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

nickg / nvc / 13887457702

16 Mar 2025 09:12PM UTC coverage: 92.285% (-0.04%) from 92.324%
13887457702

push

github

nickg
Tag Docker images on releases. Fixes #1165

68273 of 73981 relevant lines covered (92.28%)

423265.54 hits per line

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

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

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

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

50
   return b;
134,995✔
51
}
52

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

58
   mu->cursor.block = block;
1,274,239✔
59
   mu->cursor.pos   = pos;
1,274,239✔
60

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

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

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

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

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

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

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

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

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

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

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

160
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
2,307,470✔
161
{
162
   switch (node.tag) {
2,307,470✔
163
   case MIR_TAG_NODE:
2,284,414✔
164
      return mir_node_data(mu, node)->op;
2,284,414✔
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,134,150✔
171
{
172
   return &(mir_node_data(mu, node)->loc);
1,134,150✔
173
}
174

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

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

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

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

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

211
   return p;
29,473✔
212
}
213

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

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

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

232
   return v;
48,751✔
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,059,712✔
249
{
250
   assert(n >= mu->nodes && n < mu->nodes + mu->num_nodes);
1,059,712✔
251
   return n - mu->nodes;
1,059,712✔
252
}
253

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

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

268
      if (mu->num_nodes == mu->max_nodes) {
1,096,526✔
269
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
93,069✔
270
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
93,069✔
271
                                    sizeof(node_data_t));
272
      }
273

274
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
1,096,526✔
275
      n = &(mu->nodes[mu->num_nodes++]);
1,096,526✔
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,096,533✔
283
}
284

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

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

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

309
   if (nargs > MIR_INLINE_ARGS)
1,096,533✔
310
      n->spilloff = mir_spill_args(mu, nargs);
75,685✔
311

312
   return n;
1,096,533✔
313
}
314

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

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

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

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

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

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

344
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
176,611✔
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,611✔
349

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

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

358
static mir_value_t mir_build_4(mir_unit_t *mu, mir_op_t op, mir_type_t type,
3,000✔
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);
3,000✔
364

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

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

374
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
30,583✔
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,583✔
380
   n->nargs = 5;
30,583✔
381

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

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

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

393
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
19,814✔
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,814✔
400

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

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

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

413
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
117,111✔
414
{
415
   for (int i = 0; i < mu->linkage.count; i++) {
304,396✔
416
      if (mu->linkage.items[i] == ident)
239,998✔
417
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
52,713✔
418
   }
419

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

422
   APUSH(mu->linkage, ident);
64,398✔
423

424
   return link;
64,398✔
425
}
426

427
static mir_value_t mir_add_extvar(mir_unit_t *mu, ident_t ident)
2,522✔
428
{
429
   for (int i = 0; i < mu->extvars.count; i++) {
8,713✔
430
      if (mu->extvars.items[i] == ident)
7,121✔
431
         return (mir_value_t){ .tag = MIR_TAG_EXTVAR, .id = i };
930✔
432
   }
433

434
   mir_value_t var = { .tag = MIR_TAG_EXTVAR, .id = mu->extvars.count };
1,592✔
435

436
   APUSH(mu->extvars, ident);
1,592✔
437

438
   return var;
1,592✔
439
}
440

441
void mir_set_arg(mir_unit_t *mu, node_data_t *n, unsigned nth,
1,478,339✔
442
                 mir_value_t value)
443
{
444
   assert(nth < n->nargs);
1,478,339✔
445

446
   if (n->nargs <= MIR_INLINE_ARGS)
1,478,339✔
447
      n->args[nth] = value;
255,143✔
448
   else {
449
      assert(n->spilloff < mu->num_argspill);
1,223,196✔
450
      mu->argspill[n->spilloff + nth] = value;
1,223,196✔
451
   }
452
}
1,478,339✔
453

454
node_data_t *mir_node_data(mir_unit_t *mu, mir_value_t value)
9,643,253✔
455
{
456
   assert(value.tag == MIR_TAG_NODE);
9,643,253✔
457
   assert(value.id < mu->num_nodes);
9,643,253✔
458

459
   return &(mu->nodes[value.id]);
9,643,253✔
460
}
461

462
const param_data_t *mir_param_data(mir_unit_t *mu, mir_value_t value)
149,840✔
463
{
464
   assert(value.tag == MIR_TAG_PARAM);
149,840✔
465
   return AREF(mu->params, value.id);
149,840✔
466
}
467

468
const var_data_t *mir_var_data(mir_unit_t *mu, mir_value_t value)
294,186✔
469
{
470
   assert(value.tag == MIR_TAG_VAR);
294,186✔
471
   return AREF(mu->vars, value.id);
294,186✔
472
}
473

474
#ifdef DEBUG
475
void mir_comment(mir_unit_t *mu, const char *fmt, ...)
8✔
476
{
477
   va_list ap;
8✔
478
   va_start(ap, fmt);
8✔
479

480
   if (mu->comments == NULL)
8✔
481
      mu->comments = tb_new();
5✔
482

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

485
   tb_vprintf(mu->comments, fmt, ap);
8✔
486
   tb_append(mu->comments, '\0');
8✔
487

488
   va_end(ap);
8✔
489

490
   mir_build_1(mu, MIR_OP_COMMENT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
8✔
491
}
8✔
492
#endif
493

494
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
3,188,051✔
495
{
496
   switch (value.tag) {
3,188,051✔
497
   case MIR_TAG_CONST:
2,744,757✔
498
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
2,744,757✔
499
      return true;
2,744,757✔
500
   case MIR_TAG_ENUM:
196,905✔
501
      *result = value.id;
196,905✔
502
      return true;
196,905✔
503
   case MIR_TAG_NODE:
241,328✔
504
      {
505
         const node_data_t *n = mir_node_data(mu, value);
241,328✔
506
         if (n->op == MIR_OP_CONST) {
241,328✔
507
            *result = n->iconst;
7,169✔
508
            return true;
7,169✔
509
         }
510
         else
511
            return false;
512
      }
513
   default:
514
      return false;
515
   }
516
}
517

518
bool mir_get_const_real(mir_unit_t *mu, mir_value_t value, double *result)
95,107✔
519
{
520
   switch (value.tag) {
95,107✔
521
   case MIR_TAG_NODE:
71,521✔
522
      {
523
         const node_data_t *n = mir_node_data(mu, value);
71,521✔
524
         if (n->op == MIR_OP_CONST_REAL) {
71,521✔
525
            *result = n->dconst;
21,619✔
526
            return true;
21,619✔
527
         }
528
         else
529
            return false;
530
      }
531
   default:
532
      return false;
533
   }
534
}
535

536
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
2,192,421✔
537
{
538
   switch (value.tag) {
2,192,421✔
539
   case MIR_TAG_NODE:
1,809,305✔
540
      return mir_node_data(mu, value)->type;
1,809,305✔
541
   case MIR_TAG_PARAM:
139,228✔
542
      return mir_param_data(mu, value)->type;
139,228✔
543
   case MIR_TAG_VAR:
139,451✔
544
      return mir_var_data(mu, value)->pointer;
139,451✔
545
   default:
104,437✔
546
      return MIR_NULL_TYPE;
104,437✔
547
   }
548
}
549

550
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
415,144✔
551
{
552
   switch (value.tag) {
415,144✔
553
   case MIR_TAG_NODE:
320,362✔
554
      return mir_node_data(mu, value)->stamp;
320,362✔
555
   case MIR_TAG_PARAM:
10,599✔
556
      return mir_param_data(mu, value)->stamp;
10,599✔
557
   case MIR_TAG_VAR:
39,318✔
558
      return mir_var_data(mu, value)->stamp;
39,318✔
559
   case MIR_TAG_CONST:
44,865✔
560
      {
561
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
44,865✔
562
         return mir_int_stamp(mu, ival, ival);
44,865✔
563
      }
564
   default:
×
565
      return MIR_NULL_STAMP;
×
566
   }
567
}
568

569
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value)
7,841✔
570
{
571
   mir_type_t type = mir_get_type(mu, value);
7,841✔
572
   if (mir_is_null(type))
7,841✔
573
      return MIR_MEM_NONE;
574

575
   switch (mir_type_data(mu, type)->class) {
6,549✔
576
   case MIR_TYPE_UARRAY:
577
   case MIR_TYPE_CARRAY:
578
   case MIR_TYPE_RECORD:
579
   case MIR_TYPE_POINTER:
580
   case MIR_TYPE_ACCESS:
581
      break;
5,101✔
582
   default:
583
      return MIR_MEM_NONE;
584
   }
585

586
   mir_stamp_t stamp = mir_get_stamp(mu, value);
5,101✔
587
   if (mir_is_null(stamp))
5,101✔
588
      return MIR_MEM_TOP;
589

590
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
797✔
591
   assert(sd->kind == MIR_STAMP_POINTER);
797✔
592

593
   return sd->u.pointer.memory;
797✔
594
}
595

596
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
154,270✔
597
{
598
   switch (value.tag) {
154,270✔
599
   case MIR_TAG_PARAM:
13✔
600
      return mir_param_data(mu, value)->name;
13✔
601
   case MIR_TAG_VAR:
35,084✔
602
      return mir_var_data(mu, value)->name;
35,084✔
603
   case MIR_TAG_LINKAGE:
116,651✔
604
      return AGET(mu->linkage, value.id);
116,651✔
605
   case MIR_TAG_EXTVAR:
2,522✔
606
      return AGET(mu->extvars, value.id);
2,522✔
607
   case MIR_TAG_NULL:
×
608
      return mu->name;
×
609
   default:
610
      return NULL;
611
   }
612
}
613

614
void mir_set_result(mir_unit_t *mu, mir_type_t type)
20,622✔
615
{
616
   assert(mu->kind == MIR_UNIT_FUNCTION || mu->kind == MIR_UNIT_THUNK);
20,622✔
617
   mu->result = type;
20,622✔
618
}
20,622✔
619

620
mir_type_t mir_get_result(mir_unit_t *mu)
21,688✔
621
{
622
   return mu->result;
21,688✔
623
}
624

625
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
65,861✔
626
{
627
   switch (value.tag) {
65,861✔
628
   case MIR_TAG_NODE:
65,861✔
629
      {
630
         node_data_t *n = mir_node_data(mu, value);
65,861✔
631
         assert(n->op == MIR_OP_LOCUS);
65,861✔
632
         return n->locus;
65,861✔
633
      }
634
      break;
×
635
   default:
×
636
      should_not_reach_here();
637
   }
638
}
639

