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

nickg / nvc / 23163104024

16 Mar 2026 07:48PM UTC coverage: 92.479% (-0.003%) from 92.482%
23163104024

push

github

nickg
Correct size and sign extension rules for Verilog case statement

83 of 87 new or added lines in 4 files covered. (95.4%)

8 existing lines in 4 files now uncovered.

77857 of 84189 relevant lines covered (92.48%)

435065.83 hits per line

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

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

18
#include "util.h"
19
#include "array.h"
20
#include "mir/mir-node.h"
21
#include "mir/mir-structs.h"
22
#include "mir/mir-priv.h"
23

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

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

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

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

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

50
   return b;
157,053✔
51
}
52

53
void mir_set_cursor(mir_unit_t *mu, mir_block_t block, unsigned pos)
3,035,517✔
54
{
55
   if (!mir_is_null(mu->cursor.block))
3,035,517✔
56
      mir_block_data(mu, mu->cursor.block)->last_loc = mu->cursor.loc;
2,977,187✔
57

58
   mu->cursor.block = block;
3,035,517✔
59
   mu->cursor.pos   = pos;
3,035,517✔
60

61
   if (mir_is_null(block))
3,035,517✔
62
      mu->cursor.loc = LOC_INVALID;
1,969✔
63
   else
64
      mu->cursor.loc = mir_block_data(mu, block)->last_loc;
3,033,548✔
65
}
3,035,517✔
66

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

72
   return mu->cursor.block;
51,936✔
73
}
74

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

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

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

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

94
void mir_compact(mir_unit_t *mu)
1,969✔
95
{
96
   for (int i = 0; i < mu->blocks.count; i++) {
9,021✔
97
      block_data_t *bd = &(mu->blocks.items[i]);
7,052✔
98
      if (bd->gap_pos == -1)
7,052✔
99
         continue;
3,899✔
100

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

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

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

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

123
unsigned mir_count_nodes(mir_unit_t *mu, mir_block_t block)
568,839✔
124
{
125
   if (mir_is_null(block))
568,839✔
126
      return mu->num_nodes;
55,688✔
127
   else
128
      return mir_block_data(mu, block)->num_nodes;
513,151✔
129
}
130

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

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

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

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

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

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

165
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
4,197,751✔
166
{
167
   switch (node.tag) {
4,197,751✔
168
   case MIR_TAG_NODE:
4,177,907✔
169
      return mir_node_data(mu, node)->op;
4,177,907✔
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,361,042✔
176
{
177
   switch (node.tag) {
1,361,042✔
178
   case MIR_TAG_NODE:
1,361,042✔
179
      return &(mir_node_data(mu, node)->loc);
1,361,042✔
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)
251,512✔
188
{
189
   return mir_node_data(mu, node)->nargs;
251,512✔
190
}
191

192
const mir_value_t *mir_get_args(mir_unit_t *mu, const node_data_t *nd)
7,414,455✔
193
{
194
   if (nd->nargs <= MIR_INLINE_ARGS)
7,414,455✔
195
      return nd->args;
5,069,928✔
196
   else {
197
      assert(nd->spilloff < mu->num_argspill);
2,344,527✔
198
      return mu->argspill + nd->spilloff;
2,344,527✔
199
   }
200
}
201

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

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

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

223
   return p;
37,483✔
224
}
225

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

231
   mir_mem_t mem = MIR_MEM_STACK;
83,109✔
232
   if (flags & MIR_VAR_HEAP)
83,109✔
233
      mem = MIR_MEM_LOCAL;
1,151✔
234

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

244
   return v;
83,109✔
245
}
246

247
bool mir_is_terminator(mir_op_t op)
158,140✔
248
{
249
   switch (op) {
158,140✔
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,542✔
259
      return false;
1,542✔
260
   }
261
}
262

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

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

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

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

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

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

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

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

304
      if (mu->num_nodes == mu->max_nodes) {
1,344,658✔
305
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
115,423✔
306
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
115,423✔
307
                                    sizeof(node_data_t));
308
      }
309

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

318
   return n;
1,354,869✔
319
}
320

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

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

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

345
   if (nargs > MIR_INLINE_ARGS)
1,354,869✔
346
      n->spilloff = mir_spill_args(mu, nargs);
93,001✔
347

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

350
   return n;
1,354,869✔
351
}
352

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

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

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

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

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

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

382
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
216,591✔
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);
216,591✔
387

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

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

396
static mir_value_t mir_build_4(mir_unit_t *mu, mir_op_t op, mir_type_t type,
5,014✔
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);
5,014✔
402

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

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

412
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
30,234✔
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,234✔
418
   n->nargs = 5;
30,234✔
419

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

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

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

431
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
24,792✔
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,792✔
438

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

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

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

451
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
137,554✔
452
{
453
   for (int i = 0; i < mu->linkage.count; i++) {
341,854✔
454
      if (mu->linkage.items[i] == ident)
265,127✔
455
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
60,827✔
456
   }
457

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

460
   APUSH(mu->linkage, ident);
76,727✔
461

462
   return link;
76,727✔
463
}
464

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

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

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

476
   return var;
4,643✔
477
}
478

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

484
   if (n->nargs <= MIR_INLINE_ARGS)
2,112,882✔
485
      n->args[nth] = value;
299,554✔
486
   else {
487
      assert(n->spilloff < mu->num_argspill);
1,813,328✔
488
      mu->argspill[n->spilloff + nth] = value;
1,813,328✔
489
   }
490
}
2,112,882✔
491

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

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

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

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

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

518
   if (mu->comments == NULL)
16,757✔
519
      mu->comments = tb_new();
4,378✔
520

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

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

526
   va_end(ap);
16,757✔
527

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

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

539
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
4,550,565✔
540
{
541
   switch (value.tag) {
4,550,565✔
542
   case MIR_TAG_CONST:
4,022,779✔
543
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
4,022,779✔
544
      return true;
4,022,779✔
545
   case MIR_TAG_ENUM:
200,889✔
546
      *result = value.id;
200,889✔
547
      return true;
200,889✔
548
   case MIR_TAG_NODE:
317,042✔
549
      {
550
         const node_data_t *n = mir_node_data(mu, value);
317,042✔
551
         if (n->op == MIR_OP_CONST) {
317,042✔
552
            *result = n->iconst;
7,986✔
553
            return true;
7,986✔
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)
130,606✔
564
{
565
   switch (value.tag) {
130,606✔
566
   case MIR_TAG_NODE:
97,668✔
567
      {
568
         const node_data_t *n = mir_node_data(mu, value);
97,668✔
569
         if (n->op == MIR_OP_CONST_REAL) {
97,668✔
570
            *result = n->dconst;
23,102✔
571
            return true;
23,102✔
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,352,491✔
582
{
583
   switch (value.tag) {
5,352,491✔
584
   case MIR_TAG_NODE:
4,694,457✔
585
      return mir_node_data(mu, value)->type;
4,694,457✔
586
   case MIR_TAG_PARAM:
172,025✔
587
      return mir_param_data(mu, value)->type;
172,025✔
588
   case MIR_TAG_VAR:
340,332✔
589
      return mir_var_data(mu, value)->pointer;
340,332✔
590
   default:
145,677✔
591
      return MIR_NULL_TYPE;
145,677✔
592
   }
593
}
594

595
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
733,907✔
596
{
597
   switch (value.tag) {
733,907✔
598
   case MIR_TAG_NODE:
550,980✔
599
      return mir_node_data(mu, value)->stamp;
550,980✔
600
   case MIR_TAG_PARAM:
24,611✔
601
      return mir_param_data(mu, value)->stamp;
24,611✔
602
   case MIR_TAG_VAR:
97,139✔
603
      return mir_var_data(mu, value)->stamp;
97,139✔
604
   case MIR_TAG_CONST:
61,177✔
605
      {
606
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
61,177✔
607
         return mir_int_stamp(mu, ival, ival);
61,177✔
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)
175,887✔
615
{
616
   mir_type_t type = mir_get_type(mu, value);
175,887✔
617
   if (mir_is_null(type))
175,887✔
618
      return MIR_MEM_NONE;
619

620
   switch (mir_type_data(mu, type)->class) {
174,447✔
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;
173,023✔
627
   default:
628
      return MIR_MEM_NONE;
629
   }
630

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

635
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
61,520✔
636
   if (sd->kind == MIR_STAMP_POINTER)
61,520✔
637
      return sd->u.pointer.memory;
61,318✔
638

639
   return MIR_MEM_NONE;
640
}
641

642
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
200,630✔
643
{
644
   switch (value.tag) {
200,630✔
645
   case MIR_TAG_PARAM:
24✔
646
      return mir_param_data(mu, value)->name;
24✔
647
   case MIR_TAG_VAR:
64,358✔
648
      return mir_var_data(mu, value)->name;
64,358✔
649
   case MIR_TAG_LINKAGE:
130,744✔
650
      return AGET(mu->linkage, value.id);
130,744✔
651
   case MIR_TAG_EXTVAR:
5,175✔
652
      return AGET(mu->extvars, value.id);
5,175✔
653
   case MIR_TAG_NULL:
329✔
654
      return mu->name;
329✔
655
   default:
656
      return NULL;
657
   }
658
}
659

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

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

671
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
80,739✔
672
{
673
   switch (value.tag) {
80,739✔
674
   case MIR_TAG_NODE:
80,739✔
675
      {
676
         node_data_t *n = mir_node_data(mu, value);
80,739✔
677
         assert(n->op == MIR_OP_LOCUS);
80,739✔
678
         return n->locus;
80,739✔
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,
3,330✔
687
                  uint64_t *bbits)
688
{
689
   switch (value.tag) {
3,330✔
690
   case MIR_TAG_NODE:
3,330✔
691
      {
692
         node_data_t *n = mir_node_data(mu, value);
3,330✔
693
         assert(n->op == MIR_OP_CONST_VEC);
3,330✔
694

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

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

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

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

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

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

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

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

751
   switch (mir_type_data(mu, type)->class) {
51,855✔
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:
218✔
759
      return false;
218✔
760
   }
761
}
762

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

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

772
   switch (mir_type_data(mu, type)->class) {
179,920✔
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)
73,417✔
793
{
794
   mir_type_t type = mir_get_type(mu, value);
73,417✔
795
   if (mir_is_null(type))
73,417✔
796
      return false;
797

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

807
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
142,313✔
808
{
809
   if (value.tag == MIR_TAG_CONST)
142,313✔
810
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
39,741✔
811
   else
812
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
102,572✔
813
}
814

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

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

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

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

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

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

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

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

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

855
   return mir_is(mu, value, MIR_TYPE_OFFSET);
44,532✔
856
}
857

858
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
1,746,774✔
859
{
860
   switch (value.tag) {
1,746,774✔
861
   case MIR_TAG_CONST:
862
      return true;
863
   case MIR_TAG_NODE:
17,275✔
864
      {
865
         node_data_t *n = mir_node_data(mu, value);
17,275✔
866
         switch (n->op) {
17,275✔
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,819,156✔
906
{
907
   if (value.tag == MIR_TAG_CONST) {
1,819,156✔
908
      const mir_class_t class = mir_type_data(mu, type)->class;
1,738,734✔
909
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
1,738,734✔
910
   }
911
   else
912
      return mir_equals(mir_get_type(mu, value), type);
80,422✔
913
}
914
#endif
915

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

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

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

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

943
   return result;
469,763✔
944
}
945

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

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

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

964
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_VEC, type, MIR_NULL_STAMP, 0);
5,571✔
965
   n->bits[0] = abits & mask;
5,571✔
966
   n->bits[1] = bbits & mask;
5,571✔
967

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

977
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
5,571✔
978
}
979

980
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
32,002✔
981
                            const mir_value_t *values, size_t count)
982
{
983
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
64,004✔
984
                                 MIR_NULL_STAMP, count);
32,002✔
985

986
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
32,002✔
987
              "constant array must have constrained array type");
988
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
32,002✔
989
              "have %zd", mir_get_size(mu, type), count);
990

991
   mir_type_t elem = mir_get_elem(mu, type);
32,002✔
992

993
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
32,002✔
994
   int64_t low = INT64_MAX, high = INT64_MIN;
32,002✔
995
   for (size_t i = 0; i < count; i++) {
1,766,511✔
996
      mir_set_arg(mu, n, i, values[i]);
1,734,509✔
997

998
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
1,734,509✔
999
                 "element %zd has wrong type", i);
1000
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
1,734,509✔
1001

1002
      int64_t cval;
1,734,509✔
1003
      if (integral && mir_get_const(mu, values[i], &cval)) {
1,734,509✔
1004
         low = MIN(low, cval);
1,717,758✔
1005
         high = MAX(high, cval);
1,717,758✔
1006
      }
1007
   }
1008

1009
   mir_stamp_t stamp = MIR_NULL_STAMP;
32,002✔
1010
   if (integral && low <= high)
32,002✔
1011
      stamp = mir_int_stamp(mu, low, high);
31,311✔
1012

1013
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
32,002✔
1014

1015
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
32,002✔
1016
}
1017

1018
mir_value_t mir_const_string(mir_unit_t *mu, const char *str)
3,865✔
1019
{
1020
   int count = 0, low = UINT8_MAX, high = 0;
3,865✔
1021
   for (const char *p = str; *p; p++, count++) {
18,698✔
1022
      low = MIN(low, (unsigned char)*p);
14,833✔
1023
      high = MAX(high, (unsigned char)*p);
14,833✔
1024
   }
1025

1026
   mir_type_t t_char = mir_char_type(mu);
3,865✔
1027
   mir_type_t type = mir_carray_type(mu, count, t_char);
3,865✔
1028
   mir_stamp_t stamp = mir_int_stamp(mu, low, high);
3,865✔
1029

1030
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
3,865✔
1031
                                 stamp, count);
1032

1033
   for (int i = 0; i < count; i++)
18,698✔
1034
      mir_set_arg(mu, n, i, mir_const(mu, t_char, (unsigned char)str[i]));
14,833✔
1035

1036
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
3,865✔
1037
}
1038

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

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

1050
   return result;
275✔
1051
}
1052

1053
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,044✔
1054
                             const mir_value_t *values, size_t count)
1055
{
1056
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
4,088✔
1057
                                 MIR_NULL_STAMP, count);
2,044✔
1058

1059
   DEBUG_ONLY(const type_data_t *td = mir_type_data(mu, type));
2,044✔
1060

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

1066
   for (int i = 0; i < count; i++) {
7,462✔
1067
      mir_set_arg(mu, n, i, values[i]);
5,418✔
1068

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

1075
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,044✔
1076
}
1077

1078
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
56,900✔
1079
                                   mir_value_t left, mir_value_t right,
1080
                                   mir_value_t locus, mir_stamp_t stamp)
1081
{
1082
   mir_value_t result;
56,900✔
1083
   if (mir_is_null(locus))
56,900✔
1084
      result = mir_build_2(mu, op, type, stamp, left, right);
49,512✔
1085
   else
1086
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
7,388✔
1087

1088
#ifdef DEBUG
1089
   switch (mir_get_class(mu, type)) {
56,900✔
1090
   case MIR_TYPE_INT:
56,898✔
1091
   case MIR_TYPE_REAL:
1092
   case MIR_TYPE_OFFSET:
1093
      {
1094
         mir_type_t ltype = mir_get_type(mu, left);
56,898✔
1095
         mir_type_t rtype = mir_get_type(mu, right);
56,898✔
1096

1097
         MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
56,898✔
1098
                    || mir_equals(ltype, rtype),
1099
                    "arguments to %s are not the same type", mir_op_string(op));
1100
      }
1101
      break;
1102

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

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

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

1126
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
56,900✔
1127
              "locus argument to %s is not a locus", mir_op_string(op));
1128
#endif
1129

1130
   return result;
56,900✔
1131
}
1132

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

1141
   if (lconst && lval == 0)
20,719✔
1142
      return right;
672✔
1143
   else if (rconst && rval == 0)
20,047✔
1144
      return left;
202✔
1145
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
19,845✔
1146
      return mir_const(mu, type, cval);
15✔
1147

1148
   double lreal, rreal;
19,830✔
1149
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
19,830✔
1150
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
19,830✔
1151

1152
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
19,830✔
1153
      return right;
1✔
1154
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
19,829✔
1155
      return left;
2✔
1156
   else if (lconst_real && rconst_real)
19,827✔
1157
      return mir_const_real(mu, type, lreal + rreal);
4✔
1158

1159
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
19,823✔
1160
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
19,823✔
1161
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
19,823✔
1162

1163
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
19,823✔
1164
}
1165

1166
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
15,809✔
1167
                          mir_value_t right)
1168
{
1169
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
15,809✔
1170
}
1171

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

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

1187
   if (lconst && lval == 0)
30,212✔
1188
      return mir_build_neg(mu, type, right);
3✔
1189
   else if (rconst && rval == 0)
30,209✔
1190
      return left;
117✔
1191
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
30,092✔
1192
      return mir_const(mu, type, cval);
25✔
1193
   else if (mir_equals(left, right))
30,067✔
1194
      return mir_get_class(mu, type) == MIR_TYPE_REAL
168✔
1195
         ? mir_const_real(mu, type, 0.0) : mir_const(mu, type, 0);
168✔
1196

1197
   double lreal, rreal;
29,899✔
1198
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
29,899✔
1199
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
29,899✔
1200

1201
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
29,899✔
1202
      return right;
×
1203
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
29,899✔
1204
      return left;
4✔
1205
   else if (lconst_real && rconst_real)
29,895✔
1206
      return mir_const_real(mu, type, lreal - rreal);
×
1207

1208
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
29,895✔
1209
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
29,895✔
1210
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
29,895✔
1211

1212
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
29,895✔
1213
}
1214

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

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

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

1234
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
6,995✔
1235
                                    MIR_NULL_STAMP, value);
