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

nickg / nvc / 13738584171

08 Mar 2025 12:57PM UTC coverage: 92.236% (-0.05%) from 92.281%
13738584171

push

github

nickg
Add a simple pointer provenance tracking scheme

52 of 53 new or added lines in 3 files covered. (98.11%)

230 existing lines in 7 files now uncovered.

68028 of 73754 relevant lines covered (92.24%)

433200.43 hits per line

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

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

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

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

50
   return b;
134,945✔
51
}
52

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

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

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

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

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

75
void mir_set_loc(mir_unit_t *mu, const loc_t *loc)
1,538,857✔
76
{
77
   mu->cursor.loc = *loc;
1,538,857✔
78
}
1,538,857✔
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,334✔
113
{
114
   return mu->blocks.count;
89,334✔
115
}
116

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

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

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

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

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

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

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

160
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
2,304,091✔
161
{
162
   switch (node.tag) {
2,304,091✔
163
   case MIR_TAG_NODE:
2,281,101✔
164
      return mir_node_data(mu, node)->op;
2,281,101✔
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,526✔
171
{
172
   return &(mir_node_data(mu, node)->loc);
1,132,526✔
173
}
174

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

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

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

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

204
   param_data_t pd = {
29,331✔
205
      .name  = name,
206
      .type  = type,
207
      .stamp = stamp,
208
   };
209
   APUSH(mu->params, pd);
29,331✔
210

211
   return p;
29,331✔
212
}
213

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

219
   mir_mem_t mem = MIR_MEM_STACK;
48,691✔
220
   if (flags & MIR_VAR_HEAP)
48,691✔
221
      mem = MIR_MEM_LOCAL;
1,040✔
222

223
   var_data_t vd = {
97,382✔
224
      .name    = name,
225
      .type    = type,
226
      .pointer = mir_get_var_pointer(mu, type),
48,691✔
227
      .stamp   = mir_pointer_stamp(mu, mem, stamp),
48,691✔
228
      .flags   = flags,
229
   };
230
   APUSH(mu->vars, vd);
48,691✔
231

232
   return v;
48,691✔
233
}
234

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

248
static inline node_id_t mir_node_id(mir_unit_t *mu, node_data_t *n)
1,058,065✔
249
{
250
   assert(n >= mu->nodes && n < mu->nodes + mu->num_nodes);
1,058,065✔
251
   return n - mu->nodes;
1,058,065✔
252
}
253

254
static node_data_t *mir_alloc_node(mir_unit_t *mu)
1,094,926✔
255
{
256
   assert(!mir_is_null(mu->cursor.block));
1,094,926✔
257

258
   node_data_t *n;
1,094,926✔
259
   block_data_t *bd = mir_block_data(mu, mu->cursor.block);
1,094,926✔
260
   if (mu->cursor.pos >= bd->num_nodes) {
1,094,926✔
261
      // Append new node
262
      if (bd->num_nodes == bd->max_nodes) {
1,094,919✔
263
         bd->max_nodes = MAX(4, bd->num_nodes * 2);
258,705✔
264
         bd->nodes = xrealloc_array(bd->nodes, bd->max_nodes,
258,705✔
265
                                    sizeof(node_id_t));
266
      }
267

268
      if (mu->num_nodes == mu->max_nodes) {
1,094,919✔
269
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
92,928✔
270
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
92,928✔
271
                                    sizeof(node_data_t));
272
      }
273

274
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
1,094,919✔
275
      n = &(mu->nodes[mu->num_nodes++]);
1,094,919✔
276
   }
277
   else {
278
      n = &(mu->nodes[bd->nodes[mu->cursor.pos]]);
7✔
279
      assert(n->op == _MIR_DELETED_OP);
7✔
280
   }
281

282
   return n;
1,094,926✔
283
}
284

285
static size_t mir_spill_args(mir_unit_t *mu, unsigned num)
75,710✔
286
{
287
   if (mu->num_argspill + num > mu->max_argspill) {
75,710✔
288
      mu->max_argspill = MAX(16, MAX(mu->num_argspill + num,
34,076✔
289
                                     mu->max_argspill * 2));
290
      mu->argspill = xrealloc_array(mu->argspill, mu->max_argspill,
34,076✔
291
                                    sizeof(mir_value_t));
292
   }
293

294
   const size_t off = mu->num_argspill;
75,710✔
295
   mu->num_argspill += num;
75,710✔
296
   return off;
75,710✔
297
}
298

299
static node_data_t *mir_add_node(mir_unit_t *mu, mir_op_t op, mir_type_t type,
1,094,926✔
300
                                 mir_stamp_t stamp, unsigned nargs)
301
{
302
   node_data_t *n = mir_alloc_node(mu);
1,094,926✔
303
   n->loc   = mu->cursor.loc;
1,094,926✔
304
   n->op    = op;
1,094,926✔
305
   n->type  = type;
1,094,926✔
306
   n->stamp = stamp;
1,094,926✔
307
   n->nargs = nargs;
1,094,926✔
308

309
   if (nargs > MIR_INLINE_ARGS)
1,094,926✔
310
      n->spilloff = mir_spill_args(mu, nargs);
75,710✔
311

312
   return n;
1,094,926✔
313
}
314

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

322
static mir_value_t mir_build_1(mir_unit_t *mu, mir_op_t op, mir_type_t type,
359,066✔
323
                               mir_stamp_t stamp, mir_value_t arg)
324
{
325
   node_data_t *n = mir_add_node(mu, op, type, stamp, 1);
359,066✔
326
   n->args[0] = arg;
359,066✔
327

328
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
359,066✔
329
}
330

331
static mir_value_t mir_build_2(mir_unit_t *mu, mir_op_t op, mir_type_t type,
286,764✔
332
                               mir_stamp_t stamp, mir_value_t arg1,
333
                               mir_value_t arg2)
334
{
335
   STATIC_ASSERT(MIR_INLINE_ARGS >= 2);
286,764✔
336

337
   node_data_t *n = mir_add_node(mu, op, type, stamp, 2);
286,764✔
338
   n->args[0] = arg1;
286,764✔
339
   n->args[1] = arg2;
286,764✔
340

341
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
286,764✔
342
}
343

344
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
176,367✔
345
                               mir_stamp_t stamp, mir_value_t arg1,
346
                               mir_value_t arg2, mir_value_t arg3)
347
{
348
   STATIC_ASSERT(MIR_INLINE_ARGS >= 3);
176,367✔
349

350
   node_data_t *n = mir_add_node(mu, op, type, stamp, 3);
176,367✔
351
   n->args[0] = arg1;
176,367✔
352
   n->args[1] = arg2;
176,367✔
353
   n->args[2] = arg3;
176,367✔
354

355
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
176,367✔
356
}
357

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

365
   node_data_t *n = mir_add_node(mu, op, type, stamp, 4);
2,991✔
366
   n->args[0] = arg1;
2,991✔
367
   n->args[1] = arg2;
2,991✔
368
   n->args[2] = arg3;
2,991✔
369
   n->args[3] = arg4;
2,991✔
370

371
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,991✔
372
}
373

374
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
30,625✔
375
                               mir_stamp_t stamp, mir_value_t arg1,
376
                               mir_value_t arg2, mir_value_t arg3,
377
                               mir_value_t arg4, mir_value_t arg5)
378
{
379
   node_data_t *n = mir_add_node(mu, op, type, stamp, 5);
30,625✔
380
   n->nargs = 5;
30,625✔
381

382
   STATIC_ASSERT(MIR_INLINE_ARGS < 5);
30,625✔
383

384
   mu->argspill[n->spilloff + 0] = arg1;
30,625✔
385
   mu->argspill[n->spilloff + 1] = arg2;
30,625✔
386
   mu->argspill[n->spilloff + 2] = arg3;
30,625✔
387
   mu->argspill[n->spilloff + 3] = arg4;
30,625✔
388
   mu->argspill[n->spilloff + 4] = arg5;
30,625✔
389

390
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,625✔
391
}
392

393
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
19,784✔
394
                               mir_stamp_t stamp, mir_value_t arg1,
395
                               mir_value_t arg2, mir_value_t arg3,
396
                               mir_value_t arg4, mir_value_t arg5,
397
                               mir_value_t arg6)
398
{
399
   node_data_t *n = mir_add_node(mu, op, type, stamp, 6);
19,784✔
400

401
   STATIC_ASSERT(MIR_INLINE_ARGS < 6);
19,784✔
402

403
   mu->argspill[n->spilloff + 0] = arg1;
19,784✔
404
   mu->argspill[n->spilloff + 1] = arg2;
19,784✔
405
   mu->argspill[n->spilloff + 2] = arg3;
19,784✔
406
   mu->argspill[n->spilloff + 3] = arg4;
19,784✔
407
   mu->argspill[n->spilloff + 4] = arg5;
19,784✔
408
   mu->argspill[n->spilloff + 5] = arg6;
19,784✔
409

410
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
19,784✔
411
}
412

413
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
119,630✔
414
{
415
   for (int i = 0; i < mu->linkage.count; i++) {
323,787✔
416
      if (mu->linkage.items[i] == ident)
257,827✔
417
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
53,670✔
418
   }
419

420
   mir_value_t link = { .tag = MIR_TAG_LINKAGE, .id = mu->linkage.count };
65,960✔
421

422
   APUSH(mu->linkage, ident);
65,960✔
423

424
   return link;
65,960✔
425
}
426

427
void mir_set_arg(mir_unit_t *mu, node_data_t *n, unsigned nth,
1,478,175✔
428
                 mir_value_t value)
429
{
430
   assert(nth < n->nargs);
1,478,175✔
431

432
   if (n->nargs <= MIR_INLINE_ARGS)
1,478,175✔
433
      n->args[nth] = value;
254,868✔
434
   else {
435
      assert(n->spilloff < mu->num_argspill);
1,223,307✔
436
      mu->argspill[n->spilloff + nth] = value;
1,223,307✔
437
   }
438
}
1,478,175✔
439

440
node_data_t *mir_node_data(mir_unit_t *mu, mir_value_t value)
9,630,672✔
441
{
442
   assert(value.tag == MIR_TAG_NODE);
9,630,672✔
443
   assert(value.id < mu->num_nodes);
9,630,672✔
444

445
   return &(mu->nodes[value.id]);
9,630,672✔
446
}
447

448
const param_data_t *mir_param_data(mir_unit_t *mu, mir_value_t value)
149,207✔
449
{
450
   assert(value.tag == MIR_TAG_PARAM);
149,207✔
451
   return AREF(mu->params, value.id);
149,207✔
452
}
453

454
const var_data_t *mir_var_data(mir_unit_t *mu, mir_value_t value)
293,644✔
455
{
456
   assert(value.tag == MIR_TAG_VAR);
293,644✔
457
   return AREF(mu->vars, value.id);
293,644✔
458
}
459

