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

nickg / nvc / 13736123901

08 Mar 2025 09:12AM UTC coverage: 92.291% (+0.02%) from 92.276%
13736123901

push

github

nickg
Fix unit test failures on release build. Fixes #1170

1 of 1 new or added line in 1 file covered. (100.0%)

25 existing lines in 2 files now uncovered.

68034 of 73717 relevant lines covered (92.29%)

488033.61 hits per line

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

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

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

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

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

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

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

44
   block_data_t bd = {
134,980✔
45
      .gap_pos = -1,
46
      .last_loc = LOC_INVALID,
47
   };
48
   APUSH(mu->blocks, bd);
134,980✔
49

50
   return b;
134,980✔
51
}
52

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

58
   mu->cursor.block = block;
1,272,758✔
59
   mu->cursor.pos   = pos;
1,272,758✔
60

61
   if (mir_is_null(block))
1,272,758✔
62
      mu->cursor.loc = LOC_INVALID;
4✔
63
   else
64
      mu->cursor.loc = mir_block_data(mu, block)->last_loc;
1,272,754✔
65
}
1,272,758✔
66

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

72
   return mu->cursor.block;
42,779✔
73
}
74

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

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

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

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

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

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

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

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

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

123
unsigned mir_count_nodes(mir_unit_t *mu, mir_block_t block)
355,296✔
124
{
125
   if (mir_is_null(block))
355,296✔
126
      return mu->num_nodes;
42,743✔
127
   else
128
      return mir_block_data(mu, block)->num_nodes;
312,553✔
129
}
130

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

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

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

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

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

160
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
2,304,426✔
161
{
162
   switch (node.tag) {
2,304,426✔
163
   case MIR_TAG_NODE:
2,281,428✔
164
      return mir_node_data(mu, node)->op;
2,281,428✔
165
   default:
166
      return _MIR_DELETED_OP;
167
   }
168
}
169

170
const loc_t *mir_get_loc(mir_unit_t *mu, mir_value_t node)
1,132,699✔
171
{
172
   return &(mir_node_data(mu, node)->loc);
1,132,699✔
173
}
174

175
unsigned mir_count_args(mir_unit_t *mu, mir_value_t node)
211,160✔
176
{
177
   return mir_node_data(mu, node)->nargs;
211,160✔
178
}
179

180
const mir_value_t *mir_get_args(mir_unit_t *mu, const node_data_t *nd)
3,477,412✔
181
{
182
   if (nd->nargs <= MIR_INLINE_ARGS)
3,477,412✔
183
      return nd->args;
1,949,609✔
184
   else {
185
      assert(nd->spilloff < mu->num_argspill);
1,527,803✔
186
      return mu->argspill + nd->spilloff;
1,527,803✔
187
   }
188
}
189

190
mir_value_t mir_get_arg(mir_unit_t *mu, mir_value_t node, unsigned nth)
3,477,307✔
191
{
192
   const node_data_t *nd = mir_node_data(mu, node);
3,477,307✔
193
   if (nth >= nd->nargs)
3,477,307✔
194
      return MIR_NULL_VALUE;
×
195
   else
196
      return mir_get_args(mu, nd)[nth];
3,477,307✔
197
}
198

199
mir_value_t mir_add_param(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
29,342✔
200
                          ident_t name)
201
{
202
   mir_value_t p = { .tag = MIR_TAG_PARAM, .id = mu->params.count };
29,342✔
203

204
   param_data_t pd = {
3✔
205
      .name  = name,
206
      .type  = type,
207
      .stamp = mir_is_null(stamp) ? mir_top_stamp(mu, type) : stamp
29,342✔
208
   };
209
   APUSH(mu->params, pd);
29,342✔
210

211
   return p;
29,342✔
212
}
213

214
mir_value_t mir_add_var(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
48,706✔
215
                        ident_t name, mir_var_flags_t flags)
216
{
217
   mir_value_t v = { .tag = MIR_TAG_VAR, .id = mu->vars.count };
48,706✔
218

219
   var_data_t vd = {
×
220
      .name    = name,
221
      .type    = type,
222
      .pointer = mir_get_var_pointer(mu, type),
48,706✔
223
      .stamp   = mir_is_null(stamp) ? mir_top_stamp(mu, type) : stamp,
48,706✔
224
      .flags   = flags,
225
   };
226
   APUSH(mu->vars, vd);
48,706✔
227

228
   return v;
48,706✔
229
}
230

231
bool mir_is_terminator(mir_op_t op)
15✔
232
{
233
   switch (op) {
15✔
234
   case MIR_OP_RETURN:
235
   case MIR_OP_JUMP:
236
   case MIR_OP_COND:
237
   case MIR_OP_WAIT:
238
      return true;
239
   default:
×
240
      return false;
×
241
   }
242
}
243

244
static inline node_id_t mir_node_id(mir_unit_t *mu, node_data_t *n)
1,058,214✔
245
{
246
   assert(n >= mu->nodes && n < mu->nodes + mu->num_nodes);
1,058,214✔
247
   return n - mu->nodes;
1,058,214✔
248
}
249

250
static node_data_t *mir_alloc_node(mir_unit_t *mu)
1,095,091✔
251
{
252
   assert(!mir_is_null(mu->cursor.block));
1,095,091✔
253

254
   node_data_t *n;
1,095,091✔
255
   block_data_t *bd = mir_block_data(mu, mu->cursor.block);
1,095,091✔
256
   if (mu->cursor.pos >= bd->num_nodes) {
1,095,091✔
257
      // Append new node
258
      if (bd->num_nodes == bd->max_nodes) {
1,095,084✔
259
         bd->max_nodes = MAX(4, bd->num_nodes * 2);
258,761✔
260
         bd->nodes = xrealloc_array(bd->nodes, bd->max_nodes,
258,761✔
261
                                    sizeof(node_id_t));
262
      }
263

264
      if (mu->num_nodes == mu->max_nodes) {
1,095,084✔
265
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
92,950✔
266
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
92,950✔
267
                                    sizeof(node_data_t));
268
      }
269

270
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
1,095,084✔
271
      n = &(mu->nodes[mu->num_nodes++]);
1,095,084✔
272
   }
273
   else {
274
      n = &(mu->nodes[bd->nodes[mu->cursor.pos]]);
7✔
275
      assert(n->op == _MIR_DELETED_OP);
7✔
276
   }
277

278
   return n;
1,095,091✔
279
}
280

281
static size_t mir_spill_args(mir_unit_t *mu, unsigned num)
75,713✔
282
{
283
   if (mu->num_argspill + num > mu->max_argspill) {
75,713✔
284
      mu->max_argspill = MAX(16, MAX(mu->num_argspill + num,
34,078✔
285
                                     mu->max_argspill * 2));
286
      mu->argspill = xrealloc_array(mu->argspill, mu->max_argspill,
34,078✔
287
                                    sizeof(mir_value_t));
288
   }
289

290
   const size_t off = mu->num_argspill;
75,713✔
291
   mu->num_argspill += num;
75,713✔
292
   return off;
75,713✔
293
}
294

295
static node_data_t *mir_add_node(mir_unit_t *mu, mir_op_t op, mir_type_t type,
1,095,091✔
296
                                 mir_stamp_t stamp, unsigned nargs)
297
{
298
   node_data_t *n = mir_alloc_node(mu);
1,095,091✔
299
   n->loc   = mu->cursor.loc;
1,095,091✔
300
   n->op    = op;
1,095,091✔
301
   n->type  = type;
1,095,091✔
302
   n->stamp = stamp;
1,095,091✔
303
   n->nargs = nargs;
1,095,091✔
304

305
   if (nargs > MIR_INLINE_ARGS)
1,095,091✔
306
      n->spilloff = mir_spill_args(mu, nargs);
75,713✔
307

308
   return n;
1,095,091✔
309
}
310

311
static mir_value_t mir_build_0(mir_unit_t *mu, mir_op_t op, mir_type_t type,
5,545✔
312
                               mir_stamp_t stamp)
313
{
314
   node_data_t *n = mir_add_node(mu, op, type, stamp, 0);
5,545✔
315
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
5,545✔
316
}
317

318
static mir_value_t mir_build_1(mir_unit_t *mu, mir_op_t op, mir_type_t type,
359,118✔
319
                               mir_stamp_t stamp, mir_value_t arg)
320
{
321
   node_data_t *n = mir_add_node(mu, op, type, stamp, 1);
359,118✔
322
   n->args[0] = arg;
359,118✔
323

324
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
359,118✔
325
}
326

327
static mir_value_t mir_build_2(mir_unit_t *mu, mir_op_t op, mir_type_t type,
286,807✔
328
                               mir_stamp_t stamp, mir_value_t arg1,
329
                               mir_value_t arg2)
330
{
331
   STATIC_ASSERT(MIR_INLINE_ARGS >= 2);
286,807✔
332

333
   node_data_t *n = mir_add_node(mu, op, type, stamp, 2);
286,807✔
334
   n->args[0] = arg1;
286,807✔
335
   n->args[1] = arg2;
286,807✔
336

337
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
286,807✔
338
}
339

340
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
176,395✔
341
                               mir_stamp_t stamp, mir_value_t arg1,
342
                               mir_value_t arg2, mir_value_t arg3)
343
{
344
   STATIC_ASSERT(MIR_INLINE_ARGS >= 3);
176,395✔
345

346
   node_data_t *n = mir_add_node(mu, op, type, stamp, 3);
176,395✔
347
   n->args[0] = arg1;
176,395✔
348
   n->args[1] = arg2;
176,395✔
349
   n->args[2] = arg3;
176,395✔
350

351
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
176,395✔
352
}
353

354
static mir_value_t mir_build_4(mir_unit_t *mu, mir_op_t op, mir_type_t type,
2,991✔
355
                               mir_stamp_t stamp, mir_value_t arg1,
356
                               mir_value_t arg2, mir_value_t arg3,
357
                               mir_value_t arg4)
358
{
359
   STATIC_ASSERT(MIR_INLINE_ARGS >= 4);
2,991✔
360

361
   node_data_t *n = mir_add_node(mu, op, type, stamp, 4);
2,991✔
362
   n->args[0] = arg1;
2,991✔
363
   n->args[1] = arg2;
2,991✔
364
   n->args[2] = arg3;
2,991✔
365
   n->args[3] = arg4;
2,991✔
366

367
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,991✔
368
}
369

370
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
30,626✔
371
                               mir_stamp_t stamp, mir_value_t arg1,
372
                               mir_value_t arg2, mir_value_t arg3,
373
                               mir_value_t arg4, mir_value_t arg5)
374
{
375
   node_data_t *n = mir_add_node(mu, op, type, stamp, 5);
30,626✔
376
   n->nargs = 5;
30,626✔
377

378
   STATIC_ASSERT(MIR_INLINE_ARGS < 5);
30,626✔
379

380
   mu->argspill[n->spilloff + 0] = arg1;
30,626✔
381
   mu->argspill[n->spilloff + 1] = arg2;
30,626✔
382
   mu->argspill[n->spilloff + 2] = arg3;
30,626✔
383
   mu->argspill[n->spilloff + 3] = arg4;
30,626✔
384
   mu->argspill[n->spilloff + 4] = arg5;
30,626✔
385

386
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,626✔
387
}
388

389
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
19,782✔
390
                               mir_stamp_t stamp, mir_value_t arg1,
391
                               mir_value_t arg2, mir_value_t arg3,
392
                               mir_value_t arg4, mir_value_t arg5,
393
                               mir_value_t arg6)
