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

nickg / nvc / 20645692657

01 Jan 2026 09:14PM UTC coverage: 92.653% (+0.08%) from 92.573%
20645692657

push

github

nickg
Allocate virtual registers in MIR

Fixes #1259

160 of 161 new or added lines in 9 files covered. (99.38%)

579 existing lines in 12 files now uncovered.

76033 of 82062 relevant lines covered (92.65%)

466822.97 hits per line

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

97.61
/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)
12,022,628✔
35
{
36
   assert(block.tag == MIR_TAG_BLOCK);
12,022,628✔
37
   return AREF(mu->blocks, block.id);
12,022,628✔
38
}
39

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

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

50
   return b;
153,316✔
51
}
52

53
void mir_set_cursor(mir_unit_t *mu, mir_block_t block, unsigned pos)
2,938,527✔
54
{
55
   if (!mir_is_null(mu->cursor.block))
2,938,527✔
56
      mir_block_data(mu, mu->cursor.block)->last_loc = mu->cursor.loc;
2,882,718✔
57

58
   mu->cursor.block = block;
2,938,527✔
59
   mu->cursor.pos   = pos;
2,938,527✔
60

61
   if (mir_is_null(block))
2,938,527✔
62
      mu->cursor.loc = LOC_INVALID;
1,449✔
63
   else
64
      mu->cursor.loc = mir_block_data(mu, block)->last_loc;
2,937,078✔
65
}
2,938,527✔
66

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

72
   return mu->cursor.block;
50,758✔
73
}
74

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

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

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

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

94
void mir_compact(mir_unit_t *mu)
1,449✔
95
{
96
   for (int i = 0; i < mu->blocks.count; i++) {
6,607✔
97
      block_data_t *bd = &(mu->blocks.items[i]);
5,158✔
98
      if (bd->gap_pos == -1)
5,158✔
99
         continue;
2,680✔
100

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

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

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

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

123
unsigned mir_count_nodes(mir_unit_t *mu, mir_block_t block)
551,709✔
124
{
125
   if (mir_is_null(block))
551,709✔
126
      return mu->num_nodes;
53,512✔
127
   else
128
      return mir_block_data(mu, block)->num_nodes;
498,197✔
129
}
130

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

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

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

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

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

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

165
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
4,050,182✔
166
{
167
   switch (node.tag) {
4,050,182✔
168
   case MIR_TAG_NODE:
4,030,824✔
169
      return mir_node_data(mu, node)->op;
4,030,824✔
170
   default:
171
      return _MIR_DELETED_OP;
172
   }
173
}
174

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

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

192
const mir_value_t *mir_get_args(mir_unit_t *mu, const node_data_t *nd)
7,135,943✔
193
{
194
   if (nd->nargs <= MIR_INLINE_ARGS)
7,135,943✔
195
      return nd->args;
4,884,114✔
196
   else {
197
      assert(nd->spilloff < mu->num_argspill);
2,251,829✔
198
      return mu->argspill + nd->spilloff;
2,251,829✔
199
   }
200
}
201

202
mir_value_t mir_get_arg(mir_unit_t *mu, mir_value_t node, unsigned nth)
4,334,396✔
203
{
204
   const node_data_t *nd = mir_node_data(mu, node);
4,334,396✔
205
   if (nth >= nd->nargs)
4,334,396✔
206
      return MIR_NULL_VALUE;
458✔
207
   else
208
      return mir_get_args(mu, nd)[nth];
4,333,938✔
209
}
210

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

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

223
   return p;
35,046✔
224
}
225

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

231
   mir_mem_t mem = MIR_MEM_STACK;
73,855✔
232
   if (flags & MIR_VAR_HEAP)
73,855✔
233
      mem = MIR_MEM_LOCAL;
1,110✔
234

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

244
   return v;
73,855✔
245
}
246

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

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

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

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

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

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

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

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

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

304
      if (mu->num_nodes == mu->max_nodes) {
1,303,987✔
305
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
112,265✔
306
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
112,265✔
307
                                    sizeof(node_data_t));
308
      }
309

310
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
1,303,987✔
311
      n = &(mu->nodes[mu->num_nodes++]);
1,303,987✔
312
   }
313
   else {
314
      n = &(mu->nodes[bd->nodes[mu->cursor.pos]]);
7,523✔
315
      assert(n->op == _MIR_DELETED_OP);
7,523✔
316
   }
317

318
   return n;
1,311,510✔
319
}
320

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

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

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

345
   if (nargs > MIR_INLINE_ARGS)
1,311,510✔
346
      n->spilloff = mir_spill_args(mu, nargs);
90,462✔
347

348
   MIR_ASSERT(mu->vregs == NULL, "cannot add nodes after register allocation");
1,311,510✔
349

350
   return n;
1,311,510✔
351
}
352

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

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

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

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

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

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

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

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

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

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

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

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

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

420
   STATIC_ASSERT(MIR_INLINE_ARGS < 5);
30,134✔
421

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

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

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

439
   STATIC_ASSERT(MIR_INLINE_ARGS < 6);
24,515✔
440

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

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

451
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
130,645✔
452
{
453
   for (int i = 0; i < mu->linkage.count; i++) {
325,829✔
454
      if (mu->linkage.items[i] == ident)
254,055✔
455
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
58,871✔
456
   }
457

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

460
   APUSH(mu->linkage, ident);
71,774✔
461

462
   return link;
71,774✔
463
}
464

465
static mir_value_t mir_add_extvar(mir_unit_t *mu, ident_t ident)
5,702✔
466
{
467
   for (int i = 0; i < mu->extvars.count; i++) {
12,371✔
468
      if (mu->extvars.items[i] == ident)
8,187✔
469
         return (mir_value_t){ .tag = MIR_TAG_EXTVAR, .id = i };
1,518✔
470
   }
471

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

474
   APUSH(mu->extvars, ident);
4,184✔
475

476
   return var;
4,184✔
477
}
478

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

484
   if (n->nargs <= MIR_INLINE_ARGS)
2,004,130✔
485
      n->args[nth] = value;
273,480✔
486
   else {
487
      assert(n->spilloff < mu->num_argspill);
1,730,650✔
488
      mu->argspill[n->spilloff + nth] = value;
1,730,650✔
489
   }
490
}
2,004,130✔
491

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

497
   return &(mu->nodes[value.id]);
18,196,285✔
498
}
499

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

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

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

518
   if (mu->comments == NULL)
12,751✔
519
      mu->comments = tb_new();
3,662✔
520

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

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

526
   va_end(ap);
12,751✔
527

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

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

539
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
4,324,795✔
540
{
541
   switch (value.tag) {
4,324,795✔
542
   case MIR_TAG_CONST:
3,835,902✔
543
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
3,835,902✔
544
      return true;
3,835,902✔
545
   case MIR_TAG_ENUM:
196,704✔
546
      *result = value.id;
196,704✔
547
      return true;
196,704✔
548
   case MIR_TAG_NODE:
282,467✔
549
      {
550
         const node_data_t *n = mir_node_data(mu, value);
282,467✔
551
         if (n->op == MIR_OP_CONST) {
282,467✔
552
            *result = n->iconst;
7,892✔
553
            return true;
7,892✔
554
         }
555
         else
556
            return false;
557
      }
558
   default:
559
      return false;
560
   }
561
}
562

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

581
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
5,153,903✔
582
{
583
   switch (value.tag) {
5,153,903✔
584
   case MIR_TAG_NODE:
4,537,505✔
585
      return mir_node_data(mu, value)->type;
4,537,505✔
586
   case MIR_TAG_PARAM:
162,318✔
587
      return mir_param_data(mu, value)->type;
162,318✔
588
   case MIR_TAG_VAR:
316,400✔
589
      return mir_var_data(mu, value)->pointer;
316,400✔
590
   default:
137,680✔
591
      return MIR_NULL_TYPE;
137,680✔
592
   }
593
}
594

595
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
721,726✔
596
{
597
   switch (value.tag) {
721,726✔
598
   case MIR_TAG_NODE:
544,812✔
599
      return mir_node_data(mu, value)->stamp;
544,812✔
600
   case MIR_TAG_PARAM:
23,803✔
601
      return mir_param_data(mu, value)->stamp;
23,803✔
602
   case MIR_TAG_VAR:
94,888✔
603
      return mir_var_data(mu, value)->stamp;
94,888✔
604
   case MIR_TAG_CONST:
58,223✔
605
      {
606
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
58,223✔
607
         return mir_int_stamp(mu, ival, ival);
58,223✔
608
      }
609
   default:
×
610
      return MIR_NULL_STAMP;
×
611
   }
612
}
613

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

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

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

635
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
60,190✔
636
   if (sd->kind == MIR_STAMP_POINTER)
60,190✔
637
      return sd->u.pointer.memory;
59,988✔
638

639
   return MIR_MEM_NONE;
640
}
641

642
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
186,557✔
643
{
644
   switch (value.tag) {
186,557✔
645
   case MIR_TAG_PARAM:
18✔
646
      return mir_param_data(mu, value)->name;
18✔
647
   case MIR_TAG_VAR:
55,799✔
648
      return mir_var_data(mu, value)->name;
55,799✔
649
   case MIR_TAG_LINKAGE:
125,273✔
650
      return AGET(mu->linkage, value.id);
125,273✔
651
   case MIR_TAG_EXTVAR:
5,467✔
652
      return AGET(mu->extvars, value.id);
5,467✔
653
   case MIR_TAG_NULL:
×
654
      return mu->name;
×
655
   default:
656
      return NULL;
657
   }
658
}
659

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

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

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

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

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

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

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

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

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

733
   switch (mir_type_data(mu, type)->class) {
87,241✔
734
   case MIR_TYPE_INT:
735
   case MIR_TYPE_OFFSET:
736
      return true;
737
   default:
6,154✔
738
      return false;
6,154✔
739
   }
740
}
741

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

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

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

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

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

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

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

798
   switch (mir_type_data(mu, type)->class) {
65,462✔
799
   case MIR_TYPE_VEC2:
800
   case MIR_TYPE_VEC4:
801
      return true;
802
   default:
52,569✔
803
      return false;
52,569✔
804
   }
805
}
806

807
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
139,080✔
808
{
809
   if (value.tag == MIR_TAG_CONST)
139,080✔
810
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
39,521✔
811
   else
812
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
99,559✔
813
}
814

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

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

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

829
   return mir_type_data(mu, type)->class == class;
655,926✔
830
}
831

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

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

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

845
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
119,030✔
846
{
847
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
119,030✔
848
}
849

850
bool mir_is_offset(mir_unit_t *mu, mir_value_t value)
167,427✔
851
{
852
   if (value.tag == MIR_TAG_CONST)
167,427✔
853
      return true;
854

855
   return mir_is(mu, value, MIR_TYPE_OFFSET);
43,574✔
856
}
857

858
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
1,664,934✔
859
{
860
   switch (value.tag) {
1,664,934✔
861
   case MIR_TAG_CONST:
862
      return true;
863
   case MIR_TAG_NODE:
17,346✔
864
      {
865
         node_data_t *n = mir_node_data(mu, value);
17,346✔
866
         switch (n->op) {
17,346✔
867
         case MIR_OP_CONST:
868
         case MIR_OP_CONST_REAL:
869
         case MIR_OP_CONST_ARRAY:
870
         case MIR_OP_CONST_REP:
871
         case MIR_OP_CONST_RECORD:
872
         case MIR_OP_NULL:
873
            return true;
874
         default:
×
875
            return false;
×
876
         }
877
      }
878
   default:
×
879
      return false;
×
880
   }
881
}
882