640
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value)
31,586✔
641
{
642
   switch (value.tag) {
31,586✔
643
   case MIR_TAG_VAR:
31,586✔
644
      return mir_var_data(mu, value)->flags;
31,586✔
645
   default:
646
      return 0;
647
   }
648
}
649

650
mir_type_t mir_get_var_type(mir_unit_t *mu, mir_value_t value)
48,747✔
651
{
652
   switch (value.tag) {
48,747✔
653
   case MIR_TAG_VAR:
48,747✔
654
      return mir_var_data(mu, value)->type;
48,747✔
655
   default:
×
656
      return MIR_NULL_TYPE;
×
657
   }
658
}
659

660
bool mir_is_integral(mir_unit_t *mu, mir_value_t value)
80,080✔
661
{
662
   if (value.tag == MIR_TAG_CONST)
80,080✔
663
      return true;
664

665
   mir_type_t type = mir_get_type(mu, value);
34,906✔
666
   if (mir_is_null(type))
34,906✔
667
      return false;
668

669
   switch (mir_type_data(mu, type)->class) {
34,906✔
670
   case MIR_TYPE_INT:
671
   case MIR_TYPE_OFFSET:
672
      return true;
673
   default:
5,941✔
674
      return false;
5,941✔
675
   }
676
}
677

678
bool mir_is_scalar(mir_unit_t *mu, mir_value_t value)
25,443✔
679
{
680
   if (value.tag == MIR_TAG_CONST)
25,443✔
681
      return true;
682

683
   mir_type_t type = mir_get_type(mu, value);
15,666✔
684
   if (mir_is_null(type))
15,666✔
685
      return false;
686

687
   switch (mir_type_data(mu, type)->class) {
15,666✔
688
   case MIR_TYPE_INT:
689
   case MIR_TYPE_OFFSET:
690
   case MIR_TYPE_REAL:
691
   case MIR_TYPE_ACCESS:
692
      return true;
693
   default:
68✔
694
      return false;
68✔
695
   }
696
}
697

698
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
129,162✔
699
{
700
   if (value.tag == MIR_TAG_CONST)
129,162✔
701
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
32,257✔
702
   else
703
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
96,905✔
704
}
705

706
bool mir_is_time(mir_unit_t *mu, mir_value_t value)
5,288✔
707
{
708
   if (value.tag == MIR_TAG_CONST)
5,288✔
709
      return true;
710

711
   return mir_equals(mir_get_type(mu, value), mir_time_type(mu));
261✔
712
}
713

714
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class)
537,563✔
715
{
716
   mir_type_t type = mir_get_type(mu, value);
537,563✔
717
   if (mir_is_null(type))
537,563✔
718
      return false;
719

720
   return mir_type_data(mu, type)->class == class;
513,676✔
721
}
722

723
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class)
197✔
724
{
725
   mir_type_t type = mir_get_type(mu, value);
197✔
726
   if (mir_is_null(type))
197✔
727
      return false;
728

729
   const type_data_t *td = mir_type_data(mu, type);
197✔
730
   if (td->class != MIR_TYPE_POINTER)
197✔
731
      return false;
732

733
   return mir_type_data(mu, td->u.pointer)->class == class;
197✔
734
}
735

736
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
100,535✔
737
{
738
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
100,535✔
739
}
740

741
bool mir_is_offset(mir_unit_t *mu, mir_value_t value)
146,482✔
742
{
743
   if (value.tag == MIR_TAG_CONST)
146,482✔
744
      return true;
745

746
   return mir_is(mu, value, MIR_TYPE_OFFSET);
37,445✔
747
}
748

749
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
1,168,930✔
750
{
751
   switch (value.tag) {
1,168,930✔
752
   case MIR_TAG_CONST:
753
      return true;
754
   case MIR_TAG_NODE:
17,104✔
755
      {
756
         node_data_t *n = mir_node_data(mu, value);
17,104✔
757
         switch (n->op) {
17,104✔
758
         case MIR_OP_CONST:
759
         case MIR_OP_CONST_REAL:
760
         case MIR_OP_CONST_ARRAY:
761
         case MIR_OP_CONST_REP:
762
         case MIR_OP_CONST_RECORD:
763
         case MIR_OP_NULL:
764
            return true;
765
         default:
×
766
            return false;
×
767
         }
768
      }
769
   default:
×
770
      return false;
×
771
   }
772
}
773

774
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
5✔
775
{
776
   const mir_mem_t a_mem = mir_get_mem(mu, a);
5✔
777
   if (a_mem == MIR_MEM_NONE)
5✔
778
      return false;
779

780
   if (mir_equals(a, b))
5✔
781
      return true;
782

783
   const mir_mem_t b_mem = mir_get_mem(mu, b);
5✔
784
   if (b_mem == MIR_MEM_NONE)
5✔
785
      return false;
786

787
   if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
5✔
788
      // Aliasing is only relevant in the presence of mutability
789
      return false;
790
   }
791

792
   return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
3✔
793
}
794

795
#ifdef DEBUG
796
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
1,210,559✔
797
{
798
   if (value.tag == MIR_TAG_CONST) {
1,210,559✔
799
      const mir_class_t class = mir_type_data(mu, type)->class;
1,151,255✔
800
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
1,151,255✔
801
   }
802
   else
803
      return mir_equals(mir_get_type(mu, value), type);
59,304✔
804
}
805
#endif
806

807
mir_value_t mir_enum(unsigned value)
221,876✔
808
{
809
   assert(value < MIR_ID_MAX);
221,876✔
810
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
221,876✔
811
}
812

813
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
338,073✔
814
{
815
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
338,073✔
816
      const unsigned biased = value + SMALL_CONST_BIAS;
331,287✔
817
      return (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
331,287✔
818
   }
819
   else {
820
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
6,786✔
821
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
6,786✔
822
      n->iconst = value;
6,786✔
823

824
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
6,786✔
825
   }
826
}
827

828
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
20,901✔
829
{
830
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
20,901✔
831
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
20,901✔
832
   n->dconst = value;
20,901✔
833

834
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
20,901✔
835
}
836

837
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
21,166✔
838
                            const mir_value_t *values, size_t count)
839
{
840
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
42,332✔
841
                                 MIR_NULL_STAMP, count);
21,166✔
842

843
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
21,166✔
844
                "constant array must have constrained array type");
845
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
21,166✔
846
              "have %zd", mir_get_size(mu, type), count);
847

848
   mir_type_t elem = mir_get_elem(mu, type);
21,166✔
849

850
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
21,166✔
851
   int64_t low = INT64_MAX, high = INT64_MIN;
21,166✔
852
   for (size_t i = 0; i < count; i++) {
1,180,083✔
853
      mir_set_arg(mu, n, i, values[i]);
1,158,917✔
854

855
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
1,158,917✔
856
                 "element %zd has wrong type", i);
857
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
1,158,917✔
858

859
      int64_t cval;
1,158,917✔
860
      if (integral && mir_get_const(mu, values[i], &cval)) {
1,158,917✔
861
         low = MIN(low, cval);
1,143,345✔
862
         high = MAX(high, cval);
1,143,345✔
863
      }
864
   }
865

866
   mir_stamp_t stamp = MIR_NULL_STAMP;
21,166✔
867
   if (integral && low <= high)
21,166✔
868
      stamp = mir_int_stamp(mu, low, high);
20,501✔
869

870
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
21,166✔
871

872
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
21,166✔
873
}
874

875
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
279✔
876
                                mir_value_t value, unsigned rep)
877
{
878
   mir_stamp_t stamp = mir_get_stamp(mu, value);
279✔
879
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
279✔
880
                                    value, mir_enum(rep));
881

882
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
279✔
883
              "constant array must have constrained array class");
884
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
279✔
885

886
   return result;
279✔
887
}
888

889
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,139✔
890
                             const mir_value_t *values, size_t count)
891
{
892
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
4,278✔
893
                                 MIR_NULL_STAMP, count);
2,139✔
894

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

897
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,139✔
898
              "const record must have record type");
899
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,139✔
900
              td->u.record.count, count);
901

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

905
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
5,412✔
906
                               td->u.record.fields[i]),
907
                 "wrong type for element %d", i);
908
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
5,412✔
909
   }
910

911
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,139✔
912
}
913

914
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
38,671✔
915
                                   mir_value_t left, mir_value_t right,
916
                                   mir_value_t locus, mir_stamp_t stamp)
917
{
918
   mir_value_t result;
38,671✔
919
   if (mir_is_null(locus))
38,671✔
920
      result = mir_build_2(mu, op, type, stamp, left, right);
33,860✔
921
   else
922
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
4,811✔
923

924
#ifdef DEBUG
925
   mir_type_t ltype = mir_get_type(mu, left);
38,671✔
926
   mir_type_t rtype = mir_get_type(mu, right);
38,671✔
927
#endif
928

929
   MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
38,671✔
930
              || mir_equals(ltype, rtype),
931
              "arguments to %s are not the same type", mir_op_string(op));
932
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
38,671✔
933
              "locus argument to %s is not a locus", mir_op_string(op));
934

935
   return result;
38,671✔
936
}
937

938
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
14,876✔
939
                                    mir_type_t type, mir_value_t left,
940
                                    mir_value_t right, mir_value_t locus)
941
{
942
   int64_t lval, rval, cval;
14,876✔
943
   const bool lconst = mir_get_const(mu, left, &lval);
14,876✔
944
   const bool rconst = mir_get_const(mu, right, &rval);
14,876✔
945

946
   if (lconst && lval == 0)
14,876✔
947
      return right;
×
948
   else if (rconst && rval == 0)
14,876✔
949
      return left;
1✔
950
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
14,875✔
951
      return mir_const(mu, type, cval);
3✔
952

953
   double lreal, rreal;
14,872✔
954
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
14,872✔
955
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
14,872✔
956

957
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
14,872✔
958
      return right;
1✔
959
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
14,871✔
960
      return left;
2✔
961
   else if (lconst_real && rconst_real)
14,869✔
962
      return mir_const_real(mu, type, lreal + rreal);
4✔
963

964
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
14,865✔
965
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
14,865✔
966
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
14,865✔
967

968
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
14,865✔
969
}
970

971
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
12,969✔
972
                          mir_value_t right)
973
{
974
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
12,969✔
975
}
976

977
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
1,907✔
978
                               mir_value_t left, mir_value_t right,
979
                               mir_value_t locus)