460
#ifdef DEBUG
461
void mir_comment(mir_unit_t *mu, const char *fmt, ...)
8✔
462
{
463
   va_list ap;
8✔
464
   va_start(ap, fmt);
8✔
465

466
   if (mu->comments == NULL)
8✔
467
      mu->comments = tb_new();
5✔
468

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

471
   tb_vprintf(mu->comments, fmt, ap);
8✔
472
   tb_append(mu->comments, '\0');
8✔
473

474
   va_end(ap);
8✔
475

476
   mir_build_1(mu, MIR_OP_COMMENT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
8✔
477
}
8✔
478
#endif
479

480
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
3,187,201✔
481
{
482
   switch (value.tag) {
3,187,201✔
483
   case MIR_TAG_CONST:
2,744,650✔
484
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
2,744,650✔
485
      return true;
2,744,650✔
486
   case MIR_TAG_ENUM:
196,538✔
487
      *result = value.id;
196,538✔
488
      return true;
196,538✔
489
   case MIR_TAG_NODE:
240,961✔
490
      {
491
         const node_data_t *n = mir_node_data(mu, value);
240,961✔
492
         if (n->op == MIR_OP_CONST) {
240,961✔
493
            *result = n->iconst;
7,136✔
494
            return true;
7,136✔
495
         }
496
         else
497
            return false;
498
      }
499
   default:
500
      return false;
501
   }
502
}
503

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

522
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
2,188,255✔
523
{
524
   switch (value.tag) {
2,188,255✔
525
   case MIR_TAG_NODE:
1,806,111✔
526
      return mir_node_data(mu, value)->type;
1,806,111✔
527
   case MIR_TAG_PARAM:
138,622✔
528
      return mir_param_data(mu, value)->type;
138,622✔
529
   case MIR_TAG_VAR:
139,120✔
530
      return mir_var_data(mu, value)->pointer;
139,120✔
531
   default:
104,402✔
532
      return MIR_NULL_TYPE;
104,402✔
533
   }
534
}
535

536
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
414,230✔
537
{
538
   switch (value.tag) {
414,230✔
539
   case MIR_TAG_NODE:
319,546✔
540
      return mir_node_data(mu, value)->stamp;
319,546✔
541
   case MIR_TAG_PARAM:
10,572✔
542
      return mir_param_data(mu, value)->stamp;
10,572✔
543
   case MIR_TAG_VAR:
39,268✔
544
      return mir_var_data(mu, value)->stamp;
39,268✔
545
   case MIR_TAG_CONST:
44,844✔
546
      {
547
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
44,844✔
548
         return mir_int_stamp(mu, ival, ival);
44,844✔
549
      }
UNCOV
550
   default:
×
UNCOV
551
      return MIR_NULL_STAMP;
×
552
   }
553
}
554

555
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value)
7,797✔
556
{
557
   mir_type_t type = mir_get_type(mu, value);
7,797✔
558
   if (mir_is_null(type))
7,797✔
559
      return MIR_MEM_NONE;
560

561
   switch (mir_type_data(mu, type)->class) {
6,511✔
562
   case MIR_TYPE_UARRAY:
563
   case MIR_TYPE_CARRAY:
564
   case MIR_TYPE_RECORD:
565
   case MIR_TYPE_POINTER:
566
   case MIR_TYPE_ACCESS:
567
      break;
5,063✔
568
   default:
569
      return MIR_MEM_NONE;
570
   }
571

572
   mir_stamp_t stamp = mir_get_stamp(mu, value);
5,063✔
573
   if (mir_is_null(stamp))
5,063✔
574
      return MIR_MEM_TOP;
575

576
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
771✔
577
   assert(sd->kind == MIR_STAMP_POINTER);
771✔
578

579
   return sd->u.pointer.memory;
771✔
580
}
581

582
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
154,277✔
583
{
584
   switch (value.tag) {
154,277✔
585
   case MIR_TAG_PARAM:
13✔
586
      return mir_param_data(mu, value)->name;
13✔
587
   case MIR_TAG_VAR:
35,094✔
588
      return mir_var_data(mu, value)->name;
35,094✔
589
   case MIR_TAG_LINKAGE:
119,170✔
590
      return AGET(mu->linkage, value.id);
119,170✔
591
   case MIR_TAG_NULL:
×
592
      return mu->name;
×
593
   default:
594
      return NULL;
595
   }
596
}
597

598
void mir_set_result(mir_unit_t *mu, mir_type_t type)
20,553✔
599
{
600
   assert(mu->kind == MIR_UNIT_FUNCTION || mu->kind == MIR_UNIT_THUNK);
20,553✔
601
   mu->result = type;
20,553✔
602
}
20,553✔
603

604
mir_type_t mir_get_result(mir_unit_t *mu)
21,551✔
605
{
606
   return mu->result;
21,551✔
607
}
608

609
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
65,860✔
610
{
611
   switch (value.tag) {
65,860✔
612
   case MIR_TAG_NODE:
65,860✔
613
      {
614
         node_data_t *n = mir_node_data(mu, value);
65,860✔
615
         assert(n->op == MIR_OP_LOCUS);
65,860✔
616
         return n->locus;
65,860✔
617
      }
618
      break;
×
619
   default:
×
620
      should_not_reach_here();
621
   }
622
}
623

624
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value)
31,475✔
625
{
626
   switch (value.tag) {
31,475✔
627
   case MIR_TAG_VAR:
31,475✔
628
      return mir_var_data(mu, value)->flags;
31,475✔
629
   default:
630
      return 0;
631
   }
632
}
633

634
mir_type_t mir_get_var_type(mir_unit_t *mu, mir_value_t value)
48,687✔
635
{
636
   switch (value.tag) {
48,687✔
637
   case MIR_TAG_VAR:
48,687✔
638
      return mir_var_data(mu, value)->type;
48,687✔
639
   default:
×
640
      return MIR_NULL_TYPE;
×
641
   }
642
}
643

644
bool mir_is_integral(mir_unit_t *mu, mir_value_t value)
79,958✔
645
{
646
   if (value.tag == MIR_TAG_CONST)
79,958✔
647
      return true;
648

649
   mir_type_t type = mir_get_type(mu, value);
34,837✔
650
   if (mir_is_null(type))
34,837✔
651
      return false;
652

653
   switch (mir_type_data(mu, type)->class) {
34,837✔
654
   case MIR_TYPE_INT:
655
   case MIR_TYPE_OFFSET:
656
      return true;
657
   default:
5,941✔
658
      return false;
5,941✔
659
   }
660
}
661

662
bool mir_is_scalar(mir_unit_t *mu, mir_value_t value)
25,446✔
663
{
664
   if (value.tag == MIR_TAG_CONST)
25,446✔
665
      return true;
666

667
   mir_type_t type = mir_get_type(mu, value);
15,675✔
668
   if (mir_is_null(type))
15,675✔
669
      return false;
670

671
   switch (mir_type_data(mu, type)->class) {
15,675✔
672
   case MIR_TYPE_INT:
673
   case MIR_TYPE_OFFSET:
674
   case MIR_TYPE_REAL:
675
   case MIR_TYPE_ACCESS:
676
      return true;
677
   default:
68✔
678
      return false;
68✔
679
   }
680
}
681

682
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
129,020✔
683
{
684
   if (value.tag == MIR_TAG_CONST)
129,020✔
685
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
32,217✔
686
   else
687
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
96,803✔
688
}
689

690
bool mir_is_time(mir_unit_t *mu, mir_value_t value)
5,303✔
691
{
692
   if (value.tag == MIR_TAG_CONST)
5,303✔
693
      return true;
694

695
   return mir_equals(mir_get_type(mu, value), mir_time_type(mu));
261✔
696
}
697

698
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class)
536,836✔
699
{
700
   mir_type_t type = mir_get_type(mu, value);
536,836✔
701
   if (mir_is_null(type))
536,836✔
702
      return false;
703

704
   return mir_type_data(mu, type)->class == class;
512,927✔
705
}
706

707
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class)
197✔
708
{
709
   mir_type_t type = mir_get_type(mu, value);
197✔
710
   if (mir_is_null(type))
197✔
711
      return false;
712

713
   const type_data_t *td = mir_type_data(mu, type);
197✔
714
   if (td->class != MIR_TYPE_POINTER)
197✔
715
      return false;
716

717
   return mir_type_data(mu, td->u.pointer)->class == class;
197✔
718
}
719

720
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
100,408✔
721
{
722
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
100,408✔
723
}
724

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

730
   return mir_is(mu, value, MIR_TYPE_OFFSET);
37,331✔
731
}
732

733
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
1,168,957✔
734
{
735
   switch (value.tag) {
1,168,957✔
736
   case MIR_TAG_CONST:
737
      return true;
738
   case MIR_TAG_NODE:
17,104✔
739
      {
740
         node_data_t *n = mir_node_data(mu, value);
17,104✔
741
         switch (n->op) {
17,104✔
742
         case MIR_OP_CONST:
743
         case MIR_OP_CONST_REAL:
744
         case MIR_OP_CONST_ARRAY:
745
         case MIR_OP_CONST_REP:
746
         case MIR_OP_CONST_RECORD:
747
         case MIR_OP_NULL:
748
            return true;
749
         default:
×
750
            return false;
×
751
         }
752
      }
753
   default:
×
754
      return false;
×
755
   }
756
}
757

758
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
5✔
759
{
760
   const mir_mem_t a_mem = mir_get_mem(mu, a);
5✔
761
   if (a_mem == MIR_MEM_NONE)
5✔
762
      return false;
763

764
   if (mir_equals(a, b))
5✔
765
      return true;
766

767
   const mir_mem_t b_mem = mir_get_mem(mu, b);
5✔
768
   if (b_mem == MIR_MEM_NONE)
5✔
769
      return false;
770

771
   if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
5✔
772
      // Aliasing is only relevant in the presence of mutability
773
      return false;
774
   }
775

776
   return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
3✔
777
}
778

779
#ifdef DEBUG
780
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
1,210,372✔
781
{
782
   if (value.tag == MIR_TAG_CONST) {
1,210,372✔
783
      const mir_class_t class = mir_type_data(mu, type)->class;
1,151,276✔
784
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
1,151,276✔
785
   }
786
   else
787
      return mir_equals(mir_get_type(mu, value), type);
59,096✔
788
}
789
#endif
790

791
mir_value_t mir_enum(unsigned value)
221,434✔
792
{
793
   assert(value < MIR_ID_MAX);
221,434✔
794
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
221,434✔
795
}
796

797
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
338,032✔
798
{
799
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
338,032✔
800
      const unsigned biased = value + SMALL_CONST_BIAS;
331,259✔
801
      return (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
331,259✔
802
   }
803
   else {
804
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
6,773✔
805
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
6,773✔
806
      n->iconst = value;
6,773✔
807

808
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
6,773✔
809
   }
810
}
811

812
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
20,901✔
813
{
814
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
20,901✔
815
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
20,901✔
816
   n->dconst = value;
20,901✔
817

818
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
20,901✔
819
}
820

821
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
21,167✔
822
                            const mir_value_t *values, size_t count)
823
{
824
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
42,334✔
825
                                 MIR_NULL_STAMP, count);
21,167✔
826

827
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
21,167✔
828
                "constant array must have constrained array type");
829
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
21,167✔
830
              "have %zd", mir_get_size(mu, type), count);
831

832
   mir_type_t elem = mir_get_elem(mu, type);
21,167✔
833

834
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
21,167✔
835
   int64_t low = INT64_MAX, high = INT64_MIN;