883
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
5✔
884
{
885
   const mir_mem_t a_mem = mir_get_mem(mu, a);
5✔
886
   if (a_mem == MIR_MEM_NONE)
5✔
887
      return false;
888

889
   if (mir_equals(a, b))
5✔
890
      return true;
891

892
   const mir_mem_t b_mem = mir_get_mem(mu, b);
5✔
893
   if (b_mem == MIR_MEM_NONE)
5✔
894
      return false;
895

896
   if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
5✔
897
      // Aliasing is only relevant in the presence of mutability
898
      return false;
899
   }
900

901
   return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
3✔
902
}
903

904
#ifdef DEBUG
905
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
1,734,795✔
906
{
907
   if (value.tag == MIR_TAG_CONST) {
1,734,795✔
908
      const mir_class_t class = mir_type_data(mu, type)->class;
1,656,316✔
909
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
1,656,316✔
910
   }
911
   else
912
      return mir_equals(mir_get_type(mu, value), type);
78,479✔
913
}
914
#endif
915

916
mir_value_t mir_enum(unsigned value)
233,505✔
917
{
918
   assert(value < MIR_ID_MAX);
233,505✔
919
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
233,505✔
920
}
921

922
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
456,756✔
923
{
924
   mir_value_t result;
456,756✔
925
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
456,756✔
926
      const unsigned biased = value + SMALL_CONST_BIAS;
449,320✔
927
      result = (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
449,320✔
928
   }
929
   else {
930
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
7,436✔
931
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
7,436✔
932
      n->iconst = value;
7,436✔
933

934
      result = (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
7,436✔
935
   }
936

937
#ifdef DEBUG
938
   const mir_class_t class = mir_get_class(mu, type);
456,756✔
939
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET,
456,756✔
940
              "constant must have integral type");
941
#endif
942

943
   return result;
456,756✔
944
}
945

946
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
22,445✔
947
{
948
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
22,445✔
949
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
22,445✔
950
   n->dconst = value;
22,445✔
951

952
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
22,445✔
953
}
954

955
mir_value_t mir_const_vec(mir_unit_t *mu, mir_type_t type, uint64_t abits,
6,000✔
956
                          uint64_t bbits)
957
{
958
   uint64_t mask = ~UINT64_C(0), size = mir_get_size(mu, type);
6,000✔
959
   if (size < 64)
6,000✔
960
      mask >>= 64 - size;
5,928✔
961

962
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_VEC, type, MIR_NULL_STAMP, 0);
6,000✔
963
   n->bits[0] = abits & mask;
6,000✔
964
   n->bits[1] = bbits & mask;
6,000✔
965

966
#ifdef DEBUG
967
   const type_data_t *td = mir_type_data(mu, type);
6,000✔
968
   MIR_ASSERT(td->class == MIR_TYPE_VEC2 || td->class == MIR_TYPE_VEC4,
6,000✔
969
              "constant vector must have vector type");
970
   MIR_ASSERT(bbits == 0 || td->class == MIR_TYPE_VEC4,
6,000✔
971
              "b-bits cannot be set for two-value vector");
972
   MIR_ASSERT(size <= 64, "constant vector size must be 64 bits or less");
6,000✔
973
#endif
974

975
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
6,000✔
976
}
977

978
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
29,936✔
979
                            const mir_value_t *values, size_t count)
980
{
981
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
59,872✔
982
                                 MIR_NULL_STAMP, count);
29,936✔
983

984
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
29,936✔
985
              "constant array must have constrained array type");
986
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
29,936✔
987
              "have %zd", mir_get_size(mu, type), count);
988

989
   mir_type_t elem = mir_get_elem(mu, type);
29,936✔
990

991
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
29,936✔
992
   int64_t low = INT64_MAX, high = INT64_MIN;
29,936✔
993
   for (size_t i = 0; i < count; i++) {
1,682,659✔
994
      mir_set_arg(mu, n, i, values[i]);
1,652,723✔
995

996
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
1,652,723✔
997
                 "element %zd has wrong type", i);
998
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
1,652,723✔
999

1000
      int64_t cval;
1,652,723✔
1001
      if (integral && mir_get_const(mu, values[i], &cval)) {
1,652,723✔
1002
         low = MIN(low, cval);
1,635,967✔
1003
         high = MAX(high, cval);
1,635,967✔
1004
      }
1005
   }
1006

1007
   mir_stamp_t stamp = MIR_NULL_STAMP;
29,936✔
1008
   if (integral && low <= high)
29,936✔
1009
      stamp = mir_int_stamp(mu, low, high);
29,244✔
1010

1011
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
29,936✔
1012

1013
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
29,936✔
1014
}
1015

1016
mir_value_t mir_const_string(mir_unit_t *mu, const char *str)
3,834✔
1017
{
1018
   int count = 0, low = UINT8_MAX, high = 0;
3,834✔
1019
   for (const char *p = str; *p; p++, count++) {
18,582✔
1020
      low = MIN(low, (unsigned char)*p);
14,748✔
1021
      high = MAX(high, (unsigned char)*p);
14,748✔
1022
   }
1023

1024
   mir_type_t t_char = mir_char_type(mu);
3,834✔
1025
   mir_type_t type = mir_carray_type(mu, count, t_char);
3,834✔
1026
   mir_stamp_t stamp = mir_int_stamp(mu, low, high);
3,834✔
1027

1028
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
3,834✔
1029
                                 stamp, count);
1030

1031
   for (int i = 0; i < count; i++)
18,582✔
1032
      mir_set_arg(mu, n, i, mir_const(mu, t_char, (unsigned char)str[i]));
14,748✔
1033

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

1037
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
302✔
1038
                                mir_value_t value, unsigned rep)
1039
{
1040
   mir_stamp_t stamp = mir_get_stamp(mu, value);
302✔
1041
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
302✔
1042
                                    value, mir_enum(rep));
1043

1044
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
302✔
1045
              "constant array must have constrained array class");
1046
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
302✔
1047

1048
   return result;
302✔
1049
}
1050

1051
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,051✔
1052
                             const mir_value_t *values, size_t count)
1053
{
1054
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
4,102✔
1055
                                 MIR_NULL_STAMP, count);
2,051✔
1056

1057
   DEBUG_ONLY(const type_data_t *td = mir_type_data(mu, type));
2,051✔
1058

1059
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,051✔
1060
              "const record must have record type");
1061
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,051✔
1062
              td->u.record.count, count);
1063

1064
   for (int i = 0; i < count; i++) {
7,489✔
1065
      mir_set_arg(mu, n, i, values[i]);
5,438✔
1066

1067
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
5,438✔
1068
                               td->u.record.fields[i]),
1069
                 "wrong type for element %d", i);
1070
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
5,438✔
1071
   }
1072

1073
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,051✔
1074
}
1075

1076
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
55,324✔
1077
                                   mir_value_t left, mir_value_t right,
1078
                                   mir_value_t locus, mir_stamp_t stamp)
1079
{
1080
   mir_value_t result;
55,324✔
1081
   if (mir_is_null(locus))
55,324✔
1082
      result = mir_build_2(mu, op, type, stamp, left, right);
47,573✔
1083
   else
1084
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
7,751✔
1085

1086
#ifdef DEBUG
1087
   switch (mir_get_class(mu, type)) {
55,324✔
1088
   case MIR_TYPE_INT:
55,322✔
1089
   case MIR_TYPE_REAL:
1090
   case MIR_TYPE_OFFSET:
1091
      {
1092
         mir_type_t ltype = mir_get_type(mu, left);
55,322✔
1093
         mir_type_t rtype = mir_get_type(mu, right);
55,322✔
1094

1095
         MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
55,322✔
1096
                    || mir_equals(ltype, rtype),
1097
                    "arguments to %s are not the same type", mir_op_string(op));
1098
      }
1099
      break;
1100

1101
   case MIR_TYPE_VEC2:
2✔
1102
   case MIR_TYPE_VEC4:
1103
      {
1104
         const type_data_t *td = mir_type_data(mu, type);
2✔
1105
         const type_data_t *ltd = mir_type_data(mu, mir_get_type(mu, left));
2✔
1106
         const type_data_t *rtd = mir_type_data(mu, mir_get_type(mu, right));
2✔
1107

1108
         MIR_ASSERT(td->class == ltd->class && td->class == rtd->class,
2✔
1109
                    "cannot mix vector types");
1110
         MIR_ASSERT(td->u.vec.issigned == ltd->u.vec.issigned
2✔
1111
                    && td->u.vec.issigned == rtd->u.vec.issigned,
1112
                    "cannot mix vector signedness");
1113
         MIR_ASSERT(td->u.vec.size >= ltd->u.vec.size
2✔
1114
                    && td->u.vec.size >= rtd->u.vec.size,
1115
                    "implicit narrowing conversions are not allowed");
1116
      }
1117
      break;
1118

1119
   default:
1120
      MIR_ASSERT(false, "arithmetic is not allowed on this type");
×
1121
      break;
1122
   }
1123

1124
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
55,324✔
1125
              "locus argument to %s is not a locus", mir_op_string(op));
1126
#endif
1127

1128
   return result;
55,324✔
1129
}
1130

1131
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
19,704✔
1132
                                    mir_type_t type, mir_value_t left,
1133
                                    mir_value_t right, mir_value_t locus)
1134
{
1135
   int64_t lval, rval, cval;
19,704✔
1136
   const bool lconst = mir_get_const(mu, left, &lval);
19,704✔
1137
   const bool rconst = mir_get_const(mu, right, &rval);
19,704✔
1138

1139
   if (lconst && lval == 0)
19,704✔
1140
      return right;
432✔
1141
   else if (rconst && rval == 0)
19,272✔
1142
      return left;
199✔
1143
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
19,073✔
1144
      return mir_const(mu, type, cval);
207✔
1145

1146
   double lreal, rreal;
18,866✔
1147
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
18,866✔
1148
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
18,866✔
1149

1150
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
18,866✔
1151
      return right;
1✔
1152
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
18,865✔
1153
      return left;
2✔
1154
   else if (lconst_real && rconst_real)
18,863✔
1155
      return mir_const_real(mu, type, lreal + rreal);
4✔
1156

1157
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
18,859✔
1158
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
18,859✔
1159
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
18,859✔
1160

1161
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
18,859✔
1162
}
1163

1164
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
14,903✔
1165
                          mir_value_t right)
1166
{
1167
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
14,903✔
1168
}
1169

1170
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
4,801✔
1171
                               mir_value_t left, mir_value_t right,
1172
                               mir_value_t locus)
1173
{
1174
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
4,801✔
1175
}
1176

1177
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
29,949✔
1178
                                    mir_type_t type, mir_value_t left,
1179
                                    mir_value_t right, mir_value_t locus)