394
{
395
   node_data_t *n = mir_add_node(mu, op, type, stamp, 6);
19,782✔
396

397
   STATIC_ASSERT(MIR_INLINE_ARGS < 6);
19,782✔
398

399
   mu->argspill[n->spilloff + 0] = arg1;
19,782✔
400
   mu->argspill[n->spilloff + 1] = arg2;
19,782✔
401
   mu->argspill[n->spilloff + 2] = arg3;
19,782✔
402
   mu->argspill[n->spilloff + 3] = arg4;
19,782✔
403
   mu->argspill[n->spilloff + 4] = arg5;
19,782✔
404
   mu->argspill[n->spilloff + 5] = arg6;
19,782✔
405

406
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
19,782✔
407
}
408

409
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
119,643✔
410
{
411
   for (int i = 0; i < mu->linkage.count; i++) {
323,751✔
412
      if (mu->linkage.items[i] == ident)
257,781✔
413
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
53,673✔
414
   }
415

416
   mir_value_t link = { .tag = MIR_TAG_LINKAGE, .id = mu->linkage.count };
65,970✔
417

418
   APUSH(mu->linkage, ident);
65,970✔
419

420
   return link;
65,970✔
421
}
422

423
void mir_set_arg(mir_unit_t *mu, node_data_t *n, unsigned nth,
1,478,232✔
424
                 mir_value_t value)
425
{
426
   assert(nth < n->nargs);
1,478,232✔
427

428
   if (n->nargs <= MIR_INLINE_ARGS)
1,478,232✔
429
      n->args[nth] = value;
254,897✔
430
   else {
431
      assert(n->spilloff < mu->num_argspill);
1,223,335✔
432
      mu->argspill[n->spilloff + nth] = value;
1,223,335✔
433
   }
434
}
1,478,232✔
435

436
node_data_t *mir_node_data(mir_unit_t *mu, mir_value_t value)
9,613,964✔
437
{
438
   assert(value.tag == MIR_TAG_NODE);
9,613,964✔
439
   assert(value.id < mu->num_nodes);
9,613,964✔
440

441
   return &(mu->nodes[value.id]);
9,613,964✔
442
}
443

444
const param_data_t *mir_param_data(mir_unit_t *mu, mir_value_t value)
149,175✔
445
{
446
   assert(value.tag == MIR_TAG_PARAM);
149,175✔
447
   return AREF(mu->params, value.id);
149,175✔
448
}
449

450
const var_data_t *mir_var_data(mir_unit_t *mu, mir_value_t value)
253,788✔
451
{
452
   assert(value.tag == MIR_TAG_VAR);
253,788✔
453
   return AREF(mu->vars, value.id);
253,788✔
454
}
455

456
#ifdef DEBUG
457
void mir_comment(mir_unit_t *mu, const char *fmt, ...)
8✔
458
{
459
   va_list ap;
8✔
460
   va_start(ap, fmt);
8✔
461

462
   if (mu->comments == NULL)
8✔
463
      mu->comments = tb_new();
5✔
464

465
   mir_value_t value = { .tag = MIR_TAG_COMMENT, .id = tb_len(mu->comments) };
8✔
466

467
   tb_vprintf(mu->comments, fmt, ap);
8✔
468
   tb_append(mu->comments, '\0');
8✔
469

470
   va_end(ap);
8✔
471

472
   mir_build_1(mu, MIR_OP_COMMENT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
8✔
473
}
8✔
474
#endif
475

476
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
3,187,319✔
477
{
478
   switch (value.tag) {
3,187,319✔
479
   case MIR_TAG_CONST:
2,744,695✔
480
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
2,744,695✔
481
      return true;
2,744,695✔
482
   case MIR_TAG_ENUM:
196,544✔
483
      *result = value.id;
196,544✔
484
      return true;
196,544✔
485
   case MIR_TAG_NODE:
241,027✔
486
      {
487
         const node_data_t *n = mir_node_data(mu, value);
241,027✔
488
         if (n->op == MIR_OP_CONST) {
241,027✔
489
            *result = n->iconst;
7,141✔
490
            return true;
7,141✔
491
         }
492
         else
493
            return false;
494
      }
495
   default:
496
      return false;
497
   }
498
}
499

500
bool mir_get_const_real(mir_unit_t *mu, mir_value_t value, double *result)
95,072✔
501
{
502
   switch (value.tag) {
95,072✔
503
   case MIR_TAG_NODE:
71,507✔
504
      {
505
         const node_data_t *n = mir_node_data(mu, value);
71,507✔
506
         if (n->op == MIR_OP_CONST_REAL) {
71,507✔
507
            *result = n->dconst;
21,628✔
508
            return true;
21,628✔
509
         }
510
         else
511
            return false;
512
      }
513
   default:
514
      return false;
515
   }
516
}
517

518
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
2,180,776✔
519
{
520
   switch (value.tag) {
2,180,776✔
521
   case MIR_TAG_NODE:
1,800,540✔
522
      return mir_node_data(mu, value)->type;
1,800,540✔
523
   case MIR_TAG_PARAM:
138,622✔
524
      return mir_param_data(mu, value)->type;
138,622✔
525
   case MIR_TAG_VAR:
138,492✔
526
      return mir_var_data(mu, value)->pointer;
138,492✔
527
   default:
103,122✔
528
      return MIR_NULL_TYPE;
103,122✔
529
   }
530
}
531

532
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
409,244✔
533
{
534
   switch (value.tag) {
409,244✔
535
   case MIR_TAG_NODE:
315,245✔
536
      return mir_node_data(mu, value)->stamp;
315,245✔
537
   case MIR_TAG_PARAM:
10,540✔
538
      return mir_param_data(mu, value)->stamp;
10,540✔
539
   case MIR_TAG_CONST:
44,856✔
540
      {
541
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
44,856✔
542
         return mir_int_stamp(mu, ival, ival);
44,856✔
543
      }
544
   default:
38,603✔
545
      return MIR_NULL_STAMP;
38,603✔
546
   }
547
}
548

549
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
154,288✔
550
{
551
   switch (value.tag) {
154,288✔
552
   case MIR_TAG_PARAM:
13✔
553
      return mir_param_data(mu, value)->name;
13✔
554
   case MIR_TAG_VAR:
35,093✔
555
      return mir_var_data(mu, value)->name;
35,093✔
556
   case MIR_TAG_LINKAGE:
119,182✔
557
      return AGET(mu->linkage, value.id);
119,182✔
558
   case MIR_TAG_NULL:
×
559
      return mu->name;
×
560
   default:
561
      return NULL;
562
   }
563
}
564

565
void mir_set_result(mir_unit_t *mu, mir_type_t type)
20,553✔
566
{
567
   assert(mu->kind == MIR_UNIT_FUNCTION || mu->kind == MIR_UNIT_THUNK);
20,553✔
568
   mu->result = type;
20,553✔
569
}
20,553✔
570

571
mir_type_t mir_get_result(mir_unit_t *mu)
21,563✔
572
{
573
   return mu->result;
21,563✔
574
}
575

576
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
65,869✔
577
{
578
   switch (value.tag) {
65,869✔
579
   case MIR_TAG_NODE:
65,869✔
580
      {
581
         node_data_t *n = mir_node_data(mu, value);
65,869✔
582
         assert(n->op == MIR_OP_LOCUS);
65,869✔
583
         return n->locus;
65,869✔
584
      }
585
      break;
×
586
   default:
×
587
      should_not_reach_here();
588
   }
589
}
590

591
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value)
31,499✔
592
{
593
   switch (value.tag) {
31,499✔
594
   case MIR_TAG_VAR:
31,499✔
595
      return mir_var_data(mu, value)->flags;
31,499✔
596
   default:
597
      return 0;
598
   }
599
}
600

601
mir_type_t mir_get_var_type(mir_unit_t *mu, mir_value_t value)
48,704✔
602
{
603
   switch (value.tag) {
48,704✔
604
   case MIR_TAG_VAR:
48,704✔
605
      return mir_var_data(mu, value)->type;
48,704✔
606
   default:
×
607
      return MIR_NULL_TYPE;
×
608
   }
609
}
610

611
bool mir_is_integral(mir_unit_t *mu, mir_value_t value)
79,963✔
612
{
613
   if (value.tag == MIR_TAG_CONST)
79,963✔
614
      return true;
615

616
   mir_type_t type = mir_get_type(mu, value);
34,838✔
617
   if (mir_is_null(type))
34,838✔
618
      return false;
619

620
   switch (mir_type_data(mu, type)->class) {
34,838✔
621
   case MIR_TYPE_INT:
622
   case MIR_TYPE_OFFSET:
623
      return true;
624
   default:
5,941✔
625
      return false;
5,941✔
626
   }
627
}
628

629
bool mir_is_scalar(mir_unit_t *mu, mir_value_t value)
25,459✔
630
{
631
   if (value.tag == MIR_TAG_CONST)
25,459✔
632
      return true;
633

634
   mir_type_t type = mir_get_type(mu, value);
15,684✔
635
   if (mir_is_null(type))
15,684✔
636
      return false;
637

638
   switch (mir_type_data(mu, type)->class) {
15,684✔
639
   case MIR_TYPE_INT:
640
   case MIR_TYPE_OFFSET:
641
   case MIR_TYPE_REAL:
642
   case MIR_TYPE_ACCESS:
643
      return true;
644
   default:
68✔
645
      return false;
68✔
646
   }
647
}
648

649
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
129,040✔
650
{
651
   if (value.tag == MIR_TAG_CONST)
129,040✔
652
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
32,218✔
653
   else
654
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
96,822✔
655
}
656

657
bool mir_is_time(mir_unit_t *mu, mir_value_t value)
5,303✔
658
{
659
   if (value.tag == MIR_TAG_CONST)
5,303✔
660
      return true;
661

662
   return mir_equals(mir_get_type(mu, value), mir_time_type(mu));
261✔
663
}
664

665
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class)
536,881✔
666
{
667
   mir_type_t type = mir_get_type(mu, value);
536,881✔
668
   if (mir_is_null(type))
536,881✔
669
      return false;
670

671
   return mir_type_data(mu, type)->class == class;
512,973✔
672
}
673

674
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class)
197✔
675
{
676
   mir_type_t type = mir_get_type(mu, value);
197✔
677
   if (mir_is_null(type))
197✔
678
      return false;
679

680
   const type_data_t *td = mir_type_data(mu, type);
197✔
681
   if (td->class != MIR_TYPE_POINTER)
197✔
682
      return false;
683

684
   return mir_type_data(mu, td->u.pointer)->class == class;
197✔
685
}
686

687
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
100,407✔
688
{
689
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
100,407✔
690
}
691

692
bool mir_is_offset(mir_unit_t *mu, mir_value_t value)
146,414✔
693
{
694
   if (value.tag == MIR_TAG_CONST)
146,414✔
695
      return true;
696

697
   return mir_is(mu, value, MIR_TYPE_OFFSET);
37,331✔
698
}
699

700
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
1,168,955✔
701
{
702
   switch (value.tag) {
1,168,955✔
703
   case MIR_TAG_CONST:
704
      return true;
705
   case MIR_TAG_NODE:
17,104✔
706
      {
707
         node_data_t *n = mir_node_data(mu, value);
17,104✔
708
         switch (n->op) {
17,104✔
709
         case MIR_OP_CONST:
710
         case MIR_OP_CONST_REAL:
711
         case MIR_OP_CONST_ARRAY:
712
         case MIR_OP_CONST_REP:
713
         case MIR_OP_CONST_RECORD:
714
         case MIR_OP_NULL:
715
            return true;
716
         default:
×
717
            return false;
×
718
         }
719
      }
720
   default:
×
721
      return false;
×
722
   }
723
}
724