980
{
981
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
1,907✔
982
}
983

984
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
20,147✔
985
                                    mir_type_t type, mir_value_t left,
986
                                    mir_value_t right, mir_value_t locus)
987
{
988
   int64_t lval, rval, cval;
20,147✔
989
   const bool lconst = mir_get_const(mu, left, &lval);
20,147✔
990
   const bool rconst = mir_get_const(mu, right, &rval);
20,147✔
991

992
   if (lconst && lval == 0)
20,147✔
993
      return right;
3✔
994
   else if (rconst && rval == 0)
20,144✔
995
      return left;
3✔
996
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
20,141✔
997
      return mir_const(mu, type, cval);
1✔
998
   else if (mir_equals(left, right))
20,140✔
999
      return mir_const(mu, type, 0);
159✔
1000

1001
   double lreal, rreal;
19,981✔
1002
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
19,981✔
1003
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
19,981✔
1004

1005
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
19,981✔
1006
      return right;
×
1007
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
19,981✔
1008
      return left;
4✔
1009
   else if (lconst_real && rconst_real)
19,977✔
1010
      return mir_const_real(mu, type, lreal - rreal);
×
1011

1012
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
19,977✔
1013
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
19,977✔
1014
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
19,977✔
1015

1016
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
19,977✔
1017
}
1018

1019
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
17,774✔
1020
                          mir_value_t right)
1021
{
1022
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
17,774✔
1023
}
1024

1025
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
2,045✔
1026
                               mir_value_t left, mir_value_t right,
1027
                               mir_value_t locus)
1028
{
1029
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
2,045✔
1030
}
1031

1032
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
7,484✔
1033
{
1034
   int64_t cval;
7,484✔
1035
   if (mir_get_const(mu, value, &cval))
7,484✔
1036
      return mir_const(mu, type, -cval);
1✔
1037

1038
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
7,483✔
1039
                                    MIR_NULL_STAMP, value);
7,483✔
1040

1041
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
7,483✔
1042

1043
   return result;
7,483✔
1044
}
1045

1046
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
556✔
1047
                               mir_value_t value, mir_value_t locus)
1048
{
1049
   int64_t cval;
556✔
1050
   if (mir_get_const(mu, value, &cval) && cval >= 0)
556✔
1051
      return mir_const(mu, type, -cval);
×
1052
   // TODO: check if stamp bounds are non-negative
1053

1054
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
556✔
1055
                                    MIR_NULL_STAMP, value, locus);
556✔
1056

1057
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
556✔
1058
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
556✔
1059
              "locus argument must be debug locus");
1060

1061
   return result;
556✔
1062
}
1063

1064
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
233✔
1065
{
1066
   int64_t lconst;
233✔
1067
   if (mir_get_const(mu, value, &lconst))
233✔
1068
      return mir_const(mu, type, llabs(lconst));
×
1069

1070
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
233✔
1071
                                    value);
1072

1073
   MIR_ASSERT(mir_is_scalar(mu, value), "argument must be scalar");
233✔
1074

1075
   return result;
233✔
1076
}
1077

1078
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
2,250✔
1079
                                    mir_type_t type, mir_value_t left,
1080
                                    mir_value_t right, mir_value_t locus)
1081
{
1082
   int64_t lval, rval, cval;
2,250✔
1083
   const bool lconst = mir_get_const(mu, left, &lval);
2,250✔
1084
   const bool rconst = mir_get_const(mu, right, &rval);
2,250✔
1085

1086
   if (lconst && lval == 0)
2,250✔
1087
      return left;
×
1088
   else if (rconst && rval == 0)
2,250✔
1089
      return right;
×
1090
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
2,250✔
1091
      return mir_const(mu, type, cval);
×
1092

1093
   double lreal, rreal;
2,250✔
1094
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
2,250✔
1095
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
2,250✔
1096

1097
   if (lconst_real && rconst_real)
2,250✔
1098
      return mir_const_real(mu, type, lreal * rreal);
158✔
1099

1100
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
2,092✔
1101
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
2,092✔
1102
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
2,092✔
1103

1104
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
2,092✔
1105
}
1106

1107
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
2,250✔
1108
                          mir_value_t right)
1109
{
1110
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
2,250✔
1111
}
1112

1113
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
328✔
1114
                               mir_value_t left, mir_value_t right,
1115
                               mir_value_t locus)
1116
{
1117
   return mir_build_sub_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
328✔
1118
}
1119

1120
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
885✔
1121
                          mir_value_t right)
1122
{
1123
   int64_t lval, rval;
885✔
1124
   const bool lconst = mir_get_const(mu, left, &lval);
885✔
1125
   const bool rconst = mir_get_const(mu, right, &rval);
885✔
1126

1127
   if (lconst && rconst && rval != 0)
885✔
1128
      return mir_const(mu, type, lval / rval);
×
1129
   else if (rconst && rval == 1)
885✔
1130
      return left;
×
1131

1132
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
885✔
1133
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
885✔
1134
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
885✔
1135

1136
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
885✔
1137
                          MIR_NULL_VALUE, stamp);
885✔
1138
}
1139

1140
mir_value_t mir_build_rem(mir_unit_t *mu, mir_type_t type, mir_value_t left,
97✔
1141
                          mir_value_t right)
1142
{
1143
   int64_t lval, rval;
97✔
1144
   const bool lconst = mir_get_const(mu, left, &lval);
97✔
1145
   const bool rconst = mir_get_const(mu, right, &rval);
97✔
1146

1147
   if (lconst && rconst && lval > 0 && rval > 0)
97✔
1148
      return mir_const(mu, type, lval % rval);
1✔
1149

1150
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
96✔
1151
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
96✔
1152
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
96✔
1153

1154
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
96✔
1155
                          MIR_NULL_VALUE, stamp);
96✔
1156
}
1157

1158
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
153✔
1159
                          mir_value_t right)
1160
{
1161
   int64_t lval, rval;
153✔
1162
   const bool lconst = mir_get_const(mu, left, &lval);
153✔
1163
   const bool rconst = mir_get_const(mu, right, &rval);
153✔
1164

1165
   if (lconst && rconst && lval > 0 && rval > 0)
153✔
1166
      return mir_const(mu, type, lval % rval);
×
1167

1168
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
153✔
1169
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
153✔
1170

1171
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
153✔
1172
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
11✔
1173
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
11✔
1174

1175
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
11✔
1176
         // If both arguments are non-negative then rem is equivalent
1177
         // and cheaper to compute
1178
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1179
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1180
                                MIR_NULL_VALUE, stamp);
1✔
1181
      }
1182
   }
1183

1184
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
152✔
1185
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
152✔
1186
}
1187

1188
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
72✔
1189
                          mir_value_t right)
1190
{
1191
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
144✔
1192
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
72✔
1193
}
1194

1195
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
531✔
1196
                               mir_value_t left, mir_value_t right,
1197
                               mir_value_t locus)
1198
{
1199
   int64_t rconst;
531✔
1200
   if (mir_get_const(mu, right, &rconst)) {
531✔
1201
      if (rconst == 0)
435✔
1202
         return mir_const(mu, type, 1);
×
1203
      else if (rconst == 1)
435✔
1204
         return left;
×
1205
   }
1206

1207
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
531✔
1208
                                        locus, MIR_NULL_STAMP);
531✔
1209

1210
   MIR_ASSERT(mir_is_integral(mu, result),
531✔
1211
              "trapping exp may only be used with integer types");
1212

1213
   return result;
531✔
1214
}
1215

1216
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
6,494✔
1217
                                     mir_type_t type, mir_value_t left,
1218
                                     mir_value_t right)
1219
{
1220
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
6,494✔
1221

1222
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
6,494✔
1223
              mir_op_string(op));
1224
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
6,494✔
1225
              mir_op_string(op));
1226

1227
   return result;
6,494✔
1228
}
1229

1230
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
4,417✔
1231
{
1232
   int64_t lval, rval;
4,417✔
1233
   const bool lconst = mir_get_const(mu, left, &lval);
4,417✔
1234
   const bool rconst = mir_get_const(mu, right, &rval);
4,417✔
1235

1236
   mir_type_t t_bool = mir_bool_type(mu);
4,417✔
1237

1238
   if (lconst && rconst)
4,417✔
1239
      return mir_const(mu, t_bool, lval && rval);
3✔
1240
   else if (lconst)
4,415✔
1241
      return lval ? right : mir_const(mu, t_bool, 0);
×
1242
   else if (rconst)
4,415✔
1243
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1244

1245
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
4,413✔
1246
}
1247

1248
mir_value_t mir_build_nand(mir_unit_t *mu, mir_value_t left, mir_value_t right)
63✔
1249
{
1250
   int64_t lval, rval;
63✔
1251
   const bool lconst = mir_get_const(mu, left, &lval);
63✔
1252
   const bool rconst = mir_get_const(mu, right, &rval);
63✔
1253

1254
   mir_type_t t_bool = mir_bool_type(mu);
63✔
1255

1256
   if (lconst && rconst)
63✔
1257
      return mir_const(mu, t_bool, !(lval && rval));
1✔
1258

1259
   return mir_build_logical(mu, MIR_OP_NAND, t_bool, left, right);
62✔
1260
}
1261

1262
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
1,793✔
1263
{
1264
   int64_t lval, rval;
1,793✔
1265
   const bool lconst = mir_get_const(mu, left, &lval);
1,793✔
1266
   const bool rconst = mir_get_const(mu, right, &rval);
1,793✔
1267

1268
   mir_type_t t_bool = mir_bool_type(mu);
1,793✔
1269

1270
   if (lconst && rconst)
1,793✔
1271
      return mir_const(mu, t_bool, lval || rval);
3✔
1272
   else if (lconst)
1,791✔
1273
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1274
   else if (rconst)
1,790✔
1275
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1276

1277
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
1,789✔
1278
}
1279

1280
mir_value_t mir_build_nor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
64✔
1281
{
1282
   int64_t lval, rval;
64✔
1283
   const bool lconst = mir_get_const(mu, left, &lval);
64✔
1284
   const bool rconst = mir_get_const(mu, right, &rval);
64✔
1285

1286
   mir_type_t t_bool = mir_bool_type(mu);
64✔
1287

1288
   if (lconst && rconst)
64✔
1289
      return mir_const(mu, t_bool, !(lval || rval));
4✔
1290

1291
   return mir_build_logical(mu, MIR_OP_NOR, t_bool, left, right);
62✔
1292
}
1293

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