6,995✔
1236

1237
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
6,995✔
1238

1239
   return result;
6,995✔
1240
}
1241

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

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

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

1257
   return result;
258✔
1258
}
1259

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

1266
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
694✔
1267
                                    value);
1268

1269
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
694✔
1270

1271
   return result;
694✔
1272
}
1273

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

1282
   if (lconst && lval == 0)
5,140✔
UNCOV
1283
      return left;
×
1284
   else if (rconst && rval == 0)
5,140✔
1285
      return right;
×
1286
   else if (lconst && lval == 1)
5,140✔
1287
      return right;
789✔
1288
   else if (rconst && rval == 1)
4,351✔
1289
      return left;
7✔
1290
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
4,344✔
UNCOV
1291
      return mir_const(mu, type, cval);
×
1292

1293
   double lreal, rreal;
4,344✔
1294
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
4,344✔
1295
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
4,344✔
1296

1297
   if (lconst_real && rconst_real)
4,344✔
1298
      return mir_const_real(mu, type, lreal * rreal);
158✔
1299

1300
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
4,186✔
1301
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
4,186✔
1302
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
4,186✔
1303

1304
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
4,186✔
1305
}
1306

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

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

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

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

1332
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
1,662✔
1333
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
1,662✔
1334
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
1,662✔
1335

1336
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
1,662✔
1337
                          MIR_NULL_VALUE, stamp);
1,662✔
1338
}
1339

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

1347
   if (lconst && rconst && lval > 0 && rval > 0)
961✔
1348
      return mir_const(mu, type, lval % rval);
1✔
1349

1350
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
960✔
1351
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
960✔
1352
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
960✔
1353

1354
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
960✔
1355
                          MIR_NULL_VALUE, stamp);
960✔
1356
}
1357

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

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

1368
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
122✔
1369
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
122✔
1370

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

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

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

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

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

1407
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
118✔
1408
                                        locus, MIR_NULL_STAMP);
118✔
1409

1410
   MIR_ASSERT(mir_is_integral(mu, result),
118✔
1411
              "trapping exp may only be used with integer types");
1412

1413
   return result;
118✔
1414
}
1415

1416
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
8,420✔
1417
                                     mir_type_t type, mir_value_t left,
1418
                                     mir_value_t right)
1419
{
1420
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
8,420✔
1421

1422
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
8,420✔
1423
              mir_op_string(op));
1424
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
8,420✔
1425
              mir_op_string(op));
1426

1427
   return result;
8,420✔
1428
}
1429

1430
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
7,619✔
1431
{
1432
   int64_t lval, rval;
7,619✔
1433
   const bool lconst = mir_get_const(mu, left, &lval);
7,619✔
1434
   const bool rconst = mir_get_const(mu, right, &rval);
7,619✔
1435

1436
   mir_type_t t_bool = mir_bool_type(mu);
7,619✔
1437

1438
   if (lconst && rconst)
7,619✔
1439
      return mir_const(mu, t_bool, lval && rval);
33✔
1440
   else if (lconst)
7,587✔
1441
      return lval ? right : mir_const(mu, t_bool, 0);
1,454✔
1442
   else if (rconst)
6,133✔
1443
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1444

1445
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
6,131✔
1446
}
1447

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

1454
   mir_type_t t_bool = mir_bool_type(mu);
2,180✔
1455

1456
   if (lconst && rconst)
2,180✔
1457
      return mir_const(mu, t_bool, lval || rval);
3✔
1458
   else if (lconst)
2,178✔
1459
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1460
   else if (rconst)
2,177✔
1461
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1462

1463
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
2,176✔
1464
}
1465

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

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

1478
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
113✔
1479
}
1480

1481
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
2,797✔
1482
{
1483
   mir_type_t t_bool = mir_bool_type(mu);
2,797✔
1484

1485
   int64_t cval;
2,797✔
1486
   if (mir_get_const(mu, value, &cval))
2,797✔
1487
      return mir_const(mu, t_bool, !cval);
2✔
1488

1489
   if (mir_get_op(mu, value) == MIR_OP_NOT)
2,795✔
1490
      return mir_get_arg(mu, value, 0);
31✔
1491

1492
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
2,764✔
1493
                                    MIR_NULL_STAMP, value);
2,764✔
1494

1495
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
2,764✔
1496

1497
   return result;
2,764✔
1498
}
1499

1500
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
39,315✔
1501
                          mir_value_t right)
1502
{
1503
   int64_t lval, rval;
39,315✔
1504
   const bool lconst = mir_get_const(mu, left, &lval);
39,315✔
1505
   const bool rconst = mir_get_const(mu, right, &rval);
39,315✔
1506

1507
   mir_type_t t_bool = mir_bool_type(mu);
39,315✔
1508

1509
   if (lconst && rconst) {
39,315✔
1510
      switch (cmp) {
64✔
1511
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1512
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
2✔
1513
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
11✔
1514
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
2✔
1515
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
26✔
1516
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
20✔
1517
      default: should_not_reach_here();
1518
      }
1519
   }
1520

1521
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
39,251✔
1522
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
39,251✔
1523
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
39,251✔
1524

1525
   int64_t sconst;
39,251✔
1526
   if (mir_stamp_const(mu, stamp, &sconst))
39,251✔
1527
      return mir_const(mu, t_bool, sconst);
3✔
1528

1529
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
39,248✔
1530
                                    stamp, mir_enum(cmp), left, right);
1531

1532
#ifdef DEBUG
1533
   mir_type_t type = mir_get_type(mu, left);
39,248✔
1534
   MIR_ASSERT(mir_same_type(mu, type, mir_get_type(mu, right)),
39,248✔
1535
              "arguments to cmp are not the same type");