21,167✔
836
   for (size_t i = 0; i < count; i++) {
1,180,111✔
837
      mir_set_arg(mu, n, i, values[i]);
1,158,944✔
838

839
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
1,158,944✔
840
                 "element %zd has wrong type", i);
841
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
1,158,944✔
842

843
      int64_t cval;
1,158,944✔
844
      if (integral && mir_get_const(mu, values[i], &cval)) {
1,158,944✔
845
         low = MIN(low, cval);
1,143,372✔
846
         high = MAX(high, cval);
1,143,372✔
847
      }
848
   }
849

850
   mir_stamp_t stamp = MIR_NULL_STAMP;
21,167✔
851
   if (integral && low <= high)
21,167✔
852
      stamp = mir_int_stamp(mu, low, high);
20,502✔
853

854
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
21,167✔
855

856
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
21,167✔
857
}
858

859
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
279✔
860
                                mir_value_t value, unsigned rep)
861
{
862
   mir_stamp_t stamp = mir_get_stamp(mu, value);
279✔
863
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
279✔
864
                                    value, mir_enum(rep));
865

866
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
279✔
867
              "constant array must have constrained array class");
868
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
279✔
869

870
   return result;
279✔
871
}
872

873
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,139✔
874
                             const mir_value_t *values, size_t count)
875
{
876
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
4,278✔
877
                                 MIR_NULL_STAMP, count);
2,139✔
878

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

881
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,139✔
882
              "const record must have record type");
883
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,139✔
884
              td->u.record.count, count);
885

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

889
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
5,412✔
890
                               td->u.record.fields[i]),
891
                 "wrong type for element %d", i);
892
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
5,412✔
893
   }
894

895
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,139✔
896
}
897

898
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
38,635✔
899
                                   mir_value_t left, mir_value_t right,
900
                                   mir_value_t locus, mir_stamp_t stamp)
901
{
902
   mir_value_t result;
38,635✔
903
   if (mir_is_null(locus))
38,635✔
904
      result = mir_build_2(mu, op, type, stamp, left, right);
33,827✔
905
   else
906
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
4,808✔
907

908
#ifdef DEBUG
909
   mir_type_t ltype = mir_get_type(mu, left);
38,635✔
910
   mir_type_t rtype = mir_get_type(mu, right);
38,635✔
911
#endif
912

913
   MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
38,635✔
914
              || mir_equals(ltype, rtype),
915
              "arguments to %s are not the same type", mir_op_string(op));
916
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
38,635✔
917
              "locus argument to %s is not a locus", mir_op_string(op));
918

919
   return result;
38,635✔
920
}
921

922
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
14,861✔
923
                                    mir_type_t type, mir_value_t left,
924
                                    mir_value_t right, mir_value_t locus)
925
{
926
   int64_t lval, rval, cval;
14,861✔
927
   const bool lconst = mir_get_const(mu, left, &lval);
14,861✔
928
   const bool rconst = mir_get_const(mu, right, &rval);
14,861✔
929

930
   if (lconst && lval == 0)
14,861✔
931
      return right;
×
932
   else if (rconst && rval == 0)
14,861✔
933
      return left;
1✔
934
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
14,860✔
935
      return mir_const(mu, type, cval);
3✔
936

937
   double lreal, rreal;
14,857✔
938
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
14,857✔
939
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
14,857✔
940

941
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
14,857✔
942
      return right;
1✔
943
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
14,856✔
944
      return left;
2✔
945
   else if (lconst_real && rconst_real)
14,854✔
946
      return mir_const_real(mu, type, lreal + rreal);
4✔
947

948
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
14,850✔
949
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
14,850✔
950
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
14,850✔
951

952
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
14,850✔
953
}
954

955
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
12,948✔
956
                          mir_value_t right)
957
{
958
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
12,948✔
959
}
960

961
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
1,913✔
962
                               mir_value_t left, mir_value_t right,
963
                               mir_value_t locus)
964
{
965
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
1,913✔
966
}
967

968
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
20,126✔
969
                                    mir_type_t type, mir_value_t left,
970
                                    mir_value_t right, mir_value_t locus)
971
{
972
   int64_t lval, rval, cval;
20,126✔
973
   const bool lconst = mir_get_const(mu, left, &lval);
20,126✔
974
   const bool rconst = mir_get_const(mu, right, &rval);
20,126✔
975

976
   if (lconst && lval == 0)
20,126✔
977
      return right;
3✔
978
   else if (rconst && rval == 0)
20,123✔
979
      return left;
3✔
980
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
20,120✔
981
      return mir_const(mu, type, cval);
1✔
982
   else if (mir_equals(left, right))
20,119✔
983
      return mir_const(mu, type, 0);
159✔
984

985
   double lreal, rreal;
19,960✔
986
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
19,960✔
987
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
19,960✔
988

989
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
19,960✔
990
      return right;
×
991
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
19,960✔
992
      return left;
4✔
993
   else if (lconst_real && rconst_real)
19,956✔
994
      return mir_const_real(mu, type, lreal - rreal);
×
995

996
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
19,956✔
997
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
19,956✔
998
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
19,956✔
999

1000
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
19,956✔
1001
}
1002

1003
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
17,762✔
1004
                          mir_value_t right)
1005
{
1006
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
17,762✔
1007
}
1008

1009
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
2,039✔
1010
                               mir_value_t left, mir_value_t right,
1011
                               mir_value_t locus)
1012
{
1013
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
2,039✔
1014
}
1015

1016
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
7,481✔
1017
{
1018
   int64_t cval;
7,481✔
1019
   if (mir_get_const(mu, value, &cval))
7,481✔
1020
      return mir_const(mu, type, -cval);
1✔
1021

1022
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
7,480✔
1023
                                    MIR_NULL_STAMP, value);
7,480✔
1024

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

1027
   return result;
7,480✔
1028
}
1029

1030
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
556✔
1031
                               mir_value_t value, mir_value_t locus)
1032
{
1033
   int64_t cval;
556✔
1034
   if (mir_get_const(mu, value, &cval) && cval >= 0)
556✔
1035
      return mir_const(mu, type, -cval);
×
1036
   // TODO: check if stamp bounds are non-negative
1037

1038
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
556✔
1039
                                    MIR_NULL_STAMP, value, locus);
556✔
1040

1041
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
556✔
1042
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
556✔
1043
              "locus argument must be debug locus");
1044

1045
   return result;
556✔
1046
}
1047

1048
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
233✔
1049
{
1050
   int64_t lconst;
233✔
1051
   if (mir_get_const(mu, value, &lconst))
233✔
1052
      return mir_const(mu, type, llabs(lconst));
×
1053

1054
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
233✔
1055
                                    value);
1056

1057
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
233✔
1058

1059
   return result;
233✔
1060
}
1061

1062
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
2,250✔
1063
                                    mir_type_t type, mir_value_t left,
1064
                                    mir_value_t right, mir_value_t locus)
1065
{
1066
   int64_t lval, rval, cval;
2,250✔
1067
   const bool lconst = mir_get_const(mu, left, &lval);
2,250✔
1068
   const bool rconst = mir_get_const(mu, right, &rval);
2,250✔
1069

1070
   if (lconst && lval == 0)
2,250✔
1071
      return left;
×
1072
   else if (rconst && rval == 0)
2,250✔
1073
      return right;
×
1074
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
2,250✔
1075
      return mir_const(mu, type, cval);
×
1076

1077
   double lreal, rreal;
2,250✔
1078
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
2,250✔
1079
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
2,250✔
1080

1081
   if (lconst_real && rconst_real)
2,250✔
1082
      return mir_const_real(mu, type, lreal * rreal);
158✔
1083

1084
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
2,092✔
1085
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
2,092✔
1086
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
2,092✔
1087

1088
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
2,092✔
1089
}
1090

1091
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
2,250✔
1092
                          mir_value_t right)
1093
{
1094
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
2,250✔
1095
}
1096

1097
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
325✔
1098
                               mir_value_t left, mir_value_t right,
1099
                               mir_value_t locus)
1100
{
1101
   return mir_build_sub_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
325✔
1102
}
1103

1104
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
885✔
1105
                          mir_value_t right)
1106
{
1107
   int64_t lval, rval;
885✔
1108
   const bool lconst = mir_get_const(mu, left, &lval);
885✔
1109
   const bool rconst = mir_get_const(mu, right, &rval);
885✔
1110

1111
   if (lconst && rconst && rval != 0)
885✔
1112
      return mir_const(mu, type, lval / rval);
×
1113
   else if (rconst && rval == 1)
885✔
1114
      return left;
×
1115

1116
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
885✔
1117
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
885✔
1118
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
885✔
1119

1120
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
885✔
1121
                          MIR_NULL_VALUE, stamp);
885✔
1122
}
1123

1124
mir_value_t mir_build_rem(mir_unit_t *mu, mir_type_t type, mir_value_t left,
97✔
1125
                          mir_value_t right)
1126
{
1127
   int64_t lval, rval;
97✔
1128
   const bool lconst = mir_get_const(mu, left, &lval);
97✔
1129
   const bool rconst = mir_get_const(mu, right, &rval);
97✔
1130

1131
   if (lconst && rconst && lval > 0 && rval > 0)
97✔
1132
      return mir_const(mu, type, lval % rval);
1✔
1133

1134
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
96✔
1135
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
96✔
1136
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
96✔
1137

1138
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
96✔
1139
                          MIR_NULL_VALUE, stamp);
96✔
1140
}
1141

1142
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
153✔
1143
                          mir_value_t right)
1144
{
1145
   int64_t lval, rval;
153✔
1146
   const bool lconst = mir_get_const(mu, left, &lval);
153✔
1147
   const bool rconst = mir_get_const(mu, right, &rval);
153✔
1148

1149
   if (lconst && rconst && lval > 0 && rval > 0)
153✔
1150
      return mir_const(mu, type, lval % rval);
×
1151

1152
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
153✔
1153
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
153✔
1154

1155
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
153✔
1156
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
11✔
1157
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
11✔
1158

1159
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
11✔
1160
         // If both arguments are non-negative then rem is equivalent
1161
         // and cheaper to compute
1162
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1163
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1164
                                MIR_NULL_VALUE, stamp);
1✔
1165
      }
1166
   }
1167

1168
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
152✔
1169
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
152✔
1170
}
1171

1172
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
72✔
1173
                          mir_value_t right)
1174
{
1175
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
144✔
1176
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
72✔
1177
}
1178

1179
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
531✔
1180
                               mir_value_t left, mir_value_t right,
1181
                               mir_value_t locus)
1182
{
1183
   int64_t rconst;
531✔
1184
   if (mir_get_const(mu, right, &rconst)) {
531✔
1185
      if (rconst == 0)
435✔
1186
         return mir_const(mu, type, 1);
×
1187
      else if (rconst == 1)
435✔
1188
         return left;
×
1189
   }
1190

1191
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
531✔
1192
                                        locus, MIR_NULL_STAMP);
531✔
1193

1194
   MIR_ASSERT(mir_is_integral(mu, result),
531✔
1195
              "trapping exp may only be used with integer types");
1196

1197
   return result;
531✔
1198
}
1199

1200
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
6,494✔
1201
                                     mir_type_t type, mir_value_t left,