1300
   mir_type_t t_bool = mir_bool_type(mu);
106✔
1301
   if (lconst && rconst)
106✔
1302
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1303
   else if (mir_equals(left, right))
105✔
1304
      return mir_const(mu, t_bool, 0);
1✔
1305

1306
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
104✔
1307
}
1308

1309
mir_value_t mir_build_xnor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
64✔
1310
{
1311
   int64_t lval, rval;
64✔
1312
   const bool lconst = mir_get_const(mu, left, &lval);
64✔
1313
   const bool rconst = mir_get_const(mu, right, &rval);
64✔
1314

1315
   mir_type_t t_bool = mir_bool_type(mu);
64✔
1316
   if (lconst && rconst)
64✔
1317
      return mir_const(mu, t_bool, !(lval ^ rval));
×
1318

1319
   return mir_build_logical(mu, MIR_OP_XNOR, t_bool, left, right);
64✔
1320
}
1321

1322
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
2,681✔
1323
{
1324
   mir_type_t t_bool = mir_bool_type(mu);
2,681✔
1325

1326
   int64_t cval;
2,681✔
1327
   if (mir_get_const(mu, value, &cval))
2,681✔
1328
      return mir_const(mu, t_bool, !cval);
2✔
1329

1330
   if (mir_get_op(mu, value) == MIR_OP_NOT)
2,679✔
1331
      return mir_get_arg(mu, value, 0);
31✔
1332

1333
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
2,648✔
1334
                                    MIR_NULL_STAMP, value);
2,648✔
1335

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

1338
   return result;
2,648✔
1339
}
1340

1341
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
33,642✔
1342
                          mir_value_t right)
1343
{
1344
   int64_t lval, rval;
33,642✔
1345
   const bool lconst = mir_get_const(mu, left, &lval);
33,642✔
1346
   const bool rconst = mir_get_const(mu, right, &rval);
33,642✔
1347

1348
   mir_type_t t_bool = mir_bool_type(mu);
33,642✔
1349

1350
   if (lconst && rconst) {
33,642✔
1351
      switch (cmp) {
13✔
1352
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1353
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
2✔
1354
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
2✔
1355
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
2✔
1356
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
2✔
1357
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
2✔
1358
      default: should_not_reach_here();
1359
      }
1360
   }
1361

1362
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
33,629✔
1363
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
33,629✔
1364
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
33,629✔
1365

1366
   int64_t sconst;
33,629✔
1367
   if (mir_stamp_const(mu, stamp, &sconst))
33,629✔
1368
      return mir_const(mu, t_bool, sconst);
2✔
1369

1370
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
33,627✔
1371
                                    stamp, mir_enum(cmp), left, right);
1372

1373
   MIR_ASSERT(mir_equals(mir_get_type(mu, left), mir_get_type(mu, left)),
33,627✔
1374
              "arguments to cmp are not the same type");
1375

1376
   return result;
33,627✔
1377
}
1378

1379
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
72,055✔
1380
{
1381
   mir_type_t type = mir_get_type(mu, dest);
72,055✔
1382
   mir_type_t pointed = mir_get_pointer(mu, type);
72,055✔
1383

1384
   mir_build_2(mu, MIR_OP_STORE, pointed, MIR_NULL_STAMP, dest, src);
72,055✔
1385

1386
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
72,055✔
1387
              "store destination is not a pointer or variable");
1388
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
72,055✔
1389
              "source and destination have different types");
1390
}
72,055✔
1391

1392
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
117,307✔
1393
{
1394
   mir_type_t type = mir_get_type(mu, value);
117,307✔
1395
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
117,307✔
1396
   mir_type_t pointed = mir_get_pointer(mu, type);
117,307✔
1397

1398
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
117,307✔
1399

1400
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
117,307✔
1401
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
117,307✔
1402
              "argument to load is not a pointer or variable");
1403

1404
   return result;
117,307✔
1405
}
1406

1407
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
15,895✔
1408
                    mir_value_t count)
1409
{
1410
   int64_t cval;
15,895✔
1411
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
15,895✔
1412
      return;
233✔
1413
   else if (mir_equals(dest, src))
15,895✔
1414
      return;
1415

1416
   mir_type_t dtype = mir_get_type(mu, dest);
15,662✔
1417
   mir_type_t elem = mir_get_pointer(mu, dtype);
15,662✔
1418

1419
   if (mir_is_null(count))
15,662✔
1420
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
1,781✔
1421
   else
1422
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
13,881✔
1423

1424
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
15,662✔
1425
              "destination type is not a pointer");
1426
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
15,662✔
1427
              "source type is not a pointer");
1428
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
15,662✔
1429
              "source and destination types do not match");
1430
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
15,662✔
1431
              "count is not offset type");
1432
}
1433

1434
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
5,567✔
1435
                   mir_value_t count)
1436
{
1437
   int64_t cval;
5,567✔
1438
   if (mir_get_const(mu, count, &cval) && cval == 0)
5,567✔
1439
      return;
×
1440

1441
   mir_type_t dtype = mir_get_type(mu, dest);
5,567✔
1442
   mir_type_t elem = mir_get_pointer(mu, dtype);
5,567✔
1443

1444
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
5,567✔
1445

1446
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
5,567✔
1447
              "destination type is not a pointer");
1448
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
5,567✔
1449
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
5,567✔
1450
}
1451

1452
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
7,266✔
1453
                            mir_value_t count)
1454
{
1455
   mir_type_t ptr = mir_pointer_type(mu, type);
7,266✔
1456
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
7,266✔
1457

1458
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
7,266✔
1459
              "alloc element type cannot be array");
1460
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
7,266✔
1461

1462
   return result;
7,266✔
1463
}
1464

1465
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
2,718✔
1466
{
1467
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, MIR_NULL_STAMP);
2,718✔
1468

1469
#ifdef DEBUG
1470
   const mir_class_t class = mir_get_class(mu, type);
2,718✔
1471
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
2,718✔
1472
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1473
              "null type must be file, access, context, or pointer");
1474
#endif
1475

1476
   return result;
2,718✔
1477
}
1478

1479
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
410✔
1480
                          mir_value_t count)
1481
{
1482
   mir_type_t access = mir_access_type(mu, type);
410✔
1483

1484
   mir_value_t result;
410✔
1485
   if (mir_is_null(count))
410✔
1486
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
87✔
1487
   else
1488
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
323✔
1489

1490
#ifdef DEBUG
1491
   const mir_class_t class = mir_get_class(mu, type);
410✔
1492
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
410✔
1493
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1494
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1495
              "new type must be int, real, record, access, or uarray");
1496
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
410✔
1497
              "new count must have offset type");
1498
#endif
1499

1500
   return result;
410✔
1501
}
1502

1503
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
1,507✔
1504
{
1505
   mir_type_t type = mir_get_type(mu, access);
1,507✔
1506
   mir_stamp_t stamp = mir_get_stamp(mu, access);
1,507✔
1507
   mir_type_t pointed = mir_get_pointer(mu, type);
1,507✔
1508
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
1,507✔
1509

1510
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
1,507✔
1511
              "argument to all must be access type");
1512

1513
   return result;
1,507✔
1514
}
1515

1516
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
22,586✔
1517
{
1518
   mir_type_t type = mir_get_type(mu, array);
22,586✔
1519
   mir_type_t pointer = mir_get_pointer(mu, type);
22,586✔
1520
   mir_stamp_t stamp = mir_get_stamp(mu, array);
22,586✔
1521

1522
   if (mir_is_null(pointer))
22,586✔
1523
      pointer = mir_pointer_type(mu, type);
1,639✔
1524

1525
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
22,586✔
1526
                                    pointer, stamp, array);
1527

1528
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
22,586✔
1529
              || mir_is(mu, array, MIR_TYPE_RECORD),
1530
              "argument to address of must be array or record");
1531

1532
   return result;
22,586✔
1533
}
1534

1535
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
32,406✔
1536
                                mir_value_t offset)
1537
{
1538
   mir_type_t type = mir_get_type(mu, array);
32,406✔
1539
   mir_stamp_t stamp = mir_get_stamp(mu, array);
32,406✔
1540

1541
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
32,406✔
1542
                                    array, offset);
1543

1544
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
32,406✔
1545
              "argument to array ref must be pointer or signal");
1546
   MIR_ASSERT(mir_is_offset(mu, offset),
32,406✔
1547
              "offset argument to array ref must be offset");
1548

1549
   return result;
32,406✔
1550
}
1551

1552
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
37,806✔
1553
                                 unsigned field)
1554
{
1555
   mir_type_t pointer = mir_get_type(mu, record);
37,806✔
1556

1557
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
37,806✔
1558

1559
   mir_type_t type = MIR_NULL_TYPE;
37,806✔
1560
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
37,806✔
1561
      type = td->u.record.fields[field + td->u.record.count];
37,806✔
1562

1563
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, MIR_NULL_STAMP,
37,806✔
1564
                                    record, mir_enum(field));
1565

1566
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
37,806✔
1567
              "record ref argument must be pointer to record");
1568
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
37,806✔
1569
              "record ref argument must be pointer to record");
1570
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
37,806✔
1571

1572
   return result;
37,806✔
1573
}
1574

1575
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
29,045✔
1576
                           const mir_dim_t *dims, int ndims)
1577
{
1578
   mir_type_t type = mir_get_type(mu, data);
29,045✔
1579
   mir_stamp_t stamp = mir_get_stamp(mu, data);
29,045✔
1580

1581
   const type_data_t *td = mir_type_data(mu, type);
29,045✔
1582
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
29,045✔
1583

1584
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
29,045✔
1585

1586
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
58,090✔
1587
                                  ndims * 3 + 1);
29,045✔
1588

1589
   mir_set_arg(mu, n, 0, data);
29,045✔
1590

1591
   for (int i = 0; i < ndims; i++) {
58,501✔
1592
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
29,456✔
1593
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
29,456✔
1594
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
29,456✔
1595
   }
1596

1597
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
29,045✔
1598
              "wrapped data is not pointer or signal");
1599

1600
   for (int i = 0; i < ndims; i++) {
58,501✔
1601
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
29,456✔
1602
                 "dimension %d left bound must be integral", i + 1);
1603
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
29,456✔
1604
                 "dimension %d right bound must be integral", i + 1);
1605
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
29,456✔
1606
                 "dimension %d direction must be bool", i + 1);
1607
   }
1608

1609
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
29,045✔
1610
}
1611