1180
{
1181
   int64_t lval, rval, cval;
29,949✔
1182
   const bool lconst = mir_get_const(mu, left, &lval);
29,949✔
1183
   const bool rconst = mir_get_const(mu, right, &rval);
29,949✔
1184

1185
   if (lconst && lval == 0)
29,949✔
1186
      return right;
12✔
1187
   else if (rconst && rval == 0)
29,937✔
1188
      return left;
129✔
1189
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
29,808✔
1190
      return mir_const(mu, type, cval);
310✔
1191
   else if (mir_equals(left, right))
29,498✔
1192
      return mir_get_class(mu, type) == MIR_TYPE_REAL
162✔
1193
         ? mir_const_real(mu, type, 0.0) : mir_const(mu, type, 0);
162✔
1194

1195
   double lreal, rreal;
29,336✔
1196
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
29,336✔
1197
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
29,336✔
1198

1199
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
29,336✔
1200
      return right;
×
1201
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
29,336✔
1202
      return left;
4✔
1203
   else if (lconst_real && rconst_real)
29,332✔
1204
      return mir_const_real(mu, type, lreal - rreal);
×
1205

1206
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
29,332✔
1207
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
29,332✔
1208
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
29,332✔
1209

1210
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
29,332✔
1211
}
1212

1213
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
28,278✔
1214
                          mir_value_t right)
1215
{
1216
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
28,278✔
1217
}
1218

1219
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
1,671✔
1220
                               mir_value_t left, mir_value_t right,
1221
                               mir_value_t locus)
1222
{
1223
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
1,671✔
1224
}
1225

1226
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
6,986✔
1227
{
1228
   int64_t cval;
6,986✔
1229
   if (mir_get_const(mu, value, &cval))
6,986✔
1230
      return mir_const(mu, type, -cval);
1✔
1231

1232
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
6,985✔
1233
                                    MIR_NULL_STAMP, value);
6,985✔
1234

1235
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
6,985✔
1236

1237
   return result;
6,985✔
1238
}
1239

1240
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
258✔
1241
                               mir_value_t value, mir_value_t locus)
1242
{
1243
   int64_t cval;
258✔
1244
   if (mir_get_const(mu, value, &cval) && cval >= 0)
258✔
1245
      return mir_const(mu, type, -cval);
×
1246
   // TODO: check if stamp bounds are non-negative
1247

1248
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
258✔
1249
                                    MIR_NULL_STAMP, value, locus);
258✔
1250

1251
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
258✔
1252
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
258✔
1253
              "locus argument must be debug locus");
1254

1255
   return result;
258✔
1256
}
1257

1258
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
685✔
1259
{
1260
   int64_t lconst;
685✔
1261
   if (mir_get_const(mu, value, &lconst))
685✔
1262
      return mir_const(mu, type, llabs(lconst));
×
1263

1264
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
685✔
1265
                                    value);
1266

1267
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
685✔
1268

1269
   return result;
685✔
1270
}
1271

1272
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
5,004✔
1273
                                    mir_type_t type, mir_value_t left,
1274
                                    mir_value_t right, mir_value_t locus)
1275
{
1276
   int64_t lval, rval, cval;
5,004✔
1277
   const bool lconst = mir_get_const(mu, left, &lval);
5,004✔
1278
   const bool rconst = mir_get_const(mu, right, &rval);
5,004✔
1279

1280
   if (lconst && lval == 0)
5,004✔
1281
      return left;
24✔
1282
   else if (rconst && rval == 0)
4,980✔
1283
      return right;
×
1284
   else if (lconst && lval == 1)
4,980✔
1285
      return right;
867✔
1286
   else if (rconst && rval == 1)
4,113✔
1287
      return left;
1✔
1288
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
4,112✔
1289
      return mir_const(mu, type, cval);
33✔
1290

1291
   double lreal, rreal;
4,079✔
1292
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
4,079✔
1293
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
4,079✔
1294

1295
   if (lconst_real && rconst_real)
4,079✔
1296
      return mir_const_real(mu, type, lreal * rreal);
158✔
1297

1298
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
3,921✔
1299
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
3,921✔
1300
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
3,921✔
1301

1302
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
3,921✔
1303
}
1304

1305
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
4,095✔
1306
                          mir_value_t right)
1307
{
1308
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
4,095✔
1309
}
1310

1311
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
909✔
1312
                               mir_value_t left, mir_value_t right,
1313
                               mir_value_t locus)
1314
{
1315
   return mir_build_mul_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
909✔
1316
}
1317

1318
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
1,647✔
1319
                          mir_value_t right)
1320
{
1321
   int64_t lval, rval;
1,647✔
1322
   const bool lconst = mir_get_const(mu, left, &lval);
1,647✔
1323
   const bool rconst = mir_get_const(mu, right, &rval);
1,647✔
1324

1325
   if (lconst && rconst && rval != 0)
1,647✔
1326
      return mir_const(mu, type, lval / rval);
×
1327
   else if (rconst && rval == 1)
1,647✔
1328
      return left;
×
1329

1330
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
1,647✔
1331
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
1,647✔
1332
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
1,647✔
1333

1334
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
1,647✔
1335
                          MIR_NULL_VALUE, stamp);
1,647✔
1336
}
1337

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

1345
   if (lconst && rconst && lval > 0 && rval > 0)
940✔
1346
      return mir_const(mu, type, lval % rval);
1✔
1347

1348
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
939✔
1349
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
939✔
1350
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
939✔
1351

1352
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
939✔
1353
                          MIR_NULL_VALUE, stamp);
939✔
1354
}
1355

1356
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
122✔
1357
                          mir_value_t right)
1358
{
1359
   int64_t lval, rval;
122✔
1360
   const bool lconst = mir_get_const(mu, left, &lval);
122✔
1361
   const bool rconst = mir_get_const(mu, right, &rval);
122✔
1362

1363
   if (lconst && rconst && lval > 0 && rval > 0)
122✔
1364
      return mir_const(mu, type, lval % rval);
×
1365

1366
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
122✔
1367
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
122✔
1368

1369
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
122✔
1370
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
13✔
1371
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
13✔
1372

1373
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
13✔
1374
         // If both arguments are non-negative then rem is equivalent
1375
         // and cheaper to compute
1376
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1377
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1378
                                MIR_NULL_VALUE, stamp);
1✔
1379
      }
1380
   }
1381

1382
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
121✔
1383
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
121✔
1384
}
1385

1386
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
134✔
1387
                          mir_value_t right)
1388
{
1389
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
268✔
1390
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
134✔
1391
}
1392

1393
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
370✔
1394
                               mir_value_t left, mir_value_t right,
1395
                               mir_value_t locus)
1396
{
1397
   int64_t rconst;
370✔
1398
   if (mir_get_const(mu, right, &rconst)) {
370✔
1399
      if (rconst == 0)
45✔
1400
         return mir_const(mu, type, 1);
×
1401
      else if (rconst == 1)
45✔
1402
         return left;
×
1403
   }
1404

1405
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
370✔
1406
                                        locus, MIR_NULL_STAMP);
370✔
1407

1408
   MIR_ASSERT(mir_is_integral(mu, result),
370✔
1409
              "trapping exp may only be used with integer types");
1410

1411
   return result;
370✔
1412
}
1413

1414
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
7,663✔
1415
                                     mir_type_t type, mir_value_t left,
1416
                                     mir_value_t right)
1417
{
1418
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
7,663✔
1419

1420
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
7,663✔
1421
              mir_op_string(op));
1422
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
7,663✔
1423
              mir_op_string(op));
1424

1425
   return result;
7,663✔
1426
}
1427

1428
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
6,976✔
1429
{
1430
   int64_t lval, rval;
6,976✔
1431
   const bool lconst = mir_get_const(mu, left, &lval);
6,976✔
1432
   const bool rconst = mir_get_const(mu, right, &rval);
6,976✔
1433

1434
   mir_type_t t_bool = mir_bool_type(mu);
6,976✔
1435

1436
   if (lconst && rconst)
6,976✔
1437
      return mir_const(mu, t_bool, lval && rval);
669✔
1438
   else if (lconst)
6,359✔
1439
      return lval ? right : mir_const(mu, t_bool, 0);
995✔
1440
   else if (rconst)
5,364✔
1441
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1442

1443
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
5,362✔
1444
}
1445

1446
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
2,192✔
1447
{
1448
   int64_t lval, rval;
2,192✔
1449
   const bool lconst = mir_get_const(mu, left, &lval);
2,192✔
1450
   const bool rconst = mir_get_const(mu, right, &rval);
2,192✔
1451

1452
   mir_type_t t_bool = mir_bool_type(mu);
2,192✔
1453

1454
   if (lconst && rconst)
2,192✔
1455
      return mir_const(mu, t_bool, lval || rval);
3✔
1456
   else if (lconst)
2,190✔
1457
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1458
   else if (rconst)
2,189✔
1459
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1460

1461
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
2,188✔
1462
}
1463

1464
mir_value_t mir_build_xor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
115✔
1465
{
1466
   int64_t lval, rval;
115✔
1467
   const bool lconst = mir_get_const(mu, left, &lval);
115✔
1468
   const bool rconst = mir_get_const(mu, right, &rval);
115✔
1469

1470
   mir_type_t t_bool = mir_bool_type(mu);
115✔
1471
   if (lconst && rconst)
115✔
1472
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1473
   else if (mir_equals(left, right))
114✔
1474
      return mir_const(mu, t_bool, 0);
1✔
1475

1476
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
113✔
1477
}
1478

1479
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
2,803✔
1480
{
1481
   mir_type_t t_bool = mir_bool_type(mu);
2,803✔
1482

1483
   int64_t cval;
2,803✔
1484
   if (mir_get_const(mu, value, &cval))
2,803✔
1485
      return mir_const(mu, t_bool, !cval);
2✔
1486

1487
   if (mir_get_op(mu, value) == MIR_OP_NOT)
2,801✔
1488
      return mir_get_arg(mu, value, 0);
31✔
1489

1490
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
2,770✔
1491
                                    MIR_NULL_STAMP, value);
2,770✔
1492

1493
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
2,770✔
1494

1495
   return result;
2,770✔
1496
}
1497

1498
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
38,505✔
1499
                          mir_value_t right)
1500
{
1501
   int64_t lval, rval;
38,505✔
1502
   const bool lconst = mir_get_const(mu, left, &lval);
38,505✔
1503
   const bool rconst = mir_get_const(mu, right, &rval);
38,505✔
1504

1505
   mir_type_t t_bool = mir_bool_type(mu);
38,505✔
1506

1507
   if (lconst && rconst) {
38,505✔
1508
      switch (cmp) {
832✔
1509
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1510
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
2✔
1511
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
212✔
1512
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
2✔
1513
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
410✔
1514
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
203✔
1515
      default: should_not_reach_here();
1516
      }
1517
   }
1518

1519
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
37,673✔
1520
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
37,673✔
1521
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
37,673✔
1522

1523
   int64_t sconst;
37,673✔
1524
   if (mir_stamp_const(mu, stamp, &sconst))
37,673✔
1525
      return mir_const(mu, t_bool, sconst);
3✔
1526

1527
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
37,670✔
1528
                                    stamp, mir_enum(cmp), left, right);
1529

1530
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
37,670✔
1531
                            mir_get_type(mu, right)),
1532
              "arguments to cmp are not the same type");
1533

1534
   return result;
37,670✔
1535
}
1536