1202
                                     mir_value_t right)
1203
{
1204
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
6,494✔
1205

1206
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
6,494✔
1207
              mir_op_string(op));
1208
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
6,494✔
1209
              mir_op_string(op));
1210

1211
   return result;
6,494✔
1212
}
1213

1214
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
4,417✔
1215
{
1216
   int64_t lval, rval;
4,417✔
1217
   const bool lconst = mir_get_const(mu, left, &lval);
4,417✔
1218
   const bool rconst = mir_get_const(mu, right, &rval);
4,417✔
1219

1220
   mir_type_t t_bool = mir_bool_type(mu);
4,417✔
1221

1222
   if (lconst && rconst)
4,417✔
1223
      return mir_const(mu, t_bool, lval && rval);
3✔
1224
   else if (lconst)
4,415✔
1225
      return lval ? right : mir_const(mu, t_bool, 0);
×
1226
   else if (rconst)
4,415✔
1227
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1228

1229
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
4,413✔
1230
}
1231

1232
mir_value_t mir_build_nand(mir_unit_t *mu, mir_value_t left, mir_value_t right)
63✔
1233
{
1234
   int64_t lval, rval;
63✔
1235
   const bool lconst = mir_get_const(mu, left, &lval);
63✔
1236
   const bool rconst = mir_get_const(mu, right, &rval);
63✔
1237

1238
   mir_type_t t_bool = mir_bool_type(mu);
63✔
1239

1240
   if (lconst && rconst)
63✔
1241
      return mir_const(mu, t_bool, !(lval && rval));
1✔
1242

1243
   return mir_build_logical(mu, MIR_OP_NAND, t_bool, left, right);
62✔
1244
}
1245

1246
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
1,793✔
1247
{
1248
   int64_t lval, rval;
1,793✔
1249
   const bool lconst = mir_get_const(mu, left, &lval);
1,793✔
1250
   const bool rconst = mir_get_const(mu, right, &rval);
1,793✔
1251

1252
   mir_type_t t_bool = mir_bool_type(mu);
1,793✔
1253

1254
   if (lconst && rconst)
1,793✔
1255
      return mir_const(mu, t_bool, lval || rval);
3✔
1256
   else if (lconst)
1,791✔
1257
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1258
   else if (rconst)
1,790✔
1259
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1260

1261
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
1,789✔
1262
}
1263

1264
mir_value_t mir_build_nor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
64✔
1265
{
1266
   int64_t lval, rval;
64✔
1267
   const bool lconst = mir_get_const(mu, left, &lval);
64✔
1268
   const bool rconst = mir_get_const(mu, right, &rval);
64✔
1269

1270
   mir_type_t t_bool = mir_bool_type(mu);
64✔
1271

1272
   if (lconst && rconst)
64✔
1273
      return mir_const(mu, t_bool, !(lval || rval));
4✔
1274

1275
   return mir_build_logical(mu, MIR_OP_NOR, t_bool, left, right);
62✔
1276
}
1277

1278
mir_value_t mir_build_xor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
106✔
1279
{
1280
   int64_t lval, rval;
106✔
1281
   const bool lconst = mir_get_const(mu, left, &lval);
106✔
1282
   const bool rconst = mir_get_const(mu, right, &rval);
106✔
1283

1284
   mir_type_t t_bool = mir_bool_type(mu);
106✔
1285
   if (lconst && rconst)
106✔
1286
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1287
   else if (mir_equals(left, right))
105✔
1288
      return mir_const(mu, t_bool, 0);
1✔
1289

1290
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
104✔
1291
}
1292

1293
mir_value_t mir_build_xnor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
64✔
1294
{
1295
   int64_t lval, rval;
64✔
1296
   const bool lconst = mir_get_const(mu, left, &lval);
64✔
1297
   const bool rconst = mir_get_const(mu, right, &rval);
64✔
1298

1299
   mir_type_t t_bool = mir_bool_type(mu);
64✔
1300
   if (lconst && rconst)
64✔
1301
      return mir_const(mu, t_bool, !(lval ^ rval));
×
1302

1303
   return mir_build_logical(mu, MIR_OP_XNOR, t_bool, left, right);
64✔
1304
}
1305

1306
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
2,681✔
1307
{
1308
   mir_type_t t_bool = mir_bool_type(mu);
2,681✔
1309

1310
   int64_t cval;
2,681✔
1311
   if (mir_get_const(mu, value, &cval))
2,681✔
1312
      return mir_const(mu, t_bool, !cval);
2✔
1313

1314
   if (mir_get_op(mu, value) == MIR_OP_NOT)
2,679✔
1315
      return mir_get_arg(mu, value, 0);
31✔
1316

1317
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
2,648✔
1318
                                    MIR_NULL_STAMP, value);
2,648✔
1319

1320
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
2,648✔
1321

1322
   return result;
2,648✔
1323
}
1324

1325
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
33,558✔
1326
                          mir_value_t right)
1327
{
1328
   int64_t lval, rval;
33,558✔
1329
   const bool lconst = mir_get_const(mu, left, &lval);
33,558✔
1330
   const bool rconst = mir_get_const(mu, right, &rval);
33,558✔
1331

1332
   mir_type_t t_bool = mir_bool_type(mu);
33,558✔
1333

1334
   if (lconst && rconst) {
33,558✔
1335
      switch (cmp) {
13✔
1336
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1337
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
2✔
1338
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
2✔
1339
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
2✔
1340
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
2✔
1341
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
2✔
1342
      default: should_not_reach_here();
1343
      }
1344
   }
1345

1346
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
33,545✔
1347
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
33,545✔
1348
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
33,545✔
1349

1350
   int64_t sconst;
33,545✔
1351
   if (mir_stamp_const(mu, stamp, &sconst))
33,545✔
1352
      return mir_const(mu, t_bool, sconst);
2✔
1353

1354
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
33,543✔
1355
                                    stamp, mir_enum(cmp), left, right);
1356

1357
   MIR_ASSERT(mir_equals(mir_get_type(mu, left), mir_get_type(mu, left)),
33,543✔
1358
              "arguments to cmp are not the same type");
1359

1360
   return result;
33,543✔
1361
}
1362

1363
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
71,916✔
1364
{
1365
   mir_type_t type = mir_get_type(mu, dest);
71,916✔
1366
   mir_type_t pointed = mir_get_pointer(mu, type);
71,916✔
1367

1368
   mir_build_2(mu, MIR_OP_STORE, pointed, MIR_NULL_STAMP, dest, src);
71,916✔
1369

1370
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
71,916✔
1371
              "store destination is not a pointer or variable");
1372
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
71,916✔
1373
              "source and destination have different types");
1374
}
71,916✔
1375

1376
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
117,065✔
1377
{
1378
   mir_type_t type = mir_get_type(mu, value);
117,065✔
1379
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
117,065✔
1380
   mir_type_t pointed = mir_get_pointer(mu, type);
117,065✔
1381

1382
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
117,065✔
1383

1384
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
117,065✔
1385
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
117,065✔
1386
              "argument to load is not a pointer or variable");
1387

1388
   return result;
117,065✔
1389
}
1390

1391
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
15,883✔
1392
                    mir_value_t count)
1393
{
1394
   int64_t cval;
15,883✔
1395
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
15,883✔
1396
      return;
233✔
1397
   else if (mir_equals(dest, src))
15,883✔
1398
      return;
1399

1400
   mir_type_t dtype = mir_get_type(mu, dest);
15,650✔
1401
   mir_type_t elem = mir_get_pointer(mu, dtype);
15,650✔
1402

1403
   if (mir_is_null(count))
15,650✔
1404
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
1,781✔
1405
   else
1406
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
13,869✔
1407

1408
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
15,650✔
1409
              "destination type is not a pointer");
1410
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
15,650✔
1411
              "source type is not a pointer");
1412
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
15,650✔
1413
              "source and destination types do not match");
1414
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
15,650✔
1415
              "count is not offset type");
1416
}
1417

1418
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
5,549✔
1419
                   mir_value_t count)
1420
{
1421
   int64_t cval;
5,549✔
1422
   if (mir_get_const(mu, count, &cval) && cval == 0)
5,549✔
1423
      return;
×
1424

1425
   mir_type_t dtype = mir_get_type(mu, dest);
5,549✔
1426
   mir_type_t elem = mir_get_pointer(mu, dtype);
5,549✔
1427

1428
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
5,549✔
1429

1430
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
5,549✔
1431
              "destination type is not a pointer");
1432
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
5,549✔
1433
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
5,549✔
1434
}
1435

1436
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
7,239✔
1437
                            mir_value_t count)
1438
{
1439
   mir_type_t ptr = mir_pointer_type(mu, type);
7,239✔
1440
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
7,239✔
1441

1442
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
7,239✔
1443
              "alloc element type cannot be array");
1444
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
7,239✔
1445

1446
   return result;
7,239✔
1447
}
1448

1449
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
2,712✔
1450
{
1451
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, MIR_NULL_STAMP);
2,712✔
1452

1453
#ifdef DEBUG
1454
   const mir_class_t class = mir_get_class(mu, type);
2,712✔
1455
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
2,712✔
1456
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1457
              "null type must be file, access, context, or pointer");
1458
#endif
1459

1460
   return result;
2,712✔
1461
}
1462

1463
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
410✔
1464
                          mir_value_t count)
1465
{
1466
   mir_type_t access = mir_access_type(mu, type);
410✔
1467

1468
   mir_value_t result;
410✔
1469
   if (mir_is_null(count))
410✔
1470
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
87✔
1471
   else
1472
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
323✔
1473

1474
#ifdef DEBUG
1475
   const mir_class_t class = mir_get_class(mu, type);
410✔
1476
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
410✔
1477
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1478
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1479
              "new type must be int, real, record, access, or uarray");
1480
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
410✔
1481
              "new count must have offset type");
1482
#endif
1483

1484
   return result;
410✔
1485
}
1486

1487
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
1,507✔
1488
{
1489
   mir_type_t type = mir_get_type(mu, access);
1,507✔
1490
   mir_stamp_t stamp = mir_get_stamp(mu, access);
1,507✔
1491
   mir_type_t pointed = mir_get_pointer(mu, type);
1,507✔
1492
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
1,507✔
1493

1494
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
1,507✔
1495
              "argument to all must be access type");
1496

1497
   return result;
1,507✔
1498
}
1499

1500
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
22,587✔
1501
{
1502
   mir_type_t type = mir_get_type(mu, array);
22,587✔
1503
   mir_type_t pointer = mir_get_pointer(mu, type);
22,587✔
1504
   mir_stamp_t stamp = mir_get_stamp(mu, array);
22,587✔
1505

1506
   if (mir_is_null(pointer))
22,587✔
1507
      pointer = mir_pointer_type(mu, type);
1,639✔
1508

1509
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
22,587✔
1510
                                    pointer, stamp, array);
1511

1512
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
22,587✔
1513
              || mir_is(mu, array, MIR_TYPE_RECORD),
1514
              "argument to address of must be array or record");
1515

1516
   return result;
22,587✔
1517
}
1518

1519
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
32,378✔
1520
                                mir_value_t offset)