1536
   MIR_ASSERT(mir_is_scalar(mu, left), "cmp arguments must be scalar");
39,248✔
1537
   MIR_ASSERT(mir_get_slots(mu, type) == 1,
39,248✔
1538
              "can only compare single slot types");
1539
#endif
1540

1541
   return result;
39,248✔
1542
}
1543

1544
mir_value_t mir_build_pack(mir_unit_t *mu, mir_type_t type, mir_value_t arg)
3,145✔
1545
{
1546
   mir_value_t result = mir_build_1(mu, MIR_OP_PACK, type, MIR_NULL_STAMP, arg);
3,145✔
1547

1548
#ifdef DEBUG
1549
   const mir_class_t class = mir_get_class(mu, type);
3,145✔
1550
   MIR_ASSERT(class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4,
3,145✔
1551
              "pack type must be vector");
1552
   MIR_ASSERT(mir_is(mu, arg, MIR_TYPE_POINTER)
3,145✔
1553
              || (mir_get_size(mu, type) == 1 && mir_is_integral(mu, arg)),
1554
              "pack argument must be pointer if size != 1");
1555
#endif
1556

1557
   return result;
3,145✔
1558
}
1559

1560
mir_value_t mir_build_unpack(mir_unit_t *mu, mir_value_t vec, uint8_t strength,
2,779✔
1561
                             mir_value_t dest)
1562
{
1563
   mir_value_t result = dest;
2,779✔
1564
   if (mir_is_null(dest))
2,779✔
1565
      result = mir_build_2(mu, MIR_OP_UNPACK, mir_logic_type(mu),
2,466✔
1566
                           MIR_NULL_STAMP, vec, mir_enum(strength));
1,233✔
1567
   else
1568
      mir_build_3(mu, MIR_OP_UNPACK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,546✔
1569
                  vec, mir_enum(strength), dest);
1570

1571
   MIR_ASSERT(mir_is_vector(mu, vec), "unpack argument must be vector");
2,779✔
1572
   MIR_ASSERT(mir_is_null(dest) || mir_points_to(mu, dest, MIR_TYPE_INT),
2,779✔
1573
              "unpack dest must be pointer to logic or null");
1574
   MIR_ASSERT(mir_get_size(mu, mir_get_type(mu, vec)) == 1
2,779✔
1575
              || !mir_is_null(dest),
1576
              "unpack dest must be non-null if wide vector");
1577
   MIR_ASSERT((strength & 3) == 0, "strength lower bits must be zero");
2,779✔
1578

1579
   return result;
2,779✔
1580
}
1581

1582
mir_value_t mir_build_binary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
2,295✔
1583
                             mir_value_t left, mir_value_t right)
1584
{
1585
   mir_type_t otype;
2,295✔
1586
   switch (op) {
2,295✔
1587
   case MIR_VEC_CASE_EQ:
1,881✔
1588
   case MIR_VEC_CASE_NEQ:
1589
   case MIR_VEC_CASEX_EQ:
1590
   case MIR_VEC_LOG_AND:
1591
   case MIR_VEC_LOG_OR:
1592
      // XXX: these should be vec2
1593
   case MIR_VEC_LT:
1594
   case MIR_VEC_LEQ:
1595
   case MIR_VEC_GT:
1596
   case MIR_VEC_GEQ:
1597
   case MIR_VEC_LOG_EQ:
1598
   case MIR_VEC_LOG_NEQ:
1599
      otype = mir_vec4_type(mu, 1, false);
1,881✔
1600
      break;
1,881✔
1601
   default:
414✔
1602
      otype = type;
414✔
1603
   }
1604

1605
   mir_value_t result = mir_build_3(mu, MIR_OP_BINARY, otype, MIR_NULL_STAMP,
2,295✔
1606
                                    mir_enum(op), left, right);
1607

1608
   MIR_ASSERT(mir_is_vector(mu, result), "binary operation must be vector");
2,295✔
1609
   MIR_ASSERT(mir_is_vector(mu, left), "left argument must be vector");
2,295✔
1610
   MIR_ASSERT(mir_is_vector(mu, right), "right argument must be vector");
2,295✔
1611
   MIR_ASSERT(mir_check_type(mu, left, type), "left type does not match");
2,295✔
1612
   MIR_ASSERT(mir_check_type(mu, right, type), "right type does not match");
2,295✔
1613

1614
   return result;
2,295✔
1615
}
1616

1617
mir_value_t mir_build_unary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
132✔
1618
                            mir_value_t arg)
1619
{
1620
   mir_type_t otype;
132✔
1621
   switch (op) {
132✔
1622
   case MIR_VEC_LOG_NOT:
66✔
1623
   case MIR_VEC_BIT_AND:
1624
   case MIR_VEC_BIT_OR:
1625
   case MIR_VEC_BIT_XOR:
1626
      otype = mir_vec2_type(mu, 1, false);
66✔
1627
      break;
66✔
1628
   default:
66✔
1629
      otype = type;
66✔
1630
   }
1631

1632
   mir_value_t result = mir_build_2(mu, MIR_OP_UNARY, otype, MIR_NULL_STAMP,
132✔
1633
                                    mir_enum(op), arg);
1634

1635
   MIR_ASSERT(mir_is_vector(mu, result), "unary operation must be vector");
132✔
1636
   MIR_ASSERT(mir_is_vector(mu, arg), "argument must be vector");
132✔
1637
   MIR_ASSERT(mir_check_type(mu, arg, type), "arg type does not match");
132✔
1638

1639
   return result;
132✔
1640
}
1641

1642
mir_value_t mir_build_insert(mir_unit_t *mu, mir_value_t part, mir_value_t full,
444✔
1643
                             mir_value_t pos)
1644
{
1645
   mir_type_t type = mir_get_type(mu, full);
444✔
1646
   mir_value_t result = mir_build_3(mu, MIR_OP_INSERT, type, MIR_NULL_STAMP,
444✔
1647
                                    part, full, pos);
1648

1649
   MIR_ASSERT(mir_is_vector(mu, full), "full argument must be vector");
444✔
1650
   MIR_ASSERT(mir_is_vector(mu, part), "part argument must be vector");
444✔
1651

1652
#ifdef DEBUG
1653
   mir_type_t part_type = mir_get_type(mu, part);
444✔
1654
   MIR_ASSERT(mir_get_size(mu, part_type) <= mir_get_size(mu, type),
444✔
1655
              "out of bounds insert");
1656
   MIR_ASSERT(mir_get_class(mu, part_type) == mir_get_class(mu, type),
444✔
1657
              "mismatched vector types");
1658
#endif
1659

1660
   return result;
444✔
1661
}
1662

1663
mir_value_t mir_build_extract(mir_unit_t *mu, mir_type_t type, mir_value_t full,
285✔
1664
                              mir_value_t pos)
1665
{
1666
   mir_value_t result = mir_build_2(mu, MIR_OP_EXTRACT, type, MIR_NULL_STAMP,
285✔
1667
                                    full, pos);
1668

1669
   MIR_ASSERT(mir_is_vector(mu, full), "extract argument must be vector");
285✔
1670
   MIR_ASSERT(mir_is_offset(mu, pos), "extract position must be offset");
285✔
1671

1672
#ifdef DEBUG
1673
   mir_type_t full_type = mir_get_type(mu, full);
285✔
1674
   MIR_ASSERT(mir_get_class(mu, full_type) == mir_get_class(mu, type),
285✔
1675
              "mismatched vector types");
1676
#endif
1677

1678
   return result;
285✔
1679
}
1680

1681
mir_value_t mir_build_test(mir_unit_t *mu, mir_value_t vec)
1,224✔
1682
{
1683
   mir_value_t result = mir_build_1(mu, MIR_OP_TEST, mir_bool_type(mu),
1,224✔
1684
                                    MIR_NULL_STAMP, vec);
1,224✔
1685

1686
   MIR_ASSERT(mir_is_vector(mu, vec), "argument must be vector");
1,224✔
1687

1688
   return result;
1,224✔
1689
}
1690

1691
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
103,345✔
1692
{
1693
   mir_build_2(mu, MIR_OP_STORE, MIR_NULL_TYPE, MIR_NULL_STAMP, dest, src);
103,345✔
1694

1695
#ifdef DEBUG
1696
   mir_type_t type = mir_get_type(mu, dest);
103,345✔
1697
   mir_type_t pointed = mir_get_pointer(mu, type);
103,345✔
1698
#endif
1699

1700
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
103,345✔
1701
              "store destination is not a pointer or variable");
1702
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
103,345✔
1703
              "source and destination have different types");
1704
}
103,345✔
1705

1706
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
135,032✔
1707
{
1708
   mir_type_t type = mir_get_type(mu, value);
135,032✔
1709
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
135,032✔
1710
   mir_type_t pointed = mir_get_pointer(mu, type);
135,032✔
1711

1712
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
135,032✔
1713

1714
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
135,032✔
1715
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
135,032✔
1716
              "argument to load is not a pointer or variable");
1717
   MIR_ASSERT(mir_is_scalar(mu, result), "cannot load non-scalar type");
135,032✔
1718
   MIR_ASSERT(mir_get_mem(mu, value) != MIR_MEM_NULL,
135,032✔
1719
              "null pointer dereference");
1720

1721
   return result;
135,032✔
1722
}
1723

1724
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
27,166✔
1725
                    mir_value_t count)
1726
{
1727
   int64_t cval;
27,166✔
1728
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
27,166✔
1729
      return;
188✔
1730
   else if (mir_equals(dest, src))
27,166✔
1731
      return;
1732

1733
   mir_type_t dtype = mir_get_type(mu, dest);
26,978✔
1734
   mir_type_t elem = mir_get_pointer(mu, dtype);
26,978✔
1735

1736
   if (mir_is_null(count))
26,978✔
1737
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
1,587✔
1738
   else
1739
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
25,391✔
1740

1741
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
26,978✔
1742
              "destination type is not a pointer");
1743
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
26,978✔
1744
              "source type is not a pointer");
1745
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
26,978✔
1746
              "source and destination types do not match");
1747
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
26,978✔
1748
              "count is not offset type");
1749
}
1750

1751
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
5,514✔
1752
                   mir_value_t count)
1753
{
1754
   int64_t cval;
5,514✔
1755
   if (mir_get_const(mu, count, &cval) && cval == 0)
5,514✔
1756
      return;
×
1757

1758
   mir_type_t dtype = mir_get_type(mu, dest);
5,514✔
1759
   mir_type_t elem = mir_get_pointer(mu, dtype);
5,514✔
1760

1761
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
5,514✔
1762

1763
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
5,514✔
1764
              "destination type is not a pointer");
1765
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
5,514✔
1766
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
5,514✔
1767
}
1768

1769
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
7,720✔
1770
                            mir_value_t count)
1771
{
1772
   mir_type_t ptr = mir_pointer_type(mu, type);
7,720✔
1773
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
7,720✔
1774

1775
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
7,720✔
1776
              "alloc element type cannot be array");
1777
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
7,720✔
1778

1779
   return result;
7,720✔
1780
}
1781

1782
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
4,835✔
1783
{
1784
   mir_stamp_t stamp = mir_pointer_stamp(mu, MIR_MEM_NULL, MIR_NULL_STAMP);
4,835✔
1785
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, stamp);
4,835✔
1786

1787
#ifdef DEBUG
1788
   const mir_class_t class = mir_get_class(mu, type);
4,835✔
1789
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
4,835✔
1790
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1791
              "null type must be file, access, context, or pointer");
1792
#endif
1793

1794
   return result;
4,835✔
1795
}
1796

1797
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
663✔
1798
                          mir_value_t count)