1612
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
26,329✔
1613
{
1614
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
26,329✔
1615
      return mir_get_arg(mu, array, 0);
1,978✔
1616

1617
   mir_type_t type = mir_get_type(mu, array);
24,351✔
1618
   mir_type_t pointer = mir_get_pointer(mu, type);
24,351✔
1619
   mir_stamp_t stamp = mir_get_stamp(mu, array);
24,351✔
1620

1621
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
24,351✔
1622

1623
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
24,351✔
1624
              "unwrap argument must be uarray");
1625

1626
   return result;
24,351✔
1627
}
1628

1629
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
20,764✔
1630
{
1631
   mir_type_t t_offset = mir_offset_type(mu);
20,764✔
1632
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
20,764✔
1633
                                    MIR_NULL_STAMP, array,
20,764✔
1634
                                    mir_const(mu, t_offset, dim));
1635

1636
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
20,764✔
1637
              "uarray len argument must be uarrray");
1638

1639
#ifdef DEBUG
1640
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
20,764✔
1641
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
20,764✔
1642
#endif
1643

1644
   return result;
20,764✔
1645
}
1646

1647
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
49,299✔
1648
                                       mir_type_t type, int arg_index,
1649
                                       mir_value_t array, int dim)
1650
{
1651
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
49,299✔
1652
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,515✔
1653

1654
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
47,784✔
1655
                                    array, mir_enum(dim));
1656

1657
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
47,784✔
1658
              "cannot use %s with non-uarray type", mir_op_string(op));
1659

1660
#ifdef DEBUG
1661
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
47,784✔
1662
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
47,784✔
1663
#endif
1664

1665
   return result;
47,784✔
1666
}
1667

1668
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
17,219✔
1669
{
1670
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
17,219✔
1671
                              0, array, dim);
1672
}
1673

1674
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
14,899✔
1675
{
1676
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
14,899✔
1677
                              1, array, dim);
1678
}
1679

1680
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
17,181✔
1681
{
1682
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
17,181✔
1683
                              2, array, dim);
1684
}
1685

1686
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
6,141✔
1687
                                   mir_value_t right, mir_value_t dir)
1688
{
1689
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
6,141✔
1690
                                    mir_offset_type(mu), MIR_NULL_STAMP,
6,141✔
1691
                                    left, right, dir);
1692

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

1698
   return result;
6,141✔
1699
}
1700

1701
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
4,610✔
1702
                                 mir_value_t right, mir_value_t dir)
1703
{
1704
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
4,610✔
1705
                                    mir_bool_type(mu), MIR_NULL_STAMP,
4,610✔
1706
                                    left, right, dir);
1707

1708
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left), mir_get_type(mu, left)),
4,610✔
1709
              "left and right are not the same type");
1710
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
4,610✔
1711
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
4,610✔
1712

1713
   return result;
4,610✔
1714
}
1715

1716
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
35,160✔
1717
{
1718
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
35,160✔
1719
               mir_cast_value(target));
35,160✔
1720

1721
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
35,160✔
1722
}
35,160✔
1723

1724
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
32,961✔
1725
                    mir_block_t bfalse)
1726
{
1727
   int64_t tconst;
32,961✔
1728
   if (mir_get_const(mu, test, &tconst)) {
32,961✔
1729
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
1✔
1730
      return;
1✔
1731
   }
1732

1733
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
32,960✔
1734
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
32,960✔
1735

1736
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
32,960✔
1737
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
32,960✔
1738
              "invalid cond targets");
1739
}
1740

1741
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
12,518✔
1742
                             mir_value_t vtrue, mir_value_t vfalse)
1743
{
1744
   int64_t tconst;
12,518✔
1745
   if (mir_get_const(mu, test, &tconst))
12,518✔
1746
      return tconst ? vtrue : vfalse;
136✔
1747
   else if (mir_equals(vtrue, vfalse))
12,382✔
1748
      return vtrue;
1✔
1749

1750
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
12,381✔
1751
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
12,381✔
1752
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
12,381✔
1753

1754
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
12,381✔
1755
                                    vtrue, vfalse);
1756

1757
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
12,381✔
1758
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
12,381✔
1759
              "true argument to select is not expected type");
1760
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
12,381✔
1761
              "false argument to select is not expected type");
1762

1763
   return result;
12,381✔
1764
}
1765

1766
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
1767
{
1768
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
1769
                                 ninputs * 2);
1770

1771
   for (int i = 0; i < ninputs; i++)
3✔
1772
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
1773

1774
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
1775
}
1776

1777
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
1778
                   mir_block_t block, mir_value_t value)
1779
{
1780
   node_data_t *n = mir_node_data(mu, phi);
2✔
1781
   assert(n->op == MIR_OP_PHI);
2✔
1782
   assert(nth * 2 < n->nargs);
2✔
1783

1784
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
1785
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
1786

1787
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
1788

1789
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
1790
              "phi input %d has wrong type", nth);
1791

1792
#ifdef DEBUG
1793
   if (value.tag != MIR_TAG_CONST) {
2✔
1794
      const block_data_t *bd = mir_block_data(mu, block);
2✔
1795
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
1796
         if (bd->nodes[i] == value.id)
2✔
1797
         return;
1798
      }
1799

1800
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
1801
   }
1802
#endif
1803
}
1804

1805
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
623✔
1806
                    const mir_value_t *cases, const mir_block_t *blocks,
1807
                    int ncases)
1808
{
1809
   int64_t cval;
623✔
1810
   if (mir_get_const(mu, value, &cval)) {
623✔
1811
      for (int i = 0; i < ncases; i++) {
3✔
1812
         int64_t cmp;
2✔
1813
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
1814
            mir_build_jump(mu, blocks[i]);
1✔
1815
            return;
1✔
1816
         }
1817
      }
1818

1819
      mir_build_jump(mu, def);
1✔
1820
      return;
1✔
1821
   }
1822

1823
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,242✔
1824
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
621✔
1825

1826
   mir_set_arg(mu, n, 0, value);
621✔
1827
   mir_set_arg(mu, n, 1, mir_cast_value(def));
621✔
1828

1829
   for (int i = 0; i < ncases; i++) {
5,222✔
1830
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
4,601✔
1831
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
4,601✔
1832
   }
1833

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

1836
#ifdef DEBUG
1837
   mir_type_t type = mir_get_type(mu, value);
621✔
1838
   for (int i = 0; i < ncases; i++) {
5,222✔
1839
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
4,601✔
1840
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
4,601✔
1841
                 "choice and value types do not match");
1842

1843
      for (int j = 0; j < i; j++)
244,553✔
1844
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
239,952✔
1845
   }
1846
#endif
1847
}
1848

1849
void mir_build_return(mir_unit_t *mu, mir_value_t value)
51,306✔
1850
{
1851
   if (mir_is_null(value))
51,306✔
1852
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
24,234✔
1853
   else
1854
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
27,072✔
1855

1856
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
51,306✔
1857
              "wrong result type");
1858
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
51,306✔
1859
              || mir_is_null(value), "cannot return a result");
1860
}
51,306✔
1861

1862
void mir_build_wait(mir_unit_t *mu, mir_block_t target, mir_value_t time)
13,468✔
1863
{
1864
   if (mir_is_null(time))
13,468✔
1865
      mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,180✔
1866
                  mir_cast_value(target));
8,180✔
1867
   else
1868
      mir_build_2(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,288✔
1869
                  mir_cast_value(target), time);
5,288✔
1870

1871
   MIR_ASSERT(mir_is_null(time) || mir_is_time(mu, time),
13,468✔
1872
              "time argument to wait is not a time");
1873
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
13,468✔
1874
              "wait only allowed in process or procedure");
1875
}
13,468✔
1876

1877
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
1✔
1878
{
1879
   if (value.tag != MIR_TAG_NODE)
1✔
1880
      return;   // Only useful for keeping nodes alive
1881

1882
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
1883
}
1884

1885
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
35,816✔
1886
                            mir_stamp_t stamp, const mir_value_t *args,
1887
                            unsigned nargs)
1888
{
1889
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
35,816✔
1890

1891
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
35,816✔
1892

1893
   for (int i = 0; i < nargs; i++)
140,482✔
1894
      mir_set_arg(mu, n, i + 1, args[i]);
104,666✔
1895

1896
   if (mir_is_null(type))
35,816✔
1897
      return MIR_NULL_VALUE;
4,963✔
1898
   else
1899
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,853✔
1900
}
1901

1902
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
878✔
1903
                     const mir_value_t *args, unsigned nargs)
1904
{
1905
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
1,756✔
1906
                                 MIR_NULL_STAMP, nargs + 2);
878✔
1907
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
878✔
1908
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
878✔
1909

1910
   for (int i = 0; i < nargs; i++)
3,112✔
1911
      mir_set_arg(mu, n, i + 2, args[i]);
2,234✔
1912

1913
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
878✔
1914
              "first argument to VHDL procedure must be context pointer");
1915
}
878✔
1916

1917
void mir_build_resume(mir_unit_t *mu, ident_t name)
878✔
1918
{
1919
   mir_value_t link = mir_add_linkage(mu, name);
878✔
1920
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
878✔
1921

1922
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
878✔
1923
              "resume must be first op in a block");
1924
}
878✔
1925

1926
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
423✔
1927
                              mir_stamp_t stamp, mir_value_t locus,
1928
                              const mir_value_t *args, int nargs)
1929
{
1930
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
423✔
1931

1932
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
423✔
1933
   mir_set_arg(mu, n, 1, locus);
423✔
1934

1935
   for (int i = 0; i < nargs; i++)
498✔
1936
      mir_set_arg(mu, n, i + 2, args[i]);
75✔
1937

1938
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
423✔
1939
              "locus argument to syscall must be a debug locus");
1940

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

1944
   if (mir_is_null(type))
423✔
1945
      return MIR_NULL_VALUE;
384✔
1946
   else
1947
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
39✔
1948
}
1949

1950
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
594✔
1951
{
1952
   if (mir_is_null(locus))
594✔
1953
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
462✔
1954
   else
1955
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
132✔
1956

1957
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
594✔
1958
              "locus argument to unreachable must be debug locus");
1959
}
594✔
1960
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
14,116✔
1961
                                mir_value_t left, mir_value_t right,
1962
                                mir_value_t dir, mir_value_t locus,
1963
                                mir_value_t hint)
1964
{
1965
   // TODO: check if can elide bounds
1966

1967
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
14,116✔
1968
               dir, locus, hint);
1969
}
14,116✔
1970