1521
{
1522
   mir_type_t type = mir_get_type(mu, array);
32,378✔
1523
   mir_stamp_t stamp = mir_get_stamp(mu, array);
32,378✔
1524

1525
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
32,378✔
1526
                                    array, offset);
1527

1528
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
32,378✔
1529
              "argument to array ref must be pointer or signal");
1530
   MIR_ASSERT(mir_is_offset(mu, offset),
32,378✔
1531
              "offset argument to array ref must be offset");
1532

1533
   return result;
32,378✔
1534
}
1535

1536
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
37,503✔
1537
                                 unsigned field)
1538
{
1539
   mir_type_t pointer = mir_get_type(mu, record);
37,503✔
1540

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

1543
   mir_type_t type = MIR_NULL_TYPE;
37,503✔
1544
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
37,503✔
1545
      type = td->u.record.fields[field + td->u.record.count];
37,503✔
1546

1547
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, MIR_NULL_STAMP,
37,503✔
1548
                                    record, mir_enum(field));
1549

1550
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
37,503✔
1551
              "record ref argument must be pointer to record");
1552
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
37,503✔
1553
              "record ref argument must be pointer to record");
1554
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
37,503✔
1555

1556
   return result;
37,503✔
1557
}
1558

1559
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
28,990✔
1560
                           const mir_dim_t *dims, int ndims)
1561
{
1562
   mir_type_t type = mir_get_type(mu, data);
28,990✔
1563
   mir_stamp_t stamp = mir_get_stamp(mu, data);
28,990✔
1564

1565
   const type_data_t *td = mir_type_data(mu, type);
28,990✔
1566
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
28,990✔
1567

1568
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
28,990✔
1569

1570
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
57,980✔
1571
                                  ndims * 3 + 1);
28,990✔
1572

1573
   mir_set_arg(mu, n, 0, data);
28,990✔
1574

1575
   for (int i = 0; i < ndims; i++) {
58,391✔
1576
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
29,401✔
1577
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
29,401✔
1578
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
29,401✔
1579
   }
1580

1581
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
28,990✔
1582
              "wrapped data is not pointer or signal");
1583

1584
   for (int i = 0; i < ndims; i++) {
58,391✔
1585
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
29,401✔
1586
                 "dimension %d left bound must be integral", i + 1);
1587
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
29,401✔
1588
                 "dimension %d right bound must be integral", i + 1);
1589
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
29,401✔
1590
                 "dimension %d direction must be bool", i + 1);
1591
   }
1592

1593
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
28,990✔
1594
}
1595

1596
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
26,227✔
1597
{
1598
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
26,227✔
1599
      return mir_get_arg(mu, array, 0);
1,978✔
1600

1601
   mir_type_t type = mir_get_type(mu, array);
24,249✔
1602
   mir_type_t pointer = mir_get_pointer(mu, type);
24,249✔
1603
   mir_stamp_t stamp = mir_get_stamp(mu, array);
24,249✔
1604

1605
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
24,249✔
1606

1607
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
24,249✔
1608
              "unwrap argument must be uarray");
1609

1610
   return result;
24,249✔
1611
}
1612

1613
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
20,668✔
1614
{
1615
   mir_type_t t_offset = mir_offset_type(mu);
20,668✔
1616
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
20,668✔
1617
                                    MIR_NULL_STAMP, array,
20,668✔
1618
                                    mir_const(mu, t_offset, dim));
1619

1620
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
20,668✔
1621
              "uarray len argument must be uarrray");
1622

1623
#ifdef DEBUG
1624
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
20,668✔
1625
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
20,668✔
1626
#endif
1627

1628
   return result;
20,668✔
1629
}
1630

1631
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
49,197✔
1632
                                       mir_type_t type, int arg_index,
1633
                                       mir_value_t array, int dim)
1634
{
1635
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
49,197✔
1636
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,515✔
1637

1638
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
47,682✔
1639
                                    array, mir_enum(dim));
1640

1641
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
47,682✔
1642
              "cannot use %s with non-uarray type", mir_op_string(op));
1643

1644
#ifdef DEBUG
1645
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
47,682✔
1646
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
47,682✔
1647
#endif
1648

1649
   return result;
47,682✔
1650
}
1651

1652
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
17,183✔
1653
{
1654
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
17,183✔
1655
                              0, array, dim);
1656
}
1657

1658
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
14,869✔
1659
{
1660
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
14,869✔
1661
                              1, array, dim);
1662
}
1663

1664
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
17,145✔
1665
{
1666
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
17,145✔
1667
                              2, array, dim);
1668
}
1669

1670
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
6,132✔
1671
                                   mir_value_t right, mir_value_t dir)
1672
{
1673
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
6,132✔
1674
                                    mir_offset_type(mu), MIR_NULL_STAMP,
6,132✔
1675
                                    left, right, dir);
1676

1677
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left), mir_get_type(mu, left)),
6,132✔
1678
              "left and right are not the same type");
1679
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
6,132✔
1680
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
6,132✔
1681

1682
   return result;
6,132✔
1683
}
1684

1685
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
4,610✔
1686
                                 mir_value_t right, mir_value_t dir)
1687
{
1688
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
4,610✔
1689
                                    mir_bool_type(mu), MIR_NULL_STAMP,
4,610✔
1690
                                    left, right, dir);
1691

1692
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left), mir_get_type(mu, left)),
4,610✔
1693
              "left and right are not the same type");
1694
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
4,610✔
1695
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
4,610✔
1696

1697
   return result;
4,610✔
1698
}
1699

1700
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
35,160✔
1701
{
1702
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
35,160✔
1703
               mir_cast_value(target));
35,160✔
1704

1705
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
35,160✔
1706
}
35,160✔
1707

1708
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
32,931✔
1709
                    mir_block_t bfalse)
1710
{
1711
   int64_t tconst;
32,931✔
1712
   if (mir_get_const(mu, test, &tconst)) {
32,931✔
1713
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
1✔
1714
      return;
1✔
1715
   }
1716

1717
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
32,930✔
1718
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
32,930✔
1719

1720
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
32,930✔
1721
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
32,930✔
1722
              "invalid cond targets");
1723
}
1724

1725
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
12,446✔
1726
                             mir_value_t vtrue, mir_value_t vfalse)
1727
{
1728
   int64_t tconst;
12,446✔
1729
   if (mir_get_const(mu, test, &tconst))
12,446✔
1730
      return tconst ? vtrue : vfalse;
136✔
1731
   else if (mir_equals(vtrue, vfalse))
12,310✔
1732
      return vtrue;
1✔
1733

1734
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
12,309✔
1735
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
12,309✔
1736
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
12,309✔
1737

1738
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
12,309✔
1739
                                    vtrue, vfalse);
1740

1741
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
12,309✔
1742
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
12,309✔
1743
              "true argument to select is not expected type");
1744
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
12,309✔
1745
              "false argument to select is not expected type");
1746

1747
   return result;
12,309✔
1748
}
1749

1750
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
1751
{
1752
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
1753
                                 ninputs * 2);
1754

1755
   for (int i = 0; i < ninputs; i++)
3✔
1756
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
1757

1758
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
1759
}
1760

1761
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
1762
                   mir_block_t block, mir_value_t value)
1763
{
1764
   node_data_t *n = mir_node_data(mu, phi);
2✔
1765
   assert(n->op == MIR_OP_PHI);
2✔
1766
   assert(nth * 2 < n->nargs);
2✔
1767

1768
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
1769
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
1770

1771
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
1772

1773
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
1774
              "phi input %d has wrong type", nth);
1775

1776
#ifdef DEBUG
1777
   if (value.tag != MIR_TAG_CONST) {
2✔
1778
      const block_data_t *bd = mir_block_data(mu, block);
2✔
1779
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
1780
         if (bd->nodes[i] == value.id)
2✔
1781
         return;
1782
      }
1783

1784
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
1785
   }
1786
#endif
1787
}
1788

1789
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
623✔
1790
                    const mir_value_t *cases, const mir_block_t *blocks,
1791
                    int ncases)
1792
{
1793
   int64_t cval;
623✔
1794
   if (mir_get_const(mu, value, &cval)) {
623✔
1795
      for (int i = 0; i < ncases; i++) {
3✔
1796
         int64_t cmp;
2✔
1797
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
1798
            mir_build_jump(mu, blocks[i]);
1✔
1799
            return;
1✔
1800
         }
1801
      }
1802

1803
      mir_build_jump(mu, def);
1✔
1804
      return;
1✔
1805
   }
1806

1807
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,242✔
1808
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
621✔
1809

1810
   mir_set_arg(mu, n, 0, value);
621✔
1811
   mir_set_arg(mu, n, 1, mir_cast_value(def));
621✔
1812

1813
   for (int i = 0; i < ncases; i++) {
5,222✔
1814
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
4,601✔
1815
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
4,601✔
1816
   }
1817

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

1820
#ifdef DEBUG
1821
   mir_type_t type = mir_get_type(mu, value);
621✔
1822
   for (int i = 0; i < ncases; i++) {
5,222✔
1823
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
4,601✔
1824
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
4,601✔
1825
                 "choice and value types do not match");
1826

1827
      for (int j = 0; j < i; j++)
244,553✔
1828
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
239,952✔
1829
   }
1830
#endif
1831
}
1832

1833
void mir_build_return(mir_unit_t *mu, mir_value_t value)
51,267✔
1834
{
1835
   if (mir_is_null(value))
51,267✔
1836
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
24,265✔
1837
   else
1838
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
27,002✔
1839

1840
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
51,267✔
1841
              "wrong result type");
1842
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
51,267✔
1843
              || mir_is_null(value), "cannot return a result");
1844
}
51,267✔
1845

1846
void mir_build_wait(mir_unit_t *mu, mir_block_t target, mir_value_t time)
13,489✔
1847
{
1848
   if (mir_is_null(time))
13,489✔
1849
      mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,186✔
1850
                  mir_cast_value(target));
8,186✔
1851
   else
1852
      mir_build_2(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,303✔
1853
                  mir_cast_value(target), time);
5,303✔
1854

1855
   MIR_ASSERT(mir_is_null(time) || mir_is_time(mu, time),
13,489✔
1856
              "time argument to wait is not a time");
1857
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
13,489✔
1858
              "wait only allowed in process or procedure");
1859
}
13,489✔
1860

1861
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
1✔
1862
{
1863
   if (value.tag != MIR_TAG_NODE)
1✔
1864
      return;   // Only useful for keeping nodes alive
1865

1866
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
1867
}
1868

1869
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
35,802✔
1870
                            mir_stamp_t stamp, const mir_value_t *args,
1871
                            unsigned nargs)
1872
{
1873
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
35,802✔
1874

1875
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
35,802✔
1876

1877
   for (int i = 0; i < nargs; i++)
140,436✔
1878
      mir_set_arg(mu, n, i + 1, args[i]);
104,634✔
1879

1880
   if (mir_is_null(type))
35,802✔
1881
      return MIR_NULL_VALUE;
4,963✔
1882
   else
1883
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,839✔
1884
}
1885

1886
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
875✔
1887
                     const mir_value_t *args, unsigned nargs)
1888
{
1889
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
1,750✔
1890
                                 MIR_NULL_STAMP, nargs + 2);
875✔
1891
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
875✔
1892
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
875✔
1893