1799
{
1800
   mir_type_t access = mir_access_type(mu, type);
663✔
1801

1802
   mir_value_t result;
663✔
1803
   if (mir_is_null(count))
663✔
1804
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
91✔
1805
   else
1806
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
572✔
1807

1808
#ifdef DEBUG
1809
   const mir_class_t class = mir_get_class(mu, type);
663✔
1810
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
663✔
1811
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1812
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1813
              "new type must be int, real, record, access, or uarray");
1814
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
663✔
1815
              "new count must have offset type");
1816
#endif
1817

1818
   return result;
663✔
1819
}
1820

1821
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
2,922✔
1822
{
1823
   mir_type_t type = mir_get_type(mu, access);
2,922✔
1824
   mir_stamp_t stamp = mir_get_stamp(mu, access);
2,922✔
1825
   mir_type_t pointed = mir_get_pointer(mu, type);
2,922✔
1826
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
2,922✔
1827

1828
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
2,922✔
1829
              "argument to all must be access type");
1830

1831
   return result;
2,922✔
1832
}
1833

1834
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
37,171✔
1835
{
1836
   mir_type_t type = mir_get_type(mu, array);
37,171✔
1837
   mir_type_t pointer = mir_get_pointer(mu, type);
37,171✔
1838
   mir_stamp_t stamp = mir_get_stamp(mu, array);
37,171✔
1839

1840
   if (mir_is_null(pointer))
37,171✔
1841
      pointer = mir_pointer_type(mu, type);
1,528✔
1842

1843
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
37,171✔
1844
                                    pointer, stamp, array);
1845

1846
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
37,171✔
1847
              || mir_is(mu, array, MIR_TYPE_RECORD),
1848
              "argument to address of must be array or record");
1849

1850
   return result;
37,171✔
1851
}
1852

1853
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
40,829✔
1854
                                mir_value_t offset)
1855
{
1856
   int64_t cval;
40,829✔
1857
   if (mir_get_const(mu, offset, &cval) && cval == 0)
40,829✔
1858
      return array;
8,983✔
1859

1860
   mir_type_t type = mir_get_type(mu, array);
31,846✔
1861
   mir_stamp_t stamp = mir_get_stamp(mu, array);
31,846✔
1862

1863
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
31,846✔
1864
                                    array, offset);
1865

1866
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
31,846✔
1867
              "argument to array ref must be pointer or signal");
1868
   MIR_ASSERT(mir_is_offset(mu, offset),
31,846✔
1869
              "offset argument to array ref must be offset");
1870

1871
   return result;
31,846✔
1872
}
1873

1874
mir_value_t mir_build_table_ref(mir_unit_t *mu, mir_value_t array,
757✔
1875
                                mir_value_t stride, const mir_value_t *args,
1876
                                int nargs)
1877
{
1878
   mir_type_t type = mir_get_type(mu, array);
757✔
1879
   mir_stamp_t stamp = mir_get_stamp(mu, array);
757✔
1880

1881
   node_data_t *n = mir_add_node(mu, MIR_OP_TABLE_REF, type, stamp, nargs + 2);
757✔
1882

1883
   mir_set_arg(mu, n, 0, array);
757✔
1884
   mir_set_arg(mu, n, 1, stride);
757✔
1885

1886
   for (int i = 0; i < nargs; i++)
1,909✔
1887
      mir_set_arg(mu, n, i + 2, args[i]);
1,152✔
1888

1889
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER),
757✔
1890
              "argument to table ref must be pointer");
1891
   MIR_ASSERT(mir_is_offset(mu, stride),
757✔
1892
              "stride argument to table ref must be offset");
1893

1894
   for (int i = 0; i < nargs; i++)
1,909✔
1895
      MIR_ASSERT(mir_is_integral(mu, args[i]),
1,152✔
1896
                 "table ref indices must be integral");
1897

1898
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
757✔
1899
}
1900

1901
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
33,499✔
1902
                                 unsigned field)
1903
{
1904
   mir_type_t pointer = mir_get_type(mu, record);
33,499✔
1905

1906
   mir_mem_t mem = mir_get_mem(mu, record);
33,499✔
1907
   mir_stamp_t stamp = MIR_NULL_STAMP;
33,499✔
1908
   if (mem != MIR_MEM_TOP)
33,499✔
1909
      stamp = mir_pointer_stamp(mu, mem, MIR_NULL_STAMP);
14,431✔
1910

1911
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
33,499✔
1912

1913
   mir_type_t type = MIR_NULL_TYPE;
33,499✔
1914
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
33,499✔
1915
      type = td->u.record.fields[field + td->u.record.count];
33,499✔
1916

1917
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, stamp,
33,499✔
1918
                                    record, mir_enum(field));
1919

1920
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
33,499✔
1921
              "record ref argument must be pointer to record");
1922
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
33,499✔
1923
              "record ref argument must be pointer to record");
1924
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
33,499✔
1925

1926
   return result;
33,499✔
1927
}
1928

1929
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
34,257✔
1930
                           const mir_dim_t *dims, int ndims)
1931
{
1932
   mir_type_t type = mir_get_type(mu, data);
34,257✔
1933
   mir_stamp_t stamp = mir_get_stamp(mu, data);
34,257✔
1934

1935
   const type_data_t *td = mir_type_data(mu, type);
34,257✔
1936
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
34,257✔
1937

1938
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
34,257✔
1939

1940
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
68,514✔
1941
                                  ndims * 3 + 1);
34,257✔
1942

1943
   mir_set_arg(mu, n, 0, data);
34,257✔
1944

1945
   for (int i = 0; i < ndims; i++) {
69,040✔
1946
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
34,783✔
1947
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
34,783✔
1948
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
34,783✔
1949
   }
1950

1951
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
34,257✔
1952
              "wrapped data is not pointer or signal");
1953

1954
   for (int i = 0; i < ndims; i++) {
69,040✔
1955
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
34,783✔
1956
                 "dimension %d left bound must be integral", i + 1);
1957
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
34,783✔
1958
                 "dimension %d right bound must be integral", i + 1);
1959
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
34,783✔
1960
                 "dimension %d direction must be bool", i + 1);
1961
   }
1962

1963
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
34,257✔
1964
}
1965

1966
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
27,737✔
1967
{
1968
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
27,737✔
1969
      return mir_get_arg(mu, array, 0);
1,655✔
1970

1971
   mir_type_t type = mir_get_type(mu, array);
26,082✔
1972
   mir_type_t pointer = mir_get_pointer(mu, type);
26,082✔
1973
   mir_stamp_t stamp = mir_get_stamp(mu, array);
26,082✔
1974

1975
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
26,082✔
1976

1977
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
26,082✔
1978
              "unwrap argument must be uarray");
1979

1980
   return result;
26,082✔
1981
}
1982

1983
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
21,924✔
1984
{
1985
   mir_type_t t_offset = mir_offset_type(mu);
21,924✔
1986
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
21,924✔
1987
                                    MIR_NULL_STAMP, array,
21,924✔
1988
                                    mir_const(mu, t_offset, dim));
1989

1990
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
21,924✔
1991
              "uarray len argument must be uarrray");
1992

1993
#ifdef DEBUG
1994
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
21,924✔
1995
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
21,924✔
1996
#endif
1997

1998
   return result;
21,924✔
1999
}
2000

2001
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
45,568✔
2002
                                       mir_type_t type, int arg_index,
2003
                                       mir_value_t array, int dim)
2004
{
2005
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
45,568✔
2006
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,319✔
2007

2008
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
44,249✔
2009
                                    array, mir_enum(dim));
2010

2011
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
44,249✔
2012
              "cannot use %s with non-uarray type", mir_op_string(op));
2013

2014
#ifdef DEBUG
2015
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
44,249✔
2016
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
44,249✔
2017
#endif
2018

2019
   return result;
44,249✔
2020
}
2021

2022
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
16,159✔
2023
{
2024
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
16,159✔
2025
                              0, array, dim);
2026
}
2027

2028
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
13,238✔
2029
{
2030
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
13,238✔
2031
                              1, array, dim);
2032
}
2033

2034
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
16,171✔
2035
{
2036
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
16,171✔
2037
                              2, array, dim);
2038
}
2039

2040
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
6,884✔
2041
                                   mir_value_t right, mir_value_t dir)
2042
{
2043
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
6,884✔
2044
                                    mir_offset_type(mu), MIR_NULL_STAMP,
6,884✔
2045
                                    left, right, dir);
2046

2047
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
6,884✔
2048
                            mir_get_type(mu, right)),
2049
              "left and right are not the same type");
2050
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
6,884✔
2051
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
6,884✔
2052

2053
   return result;
6,884✔
2054
}
2055

2056
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
3,071✔
2057
                                 mir_value_t right, mir_value_t dir)
2058
{
2059
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
3,071✔
2060
                                    mir_bool_type(mu), MIR_NULL_STAMP,
3,071✔
2061
                                    left, right, dir);
2062

2063
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
3,071✔
2064
                            mir_get_type(mu, right)),
2065
              "left and right are not the same type");
2066
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
3,071✔
2067
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
3,071✔
2068

2069
   return result;
3,071✔
2070
}
2071

2072
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
38,793✔
2073
{
2074
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
38,793✔
2075
               mir_cast_value(target));
38,793✔
2076

2077
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
38,793✔
2078
}
38,793✔
2079

2080
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
35,826✔
2081
                    mir_block_t bfalse)
2082
{
2083
   int64_t tconst;
35,826✔
2084
   if (mir_get_const(mu, test, &tconst)) {
35,826✔
2085
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
21✔
2086
      return;
21✔
2087
   }
2088

2089
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
35,805✔
2090
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
35,805✔
2091

2092
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
35,805✔
2093
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
35,805✔
2094
              "invalid cond targets");
2095
}
2096

2097
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
12,881✔
2098
                             mir_value_t vtrue, mir_value_t vfalse)
2099
{
2100
   int64_t tconst;
12,881✔
2101
   if (mir_get_const(mu, test, &tconst))
12,881✔
2102
      return tconst ? vtrue : vfalse;
118✔
2103
   else if (mir_equals(vtrue, vfalse))
12,763✔
2104
      return vtrue;
1✔
2105

2106
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
12,762✔
2107
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
12,762✔
2108
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
12,762✔
2109

2110
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
12,762✔
2111
                                    vtrue, vfalse);
2112

2113
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
12,762✔
2114
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
12,762✔
2115
              "true argument to select is not expected type");
2116
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
12,762✔
2117
              "false argument to select is not expected type");
2118

2119
   return result;
12,762✔
2120
}
2121

2122
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
2123
{
2124
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
2125
                                 ninputs * 2);
2126

2127
   for (int i = 0; i < ninputs; i++)
3✔
2128
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
2129

2130
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
2131
}
2132

2133
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
2134
                   mir_block_t block, mir_value_t value)
2135
{
2136
   node_data_t *n = mir_node_data(mu, phi);
2✔
2137
   assert(n->op == MIR_OP_PHI);
2✔
2138
   assert(nth * 2 < n->nargs);
2✔
2139

2140
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
2141
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
2142

2143
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
2144

2145
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
2146
              "phi input %d has wrong type", nth);
2147

2148
#ifdef DEBUG
2149
   if (value.tag != MIR_TAG_CONST) {
2✔
2150
      const block_data_t *bd = mir_block_data(mu, block);
2✔
2151
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
2152
         if (bd->nodes[i] == value.id)
2✔
2153
         return;
2154
      }
2155

2156
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
2157
   }
2158
#endif
2159
}
2160

2161
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
781✔
2162
                    const mir_value_t *cases, const mir_block_t *blocks,
2163
                    int ncases)
2164
{
2165
   int64_t cval;
781✔
2166
   if (mir_get_const(mu, value, &cval)) {
781✔
2167
      for (int i = 0; i < ncases; i++) {
3✔
2168
         int64_t cmp;
2✔
2169
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
2170
            mir_build_jump(mu, blocks[i]);
1✔
2171
            return;
1✔
2172
         }
2173
      }
2174

2175
      mir_build_jump(mu, def);
1✔
2176
      return;
1✔
2177
   }