1537
mir_value_t mir_build_pack(mir_unit_t *mu, mir_type_t type, mir_value_t arg)
2,677✔
1538
{
1539
   mir_value_t result = mir_build_1(mu, MIR_OP_PACK, type, MIR_NULL_STAMP, arg);
2,677✔
1540

1541
#ifdef DEBUG
1542
   const mir_class_t class = mir_get_class(mu, type);
2,677✔
1543
   MIR_ASSERT(class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4,
2,677✔
1544
              "pack type must be vector");
1545
   MIR_ASSERT(mir_is(mu, arg, MIR_TYPE_POINTER)
2,677✔
1546
              || (mir_get_size(mu, type) == 1 && mir_is_integral(mu, arg)),
1547
              "pack argument must be pointer if size != 1");
1548
#endif
1549

1550
   return result;
2,677✔
1551
}
1552

1553
mir_value_t mir_build_unpack(mir_unit_t *mu, mir_value_t vec, uint8_t strength,
2,341✔
1554
                             mir_value_t dest)
1555
{
1556
   mir_value_t result = dest;
2,341✔
1557
   if (mir_is_null(dest))
2,341✔
1558
      result = mir_build_2(mu, MIR_OP_UNPACK, mir_logic_type(mu),
1,986✔
1559
                           MIR_NULL_STAMP, vec, mir_enum(strength));
993✔
1560
   else
1561
      mir_build_3(mu, MIR_OP_UNPACK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,348✔
1562
                  vec, mir_enum(strength), dest);
1563

1564
   MIR_ASSERT(mir_is_vector(mu, vec), "unpack argument must be vector");
2,341✔
1565
   MIR_ASSERT(mir_is_null(dest) || mir_points_to(mu, dest, MIR_TYPE_INT),
2,341✔
1566
              "unpack dest must be pointer to logic or null");
1567
   MIR_ASSERT(mir_get_size(mu, mir_get_type(mu, vec)) == 1
2,341✔
1568
              || !mir_is_null(dest),
1569
              "unpack dest must be non-null if wide vector");
1570
   MIR_ASSERT((strength & 3) == 0, "strength lower bits must be zero");
2,341✔
1571

1572
   return result;
2,341✔
1573
}
1574

1575
mir_value_t mir_build_binary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
1,980✔
1576
                             mir_value_t left, mir_value_t right)
1577
{
1578
   mir_type_t otype;
1,980✔
1579
   switch (op) {
1,980✔
1580
   case MIR_VEC_CASE_EQ:
1,584✔
1581
   case MIR_VEC_CASE_NEQ:
1582
   case MIR_VEC_CASEX_EQ:
1583
   case MIR_VEC_LOG_AND:
1584
   case MIR_VEC_LOG_OR:
1585
      // XXX: these should be vec2
1586
   case MIR_VEC_LT:
1587
   case MIR_VEC_LEQ:
1588
   case MIR_VEC_GT:
1589
   case MIR_VEC_GEQ:
1590
   case MIR_VEC_LOG_EQ:
1591
   case MIR_VEC_LOG_NEQ:
1592
      otype = mir_vec4_type(mu, 1, false);
1,584✔
1593
      break;
1,584✔
1594
   default:
396✔
1595
      otype = type;
396✔
1596
   }
1597

1598
   mir_value_t result = mir_build_3(mu, MIR_OP_BINARY, otype, MIR_NULL_STAMP,
1,980✔
1599
                                    mir_enum(op), left, right);
1600

1601
   MIR_ASSERT(mir_is_vector(mu, result), "binary operation must be vector");
1,980✔
1602
   MIR_ASSERT(mir_check_type(mu, left, type), "left type does not match");
1,980✔
1603
   MIR_ASSERT(mir_check_type(mu, right, type), "right type does not match");
1,980✔
1604

1605
   return result;
1,980✔
1606
}
1607

1608
mir_value_t mir_build_unary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
132✔
1609
                            mir_value_t arg)
1610
{
1611
   mir_type_t otype;
132✔
1612
   switch (op) {
132✔
1613
   case MIR_VEC_LOG_NOT:
66✔
1614
   case MIR_VEC_BIT_AND:
1615
   case MIR_VEC_BIT_OR:
1616
   case MIR_VEC_BIT_XOR:
1617
      otype = mir_vec2_type(mu, 1, false);
66✔
1618
      break;
66✔
1619
   default:
66✔
1620
      otype = type;
66✔
1621
   }
1622

1623
   mir_value_t result = mir_build_2(mu, MIR_OP_UNARY, otype, MIR_NULL_STAMP,
132✔
1624
                                    mir_enum(op), arg);
1625

1626
   MIR_ASSERT(mir_is_vector(mu, result), "unary operation must be vector");
132✔
1627
   MIR_ASSERT(mir_check_type(mu, arg, type), "arg type does not match");
132✔
1628

1629
   return result;
132✔
1630
}
1631

1632
mir_value_t mir_build_insert(mir_unit_t *mu, mir_value_t part, mir_value_t full,
444✔
1633
                             mir_value_t pos)
1634
{
1635
   mir_type_t type = mir_get_type(mu, full);
444✔
1636
   mir_value_t result = mir_build_3(mu, MIR_OP_INSERT, type, MIR_NULL_STAMP,
444✔
1637
                                    part, full, pos);
1638

1639
   MIR_ASSERT(mir_is_vector(mu, full), "full argument must be vector");
444✔
1640
   MIR_ASSERT(mir_is_vector(mu, part), "part argument must be vector");
444✔
1641

1642
#ifdef DEBUG
1643
   mir_type_t part_type = mir_get_type(mu, part);
444✔
1644
   MIR_ASSERT(mir_get_size(mu, part_type) <= mir_get_size(mu, type),
444✔
1645
              "out of bounds insert");
1646
   MIR_ASSERT(mir_get_class(mu, part_type) == mir_get_class(mu, type),
444✔
1647
              "mismatched vector types");
1648
#endif
1649

1650
   return result;
444✔
1651
}
1652

1653
mir_value_t mir_build_extract(mir_unit_t *mu, mir_type_t type, mir_value_t full,
336✔
1654
                              mir_value_t pos)
1655
{
1656
   mir_value_t result = mir_build_2(mu, MIR_OP_EXTRACT, type, MIR_NULL_STAMP,
336✔
1657
                                    full, pos);
1658

1659
   MIR_ASSERT(mir_is_vector(mu, full), "extract argument must be vector");
336✔
1660
   MIR_ASSERT(mir_is_offset(mu, pos), "extract position must be offset");
336✔
1661

1662
#ifdef DEBUG
1663
   mir_type_t full_type = mir_get_type(mu, full);
336✔
1664
   MIR_ASSERT(mir_get_class(mu, full_type) == mir_get_class(mu, type),
336✔
1665
              "mismatched vector types");
1666
#endif
1667

1668
   return result;
336✔
1669
}
1670

1671
mir_value_t mir_build_test(mir_unit_t *mu, mir_value_t vec)
900✔
1672
{
1673
   mir_value_t result = mir_build_1(mu, MIR_OP_TEST, mir_bool_type(mu),
900✔
1674
                                    MIR_NULL_STAMP, vec);
900✔
1675

1676
   MIR_ASSERT(mir_is_vector(mu, vec), "argument must be vector");
900✔
1677

1678
   return result;
900✔
1679
}
1680

1681
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
94,761✔
1682
{
1683
   mir_build_2(mu, MIR_OP_STORE, MIR_NULL_TYPE, MIR_NULL_STAMP, dest, src);
94,761✔
1684

1685
#ifdef DEBUG
1686
   mir_type_t type = mir_get_type(mu, dest);
94,761✔
1687
   mir_type_t pointed = mir_get_pointer(mu, type);
94,761✔
1688
#endif
1689

1690
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
94,761✔
1691
              "store destination is not a pointer or variable");
1692
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
94,761✔
1693
              "source and destination have different types");
1694
}
94,761✔
1695

1696
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
132,662✔
1697
{
1698
   mir_type_t type = mir_get_type(mu, value);
132,662✔
1699
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
132,662✔
1700
   mir_type_t pointed = mir_get_pointer(mu, type);
132,662✔
1701

1702
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
132,662✔
1703

1704
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
132,662✔
1705
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
132,662✔
1706
              "argument to load is not a pointer or variable");
1707
   MIR_ASSERT(mir_is_scalar(mu, result), "cannot load non-scalar type");
132,662✔
1708
   MIR_ASSERT(mir_get_mem(mu, value) != MIR_MEM_NULL,
132,662✔
1709
              "null pointer dereference");
1710

1711
   return result;
132,662✔
1712
}
1713

1714
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
25,002✔
1715
                    mir_value_t count)
1716
{
1717
   int64_t cval;
25,002✔
1718
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
25,002✔
1719
      return;
189✔
1720
   else if (mir_equals(dest, src))
25,002✔
1721
      return;
1722

1723
   mir_type_t dtype = mir_get_type(mu, dest);
24,813✔
1724
   mir_type_t elem = mir_get_pointer(mu, dtype);
24,813✔
1725

1726
   if (mir_is_null(count))
24,813✔
1727
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
1,577✔
1728
   else
1729
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
23,236✔
1730

1731
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
24,813✔
1732
              "destination type is not a pointer");
1733
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
24,813✔
1734
              "source type is not a pointer");
1735
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
24,813✔
1736
              "source and destination types do not match");
1737
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
24,813✔
1738
              "count is not offset type");
1739
}
1740

1741
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
5,480✔
1742
                   mir_value_t count)
1743
{
1744
   int64_t cval;
5,480✔
1745
   if (mir_get_const(mu, count, &cval) && cval == 0)
5,480✔
UNCOV
1746
      return;
×
1747

1748
   mir_type_t dtype = mir_get_type(mu, dest);
5,480✔
1749
   mir_type_t elem = mir_get_pointer(mu, dtype);
5,480✔
1750

1751
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
5,480✔
1752

1753
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
5,480✔
1754
              "destination type is not a pointer");
1755
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
5,480✔
1756
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
5,480✔
1757
}
1758

1759
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
7,476✔
1760
                            mir_value_t count)
1761
{
1762
   mir_type_t ptr = mir_pointer_type(mu, type);
7,476✔
1763
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
7,476✔
1764

1765
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
7,476✔
1766
              "alloc element type cannot be array");
1767
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
7,476✔
1768

1769
   return result;
7,476✔
1770
}
1771

1772
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
4,218✔
1773
{
1774
   mir_stamp_t stamp = mir_pointer_stamp(mu, MIR_MEM_NULL, MIR_NULL_STAMP);
4,218✔
1775
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, stamp);
4,218✔
1776

1777
#ifdef DEBUG
1778
   const mir_class_t class = mir_get_class(mu, type);
4,218✔
1779
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
4,218✔
1780
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1781
              "null type must be file, access, context, or pointer");
1782
#endif
1783

1784
   return result;
4,218✔
1785
}
1786

1787
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
645✔
1788
                          mir_value_t count)
1789
{
1790
   mir_type_t access = mir_access_type(mu, type);
645✔
1791

1792
   mir_value_t result;
645✔
1793
   if (mir_is_null(count))
645✔
1794
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
91✔
1795
   else
1796
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
554✔
1797

1798
#ifdef DEBUG
1799
   const mir_class_t class = mir_get_class(mu, type);
645✔
1800
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
645✔
1801
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1802
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1803
              "new type must be int, real, record, access, or uarray");
1804
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
645✔
1805
              "new count must have offset type");
1806
#endif
1807

1808
   return result;
645✔
1809
}
1810