1971
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
3,019✔
1972
                           mir_value_t right, mir_value_t dir,
1973
                           mir_value_t locus, mir_value_t hint)
1974
{
1975
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
3,019✔
1976
                       locus, hint);
1977
}
3,019✔
1978

1979
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
11,097✔
1980
                           mir_value_t right, mir_value_t dir,
1981
                           mir_value_t locus, mir_value_t hint)
1982
{
1983
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
11,097✔
1984
                       locus, hint);
1985
}
11,097✔
1986

1987
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
1,097✔
1988
{
1989
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,097✔
1990
               ptr, locus);
1991

1992
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
1,097✔
1993
              "null check argument must be an access");
1994
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,097✔
1995
              "locus argument to null check must be a debug locus");
1996
}
1,097✔
1997

1998
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
100✔
1999
{
2000
   int64_t cval;
100✔
2001
   if (mir_get_const(mu, value, &cval) && cval != 0)
100✔
2002
      return;
×
2003

2004
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
100✔
2005
               value, locus);
2006

2007
   MIR_ASSERT(mir_is_integral(mu, value),
100✔
2008
              "argument to zero check must be integral");
2009
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
100✔
2010
              "locus argument to zero check must be a debug locus");
2011
}
2012

2013
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
6,768✔
2014
                            mir_value_t locus, mir_value_t dim)
2015
{
2016
   if (mir_equals(llen, rlen))
6,768✔
2017
      return;
2018

2019
   if (mir_is_null(dim))
6,768✔
2020
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
6,744✔
2021
                  llen, rlen, locus);
2022
   else
2023
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2024
                  llen, rlen, locus, dim);
2025

2026
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
6,768✔
2027
              "locus argument to length check must be a debug locus");
2028
}
2029

2030
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
513✔
2031
                              mir_value_t locus)
2032
{
2033
   int64_t cval;
513✔
2034
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
513✔
2035
      return;
×
2036

2037
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
513✔
2038
               exp, locus);
2039

2040
   MIR_ASSERT(mir_is_integral(mu, exp),
513✔
2041
              "exp argument to exponent check must be a integer");
2042
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
513✔
2043
              "locus argument to exponent check must be a debug locus");
2044
}
2045

2046
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
261✔
2047
                         mir_value_t length, mir_value_t kind,
2048
                         mir_value_t status)
2049
{
2050
   if (mir_is_null(status))
261✔
2051
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
235✔
2052
                  file, name, length, kind);
2053
   else
2054
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
26✔
2055
                  file, name, length, kind, status);
2056

2057
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
261✔
2058
              "file open first argument must be pointer to file");
2059
}
261✔
2060

2061
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
75✔
2062
                         mir_value_t inlen, mir_value_t outlen)
2063
{
2064
   if (mir_is_null(inlen))
75✔
2065
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
48✔
2066
                  file, ptr);
2067
   else if (mir_is_null(outlen))
27✔
2068
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
9✔
2069
                  file, ptr, inlen);
2070
   else
2071
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
2072
                  file, ptr, inlen, outlen);
2073

2074
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
75✔
2075
              "file read first argument must have file pointer type");
2076
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
75✔
2077
              "file read pointer argument must have pointer type");
2078
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
75✔
2079
              "file read inlen argument must be integral");
2080
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
75✔
2081
              "file read outlen argument must have pointer type");
2082
}
75✔
2083

2084
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
122✔
2085
                          mir_value_t length)
2086
{
2087
   if (mir_is_null(length))
122✔
2088
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2089
                  file, value);
2090
   else
2091
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
65✔
2092
                  file, value, length);
2093

2094
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
122✔
2095
              "file write first argument must have file pointer type");
2096
}
122✔
2097

2098
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
285✔
2099
                                      mir_value_t effective)
2100
{
2101
   mir_type_t type = mir_conversion_type(mu);
285✔
2102

2103
   mir_value_t result;
285✔
2104
   if (mir_is_null(effective) || mir_equals(effective, driving))
285✔
2105
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
267✔
2106
                           driving);
2107
   else
2108
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
18✔
2109
                           driving, effective);
2110

2111
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
285✔
2112
              "port conversion argument must be a closure");
2113
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
285✔
2114
              "port conversion argument must be a closure");
2115

2116
   return result;
285✔
2117
}
2118

2119
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
363✔
2120
                          mir_value_t count)
2121
{
2122
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
363✔
2123
               conv, nets, count);
2124

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

2133
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
405✔
2134
                           mir_value_t count)
2135
{
2136
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
405✔
2137
               conv, nets, count);
2138

2139
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
405✔
2140
              "conv argument to convert must be a port conversion");
2141
   MIR_ASSERT(mir_is_signal(mu, nets),
405✔
2142
              "nets argument to convert must be a signal");
2143
   MIR_ASSERT(mir_is_offset(mu, count),
405✔
2144
              "count argument to convert must be offset");
2145
}
405✔
2146

2147
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
411✔
2148
                              mir_value_t target, mir_value_t count,
2149
                              mir_value_t values)
2150
{
2151
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
411✔
2152
               cf, target, count, values);
2153

2154
   MIR_ASSERT(mir_is_signal(mu, target),
411✔
2155
              "put conversion target is not signal");
2156
   MIR_ASSERT(mir_is_offset(mu, count),
411✔
2157
              "put conversion net count is not offset type");
2158
   MIR_ASSERT(!mir_is_signal(mu, values),
411✔
2159
              "signal cannot be values argument for put conversion");
2160
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
411✔
2161
              "cf argument to put conversion must be conversion function");
2162
}
411✔
2163

2164
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
16,176✔
2165
                                  mir_value_t count, mir_value_t size,
2166
                                  mir_value_t value, mir_value_t flags,
2167
                                  mir_value_t locus, mir_value_t offset)
2168
{
2169
   mir_type_t stype = mir_signal_type(mu, type);
16,176✔
2170

2171
   mir_value_t result;
16,176✔
2172
   if (mir_is_null(offset))
16,176✔
2173
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
10,553✔
2174
                           count, size, value, flags, locus);
2175
   else
2176
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
5,623✔
2177
                           count, size, value, flags, locus, offset);
2178

2179
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
16,176✔
2180
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2181
              "signal must have integer or real type");
2182
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
16,176✔
2183
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
16,176✔
2184
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
16,176✔
2185
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
16,176✔
2186
              "locus argument to init signal is not debug locus");
2187
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
16,176✔
2188
              "offset argument must be pointer or null");
2189

2190
   return result;
16,176✔
2191
}
2192

2193
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
75✔
2194
                                      mir_value_t count, mir_value_t size,
2195
                                      mir_value_t locus, mir_value_t kind,
2196
                                      mir_value_t closure, mir_value_t delay)
2197
{
2198
   mir_type_t stype = mir_signal_type(mu, type);
75✔
2199

2200
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
75✔
2201
                                    MIR_NULL_STAMP, count, size, locus,
75✔
2202
                                    kind, closure, delay);
2203

2204
   MIR_ASSERT(mir_is_offset(mu, count),
75✔
2205
              "count argument to implicit signal is not offset");
2206
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
75✔
2207
              "kind argument to implicit signal is not offset");
2208
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
75✔
2209
              "closure argument to implicit signal is not a closure");
2210
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
75✔
2211
              "locus argument to implicit signal must be a debug locus");
2212
   MIR_ASSERT(mir_is_integral(mu, delay),
75✔
2213
              "delay argument to implicit signal must be time");
2214

2215
   return result;
75✔
2216
}
2217

2218
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
9,191✔
2219
                            mir_value_t count)
2220
{
2221
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,191✔
2222
               target, count);
2223

2224
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
9,191✔
2225
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
9,191✔
2226
}
9,191✔
2227

2228
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
10,596✔
2229
                              mir_value_t count, mir_value_t values,
2230
                              mir_value_t reject, mir_value_t after)
2231
{
2232
   int64_t nconst;
10,596✔
2233
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
10,596✔
2234
      mir_comment(mu, "Skip empty waveform");
×
2235
      return;
×
2236
   }
2237

2238
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
10,596✔
2239
               target, count, values, reject, after);
2240

2241
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
10,596✔
2242
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
10,596✔
2243
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
10,596✔
2244
}
2245

2246
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
177✔
2247
                              mir_value_t count, mir_value_t values)
2248
{
2249
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
177✔
2250
               target, count, values);
2251

2252
   MIR_ASSERT(mir_is_signal(mu, target),
177✔
2253
              "deposit signal target is not signal");
2254
   MIR_ASSERT(mir_is_offset(mu, count),
177✔
2255
              "deposit signal count is not offset type");
2256
   MIR_ASSERT(!mir_is_signal(mu, values),
177✔
2257
              "signal cannot be values argument for deposit signal");
2258
}
177✔
2259

2260
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
14,110✔
2261
{
2262
   mir_type_t type = mir_get_type(mu, signal);
14,110✔
2263
   mir_type_t pointer = mir_get_pointer(mu, type);
14,110✔
2264
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
14,110✔
2265

2266
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
14,110✔
2267
                                    stamp, signal);
2268

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

2272
   return result;
14,110✔
2273
}
2274

2275
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
123✔
2276
{
2277
   mir_type_t type = mir_get_type(mu, signal);
123✔
2278
   mir_type_t pointer = mir_get_pointer(mu, type);
123✔
2279
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
123✔
2280

2281
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
123✔
2282
                                    stamp, signal);
2283

2284
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
123✔
2285
              "argument to resolved must be signal");
2286

2287
   return result;
123✔
2288
}
2289

2290
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
171✔
2291
                                    mir_value_t count)
2292
{
2293
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
171✔
2294
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
171✔
2295

2296
   mir_value_t result;
171✔
2297
   if (mir_is_null(count))
171✔
2298
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
138✔
2299
   else
2300
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
33✔
2301
                           signal, count);
2302

2303
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
171✔
2304
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
171✔
2305
              "count argument must have offset type");
2306

2307
   return result;
171✔
2308
}
2309

2310
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
60✔
2311
                     mir_value_t values)
2312
{
2313
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
60✔
2314
               target, count, values);
2315

2316
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
60✔
2317
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
60✔
2318
}
60✔
2319

2320
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
30✔
2321
{
2322
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
30✔
2323
               target, count);
2324

2325
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
30✔
2326
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
30✔
2327
}
30✔
2328

2329
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
24✔
2330
                          mir_value_t reject, mir_value_t after)
2331
{
2332
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
2333
               target, count, reject, after);