2178

2179
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,558✔
2180
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
779✔
2181

2182
   mir_set_arg(mu, n, 0, value);
779✔
2183
   mir_set_arg(mu, n, 1, mir_cast_value(def));
779✔
2184

2185
   for (int i = 0; i < ncases; i++) {
7,626✔
2186
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
6,847✔
2187
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
6,847✔
2188
   }
2189

2190
   MIR_ASSERT(mir_is_integral(mu, value), "case choice must be integral");
779✔
2191

2192
#ifdef DEBUG
2193
   mir_type_t type = mir_get_type(mu, value);
779✔
2194
   for (int i = 0; i < ncases; i++) {
7,626✔
2195
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
6,847✔
2196
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
6,847✔
2197
                 "choice and value types do not match");
2198

2199
      for (int j = 0; j < i; j++)
444,862✔
2200
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
438,015✔
2201
   }
2202
#endif
2203
}
2204

2205
void mir_build_return(mir_unit_t *mu, mir_value_t value)
65,616✔
2206
{
2207
   if (mir_is_null(value))
65,616✔
2208
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
33,068✔
2209
   else
2210
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
32,548✔
2211

2212
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
65,616✔
2213
              "wrong result type");
2214
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
65,616✔
2215
              || mir_is_null(value), "cannot return a result");
2216
}
65,616✔
2217

2218
void mir_build_wait(mir_unit_t *mu, mir_block_t target)
13,798✔
2219
{
2220
   mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
13,798✔
2221
               mir_cast_value(target));
13,798✔
2222

2223
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
13,798✔
2224
              "wait only allowed in process or procedure");
2225
}
13,798✔
2226

2227
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
2,152✔
2228
{
2229
   if (value.tag != MIR_TAG_NODE)
2,152✔
2230
      return;   // Only useful for keeping nodes alive
2231

2232
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
408✔
2233
}
2234

2235
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
35,773✔
2236
                            mir_stamp_t stamp, const mir_value_t *args,
2237
                            unsigned nargs)
2238
{
2239
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
35,773✔
2240

2241
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
35,773✔
2242

2243
   for (int i = 0; i < nargs; i++)
125,045✔
2244
      mir_set_arg(mu, n, i + 1, args[i]);
89,272✔
2245

2246
   if (mir_is_null(type))
35,773✔
2247
      return MIR_NULL_VALUE;
5,618✔
2248
   else
2249
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,155✔
2250
}
2251

2252
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
862✔
2253
                     const mir_value_t *args, unsigned nargs)
2254
{
2255
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
1,724✔
2256
                                 MIR_NULL_STAMP, nargs + 2);
862✔
2257
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
862✔
2258
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
862✔
2259

2260
   for (int i = 0; i < nargs; i++)
2,885✔
2261
      mir_set_arg(mu, n, i + 2, args[i]);
2,023✔
2262

2263
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
862✔
2264
              "first argument to VHDL procedure must be context pointer");
2265
}
862✔
2266

2267
void mir_build_resume(mir_unit_t *mu, ident_t name)
862✔
2268
{
2269
   mir_value_t link = mir_add_linkage(mu, name);
862✔
2270
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
862✔
2271

2272
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
862✔
2273
              "resume must be first op in a block");
2274
}
862✔
2275

2276
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
1,974✔
2277
                              mir_stamp_t stamp, mir_value_t locus,
2278
                              const mir_value_t *args, int nargs)
2279
{
2280
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
1,974✔
2281

2282
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
1,974✔
2283
   mir_set_arg(mu, n, 1, locus);
1,974✔
2284

2285
   for (int i = 0; i < nargs; i++)
2,718✔
2286
      mir_set_arg(mu, n, i + 2, args[i]);
744✔
2287

2288
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,974✔
2289
              "locus argument to syscall must be a debug locus");
2290

2291
   for (int i = 0; i < nargs; i++)
2,718✔
2292
      MIR_ASSERT(!mir_is_null(args[i]), "invalid argument to syscall");
744✔
2293

2294
   if (mir_is_null(type))
1,974✔
2295
      return MIR_NULL_VALUE;
1,743✔
2296
   else
2297
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
231✔
2298
}
2299

2300
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
1,831✔
2301
{
2302
   if (mir_is_null(locus))
1,831✔
2303
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
1,710✔
2304
   else
2305
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
121✔
2306

2307
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
1,831✔
2308
              "locus argument to unreachable must be debug locus");
2309
}
1,831✔
2310

2311
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
18,900✔
2312
                                mir_value_t left, mir_value_t right,
2313
                                mir_value_t dir, mir_value_t locus,
2314
                                mir_value_t hint)
2315
{
2316
   // TODO: check if can elide bounds
2317

2318
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
18,900✔
2319
               dir, locus, hint);
2320

2321
   MIR_ASSERT(mir_is_numeric(mu, value), "value must be numeric");
18,900✔
2322
   MIR_ASSERT(mir_is_numeric(mu, left), "left bound must be numeric");
18,900✔
2323
   MIR_ASSERT(mir_is_numeric(mu, right), "right bound must be numeric");
18,900✔
2324
   MIR_ASSERT(mir_check_type(mu, dir, mir_bool_type(mu)),
18,900✔
2325
              "direction must be a bool");
2326
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS), "locus must be a debug locus");
18,900✔
2327
}
18,900✔
2328

2329
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
3,828✔
2330
                           mir_value_t right, mir_value_t dir,
2331
                           mir_value_t locus, mir_value_t hint)
2332
{
2333
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
3,828✔
2334
                       locus, hint);
2335
}
3,828✔
2336

2337
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
15,072✔
2338
                           mir_value_t right, mir_value_t dir,
2339
                           mir_value_t locus, mir_value_t hint)
2340
{
2341
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
15,072✔
2342
                       locus, hint);
2343
}
15,072✔
2344

2345
void mir_build_dir_check(mir_unit_t *mu, mir_value_t value, mir_value_t dir,
2,394✔
2346
                         mir_value_t locus)
2347
{
2348
   if (mir_equals(value, dir)) {
2,394✔
2349
      mir_comment(mu, "Elided direction check");
814✔
2350
      return;
814✔
2351
   }
2352

2353
   mir_build_3(mu, MIR_OP_DIR_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,580✔
2354
               value, dir, locus);
2355

2356
   MIR_ASSERT(mir_check_type(mu, value, mir_bool_type(mu)),
1,580✔
2357
              "null check argument must be a bool");
2358
   MIR_ASSERT(mir_check_type(mu, dir, mir_bool_type(mu)),
1,580✔
2359
              "null check direction must be a bool");
2360
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,580✔
2361
              "locus argument to null check must be a debug locus");
2362
}
2363

2364
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
2,259✔
2365
{
2366
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,259✔
2367
               ptr, locus);
2368

2369
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
2,259✔
2370
              "null check argument must be an access");
2371
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,259✔
2372
              "locus argument to null check must be a debug locus");
2373
}
2,259✔
2374

2375
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
88✔
2376
{
2377
   int64_t cval;
88✔
2378
   if (mir_get_const(mu, value, &cval) && cval != 0)
88✔
2379
      return;
×
2380

2381
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
88✔
2382
               value, locus);
2383

2384
   MIR_ASSERT(mir_is_integral(mu, value),
88✔
2385
              "argument to zero check must be integral");
2386
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
88✔
2387
              "locus argument to zero check must be a debug locus");
2388
}
2389

2390
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
7,271✔
2391
                            mir_value_t locus, mir_value_t dim)
2392
{
2393
   if (mir_equals(llen, rlen))
7,271✔
2394
      return;
2395

2396
   if (mir_is_null(dim))
7,101✔
2397
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,074✔
2398
                  llen, rlen, locus);
2399
   else
2400
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
27✔
2401
                  llen, rlen, locus, dim);
2402

2403
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
7,101✔
2404
              "locus argument to length check must be a debug locus");
2405
}
2406

2407
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
112✔
2408
                              mir_value_t locus)
2409
{
2410
   int64_t cval;
112✔
2411
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
112✔
2412
      return;
×
2413

2414
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
112✔
2415
               exp, locus);
2416

2417
   MIR_ASSERT(mir_is_integral(mu, exp),
112✔
2418
              "exp argument to exponent check must be a integer");
2419
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
112✔
2420
              "locus argument to exponent check must be a debug locus");
2421
}
2422

2423
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
1,268✔
2424
                         mir_value_t length, mir_value_t kind,
2425
                         mir_value_t status)
2426
{
2427
   if (mir_is_null(status))
1,268✔
2428
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,243✔
2429
                  file, name, length, kind);
2430
   else
2431
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
25✔
2432
                  file, name, length, kind, status);
2433

2434
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
1,268✔
2435
              "file open first argument must be pointer to file");
2436
}
1,268✔
2437

2438
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
90✔
2439
                         mir_value_t inlen, mir_value_t outlen)
2440
{
2441
   if (mir_is_null(inlen))
90✔
2442
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
48✔
2443
                  file, ptr);
2444
   else if (mir_is_null(outlen))
42✔
2445
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
9✔
2446
                  file, ptr, inlen);
2447
   else
2448
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
33✔
2449
                  file, ptr, inlen, outlen);
2450

2451
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
90✔
2452
              "file read first argument must have file pointer type");
2453
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
90✔
2454
              "file read pointer argument must have pointer type");
2455
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
90✔
2456
              "file read inlen argument must be integral");
2457
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
90✔
2458
              "file read outlen argument must have pointer type");
2459
}
90✔
2460

2461
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
273✔
2462
                          mir_value_t length)
2463
{
2464
   if (mir_is_null(length))
273✔
2465
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2466
                  file, value);
2467
   else
2468
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
216✔
2469
                  file, value, length);
2470

2471
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
273✔
2472
              "file write first argument must have file pointer type");
2473
}
273✔
2474

2475
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
411✔
2476
                                      mir_value_t effective)
2477
{
2478
   mir_type_t type = mir_conversion_type(mu);
411✔
2479

2480
   mir_value_t result;
411✔
2481
   if (mir_is_null(effective) || mir_equals(effective, driving))
411✔
2482
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
393✔
2483
                           driving);
2484
   else
2485
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
18✔
2486
                           driving, effective);
2487

2488
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
411✔
2489
              "port conversion argument must be a closure");
2490
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
411✔
2491
              "port conversion argument must be a closure");
2492

2493
   return result;
411✔
2494
}
2495

2496
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
489✔
2497
                          mir_value_t count)
2498
{
2499
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
489✔
2500
               conv, nets, count);
2501

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

2510
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
531✔
2511
                           mir_value_t count)
2512
{
2513
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
531✔
2514
               conv, nets, count);
2515

2516
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
531✔
2517
              "conv argument to convert must be a port conversion");
2518
   MIR_ASSERT(mir_is_signal(mu, nets),
531✔
2519
              "nets argument to convert must be a signal");
2520
   MIR_ASSERT(mir_is_offset(mu, count),
531✔
2521
              "count argument to convert must be offset");
2522
}
531✔
2523

2524
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
525✔
2525
                              mir_value_t target, mir_value_t count,
2526
                              mir_value_t values)
2527
{
2528
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
525✔
2529
               cf, target, count, values);
2530

2531
   MIR_ASSERT(mir_is_signal(mu, target),
525✔
2532
              "put conversion target is not signal");
2533
   MIR_ASSERT(mir_is_offset(mu, count),
525✔
2534
              "put conversion net count is not offset type");
2535
   MIR_ASSERT(!mir_is_signal(mu, values),
525✔
2536
              "signal cannot be values argument for put conversion");
2537
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
525✔
2538
              "cf argument to put conversion must be conversion function");
2539
}
525✔
2540