1894
   for (int i = 0; i < nargs; i++)
3,106✔
1895
      mir_set_arg(mu, n, i + 2, args[i]);
2,231✔
1896

1897
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
875✔
1898
              "first argument to VHDL procedure must be context pointer");
1899
}
875✔
1900

1901
void mir_build_resume(mir_unit_t *mu, ident_t name)
875✔
1902
{
1903
   mir_value_t link = mir_add_linkage(mu, name);
875✔
1904
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
875✔
1905

1906
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
875✔
1907
              "resume must be first op in a block");
1908
}
875✔
1909

1910
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
423✔
1911
                              mir_stamp_t stamp, mir_value_t locus,
1912
                              const mir_value_t *args, int nargs)
1913
{
1914
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
423✔
1915

1916
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
423✔
1917
   mir_set_arg(mu, n, 1, locus);
423✔
1918

1919
   for (int i = 0; i < nargs; i++)
498✔
1920
      mir_set_arg(mu, n, i + 2, args[i]);
75✔
1921

1922
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
423✔
1923
              "locus argument to syscall must be a debug locus");
1924

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

1928
   if (mir_is_null(type))
423✔
1929
      return MIR_NULL_VALUE;
384✔
1930
   else
1931
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
39✔
1932
}
1933

1934
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
595✔
1935
{
1936
   if (mir_is_null(locus))
595✔
1937
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
463✔
1938
   else
1939
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
132✔
1940

1941
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
595✔
1942
              "locus argument to unreachable must be debug locus");
1943
}
595✔
1944
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
14,104✔
1945
                                mir_value_t left, mir_value_t right,
1946
                                mir_value_t dir, mir_value_t locus,
1947
                                mir_value_t hint)
1948
{
1949
   // TODO: check if can elide bounds
1950

1951
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
14,104✔
1952
               dir, locus, hint);
1953
}
14,104✔
1954

1955
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
3,019✔
1956
                           mir_value_t right, mir_value_t dir,
1957
                           mir_value_t locus, mir_value_t hint)
1958
{
1959
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
3,019✔
1960
                       locus, hint);
1961
}
3,019✔
1962

1963
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
11,085✔
1964
                           mir_value_t right, mir_value_t dir,
1965
                           mir_value_t locus, mir_value_t hint)
1966
{
1967
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
11,085✔
1968
                       locus, hint);
1969
}
11,085✔
1970

1971
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
1,097✔
1972
{
1973
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,097✔
1974
               ptr, locus);
1975

1976
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
1,097✔
1977
              "null check argument must be an access");
1978
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,097✔
1979
              "locus argument to null check must be a debug locus");
1980
}
1,097✔
1981

1982
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
100✔
1983
{
1984
   int64_t cval;
100✔
1985
   if (mir_get_const(mu, value, &cval) && cval != 0)
100✔
1986
      return;
×
1987

1988
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
100✔
1989
               value, locus);
1990

1991
   MIR_ASSERT(mir_is_integral(mu, value),
100✔
1992
              "argument to zero check must be integral");
1993
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
100✔
1994
              "locus argument to zero check must be a debug locus");
1995
}
1996

1997
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
6,744✔
1998
                            mir_value_t locus, mir_value_t dim)
1999
{
2000
   if (mir_equals(llen, rlen))
6,744✔
2001
      return;
2002

2003
   if (mir_is_null(dim))
6,744✔
2004
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
6,720✔
2005
                  llen, rlen, locus);
2006
   else
2007
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2008
                  llen, rlen, locus, dim);
2009

2010
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
6,744✔
2011
              "locus argument to length check must be a debug locus");
2012
}
2013

2014
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
513✔
2015
                              mir_value_t locus)
2016
{
2017
   int64_t cval;
513✔
2018
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
513✔
2019
      return;
×
2020

2021
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
513✔
2022
               exp, locus);
2023

2024
   MIR_ASSERT(mir_is_integral(mu, exp),
513✔
2025
              "exp argument to exponent check must be a integer");
2026
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
513✔
2027
              "locus argument to exponent check must be a debug locus");
2028
}
2029

2030
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
261✔
2031
                         mir_value_t length, mir_value_t kind,
2032
                         mir_value_t status)
2033
{
2034
   if (mir_is_null(status))
261✔
2035
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
235✔
2036
                  file, name, length, kind);
2037
   else
2038
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
26✔
2039
                  file, name, length, kind, status);
2040

2041
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
261✔
2042
              "file open first argument must be pointer to file");
2043
}
261✔
2044

2045
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
75✔
2046
                         mir_value_t inlen, mir_value_t outlen)
2047
{
2048
   if (mir_is_null(inlen))
75✔
2049
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
48✔
2050
                  file, ptr);
2051
   else if (mir_is_null(outlen))
27✔
2052
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
9✔
2053
                  file, ptr, inlen);
2054
   else
2055
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
2056
                  file, ptr, inlen, outlen);
2057

2058
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
75✔
2059
              "file read first argument must have file pointer type");
2060
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
75✔
2061
              "file read pointer argument must have pointer type");
2062
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
75✔
2063
              "file read inlen argument must be integral");
2064
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
75✔
2065
              "file read outlen argument must have pointer type");
2066
}
75✔
2067

2068
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
122✔
2069
                          mir_value_t length)
2070
{
2071
   if (mir_is_null(length))
122✔
2072
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2073
                  file, value);
2074
   else
2075
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
65✔
2076
                  file, value, length);
2077

2078
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
122✔
2079
              "file write first argument must have file pointer type");
2080
}
122✔
2081

2082
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
279✔
2083
                                      mir_value_t effective)
2084
{
2085
   mir_type_t type = mir_conversion_type(mu);
279✔
2086

2087
   mir_value_t result;
279✔
2088
   if (mir_is_null(effective) || mir_equals(effective, driving))
279✔
2089
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
261✔
2090
                           driving);
2091
   else
2092
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
18✔
2093
                           driving, effective);
2094

2095
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
279✔
2096
              "port conversion argument must be a closure");
2097
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
279✔
2098
              "port conversion argument must be a closure");
2099

2100
   return result;
279✔
2101
}
2102

2103
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
354✔
2104
                          mir_value_t count)
2105
{
2106
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
354✔
2107
               conv, nets, count);
2108

2109
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
354✔
2110
              "conv argument to convert must be a port conversion");
2111
   MIR_ASSERT(mir_is_signal(mu, nets),
354✔
2112
              "nets argument to convert must be a signal");
2113
   MIR_ASSERT(mir_is_offset(mu, count),
354✔
2114
              "count argument to convert must be offset");
2115
}
354✔
2116

2117
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
396✔
2118
                           mir_value_t count)
2119
{
2120
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
396✔
2121
               conv, nets, count);
2122

2123
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
396✔
2124
              "conv argument to convert must be a port conversion");
2125
   MIR_ASSERT(mir_is_signal(mu, nets),
396✔
2126
              "nets argument to convert must be a signal");
2127
   MIR_ASSERT(mir_is_offset(mu, count),
396✔
2128
              "count argument to convert must be offset");
2129
}
396✔
2130

2131
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
402✔
2132
                              mir_value_t target, mir_value_t count,
2133
                              mir_value_t values)
2134
{
2135
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
402✔
2136
               cf, target, count, values);
2137

2138
   MIR_ASSERT(mir_is_signal(mu, target),
402✔
2139
              "put conversion target is not signal");
2140
   MIR_ASSERT(mir_is_offset(mu, count),
402✔
2141
              "put conversion net count is not offset type");
2142
   MIR_ASSERT(!mir_is_signal(mu, values),
402✔
2143
              "signal cannot be values argument for put conversion");
2144
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
402✔
2145
              "cf argument to put conversion must be conversion function");
2146
}
402✔
2147

2148
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
16,185✔
2149
                                  mir_value_t count, mir_value_t size,
2150
                                  mir_value_t value, mir_value_t flags,
2151
                                  mir_value_t locus, mir_value_t offset)
2152
{
2153
   mir_type_t stype = mir_signal_type(mu, type);
16,185✔
2154

2155
   mir_value_t result;
16,185✔
2156
   if (mir_is_null(offset))
16,185✔
2157
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
10,580✔
2158
                           count, size, value, flags, locus);
2159
   else
2160
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
5,605✔
2161
                           count, size, value, flags, locus, offset);
2162

2163
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
16,185✔
2164
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2165
              "signal must have integer or real type");
2166
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
16,185✔
2167
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
16,185✔
2168
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
16,185✔
2169
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
16,185✔
2170
              "locus argument to init signal is not debug locus");
2171
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
16,185✔
2172
              "offset argument must be pointer or null");
2173

2174
   return result;
16,185✔
2175
}
2176

2177
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
75✔
2178
                                      mir_value_t count, mir_value_t size,
2179
                                      mir_value_t locus, mir_value_t kind,
2180
                                      mir_value_t closure, mir_value_t delay)
2181
{
2182
   mir_type_t stype = mir_signal_type(mu, type);
75✔
2183

2184
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
75✔
2185
                                    MIR_NULL_STAMP, count, size, locus,
75✔
2186
                                    kind, closure, delay);
2187

2188
   MIR_ASSERT(mir_is_offset(mu, count),
75✔
2189
              "count argument to implicit signal is not offset");
2190
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
75✔
2191
              "kind argument to implicit signal is not offset");
2192
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
75✔
2193
              "closure argument to implicit signal is not a closure");
2194
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
75✔
2195
              "locus argument to implicit signal must be a debug locus");
2196
   MIR_ASSERT(mir_is_integral(mu, delay),
75✔
2197
              "delay argument to implicit signal must be time");
2198

2199
   return result;
75✔
2200
}
2201

2202
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
9,197✔
2203
                            mir_value_t count)
2204
{
2205
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,197✔
2206
               target, count);
2207

2208
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
9,197✔
2209
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
9,197✔
2210
}
9,197✔
2211

2212
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
10,611✔
2213
                              mir_value_t count, mir_value_t values,
2214
                              mir_value_t reject, mir_value_t after)
2215
{
2216
   int64_t nconst;
10,611✔
2217
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
10,611✔
2218
      mir_comment(mu, "Skip empty waveform");
×
2219
      return;
×
2220
   }
2221

2222
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
10,611✔
2223
               target, count, values, reject, after);
2224

2225
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
10,611✔
2226
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
10,611✔
2227
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
10,611✔
2228
}
2229

2230
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
177✔
2231
                              mir_value_t count, mir_value_t values)
2232
{
2233
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
177✔
2234
               target, count, values);
2235

2236
   MIR_ASSERT(mir_is_signal(mu, target),
177✔
2237
              "deposit signal target is not signal");
2238
   MIR_ASSERT(mir_is_offset(mu, count),
177✔
2239
              "deposit signal count is not offset type");
2240
   MIR_ASSERT(!mir_is_signal(mu, values),
177✔
2241
              "signal cannot be values argument for deposit signal");
2242
}
177✔
2243

2244
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
14,110✔
2245
{
2246
   mir_type_t type = mir_get_type(mu, signal);
14,110✔
2247
   mir_type_t pointer = mir_get_pointer(mu, type);
14,110✔
2248
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
14,110✔
2249

2250
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
14,110✔
2251
                                    stamp, signal);