1811
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
2,818✔
1812
{
1813
   mir_type_t type = mir_get_type(mu, access);
2,818✔
1814
   mir_stamp_t stamp = mir_get_stamp(mu, access);
2,818✔
1815
   mir_type_t pointed = mir_get_pointer(mu, type);
2,818✔
1816
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
2,818✔
1817

1818
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
2,818✔
1819
              "argument to all must be access type");
1820

1821
   return result;
2,818✔
1822
}
1823

1824
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
35,061✔
1825
{
1826
   mir_type_t type = mir_get_type(mu, array);
35,061✔
1827
   mir_type_t pointer = mir_get_pointer(mu, type);
35,061✔
1828
   mir_stamp_t stamp = mir_get_stamp(mu, array);
35,061✔
1829

1830
   if (mir_is_null(pointer))
35,061✔
1831
      pointer = mir_pointer_type(mu, type);
1,511✔
1832

1833
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
35,061✔
1834
                                    pointer, stamp, array);
1835

1836
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
35,061✔
1837
              || mir_is(mu, array, MIR_TYPE_RECORD),
1838
              "argument to address of must be array or record");
1839

1840
   return result;
35,061✔
1841
}
1842

1843
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
39,368✔
1844
                                mir_value_t offset)
1845
{
1846
   mir_type_t type = mir_get_type(mu, array);
39,368✔
1847
   mir_stamp_t stamp = mir_get_stamp(mu, array);
39,368✔
1848

1849
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
39,368✔
1850
                                    array, offset);
1851

1852
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
39,368✔
1853
              "argument to array ref must be pointer or signal");
1854
   MIR_ASSERT(mir_is_offset(mu, offset),
39,368✔
1855
              "offset argument to array ref must be offset");
1856

1857
   return result;
39,368✔
1858
}
1859

1860
mir_value_t mir_build_table_ref(mir_unit_t *mu, mir_value_t array,
699✔
1861
                                mir_value_t stride, const mir_value_t *args,
1862
                                int nargs)
1863
{
1864
   mir_type_t type = mir_get_type(mu, array);
699✔
1865
   mir_stamp_t stamp = mir_get_stamp(mu, array);
699✔
1866

1867
   node_data_t *n = mir_add_node(mu, MIR_OP_TABLE_REF, type, stamp, nargs + 2);
699✔
1868

1869
   mir_set_arg(mu, n, 0, array);
699✔
1870
   mir_set_arg(mu, n, 1, stride);
699✔
1871

1872
   for (int i = 0; i < nargs; i++)
1,745✔
1873
      mir_set_arg(mu, n, i + 2, args[i]);
1,046✔
1874

1875
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER),
699✔
1876
              "argument to table ref must be pointer");
1877
   MIR_ASSERT(mir_is_offset(mu, stride),
699✔
1878
              "stride argument to table ref must be offset");
1879

1880
   for (int i = 0; i < nargs; i++)
1,745✔
1881
      MIR_ASSERT(mir_is_integral(mu, args[i]),
1,046✔
1882
                 "table ref indices must be integral");
1883

1884
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
699✔
1885
}
1886

1887
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
33,151✔
1888
                                 unsigned field)
1889
{
1890
   mir_type_t pointer = mir_get_type(mu, record);
33,151✔
1891

1892
   mir_mem_t mem = mir_get_mem(mu, record);
33,151✔
1893
   mir_stamp_t stamp = MIR_NULL_STAMP;
33,151✔
1894
   if (mem != MIR_MEM_TOP)
33,151✔
1895
      stamp = mir_pointer_stamp(mu, mem, MIR_NULL_STAMP);
14,235✔
1896

1897
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
33,151✔
1898

1899
   mir_type_t type = MIR_NULL_TYPE;
33,151✔
1900
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
33,151✔
1901
      type = td->u.record.fields[field + td->u.record.count];
33,151✔
1902

1903
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, stamp,
33,151✔
1904
                                    record, mir_enum(field));
1905

1906
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
33,151✔
1907
              "record ref argument must be pointer to record");
1908
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
33,151✔
1909
              "record ref argument must be pointer to record");
1910
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
33,151✔
1911

1912
   return result;
33,151✔
1913
}
1914

1915
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
33,778✔
1916
                           const mir_dim_t *dims, int ndims)
1917
{
1918
   mir_type_t type = mir_get_type(mu, data);
33,778✔
1919
   mir_stamp_t stamp = mir_get_stamp(mu, data);
33,778✔
1920

1921
   const type_data_t *td = mir_type_data(mu, type);
33,778✔
1922
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
33,778✔
1923

1924
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
33,778✔
1925

1926
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
67,556✔
1927
                                  ndims * 3 + 1);
33,778✔
1928

1929
   mir_set_arg(mu, n, 0, data);
33,778✔
1930

1931
   for (int i = 0; i < ndims; i++) {
68,089✔
1932
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
34,311✔
1933
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
34,311✔
1934
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
34,311✔
1935
   }
1936

1937
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
33,778✔
1938
              "wrapped data is not pointer or signal");
1939

1940
   for (int i = 0; i < ndims; i++) {
68,089✔
1941
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
34,311✔
1942
                 "dimension %d left bound must be integral", i + 1);
1943
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
34,311✔
1944
                 "dimension %d right bound must be integral", i + 1);
1945
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
34,311✔
1946
                 "dimension %d direction must be bool", i + 1);
1947
   }
1948

1949
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
33,778✔
1950
}
1951

1952
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
27,397✔
1953
{
1954
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
27,397✔
1955
      return mir_get_arg(mu, array, 0);
1,654✔
1956

1957
   mir_type_t type = mir_get_type(mu, array);
25,743✔
1958
   mir_type_t pointer = mir_get_pointer(mu, type);
25,743✔
1959
   mir_stamp_t stamp = mir_get_stamp(mu, array);
25,743✔
1960

1961
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
25,743✔
1962

1963
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
25,743✔
1964
              "unwrap argument must be uarray");
1965

1966
   return result;
25,743✔
1967
}
1968

1969
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
21,693✔
1970
{
1971
   mir_type_t t_offset = mir_offset_type(mu);
21,693✔
1972
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
21,693✔
1973
                                    MIR_NULL_STAMP, array,
21,693✔
1974
                                    mir_const(mu, t_offset, dim));
1975

1976
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
21,693✔
1977
              "uarray len argument must be uarrray");
1978

1979
#ifdef DEBUG
1980
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
21,693✔
1981
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
21,693✔
1982
#endif
1983

1984
   return result;
21,693✔
1985
}
1986

1987
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
45,009✔
1988
                                       mir_type_t type, int arg_index,
1989
                                       mir_value_t array, int dim)
1990
{
1991
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
45,009✔
1992
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,322✔
1993

1994
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
43,687✔
1995
                                    array, mir_enum(dim));
1996

1997
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
43,687✔
1998
              "cannot use %s with non-uarray type", mir_op_string(op));
1999

2000
#ifdef DEBUG
2001
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
43,687✔
2002
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
43,687✔
2003
#endif
2004

2005
   return result;
43,687✔
2006
}
2007

2008
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
15,987✔
2009
{
2010
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
15,987✔
2011
                              0, array, dim);
2012
}
2013

2014
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
13,088✔
2015
{
2016
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
13,088✔
2017
                              1, array, dim);
2018
}
2019

2020
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
15,934✔
2021
{
2022
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
15,934✔
2023
                              2, array, dim);
2024
}
2025

2026
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
7,035✔
2027
                                   mir_value_t right, mir_value_t dir)
2028
{
2029
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
7,035✔
2030
                                    mir_offset_type(mu), MIR_NULL_STAMP,
7,035✔
2031
                                    left, right, dir);
2032

2033
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
7,035✔
2034
                            mir_get_type(mu, right)),
2035
              "left and right are not the same type");
2036
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
7,035✔
2037
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
7,035✔
2038

2039
   return result;
7,035✔
2040
}
2041

2042
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
2,997✔
2043
                                 mir_value_t right, mir_value_t dir)
2044
{
2045
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
2,997✔
2046
                                    mir_bool_type(mu), MIR_NULL_STAMP,
2,997✔
2047
                                    left, right, dir);
2048

2049
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
2,997✔
2050
                            mir_get_type(mu, right)),
2051
              "left and right are not the same type");
2052
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
2,997✔
2053
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
2,997✔
2054

2055
   return result;
2,997✔
2056
}
2057

2058
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
37,836✔
2059
{
2060
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
37,836✔
2061
               mir_cast_value(target));
37,836✔
2062

2063
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
37,836✔
2064
}
37,836✔
2065

2066
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
34,799✔
2067
                    mir_block_t bfalse)
2068
{
2069
   int64_t tconst;
34,799✔
2070
   if (mir_get_const(mu, test, &tconst)) {
34,799✔
2071
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
21✔
2072
      return;
21✔
2073
   }
2074

2075
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
34,778✔
2076
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
34,778✔
2077

2078
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
34,778✔
2079
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
34,778✔
2080
              "invalid cond targets");
2081
}
2082

2083
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
12,714✔
2084
                             mir_value_t vtrue, mir_value_t vfalse)
2085
{
2086
   int64_t tconst;
12,714✔
2087
   if (mir_get_const(mu, test, &tconst))
12,714✔
2088
      return tconst ? vtrue : vfalse;
118✔
2089
   else if (mir_equals(vtrue, vfalse))
12,596✔
2090
      return vtrue;
1✔
2091

2092
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
12,595✔
2093
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
12,595✔
2094
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
12,595✔
2095

2096
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
12,595✔
2097
                                    vtrue, vfalse);
2098

2099
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
12,595✔
2100
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
12,595✔
2101
              "true argument to select is not expected type");
2102
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
12,595✔
2103
              "false argument to select is not expected type");
2104

2105
   return result;
12,595✔
2106
}
2107

2108
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
2109
{
2110
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
2111
                                 ninputs * 2);
2112

2113
   for (int i = 0; i < ninputs; i++)
3✔
2114
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
2115

2116
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
2117
}
2118

2119
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
2120
                   mir_block_t block, mir_value_t value)
2121
{
2122
   node_data_t *n = mir_node_data(mu, phi);
2✔
2123
   assert(n->op == MIR_OP_PHI);
2✔
2124
   assert(nth * 2 < n->nargs);
2✔
2125

2126
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
2127
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
2128

2129
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
2130

2131
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
2132
              "phi input %d has wrong type", nth);
2133

2134
#ifdef DEBUG
2135
   if (value.tag != MIR_TAG_CONST) {
2✔
2136
      const block_data_t *bd = mir_block_data(mu, block);
2✔
2137
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
2138
         if (bd->nodes[i] == value.id)
2✔
2139
         return;
2140
      }
2141

UNCOV
2142
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
2143
   }
2144
#endif
2145
}
2146

2147
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
767✔
2148
                    const mir_value_t *cases, const mir_block_t *blocks,
2149
                    int ncases)
2150
{
2151
   int64_t cval;
767✔
2152
   if (mir_get_const(mu, value, &cval)) {
767✔
2153
      for (int i = 0; i < ncases; i++) {
3✔
2154
         int64_t cmp;
2✔
2155
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
2156
            mir_build_jump(mu, blocks[i]);
1✔
2157
            return;
1✔
2158
         }
2159
      }
2160

2161
      mir_build_jump(mu, def);
1✔
2162
      return;
1✔
2163
   }
2164

2165
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,530✔
2166
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
765✔
2167

2168
   mir_set_arg(mu, n, 0, value);
765✔
2169
   mir_set_arg(mu, n, 1, mir_cast_value(def));