725
#ifdef DEBUG
726
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
1,210,372✔
727
{
728
   if (value.tag == MIR_TAG_CONST) {
1,210,372✔
729
      const mir_class_t class = mir_type_data(mu, type)->class;
1,151,276✔
730
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
1,151,276✔
731
   }
732
   else
733
      return mir_equals(mir_get_type(mu, value), type);
59,096✔
734
}
735
#endif
736

737
mir_value_t mir_enum(unsigned value)
221,448✔
738
{
739
   assert(value < MIR_ID_MAX);
221,448✔
740
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
221,448✔
741
}
742

743
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
338,070✔
744
{
745
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
338,070✔
746
      const unsigned biased = value + SMALL_CONST_BIAS;
331,293✔
747
      return (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
331,293✔
748
   }
749
   else {
750
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
6,777✔
751
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
6,777✔
752
      n->iconst = value;
6,777✔
753

754
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
6,777✔
755
   }
756
}
757

758
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
20,908✔
759
{
760
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
20,908✔
761
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
20,908✔
762
   n->dconst = value;
20,908✔
763

764
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
20,908✔
765
}
766

767
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
21,167✔
768
                            const mir_value_t *values, size_t count)
769
{
770
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
42,334✔
771
                                 MIR_NULL_STAMP, count);
21,167✔
772

773
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
21,167✔
774
                "constant array must have constrained array type");
775
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
21,167✔
776
              "have %zd", mir_get_size(mu, type), count);
777

778
   mir_type_t elem = mir_get_elem(mu, type);
21,167✔
779

780
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
21,167✔
781
   int64_t low = INT64_MAX, high = INT64_MIN;
21,167✔
782
   for (size_t i = 0; i < count; i++) {
1,180,109✔
783
      mir_set_arg(mu, n, i, values[i]);
1,158,942✔
784

785
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
1,158,942✔
786
                 "element %zd has wrong type", i);
787
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
1,158,942✔
788

789
      int64_t cval;
1,158,942✔
790
      if (integral && mir_get_const(mu, values[i], &cval)) {
1,158,942✔
791
         low = MIN(low, cval);
1,143,370✔
792
         high = MAX(high, cval);
1,143,370✔
793
      }
794
   }
795

796
   if (integral && low <= high)
21,167✔
797
      n->stamp = mir_int_stamp(mu, low, high);
20,502✔
798

799
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
21,167✔
800
}
801

802
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
279✔
803
                                mir_value_t value, unsigned rep)
804
{
805
   mir_stamp_t stamp = mir_get_stamp(mu, value);
279✔
806
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
279✔
807
                                    value, mir_enum(rep));
808

809
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
279✔
810
              "constant array must have constrained array class");
811
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
279✔
812

813
   return result;
279✔
814
}
815

816
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,139✔
817
                             const mir_value_t *values, size_t count)
818
{
819
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
4,278✔
820
                                 MIR_NULL_STAMP, count);
2,139✔
821

822
   DEBUG_ONLY(const type_data_t *td = mir_type_data(mu, type));
2,139✔
823

824
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,139✔
825
              "const record must have record type");
826
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,139✔
827
              td->u.record.count, count);
828

829
   for (int i = 0; i < count; i++) {
7,551✔
830
      mir_set_arg(mu, n, i, values[i]);
5,412✔
831

832
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
5,412✔
833
                               td->u.record.fields[i]),
834
                 "wrong type for element %d", i);
835
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
5,412✔
836
   }
837

838
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,139✔
839
}
840

841
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
38,651✔
842
                                   mir_value_t left, mir_value_t right,
843
                                   mir_value_t locus, mir_stamp_t stamp)
844
{
845
   mir_value_t result;
38,651✔
846
   if (mir_is_null(locus))
38,651✔
847
      result = mir_build_2(mu, op, type, stamp, left, right);
33,839✔
848
   else
849
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
4,812✔
850

851
#ifdef DEBUG
852
   mir_type_t ltype = mir_get_type(mu, left);
38,651✔
853
   mir_type_t rtype = mir_get_type(mu, right);
38,651✔
854
#endif
855

856
   MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
38,651✔
857
              || mir_equals(ltype, rtype),
858
              "arguments to %s are not the same type", mir_op_string(op));
859
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
38,651✔
860
              "locus argument to %s is not a locus", mir_op_string(op));
861

862
   return result;
38,651✔
863
}
864

865
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
14,873✔
866
                                    mir_type_t type, mir_value_t left,
867
                                    mir_value_t right, mir_value_t locus)
868
{
869
   int64_t lval, rval, cval;
14,873✔
870
   const bool lconst = mir_get_const(mu, left, &lval);
14,873✔
871
   const bool rconst = mir_get_const(mu, right, &rval);
14,873✔
872

873
   if (lconst && lval == 0)
14,873✔
UNCOV
874
      return right;
×
875
   else if (rconst && rval == 0)
14,873✔
876
      return left;
1✔
877
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
14,872✔
878
      return mir_const(mu, type, cval);
3✔
879

880
   double lreal, rreal;
14,869✔
881
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
14,869✔
882
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
14,869✔
883

884
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
14,869✔
885
      return right;
1✔
886
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
14,868✔
887
      return left;
2✔
888
   else if (lconst_real && rconst_real)
14,866✔
889
      return mir_const_real(mu, type, lreal + rreal);
4✔
890

891
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
14,862✔
892
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
14,862✔
893
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
14,862✔
894

895
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
14,862✔
896
}
897

898
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
12,957✔
899
                          mir_value_t right)
900
{
901
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
12,957✔
902
}
903

904
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
1,916✔
905
                               mir_value_t left, mir_value_t right,
906
                               mir_value_t locus)
907
{
908
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
1,916✔
909
}
910

911
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
20,128✔
912
                                    mir_type_t type, mir_value_t left,
913
                                    mir_value_t right, mir_value_t locus)
914
{
915
   int64_t lval, rval, cval;
20,128✔
916
   const bool lconst = mir_get_const(mu, left, &lval);
20,128✔
917
   const bool rconst = mir_get_const(mu, right, &rval);
20,128✔
918

919
   if (lconst && lval == 0)
20,128✔
920
      return right;
3✔
921
   else if (rconst && rval == 0)
20,125✔
922
      return left;
3✔
923
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
20,122✔
924
      return mir_const(mu, type, cval);
1✔
925
   else if (mir_equals(left, right))
20,121✔
926
      return mir_const(mu, type, 0);
159✔
927

928
   double lreal, rreal;
19,962✔
929
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
19,962✔
930
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
19,962✔
931

932
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
19,962✔
UNCOV
933
      return right;
×
934
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
19,962✔
935
      return left;
4✔
936
   else if (lconst_real && rconst_real)
19,958✔
UNCOV
937
      return mir_const_real(mu, type, lreal - rreal);
×
938

939
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
19,958✔
940
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
19,958✔
941
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
19,958✔
942

943
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
19,958✔
944
}
945

946
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
17,763✔
947
                          mir_value_t right)
948
{
949
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
17,763✔
950
}
951

952
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
2,039✔
953
                               mir_value_t left, mir_value_t right,
954
                               mir_value_t locus)
955
{
956
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
2,039✔
957
}
958

959
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
7,481✔
960
{
961
   int64_t cval;
7,481✔
962
   if (mir_get_const(mu, value, &cval))
7,481✔
963
      return mir_const(mu, type, -cval);
1✔
964

965
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
7,480✔
966
                                    MIR_NULL_STAMP, value);
7,480✔
967

968
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
7,480✔
969

970
   return result;
7,480✔
971
}
972

973
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
556✔
974
                               mir_value_t value, mir_value_t locus)
975
{
976
   int64_t cval;
556✔
977
   if (mir_get_const(mu, value, &cval) && cval >= 0)
556✔
UNCOV
978
      return mir_const(mu, type, -cval);
×
979
   // TODO: check if stamp bounds are non-negative
980

981
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
556✔
982
                                    MIR_NULL_STAMP, value, locus);
556✔
983

984
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
556✔
985
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
556✔
986
              "locus argument must be debug locus");
987

988
   return result;
556✔
989
}
990

991
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
235✔
992
{
993
   int64_t lconst;
235✔
994
   if (mir_get_const(mu, value, &lconst))
235✔
UNCOV
995
      return mir_const(mu, type, llabs(lconst));
×
996

997
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
235✔
998
                                    value);
999

1000
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
235✔
1001

1002
   return result;
235✔
1003
}
1004

1005
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
2,251✔
1006
                                    mir_type_t type, mir_value_t left,
1007
                                    mir_value_t right, mir_value_t locus)
1008
{
1009
   int64_t lval, rval, cval;
2,251✔
1010
   const bool lconst = mir_get_const(mu, left, &lval);
2,251✔
1011
   const bool rconst = mir_get_const(mu, right, &rval);
2,251✔
1012

1013
   if (lconst && lval == 0)
2,251✔
1014
      return left;
×
1015
   else if (rconst && rval == 0)
2,251✔
1016
      return right;
×
1017
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
2,251✔
UNCOV
1018
      return mir_const(mu, type, cval);
×
1019

1020
   double lreal, rreal;
2,251✔
1021
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
2,251✔
1022
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
2,251✔
1023

1024
   if (lconst_real && rconst_real)
2,251✔
1025
      return mir_const_real(mu, type, lreal * rreal);
158✔
1026

1027
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
2,093✔
1028
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
2,093✔
1029
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
2,093✔
1030

1031
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
2,093✔
1032
}
1033

1034
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
2,251✔
1035
                          mir_value_t right)
1036
{
1037
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
2,251✔
1038
}
1039

1040
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
326✔
1041
                               mir_value_t left, mir_value_t right,
1042
                               mir_value_t locus)
1043
{
1044
   return mir_build_sub_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
326✔
1045
}
1046

1047
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
886✔
1048
                          mir_value_t right)
1049
{
1050
   int64_t lval, rval;
886✔
1051
   const bool lconst = mir_get_const(mu, left, &lval);
886✔
1052
   const bool rconst = mir_get_const(mu, right, &rval);
886✔
1053

1054
   if (lconst && rconst && rval != 0)
886✔
1055
      return mir_const(mu, type, lval / rval);
×
1056
   else if (rconst && rval == 1)
886✔
UNCOV
1057
      return left;
×
1058

1059
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
886✔
1060
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
886✔
1061
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
886✔
1062

1063
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
886✔
1064
                          MIR_NULL_VALUE, stamp);
886✔
1065
}
1066

1067
mir_value_t mir_build_rem(mir_unit_t *mu, mir_type_t type, mir_value_t left,
97✔
1068
                          mir_value_t right)
1069
{
1070
   int64_t lval, rval;
97✔
1071
   const bool lconst = mir_get_const(mu, left, &lval);
97✔
1072
   const bool rconst = mir_get_const(mu, right, &rval);
97✔
1073

1074
   if (lconst && rconst && lval > 0 && rval > 0)
97✔
1075
      return mir_const(mu, type, lval % rval);
1✔
1076

1077
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
96✔
1078
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
96✔
1079
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
96✔
1080

1081
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
96✔
1082
                          MIR_NULL_VALUE, stamp);
96✔
1083
}
1084

1085
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
153✔
1086
                          mir_value_t right)