2541
mir_value_t mir_build_init_functor(mir_unit_t *mu, mir_value_t closure)
338✔
2542
{
2543
   mir_type_t type = mir_functor_type(mu);
338✔
2544
   mir_value_t result = mir_build_1(mu, MIR_OP_INIT_FUNCTOR, type,
338✔
2545
                                    MIR_NULL_STAMP, closure);
338✔
2546

2547
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
338✔
2548
              "init functor argument must be a closure");
2549

2550
   return result;
338✔
2551
}
2552

2553
void mir_build_functor_in(mir_unit_t *mu, mir_value_t functor,
314✔
2554
                          mir_value_t nets, mir_value_t count)
2555
{
2556
   mir_build_3(mu, MIR_OP_FUNCTOR_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
314✔
2557
               functor, nets, count);
2558

2559
   MIR_ASSERT(mir_is(mu, functor, MIR_TYPE_FUNCTOR),
314✔
2560
              "argument to functor in must be a functor");
2561
   MIR_ASSERT(mir_is_signal(mu, nets),
314✔
2562
              "nets argument to functor in must be a signal");
2563
   MIR_ASSERT(mir_is_offset(mu, count),
314✔
2564
              "count argument to functor in must be offset");
2565
}
314✔
2566

2567
void mir_build_functor_out(mir_unit_t *mu, mir_value_t functor,
347✔
2568
                           mir_value_t nets, mir_value_t count)
2569
{
2570
   mir_build_3(mu, MIR_OP_FUNCTOR_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
347✔
2571
               functor, nets, count);
2572

2573
   MIR_ASSERT(mir_is(mu, functor, MIR_TYPE_FUNCTOR),
347✔
2574
              "argument to functor out must be a functor");
2575
   MIR_ASSERT(mir_is_signal(mu, nets),
347✔
2576
              "nets argument to functor out must be a signal");
2577
   MIR_ASSERT(mir_is_offset(mu, count),
347✔
2578
              "count argument to functor out must be offset");
2579
}
347✔
2580

2581
void mir_build_put_functor(mir_unit_t *mu, mir_value_t functor,
336✔
2582
                           mir_value_t target, mir_value_t count,
2583
                           mir_value_t values)
2584
{
2585
   mir_build_4(mu, MIR_OP_PUT_FUNCTOR, MIR_NULL_TYPE, MIR_NULL_STAMP,
336✔
2586
               functor, target, count, values);
2587

2588
   MIR_ASSERT(mir_is_signal(mu, target),
336✔
2589
              "put functor target is not signal");
2590
   MIR_ASSERT(mir_is_offset(mu, count),
336✔
2591
              "put functor net count is not offset type");
2592
   MIR_ASSERT(!mir_is_signal(mu, values),
336✔
2593
              "signal cannot be values argument for put functor");
2594
   MIR_ASSERT(mir_is(mu, functor, MIR_TYPE_FUNCTOR),
336✔
2595
              "argument to put functor must be functor");
2596
}
336✔
2597

2598
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
17,722✔
2599
                                  mir_value_t count, mir_value_t size,
2600
                                  mir_value_t value, mir_value_t flags,
2601
                                  mir_value_t locus, mir_value_t offset)
2602
{
2603
   mir_type_t stype = mir_signal_type(mu, type);
17,722✔
2604

2605
   mir_value_t result;
17,722✔
2606
   if (mir_is_null(offset))
17,722✔
2607
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
11,907✔
2608
                           count, size, value, flags, locus);
2609
   else
2610
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
5,815✔
2611
                           count, size, value, flags, locus, offset);
2612

2613
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
17,722✔
2614
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2615
              "signal must have integer or real type");
2616
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
17,722✔
2617
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
17,722✔
2618
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
17,722✔
2619
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
17,722✔
2620
              "locus argument to init signal is not debug locus");
2621
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
17,722✔
2622
              "offset argument must be pointer or null");
2623

2624
   return result;
17,722✔
2625
}
2626

2627
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
77✔
2628
                                      mir_value_t count, mir_value_t size,
2629
                                      mir_value_t locus, mir_value_t kind,
2630
                                      mir_value_t closure, mir_value_t delay)
2631
{
2632
   mir_type_t stype = mir_signal_type(mu, type);
77✔
2633

2634
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
77✔
2635
                                    MIR_NULL_STAMP, count, size, locus,
77✔
2636
                                    kind, closure, delay);
2637

2638
   MIR_ASSERT(mir_is_offset(mu, count),
77✔
2639
              "count argument to implicit signal is not offset");
2640
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
77✔
2641
              "kind argument to implicit signal is not offset");
2642
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
77✔
2643
              "closure argument to implicit signal is not a closure");
2644
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
77✔
2645
              "locus argument to implicit signal must be a debug locus");
2646
   MIR_ASSERT(mir_is_integral(mu, delay),
77✔
2647
              "delay argument to implicit signal must be time");
2648

2649
   return result;
77✔
2650
}
2651

2652
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
7,234✔
2653
                            mir_value_t count)
2654
{
2655
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,234✔
2656
               target, count);
2657

2658
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
7,234✔
2659
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
7,234✔
2660
}
7,234✔
2661

2662
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
9,213✔
2663
                              mir_value_t count, mir_value_t values,
2664
                              mir_value_t reject, mir_value_t after)
2665
{
2666
   int64_t nconst;
9,213✔
2667
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
9,213✔
2668
      mir_comment(mu, "Skip empty waveform");
×
2669
      return;
×
2670
   }
2671

2672
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,213✔
2673
               target, count, values, reject, after);
2674

2675
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
9,213✔
2676
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
9,213✔
2677
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
9,213✔
2678
}
2679

2680
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
2,097✔
2681
                              mir_value_t count, mir_value_t values)
2682
{
2683
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,097✔
2684
               target, count, values);
2685

2686
   MIR_ASSERT(mir_is_signal(mu, target),
2,097✔
2687
              "deposit signal target is not signal");
2688
   MIR_ASSERT(mir_is_offset(mu, count),
2,097✔
2689
              "deposit signal count is not offset type");
2690
   MIR_ASSERT(!mir_is_signal(mu, values),
2,097✔
2691
              "signal cannot be values argument for deposit signal");
2692
}
2,097✔
2693

2694
void mir_build_sched_deposit(mir_unit_t *mu, mir_value_t target,
138✔
2695
                             mir_value_t count, mir_value_t values,
2696
                             mir_value_t after)
2697
{
2698
   mir_build_4(mu, MIR_OP_SCHED_DEPOSIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
138✔
2699
               target, count, values, after);
2700

2701
   MIR_ASSERT(mir_is_signal(mu, target),
138✔
2702
              "sched deposit target is not signal");
2703
   MIR_ASSERT(mir_is_offset(mu, count),
138✔
2704
              "sched deposit count is not offset type");
2705
   MIR_ASSERT(!mir_is_signal(mu, values),
138✔
2706
              "signal cannot be values argument for sched deposit");
2707
}
138✔
2708

2709
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
16,157✔
2710
{
2711
   mir_type_t type = mir_get_type(mu, signal);
16,157✔
2712
   mir_type_t pointer = mir_get_pointer(mu, type);
16,157✔
2713
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
16,157✔
2714

2715
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
16,157✔
2716
                                    stamp, signal);
2717

2718
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
16,157✔
2719
              "argument to resolved must be signal");
2720

2721
   return result;
16,157✔
2722
}
2723

2724
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
271✔
2725
{
2726
   mir_type_t type = mir_get_type(mu, signal);
271✔
2727
   mir_type_t pointer = mir_get_pointer(mu, type);
271✔
2728
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
271✔
2729

2730
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
271✔
2731
                                    stamp, signal);
2732

2733
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
271✔
2734
              "argument to resolved must be signal");
2735

2736
   return result;
271✔
2737
}
2738

2739
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
120✔
2740
                                    mir_value_t count)
2741
{
2742
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
120✔
2743
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
120✔
2744

2745
   mir_value_t result;
120✔
2746
   if (mir_is_null(count))
120✔
2747
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
84✔
2748
   else
2749
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
36✔
2750
                           signal, count);
2751

2752
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
120✔
2753
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
120✔
2754
              "count argument must have offset type");
2755

2756
   return result;
120✔
2757
}
2758

2759
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
70✔
2760
                     mir_value_t values)
2761
{
2762
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
70✔
2763
               target, count, values);
2764

2765
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
70✔
2766
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
70✔
2767
}
70✔
2768

2769
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
42✔
2770
{
2771
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
42✔
2772
               target, count);
2773

2774
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
42✔
2775
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
42✔
2776
}
42✔
2777

2778
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
24✔
2779
                          mir_value_t reject, mir_value_t after)
2780
{
2781
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2782
               target, count, reject, after);
2783

2784
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
24✔
2785
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
24✔
2786
}
24✔
2787

2788

2789
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
42✔
2790
                                 mir_value_t count)
2791
{
2792
   mir_type_t type = mir_time_type(mu);
42✔
2793

2794
   mir_value_t result;
42✔
2795
   if (mir_is_null(count))
42✔
2796
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
33✔
2797
   else
2798
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
9✔
2799
                           signal, count);
2800

2801
   MIR_ASSERT(mir_is_signal(mu, signal),
42✔
2802
              "signal argument to last event must have signal type");
2803
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
42✔
2804
              "length argument to last event must have offset type");
2805

2806
   return result;
42✔
2807
}
2808

2809
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
45✔
2810
                                  mir_value_t count)
2811
{
2812
   mir_type_t type = mir_time_type(mu);
45✔
2813

2814
   mir_value_t result;
45✔
2815
   if (mir_is_null(count))
45✔
2816
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
39✔
2817
                           signal);
2818
   else
2819
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
6✔
2820
                           signal, count);
2821

2822
   MIR_ASSERT(mir_is_signal(mu, signal),
45✔
2823
              "signal argument to last event must have signal type");
2824
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
45✔
2825
              "length argument to last event must have offset type");
2826

2827
   return result;
45✔
2828
}
2829

2830

2831
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
778✔
2832
                                         mir_value_t signal, mir_value_t count)
2833
{
2834
   mir_type_t t_bool = mir_bool_type(mu);
778✔
2835
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
778✔
2836
                                    signal, count);
2837

2838
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
778✔
2839
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
778✔
2840

2841
   return result;
778✔
2842
}
2843

2844
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
525✔
2845
                                 mir_value_t count)
2846
{
2847
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
525✔
2848
}
2849

2850
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
217✔
2851
                                  mir_value_t count)
2852
{
2853
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
217✔
2854
}
2855

2856
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
36✔
2857
                                   mir_value_t count)
2858
{
2859
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
36✔
2860
}
2861

2862
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
3,971✔
2863
                              mir_value_t resolution)
2864
{
2865
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,971✔
2866
               signal, resolution);
2867

2868
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
3,971✔
2869
   MIR_ASSERT(mir_points_to(mu, resolution, MIR_TYPE_RESOLUTION),
3,971✔
2870
              "resolution wrapper argument has wrong type");
2871
}
3,971✔
2872

2873
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
488✔
2874
                               mir_value_t source, mir_value_t count,
2875
                               mir_value_t reject, mir_value_t after)
2876
{
2877
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
488✔
2878
               target, source, count, reject, after);
2879

2880
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
488✔
2881
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
488✔
2882
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
488✔
2883
}
488✔
2884

2885
mir_value_t mir_build_get_counters(mir_unit_t *mu, ident_t block)
700✔
2886
{
2887
   mir_type_t t_int32 = mir_int_type(mu, INT32_MIN, INT32_MAX);
700✔
2888
   mir_type_t t_ptr = mir_pointer_type(mu, t_int32);
700✔
2889

2890
   mir_value_t link = mir_add_linkage(mu, block);
700✔
2891
   return mir_build_1(mu, MIR_OP_GET_COUNTERS, t_ptr, MIR_NULL_STAMP, link);
700✔
2892
}
2893