765✔
2170

2171
   for (int i = 0; i < ncases; i++) {
7,538✔
2172
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
6,773✔
2173
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
6,773✔
2174
   }
2175

2176
   MIR_ASSERT(mir_is_integral(mu, value), "case choice must be integral");
765✔
2177

2178
#ifdef DEBUG
2179
   mir_type_t type = mir_get_type(mu, value);
765✔
2180
   for (int i = 0; i < ncases; i++) {
7,538✔
2181
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
6,773✔
2182
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
6,773✔
2183
                 "choice and value types do not match");
2184

2185
      for (int j = 0; j < i; j++)
444,606✔
2186
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
437,833✔
2187
   }
2188
#endif
2189
}
2190

2191
void mir_build_return(mir_unit_t *mu, mir_value_t value)
63,573✔
2192
{
2193
   if (mir_is_null(value))
63,573✔
2194
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
32,411✔
2195
   else
2196
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
31,162✔
2197

2198
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
63,573✔
2199
              "wrong result type");
2200
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
63,573✔
2201
              || mir_is_null(value), "cannot return a result");
2202
}
63,573✔
2203

2204
void mir_build_wait(mir_unit_t *mu, mir_block_t target)
14,148✔
2205
{
2206
   mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
14,148✔
2207
               mir_cast_value(target));
14,148✔
2208

2209
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
14,148✔
2210
              "wait only allowed in process or procedure");
2211
}
14,148✔
2212

2213
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
1,759✔
2214
{
2215
   if (value.tag != MIR_TAG_NODE)
1,759✔
2216
      return;   // Only useful for keeping nodes alive
2217

2218
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
339✔
2219
}
2220

2221
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
35,155✔
2222
                            mir_stamp_t stamp, const mir_value_t *args,
2223
                            unsigned nargs)
2224
{
2225
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
35,155✔
2226

2227
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
35,155✔
2228

2229
   for (int i = 0; i < nargs; i++)
123,174✔
2230
      mir_set_arg(mu, n, i + 1, args[i]);
88,019✔
2231

2232
   if (mir_is_null(type))
35,155✔
2233
      return MIR_NULL_VALUE;
5,538✔
2234
   else
2235
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
29,617✔
2236
}
2237

2238
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
846✔
2239
                     const mir_value_t *args, unsigned nargs)
2240
{
2241
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
1,692✔
2242
                                 MIR_NULL_STAMP, nargs + 2);
846✔
2243
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
846✔
2244
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
846✔
2245

2246
   for (int i = 0; i < nargs; i++)
2,854✔
2247
      mir_set_arg(mu, n, i + 2, args[i]);
2,008✔
2248

2249
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
846✔
2250
              "first argument to VHDL procedure must be context pointer");
2251
}
846✔
2252

2253
void mir_build_resume(mir_unit_t *mu, ident_t name)
846✔
2254
{
2255
   mir_value_t link = mir_add_linkage(mu, name);
846✔
2256
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
846✔
2257

2258
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
846✔
2259
              "resume must be first op in a block");
2260
}
846✔
2261

2262
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
1,620✔
2263
                              mir_stamp_t stamp, mir_value_t locus,
2264
                              const mir_value_t *args, int nargs)
2265
{
2266
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
1,620✔
2267

2268
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
1,620✔
2269
   mir_set_arg(mu, n, 1, locus);
1,620✔
2270

2271
   for (int i = 0; i < nargs; i++)
2,058✔
2272
      mir_set_arg(mu, n, i + 2, args[i]);
438✔
2273

2274
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,620✔
2275
              "locus argument to syscall must be a debug locus");
2276

2277
   for (int i = 0; i < nargs; i++)
2,058✔
2278
      MIR_ASSERT(!mir_is_null(args[i]), "invalid argument to syscall");
438✔
2279

2280
   if (mir_is_null(type))
1,620✔
2281
      return MIR_NULL_VALUE;
1,419✔
2282
   else
2283
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
201✔
2284
}
2285

2286
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
1,803✔
2287
{
2288
   if (mir_is_null(locus))
1,803✔
2289
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
1,685✔
2290
   else
2291
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
118✔
2292

2293
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
1,803✔
2294
              "locus argument to unreachable must be debug locus");
2295
}
1,803✔
2296

2297
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
18,704✔
2298
                                mir_value_t left, mir_value_t right,
2299
                                mir_value_t dir, mir_value_t locus,
2300
                                mir_value_t hint)
2301
{
2302
   // TODO: check if can elide bounds
2303

2304
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
18,704✔
2305
               dir, locus, hint);
2306

2307
   MIR_ASSERT(mir_is_numeric(mu, value), "value must be numeric");
18,704✔
2308
   MIR_ASSERT(mir_is_numeric(mu, left), "left bound must be numeric");
18,704✔
2309
   MIR_ASSERT(mir_is_numeric(mu, right), "right bound must be numeric");
18,704✔
2310
   MIR_ASSERT(mir_check_type(mu, dir, mir_bool_type(mu)),
18,704✔
2311
              "direction must be a bool");
2312
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS), "locus must be a debug locus");
18,704✔
2313
}
18,704✔
2314

2315
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
3,785✔
2316
                           mir_value_t right, mir_value_t dir,
2317
                           mir_value_t locus, mir_value_t hint)
2318
{
2319
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
3,785✔
2320
                       locus, hint);
2321
}
3,785✔
2322

2323
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
14,919✔
2324
                           mir_value_t right, mir_value_t dir,
2325
                           mir_value_t locus, mir_value_t hint)
2326
{
2327
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
14,919✔
2328
                       locus, hint);
2329
}
14,919✔
2330

2331
void mir_build_dir_check(mir_unit_t *mu, mir_value_t value, mir_value_t dir,
2,370✔
2332
                         mir_value_t locus)
2333
{
2334
   if (mir_equals(value, dir)) {
2,370✔
2335
      mir_comment(mu, "Elided direction check");
806✔
2336
      return;
806✔
2337
   }
2338

2339
   mir_build_3(mu, MIR_OP_DIR_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,564✔
2340
               value, dir, locus);
2341

2342
   MIR_ASSERT(mir_check_type(mu, value, mir_bool_type(mu)),
1,564✔
2343
              "null check argument must be a bool");
2344
   MIR_ASSERT(mir_check_type(mu, dir, mir_bool_type(mu)),
1,564✔
2345
              "null check direction must be a bool");
2346
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,564✔
2347
              "locus argument to null check must be a debug locus");
2348
}
2349

2350
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
2,173✔
2351
{
2352
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,173✔
2353
               ptr, locus);
2354

2355
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
2,173✔
2356
              "null check argument must be an access");
2357
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,173✔
2358
              "locus argument to null check must be a debug locus");
2359
}
2,173✔
2360

2361
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
91✔
2362
{
2363
   int64_t cval;
91✔
2364
   if (mir_get_const(mu, value, &cval) && cval != 0)
91✔
UNCOV
2365
      return;
×
2366

2367
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
91✔
2368
               value, locus);
2369

2370
   MIR_ASSERT(mir_is_integral(mu, value),
91✔
2371
              "argument to zero check must be integral");
2372
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
91✔
2373
              "locus argument to zero check must be a debug locus");
2374
}
2375

2376
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
7,442✔
2377
                            mir_value_t locus, mir_value_t dim)
2378
{
2379
   if (mir_equals(llen, rlen))
7,442✔
2380
      return;
2381

2382
   if (mir_is_null(dim))
7,281✔
2383
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,254✔
2384
                  llen, rlen, locus);
2385
   else
2386
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
27✔
2387
                  llen, rlen, locus, dim);
2388

2389
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
7,281✔
2390
              "locus argument to length check must be a debug locus");
2391
}
2392

2393
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
364✔
2394
                              mir_value_t locus)
2395
{
2396
   int64_t cval;
364✔
2397
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
364✔
UNCOV
2398
      return;
×
2399

2400
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
364✔
2401
               exp, locus);
2402

2403
   MIR_ASSERT(mir_is_integral(mu, exp),
364✔
2404
              "exp argument to exponent check must be a integer");
2405
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
364✔
2406
              "locus argument to exponent check must be a debug locus");
2407
}
2408

2409
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
1,236✔
2410
                         mir_value_t length, mir_value_t kind,
2411
                         mir_value_t status)
2412
{
2413
   if (mir_is_null(status))
1,236✔
2414
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,211✔
2415
                  file, name, length, kind);
2416
   else
2417
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
25✔
2418
                  file, name, length, kind, status);
2419

2420
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
1,236✔
2421
              "file open first argument must be pointer to file");
2422
}
1,236✔
2423

2424
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
90✔
2425
                         mir_value_t inlen, mir_value_t outlen)
2426
{
2427
   if (mir_is_null(inlen))
90✔
2428
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
48✔
2429
                  file, ptr);
2430
   else if (mir_is_null(outlen))
42✔
2431
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
9✔
2432
                  file, ptr, inlen);
2433
   else
2434
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
33✔
2435
                  file, ptr, inlen, outlen);
2436

2437
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
90✔
2438
              "file read first argument must have file pointer type");
2439
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
90✔
2440
              "file read pointer argument must have pointer type");
2441
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
90✔
2442
              "file read inlen argument must be integral");
2443
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
90✔
2444
              "file read outlen argument must have pointer type");
2445
}
90✔
2446

2447
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
261✔
2448
                          mir_value_t length)
2449
{
2450
   if (mir_is_null(length))
261✔
2451
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2452
                  file, value);
2453
   else
2454
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
204✔
2455
                  file, value, length);
2456

2457
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
261✔
2458
              "file write first argument must have file pointer type");
2459
}
261✔
2460

2461
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
402✔
2462
                                      mir_value_t effective)
2463
{
2464
   mir_type_t type = mir_conversion_type(mu);
402✔
2465

2466
   mir_value_t result;
402✔
2467
   if (mir_is_null(effective) || mir_equals(effective, driving))
402✔
2468
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
384✔
2469
                           driving);
2470
   else
2471
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
18✔
2472
                           driving, effective);
2473

2474
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
402✔
2475
              "port conversion argument must be a closure");
2476
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
402✔
2477
              "port conversion argument must be a closure");
2478

2479
   return result;
402✔
2480
}
2481

2482
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
480✔
2483
                          mir_value_t count)
2484
{
2485
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
480✔
2486
               conv, nets, count);
2487

2488
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
480✔
2489
              "conv argument to convert must be a port conversion");
2490
   MIR_ASSERT(mir_is_signal(mu, nets),
480✔
2491
              "nets argument to convert must be a signal");
2492
   MIR_ASSERT(mir_is_offset(mu, count),
480✔
2493
              "count argument to convert must be offset");
2494
}
480✔
2495

2496
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
522✔
2497
                           mir_value_t count)
2498
{
2499
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
522✔
2500
               conv, nets, count);
2501

2502
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
522✔
2503
              "conv argument to convert must be a port conversion");
2504
   MIR_ASSERT(mir_is_signal(mu, nets),
522✔
2505
              "nets argument to convert must be a signal");
2506
   MIR_ASSERT(mir_is_offset(mu, count),
522✔
2507
              "count argument to convert must be offset");
2508
}
522✔
2509

2510
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
519✔
2511
                              mir_value_t target, mir_value_t count,
2512
                              mir_value_t values)
2513
{
2514
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
519✔
2515
               cf, target, count, values);
2516