2252

2253
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
14,110✔
2254
              "argument to resolved must be signal");
2255

2256
   return result;
14,110✔
2257
}
2258

2259
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
90✔
2260
{
2261
   mir_type_t type = mir_get_type(mu, signal);
90✔
2262
   mir_type_t pointer = mir_get_pointer(mu, type);
90✔
2263
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
90✔
2264

2265
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
90✔
2266
                                    stamp, signal);
2267

2268
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
90✔
2269
              "argument to resolved must be signal");
2270

2271
   return result;
90✔
2272
}
2273

2274
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
138✔
2275
                                    mir_value_t count)
2276
{
2277
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
138✔
2278
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
138✔
2279

2280
   mir_value_t result;
138✔
2281
   if (mir_is_null(count))
138✔
2282
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
105✔
2283
   else
2284
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
33✔
2285
                           signal, count);
2286

2287
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
138✔
2288
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
138✔
2289
              "count argument must have offset type");
2290

2291
   return result;
138✔
2292
}
2293

2294
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
60✔
2295
                     mir_value_t values)
2296
{
2297
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
60✔
2298
               target, count, values);
2299

2300
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
60✔
2301
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
60✔
2302
}
60✔
2303

2304
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
30✔
2305
{
2306
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
30✔
2307
               target, count);
2308

2309
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
30✔
2310
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
30✔
2311
}
30✔
2312

2313
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
24✔
2314
                          mir_value_t reject, mir_value_t after)
2315
{
2316
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2317
               target, count, reject, after);
2318

2319
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
24✔
2320
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
24✔
2321
}
24✔
2322

2323

2324
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
33✔
2325
                                 mir_value_t count)
2326
{
2327
   mir_type_t type = mir_time_type(mu);
33✔
2328

2329
   mir_value_t result;
33✔
2330
   if (mir_is_null(count))
33✔
2331
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
24✔
2332
   else
2333
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
9✔
2334
                           signal, count);
2335

2336
   MIR_ASSERT(mir_is_signal(mu, signal),
33✔
2337
              "signal argument to last event must have signal type");
2338
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
33✔
2339
              "length argument to last event must have offset type");
2340

2341
   return result;
33✔
2342
}
2343

2344
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
36✔
2345
                                  mir_value_t count)
2346
{
2347
   mir_type_t type = mir_time_type(mu);
36✔
2348

2349
   mir_value_t result;
36✔
2350
   if (mir_is_null(count))
36✔
2351
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
30✔
2352
                           signal);
2353
   else
2354
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
6✔
2355
                           signal, count);
2356

2357
   MIR_ASSERT(mir_is_signal(mu, signal),
36✔
2358
              "signal argument to last event must have signal type");
2359
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
36✔
2360
              "length argument to last event must have offset type");
2361

2362
   return result;
36✔
2363
}
2364

2365

2366
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
666✔
2367
                                         mir_value_t signal, mir_value_t count)
2368
{
2369
   mir_type_t t_bool = mir_bool_type(mu);
666✔
2370
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
666✔
2371
                                    signal, count);
2372

2373
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
666✔
2374
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
666✔
2375

2376
   return result;
666✔
2377
}
2378

2379
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
411✔
2380
                                 mir_value_t count)
2381
{
2382
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
411✔
2383
}
2384

2385
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
219✔
2386
                                  mir_value_t count)
2387
{
2388
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
219✔
2389
}
2390

2391
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
36✔
2392
                                   mir_value_t count)
2393
{
2394
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
36✔
2395
}
2396

2397
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
3,451✔
2398
                              mir_value_t resolution)
2399
{
2400
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,451✔
2401
               signal, resolution);
2402

2403
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
3,451✔
2404
   MIR_ASSERT(mir_is(mu, resolution, MIR_TYPE_RESOLUTION),
3,451✔
2405
              "resolution wrapper argument has wrong type");
2406
}
3,451✔
2407

2408
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
1,160✔
2409
                               mir_value_t source, mir_value_t count,
2410
                               mir_value_t reject, mir_value_t after)
2411
{
2412
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,160✔
2413
               target, source, count, reject, after);
2414

2415
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
1,160✔
2416
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,160✔
2417
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
1,160✔
2418
}
1,160✔
2419

2420
void mir_build_cover_stmt(mir_unit_t *mu, uint32_t tag)
961✔
2421
{
2422
   mir_build_1(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
961✔
2423
               mir_enum(tag));
2424
}
961✔
2425

2426
void mir_build_cover_branch(mir_unit_t *mu, uint32_t tag)
486✔
2427
{
2428
   mir_build_1(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
486✔
2429
               mir_enum(tag));
2430
}
486✔
2431

2432
void mir_build_cover_expr(mir_unit_t *mu, uint32_t tag)
849✔
2433
{
2434
   mir_build_1(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
849✔
2435
               mir_enum(tag));
2436
}
849✔
2437

2438
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
381✔
2439
{
2440
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
381✔
2441
               signal, mir_enum(tag));
2442

2443
   MIR_ASSERT(mir_is_signal(mu, signal),
381✔
2444
              "argument to cover toggle must be signal");
2445
}
381✔
2446

2447
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
12✔
2448
                           uint32_t tag)
2449
{
2450
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2451
               signal, low, mir_enum(tag));
2452

2453
   MIR_ASSERT(mir_is_signal(mu, signal),
12✔
2454
              "argument to cover state must be signal");
2455
}
12✔
2456
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
17,631✔
2457
                                   mir_value_t context)
2458
{
2459
   mir_value_t link = mir_add_linkage(mu, name);
17,631✔
2460
   mir_type_t type = mir_context_type(mu, name);
17,631✔
2461

2462
   mir_value_t result;
17,631✔
2463
   if (mir_is_null(context))
17,631✔
2464
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
17,449✔
2465
                           MIR_NULL_STAMP, link);
17,449✔
2466
   else
2467
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
182✔
2468
                           MIR_NULL_STAMP, link, context);
182✔
2469

2470
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
17,631✔
2471
              "invalid package init context argument");
2472
   MIR_ASSERT(mu->kind == MIR_UNIT_INSTANCE
17,631✔
2473
              || mu->kind == MIR_UNIT_PACKAGE
2474
              || mu->kind == MIR_UNIT_THUNK,
2475
              "cannot use package init here");
2476
   MIR_ASSERT(name != mu->name, "cyclic package init");
17,631✔
2477

2478
   return result;
17,631✔
2479
}
2480

2481
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
112✔
2482
{
2483
   mir_value_t link = mir_add_linkage(mu, name);
112✔
2484
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
112✔
2485
               link, locus);
2486

2487
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
112✔
2488
              "locus argument to process init must be a debug locus");
2489
}
112✔
2490

2491
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
162✔
2492
                                     mir_value_t context, mir_value_t path_name,
2493
                                     mir_value_t inst_name)
2494
{
2495
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
162✔
2496

2497
   mir_value_t result;
162✔
2498
   if (mir_is_null(path_name) && mir_is_null(inst_name))
162✔
2499
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
124✔
2500
                           link, context);
2501
   else {
2502
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
38✔
2503
                           link, context, path_name, inst_name);
2504

2505
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
38✔
2506
                 "path name argument must be array");
2507
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
38✔
2508
                 "inst name argument must be array");
2509
   }
2510

2511
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
162✔
2512
                "protected init type must be context");
2513
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
162✔
2514
              "invalid protected init context argument");
2515

2516
   return result;
162✔
2517
}
2518

2519
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
1,606✔
2520
{
2521
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
1,606✔
2522

2523
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,606✔
2524
              "locus argument to record scope must be a debug locus");
2525
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
1,606✔
2526
              "record scope type must be record");
2527
}
1,606✔
2528

2529
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
632✔
2530
{
2531
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
632✔
2532

2533
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
632✔
2534
              "locus argument to array scope must be a debug locus");
2535
}
632✔
2536

2537
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
45✔
2538
{
2539
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
45✔
2540

2541
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2542
              "locus argument to package scope must be a debug locus");
2543
}
45✔
2544

2545
void mir_build_pop_scope(mir_unit_t *mu)
2,283✔
2546
{
2547
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
2,283✔
2548
}
2,283✔
2549

2550
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
4,232✔
2551
                            mir_value_t locus)
2552
{
2553
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,232✔
2554
               signal, locus);
2555

2556
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
4,232✔
2557
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
4,232✔
2558
              "locus argument must have debug locus type");
2559
}
4,232✔
2560

2561
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
5,322✔
2562
                          mir_value_t count)
2563
{
2564
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,322✔
2565
               src, dst, count);
2566

2567
   MIR_ASSERT(mir_is_signal(mu, src),
5,322✔
2568
              "src argument to map signal is not a signal");
2569
   MIR_ASSERT(mir_is_signal(mu, dst),
5,322✔
2570
              "dst argument to map signal is not a signal");
2571
   MIR_ASSERT(mir_is_offset(mu, count),
5,322✔
2572
              "count argument to map signal is not offset type");
2573
}
5,322✔
2574

2575
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
219✔
2576
                         mir_value_t count)
2577
{
2578
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
219✔
2579
               src, dst, count);
2580

2581
   MIR_ASSERT(mir_is_signal(mu, dst),
219✔
2582
              "dst argument to map const is not a signal");
2583
   MIR_ASSERT(mir_is_offset(mu, count),
219✔
2584
              "count argument to map const is not offset type");
2585
}
219✔
2586

2587
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
57✔
2588
                            mir_value_t count)
2589
{
2590
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2591
               src, dst, count);
2592

2593
   MIR_ASSERT(mir_is_signal(mu, src),
57✔
2594
              "src argument to map implicit is not a signal");
2595
   MIR_ASSERT(mir_is_signal(mu, dst),
57✔
2596
              "dst argument to map implicit is not a signal");
2597
   MIR_ASSERT(mir_is_offset(mu, count),
57✔
2598
              "count argument type to map implicit is not offset");
2599
}
57✔
2600

2601
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
45✔
2602
                                  mir_value_t right)
2603
{
2604
   mir_type_t type = mir_trigger_type(mu);
45✔
2605
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
45✔
2606
                                    MIR_NULL_STAMP, left, right);
45✔
2607

2608
   MIR_ASSERT(mir_is_signal(mu, left),
45✔
2609
              "cmp trigger left argument must be signal");
2610
   MIR_ASSERT(mir_is_integral(mu, right),
45✔
2611
              "cmp trigger right argument must be integer");
2612

2613
   return result;
45✔
2614
}
2615

2616
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
212✔
2617
                                       const mir_value_t *args, unsigned nargs)
2618
{
2619
   mir_type_t type = mir_trigger_type(mu);
212✔
2620
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
424✔
2621
                                 MIR_NULL_STAMP, nargs + 1);
212✔
2622

2623
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
212✔
2624

2625
   for (int i = 0; i < nargs; i++)
561✔
2626
      mir_set_arg(mu, n, i + 1, args[i]);
349✔
2627

2628
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
212✔
2629
}
2630

2631
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
33✔
2632
                                 mir_value_t right)
2633
{
2634
   mir_type_t type = mir_trigger_type(mu);
33✔
2635
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
33✔
2636
                                    MIR_NULL_STAMP, left, right);