2894
void mir_build_cover_stmt(mir_unit_t *mu, mir_value_t counters, uint32_t tag)
1,214✔
2895
{
2896
   mir_build_2(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,214✔
2897
               counters, mir_enum(tag));
2898
}
1,214✔
2899

2900
void mir_build_cover_branch(mir_unit_t *mu, mir_value_t counters, uint32_t tag)
515✔
2901
{
2902
   mir_build_2(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
515✔
2903
               counters, mir_enum(tag));
2904
}
515✔
2905

2906
void mir_build_cover_expr(mir_unit_t *mu, mir_value_t counters, uint32_t tag)
861✔
2907
{
2908
   mir_build_2(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
861✔
2909
               counters, mir_enum(tag));
2910
}
861✔
2911

2912
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
322✔
2913
{
2914
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
322✔
2915
               signal, mir_enum(tag));
2916

2917
   MIR_ASSERT(mir_is_signal(mu, signal),
322✔
2918
              "argument to cover toggle must be signal");
2919
}
322✔
2920

2921
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
12✔
2922
                           uint32_t tag)
2923
{
2924
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2925
               signal, low, mir_enum(tag));
2926

2927
   MIR_ASSERT(mir_is_signal(mu, signal),
12✔
2928
              "argument to cover state must be signal");
2929
}
12✔
2930

2931
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
24,233✔
2932
                                   mir_value_t context)
2933
{
2934
   mir_value_t link = mir_add_linkage(mu, name);
24,233✔
2935
   mir_type_t type = mir_context_type(mu, name);
24,233✔
2936

2937
   mir_value_t result;
24,233✔
2938
   if (mir_is_null(context))
24,233✔
2939
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
24,042✔
2940
                           MIR_NULL_STAMP, link);
24,042✔
2941
   else
2942
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
191✔
2943
                           MIR_NULL_STAMP, link, context);
191✔
2944

2945
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
24,233✔
2946
              "invalid package init context argument");
2947
   MIR_ASSERT(name != mu->name, "cyclic package init");
24,233✔
2948

2949
   return result;
24,233✔
2950
}
2951

2952
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
117✔
2953
{
2954
   mir_value_t link = mir_add_linkage(mu, name);
117✔
2955
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
117✔
2956
               link, locus);
2957

2958
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
117✔
2959
              "locus argument to process init must be a debug locus");
2960
}
117✔
2961

2962
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
628✔
2963
                                     mir_value_t context, mir_value_t path_name,
2964
                                     mir_value_t inst_name)
2965
{
2966
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
628✔
2967

2968
   mir_value_t result;
628✔
2969
   if (mir_is_null(path_name) && mir_is_null(inst_name))
628✔
2970
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
139✔
2971
                           link, context);
2972
   else {
2973
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
489✔
2974
                           link, context, path_name, inst_name);
2975

2976
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
489✔
2977
                 "path name argument must be array");
2978
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
489✔
2979
                 "inst name argument must be array");
2980
   }
2981

2982
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
628✔
2983
                "protected init type must be context");
2984
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
628✔
2985
              "invalid protected init context argument");
2986

2987
   return result;
628✔
2988
}
2989

2990
mir_value_t mir_build_instance_init(mir_unit_t *mu, ident_t name,
546✔
2991
                                    const mir_value_t *args, unsigned nargs)
2992
{
2993
   node_data_t *n = mir_add_node(mu, MIR_OP_INSTANCE_INIT,
546✔
2994
                                 mir_context_type(mu, name),
2995
                                 MIR_NULL_STAMP, nargs + 1);
546✔
2996
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
546✔
2997

2998
   for (int i = 0; i < nargs; i++)
1,489✔
2999
      mir_set_arg(mu, n, i + 1, args[i]);
943✔
3000

3001
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
546✔
3002
}
3003

3004
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
1,731✔
3005
{
3006
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
1,731✔
3007

3008
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,731✔
3009
              "locus argument to record scope must be a debug locus");
3010
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
1,731✔
3011
              "record scope type must be record");
3012
}
1,731✔
3013

3014
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
663✔
3015
{
3016
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
663✔
3017

3018
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
663✔
3019
              "locus argument to array scope must be a debug locus");
3020
}
663✔
3021

3022
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
45✔
3023
{
3024
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
45✔
3025

3026
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
3027
              "locus argument to package scope must be a debug locus");
3028
}
45✔
3029

3030
void mir_build_pop_scope(mir_unit_t *mu)
2,439✔
3031
{
3032
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
2,439✔
3033
}
2,439✔
3034

3035
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
4,315✔
3036
                            mir_value_t locus)
3037
{
3038
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,315✔
3039
               signal, locus);
3040

3041
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
4,315✔
3042
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
4,315✔
3043
              "locus argument must have debug locus type");
3044
}
4,315✔
3045

3046
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
5,474✔
3047
                          mir_value_t count)
3048
{
3049
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,474✔
3050
               src, dst, count);
3051

3052
   MIR_ASSERT(mir_is_signal(mu, src),
5,474✔
3053
              "src argument to map signal is not a signal");
3054
   MIR_ASSERT(mir_is_signal(mu, dst),
5,474✔
3055
              "dst argument to map signal is not a signal");
3056
   MIR_ASSERT(mir_is_offset(mu, count),
5,474✔
3057
              "count argument to map signal is not offset type");
3058
}
5,474✔
3059

3060
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
215✔
3061
                         mir_value_t count)
3062
{
3063
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
215✔
3064
               src, dst, count);
3065

3066
   MIR_ASSERT(mir_is_signal(mu, dst),
215✔
3067
              "dst argument to map const is not a signal");
3068
   MIR_ASSERT(mir_is_offset(mu, count),
215✔
3069
              "count argument to map const is not offset type");
3070
}
215✔
3071

3072
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
57✔
3073
                            mir_value_t count)
3074
{
3075
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
3076
               src, dst, count);
3077

3078
   MIR_ASSERT(mir_is_signal(mu, src),
57✔
3079
              "src argument to map implicit is not a signal");
3080
   MIR_ASSERT(mir_is_signal(mu, dst),
57✔
3081
              "dst argument to map implicit is not a signal");
3082
   MIR_ASSERT(mir_is_offset(mu, count),
57✔
3083
              "count argument type to map implicit is not offset");
3084
}
57✔
3085

3086
mir_value_t mir_build_level_trigger(mir_unit_t *mu, mir_value_t signal,
204✔
3087
                                    mir_value_t count)
3088
{
3089
   mir_type_t type = mir_trigger_type(mu);
204✔
3090
   mir_value_t result = mir_build_2(mu, MIR_OP_LEVEL_TRIGGER, type,
204✔
3091
                                    MIR_NULL_STAMP, signal, count);
204✔
3092

3093
   MIR_ASSERT(mir_is_signal(mu, signal),
204✔
3094
              "level trigger argument must be signal");
3095
   MIR_ASSERT(mir_is_offset(mu, count),
204✔
3096
              "level trigger count argument must be offset");
3097

3098
   return result;
204✔
3099
}
3100

3101
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
47✔
3102
                                  mir_value_t right)
3103
{
3104
   mir_type_t type = mir_trigger_type(mu);
47✔
3105
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
47✔
3106
                                    MIR_NULL_STAMP, left, right);
47✔
3107

3108
   MIR_ASSERT(mir_is_signal(mu, left),
47✔
3109
              "cmp trigger left argument must be signal");
3110
   MIR_ASSERT(mir_is_integral(mu, right),
47✔
3111
              "cmp trigger right argument must be integer");
3112

3113
   return result;
47✔
3114
}
3115

3116
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
262✔
3117
                                       const mir_value_t *args, unsigned nargs)
3118
{
3119
   mir_type_t type = mir_trigger_type(mu);
262✔
3120
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
524✔
3121
                                 MIR_NULL_STAMP, nargs + 1);
262✔
3122

3123
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
262✔
3124

3125
   for (int i = 0; i < nargs; i++)
660✔
3126
      mir_set_arg(mu, n, i + 1, args[i]);
398✔
3127

3128
   MIR_ASSERT(nargs >= 1, "function trigger requires at least one argument");
262✔
3129

3130
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
262✔
3131
}
3132

3133
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
124✔
3134
                                 mir_value_t right)
3135
{
3136
   mir_type_t type = mir_trigger_type(mu);
124✔
3137
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
124✔
3138
                                    MIR_NULL_STAMP, left, right);
124✔
3139

3140
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
124✔
3141
              "or trigger left argument must be trigger");
3142
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
124✔
3143
              "or trigger right argument must be trigger");
3144

3145
   return result;
124✔
3146
}
3147

3148
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
371✔
3149
{
3150
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
371✔
3151

3152
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
371✔
3153
              "add trigger argument must be trigger");
3154
}
371✔
3155

3156
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
7,412✔
3157
{
3158
   mir_value_t link = mir_add_linkage(mu, name);
7,412✔
3159
   mir_type_t type = mir_context_type(mu, name);
7,412✔
3160

3161
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
7,412✔
3162
                                    MIR_NULL_STAMP, link);
7,412✔
3163

3164
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
7,412✔
3165

3166
   return result;
7,412✔
3167
}
3168

3169
mir_value_t mir_build_link_var(mir_unit_t *mu, mir_value_t context,
6,000✔
3170
                               ident_t name, mir_type_t type)
3171
{
3172
   mir_type_t pointer = mir_get_var_pointer(mu, type);
6,000✔
3173
   mir_type_t context_type = mir_get_type(mu, context);
6,000✔
3174

3175
   ident_t unit_name = mir_type_data(mu, context_type)->u.context;
6,000✔
3176

3177
   mir_value_t link = mir_add_linkage(mu, unit_name);
6,000✔
3178
   mir_value_t var = mir_add_extvar(mu, name);
6,000✔
3179
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
6,000✔
3180
                                    MIR_NULL_STAMP, link, context, var);
6,000✔
3181

3182
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
6,000✔
3183
              "first argument to link var must be context");
3184

3185
   return result;
6,000✔
3186
}
3187

3188
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
1,035✔
3189
                            mir_value_t length, mir_value_t locus)
3190
{
3191
   if (mir_is_null(locus))
1,035✔
3192
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
165✔
3193
                  spec, length);
3194
   else
3195
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
870✔
3196
                  spec, length, locus);
3197

3198
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
1,035✔
3199
              "spec argument to bind foreign must be a pointer");
3200
   MIR_ASSERT(mir_is_offset(mu, length),
1,035✔
3201
              "legnth argument to bind foreign must be offset");
3202
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
1,035✔
3203
              "locus argument to bind foreign value must be a debug locus");
3204
}
1,035✔
3205

3206
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
180✔
3207
                                    ident_t scope, mir_type_t type,
3208
                                    mir_stamp_t stamp, const mir_value_t *args,
3209
                                    int nargs)
3210
{
3211
   mir_type_t pointer = mir_get_var_pointer(mu, type);
180✔
3212
   mir_value_t link = mir_add_linkage(mu, scope);
180✔
3213

3214
   node_data_t *n = mir_add_node(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
360✔
3215
                                 nargs + 2);
180✔
3216
   mir_set_arg(mu, n, 0, locus);
180✔
3217
   mir_set_arg(mu, n, 1, link);
180✔
3218

3219
   for (int i = 0; i < nargs; i++)
210✔
3220
      mir_set_arg(mu, n, i + 2, args[i]);
30✔
3221

3222
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
180✔
3223
              "bind external argument must be locus");
3224

3225
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
180✔
3226
}
3227