1087
{
1088
   int64_t lval, rval;
153✔
1089
   const bool lconst = mir_get_const(mu, left, &lval);
153✔
1090
   const bool rconst = mir_get_const(mu, right, &rval);
153✔
1091

1092
   if (lconst && rconst && lval > 0 && rval > 0)
153✔
UNCOV
1093
      return mir_const(mu, type, lval % rval);
×
1094

1095
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
153✔
1096
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
153✔
1097

1098
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
153✔
1099
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
20✔
1100
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
20✔
1101

1102
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
20✔
1103
         // If both arguments are non-negative then rem is equivalent
1104
         // and cheaper to compute
1105
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1106
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1107
                                MIR_NULL_VALUE, stamp);
1✔
1108
      }
1109
   }
1110

1111
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
152✔
1112
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
152✔
1113
}
1114

1115
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
72✔
1116
                          mir_value_t right)
1117
{
1118
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
144✔
1119
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
72✔
1120
}
1121

1122
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
531✔
1123
                               mir_value_t left, mir_value_t right,
1124
                               mir_value_t locus)
1125
{
1126
   int64_t rconst;
531✔
1127
   if (mir_get_const(mu, right, &rconst)) {
531✔
1128
      if (rconst == 0)
435✔
1129
         return mir_const(mu, type, 1);
×
1130
      else if (rconst == 1)
435✔
UNCOV
1131
         return left;
×
1132
   }
1133

1134
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
531✔
1135
                                        locus, MIR_NULL_STAMP);
531✔
1136

1137
   MIR_ASSERT(mir_is_integral(mu, result),
531✔
1138
              "trapping exp may only be used with integer types");
1139

1140
   return result;
531✔
1141
}
1142

1143
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
6,494✔
1144
                                     mir_type_t type, mir_value_t left,
1145
                                     mir_value_t right)
1146
{
1147
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
6,494✔
1148

1149
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
6,494✔
1150
              mir_op_string(op));
1151
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
6,494✔
1152
              mir_op_string(op));
1153

1154
   return result;
6,494✔
1155
}
1156

1157
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
4,417✔
1158
{
1159
   int64_t lval, rval;
4,417✔
1160
   const bool lconst = mir_get_const(mu, left, &lval);
4,417✔
1161
   const bool rconst = mir_get_const(mu, right, &rval);
4,417✔
1162

1163
   mir_type_t t_bool = mir_bool_type(mu);
4,417✔
1164

1165
   if (lconst && rconst)
4,417✔
1166
      return mir_const(mu, t_bool, lval && rval);
3✔
1167
   else if (lconst)
4,415✔
UNCOV
1168
      return lval ? right : mir_const(mu, t_bool, 0);
×
1169
   else if (rconst)
4,415✔
1170
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1171

1172
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
4,413✔
1173
}
1174

1175
mir_value_t mir_build_nand(mir_unit_t *mu, mir_value_t left, mir_value_t right)
63✔
1176
{
1177
   int64_t lval, rval;
63✔
1178
   const bool lconst = mir_get_const(mu, left, &lval);
63✔
1179
   const bool rconst = mir_get_const(mu, right, &rval);
63✔
1180

1181
   mir_type_t t_bool = mir_bool_type(mu);
63✔
1182

1183
   if (lconst && rconst)
63✔
1184
      return mir_const(mu, t_bool, !(lval && rval));
1✔
1185

1186
   return mir_build_logical(mu, MIR_OP_NAND, t_bool, left, right);
62✔
1187
}
1188

1189
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
1,793✔
1190
{
1191
   int64_t lval, rval;
1,793✔
1192
   const bool lconst = mir_get_const(mu, left, &lval);
1,793✔
1193
   const bool rconst = mir_get_const(mu, right, &rval);
1,793✔
1194

1195
   mir_type_t t_bool = mir_bool_type(mu);
1,793✔
1196

1197
   if (lconst && rconst)
1,793✔
1198
      return mir_const(mu, t_bool, lval || rval);
3✔
1199
   else if (lconst)
1,791✔
1200
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1201
   else if (rconst)
1,790✔
1202
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1203

1204
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
1,789✔
1205
}
1206

1207
mir_value_t mir_build_nor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
64✔
1208
{
1209
   int64_t lval, rval;
64✔
1210
   const bool lconst = mir_get_const(mu, left, &lval);
64✔
1211
   const bool rconst = mir_get_const(mu, right, &rval);
64✔
1212

1213
   mir_type_t t_bool = mir_bool_type(mu);
64✔
1214

1215
   if (lconst && rconst)
64✔
1216
      return mir_const(mu, t_bool, !(lval || rval));
4✔
1217

1218
   return mir_build_logical(mu, MIR_OP_NOR, t_bool, left, right);
62✔
1219
}
1220

1221
mir_value_t mir_build_xor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
106✔
1222
{
1223
   int64_t lval, rval;
106✔
1224
   const bool lconst = mir_get_const(mu, left, &lval);
106✔
1225
   const bool rconst = mir_get_const(mu, right, &rval);
106✔
1226

1227
   mir_type_t t_bool = mir_bool_type(mu);
106✔
1228
   if (lconst && rconst)
106✔
1229
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1230
   else if (mir_equals(left, right))
105✔
1231
      return mir_const(mu, t_bool, 0);
1✔
1232

1233
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
104✔
1234
}
1235

1236
mir_value_t mir_build_xnor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
64✔
1237
{
1238
   int64_t lval, rval;
64✔
1239
   const bool lconst = mir_get_const(mu, left, &lval);
64✔
1240
   const bool rconst = mir_get_const(mu, right, &rval);
64✔
1241

1242
   mir_type_t t_bool = mir_bool_type(mu);
64✔
1243
   if (lconst && rconst)
64✔
UNCOV
1244
      return mir_const(mu, t_bool, !(lval ^ rval));
×
1245

1246
   return mir_build_logical(mu, MIR_OP_XNOR, t_bool, left, right);
64✔
1247
}
1248

1249
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
2,680✔
1250
{
1251
   mir_type_t t_bool = mir_bool_type(mu);
2,680✔
1252

1253
   int64_t cval;
2,680✔
1254
   if (mir_get_const(mu, value, &cval))
2,680✔
1255
      return mir_const(mu, t_bool, !cval);
2✔
1256

1257
   if (mir_get_op(mu, value) == MIR_OP_NOT)
2,678✔
1258
      return mir_get_arg(mu, value, 0);
31✔
1259

1260
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
2,647✔
1261
                                    MIR_NULL_STAMP, value);
2,647✔
1262

1263
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
2,647✔
1264

1265
   return result;
2,647✔
1266
}
1267

1268
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
33,569✔
1269
                          mir_value_t right)
1270
{
1271
   int64_t lval, rval;
33,569✔
1272
   const bool lconst = mir_get_const(mu, left, &lval);
33,569✔
1273
   const bool rconst = mir_get_const(mu, right, &rval);
33,569✔
1274

1275
   mir_type_t t_bool = mir_bool_type(mu);
33,569✔
1276

1277
   if (lconst && rconst) {
33,569✔
1278
      switch (cmp) {
13✔
1279
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1280
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
2✔
1281
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
2✔
1282
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
2✔
1283
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
2✔
1284
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
2✔
1285
      default: should_not_reach_here();
1286
      }
1287
   }
1288

1289
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
33,556✔
1290
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
33,556✔
1291
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
33,556✔
1292

1293
   int64_t sconst;
33,556✔
1294
   if (mir_stamp_const(mu, stamp, &sconst))
33,556✔
1295
      return mir_const(mu, t_bool, sconst);
2✔
1296

1297
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
33,554✔
1298
                                    stamp, mir_enum(cmp), left, right);
1299

1300
   MIR_ASSERT(mir_equals(mir_get_type(mu, left), mir_get_type(mu, left)),
33,554✔
1301
              "arguments to cmp are not the same type");
1302

1303
   return result;
33,554✔
1304
}
1305

1306
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
71,944✔
1307
{
1308
   mir_type_t type = mir_get_type(mu, dest);
71,944✔
1309
   mir_type_t pointed = mir_get_pointer(mu, type);
71,944✔
1310

1311
   mir_build_2(mu, MIR_OP_STORE, pointed, MIR_NULL_STAMP, dest, src);
71,944✔
1312

1313
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
71,944✔
1314
              "store destination is not a pointer or variable");
1315
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
71,944✔
1316
              "source and destination have different types");
1317
}
71,944✔
1318

1319
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
117,084✔
1320
{
1321
   mir_type_t type = mir_get_type(mu, value);
117,084✔
1322
   mir_stamp_t stamp = mir_get_stamp(mu, value);
117,084✔
1323
   mir_type_t pointed = mir_get_pointer(mu, type);
117,084✔
1324

1325
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
117,084✔
1326

1327
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
117,084✔
1328
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
117,084✔
1329
              "argument to load is not a pointer or variable");
1330

1331
   return result;
117,084✔
1332
}
1333

1334
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
15,884✔
1335
                    mir_value_t count)
1336
{
1337
   int64_t cval;
15,884✔
1338
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
15,884✔
1339
      return;
233✔
1340
   else if (mir_equals(dest, src))
15,884✔
1341
      return;
1342

1343
   mir_type_t dtype = mir_get_type(mu, dest);
15,651✔
1344
   mir_type_t elem = mir_get_pointer(mu, dtype);
15,651✔
1345

1346
   if (mir_is_null(count))
15,651✔
1347
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
1,781✔
1348
   else
1349
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
13,870✔
1350

1351
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
15,651✔
1352
              "destination type is not a pointer");
1353
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
15,651✔
1354
              "source type is not a pointer");
1355
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
15,651✔
1356
              "source and destination types do not match");
1357
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
15,651✔
1358
              "count is not offset type");
1359
}
1360

1361
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
5,552✔
1362
                   mir_value_t count)
1363
{
1364
   int64_t cval;
5,552✔
1365
   if (mir_get_const(mu, count, &cval) && cval == 0)
5,552✔
UNCOV
1366
      return;
×
1367

1368
   mir_type_t dtype = mir_get_type(mu, dest);
5,552✔
1369
   mir_type_t elem = mir_get_pointer(mu, dtype);
5,552✔
1370

1371
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
5,552✔
1372

1373
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
5,552✔
1374
              "destination type is not a pointer");
1375
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
5,552✔
1376
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
5,552✔
1377
}
1378

1379
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
7,238✔
1380
                            mir_value_t count)
1381
{
1382
   mir_type_t ptr = mir_pointer_type(mu, type);
7,238✔
1383
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
7,238✔
1384

1385
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
7,238✔
1386
              "alloc element type cannot be array");
1387
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
7,238✔
1388

1389
   return result;
7,238✔
1390
}
1391

1392
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
2,712✔
1393
{
1394
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, MIR_NULL_STAMP);
2,712✔
1395

1396
#ifdef DEBUG
1397
   const mir_class_t class = mir_get_class(mu, type);
2,712✔
1398
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
2,712✔
1399
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1400
              "null type must be file, access, context, or pointer");
1401
#endif
1402

1403
   return result;
2,712✔
1404
}
1405

1406
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
410✔
1407
                          mir_value_t count)
1408
{
1409
   mir_type_t access = mir_access_type(mu, type);
410✔
1410

1411
   mir_value_t result;
410✔
1412
   if (mir_is_null(count))
410✔
1413
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
87✔
1414
   else
1415
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
323✔
1416

1417
#ifdef DEBUG
1418
   const mir_class_t class = mir_get_class(mu, type);
410✔
1419
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
410✔
1420
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1421
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1422
              "new type must be int, real, record, access, or uarray");
1423
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
410✔
1424
              "new count must have offset type");
1425
#endif
1426

1427
   return result;
410✔
1428
}
1429