2517
   MIR_ASSERT(mir_is_signal(mu, target),
519✔
2518
              "put conversion target is not signal");
2519
   MIR_ASSERT(mir_is_offset(mu, count),
519✔
2520
              "put conversion net count is not offset type");
2521
   MIR_ASSERT(!mir_is_signal(mu, values),
519✔
2522
              "signal cannot be values argument for put conversion");
2523
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
519✔
2524
              "cf argument to put conversion must be conversion function");
2525
}
519✔
2526

2527
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
17,501✔
2528
                                  mir_value_t count, mir_value_t size,
2529
                                  mir_value_t value, mir_value_t flags,
2530
                                  mir_value_t locus, mir_value_t offset)
2531
{
2532
   mir_type_t stype = mir_signal_type(mu, type);
17,501✔
2533

2534
   mir_value_t result;
17,501✔
2535
   if (mir_is_null(offset))
17,501✔
2536
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
11,765✔
2537
                           count, size, value, flags, locus);
2538
   else
2539
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
5,736✔
2540
                           count, size, value, flags, locus, offset);
2541

2542
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
17,501✔
2543
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2544
              "signal must have integer or real type");
2545
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
17,501✔
2546
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
17,501✔
2547
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
17,501✔
2548
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
17,501✔
2549
              "locus argument to init signal is not debug locus");
2550
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
17,501✔
2551
              "offset argument must be pointer or null");
2552

2553
   return result;
17,501✔
2554
}
2555

2556
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
75✔
2557
                                      mir_value_t count, mir_value_t size,
2558
                                      mir_value_t locus, mir_value_t kind,
2559
                                      mir_value_t closure, mir_value_t delay)
2560
{
2561
   mir_type_t stype = mir_signal_type(mu, type);
75✔
2562

2563
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
75✔
2564
                                    MIR_NULL_STAMP, count, size, locus,
75✔
2565
                                    kind, closure, delay);
2566

2567
   MIR_ASSERT(mir_is_offset(mu, count),
75✔
2568
              "count argument to implicit signal is not offset");
2569
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
75✔
2570
              "kind argument to implicit signal is not offset");
2571
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
75✔
2572
              "closure argument to implicit signal is not a closure");
2573
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
75✔
2574
              "locus argument to implicit signal must be a debug locus");
2575
   MIR_ASSERT(mir_is_integral(mu, delay),
75✔
2576
              "delay argument to implicit signal must be time");
2577

2578
   return result;
75✔
2579
}
2580

2581
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
7,737✔
2582
                            mir_value_t count)
2583
{
2584
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,737✔
2585
               target, count);
2586

2587
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
7,737✔
2588
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
7,737✔
2589
}
7,737✔
2590

2591
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
9,268✔
2592
                              mir_value_t count, mir_value_t values,
2593
                              mir_value_t reject, mir_value_t after)
2594
{
2595
   int64_t nconst;
9,268✔
2596
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
9,268✔
UNCOV
2597
      mir_comment(mu, "Skip empty waveform");
×
UNCOV
2598
      return;
×
2599
   }
2600

2601
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,268✔
2602
               target, count, values, reject, after);
2603

2604
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
9,268✔
2605
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
9,268✔
2606
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
9,268✔
2607
}
2608

2609
void mir_build_put_driver(mir_unit_t *mu, mir_value_t target,
432✔
2610
                          mir_value_t count, mir_value_t values)
2611
{
2612
   mir_build_3(mu, MIR_OP_PUT_DRIVER, MIR_NULL_TYPE, MIR_NULL_STAMP,
432✔
2613
               target, count, values);
2614

2615
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
432✔
2616
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
432✔
2617
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
432✔
2618
}
432✔
2619

2620
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
1,662✔
2621
                              mir_value_t count, mir_value_t values)
2622
{
2623
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,662✔
2624
               target, count, values);
2625

2626
   MIR_ASSERT(mir_is_signal(mu, target),
1,662✔
2627
              "deposit signal target is not signal");
2628
   MIR_ASSERT(mir_is_offset(mu, count),
1,662✔
2629
              "deposit signal count is not offset type");
2630
   MIR_ASSERT(!mir_is_signal(mu, values),
1,662✔
2631
              "signal cannot be values argument for deposit signal");
2632
}
1,662✔
2633

2634
void mir_build_sched_deposit(mir_unit_t *mu, mir_value_t target,
132✔
2635
                             mir_value_t count, mir_value_t values,
2636
                             mir_value_t after)
2637
{
2638
   mir_build_4(mu, MIR_OP_SCHED_DEPOSIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
132✔
2639
               target, count, values, after);
2640

2641
   MIR_ASSERT(mir_is_signal(mu, target),
132✔
2642
              "sched deposit target is not signal");
2643
   MIR_ASSERT(mir_is_offset(mu, count),
132✔
2644
              "sched deposit count is not offset type");
2645
   MIR_ASSERT(!mir_is_signal(mu, values),
132✔
2646
              "signal cannot be values argument for sched deposit");
2647
}
132✔
2648

2649
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
15,759✔
2650
{
2651
   mir_type_t type = mir_get_type(mu, signal);
15,759✔
2652
   mir_type_t pointer = mir_get_pointer(mu, type);
15,759✔
2653
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
15,759✔
2654

2655
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
15,759✔
2656
                                    stamp, signal);
2657

2658
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
15,759✔
2659
              "argument to resolved must be signal");
2660

2661
   return result;
15,759✔
2662
}
2663

2664
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
228✔
2665
{
2666
   mir_type_t type = mir_get_type(mu, signal);
228✔
2667
   mir_type_t pointer = mir_get_pointer(mu, type);
228✔
2668
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
228✔
2669

2670
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
228✔
2671
                                    stamp, signal);
2672

2673
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
228✔
2674
              "argument to resolved must be signal");
2675

2676
   return result;
228✔
2677
}
2678

2679
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
120✔
2680
                                    mir_value_t count)
2681
{
2682
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
120✔
2683
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
120✔
2684

2685
   mir_value_t result;
120✔
2686
   if (mir_is_null(count))
120✔
2687
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
84✔
2688
   else
2689
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
36✔
2690
                           signal, count);
2691

2692
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
120✔
2693
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
120✔
2694
              "count argument must have offset type");
2695

2696
   return result;
120✔
2697
}
2698

2699
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
70✔
2700
                     mir_value_t values)
2701
{
2702
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
70✔
2703
               target, count, values);
2704

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

2709
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
42✔
2710
{
2711
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
42✔
2712
               target, count);
2713

2714
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
42✔
2715
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
42✔
2716
}
42✔
2717

2718
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
24✔
2719
                          mir_value_t reject, mir_value_t after)
2720
{
2721
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2722
               target, count, reject, after);
2723

2724
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
24✔
2725
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
24✔
2726
}
24✔
2727

2728

2729
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
42✔
2730
                                 mir_value_t count)
2731
{
2732
   mir_type_t type = mir_time_type(mu);
42✔
2733

2734
   mir_value_t result;
42✔
2735
   if (mir_is_null(count))
42✔
2736
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
33✔
2737
   else
2738
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
9✔
2739
                           signal, count);
2740

2741
   MIR_ASSERT(mir_is_signal(mu, signal),
42✔
2742
              "signal argument to last event must have signal type");
2743
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
42✔
2744
              "length argument to last event must have offset type");
2745

2746
   return result;
42✔
2747
}
2748

2749
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
45✔
2750
                                  mir_value_t count)
2751
{
2752
   mir_type_t type = mir_time_type(mu);
45✔
2753

2754
   mir_value_t result;
45✔
2755
   if (mir_is_null(count))
45✔
2756
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
39✔
2757
                           signal);
2758
   else
2759
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
6✔
2760
                           signal, count);
2761

2762
   MIR_ASSERT(mir_is_signal(mu, signal),
45✔
2763
              "signal argument to last event must have signal type");
2764
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
45✔
2765
              "length argument to last event must have offset type");
2766

2767
   return result;
45✔
2768
}
2769

2770

2771
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
784✔
2772
                                         mir_value_t signal, mir_value_t count)
2773
{
2774
   mir_type_t t_bool = mir_bool_type(mu);
784✔
2775
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
784✔
2776
                                    signal, count);
2777

2778
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
784✔
2779
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
784✔
2780

2781
   return result;
784✔
2782
}
2783

2784
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
531✔
2785
                                 mir_value_t count)
2786
{
2787
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
531✔
2788
}
2789

2790
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
217✔
2791
                                  mir_value_t count)
2792
{
2793
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
217✔
2794
}
2795

2796
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
36✔
2797
                                   mir_value_t count)
2798
{
2799
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
36✔
2800
}
2801

2802
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
3,983✔
2803
                              mir_value_t resolution)
2804
{
2805
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,983✔
2806
               signal, resolution);
2807

2808
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
3,983✔
2809
   MIR_ASSERT(mir_points_to(mu, resolution, MIR_TYPE_RESOLUTION),
3,983✔
2810
              "resolution wrapper argument has wrong type");
2811
}
3,983✔
2812

2813
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
530✔
2814
                               mir_value_t source, mir_value_t count,
2815
                               mir_value_t reject, mir_value_t after)
2816
{
2817
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
530✔
2818
               target, source, count, reject, after);
2819

2820
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
530✔
2821
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
530✔
2822
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
530✔
2823
}
530✔
2824

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

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

2837
void mir_build_cover_expr(mir_unit_t *mu, uint32_t tag)
887✔
2838
{
2839
   mir_build_1(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
887✔
2840
               mir_enum(tag));
2841
}
887✔
2842

2843
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
312✔
2844
{
2845
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
312✔
2846
               signal, mir_enum(tag));
2847

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

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

2858
   MIR_ASSERT(mir_is_signal(mu, signal),
12✔
2859
              "argument to cover state must be signal");
2860
}
12✔
2861
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
22,278✔
2862
                                   mir_value_t context)
2863
{
2864
   mir_value_t link = mir_add_linkage(mu, name);
22,278✔
2865
   mir_type_t type = mir_context_type(mu, name);
22,278✔
2866

2867
   mir_value_t result;
22,278✔
2868
   if (mir_is_null(context))
22,278✔
2869
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
22,088✔
2870
                           MIR_NULL_STAMP, link);
22,088✔
2871
   else
2872
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
190✔
2873
                           MIR_NULL_STAMP, link, context);
190✔
2874

2875
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
22,278✔
2876
              "invalid package init context argument");
2877
   MIR_ASSERT(mu->kind == MIR_UNIT_INSTANCE
22,278✔
2878
              || mu->kind == MIR_UNIT_PACKAGE
2879
              || mu->kind == MIR_UNIT_THUNK,
2880
              "cannot use package init here");
2881
   MIR_ASSERT(name != mu->name, "cyclic package init");
22,278✔
2882

2883
   return result;
22,278✔
2884
}
2885

2886
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
117✔
2887
{
2888
   mir_value_t link = mir_add_linkage(mu, name);
117✔
2889
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
117✔
2890
               link, locus);
2891

2892
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
117✔
2893
              "locus argument to process init must be a debug locus");
2894
}
117✔
2895

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

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

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

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

2921
   return result;
547✔
2922
}
2923

2924
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
1,690✔
2925
{
2926
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
1,690✔
2927

2928
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,690✔
2929
              "locus argument to record scope must be a debug locus");
2930
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
1,690✔
2931
              "record scope type must be record");