3228
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
11,951✔
3229
{
3230
   mir_type_t type = MIR_NULL_TYPE;
11,951✔
3231
   if (hops == 0)
11,951✔
3232
      type = mir_self_type(mu);
3,659✔
3233
   else {
3234
      mir_shape_t *s = mu->parent;
8,292✔
3235
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
8,516✔
3236

3237
      if (s != NULL) type = s->type;
8,292✔
3238
   }
3239

3240
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
11,951✔
3241
                                    MIR_NULL_STAMP, mir_enum(hops));
11,951✔
3242

3243
   MIR_ASSERT(hops >= 0, "invalid hop count");
11,951✔
3244
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
11,951✔
3245

3246
   return result;
11,951✔
3247
}
3248

3249
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
50,834✔
3250
{
3251
   mir_type_t type = MIR_NULL_TYPE;
50,834✔
3252
   mir_value_t link = MIR_NULL_VALUE;
50,834✔
3253

3254
   mir_shape_t *s = mu->parent;
50,834✔
3255
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
59,913✔
3256

3257
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
50,834✔
3258
      type = s->slots[nth].pointer;
50,834✔
3259
      link = mir_add_linkage(mu, s->name);
50,834✔
3260
   }
3261

3262
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
50,834✔
3263
                                    mir_enum(hops), link, mir_enum(nth));
3264

3265
   MIR_ASSERT(hops > 0, "invalid hop count");
50,834✔
3266
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
50,834✔
3267

3268
   return result;
50,834✔
3269
}
3270

3271
void mir_build_sched_event(mir_unit_t *mu, mir_value_t on, mir_value_t count)
4,590✔
3272
{
3273
   if (mir_is_null(count)) {
4,590✔
3274
      mir_build_1(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP, on);
168✔
3275

3276
      MIR_ASSERT(mir_is(mu, on, MIR_TYPE_TRIGGER), "argument must be trigger");
168✔
3277
   }
3278
   else {
3279
      mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,422✔
3280
                  on, count);
3281

3282
      MIR_ASSERT(mir_is_signal(mu, on), "argument must be signal");
4,422✔
3283
      MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
4,422✔
3284
   }
3285
}
4,590✔
3286

3287
void mir_build_clear_event(mir_unit_t *mu, mir_value_t on, mir_value_t count)
581✔
3288
{
3289
   if (mir_is_null(count)) {
581✔
3290
      mir_build_1(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP, on);
33✔
3291

3292
      MIR_ASSERT(mir_is(mu, on, MIR_TYPE_TRIGGER), "argument must be trigger");
33✔
3293
   }
3294
   else {
3295
      mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
548✔
3296
                  on, count);
3297

3298
      MIR_ASSERT(mir_is_signal(mu, on), "argument must be signal");
548✔
3299
      MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
548✔
3300
   }
3301
}
581✔
3302

3303
void mir_build_sched_process(mir_unit_t *mu, mir_value_t delay)
6,028✔
3304
{
3305
   mir_build_1(mu, MIR_OP_SCHED_PROCESS, MIR_NULL_TYPE, MIR_NULL_STAMP, delay);
6,028✔
3306

3307
   MIR_ASSERT(mir_is_time(mu, delay), "delay argument is not a time");
6,028✔
3308
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
6,028✔
3309
              "sched process only allowed in process or procedure");
3310
}
6,028✔
3311

3312
void mir_build_sched_inactive(mir_unit_t *mu)
54✔
3313
{
3314
   mir_build_0(mu, MIR_OP_SCHED_INACTIVE, MIR_NULL_TYPE, MIR_NULL_STAMP);
54✔
3315

3316
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
54✔
3317
              "sched inactive only allowed in process or procedure");
3318
}
54✔
3319

3320
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
51✔
3321
                                    mir_value_t context, mir_value_t locus,
3322
                                    mir_value_t bounds)
3323
{
3324
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
51✔
3325

3326
   mir_value_t result;
51✔
3327
   if (mir_is_null(bounds))
51✔
3328
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
45✔
3329
                           value, context, locus);
3330
   else
3331
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
6✔
3332
                           value, context, locus, bounds);
3333

3334
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
51✔
3335
              "invalid reflect value context argument");
3336
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
51✔
3337
              "locus argument to reflect value must be a debug locus");
3338

3339
   return result;
51✔
3340
}
3341

3342
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
51✔
3343
                                      mir_value_t locus, mir_value_t bounds)
3344
{
3345
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
51✔
3346

3347
   mir_value_t result;
51✔
3348
   if (mir_is_null(bounds))
51✔
3349
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
42✔
3350
                           context, locus);
3351
   else
3352
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
9✔
3353
                           context, locus, bounds);
3354

3355
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
51✔
3356
              "invalid reflect subtype context argument");
3357
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
51✔
3358
              "locus argument to reflect subtype must be a debug locus");
3359

3360
   return result;
51✔
3361
}
3362

3363
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
14,702✔
3364
                      mir_value_t length, mir_value_t severity,
3365
                      mir_value_t locus, mir_value_t hint_left,
3366
                      mir_value_t hint_right)
3367
{
3368
   int64_t value_const;
14,702✔
3369
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
14,702✔
3370
      mir_comment(mu, "Always true assertion");
×
3371
      return;
×
3372
   }
3373

3374
   if (mir_is_null(hint_left))
14,702✔
3375
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,601✔
3376
                  value, severity, message, length, locus);
3377
   else {
3378
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
12,202✔
3379
                                     MIR_NULL_STAMP, 7);
6,101✔
3380
      mir_set_arg(mu, n, 0, value);
6,101✔
3381
      mir_set_arg(mu, n, 1, severity);
6,101✔
3382
      mir_set_arg(mu, n, 2, message);
6,101✔
3383
      mir_set_arg(mu, n, 3, length);
6,101✔
3384
      mir_set_arg(mu, n, 4, locus);
6,101✔
3385
      mir_set_arg(mu, n, 5, hint_left);
6,101✔
3386
      mir_set_arg(mu, n, 6, hint_right);
6,101✔
3387

3388
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
6,101✔
3389
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
6,101✔
3390
   }
3391

3392
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,702✔
3393
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
14,702✔
3394
              "message parameter to assert is not a pointer");
3395
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,702✔
3396
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
14,702✔
3397
              "locus argument to report must be a debug locus");
3398
}
3399

3400
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,193✔
3401
                      mir_value_t severity, mir_value_t locus)
3402
{
3403
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,193✔
3404
               severity, message, length, locus);
3405

3406
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,193✔
3407
              "message parameter to report is not a pointer");
3408
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,193✔
3409
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,193✔
3410
              "locus argument to report must be a debug locus");
3411
}
2,193✔
3412

3413
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
4,359✔
3414
{
3415
   mir_type_t type = mir_string_type(mu);
4,359✔
3416
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
4,359✔
3417
                                    MIR_NULL_STAMP, kind);
4,359✔
3418

3419
   MIR_ASSERT(mir_is_offset(mu, kind),
4,359✔
3420
              "kind argument to instance name must be offset");
3421

3422
   return result;
4,359✔
3423
}
3424

3425
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
852✔
3426
                           mir_value_t strong)
3427
{
3428
   if (mir_is_null(strong))
852✔
3429
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
816✔
3430
   else
3431
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
36✔
3432
                  state, strong);
3433

3434
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
852✔
3435
   MIR_ASSERT(mir_is_null(strong)
852✔
3436
              || mir_check_type(mu, strong, mir_bool_type(mu)),
3437
                "strong argument not is not boolean");
3438
}
852✔
3439

3440
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_type_t rtype,
7,171✔
3441
                              const mir_value_t *args, unsigned nargs)
3442
{
3443
   mir_type_t ctype = mir_closure_type(mu, rtype);
7,171✔
3444

3445
   node_data_t *n = mir_add_node(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP, nargs + 1);
7,171✔
3446
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
7,171✔
3447

3448
   for (int i = 0; i < nargs; i++)
14,765✔
3449
      mir_set_arg(mu, n, i + 1, args[i]);
7,594✔
3450

3451
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
7,171✔
3452
}
3453

3454
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
6,327✔
3455
                                         mir_value_t closure, mir_value_t nlits)
3456
{
3457
   mir_type_t rtype = mir_resolution_type(mu, type);
6,327✔
3458
   mir_value_t result = mir_build_2(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
6,327✔
3459
                                    MIR_NULL_STAMP, closure, nlits);
6,327✔
3460

3461
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
6,327✔
3462
              "first argument to resolution wrapper must be closure");
3463

3464
   return result;
6,327✔
3465
}
3466

3467
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
81,181✔
3468
{
3469
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
81,181✔
3470
                                  MIR_NULL_STAMP, 0);
81,181✔
3471
   n->locus = obj;
81,181✔
3472

3473
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
81,181✔
3474
}
3475

3476
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
64,805✔
3477
{
3478
   mir_type_t from = mir_get_type(mu, value);
64,805✔
3479
   if (mir_equals(from, type))
64,805✔
3480
      return value;
64,805✔
3481

3482
   const mir_class_t class = mir_get_class(mu, type);
59,862✔
3483
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
59,862✔
3484

3485
   int64_t cval;
59,862✔
3486
   if (integral && mir_get_const(mu, value, &cval))
59,862✔
3487
      return mir_const(mu, type, cval);
401✔
3488

3489
   if (class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4) {
59,461✔
3490
      if (value.tag == MIR_TAG_NODE) {
4,009✔
3491
         node_data_t *n = mir_node_data(mu, value);
4,009✔
3492
         const bool can_fold =
8,018✔
3493
            n->op == MIR_OP_CONST_VEC
4,009✔
3494
            && mir_get_size(mu, type) <= 64
2,485✔
3495
            && !mir_get_signed(mu, type)
2,323✔
3496
            && !mir_get_signed(mu, n->type);
6,251✔
3497

3498
         if (can_fold) {
4,009✔
3499
            const uint64_t bbits = (class == MIR_TYPE_VEC2 ? 0 : n->bits[1]);
31✔
3500
            return mir_const_vec(mu, type, n->bits[0], bbits);
31✔
3501
         }
3502
      }
3503
   }
3504
   else if (integral && mir_is_vector(mu, value)) {
55,452✔
3505
      node_data_t *n = mir_node_data(mu, value);
1,684✔
3506
      if (n->op == MIR_OP_CONST_VEC) {
1,684✔
3507
         MIR_ASSERT(n->bits[1] == 0, "X value in integral cast");
760✔
3508
         return mir_const(mu, type, n->bits[0]);
760✔
3509
      }
3510
   }
3511

3512
   mir_stamp_t stamp = mir_stamp_cast(mu, type, mir_get_stamp(mu, value));
58,670✔
3513

3514
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type, stamp, value);
58,670✔
3515

3516
#ifdef DEBUG
3517
   static const mir_class_t allowed[][2] = {
58,670✔
3518
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
3519
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
3520
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
3521
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
3522
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
3523
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
3524
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
3525
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC2    },
3526
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC4    },
3527
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC2    },
3528
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC4    },
3529
      { MIR_TYPE_VEC2,   MIR_TYPE_INT     },
3530
      { MIR_TYPE_VEC2,   MIR_TYPE_OFFSET  },
3531
      { MIR_TYPE_INT,    MIR_TYPE_VEC2    },
3532
      { MIR_TYPE_INT,    MIR_TYPE_VEC4    },
3533
   };
3534

3535
   if (value.tag == MIR_TAG_CONST)
58,670✔
3536
      return result;
62✔
3537

3538
   const mir_class_t from_k = mir_get_class(mu, from);
58,608✔
3539

3540
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
146,922✔
3541
      if (from_k == allowed[i][0] && class == allowed[i][1])
146,922✔
3542
         return result;
58,608✔
3543
   }
3544

3545
   MIR_ASSERT(false, "invalid type conversion in cast");
×
3546
#else
3547
   return result;
3548
#endif
3549
}
3550

3551
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
2✔
3552
{
3553
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
2✔
3554

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