1430
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
1,507✔
1431
{
1432
   mir_type_t type = mir_get_type(mu, access);
1,507✔
1433
   mir_stamp_t stamp = mir_get_stamp(mu, access);
1,507✔
1434
   mir_type_t pointed = mir_get_pointer(mu, type);
1,507✔
1435
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
1,507✔
1436

1437
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
1,507✔
1438
              "argument to all must be access type");
1439

1440
   return result;
1,507✔
1441
}
1442

1443
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
22,587✔
1444
{
1445
   mir_type_t type = mir_get_type(mu, array);
22,587✔
1446
   mir_type_t pointer = mir_get_pointer(mu, type);
22,587✔
1447
   mir_stamp_t stamp = mir_get_stamp(mu, array);
22,587✔
1448

1449
   if (mir_is_null(pointer))
22,587✔
1450
      pointer = mir_pointer_type(mu, type);
1,639✔
1451

1452
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
22,587✔
1453
                                    pointer, stamp, array);
1454

1455
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
22,587✔
1456
              || mir_is(mu, array, MIR_TYPE_RECORD),
1457
              "argument to address of must be array or record");
1458

1459
   return result;
22,587✔
1460
}
1461

1462
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
32,376✔
1463
                                mir_value_t offset)
1464
{
1465
   mir_type_t type = mir_get_type(mu, array);
32,376✔
1466
   mir_stamp_t stamp = mir_get_stamp(mu, array);
32,376✔
1467

1468
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
32,376✔
1469
                                    array, offset);
1470

1471
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
32,376✔
1472
              "argument to array ref must be pointer or signal");
1473
   MIR_ASSERT(mir_is_offset(mu, offset),
32,376✔
1474
              "offset argument to array ref must be offset");
1475

1476
   return result;
32,376✔
1477
}
1478

1479
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
37,503✔
1480
                                 unsigned field)
1481
{
1482
   mir_type_t pointer = mir_get_type(mu, record);
37,503✔
1483

1484
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
37,503✔
1485

1486
   mir_type_t type = MIR_NULL_TYPE;
37,503✔
1487
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
37,503✔
1488
      type = td->u.record.fields[field + td->u.record.count];
37,503✔
1489

1490
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, MIR_NULL_STAMP,
37,503✔
1491
                                    record, mir_enum(field));
1492

1493
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
37,503✔
1494
              "record ref argument must be pointer to record");
1495
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
37,503✔
1496
              "record ref argument must be pointer to record");
1497
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
37,503✔
1498

1499
   return result;
37,503✔
1500
}
1501

1502
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
28,992✔
1503
                           const mir_dim_t *dims, int ndims)
1504
{
1505
   mir_type_t type = mir_get_type(mu, data);
28,992✔
1506
   mir_stamp_t stamp = mir_get_stamp(mu, data);
28,992✔
1507

1508
   const type_data_t *td = mir_type_data(mu, type);
28,992✔
1509
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
28,992✔
1510

1511
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
28,992✔
1512

1513
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
57,984✔
1514
                                  ndims * 3 + 1);
28,992✔
1515

1516
   mir_set_arg(mu, n, 0, data);
28,992✔
1517

1518
   for (int i = 0; i < ndims; i++) {
58,395✔
1519
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
29,403✔
1520
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
29,403✔
1521
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
29,403✔
1522
   }
1523

1524
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
28,992✔
1525
              "wrapped data is not pointer or signal");
1526

1527
   for (int i = 0; i < ndims; i++) {
58,395✔
1528
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
29,403✔
1529
                 "dimension %d left bound must be integral", i + 1);
1530
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
29,403✔
1531
                 "dimension %d right bound must be integral", i + 1);
1532
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
29,403✔
1533
                 "dimension %d direction must be bool", i + 1);
1534
   }
1535

1536
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
28,992✔
1537
}
1538

1539
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
26,229✔
1540
{
1541
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
26,229✔
1542
      return mir_get_arg(mu, array, 0);
1,978✔
1543

1544
   mir_type_t type = mir_get_type(mu, array);
24,251✔
1545
   mir_type_t pointer = mir_get_pointer(mu, type);
24,251✔
1546
   mir_stamp_t stamp = mir_get_stamp(mu, array);
24,251✔
1547

1548
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
24,251✔
1549

1550
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
24,251✔
1551
              "unwrap argument must be uarray");
1552

1553
   return result;
24,251✔
1554
}
1555

1556
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
20,671✔
1557
{
1558
   mir_type_t t_offset = mir_offset_type(mu);
20,671✔
1559
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
20,671✔
1560
                                    MIR_NULL_STAMP, array,
20,671✔
1561
                                    mir_const(mu, t_offset, dim));
1562

1563
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
20,671✔
1564
              "uarray len argument must be uarrray");
1565

1566
#ifdef DEBUG
1567
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
20,671✔
1568
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
20,671✔
1569
#endif
1570

1571
   return result;
20,671✔
1572
}
1573

1574
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
49,197✔
1575
                                       mir_type_t type, int arg_index,
1576
                                       mir_value_t array, int dim)
1577
{
1578
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
49,197✔
1579
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,513✔
1580

1581
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
47,684✔
1582
                                    array, mir_enum(dim));
1583

1584
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
47,684✔
1585
              "cannot use %s with non-uarray type", mir_op_string(op));
1586

1587
#ifdef DEBUG
1588
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
47,684✔
1589
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
47,684✔
1590
#endif
1591

1592
   return result;
47,684✔
1593
}
1594

1595
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
17,183✔
1596
{
1597
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
17,183✔
1598
                              0, array, dim);
1599
}
1600

1601
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
14,869✔
1602
{
1603
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
14,869✔
1604
                              1, array, dim);
1605
}
1606

1607
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
17,145✔
1608
{
1609
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
17,145✔
1610
                              2, array, dim);
1611
}
1612

1613
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
6,131✔
1614
                                   mir_value_t right, mir_value_t dir)
1615
{
1616
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
6,131✔
1617
                                    mir_offset_type(mu), MIR_NULL_STAMP,
6,131✔
1618
                                    left, right, dir);
1619

1620
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left), mir_get_type(mu, left)),
6,131✔
1621
              "left and right are not the same type");
1622
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
6,131✔
1623
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
6,131✔
1624

1625
   return result;
6,131✔
1626
}
1627

1628
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
4,611✔
1629
                                 mir_value_t right, mir_value_t dir)
1630
{
1631
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
4,611✔
1632
                                    mir_bool_type(mu), MIR_NULL_STAMP,
4,611✔
1633
                                    left, right, dir);
1634

1635
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left), mir_get_type(mu, left)),
4,611✔
1636
              "left and right are not the same type");
1637
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
4,611✔
1638
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
4,611✔
1639

1640
   return result;
4,611✔
1641
}
1642

1643
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
35,176✔
1644
{
1645
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
35,176✔
1646
               mir_cast_value(target));
35,176✔
1647

1648
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
35,176✔
1649
}
35,176✔
1650

1651
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
32,939✔
1652
                    mir_block_t bfalse)
1653
{
1654
   int64_t tconst;
32,939✔
1655
   if (mir_get_const(mu, test, &tconst)) {
32,939✔
1656
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
1✔
1657
      return;
1✔
1658
   }
1659

1660
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
32,938✔
1661
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
32,938✔
1662

1663
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
32,938✔
1664
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
32,938✔
1665
              "invalid cond targets");
1666
}
1667

1668
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
12,446✔
1669
                             mir_value_t vtrue, mir_value_t vfalse)
1670
{
1671
   int64_t tconst;
12,446✔
1672
   if (mir_get_const(mu, test, &tconst))
12,446✔
1673
      return tconst ? vtrue : vfalse;
135✔
1674
   else if (mir_equals(vtrue, vfalse))
12,311✔
1675
      return vtrue;
1✔
1676

1677
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
12,310✔
1678
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
12,310✔
1679
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
12,310✔
1680

1681
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
12,310✔
1682
                                    vtrue, vfalse);
1683

1684
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
12,310✔
1685
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
12,310✔
1686
              "true argument to select is not expected type");
1687
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
12,310✔
1688
              "false argument to select is not expected type");
1689

1690
   return result;
12,310✔
1691
}
1692

1693
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
1694
{
1695
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
1696
                                 ninputs * 2);
1697

1698
   for (int i = 0; i < ninputs; i++)
3✔
1699
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
1700

1701
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
1702
}
1703

1704
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
1705
                   mir_block_t block, mir_value_t value)
1706
{
1707
   node_data_t *n = mir_node_data(mu, phi);
2✔
1708
   assert(n->op == MIR_OP_PHI);
2✔
1709
   assert(nth * 2 < n->nargs);
2✔
1710

1711
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
1712
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
1713

1714
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
1715

1716
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
1717
              "phi input %d has wrong type", nth);
1718

1719
#ifdef DEBUG
1720
   if (value.tag != MIR_TAG_CONST) {
2✔
1721
      const block_data_t *bd = mir_block_data(mu, block);
2✔
1722
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
1723
         if (bd->nodes[i] == value.id)
2✔
1724
         return;
1725
      }
1726

UNCOV
1727
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
1728
   }
1729
#endif
1730
}
1731

1732
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
623✔
1733
                    const mir_value_t *cases, const mir_block_t *blocks,
1734
                    int ncases)
1735
{
1736
   int64_t cval;
623✔
1737
   if (mir_get_const(mu, value, &cval)) {
623✔
1738
      for (int i = 0; i < ncases; i++) {
3✔
1739
         int64_t cmp;
2✔
1740
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
1741
            mir_build_jump(mu, blocks[i]);
1✔
1742
            return;
1✔
1743
         }
1744
      }
1745

1746
      mir_build_jump(mu, def);
1✔
1747
      return;
1✔
1748
   }
1749

1750
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,242✔
1751
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
621✔
1752

1753
   mir_set_arg(mu, n, 0, value);
621✔
1754
   mir_set_arg(mu, n, 1, mir_cast_value(def));
621✔
1755

1756
   for (int i = 0; i < ncases; i++) {
5,222✔
1757
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
4,601✔
1758
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
4,601✔
1759
   }
1760

1761
   MIR_ASSERT(mir_is_integral(mu, value), "case choice must be integral");
621✔
1762

1763
#ifdef DEBUG
1764
   mir_type_t type = mir_get_type(mu, value);
621✔
1765
   for (int i = 0; i < ncases; i++) {
5,222✔
1766
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
4,601✔
1767
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
4,601✔
1768
                 "choice and value types do not match");
1769

1770
      for (int j = 0; j < i; j++)
244,553✔
1771
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
239,952✔
1772
   }
1773
#endif
1774
}
1775

1776
void mir_build_return(mir_unit_t *mu, mir_value_t value)
51,278✔
1777
{
1778
   if (mir_is_null(value))
51,278✔
1779
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
24,276✔
1780
   else
1781
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
27,002✔
1782

1783
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
51,278✔
1784
              "wrong result type");
1785
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
51,278✔
1786
              || mir_is_null(value), "cannot return a result");
1787
}
51,278✔
1788

1789
void mir_build_wait(mir_unit_t *mu, mir_block_t target, mir_value_t time)
13,489✔
1790
{
1791
   if (mir_is_null(time))
13,489✔
1792
      mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,186✔
1793
                  mir_cast_value(target));
8,186✔
1794
   else
1795
      mir_build_2(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,303✔
1796
                  mir_cast_value(target), time);
5,303✔
1797

1798
   MIR_ASSERT(mir_is_null(time) || mir_is_time(mu, time),
13,489✔
1799
              "time argument to wait is not a time");
1800
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
13,489✔
1801
              "wait only allowed in process or procedure");
1802
}
13,489✔
1803