2334

2335
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
24✔
2336
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
24✔
2337
}
24✔
2338

2339

2340
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
66✔
2341
                                 mir_value_t count)
2342
{
2343
   mir_type_t type = mir_time_type(mu);
66✔
2344

2345
   mir_value_t result;
66✔
2346
   if (mir_is_null(count))
66✔
2347
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
57✔
2348
   else
2349
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
9✔
2350
                           signal, count);
2351

2352
   MIR_ASSERT(mir_is_signal(mu, signal),
66✔
2353
              "signal argument to last event must have signal type");
2354
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
66✔
2355
              "length argument to last event must have offset type");
2356

2357
   return result;
66✔
2358
}
2359

2360
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
69✔
2361
                                  mir_value_t count)
2362
{
2363
   mir_type_t type = mir_time_type(mu);
69✔
2364

2365
   mir_value_t result;
69✔
2366
   if (mir_is_null(count))
69✔
2367
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
63✔
2368
                           signal);
2369
   else
2370
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
6✔
2371
                           signal, count);
2372

2373
   MIR_ASSERT(mir_is_signal(mu, signal),
69✔
2374
              "signal argument to last event must have signal type");
2375
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
69✔
2376
              "length argument to last event must have offset type");
2377

2378
   return result;
69✔
2379
}
2380

2381

2382
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
666✔
2383
                                         mir_value_t signal, mir_value_t count)
2384
{
2385
   mir_type_t t_bool = mir_bool_type(mu);
666✔
2386
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
666✔
2387
                                    signal, count);
2388

2389
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
666✔
2390
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
666✔
2391

2392
   return result;
666✔
2393
}
2394

2395
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
411✔
2396
                                 mir_value_t count)
2397
{
2398
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
411✔
2399
}
2400

2401
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
219✔
2402
                                  mir_value_t count)
2403
{
2404
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
219✔
2405
}
2406

2407
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
36✔
2408
                                   mir_value_t count)
2409
{
2410
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
36✔
2411
}
2412

2413
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
3,451✔
2414
                              mir_value_t resolution)
2415
{
2416
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,451✔
2417
               signal, resolution);
2418

2419
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
3,451✔
2420
   MIR_ASSERT(mir_is(mu, resolution, MIR_TYPE_RESOLUTION),
3,451✔
2421
              "resolution wrapper argument has wrong type");
2422
}
3,451✔
2423

2424
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
1,160✔
2425
                               mir_value_t source, mir_value_t count,
2426
                               mir_value_t reject, mir_value_t after)
2427
{
2428
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,160✔
2429
               target, source, count, reject, after);
2430

2431
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
1,160✔
2432
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,160✔
2433
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
1,160✔
2434
}
1,160✔
2435

2436
void mir_build_cover_stmt(mir_unit_t *mu, uint32_t tag)
961✔
2437
{
2438
   mir_build_1(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
961✔
2439
               mir_enum(tag));
2440
}
961✔
2441

2442
void mir_build_cover_branch(mir_unit_t *mu, uint32_t tag)
486✔
2443
{
2444
   mir_build_1(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
486✔
2445
               mir_enum(tag));
2446
}
486✔
2447

2448
void mir_build_cover_expr(mir_unit_t *mu, uint32_t tag)
849✔
2449
{
2450
   mir_build_1(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
849✔
2451
               mir_enum(tag));
2452
}
849✔
2453

2454
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
381✔
2455
{
2456
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
381✔
2457
               signal, mir_enum(tag));
2458

2459
   MIR_ASSERT(mir_is_signal(mu, signal),
381✔
2460
              "argument to cover toggle must be signal");
2461
}
381✔
2462

2463
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
12✔
2464
                           uint32_t tag)
2465
{
2466
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2467
               signal, low, mir_enum(tag));
2468

2469
   MIR_ASSERT(mir_is_signal(mu, signal),
12✔
2470
              "argument to cover state must be signal");
2471
}
12✔
2472
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
17,624✔
2473
                                   mir_value_t context)
2474
{
2475
   mir_value_t link = mir_add_linkage(mu, name);
17,624✔
2476
   mir_type_t type = mir_context_type(mu, name);
17,624✔
2477

2478
   mir_value_t result;
17,624✔
2479
   if (mir_is_null(context))
17,624✔
2480
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
17,442✔
2481
                           MIR_NULL_STAMP, link);
17,442✔
2482
   else
2483
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
182✔
2484
                           MIR_NULL_STAMP, link, context);
182✔
2485

2486
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
17,624✔
2487
              "invalid package init context argument");
2488
   MIR_ASSERT(mu->kind == MIR_UNIT_INSTANCE
17,624✔
2489
              || mu->kind == MIR_UNIT_PACKAGE
2490
              || mu->kind == MIR_UNIT_THUNK,
2491
              "cannot use package init here");
2492
   MIR_ASSERT(name != mu->name, "cyclic package init");
17,624✔
2493

2494
   return result;
17,624✔
2495
}
2496

2497
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
112✔
2498
{
2499
   mir_value_t link = mir_add_linkage(mu, name);
112✔
2500
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
112✔
2501
               link, locus);
2502

2503
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
112✔
2504
              "locus argument to process init must be a debug locus");
2505
}
112✔
2506

2507
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
162✔
2508
                                     mir_value_t context, mir_value_t path_name,
2509
                                     mir_value_t inst_name)
2510
{
2511
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
162✔
2512

2513
   mir_value_t result;
162✔
2514
   if (mir_is_null(path_name) && mir_is_null(inst_name))
162✔
2515
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
124✔
2516
                           link, context);
2517
   else {
2518
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
38✔
2519
                           link, context, path_name, inst_name);
2520

2521
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
38✔
2522
                 "path name argument must be array");
2523
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
38✔
2524
                 "inst name argument must be array");
2525
   }
2526

2527
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
162✔
2528
                "protected init type must be context");
2529
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
162✔
2530
              "invalid protected init context argument");
2531

2532
   return result;
162✔
2533
}
2534

2535
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
1,615✔
2536
{
2537
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
1,615✔
2538

2539
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,615✔
2540
              "locus argument to record scope must be a debug locus");
2541
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
1,615✔
2542
              "record scope type must be record");
2543
}
1,615✔
2544

2545
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
632✔
2546
{
2547
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
632✔
2548

2549
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
632✔
2550
              "locus argument to array scope must be a debug locus");
2551
}
632✔
2552

2553
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
45✔
2554
{
2555
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
45✔
2556

2557
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2558
              "locus argument to package scope must be a debug locus");
2559
}
45✔
2560

2561
void mir_build_pop_scope(mir_unit_t *mu)
2,292✔
2562
{
2563
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
2,292✔
2564
}
2,292✔
2565

2566
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
4,225✔
2567
                            mir_value_t locus)
2568
{
2569
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,225✔
2570
               signal, locus);
2571

2572
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
4,225✔
2573
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
4,225✔
2574
              "locus argument must have debug locus type");
2575
}
4,225✔
2576

2577
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
5,325✔
2578
                          mir_value_t count)
2579
{
2580
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,325✔
2581
               src, dst, count);
2582

2583
   MIR_ASSERT(mir_is_signal(mu, src),
5,325✔
2584
              "src argument to map signal is not a signal");
2585
   MIR_ASSERT(mir_is_signal(mu, dst),
5,325✔
2586
              "dst argument to map signal is not a signal");
2587
   MIR_ASSERT(mir_is_offset(mu, count),
5,325✔
2588
              "count argument to map signal is not offset type");
2589
}
5,325✔
2590

2591
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
219✔
2592
                         mir_value_t count)
2593
{
2594
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
219✔
2595
               src, dst, count);
2596

2597
   MIR_ASSERT(mir_is_signal(mu, dst),
219✔
2598
              "dst argument to map const is not a signal");
2599
   MIR_ASSERT(mir_is_offset(mu, count),
219✔
2600
              "count argument to map const is not offset type");
2601
}
219✔
2602

2603
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
57✔
2604
                            mir_value_t count)
2605
{
2606
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
57✔
2607
               src, dst, count);
2608

2609
   MIR_ASSERT(mir_is_signal(mu, src),
57✔
2610
              "src argument to map implicit is not a signal");
2611
   MIR_ASSERT(mir_is_signal(mu, dst),
57✔
2612
              "dst argument to map implicit is not a signal");
2613
   MIR_ASSERT(mir_is_offset(mu, count),
57✔
2614
              "count argument type to map implicit is not offset");
2615
}
57✔
2616

2617
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
45✔
2618
                                  mir_value_t right)
2619
{
2620
   mir_type_t type = mir_trigger_type(mu);
45✔
2621
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
45✔
2622
                                    MIR_NULL_STAMP, left, right);
45✔
2623

2624
   MIR_ASSERT(mir_is_signal(mu, left),
45✔
2625
              "cmp trigger left argument must be signal");
2626
   MIR_ASSERT(mir_is_integral(mu, right),
45✔
2627
              "cmp trigger right argument must be integer");
2628

2629
   return result;
45✔
2630
}
2631

2632
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
212✔
2633
                                       const mir_value_t *args, unsigned nargs)
2634
{
2635
   mir_type_t type = mir_trigger_type(mu);
212✔
2636
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
424✔
2637
                                 MIR_NULL_STAMP, nargs + 1);
212✔
2638

2639
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
212✔
2640

2641
   for (int i = 0; i < nargs; i++)
561✔
2642
      mir_set_arg(mu, n, i + 1, args[i]);
349✔
2643

2644
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
212✔
2645
}
2646

2647
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
33✔
2648
                                 mir_value_t right)
2649
{
2650
   mir_type_t type = mir_trigger_type(mu);
33✔
2651
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
33✔
2652
                                    MIR_NULL_STAMP, left, right);
33✔
2653

2654
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
33✔
2655
              "or trigger left argument must be trigger");
2656
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
33✔
2657
              "or trigger right argument must be trigger");
2658

2659
   return result;
33✔
2660
}
2661

2662
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
362✔
2663
{
2664
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
362✔
2665

2666
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
362✔
2667
              "add trigger argument must be trigger");
2668
}
362✔
2669

2670
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
11,412✔
2671
{
2672
   mir_value_t link = mir_add_linkage(mu, name);
11,412✔
2673
   mir_type_t type = mir_context_type(mu, name);
11,412✔
2674

2675
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
11,412✔
2676
                                    MIR_NULL_STAMP, link);
11,412✔
2677

2678
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
11,412✔
2679