33✔
2637

2638
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
33✔
2639
              "or trigger left argument must be trigger");
2640
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
33✔
2641
              "or trigger right argument must be trigger");
2642

2643
   return result;
33✔
2644
}
2645

2646
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
362✔
2647
{
2648
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
362✔
2649

2650
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
362✔
2651
              "add trigger argument must be trigger");
2652
}
362✔
2653

2654
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
11,400✔
2655
{
2656
   mir_value_t link = mir_add_linkage(mu, name);
11,400✔
2657
   mir_type_t type = mir_context_type(mu, name);
11,400✔
2658

2659
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
11,400✔
2660
                                    MIR_NULL_STAMP, link);
11,400✔
2661

2662
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
11,400✔
2663

2664
   return result;
11,400✔
2665
}
2666

2667
mir_value_t mir_build_link_var(mir_unit_t *mu, ident_t unit,
2,522✔
2668
                               mir_value_t context, ident_t name,
2669
                               mir_type_t type)
2670
{
2671
   mir_type_t pointer = mir_get_var_pointer(mu, type);
2,522✔
2672
   mir_value_t link = mir_add_linkage(mu, unit);
2,522✔
2673
   mir_value_t var_link = mir_add_linkage(mu, name);   // TODO: rethink this
2,522✔
2674
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
2,522✔
2675
                                    MIR_NULL_STAMP, link, context, var_link);
2,522✔
2676

2677
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
2,522✔
2678
              "first argument to link var must be context");
2679

2680
   return result;
2,522✔
2681
}
2682

2683
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
259✔
2684
                            mir_value_t length, mir_value_t locus)
2685
{
2686
   if (mir_is_null(locus))
259✔
2687
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
122✔
2688
                  spec, length);
2689
   else
2690
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
137✔
2691
                  spec, length, locus);
2692

2693
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
259✔
2694
              "spec argument to bind foreign must be a pointer");
2695
   MIR_ASSERT(mir_is_offset(mu, length),
259✔
2696
              "legnth argument to bind foreign must be offset");
2697
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
259✔
2698
              "locus argument to bind foreign value must be a debug locus");
2699
}
259✔
2700

2701
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
194✔
2702
                                    ident_t scope, mir_type_t type,
2703
                                    mir_stamp_t stamp)
2704
{
2705
   mir_type_t pointer = mir_get_var_pointer(mu, type);
194✔
2706
   mir_value_t link = mir_add_linkage(mu, scope);
194✔
2707
   mir_value_t result = mir_build_2(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
194✔
2708
                                    locus, link);
2709

2710
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
194✔
2711
              "bind external argument must be locus");
2712

2713
   return result;
194✔
2714
}
2715

2716
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
8,648✔
2717
{
2718
   mir_type_t type = MIR_NULL_TYPE;
8,648✔
2719
   if (hops == 0)
8,648✔
2720
      type = mir_self_type(mu);
987✔
2721
   else {
2722
      mir_shape_t *s = mu->parent;
7,661✔
2723
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
7,931✔
2724

2725
      if (s != NULL) type = s->type;
7,661✔
2726
   }
2727

2728
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
8,648✔
2729
                                    MIR_NULL_STAMP, mir_enum(hops));
8,648✔
2730

2731
   MIR_ASSERT(hops >= 0, "invalid hop count");
8,648✔
2732
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
8,648✔
2733

2734
   return result;
8,648✔
2735
}
2736

2737
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
45,545✔
2738
{
2739
   mir_type_t type = MIR_NULL_TYPE;
45,545✔
2740
   mir_value_t link = MIR_NULL_VALUE;
45,545✔
2741

2742
   mir_shape_t *s = mu->parent;
45,545✔
2743
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
56,068✔
2744

2745
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
45,545✔
2746
      type = s->slots[nth].pointer;
45,545✔
2747
      link = mir_add_linkage(mu, s->name);
45,545✔
2748
   }
2749

2750
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
45,545✔
2751
                                    mir_enum(hops), link, mir_enum(nth));
2752

2753
   MIR_ASSERT(hops > 0, "invalid hop count");
45,545✔
2754
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
45,545✔
2755

2756
   return result;
45,545✔
2757
}
2758

2759
void mir_build_sched_event(mir_unit_t *mu, mir_value_t signal,
5,813✔
2760
                           mir_value_t count)
2761
{
2762
   mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,813✔
2763
               signal, count);
2764

2765
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
5,813✔
2766
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
5,813✔
2767
}
5,813✔
2768

2769
void mir_build_clear_event(mir_unit_t *mu, mir_value_t signal,
499✔
2770
                           mir_value_t count)
2771
{
2772
   mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
499✔
2773
               signal, count);
2774

2775
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
499✔
2776
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
499✔
2777
}
499✔
2778

2779
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
45✔
2780
                                    mir_value_t context, mir_value_t locus,
2781
                                    mir_value_t bounds)
2782
{
2783
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
45✔
2784

2785
   mir_value_t result;
45✔
2786
   if (mir_is_null(bounds))
45✔
2787
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
39✔
2788
                           value, context, locus);
2789
   else
2790
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
6✔
2791
                           value, context, locus, bounds);
2792

2793
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
45✔
2794
              "invalid reflect value context argument");
2795
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2796
              "locus argument to reflect value must be a debug locus");
2797

2798
   return result;
45✔
2799
}
2800

2801
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
42✔
2802
                                      mir_value_t locus, mir_value_t bounds)
2803
{
2804
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
42✔
2805

2806
   mir_value_t result;
42✔
2807
   if (mir_is_null(bounds))
42✔
2808
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
42✔
2809
                           context, locus);
2810
   else
2811
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
×
2812
                           context, locus, bounds);
2813

2814
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
42✔
2815
              "invalid reflect subtype context argument");
2816
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
42✔
2817
              "locus argument to reflect subtype must be a debug locus");
2818

2819
   return result;
42✔
2820
}
2821

2822
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
14,001✔
2823
                      mir_value_t length, mir_value_t severity,
2824
                      mir_value_t locus, mir_value_t hint_left,
2825
                      mir_value_t hint_right)
2826
{
2827
   int64_t value_const;
14,001✔
2828
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
14,001✔
2829
      mir_comment(mu, "Always true assertion");
×
2830
      return;
×
2831
   }
2832

2833
   if (mir_is_null(hint_left))
14,001✔
2834
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,248✔
2835
                  value, severity, message, length, locus);
2836
   else {
2837
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
11,506✔
2838
                                     MIR_NULL_STAMP, 7);
5,753✔
2839
      mir_set_arg(mu, n, 0, value);
5,753✔
2840
      mir_set_arg(mu, n, 1, severity);
5,753✔
2841
      mir_set_arg(mu, n, 2, message);
5,753✔
2842
      mir_set_arg(mu, n, 3, length);
5,753✔
2843
      mir_set_arg(mu, n, 4, locus);
5,753✔
2844
      mir_set_arg(mu, n, 5, hint_left);
5,753✔
2845
      mir_set_arg(mu, n, 6, hint_right);
5,753✔
2846

2847
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
5,753✔
2848
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
5,753✔
2849
   }
2850

2851
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,001✔
2852
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
14,001✔
2853
              "message parameter to assert is not a pointer");
2854
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
14,001✔
2855
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
14,001✔
2856
              "locus argument to report must be a debug locus");
2857
}
2858

2859
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,244✔
2860
                      mir_value_t severity, mir_value_t locus)
2861
{
2862
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,244✔
2863
               severity, message, length, locus);
2864

2865
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,244✔
2866
              "message parameter to report is not a pointer");
2867
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,244✔
2868
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,244✔
2869
              "locus argument to report must be a debug locus");
2870
}
2,244✔
2871

2872
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
812✔
2873
{
2874
   mir_type_t type = mir_string_type(mu);
812✔
2875
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
812✔
2876
                                    MIR_NULL_STAMP, kind);
812✔
2877

2878
   MIR_ASSERT(mir_is_offset(mu, kind),
812✔
2879
              "kind argument to instance name must be offset");
2880

2881
   return result;
812✔
2882
}
2883

2884
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
768✔
2885
                           mir_value_t strong)
2886
{
2887
   if (mir_is_null(strong))
768✔
2888
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
750✔
2889
   else
2890
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
2891
                  state, strong);
2892

2893
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
768✔
2894
   MIR_ASSERT(mir_is_null(strong)
768✔
2895
              || mir_check_type(mu, strong, mir_bool_type(mu)),
2896
                "strong argument not is not boolean");
2897
}
768✔
2898

2899
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_value_t context,
1,355✔
2900
                              mir_type_t atype, mir_type_t rtype)
2901
{
2902
   mir_type_t ctype = mir_closure_type(mu, atype, rtype);
1,355✔
2903
   mir_value_t link = mir_add_linkage(mu, func);
1,355✔
2904

2905
   mir_value_t result = mir_build_2(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
1,355✔
2906
                                    link, context);
2907

2908
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
1,355✔
2909
              "invalid closure context argument");
2910

2911
   return result;
1,355✔
2912
}
2913

2914
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
983✔
2915
                                         mir_value_t closure, mir_value_t ileft,
2916
                                         mir_value_t nlits)
2917
{
2918
   mir_type_t rtype = mir_resolution_type(mu, type);
983✔
2919
   mir_value_t result = mir_build_3(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
983✔
2920
                                    MIR_NULL_STAMP, closure, ileft, nlits);
983✔
2921

2922
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
983✔
2923
              "first argument to resolution wrapper must be closure");
2924

2925
   return result;
983✔
2926
}
2927

2928
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
65,862✔
2929
{
2930
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
65,862✔
2931
                                  MIR_NULL_STAMP, 0);
65,862✔
2932
   n->locus = obj;
65,862✔
2933

2934
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
65,862✔
2935
}
2936

2937
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
46,646✔
2938
{
2939
   mir_type_t from = mir_get_type(mu, value);
46,646✔
2940
   if (mir_equals(from, type))
46,646✔
2941
      return value;
46,646✔
2942

2943
   const mir_class_t class = mir_get_class(mu, type);
46,166✔
2944
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
46,166✔
2945

2946
   int64_t cval;
46,166✔
2947
   if (integral && mir_get_const(mu, value, &cval))
46,166✔
2948
      return mir_const(mu, type, cval);
414✔
2949

2950
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type,
45,752✔
2951
                                    MIR_NULL_STAMP, value);
45,752✔
2952

2953
#ifdef DEBUG
2954
   static const mir_class_t allowed[][2] = {
45,752✔
2955
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
2956
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
2957
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
2958
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
2959
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
2960
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
2961
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
2962
   };
2963

2964
   if (value.tag == MIR_TAG_CONST)
45,752✔
2965
      return result;
56✔
2966

2967
   const mir_class_t from_k = mir_get_class(mu, from);
45,696✔
2968

2969
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
83,458✔
2970
      if (from_k == allowed[i][0] && class == allowed[i][1])
83,458✔
2971
         return result;
45,696✔
2972
   }
2973

2974
   MIR_ASSERT(false, "invalid type conversion in cast");
×
2975
#else
2976
   return result;
2977
#endif
2978
}
2979

2980
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
×
2981
{
2982
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
2983

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

© 2025 Coveralls, Inc