1804
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
1✔
1805
{
1806
   if (value.tag != MIR_TAG_NODE)
1✔
1807
      return;   // Only useful for keeping nodes alive
1808

UNCOV
1809
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
1810
}
1811

1812
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
35,808✔
1813
                            mir_stamp_t stamp, const mir_value_t *args,
1814
                            unsigned nargs)
1815
{
1816
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
35,808✔
1817

1818
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
35,808✔
1819

1820
   for (int i = 0; i < nargs; i++)
140,459✔
1821
      mir_set_arg(mu, n, i + 1, args[i]);
104,651✔
1822

1823
   if (mir_is_null(type))
35,808✔
1824
      return MIR_NULL_VALUE;
4,964✔
1825
   else
1826
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,844✔
1827
}
1828

1829
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
875✔
1830
                     const mir_value_t *args, unsigned nargs)
1831
{
1832
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
1,750✔
1833
                                 MIR_NULL_STAMP, nargs + 2);
875✔
1834
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
875✔
1835
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
875✔
1836

1837
   for (int i = 0; i < nargs; i++)
3,106✔
1838
      mir_set_arg(mu, n, i + 2, args[i]);
2,231✔
1839

1840
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
875✔
1841
              "first argument to VHDL procedure must be context pointer");
1842
}
875✔
1843

1844
void mir_build_resume(mir_unit_t *mu, ident_t name)
875✔
1845
{
1846
   mir_value_t link = mir_add_linkage(mu, name);
875✔
1847
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
875✔
1848

1849
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
875✔
1850
              "resume must be first op in a block");
1851
}
875✔
1852

1853
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
423✔
1854
                              mir_stamp_t stamp, mir_value_t locus,
1855
                              const mir_value_t *args, int nargs)
1856
{
1857
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
423✔
1858

1859
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
423✔
1860
   mir_set_arg(mu, n, 1, locus);
423✔
1861

1862
   for (int i = 0; i < nargs; i++)
498✔
1863
      mir_set_arg(mu, n, i + 2, args[i]);
75✔
1864

1865
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
423✔
1866
              "locus argument to syscall must be a debug locus");
1867

1868
   for (int i = 0; i < nargs; i++)
498✔
1869
      MIR_ASSERT(!mir_is_null(args[i]), "invalid argument to syscall");
75✔
1870

1871
   if (mir_is_null(type))
423✔
1872
      return MIR_NULL_VALUE;
384✔
1873
   else
1874
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
39✔
1875
}
1876

1877
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
595✔
1878
{
1879
   if (mir_is_null(locus))
595✔
1880
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
463✔
1881
   else
1882
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
132✔
1883

1884
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
595✔
1885
              "locus argument to unreachable must be debug locus");
1886
}
595✔
1887
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
14,102✔
1888
                                mir_value_t left, mir_value_t right,
1889
                                mir_value_t dir, mir_value_t locus,
1890
                                mir_value_t hint)
1891
{
1892
   // TODO: check if can elide bounds
1893

1894
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
14,102✔
1895
               dir, locus, hint);
1896
}
14,102✔
1897

1898
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
3,020✔
1899
                           mir_value_t right, mir_value_t dir,
1900
                           mir_value_t locus, mir_value_t hint)
1901
{
1902
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
3,020✔
1903
                       locus, hint);
1904
}
3,020✔
1905

1906
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
11,082✔
1907
                           mir_value_t right, mir_value_t dir,
1908
                           mir_value_t locus, mir_value_t hint)
1909
{
1910
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
11,082✔
1911
                       locus, hint);
1912
}
11,082✔
1913

1914
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
1,097✔
1915
{
1916
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,097✔
1917
               ptr, locus);
1918

1919
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
1,097✔
1920
              "null check argument must be an access");
1921
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,097✔
1922
              "locus argument to null check must be a debug locus");
1923
}
1,097✔
1924

1925
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
100✔
1926
{
1927
   int64_t cval;
100✔
1928
   if (mir_get_const(mu, value, &cval) && cval != 0)
100✔
UNCOV
1929
      return;
×
1930

1931
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
100✔
1932
               value, locus);
1933

1934
   MIR_ASSERT(mir_is_integral(mu, value),
100✔
1935
              "argument to zero check must be integral");
1936
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
100✔
1937
              "locus argument to zero check must be a debug locus");
1938
}
1939

1940
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
6,745✔
1941
                            mir_value_t locus, mir_value_t dim)
1942
{
1943
   if (mir_equals(llen, rlen))
6,745✔
1944
      return;
1945

1946
   if (mir_is_null(dim))
6,745✔
1947
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
6,721✔
1948
                  llen, rlen, locus);
1949
   else
1950
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
1951
                  llen, rlen, locus, dim);
1952

1953
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
6,745✔
1954
              "locus argument to length check must be a debug locus");
1955
}
1956

1957
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
513✔
1958
                              mir_value_t locus)
1959
{
1960
   int64_t cval;
513✔
1961
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
513✔
UNCOV
1962
      return;
×
1963

1964
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
513✔
1965
               exp, locus);
1966

1967
   MIR_ASSERT(mir_is_integral(mu, exp),
513✔
1968
              "exp argument to exponent check must be a integer");
1969
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
513✔
1970
              "locus argument to exponent check must be a debug locus");
1971
}
1972

1973
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
261✔
1974
                         mir_value_t length, mir_value_t kind,
1975
                         mir_value_t status)
1976
{
1977
   if (mir_is_null(status))
261✔
1978
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
235✔
1979
                  file, name, length, kind);
1980
   else
1981
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
26✔
1982
                  file, name, length, kind, status);
1983

1984
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
261✔
1985
              "file open first argument must be pointer to file");
1986
}
261✔
1987

1988
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
75✔
1989
                         mir_value_t inlen, mir_value_t outlen)
1990
{
1991
   if (mir_is_null(inlen))
75✔
1992
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
48✔
1993
                  file, ptr);
1994
   else if (mir_is_null(outlen))
27✔
1995
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
9✔
1996
                  file, ptr, inlen);
1997
   else
1998
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
1999
                  file, ptr, inlen, outlen);
2000

2001
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
75✔
2002
              "file read first argument must have file pointer type");
2003
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
75✔
2004
              "file read pointer argument must have pointer type");
2005
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
75✔
2006
              "file read inlen argument must be integral");
2007
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
75✔
2008
              "file read outlen argument must have pointer type");
2009
}
75✔
2010

2011
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
122✔
2012
                          mir_value_t length)
2013
{
2014
   if (mir_is_null(length))
122✔
2015
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2016
                  file, value);
2017
   else
2018
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
65✔
2019
                  file, value, length);
2020

2021
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
122✔
2022
              "file write first argument must have file pointer type");
2023
}
122✔
2024

2025
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
279✔
2026
                                      mir_value_t effective)
2027
{
2028
   mir_type_t type = mir_conversion_type(mu);
279✔
2029

2030
   mir_value_t result;
279✔
2031
   if (mir_is_null(effective) || mir_equals(effective, driving))
279✔
2032
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
261✔
2033
                           driving);
2034
   else
2035
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
18✔
2036
                           driving, effective);
2037

2038
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
279✔
2039
              "port conversion argument must be a closure");
2040
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
279✔
2041
              "port conversion argument must be a closure");
2042

2043
   return result;
279✔
2044
}
2045

2046
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
354✔
2047
                          mir_value_t count)
2048
{
2049
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
354✔
2050
               conv, nets, count);
2051

2052
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
354✔
2053
              "conv argument to convert must be a port conversion");
2054
   MIR_ASSERT(mir_is_signal(mu, nets),
354✔
2055
              "nets argument to convert must be a signal");
2056
   MIR_ASSERT(mir_is_offset(mu, count),
354✔
2057
              "count argument to convert must be offset");
2058
}
354✔
2059

2060
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
396✔
2061
                           mir_value_t count)
2062
{
2063
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
396✔
2064
               conv, nets, count);
2065

2066
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
396✔
2067
              "conv argument to convert must be a port conversion");
2068
   MIR_ASSERT(mir_is_signal(mu, nets),
396✔
2069
              "nets argument to convert must be a signal");
2070
   MIR_ASSERT(mir_is_offset(mu, count),
396✔
2071
              "count argument to convert must be offset");
2072
}
396✔
2073

2074
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
402✔
2075
                              mir_value_t target, mir_value_t count,
2076
                              mir_value_t values)
2077
{
2078
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
402✔
2079
               cf, target, count, values);
2080

2081
   MIR_ASSERT(mir_is_signal(mu, target),
402✔
2082
              "put conversion target is not signal");
2083
   MIR_ASSERT(mir_is_offset(mu, count),
402✔
2084
              "put conversion net count is not offset type");
2085
   MIR_ASSERT(!mir_is_signal(mu, values),
402✔
2086
              "signal cannot be values argument for put conversion");
2087
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
402✔
2088
              "cf argument to put conversion must be conversion function");
2089
}
402✔
2090

2091
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
16,185✔
2092
                                  mir_value_t count, mir_value_t size,
2093
                                  mir_value_t value, mir_value_t flags,
2094
                                  mir_value_t locus, mir_value_t offset)
2095
{
2096
   mir_type_t stype = mir_signal_type(mu, type);
16,185✔
2097

2098
   mir_value_t result;
16,185✔
2099
   if (mir_is_null(offset))
16,185✔
2100
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
10,580✔
2101
                           count, size, value, flags, locus);
2102
   else
2103
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
5,605✔
2104
                           count, size, value, flags, locus, offset);
2105

2106
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
16,185✔
2107
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2108
              "signal must have integer or real type");
2109
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
16,185✔
2110
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
16,185✔
2111
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
16,185✔
2112
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
16,185✔
2113
              "locus argument to init signal is not debug locus");
2114
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
16,185✔
2115
              "offset argument must be pointer or null");
2116

2117
   return result;
16,185✔
2118
}
2119

2120
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
75✔
2121
                                      mir_value_t count, mir_value_t size,
2122
                                      mir_value_t locus, mir_value_t kind,
2123
                                      mir_value_t closure, mir_value_t delay)
2124
{
2125
   mir_type_t stype = mir_signal_type(mu, type);
75✔
2126

2127
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
75✔
2128
                                    MIR_NULL_STAMP, count, size, locus,
75✔
2129
                                    kind, closure, delay);
2130

2131
   MIR_ASSERT(mir_is_offset(mu, count),
75✔
2132
              "count argument to implicit signal is not offset");
2133
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
75✔
2134
              "kind argument to implicit signal is not offset");
2135
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
75✔
2136
              "closure argument to implicit signal is not a closure");
2137
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
75✔
2138
              "locus argument to implicit signal must be a debug locus");
2139
   MIR_ASSERT(mir_is_integral(mu, delay),
75✔
2140
              "delay argument to implicit signal must be time");
2141

2142
   return result;
75✔
2143
}
2144

2145
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
9,197✔
2146
                            mir_value_t count)
2147
{
2148
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,197✔
2149
               target, count);
2150

2151
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
9,197✔
2152
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
9,197✔
2153
}
9,197✔
2154

2155
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
10,611✔
2156
                              mir_value_t count, mir_value_t values,
2157
                              mir_value_t reject, mir_value_t after)
2158
{
2159
   int64_t nconst;
10,611✔
2160
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
10,611✔
UNCOV
2161
      mir_comment(mu, "Skip empty waveform");
×
UNCOV
2162
      return;
×
2163
   }
2164

2165
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
10,611✔
2166
               target, count, values, reject, after);
2167

2168
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
10,611✔
2169
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
10,611✔
2170
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
10,611✔
2171
}
2172

2173
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
177✔
2174
                              mir_value_t count, mir_value_t values)
2175
{
2176
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
177✔
2177
               target, count, values);
2178

2179
   MIR_ASSERT(mir_is_signal(mu, target),
177✔
2180
              "deposit signal target is not signal");
2181
   MIR_ASSERT(mir_is_offset(mu, count),
177✔
2182
              "deposit signal count is not offset type");
2183
   MIR_ASSERT(!mir_is_signal(mu, values),
177✔
2184
              "signal cannot be values argument for deposit signal");
2185
}
177✔
2186

2187
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
14,110✔
2188
{
2189
   mir_type_t type = mir_get_type(mu, signal);
14,110✔
2190
   mir_type_t pointer = mir_get_pointer(mu, type);
14,110✔
2191
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
14,110✔
2192

2193
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
14,110✔
2194
                                    stamp, signal);
2195

2196
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
14,110✔
2197
              "argument to resolved must be signal");
2198

2199
   return result;
14,110✔
2200
}
2201

2202
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
90✔
2203
{
2204
   mir_type_t type = mir_get_type(mu, signal);
90✔
2205
   mir_type_t pointer = mir_get_pointer(mu, type);
90✔
2206
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
90✔
2207

2208
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
90✔
2209
                                    stamp, signal);
2210

2211
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
90✔
2212
              "argument to resolved must be signal");
2213

2214
   return result;
90✔
2215
}
2216

2217
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
138✔
2218
                                    mir_value_t count)
2219
{
2220
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
138✔
2221
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
138✔
2222

2223
   mir_value_t result;
138✔
2224
   if (mir_is_null(count))
138✔
2225
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
105✔
2226
   else
2227
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
33✔
2228
                           signal, count);
2229

2230
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
138✔
2231
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
138✔
2232
              "count argument must have offset type");
2233

2234
   return result;
138✔
2235
}
2236

2237
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
60✔
2238
                     mir_value_t values)
2239
{
2240
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
60✔
2241
               target, count, values);
2242

2243
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
60✔
2244
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
60✔
2245
}
60✔
2246

2247
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
30✔
2248
{
2249
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
30✔
2250
               target, count);
2251

2252
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
30✔
2253
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
30✔
2254
}
30✔
2255

2256
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
24✔
2257
                          mir_value_t reject, mir_value_t after)
2258
{
2259
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2260
               target, count, reject, after);
2261

2262
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
24✔
2263
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
24✔
2264
}
24✔
2265

2266

2267
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
33✔
2268
                                 mir_value_t count)
2269
{
2270
   mir_type_t type = mir_time_type(mu);
33✔
2271

2272
   mir_value_t result;
33✔
2273
   if (mir_is_null(count))
33✔
2274
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
24✔
2275
   else
2276
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
9✔
2277
                           signal, count);
2278

2279
   MIR_ASSERT(mir_is_signal(mu, signal),
33✔
2280
              "signal argument to last event must have signal type");
2281
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
33✔
2282
              "length argument to last event must have offset type");
2283

2284
   return result;
33✔
2285
}
2286

2287
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
36✔
2288
                                  mir_value_t count)
2289
{
2290
   mir_type_t type = mir_time_type(mu);
36✔
2291

2292
   mir_value_t result;
36✔
2293
   if (mir_is_null(count))
36✔
2294
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
30✔
2295
                           signal);
2296
   else
2297
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
6✔
2298
                           signal, count);
2299

2300
   MIR_ASSERT(mir_is_signal(mu, signal),
36✔
2301
              "signal argument to last event must have signal type");
2302
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
36✔
2303
              "length argument to last event must have offset type");
2304

2305
   return result;
36✔
2306
}
2307

2308

2309
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
666✔
2310
                                         mir_value_t signal, mir_value_t count)
2311
{
2312
   mir_type_t t_bool = mir_bool_type(mu);
666✔
2313
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
666✔
2314
                                    signal, count);
2315

2316
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
666✔
2317
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
666✔
2318

2319
   return result;
666✔
2320
}
2321

2322
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
411✔
2323
                                 mir_value_t count)
2324
{
2325
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
411✔
2326
}
2327

2328
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
219✔
2329
                                  mir_value_t count)
2330
{
2331
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
219✔
2332
}
2333

2334
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
36✔
2335
                                   mir_value_t count)
2336
{
2337
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
36✔
2338
}
2339

2340
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
3,451✔
2341
                              mir_value_t resolution)
2342
{
2343
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,451✔
2344
               signal, resolution);
2345

2346
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
3,451✔
2347
   MIR_ASSERT(mir_is(mu, resolution, MIR_TYPE_RESOLUTION),
3,451✔
2348
              "resolution wrapper argument has wrong type");
2349
}
3,451✔
2350

2351
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
1,160✔
2352
                               mir_value_t source, mir_value_t count,
2353
                               mir_value_t reject, mir_value_t after)
2354
{
2355
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,160✔
2356
               target, source, count, reject, after);
2357

2358
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
1,160✔
2359
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,160✔
2360
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
1,160✔
2361
}
1,160✔
2362

2363
void mir_build_cover_stmt(mir_unit_t *mu, uint32_t tag)
961✔
2364
{
2365
   mir_build_1(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
961✔
2366
               mir_enum(tag));
2367
}
961✔
2368

2369
void mir_build_cover_branch(mir_unit_t *mu, uint32_t tag)
486✔
2370
{
2371
   mir_build_1(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
486✔
2372
               mir_enum(tag));
2373
}
486✔
2374

2375
void mir_build_cover_expr(mir_unit_t *mu, uint32_t tag)
849✔
2376
{
2377
   mir_build_1(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
849✔
2378
               mir_enum(tag));
2379
}
849✔
2380

2381
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
381✔
2382
{
2383
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
381✔
2384
               signal, mir_enum(tag));
2385

2386
   MIR_ASSERT(mir_is_signal(mu, signal),
381✔
2387
              "argument to cover toggle must be signal");
2388
}
381✔
2389

2390
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
12✔
2391
                           uint32_t tag)
2392
{
2393
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2394
               signal, low, mir_enum(tag));
2395

2396
   MIR_ASSERT(mir_is_signal(mu, signal),
12✔
2397
              "argument to cover state must be signal");
2398
}
12✔
2399
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
17,637✔
2400
                                   mir_value_t context)
2401
{
2402
   mir_value_t link = mir_add_linkage(mu, name);
17,637✔
2403
   mir_type_t type = mir_context_type(mu, name);
17,637✔
2404

2405
   mir_value_t result;
17,637✔
2406
   if (mir_is_null(context))
17,637✔
2407
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
17,455✔
2408
                           MIR_NULL_STAMP, link);
17,455✔
2409
   else
2410
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
182✔
2411
                           MIR_NULL_STAMP, link, context);
182✔
2412

2413
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
17,637✔
2414
              "invalid package init context argument");
2415
   MIR_ASSERT(mu->kind == MIR_UNIT_INSTANCE
17,637✔
2416
              || mu->kind == MIR_UNIT_PACKAGE
2417
              || mu->kind == MIR_UNIT_THUNK,
2418
              "cannot use package init here");
2419
   MIR_ASSERT(name != mu->name, "cyclic package init");
17,637✔
2420

2421
   return result;
17,637✔
2422
}
2423

2424
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
112✔
2425
{
2426
   mir_value_t link = mir_add_linkage(mu, name);
112✔
2427
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
112✔
2428
               link, locus);
2429

2430
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
112✔
2431
              "locus argument to process init must be a debug locus");
2432
}
112✔
2433

2434
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
162✔
2435
                                     mir_value_t context, mir_value_t path_name,
2436
                                     mir_value_t inst_name)
2437
{
2438
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
162✔
2439

2440
   mir_value_t result;
162✔
2441
   if (mir_is_null(path_name) && mir_is_null(inst_name))
162✔
2442
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
124✔
2443
                           link, context);
2444
   else {
2445
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
38✔
2446
                           link, context, path_name, inst_name);
2447

2448
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
38✔
2449
                 "path name argument must be array");
2450
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
38✔
2451
                 "inst name argument must be array");
2452
   }
2453

2454
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
162✔
2455
                "protected init type must be context");
2456
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
162✔
2457
              "invalid protected init context argument");
2458

2459
   return result;
162✔
2460
}
2461

2462
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
1,606✔
2463
{
2464
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
1,606✔
2465

2466
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,606✔
2467
              "locus argument to record scope must be a debug locus");
2468
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
1,606✔
2469
              "record scope type must be record");
2470
}
1,606✔
2471

2472
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
632✔
2473
{
2474
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
632✔
2475

2476
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
632✔
2477
              "locus argument to array scope must be a debug locus");
2478
}
632✔
2479

2480
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
45✔
2481
{
2482
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
45✔
2483

2484
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2485
              "locus argument to package scope must be a debug locus");
2486
}
45✔
2487

2488
void mir_build_pop_scope(mir_unit_t *mu)
2,283✔
2489
{
2490
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
2,283✔
2491
}
2,283✔
2492

2493
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
4,232✔
2494
                            mir_value_t locus)
2495
{
2496
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,232✔
2497
               signal, locus);
2498

2499
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
4,232✔
2500
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
4,232✔
2501
              "locus argument must have debug locus type");
2502
}
4,232✔
2503

2504
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
5,322✔
2505
                          mir_value_t count)
2506
{
2507
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,322✔
2508
               src, dst, count);
2509

2510
   MIR_ASSERT(mir_is_signal(mu, src),
5,322✔
2511
              "src argument to map signal is not a signal");
2512
   MIR_ASSERT(mir_is_signal(mu, dst),
5,322✔
2513
              "dst argument to map signal is not a signal");
2514
   MIR_ASSERT(mir_is_offset(mu, count),
5,322✔
2515
              "count argument to map signal is not offset type");
2516
}
5,322✔
2517

2518
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
219✔
2519
                         mir_value_t count)
2520
{
2521
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
219✔
2522
               src, dst, count);
2523

2524
   MIR_ASSERT(mir_is_signal(mu, dst),
219✔
2525
              "dst argument to map const is not a signal");
2526
   MIR_ASSERT(mir_is_offset(mu, count),
219✔
2527
              "count argument to map const is not offset type");
2528
}
219✔
2529

2530
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
57✔
2531
                            mir_value_t count)
2532
{
2533
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2534
               src, dst, count);
2535

2536
   MIR_ASSERT(mir_is_signal(mu, src),
57✔
2537
              "src argument to map implicit is not a signal");
2538
   MIR_ASSERT(mir_is_signal(mu, dst),
57✔
2539
              "dst argument to map implicit is not a signal");
2540
   MIR_ASSERT(mir_is_offset(mu, count),
57✔
2541
              "count argument type to map implicit is not offset");
2542
}
57✔
2543

2544
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
45✔
2545
                                  mir_value_t right)
2546
{
2547
   mir_type_t type = mir_trigger_type(mu);
45✔
2548
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
45✔
2549
                                    MIR_NULL_STAMP, left, right);
45✔
2550

2551
   MIR_ASSERT(mir_is_signal(mu, left),
45✔
2552
              "cmp trigger left argument must be signal");
2553
   MIR_ASSERT(mir_is_integral(mu, right),
45✔
2554
              "cmp trigger right argument must be integer");
2555

2556
   return result;
45✔
2557
}
2558

2559
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
212✔
2560
                                       const mir_value_t *args, unsigned nargs)
2561
{
2562
   mir_type_t type = mir_trigger_type(mu);
212✔
2563
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
424✔
2564
                                 MIR_NULL_STAMP, nargs + 1);
212✔
2565

2566
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
212✔
2567

2568
   for (int i = 0; i < nargs; i++)
561✔
2569
      mir_set_arg(mu, n, i + 1, args[i]);
349✔
2570

2571
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
212✔
2572
}
2573

2574
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
33✔
2575
                                 mir_value_t right)
2576
{
2577
   mir_type_t type = mir_trigger_type(mu);
33✔
2578
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
33✔
2579
                                    MIR_NULL_STAMP, left, right);
33✔
2580

2581
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
33✔
2582
              "or trigger left argument must be trigger");
2583
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
33✔
2584
              "or trigger right argument must be trigger");
2585

2586
   return result;
33✔
2587
}
2588

2589
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
362✔
2590
{
2591
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
362✔
2592

2593
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
362✔
2594
              "add trigger argument must be trigger");
2595
}
362✔
2596

2597
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
11,402✔
2598
{
2599
   mir_value_t link = mir_add_linkage(mu, name);
11,402✔
2600
   mir_type_t type = mir_context_type(mu, name);
11,402✔
2601

2602
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
11,402✔
2603
                                    MIR_NULL_STAMP, link);
11,402✔
2604

2605
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
11,402✔
2606

2607
   return result;
11,402✔
2608
}
2609

2610
mir_value_t mir_build_link_var(mir_unit_t *mu, ident_t unit,
2,522✔
2611
                               mir_value_t context, ident_t name,
2612
                               mir_type_t type)
2613
{
2614
   mir_type_t pointer = mir_get_var_pointer(mu, type);
2,522✔
2615
   mir_value_t link = mir_add_linkage(mu, unit);
2,522✔
2616
   mir_value_t var_link = mir_add_linkage(mu, name);   // TODO: rethink this
2,522✔
2617
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
2,522✔
2618
                                    MIR_NULL_STAMP, link, context, var_link);
2,522✔
2619

2620
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
2,522✔
2621
              "first argument to link var must be context");
2622

2623
   return result;
2,522✔
2624
}
2625

2626
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
259✔
2627
                            mir_value_t length, mir_value_t locus)
2628
{
2629
   if (mir_is_null(locus))
259✔
2630
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
122✔
2631
                  spec, length);
2632
   else
2633
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
137✔
2634
                  spec, length, locus);
2635

2636
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
259✔
2637
              "spec argument to bind foreign must be a pointer");
2638
   MIR_ASSERT(mir_is_offset(mu, length),
259✔
2639
              "legnth argument to bind foreign must be offset");
2640
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
259✔
2641
              "locus argument to bind foreign value must be a debug locus");
2642
}
259✔
2643

2644
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
194✔
2645
                                    ident_t scope, mir_type_t type,
2646
                                    mir_stamp_t stamp)
2647
{
2648
   mir_type_t pointer = mir_get_var_pointer(mu, type);
194✔
2649
   mir_value_t link = mir_add_linkage(mu, scope);
194✔
2650
   mir_value_t result = mir_build_2(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
194✔
2651
                                    locus, link);
2652

2653
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
194✔
2654
              "bind external argument must be locus");
2655

2656
   return result;
194✔
2657
}
2658

2659
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
8,651✔
2660
{
2661
   mir_type_t type = MIR_NULL_TYPE;
8,651✔
2662
   if (hops == 0)
8,651✔
2663
      type = mir_self_type(mu);
986✔
2664
   else {
2665
      mir_shape_t *s = mu->parent;
7,665✔
2666
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
7,935✔
2667

2668
      if (s != NULL) type = s->type;
7,665✔
2669
   }
2670

2671
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
8,651✔
2672
                                    MIR_NULL_STAMP, mir_enum(hops));
8,651✔
2673

2674
   MIR_ASSERT(hops >= 0, "invalid hop count");
8,651✔
2675
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
8,651✔
2676

2677
   return result;
8,651✔
2678
}
2679

2680
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
45,544✔
2681
{
2682
   mir_type_t type = MIR_NULL_TYPE;
45,544✔
2683
   mir_value_t link = MIR_NULL_VALUE;
45,544✔
2684

2685
   mir_shape_t *s = mu->parent;
45,544✔
2686
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
56,067✔
2687

2688
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
45,544✔
2689
      type = s->slots[nth].pointer;
45,544✔
2690
      link = mir_add_linkage(mu, s->name);
45,544✔
2691
   }
2692

2693
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
45,544✔
2694
                                    mir_enum(hops), link, mir_enum(nth));
2695

2696
   MIR_ASSERT(hops > 0, "invalid hop count");
45,544✔
2697
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
45,544✔
2698

2699
   return result;
45,544✔
2700
}
2701

2702
void mir_build_sched_event(mir_unit_t *mu, mir_value_t signal,
5,813✔
2703
                           mir_value_t count)
2704
{
2705
   mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,813✔
2706
               signal, count);
2707

2708
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
5,813✔
2709
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
5,813✔
2710
}
5,813✔
2711

2712
void mir_build_clear_event(mir_unit_t *mu, mir_value_t signal,
499✔
2713
                           mir_value_t count)
2714
{
2715
   mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
499✔
2716
               signal, count);
2717

2718
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
499✔
2719
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
499✔
2720
}
499✔
2721

2722
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
45✔
2723
                                    mir_value_t context, mir_value_t locus,
2724
                                    mir_value_t bounds)
2725
{
2726
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
45✔
2727

2728
   mir_value_t result;
45✔
2729
   if (mir_is_null(bounds))
45✔
2730
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
39✔
2731
                           value, context, locus);
2732
   else
2733
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
6✔
2734
                           value, context, locus, bounds);
2735

2736
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
45✔
2737
              "invalid reflect value context argument");
2738
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2739
              "locus argument to reflect value must be a debug locus");
2740

2741
   return result;
45✔
2742
}
2743

2744
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
42✔
2745
                                      mir_value_t locus, mir_value_t bounds)
2746
{
2747
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
42✔
2748

2749
   mir_value_t result;
42✔
2750
   if (mir_is_null(bounds))
42✔
2751
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
42✔
2752
                           context, locus);
2753
   else
UNCOV
2754
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
×
2755
                           context, locus, bounds);
2756

2757
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
42✔
2758
              "invalid reflect subtype context argument");
2759
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
42✔
2760
              "locus argument to reflect subtype must be a debug locus");
2761

2762
   return result;
42✔
2763
}
2764

2765
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
14,006✔
2766
                      mir_value_t length, mir_value_t severity,
2767
                      mir_value_t locus, mir_value_t hint_left,
2768
                      mir_value_t hint_right)
2769
{
2770
   int64_t value_const;
14,006✔
2771
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
14,006✔
UNCOV
2772
      mir_comment(mu, "Always true assertion");
×
UNCOV
2773
      return;
×
2774
   }
2775

2776
   if (mir_is_null(hint_left))
14,006✔
2777
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,249✔
2778
                  value, severity, message, length, locus);
2779
   else {
2780
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
11,514✔
2781
                                     MIR_NULL_STAMP, 7);
5,757✔
2782
      mir_set_arg(mu, n, 0, value);
5,757✔
2783
      mir_set_arg(mu, n, 1, severity);
5,757✔
2784
      mir_set_arg(mu, n, 2, message);
5,757✔
2785
      mir_set_arg(mu, n, 3, length);
5,757✔
2786
      mir_set_arg(mu, n, 4, locus);
5,757✔
2787
      mir_set_arg(mu, n, 5, hint_left);
5,757✔
2788
      mir_set_arg(mu, n, 6, hint_right);
5,757✔
2789

2790
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
5,757✔
2791
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
5,757✔
2792
   }
2793

2794
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,006✔
2795
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
14,006✔
2796
              "message parameter to assert is not a pointer");
2797
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,006✔
2798
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
14,006✔
2799
              "locus argument to report must be a debug locus");
2800
}
2801

2802
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,244✔
2803
                      mir_value_t severity, mir_value_t locus)
2804
{
2805
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,244✔
2806
               severity, message, length, locus);
2807

2808
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,244✔
2809
              "message parameter to report is not a pointer");
2810
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,244✔
2811
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,244✔
2812
              "locus argument to report must be a debug locus");
2813
}
2,244✔
2814

2815
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
812✔
2816
{
2817
   mir_type_t type = mir_string_type(mu);
812✔
2818
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
812✔
2819
                                    MIR_NULL_STAMP, kind);
812✔
2820

2821
   MIR_ASSERT(mir_is_offset(mu, kind),
812✔
2822
              "kind argument to instance name must be offset");
2823

2824
   return result;
812✔
2825
}
2826

2827
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
768✔
2828
                           mir_value_t strong)
2829
{
2830
   if (mir_is_null(strong))
768✔
2831
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
750✔
2832
   else
2833
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
2834
                  state, strong);
2835

2836
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
768✔
2837
   MIR_ASSERT(mir_is_null(strong)
768✔
2838
              || mir_check_type(mu, strong, mir_bool_type(mu)),
2839
                "strong argument not is not boolean");
2840
}
768✔
2841

2842
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_value_t context,
1,355✔
2843
                              mir_type_t atype, mir_type_t rtype)
2844
{
2845
   mir_type_t ctype = mir_closure_type(mu, atype, rtype);
1,355✔
2846
   mir_value_t link = mir_add_linkage(mu, func);
1,355✔
2847

2848
   mir_value_t result = mir_build_2(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
1,355✔
2849
                                    link, context);
2850

2851
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
1,355✔
2852
              "invalid closure context argument");
2853

2854
   return result;
1,355✔
2855
}
2856

2857
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
983✔
2858
                                         mir_value_t closure, mir_value_t ileft,
2859
                                         mir_value_t nlits)
2860
{
2861
   mir_type_t rtype = mir_resolution_type(mu, type);
983✔
2862
   mir_value_t result = mir_build_3(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
983✔
2863
                                    MIR_NULL_STAMP, closure, ileft, nlits);
983✔
2864

2865
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
983✔
2866
              "first argument to resolution wrapper must be closure");
2867

2868
   return result;
983✔
2869
}
2870

2871
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
65,871✔
2872
{
2873
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
65,871✔
2874
                                  MIR_NULL_STAMP, 0);
65,871✔
2875
   n->locus = obj;
65,871✔
2876

2877
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
65,871✔
2878
}
2879

2880
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
46,649✔
2881
{
2882
   mir_type_t from = mir_get_type(mu, value);
46,649✔
2883
   if (mir_equals(from, type))
46,649✔
2884
      return value;
46,649✔
2885

2886
   const mir_class_t class = mir_get_class(mu, type);
46,169✔
2887
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
46,169✔
2888

2889
   int64_t cval;
46,169✔
2890
   if (integral && mir_get_const(mu, value, &cval))
46,169✔
2891
      return mir_const(mu, type, cval);
413✔
2892

2893
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type,
45,756✔
2894
                                    MIR_NULL_STAMP, value);
45,756✔
2895

2896
#ifdef DEBUG
2897
   static const mir_class_t allowed[][2] = {
45,756✔
2898
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
2899
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
2900
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
2901
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
2902
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
2903
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
2904
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
2905
   };
2906

2907
   if (value.tag == MIR_TAG_CONST)
45,756✔
2908
      return result;
56✔
2909

2910
   const mir_class_t from_k = mir_get_class(mu, from);
45,700✔
2911

2912
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
83,471✔
2913
      if (from_k == allowed[i][0] && class == allowed[i][1])
83,471✔
2914
         return result;
45,700✔
2915
   }
2916

UNCOV
2917
   MIR_ASSERT(false, "invalid type conversion in cast");
×
2918
#else
2919
   return result;
2920
#endif
2921
}
2922

2923
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
×
2924
{
2925
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
2926

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