2680
   return result;
11,412✔
2681
}
2682

2683
mir_value_t mir_build_link_var(mir_unit_t *mu, ident_t unit,
2,522✔
2684
                               mir_value_t context, ident_t name,
2685
                               mir_type_t type)
2686
{
2687
   mir_type_t pointer = mir_get_var_pointer(mu, type);
2,522✔
2688
   mir_value_t link = mir_add_linkage(mu, unit);
2,522✔
2689
   mir_value_t var = mir_add_extvar(mu, name);
2,522✔
2690
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
2,522✔
2691
                                    MIR_NULL_STAMP, link, context, var);
2,522✔
2692

2693
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
2,522✔
2694
              "first argument to link var must be context");
2695

2696
   return result;
2,522✔
2697
}
2698

2699
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
258✔
2700
                            mir_value_t length, mir_value_t locus)
2701
{
2702
   if (mir_is_null(locus))
258✔
2703
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
122✔
2704
                  spec, length);
2705
   else
2706
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
136✔
2707
                  spec, length, locus);
2708

2709
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
258✔
2710
              "spec argument to bind foreign must be a pointer");
2711
   MIR_ASSERT(mir_is_offset(mu, length),
258✔
2712
              "legnth argument to bind foreign must be offset");
2713
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
258✔
2714
              "locus argument to bind foreign value must be a debug locus");
2715
}
258✔
2716

2717
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
194✔
2718
                                    ident_t scope, mir_type_t type,
2719
                                    mir_stamp_t stamp)
2720
{
2721
   mir_type_t pointer = mir_get_var_pointer(mu, type);
194✔
2722
   mir_value_t link = mir_add_linkage(mu, scope);
194✔
2723
   mir_value_t result = mir_build_2(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
194✔
2724
                                    locus, link);
2725

2726
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
194✔
2727
              "bind external argument must be locus");
2728

2729
   return result;
194✔
2730
}
2731

2732
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
8,657✔
2733
{
2734
   mir_type_t type = MIR_NULL_TYPE;
8,657✔
2735
   if (hops == 0)
8,657✔
2736
      type = mir_self_type(mu);
993✔
2737
   else {
2738
      mir_shape_t *s = mu->parent;
7,664✔
2739
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
7,937✔
2740

2741
      if (s != NULL) type = s->type;
7,664✔
2742
   }
2743

2744
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
8,657✔
2745
                                    MIR_NULL_STAMP, mir_enum(hops));
8,657✔
2746

2747
   MIR_ASSERT(hops >= 0, "invalid hop count");
8,657✔
2748
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
8,657✔
2749

2750
   return result;
8,657✔
2751
}
2752

2753
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
45,517✔
2754
{
2755
   mir_type_t type = MIR_NULL_TYPE;
45,517✔
2756
   mir_value_t link = MIR_NULL_VALUE;
45,517✔
2757

2758
   mir_shape_t *s = mu->parent;
45,517✔
2759
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
56,046✔
2760

2761
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
45,517✔
2762
      type = s->slots[nth].pointer;
45,517✔
2763
      link = mir_add_linkage(mu, s->name);
45,517✔
2764
   }
2765

2766
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
45,517✔
2767
                                    mir_enum(hops), link, mir_enum(nth));
2768

2769
   MIR_ASSERT(hops > 0, "invalid hop count");
45,517✔
2770
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
45,517✔
2771

2772
   return result;
45,517✔
2773
}
2774

2775
void mir_build_sched_event(mir_unit_t *mu, mir_value_t signal,
5,816✔
2776
                           mir_value_t count)
2777
{
2778
   mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,816✔
2779
               signal, count);
2780

2781
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
5,816✔
2782
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
5,816✔
2783
}
5,816✔
2784

2785
void mir_build_clear_event(mir_unit_t *mu, mir_value_t signal,
499✔
2786
                           mir_value_t count)
2787
{
2788
   mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
499✔
2789
               signal, count);
2790

2791
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
499✔
2792
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
499✔
2793
}
499✔
2794

2795
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
45✔
2796
                                    mir_value_t context, mir_value_t locus,
2797
                                    mir_value_t bounds)
2798
{
2799
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
45✔
2800

2801
   mir_value_t result;
45✔
2802
   if (mir_is_null(bounds))
45✔
2803
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
39✔
2804
                           value, context, locus);
2805
   else
2806
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
6✔
2807
                           value, context, locus, bounds);
2808

2809
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
45✔
2810
              "invalid reflect value context argument");
2811
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
45✔
2812
              "locus argument to reflect value must be a debug locus");
2813

2814
   return result;
45✔
2815
}
2816

2817
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
42✔
2818
                                      mir_value_t locus, mir_value_t bounds)
2819
{
2820
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
42✔
2821

2822
   mir_value_t result;
42✔
2823
   if (mir_is_null(bounds))
42✔
2824
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
42✔
2825
                           context, locus);
2826
   else
2827
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
×
2828
                           context, locus, bounds);
2829

2830
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
42✔
2831
              "invalid reflect subtype context argument");
2832
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
42✔
2833
              "locus argument to reflect subtype must be a debug locus");
2834

2835
   return result;
42✔
2836
}
2837

2838
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
13,989✔
2839
                      mir_value_t length, mir_value_t severity,
2840
                      mir_value_t locus, mir_value_t hint_left,
2841
                      mir_value_t hint_right)
2842
{
2843
   int64_t value_const;
13,989✔
2844
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
13,989✔
2845
      mir_comment(mu, "Always true assertion");
×
2846
      return;
×
2847
   }
2848

2849
   if (mir_is_null(hint_left))
13,989✔
2850
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,248✔
2851
                  value, severity, message, length, locus);
2852
   else {
2853
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
11,482✔
2854
                                     MIR_NULL_STAMP, 7);
5,741✔
2855
      mir_set_arg(mu, n, 0, value);
5,741✔
2856
      mir_set_arg(mu, n, 1, severity);
5,741✔
2857
      mir_set_arg(mu, n, 2, message);
5,741✔
2858
      mir_set_arg(mu, n, 3, length);
5,741✔
2859
      mir_set_arg(mu, n, 4, locus);
5,741✔
2860
      mir_set_arg(mu, n, 5, hint_left);
5,741✔
2861
      mir_set_arg(mu, n, 6, hint_right);
5,741✔
2862

2863
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
5,741✔
2864
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
5,741✔
2865
   }
2866

2867
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
13,989✔
2868
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
13,989✔
2869
              "message parameter to assert is not a pointer");
2870
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
13,989✔
2871
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
13,989✔
2872
              "locus argument to report must be a debug locus");
2873
}
2874

2875
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,244✔
2876
                      mir_value_t severity, mir_value_t locus)
2877
{
2878
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,244✔
2879
               severity, message, length, locus);
2880

2881
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,244✔
2882
              "message parameter to report is not a pointer");
2883
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,244✔
2884
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,244✔
2885
              "locus argument to report must be a debug locus");
2886
}
2,244✔
2887

2888
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
812✔
2889
{
2890
   mir_type_t type = mir_string_type(mu);
812✔
2891
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
812✔
2892
                                    MIR_NULL_STAMP, kind);
812✔
2893

2894
   MIR_ASSERT(mir_is_offset(mu, kind),
812✔
2895
              "kind argument to instance name must be offset");
2896

2897
   return result;
812✔
2898
}
2899

2900
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
768✔
2901
                           mir_value_t strong)
2902
{
2903
   if (mir_is_null(strong))
768✔
2904
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
750✔
2905
   else
2906
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
2907
                  state, strong);
2908

2909
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
768✔
2910
   MIR_ASSERT(mir_is_null(strong)
768✔
2911
              || mir_check_type(mu, strong, mir_bool_type(mu)),
2912
                "strong argument not is not boolean");
2913
}
768✔
2914

2915
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_value_t context,
1,361✔
2916
                              mir_type_t atype, mir_type_t rtype)
2917
{
2918
   mir_type_t ctype = mir_closure_type(mu, atype, rtype);
1,361✔
2919
   mir_value_t link = mir_add_linkage(mu, func);
1,361✔
2920

2921
   mir_value_t result = mir_build_2(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
1,361✔
2922
                                    link, context);
2923

2924
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
1,361✔
2925
              "invalid closure context argument");
2926

2927
   return result;
1,361✔
2928
}
2929

2930
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
983✔
2931
                                         mir_value_t closure, mir_value_t ileft,
2932
                                         mir_value_t nlits)
2933
{
2934
   mir_type_t rtype = mir_resolution_type(mu, type);
983✔
2935
   mir_value_t result = mir_build_3(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
983✔
2936
                                    MIR_NULL_STAMP, closure, ileft, nlits);
983✔
2937

2938
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
983✔
2939
              "first argument to resolution wrapper must be closure");
2940

2941
   return result;
983✔
2942
}
2943

2944
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
65,863✔
2945
{
2946
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
65,863✔
2947
                                  MIR_NULL_STAMP, 0);
65,863✔
2948
   n->locus = obj;
65,863✔
2949

2950
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
65,863✔
2951
}
2952

2953
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
46,673✔
2954
{
2955
   mir_type_t from = mir_get_type(mu, value);
46,673✔
2956
   if (mir_equals(from, type))
46,673✔
2957
      return value;
46,673✔
2958

2959
   const mir_class_t class = mir_get_class(mu, type);
46,193✔
2960
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
46,193✔
2961

2962
   int64_t cval;
46,193✔
2963
   if (integral && mir_get_const(mu, value, &cval))
46,193✔
2964
      return mir_const(mu, type, cval);
414✔
2965

2966
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type,
45,779✔
2967
                                    MIR_NULL_STAMP, value);
45,779✔
2968

2969
#ifdef DEBUG
2970
   static const mir_class_t allowed[][2] = {
45,779✔
2971
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
2972
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
2973
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
2974
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
2975
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
2976
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
2977
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
2978
   };
2979

2980
   if (value.tag == MIR_TAG_CONST)
45,779✔
2981
      return result;
56✔
2982

2983
   const mir_class_t from_k = mir_get_class(mu, from);
45,723✔
2984

2985
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
83,506✔
2986
      if (from_k == allowed[i][0] && class == allowed[i][1])
83,506✔
2987
         return result;
45,723✔
2988
   }
2989

2990
   MIR_ASSERT(false, "invalid type conversion in cast");
×
2991
#else
2992
   return result;
2993
#endif
2994
}
2995

2996
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
×
2997
{
2998
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
2999

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