2932
}
1,690✔
2933

2934
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
654✔
2935
{
2936
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
654✔
2937

2938
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
654✔
2939
              "locus argument to array scope must be a debug locus");
2940
}
654✔
2941

2942
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
45✔
2943
{
2944
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
45✔
2945

2946
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2947
              "locus argument to package scope must be a debug locus");
2948
}
45✔
2949

2950
void mir_build_pop_scope(mir_unit_t *mu)
2,389✔
2951
{
2952
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
2,389✔
2953
}
2,389✔
2954

2955
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
4,296✔
2956
                            mir_value_t locus)
2957
{
2958
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,296✔
2959
               signal, locus);
2960

2961
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
4,296✔
2962
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
4,296✔
2963
              "locus argument must have debug locus type");
2964
}
4,296✔
2965

2966
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
5,440✔
2967
                          mir_value_t count)
2968
{
2969
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,440✔
2970
               src, dst, count);
2971

2972
   MIR_ASSERT(mir_is_signal(mu, src),
5,440✔
2973
              "src argument to map signal is not a signal");
2974
   MIR_ASSERT(mir_is_signal(mu, dst),
5,440✔
2975
              "dst argument to map signal is not a signal");
2976
   MIR_ASSERT(mir_is_offset(mu, count),
5,440✔
2977
              "count argument to map signal is not offset type");
2978
}
5,440✔
2979

2980
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
203✔
2981
                         mir_value_t count)
2982
{
2983
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
203✔
2984
               src, dst, count);
2985

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

2992
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
57✔
2993
                            mir_value_t count)
2994
{
2995
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2996
               src, dst, count);
2997

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

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

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

3018
   return result;
192✔
3019
}
3020

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

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

3033
   return result;
47✔
3034
}
3035

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

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

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

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

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

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

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

3065
   return result;
118✔
3066
}
3067

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

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

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

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

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

3086
   return result;
7,626✔
3087
}
3088

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

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

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

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

3105
   return result;
5,702✔
3106
}
3107

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

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

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

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

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

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

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

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

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

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

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

3166
   return result;
11,556✔
3167
}
3168

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

3174
   mir_shape_t *s = mu->parent;
49,838✔
3175
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
59,550✔
3176

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

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

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

3188
   return result;
49,838✔
3189
}
3190

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

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

3202
      MIR_ASSERT(mir_is_signal(mu, on), "argument must be signal");
4,990✔
3203
      MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
4,990✔
3204
   }
3205
}
5,143✔
3206

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

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

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

3223
void mir_build_sched_process(mir_unit_t *mu, mir_value_t delay)
5,894✔
3224
{
3225
   mir_build_1(mu, MIR_OP_SCHED_PROCESS, MIR_NULL_TYPE, MIR_NULL_STAMP, delay);
5,894✔
3226

3227
   MIR_ASSERT(mir_is_time(mu, delay), "delay argument is not a time");
5,894✔
3228
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
5,894✔
3229
              "sched process only allowed in process or procedure");
3230
}
5,894✔
3231

3232
void mir_build_sched_inactive(mir_unit_t *mu)
27✔
3233
{
3234
   mir_build_0(mu, MIR_OP_SCHED_INACTIVE, MIR_NULL_TYPE, MIR_NULL_STAMP);
27✔
3235

3236
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
27✔
3237
              "sched inactive only allowed in process or procedure");
3238
}
27✔
3239

3240
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
48✔
3241
                                    mir_value_t context, mir_value_t locus,
3242
                                    mir_value_t bounds)
3243
{
3244
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
48✔
3245

3246
   mir_value_t result;
48✔
3247
   if (mir_is_null(bounds))
48✔
3248
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
42✔
3249
                           value, context, locus);
3250
   else
3251
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
6✔
3252
                           value, context, locus, bounds);
3253

3254
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
48✔
3255
              "invalid reflect value context argument");
3256
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
48✔
3257
              "locus argument to reflect value must be a debug locus");
3258

3259
   return result;
48✔
3260
}
3261

3262
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
42✔
3263
                                      mir_value_t locus, mir_value_t bounds)
3264
{
3265
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
42✔
3266

3267
   mir_value_t result;
42✔
3268
   if (mir_is_null(bounds))
42✔
3269
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
42✔
3270
                           context, locus);
3271
   else
UNCOV
3272
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
×
3273
                           context, locus, bounds);
3274

3275
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
42✔
3276
              "invalid reflect subtype context argument");
3277
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
42✔
3278
              "locus argument to reflect subtype must be a debug locus");
3279

3280
   return result;
42✔
3281
}
3282

3283
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
14,634✔
3284
                      mir_value_t length, mir_value_t severity,
3285
                      mir_value_t locus, mir_value_t hint_left,
3286
                      mir_value_t hint_right)
3287
{
3288
   int64_t value_const;
14,634✔
3289
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
14,634✔
UNCOV
3290
      mir_comment(mu, "Always true assertion");
×
UNCOV
3291
      return;
×
3292
   }
3293

3294
   if (mir_is_null(hint_left))
14,634✔
3295
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,546✔
3296
                  value, severity, message, length, locus);
3297
   else {
3298
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
12,176✔
3299
                                     MIR_NULL_STAMP, 7);
6,088✔
3300
      mir_set_arg(mu, n, 0, value);
6,088✔
3301
      mir_set_arg(mu, n, 1, severity);
6,088✔
3302
      mir_set_arg(mu, n, 2, message);
6,088✔
3303
      mir_set_arg(mu, n, 3, length);
6,088✔
3304
      mir_set_arg(mu, n, 4, locus);
6,088✔
3305
      mir_set_arg(mu, n, 5, hint_left);
6,088✔
3306
      mir_set_arg(mu, n, 6, hint_right);
6,088✔
3307

3308
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
6,088✔
3309
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
6,088✔
3310
   }
3311

3312
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,634✔
3313
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
14,634✔
3314
              "message parameter to assert is not a pointer");
3315
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,634✔
3316
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
14,634✔
3317
              "locus argument to report must be a debug locus");
3318
}
3319

3320
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,162✔
3321
                      mir_value_t severity, mir_value_t locus)
3322
{
3323
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,162✔
3324
               severity, message, length, locus);
3325

3326
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,162✔
3327
              "message parameter to report is not a pointer");
3328
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,162✔
3329
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,162✔
3330
              "locus argument to report must be a debug locus");
3331
}
2,162✔
3332

3333
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
767✔
3334
{
3335
   mir_type_t type = mir_string_type(mu);
767✔
3336
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
767✔
3337
                                    MIR_NULL_STAMP, kind);
767✔
3338

3339
   MIR_ASSERT(mir_is_offset(mu, kind),
767✔
3340
              "kind argument to instance name must be offset");
3341

3342
   return result;
767✔
3343
}
3344

3345
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
849✔
3346
                           mir_value_t strong)
3347
{
3348
   if (mir_is_null(strong))
849✔
3349
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
813✔
3350
   else
3351
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
36✔
3352
                  state, strong);
3353

3354
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
849✔
3355
   MIR_ASSERT(mir_is_null(strong)
849✔
3356
              || mir_check_type(mu, strong, mir_bool_type(mu)),
3357
                "strong argument not is not boolean");
3358
}
849✔
3359

3360
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_value_t context,
5,646✔
3361
                              mir_type_t atype, mir_type_t rtype)
3362
{
3363
   mir_type_t ctype = mir_closure_type(mu, atype, rtype);
5,646✔
3364
   mir_value_t link = mir_add_linkage(mu, func);
5,646✔
3365

3366
   mir_value_t result = mir_build_2(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
5,646✔
3367
                                    link, context);
3368

3369
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
5,646✔
3370
              "invalid closure context argument");
3371

3372
   return result;
5,646✔
3373
}
3374

3375
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
5,151✔
3376
                                         mir_value_t closure, mir_value_t nlits)
3377
{
3378
   mir_type_t rtype = mir_resolution_type(mu, type);
5,151✔
3379
   mir_value_t result = mir_build_2(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
5,151✔
3380
                                    MIR_NULL_STAMP, closure, nlits);
5,151✔
3381

3382
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
5,151✔
3383
              "first argument to resolution wrapper must be closure");
3384

3385
   return result;
5,151✔
3386
}
3387

3388
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
80,602✔
3389
{
3390
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
80,602✔
3391
                                  MIR_NULL_STAMP, 0);
80,602✔
3392
   n->locus = obj;
80,602✔
3393

3394
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
80,602✔
3395
}
3396

3397
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
62,388✔
3398
{
3399
   mir_type_t from = mir_get_type(mu, value);
62,388✔
3400
   if (mir_equals(from, type))
62,388✔
3401
      return value;
62,388✔
3402

3403
   const mir_class_t class = mir_get_class(mu, type);
58,171✔
3404
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
58,171✔
3405

3406
   int64_t cval;
58,171✔
3407
   if (integral && mir_get_const(mu, value, &cval))
58,171✔
3408
      return mir_const(mu, type, cval);
395✔
3409

3410
   if (class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4) {
57,776✔
3411
      if (value.tag == MIR_TAG_NODE) {
3,283✔
3412
         node_data_t *n = mir_node_data(mu, value);
3,283✔
3413
         if (n->op == MIR_OP_CONST_VEC && mir_get_size(mu, type) <= 64) {
3,283✔
3414
            const uint64_t bbits = (class == MIR_TYPE_VEC2 ? 0 : n->bits[1]);
1,816✔
3415
            return mir_const_vec(mu, type, n->bits[0], bbits);
1,816✔
3416
         }
3417
      }
3418
   }
3419
   else if (integral && mir_is_vector(mu, value)) {
54,493✔
3420
      node_data_t *n = mir_node_data(mu, value);
1,267✔
3421
      if (n->op == MIR_OP_CONST_VEC) {
1,267✔
3422
         MIR_ASSERT(n->bits[1] == 0, "X value in integral cast");
1,039✔
3423
         return mir_const(mu, type, n->bits[0]);
1,039✔
3424
      }
3425
   }
3426

3427
   mir_stamp_t stamp = mir_stamp_cast(mu, type, mir_get_stamp(mu, value));
54,921✔
3428

3429
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type, stamp, value);
54,921✔
3430

3431
#ifdef DEBUG
3432
   static const mir_class_t allowed[][2] = {
54,921✔
3433
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
3434
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
3435
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
3436
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
3437
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
3438
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
3439
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
3440
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC2    },
3441
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC4    },
3442
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC2    },
3443
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC4    },
3444
      { MIR_TYPE_VEC2,   MIR_TYPE_INT     },
3445
      { MIR_TYPE_VEC2,   MIR_TYPE_OFFSET  },
3446
   };
3447

3448
   if (value.tag == MIR_TAG_CONST)
54,921✔
3449
      return result;
56✔
3450

3451
   const mir_class_t from_k = mir_get_class(mu, from);
54,865✔
3452

3453
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
111,409✔
3454
      if (from_k == allowed[i][0] && class == allowed[i][1])
111,409✔
3455
         return result;
54,865✔
3456
   }
3457

UNCOV
3458
   MIR_ASSERT(false, "invalid type conversion in cast");
×
3459
#else
3460
   return result;
3461
#endif
3462
}
3463

3464
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
2✔
3465
{
3466
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
2✔
3467

3468
   MIR_ASSERT(mir_is_integral(mu, value), "argument must be integral");
2✔
3469
}
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc