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

nickg / nvc / 15180719318

22 May 2025 07:28AM UTC coverage: 92.297% (-0.01%) from 92.31%
15180719318

push

github

nickg
Generate 'image helpers in MIR directly

351 of 379 new or added lines in 6 files covered. (92.61%)

15 existing lines in 4 files now uncovered.

69412 of 75205 relevant lines covered (92.3%)

520015.75 hits per line

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

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

40
mir_block_t mir_add_block(mir_unit_t *mu)
169,418✔
41
{
42
   assert(mu->kind != MIR_UNIT_PLACEHOLDER);
169,418✔
43

44
   mir_block_t b = { .tag = MIR_TAG_BLOCK, .id = mu->blocks.count };
169,418✔
45

46
   block_data_t bd = {
169,418✔
47
      .gap_pos = -1,
48
      .last_loc = LOC_INVALID,
49
   };
50
   APUSH(mu->blocks, bd);
169,418✔
51

52
   return b;
169,418✔
53
}
54

55
void mir_set_cursor(mir_unit_t *mu, mir_block_t block, unsigned pos)
1,594,401✔
56
{
57
   if (!mir_is_null(mu->cursor.block))
1,594,401✔
58
      mir_block_data(mu, mu->cursor.block)->last_loc = mu->cursor.loc;
1,537,908✔
59

60
   mu->cursor.block = block;
1,594,401✔
61
   mu->cursor.pos   = pos;
1,594,401✔
62

63
   if (mir_is_null(block))
1,594,401✔
64
      mu->cursor.loc = LOC_INVALID;
4✔
65
   else
66
      mu->cursor.loc = mir_block_data(mu, block)->last_loc;
1,594,397✔
67
}
1,594,401✔
68

69
mir_block_t mir_get_cursor(mir_unit_t *mu, unsigned *pos)
56,052✔
70
{
71
   if (pos != NULL)
56,052✔
72
      *pos = mu->cursor.pos;
×
73

74
   return mu->cursor.block;
56,052✔
75
}
76

77
void mir_set_loc(mir_unit_t *mu, const loc_t *loc)
1,956,251✔
78
{
79
   mu->cursor.loc = *loc;
1,956,251✔
80
}
1,956,251✔
81

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

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

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

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

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

111
   mir_set_cursor(mu, MIR_NULL_BLOCK, MIR_APPEND);
4✔
112
}
4✔
113

114
unsigned mir_count_blocks(mir_unit_t *mu)
116,710✔
115
{
116
   return mu->blocks.count;
116,710✔
117
}
118

119
mir_block_t mir_get_block(mir_unit_t *mu, unsigned nth)
375,245✔
120
{
121
   assert(nth < mu->blocks.count);
375,245✔
122
   return (mir_block_t) { .tag = MIR_TAG_BLOCK, .id = nth };
375,245✔
123
}
124

125
unsigned mir_count_nodes(mir_unit_t *mu, mir_block_t block)
445,047✔
126
{
127
   if (mir_is_null(block))
445,047✔
128
      return mu->num_nodes;
55,778✔
129
   else
130
      return mir_block_data(mu, block)->num_nodes;
389,269✔
131
}
132

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

140
unsigned mir_count_vars(mir_unit_t *mu)
111,556✔
141
{
142
   return mu->vars.count;
111,556✔
143
}
144

145
mir_value_t mir_get_var(mir_unit_t *mu, unsigned nth)
85,252✔
146
{
147
   assert(nth < mu->vars.count);
85,252✔
148
   return (mir_value_t) { .tag = MIR_TAG_VAR, .id = nth };
85,252✔
149
}
150

151
mir_value_t mir_get_param(mir_unit_t *mu, unsigned nth)
44,290✔
152
{
153
   assert(nth < mu->params.count);
44,290✔
154
   return (mir_value_t) { .tag = MIR_TAG_PARAM, .id = nth };
44,290✔
155
}
156

157
unsigned mir_count_params(mir_unit_t *mu)
13,750✔
158
{
159
   return mu->params.count;
13,750✔
160
}
161

162
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
2,876,224✔
163
{
164
   switch (node.tag) {
2,876,224✔
165
   case MIR_TAG_NODE:
2,850,614✔
166
      return mir_node_data(mu, node)->op;
2,850,614✔
167
   default:
168
      return _MIR_DELETED_OP;
169
   }
170
}
171

172
const loc_t *mir_get_loc(mir_unit_t *mu, mir_value_t node)
1,415,265✔
173
{
174
   return &(mir_node_data(mu, node)->loc);
1,415,265✔
175
}
176

177
unsigned mir_count_args(mir_unit_t *mu, mir_value_t node)
270,095✔
178
{
179
   return mir_node_data(mu, node)->nargs;
270,095✔
180
}
181

182
const mir_value_t *mir_get_args(mir_unit_t *mu, const node_data_t *nd)
4,397,390✔
183
{
184
   if (nd->nargs <= MIR_INLINE_ARGS)
4,397,390✔
185
      return nd->args;
2,421,448✔
186
   else {
187
      assert(nd->spilloff < mu->num_argspill);
1,975,942✔
188
      return mu->argspill + nd->spilloff;
1,975,942✔
189
   }
190
}
191

192
mir_value_t mir_get_arg(mir_unit_t *mu, mir_value_t node, unsigned nth)
4,398,034✔
193
{
194
   const node_data_t *nd = mir_node_data(mu, node);
4,398,034✔
195
   if (nth >= nd->nargs)
4,398,034✔
196
      return MIR_NULL_VALUE;
748✔
197
   else
198
      return mir_get_args(mu, nd)[nth];
4,397,286✔
199
}
200

201
mir_value_t mir_add_param(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
35,251✔
202
                          ident_t name)
203
{
204
   mir_value_t p = { .tag = MIR_TAG_PARAM, .id = mu->params.count };
35,251✔
205

206
   param_data_t pd = {
35,251✔
207
      .name  = name,
208
      .type  = type,
209
      .stamp = stamp,
210
   };
211
   APUSH(mu->params, pd);
35,251✔
212

213
   return p;
35,251✔
214
}
215

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

221
   mir_mem_t mem = MIR_MEM_STACK;
62,535✔
222
   if (flags & MIR_VAR_HEAP)
62,535✔
223
      mem = MIR_MEM_LOCAL;
1,270✔
224

225
   var_data_t vd = {
125,070✔
226
      .name    = name,
227
      .type    = type,
228
      .pointer = mir_get_var_pointer(mu, type),
62,535✔
229
      .stamp   = mir_pointer_stamp(mu, mem, stamp),
62,535✔
230
      .flags   = flags,
231
   };
232
   APUSH(mu->vars, vd);
62,535✔
233

234
   return v;
62,535✔
235
}
236

237
bool mir_is_terminator(mir_op_t op)
15✔
238
{
239
   switch (op) {
15✔
240
   case MIR_OP_RETURN:
241
   case MIR_OP_JUMP:
242
   case MIR_OP_COND:
243
   case MIR_OP_WAIT:
244
   case MIR_OP_CASE:
245
   case MIR_OP_PCALL:
246
   case MIR_OP_UNREACHABLE:
247
      return true;
248
   default:
×
249
      return false;
×
250
   }
251
}
252

253
bool mir_block_finished(mir_unit_t *mu, mir_block_t block)
13✔
254
{
255
   const block_data_t *bd = mir_block_data(mu, block);
13✔
256
   if (bd->num_nodes == 0)
13✔
257
      return false;
258

259
   return mir_is_terminator(mu->nodes[bd->nodes[bd->num_nodes - 1]].op);
×
260
}
261

262
static inline node_id_t mir_node_id(mir_unit_t *mu, node_data_t *n)
1,330,080✔
263
{
264
   assert(n >= mu->nodes && n < mu->nodes + mu->num_nodes);
1,330,080✔
265
   return n - mu->nodes;
1,330,080✔
266
}
267

268
static node_data_t *mir_alloc_node(mir_unit_t *mu)
1,379,125✔
269
{
270
   assert(!mir_is_null(mu->cursor.block));
1,379,125✔
271
   assert(mu->kind != MIR_UNIT_PLACEHOLDER);
1,379,125✔
272

273
   node_data_t *n;
1,379,125✔
274
   block_data_t *bd = mir_block_data(mu, mu->cursor.block);
1,379,125✔
275
   if (mu->cursor.pos >= bd->num_nodes) {
1,379,125✔
276
      // Append new node
277
      if (bd->num_nodes == bd->max_nodes) {
1,379,118✔
278
         bd->max_nodes = MAX(4, bd->num_nodes * 2);
323,771✔
279
         bd->nodes = xrealloc_array(bd->nodes, bd->max_nodes,
323,771✔
280
                                    sizeof(node_id_t));
281
      }
282

283
      if (mu->num_nodes == mu->max_nodes) {
1,379,118✔
284
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
120,064✔
285
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
120,064✔
286
                                    sizeof(node_data_t));
287
      }
288

289
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
1,379,118✔
290
      n = &(mu->nodes[mu->num_nodes++]);
1,379,118✔
291
   }
292
   else {
293
      n = &(mu->nodes[bd->nodes[mu->cursor.pos]]);
7✔
294
      assert(n->op == _MIR_DELETED_OP);
7✔
295
   }
296

297
   return n;
1,379,125✔
298
}
299

300
static size_t mir_spill_args(mir_unit_t *mu, unsigned num)
98,324✔
301
{
302
   if (mu->num_argspill + num > mu->max_argspill) {
98,324✔
303
      mu->max_argspill = MAX(16, MAX(mu->num_argspill + num,
44,578✔
304
                                     mu->max_argspill * 2));
305
      mu->argspill = xrealloc_array(mu->argspill, mu->max_argspill,
44,578✔
306
                                    sizeof(mir_value_t));
307
   }
308

309
   const size_t off = mu->num_argspill;
98,324✔
310
   mu->num_argspill += num;
98,324✔
311
   return off;
98,324✔
312
}
313

314
static node_data_t *mir_add_node(mir_unit_t *mu, mir_op_t op, mir_type_t type,
1,379,125✔
315
                                 mir_stamp_t stamp, unsigned nargs)
316
{
317
   node_data_t *n = mir_alloc_node(mu);
1,379,125✔
318
   n->loc   = mu->cursor.loc;
1,379,125✔
319
   n->op    = op;
1,379,125✔
320
   n->type  = type;
1,379,125✔
321
   n->stamp = stamp;
1,379,125✔
322
   n->nargs = nargs;
1,379,125✔
323

324
   if (nargs > MIR_INLINE_ARGS)
1,379,125✔
325
      n->spilloff = mir_spill_args(mu, nargs);
98,324✔
326

327
   return n;
1,379,125✔
328
}
329

330
static mir_value_t mir_build_0(mir_unit_t *mu, mir_op_t op, mir_type_t type,
7,564✔
331
                               mir_stamp_t stamp)
332
{
333
   node_data_t *n = mir_add_node(mu, op, type, stamp, 0);
7,564✔
334
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
7,564✔
335
}
336

337
static mir_value_t mir_build_1(mir_unit_t *mu, mir_op_t op, mir_type_t type,
454,960✔
338
                               mir_stamp_t stamp, mir_value_t arg)
339
{
340
   node_data_t *n = mir_add_node(mu, op, type, stamp, 1);
454,960✔
341
   n->args[0] = arg;
454,960✔
342

343
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
454,960✔
344
}
345

346
static mir_value_t mir_build_2(mir_unit_t *mu, mir_op_t op, mir_type_t type,
360,019✔
347
                               mir_stamp_t stamp, mir_value_t arg1,
348
                               mir_value_t arg2)
349
{
350
   STATIC_ASSERT(MIR_INLINE_ARGS >= 2);
360,019✔
351

352
   node_data_t *n = mir_add_node(mu, op, type, stamp, 2);
360,019✔
353
   n->args[0] = arg1;
360,019✔
354
   n->args[1] = arg2;
360,019✔
355

356
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
360,019✔
357
}
358

359
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
217,827✔
360
                               mir_stamp_t stamp, mir_value_t arg1,
361
                               mir_value_t arg2, mir_value_t arg3)
362
{
363
   STATIC_ASSERT(MIR_INLINE_ARGS >= 3);
217,827✔
364

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

370
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
217,827✔
371
}
372

373
static mir_value_t mir_build_4(mir_unit_t *mu, mir_op_t op, mir_type_t type,
3,956✔
374
                               mir_stamp_t stamp, mir_value_t arg1,
375
                               mir_value_t arg2, mir_value_t arg3,
376
                               mir_value_t arg4)
377
{
378
   STATIC_ASSERT(MIR_INLINE_ARGS >= 4);
3,956✔
379

380
   node_data_t *n = mir_add_node(mu, op, type, stamp, 4);
3,956✔
381
   n->args[0] = arg1;
3,956✔
382
   n->args[1] = arg2;
3,956✔
383
   n->args[2] = arg3;
3,956✔
384
   n->args[3] = arg4;
3,956✔
385

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

389
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
40,170✔
390
                               mir_stamp_t stamp, mir_value_t arg1,
391
                               mir_value_t arg2, mir_value_t arg3,
392
                               mir_value_t arg4, mir_value_t arg5)
393
{
394
   node_data_t *n = mir_add_node(mu, op, type, stamp, 5);
40,170✔
395
   n->nargs = 5;
40,170✔
396

397
   STATIC_ASSERT(MIR_INLINE_ARGS < 5);
40,170✔
398

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

405
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
40,170✔
406
}
407

408
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
25,338✔
409
                               mir_stamp_t stamp, mir_value_t arg1,
410
                               mir_value_t arg2, mir_value_t arg3,
411
                               mir_value_t arg4, mir_value_t arg5,
412
                               mir_value_t arg6)
413
{
414
   node_data_t *n = mir_add_node(mu, op, type, stamp, 6);
25,338✔
415

416
   STATIC_ASSERT(MIR_INLINE_ARGS < 6);
25,338✔
417

418
   mu->argspill[n->spilloff + 0] = arg1;
25,338✔
419
   mu->argspill[n->spilloff + 1] = arg2;
25,338✔
420
   mu->argspill[n->spilloff + 2] = arg3;
25,338✔
421
   mu->argspill[n->spilloff + 3] = arg4;
25,338✔
422
   mu->argspill[n->spilloff + 4] = arg5;
25,338✔
423
   mu->argspill[n->spilloff + 5] = arg6;
25,338✔
424

425
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
25,338✔
426
}
427

428
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
156,918✔
429
{
430
   for (int i = 0; i < mu->linkage.count; i++) {
401,672✔
431
      if (mu->linkage.items[i] == ident)
316,074✔
432
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
71,320✔
433
   }
434

435
   mir_value_t link = { .tag = MIR_TAG_LINKAGE, .id = mu->linkage.count };
85,598✔
436

437
   APUSH(mu->linkage, ident);
85,598✔
438

439
   return link;
85,598✔
440
}
441

442
static mir_value_t mir_add_extvar(mir_unit_t *mu, ident_t ident)
4,657✔
443
{
444
   for (int i = 0; i < mu->extvars.count; i++) {
13,078✔
445
      if (mu->extvars.items[i] == ident)
9,717✔
446
         return (mir_value_t){ .tag = MIR_TAG_EXTVAR, .id = i };
1,296✔
447
   }
448

449
   mir_value_t var = { .tag = MIR_TAG_EXTVAR, .id = mu->extvars.count };
3,361✔
450

451
   APUSH(mu->extvars, ident);
3,361✔
452

453
   return var;
3,361✔
454
}
455

456
void mir_set_arg(mir_unit_t *mu, node_data_t *n, unsigned nth,
1,901,532✔
457
                 mir_value_t value)
458
{
459
   assert(nth < n->nargs);
1,901,532✔
460

461
   if (n->nargs <= MIR_INLINE_ARGS)
1,901,532✔
462
      n->args[nth] = value;
314,850✔
463
   else {
464
      assert(n->spilloff < mu->num_argspill);
1,586,682✔
465
      mu->argspill[n->spilloff + nth] = value;
1,586,682✔
466
   }
467
}
1,901,532✔
468

469
node_data_t *mir_node_data(mir_unit_t *mu, mir_value_t value)
12,247,487✔
470
{
471
   assert(value.tag == MIR_TAG_NODE);
12,247,487✔
472
   assert(value.id < mu->num_nodes);
12,247,487✔
473

474
   return &(mu->nodes[value.id]);
12,247,487✔
475
}
476

477
const param_data_t *mir_param_data(mir_unit_t *mu, mir_value_t value)
169,887✔
478
{
479
   assert(value.tag == MIR_TAG_PARAM);
169,887✔
480
   return AREF(mu->params, value.id);
169,887✔
481
}
482

483
const var_data_t *mir_var_data(mir_unit_t *mu, mir_value_t value)
363,543✔
484
{
485
   assert(value.tag == MIR_TAG_VAR);
363,543✔
486
   return AREF(mu->vars, value.id);
363,543✔
487
}
488

489
#ifdef DEBUG
490
void mir_comment(mir_unit_t *mu, const char *fmt, ...)
106✔
491
{
492
   va_list ap;
106✔
493
   va_start(ap, fmt);
106✔
494

495
   if (mu->comments == NULL)
106✔
496
      mu->comments = tb_new();
18✔
497

498
   mir_value_t value = { .tag = MIR_TAG_COMMENT, .id = tb_len(mu->comments) };
106✔
499

500
   tb_vprintf(mu->comments, fmt, ap);
106✔
501
   tb_append(mu->comments, '\0');
106✔
502

503
   va_end(ap);
106✔
504

505
   mir_build_1(mu, MIR_OP_COMMENT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
106✔
506
}
106✔
507
#endif
508

509
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
4,087,306✔
510
{
511
   switch (value.tag) {
4,087,306✔
512
   case MIR_TAG_CONST:
3,542,774✔
513
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
3,542,774✔
514
      return true;
3,542,774✔
515
   case MIR_TAG_ENUM:
250,046✔
516
      *result = value.id;
250,046✔
517
      return true;
250,046✔
518
   case MIR_TAG_NODE:
288,548✔
519
      {
520
         const node_data_t *n = mir_node_data(mu, value);
288,548✔
521
         if (n->op == MIR_OP_CONST) {
288,548✔
522
            *result = n->iconst;
7,936✔
523
            return true;
7,936✔
524
         }
525
         else
526
            return false;
527
      }
528
   default:
529
      return false;
530
   }
531
}
532

533
bool mir_get_const_real(mir_unit_t *mu, mir_value_t value, double *result)
117,765✔
534
{
535
   switch (value.tag) {
117,765✔
536
   case MIR_TAG_NODE:
86,762✔
537
      {
538
         const node_data_t *n = mir_node_data(mu, value);
86,762✔
539
         if (n->op == MIR_OP_CONST_REAL) {
86,762✔
540
            *result = n->dconst;
26,320✔
541
            return true;
26,320✔
542
         }
543
         else
544
            return false;
545
      }
546
   default:
547
      return false;
548
   }
549
}
550

551
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
2,854,505✔
552
{
553
   switch (value.tag) {
2,854,505✔
554
   case MIR_TAG_NODE:
2,375,954✔
555
      return mir_node_data(mu, value)->type;
2,375,954✔
556
   case MIR_TAG_PARAM:
156,605✔
557
      return mir_param_data(mu, value)->type;
156,605✔
558
   case MIR_TAG_VAR:
170,980✔
559
      return mir_var_data(mu, value)->pointer;
170,980✔
560
   default:
150,966✔
561
      return MIR_NULL_TYPE;
150,966✔
562
   }
563
}
564

565
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
573,075✔
566
{
567
   switch (value.tag) {
573,075✔
568
   case MIR_TAG_NODE:
457,613✔
569
      return mir_node_data(mu, value)->stamp;
457,613✔
570
   case MIR_TAG_PARAM:
13,267✔
571
      return mir_param_data(mu, value)->stamp;
13,267✔
572
   case MIR_TAG_VAR:
44,851✔
573
      return mir_var_data(mu, value)->stamp;
44,851✔
574
   case MIR_TAG_CONST:
57,344✔
575
      {
576
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
57,344✔
577
         return mir_int_stamp(mu, ival, ival);
57,344✔
578
      }
579
   default:
×
580
      return MIR_NULL_STAMP;
×
581
   }
582
}
583

584
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value)
8,596✔
585
{
586
   mir_type_t type = mir_get_type(mu, value);
8,596✔
587
   if (mir_is_null(type))
8,596✔
588
      return MIR_MEM_NONE;
589

590
   switch (mir_type_data(mu, type)->class) {
7,158✔
591
   case MIR_TYPE_UARRAY:
592
   case MIR_TYPE_CARRAY:
593
   case MIR_TYPE_RECORD:
594
   case MIR_TYPE_POINTER:
595
   case MIR_TYPE_ACCESS:
596
      break;
5,633✔
597
   default:
598
      return MIR_MEM_NONE;
599
   }
600

601
   mir_stamp_t stamp = mir_get_stamp(mu, value);
5,633✔
602
   if (mir_is_null(stamp))
5,633✔
603
      return MIR_MEM_TOP;
604

605
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
954✔
606
   assert(sd->kind == MIR_STAMP_POINTER);
954✔
607

608
   return sd->u.pointer.memory;
954✔
609
}
610

611
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
207,515✔
612
{
613
   switch (value.tag) {
207,515✔
614
   case MIR_TAG_PARAM:
15✔
615
      return mir_param_data(mu, value)->name;
15✔
616
   case MIR_TAG_VAR:
47,243✔
617
      return mir_var_data(mu, value)->name;
47,243✔
618
   case MIR_TAG_LINKAGE:
155,578✔
619
      return AGET(mu->linkage, value.id);
155,578✔
620
   case MIR_TAG_EXTVAR:
4,679✔
621
      return AGET(mu->extvars, value.id);
4,679✔
622
   case MIR_TAG_NULL:
×
623
      return mu->name;
×
624
   default:
625
      return NULL;
626
   }
627
}
628

629
void mir_set_result(mir_unit_t *mu, mir_type_t type)
26,539✔
630
{
631
   assert(mu->kind == MIR_UNIT_FUNCTION || mu->kind == MIR_UNIT_THUNK);
26,539✔
632
   mu->result = type;
26,539✔
633
}
26,539✔
634

635
mir_type_t mir_get_result(mir_unit_t *mu)
25,500✔
636
{
637
   return mu->result;
25,500✔
638
}
639

640
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
83,301✔
641
{
642
   switch (value.tag) {
83,301✔
643
   case MIR_TAG_NODE:
83,301✔
644
      {
645
         node_data_t *n = mir_node_data(mu, value);
83,301✔
646
         assert(n->op == MIR_OP_LOCUS);
83,301✔
647
         return n->locus;
83,301✔
648
      }
649
      break;
×
650
   default:
×
651
      should_not_reach_here();
652
   }
653
}
654

655
void mir_get_bits(mir_unit_t *mu, mir_value_t value, uint64_t *abits,
40✔
656
                  uint64_t *bbits)
657
{
658
   switch (value.tag) {
40✔
659
   case MIR_TAG_NODE:
40✔
660
      {
661
         node_data_t *n = mir_node_data(mu, value);
40✔
662
         assert(n->op == MIR_OP_CONST_VEC);
40✔
663

664
         *abits = n->bits[0];
40✔
665
         *bbits = n->bits[1];
40✔
666
      }
667
      break;
40✔
668
   default:
×
669
      should_not_reach_here();
670
   }
671
}
40✔
672

673
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value)
38,012✔
674
{
675
   switch (value.tag) {
38,012✔
676
   case MIR_TAG_VAR:
38,012✔
677
      return mir_var_data(mu, value)->flags;
38,012✔
678
   default:
679
      return 0;
680
   }
681
}
682

683
mir_type_t mir_get_var_type(mir_unit_t *mu, mir_value_t value)
62,457✔
684
{
685
   switch (value.tag) {
62,457✔
686
   case MIR_TAG_VAR:
62,457✔
687
      return mir_var_data(mu, value)->type;
62,457✔
688
   default:
×
689
      return MIR_NULL_TYPE;
×
690
   }
691
}
692

693
bool mir_is_integral(mir_unit_t *mu, mir_value_t value)
97,896✔
694
{
695
   if (value.tag == MIR_TAG_CONST)
97,896✔
696
      return true;
697

698
   mir_type_t type = mir_get_type(mu, value);
40,171✔
699
   if (mir_is_null(type))
40,171✔
700
      return false;
701

702
   switch (mir_type_data(mu, type)->class) {
40,171✔
703
   case MIR_TYPE_INT:
704
   case MIR_TYPE_OFFSET:
705
      return true;
706
   default:
7,326✔
707
      return false;
7,326✔
708
   }
709
}
710

711
bool mir_is_numeric(mir_unit_t *mu, mir_value_t value)
10,038✔
712
{
713
   if (value.tag == MIR_TAG_CONST)
10,038✔
714
      return true;
715

716
   mir_type_t type = mir_get_type(mu, value);
9,974✔
717
   if (mir_is_null(type))
9,974✔
718
      return false;
719

720
   switch (mir_type_data(mu, type)->class) {
9,974✔
721
   case MIR_TYPE_INT:
722
   case MIR_TYPE_OFFSET:
723
   case MIR_TYPE_REAL:
724
   case MIR_TYPE_VEC2:
725
   case MIR_TYPE_VEC4:
726
      return true;
727
   default:
86✔
728
      return false;
86✔
729
   }
730
}
731

732
bool mir_is_scalar(mir_unit_t *mu, mir_value_t value)
171,821✔
733
{
734
   if (value.tag == MIR_TAG_CONST)
171,821✔
735
      return true;
736

737
   mir_type_t type = mir_get_type(mu, value);
159,724✔
738
   if (mir_is_null(type))
159,724✔
739
      return false;
740

741
   switch (mir_type_data(mu, type)->class) {
159,724✔
742
   case MIR_TYPE_INT:
743
   case MIR_TYPE_OFFSET:
744
   case MIR_TYPE_REAL:
745
   case MIR_TYPE_ACCESS:
746
   case MIR_TYPE_POINTER:
747
   case MIR_TYPE_UARRAY:
748
   case MIR_TYPE_SIGNAL:
749
   case MIR_TYPE_CONTEXT:
750
   case MIR_TYPE_RESOLUTION:
751
   case MIR_TYPE_FILE:
752
   case MIR_TYPE_TRIGGER:
753
   case MIR_TYPE_VEC2:
754
   case MIR_TYPE_VEC4:
755
      return true;
UNCOV
756
   default:
×
UNCOV
757
      return false;
×
758
   }
759
}
760

761
bool mir_is_vector(mir_unit_t *mu, mir_value_t value)
14✔
762
{
763
   mir_type_t type = mir_get_type(mu, value);
14✔
764
   if (mir_is_null(type))
14✔
765
      return false;
766

767
   switch (mir_type_data(mu, type)->class) {
14✔
768
   case MIR_TYPE_VEC2:
769
   case MIR_TYPE_VEC4:
770
      return true;
771
   default:
×
772
      return false;
×
773
   }
774
}
775

776
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
155,831✔
777
{
778
   if (value.tag == MIR_TAG_CONST)
155,831✔
779
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
39,835✔
780
   else
781
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
115,996✔
782
}
783

784
bool mir_is_time(mir_unit_t *mu, mir_value_t value)
7,142✔
785
{
786
   if (value.tag == MIR_TAG_CONST)
7,142✔
787
      return true;
788

789
   return mir_equals(mir_get_type(mu, value), mir_time_type(mu));
349✔
790
}
791

792
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class)
666,885✔
793
{
794
   mir_type_t type = mir_get_type(mu, value);
666,885✔
795
   if (mir_is_null(type))
666,885✔
796
      return false;
797

798
   return mir_type_data(mu, type)->class == class;
635,647✔
799
}
800

801
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class)
4,728✔
802
{
803
   mir_type_t type = mir_get_type(mu, value);
4,728✔
804
   if (mir_is_null(type))
4,728✔
805
      return false;
806

807
   const type_data_t *td = mir_type_data(mu, type);
4,728✔
808
   if (td->class != MIR_TYPE_POINTER)
4,728✔
809
      return false;
810

811
   return mir_type_data(mu, td->u.pointer)->class == class;
4,728✔
812
}
813

814
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
132,735✔
815
{
816
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
132,735✔
817
}
818

819
bool mir_is_offset(mir_unit_t *mu, mir_value_t value)
189,398✔
820
{
821
   if (value.tag == MIR_TAG_CONST)
189,398✔
822
      return true;
823

824
   return mir_is(mu, value, MIR_TYPE_OFFSET);
45,238✔
825
}
826

827
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
1,506,796✔
828
{
829
   switch (value.tag) {
1,506,796✔
830
   case MIR_TAG_CONST:
831
      return true;
832
   case MIR_TAG_NODE:
21,182✔
833
      {
834
         node_data_t *n = mir_node_data(mu, value);
21,182✔
835
         switch (n->op) {
21,182✔
836
         case MIR_OP_CONST:
837
         case MIR_OP_CONST_REAL:
838
         case MIR_OP_CONST_ARRAY:
839
         case MIR_OP_CONST_REP:
840
         case MIR_OP_CONST_RECORD:
841
         case MIR_OP_NULL:
842
            return true;
843
         default:
×
844
            return false;
×
845
         }
846
      }
847
   default:
×
848
      return false;
×
849
   }
850
}
851

852
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
5✔
853
{
854
   const mir_mem_t a_mem = mir_get_mem(mu, a);
5✔
855
   if (a_mem == MIR_MEM_NONE)
5✔
856
      return false;
857

858
   if (mir_equals(a, b))
5✔
859
      return true;
860

861
   const mir_mem_t b_mem = mir_get_mem(mu, b);
5✔
862
   if (b_mem == MIR_MEM_NONE)
5✔
863
      return false;
864

865
   if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
5✔
866
      // Aliasing is only relevant in the presence of mutability
867
      return false;
868
   }
869

870
   return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
3✔
871
}
872

873
#ifdef DEBUG
874
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
1,555,992✔
875
{
876
   if (value.tag == MIR_TAG_CONST) {
1,555,992✔
877
      const mir_class_t class = mir_type_data(mu, type)->class;
1,484,948✔
878
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
1,484,948✔
879
   }
880
   else
881
      return mir_equals(mir_get_type(mu, value), type);
71,044✔
882
}
883
#endif
884

885
mir_value_t mir_enum(unsigned value)
283,290✔
886
{
887
   assert(value < MIR_ID_MAX);
283,290✔
888
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
283,290✔
889
}
890

891
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
426,175✔
892
{
893
   mir_value_t result;
426,175✔
894
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
426,175✔
895
      const unsigned biased = value + SMALL_CONST_BIAS;
418,732✔
896
      result = (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
418,732✔
897
   }
898
   else {
899
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
7,443✔
900
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
7,443✔
901
      n->iconst = value;
7,443✔
902

903
      result = (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
7,443✔
904
   }
905

906
#ifdef DEBUG
907
   const mir_class_t class = mir_get_class(mu, type);
426,175✔
908
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET,
426,175✔
909
              "constant must have integral type");
910
#endif
911

912
   return result;
426,175✔
913
}
914

915
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
25,518✔
916
{
917
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
25,518✔
918
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
25,518✔
919
   n->dconst = value;
25,518✔
920

921
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
25,518✔
922
}
923

924
mir_value_t mir_const_vec(mir_unit_t *mu, mir_type_t type, uint64_t abits,
44✔
925
                          uint64_t bbits)
926
{
927
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_VEC, type, MIR_NULL_STAMP, 0);
44✔
928
   n->bits[0] = abits;
44✔
929
   n->bits[1] = bbits;
44✔
930

931
#ifdef DEBUG
932
   const type_data_t *td = mir_type_data(mu, type);
44✔
933
   MIR_ASSERT(td->class == MIR_TYPE_VEC2 || td->class == MIR_TYPE_VEC4,
44✔
934
              "constant vector must have vector type");
935
   MIR_ASSERT(bbits == 0 || td->class == MIR_TYPE_VEC4,
44✔
936
              "b-bits cannot be set for two-value vector");
937
#endif
938

939
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
44✔
940
}
941

942
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
24,797✔
943
                            const mir_value_t *values, size_t count)
944
{
945
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
49,594✔
946
                                 MIR_NULL_STAMP, count);
24,797✔
947

948
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
24,797✔
949
              "constant array must have constrained array type");
950
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
24,797✔
951
              "have %zd", mir_get_size(mu, type), count);
952

953
   mir_type_t elem = mir_get_elem(mu, type);
24,797✔
954

955
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
24,797✔
956
   int64_t low = INT64_MAX, high = INT64_MIN;
24,797✔
957
   for (size_t i = 0; i < count; i++) {
1,518,779✔
958
      mir_set_arg(mu, n, i, values[i]);
1,493,982✔
959

960
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
1,493,982✔
961
                 "element %zd has wrong type", i);
962
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
1,493,982✔
963

964
      int64_t cval;
1,493,982✔
965
      if (integral && mir_get_const(mu, values[i], &cval)) {
1,493,982✔
966
         low = MIN(low, cval);
1,475,066✔
967
         high = MAX(high, cval);
1,475,066✔
968
      }
969
   }
970

971
   mir_stamp_t stamp = MIR_NULL_STAMP;
24,797✔
972
   if (integral && low <= high)
24,797✔
973
      stamp = mir_int_stamp(mu, low, high);
23,959✔
974

975
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
24,797✔
976

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

980
mir_value_t mir_const_string(mir_unit_t *mu, const char *str)
2,489✔
981
{
982
   int count = 0, low = UINT8_MAX, high = 0;
2,489✔
983
   for (const char *p = str; *p; p++, count++) {
12,735✔
984
      low = MIN(low, (unsigned char)*p);
10,246✔
985
      high = MAX(high, (unsigned char)*p);
10,246✔
986
   }
987

988
   mir_type_t t_char = mir_char_type(mu);
2,489✔
989
   mir_type_t type = mir_carray_type(mu, count, t_char);
2,489✔
990
   mir_stamp_t stamp = mir_int_stamp(mu, low, high);
2,489✔
991

992
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
2,489✔
993
                                 stamp, count);
994

995
   for (int i = 0; i < count; i++)
12,735✔
996
      mir_set_arg(mu, n, i, mir_const(mu, t_char, (unsigned char)str[i]));
10,246✔
997

998
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,489✔
999
}
1000

1001
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
423✔
1002
                                mir_value_t value, unsigned rep)
1003
{
1004
   mir_stamp_t stamp = mir_get_stamp(mu, value);
423✔
1005
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
423✔
1006
                                    value, mir_enum(rep));
1007

1008
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
423✔
1009
              "constant array must have constrained array class");
1010
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
423✔
1011

1012
   return result;
423✔
1013
}
1014

1015
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,866✔
1016
                             const mir_value_t *values, size_t count)
1017
{
1018
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
5,732✔
1019
                                 MIR_NULL_STAMP, count);
2,866✔
1020

1021
   DEBUG_ONLY(const type_data_t *td = mir_type_data(mu, type));
2,866✔
1022

1023
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,866✔
1024
              "const record must have record type");
1025
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,866✔
1026
              td->u.record.count, count);
1027

1028
   for (int i = 0; i < count; i++) {
10,233✔
1029
      mir_set_arg(mu, n, i, values[i]);
7,367✔
1030

1031
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
7,367✔
1032
                               td->u.record.fields[i]),
1033
                 "wrong type for element %d", i);
1034
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
7,367✔
1035
   }
1036

1037
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,866✔
1038
}
1039

1040
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
48,061✔
1041
                                   mir_value_t left, mir_value_t right,
1042
                                   mir_value_t locus, mir_stamp_t stamp)
1043
{
1044
   mir_value_t result;
48,061✔
1045
   if (mir_is_null(locus))
48,061✔
1046
      result = mir_build_2(mu, op, type, stamp, left, right);
43,416✔
1047
   else
1048
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
4,645✔
1049

1050
#ifdef DEBUG
1051
   switch (mir_get_class(mu, type)) {
48,061✔
1052
   case MIR_TYPE_INT:
48,059✔
1053
   case MIR_TYPE_REAL:
1054
   case MIR_TYPE_OFFSET:
1055
      {
1056
         mir_type_t ltype = mir_get_type(mu, left);
48,059✔
1057
         mir_type_t rtype = mir_get_type(mu, right);
48,059✔
1058

1059
         MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
48,059✔
1060
                    || mir_equals(ltype, rtype),
1061
                    "arguments to %s are not the same type", mir_op_string(op));
1062
      }
1063
      break;
1064

1065
   case MIR_TYPE_VEC2:
2✔
1066
   case MIR_TYPE_VEC4:
1067
      {
1068
         const type_data_t *td = mir_type_data(mu, type);
2✔
1069
         const type_data_t *ltd = mir_type_data(mu, mir_get_type(mu, left));
2✔
1070
         const type_data_t *rtd = mir_type_data(mu, mir_get_type(mu, right));
2✔
1071

1072
         MIR_ASSERT(td->class == ltd->class && td->class == rtd->class,
2✔
1073
                    "cannot mix vector types");
1074
         MIR_ASSERT(td->u.vec.issigned == ltd->u.vec.issigned
2✔
1075
                    && td->u.vec.issigned == rtd->u.vec.issigned,
1076
                    "cannot mix vector signedness");
1077
         MIR_ASSERT(td->u.vec.size >= ltd->u.vec.size
2✔
1078
                    && td->u.vec.size >= rtd->u.vec.size,
1079
                    "implicit narrowing conversions are not allowed");
1080
      }
1081
      break;
1082

1083
   default:
1084
      MIR_ASSERT(false, "arithmetic is not allowed on this type");
×
1085
      break;
1086
   }
1087

1088
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
48,061✔
1089
              "locus argument to %s is not a locus", mir_op_string(op));
1090
#endif
1091

1092
   return result;
48,061✔
1093
}
1094

1095
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
18,212✔
1096
                                    mir_type_t type, mir_value_t left,
1097
                                    mir_value_t right, mir_value_t locus)
1098
{
1099
   int64_t lval, rval, cval;
18,212✔
1100
   const bool lconst = mir_get_const(mu, left, &lval);
18,212✔
1101
   const bool rconst = mir_get_const(mu, right, &rval);
18,212✔
1102

1103
   if (lconst && lval == 0)
18,212✔
1104
      return right;
×
1105
   else if (rconst && rval == 0)
18,212✔
1106
      return left;
1✔
1107
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
18,211✔
1108
      return mir_const(mu, type, cval);
3✔
1109

1110
   double lreal, rreal;
18,208✔
1111
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
18,208✔
1112
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
18,208✔
1113

1114
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
18,208✔
1115
      return right;
1✔
1116
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
18,207✔
1117
      return left;
2✔
1118
   else if (lconst_real && rconst_real)
18,205✔
1119
      return mir_const_real(mu, type, lreal + rreal);
5✔
1120

1121
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
18,200✔
1122
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
18,200✔
1123
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
18,200✔
1124

1125
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
18,200✔
1126
}
1127

1128
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
15,950✔
1129
                          mir_value_t right)
1130
{
1131
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
15,950✔
1132
}
1133

1134
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
2,262✔
1135
                               mir_value_t left, mir_value_t right,
1136
                               mir_value_t locus)
1137
{
1138
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
2,262✔
1139
}
1140

1141
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
25,339✔
1142
                                    mir_type_t type, mir_value_t left,
1143
                                    mir_value_t right, mir_value_t locus)
1144
{
1145
   int64_t lval, rval, cval;
25,339✔
1146
   const bool lconst = mir_get_const(mu, left, &lval);
25,339✔
1147
   const bool rconst = mir_get_const(mu, right, &rval);
25,339✔
1148

1149
   if (lconst && lval == 0)
25,339✔
1150
      return right;
4✔
1151
   else if (rconst && rval == 0)
25,335✔
1152
      return left;
4✔
1153
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
25,331✔
1154
      return mir_const(mu, type, cval);
1✔
1155
   else if (mir_equals(left, right))
25,330✔
1156
      return mir_get_class(mu, type) == MIR_TYPE_REAL
178✔
1157
         ? mir_const_real(mu, type, 0.0) : mir_const(mu, type, 0);
178✔
1158

1159
   double lreal, rreal;
25,152✔
1160
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
25,152✔
1161
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
25,152✔
1162

1163
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
25,152✔
1164
      return right;
×
1165
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
25,152✔
1166
      return left;
5✔
1167
   else if (lconst_real && rconst_real)
25,147✔
1168
      return mir_const_real(mu, type, lreal - rreal);
×
1169

1170
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
25,147✔
1171
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
25,147✔
1172
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
25,147✔
1173

1174
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
25,147✔
1175
}
1176

1177
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
23,649✔
1178
                          mir_value_t right)
1179
{
1180
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
23,649✔
1181
}
1182

1183
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
1,293✔
1184
                               mir_value_t left, mir_value_t right,
1185
                               mir_value_t locus)
1186
{
1187
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
1,293✔
1188
}
1189

1190
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
9,061✔
1191
{
1192
   int64_t cval;
9,061✔
1193
   if (mir_get_const(mu, value, &cval))
9,061✔
1194
      return mir_const(mu, type, -cval);
1✔
1195

1196
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
9,060✔
1197
                                    MIR_NULL_STAMP, value);
9,060✔
1198

1199
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
9,060✔
1200

1201
   return result;
9,060✔
1202
}
1203

1204
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
562✔
1205
                               mir_value_t value, mir_value_t locus)
1206
{
1207
   int64_t cval;
562✔
1208
   if (mir_get_const(mu, value, &cval) && cval >= 0)
562✔
1209
      return mir_const(mu, type, -cval);
×
1210
   // TODO: check if stamp bounds are non-negative
1211

1212
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
562✔
1213
                                    MIR_NULL_STAMP, value, locus);
562✔
1214

1215
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
562✔
1216
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
562✔
1217
              "locus argument must be debug locus");
1218

1219
   return result;
562✔
1220
}
1221

1222
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
258✔
1223
{
1224
   int64_t lconst;
258✔
1225
   if (mir_get_const(mu, value, &lconst))
258✔
1226
      return mir_const(mu, type, llabs(lconst));
×
1227

1228
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
258✔
1229
                                    value);
1230

1231
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
258✔
1232

1233
   return result;
258✔
1234
}
1235

1236
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
2,767✔
1237
                                    mir_type_t type, mir_value_t left,
1238
                                    mir_value_t right, mir_value_t locus)
1239
{
1240
   int64_t lval, rval, cval;
2,767✔
1241
   const bool lconst = mir_get_const(mu, left, &lval);
2,767✔
1242
   const bool rconst = mir_get_const(mu, right, &rval);
2,767✔
1243

1244
   if (lconst && lval == 0)
2,767✔
1245
      return left;
×
1246
   else if (rconst && rval == 0)
2,767✔
1247
      return right;
×
1248
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
2,767✔
1249
      return mir_const(mu, type, cval);
×
1250

1251
   double lreal, rreal;
2,767✔
1252
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
2,767✔
1253
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
2,767✔
1254

1255
   if (lconst_real && rconst_real)
2,767✔
1256
      return mir_const_real(mu, type, lreal * rreal);
192✔
1257

1258
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
2,575✔
1259
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
2,575✔
1260
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
2,575✔
1261

1262
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
2,575✔
1263
}
1264

1265
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
2,767✔
1266
                          mir_value_t right)
1267
{
1268
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
2,767✔
1269
}
1270

1271
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
397✔
1272
                               mir_value_t left, mir_value_t right,
1273
                               mir_value_t locus)
1274
{
1275
   return mir_build_sub_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
397✔
1276
}
1277

1278
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
1,056✔
1279
                          mir_value_t right)
1280
{
1281
   int64_t lval, rval;
1,056✔
1282
   const bool lconst = mir_get_const(mu, left, &lval);
1,056✔
1283
   const bool rconst = mir_get_const(mu, right, &rval);
1,056✔
1284

1285
   if (lconst && rconst && rval != 0)
1,056✔
1286
      return mir_const(mu, type, lval / rval);
×
1287
   else if (rconst && rval == 1)
1,056✔
1288
      return left;
×
1289

1290
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
1,056✔
1291
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
1,056✔
1292
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
1,056✔
1293

1294
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
1,056✔
1295
                          MIR_NULL_VALUE, stamp);
1,056✔
1296
}
1297

1298
mir_value_t mir_build_rem(mir_unit_t *mu, mir_type_t type, mir_value_t left,
127✔
1299
                          mir_value_t right)
1300
{
1301
   int64_t lval, rval;
127✔
1302
   const bool lconst = mir_get_const(mu, left, &lval);
127✔
1303
   const bool rconst = mir_get_const(mu, right, &rval);
127✔
1304

1305
   if (lconst && rconst && lval > 0 && rval > 0)
127✔
1306
      return mir_const(mu, type, lval % rval);
1✔
1307

1308
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
126✔
1309
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
126✔
1310
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
126✔
1311

1312
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
126✔
1313
                          MIR_NULL_VALUE, stamp);
126✔
1314
}
1315

1316
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
185✔
1317
                          mir_value_t right)
1318
{
1319
   int64_t lval, rval;
185✔
1320
   const bool lconst = mir_get_const(mu, left, &lval);
185✔
1321
   const bool rconst = mir_get_const(mu, right, &rval);
185✔
1322

1323
   if (lconst && rconst && lval > 0 && rval > 0)
185✔
1324
      return mir_const(mu, type, lval % rval);
×
1325

1326
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
185✔
1327
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
185✔
1328

1329
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
185✔
1330
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
16✔
1331
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
16✔
1332

1333
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
16✔
1334
         // If both arguments are non-negative then rem is equivalent
1335
         // and cheaper to compute
1336
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1337
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1338
                                MIR_NULL_VALUE, stamp);
1✔
1339
      }
1340
   }
1341

1342
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
184✔
1343
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
184✔
1344
}
1345

1346
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
79✔
1347
                          mir_value_t right)
1348
{
1349
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
158✔
1350
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
79✔
1351
}
1352

1353
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
693✔
1354
                               mir_value_t left, mir_value_t right,
1355
                               mir_value_t locus)
1356
{
1357
   int64_t rconst;
693✔
1358
   if (mir_get_const(mu, right, &rconst)) {
693✔
1359
      if (rconst == 0)
580✔
1360
         return mir_const(mu, type, 1);
×
1361
      else if (rconst == 1)
580✔
1362
         return left;
×
1363
   }
1364

1365
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
693✔
1366
                                        locus, MIR_NULL_STAMP);
693✔
1367

1368
   MIR_ASSERT(mir_is_integral(mu, result),
693✔
1369
              "trapping exp may only be used with integer types");
1370

1371
   return result;
693✔
1372
}
1373

1374
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
7,239✔
1375
                                     mir_type_t type, mir_value_t left,
1376
                                     mir_value_t right)
1377
{
1378
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
7,239✔
1379

1380
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
7,239✔
1381
              mir_op_string(op));
1382
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
7,239✔
1383
              mir_op_string(op));
1384

1385
   return result;
7,239✔
1386
}
1387

1388
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
4,933✔
1389
{
1390
   int64_t lval, rval;
4,933✔
1391
   const bool lconst = mir_get_const(mu, left, &lval);
4,933✔
1392
   const bool rconst = mir_get_const(mu, right, &rval);
4,933✔
1393

1394
   mir_type_t t_bool = mir_bool_type(mu);
4,933✔
1395

1396
   if (lconst && rconst)
4,933✔
1397
      return mir_const(mu, t_bool, lval && rval);
3✔
1398
   else if (lconst)
4,931✔
1399
      return lval ? right : mir_const(mu, t_bool, 0);
×
1400
   else if (rconst)
4,931✔
1401
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1402

1403
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
4,929✔
1404
}
1405

1406
mir_value_t mir_build_nand(mir_unit_t *mu, mir_value_t left, mir_value_t right)
74✔
1407
{
1408
   int64_t lval, rval;
74✔
1409
   const bool lconst = mir_get_const(mu, left, &lval);
74✔
1410
   const bool rconst = mir_get_const(mu, right, &rval);
74✔
1411

1412
   mir_type_t t_bool = mir_bool_type(mu);
74✔
1413

1414
   if (lconst && rconst)
74✔
1415
      return mir_const(mu, t_bool, !(lval && rval));
1✔
1416

1417
   return mir_build_logical(mu, MIR_OP_NAND, t_bool, left, right);
73✔
1418
}
1419

1420
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
1,973✔
1421
{
1422
   int64_t lval, rval;
1,973✔
1423
   const bool lconst = mir_get_const(mu, left, &lval);
1,973✔
1424
   const bool rconst = mir_get_const(mu, right, &rval);
1,973✔
1425

1426
   mir_type_t t_bool = mir_bool_type(mu);
1,973✔
1427

1428
   if (lconst && rconst)
1,973✔
1429
      return mir_const(mu, t_bool, lval || rval);
3✔
1430
   else if (lconst)
1,971✔
1431
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1432
   else if (rconst)
1,970✔
1433
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1434

1435
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
1,969✔
1436
}
1437

1438
mir_value_t mir_build_nor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
76✔
1439
{
1440
   int64_t lval, rval;
76✔
1441
   const bool lconst = mir_get_const(mu, left, &lval);
76✔
1442
   const bool rconst = mir_get_const(mu, right, &rval);
76✔
1443

1444
   mir_type_t t_bool = mir_bool_type(mu);
76✔
1445

1446
   if (lconst && rconst)
76✔
1447
      return mir_const(mu, t_bool, !(lval || rval));
4✔
1448

1449
   return mir_build_logical(mu, MIR_OP_NOR, t_bool, left, right);
74✔
1450
}
1451

1452
mir_value_t mir_build_xor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
120✔
1453
{
1454
   int64_t lval, rval;
120✔
1455
   const bool lconst = mir_get_const(mu, left, &lval);
120✔
1456
   const bool rconst = mir_get_const(mu, right, &rval);
120✔
1457

1458
   mir_type_t t_bool = mir_bool_type(mu);
120✔
1459
   if (lconst && rconst)
120✔
1460
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1461
   else if (mir_equals(left, right))
119✔
1462
      return mir_const(mu, t_bool, 0);
1✔
1463

1464
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
118✔
1465
}
1466

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

1473
   mir_type_t t_bool = mir_bool_type(mu);
76✔
1474
   if (lconst && rconst)
76✔
1475
      return mir_const(mu, t_bool, !(lval ^ rval));
×
1476

1477
   return mir_build_logical(mu, MIR_OP_XNOR, t_bool, left, right);
76✔
1478
}
1479

1480
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
3,350✔
1481
{
1482
   mir_type_t t_bool = mir_bool_type(mu);
3,350✔
1483

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

1488
   if (mir_get_op(mu, value) == MIR_OP_NOT)
3,348✔
1489
      return mir_get_arg(mu, value, 0);
41✔
1490

1491
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
3,307✔
1492
                                    MIR_NULL_STAMP, value);
3,307✔
1493

1494
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
3,307✔
1495

1496
   return result;
3,307✔
1497
}
1498

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

1506
   mir_type_t t_bool = mir_bool_type(mu);
41,846✔
1507

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

1520
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
41,833✔
1521
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
41,833✔
1522
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
41,833✔
1523

1524
   int64_t sconst;
41,833✔
1525
   if (mir_stamp_const(mu, stamp, &sconst))
41,833✔
1526
      return mir_const(mu, t_bool, sconst);
3✔
1527

1528
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
41,830✔
1529
                                    stamp, mir_enum(cmp), left, right);
1530

1531
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
41,830✔
1532
                            mir_get_type(mu, right)),
1533
              "arguments to cmp are not the same type");
1534

1535
   return result;
41,830✔
1536
}
1537

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

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

1551
   return result;
160✔
1552
}
1553

1554
mir_value_t mir_build_unpack(mir_unit_t *mu, mir_value_t vec, uint8_t strength,
14✔
1555
                             mir_value_t dest)
1556
{
1557
   mir_type_t type, vec_type = mir_get_type(mu, vec);
14✔
1558
   if (mir_get_size(mu, vec_type) == 1)
14✔
1559
      type = mir_logic_type(mu);
13✔
1560
   else
1561
      type = mir_get_type(mu, dest);
1✔
1562

1563
   mir_value_t result;
14✔
1564
   if (mir_is_null(dest))
14✔
1565
      result = mir_build_2(mu, MIR_OP_UNPACK, type, MIR_NULL_STAMP,
13✔
1566
                           vec, mir_enum(strength));
1567
   else
1568
      result = mir_build_3(mu, MIR_OP_UNPACK, type, MIR_NULL_STAMP,
1✔
1569
                           vec, mir_enum(strength), dest);
1570

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

1578
   return result;
14✔
1579
}
1580

1581
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
90,057✔
1582
{
1583
   mir_type_t type = mir_get_type(mu, dest);
90,057✔
1584
   mir_type_t pointed = mir_get_pointer(mu, type);
90,057✔
1585

1586
   mir_build_2(mu, MIR_OP_STORE, pointed, MIR_NULL_STAMP, dest, src);
90,057✔
1587

1588
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
90,057✔
1589
              "store destination is not a pointer or variable");
1590
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
90,057✔
1591
              "source and destination have different types");
1592
}
90,057✔
1593

1594
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
149,698✔
1595
{
1596
   mir_type_t type = mir_get_type(mu, value);
149,698✔
1597
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
149,698✔
1598
   mir_type_t pointed = mir_get_pointer(mu, type);
149,698✔
1599

1600
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
149,698✔
1601

1602
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
149,698✔
1603
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
149,698✔
1604
              "argument to load is not a pointer or variable");
1605
   MIR_ASSERT(mir_is_scalar(mu, result), "cannot load non-scalar type");
149,698✔
1606

1607
   return result;
149,698✔
1608
}
1609

1610
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
19,473✔
1611
                    mir_value_t count)
1612
{
1613
   int64_t cval;
19,473✔
1614
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
19,473✔
1615
      return;
251✔
1616
   else if (mir_equals(dest, src))
19,473✔
1617
      return;
1618

1619
   mir_type_t dtype = mir_get_type(mu, dest);
19,222✔
1620
   mir_type_t elem = mir_get_pointer(mu, dtype);
19,222✔
1621

1622
   if (mir_is_null(count))
19,222✔
1623
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
2,278✔
1624
   else
1625
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
16,944✔
1626

1627
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
19,222✔
1628
              "destination type is not a pointer");
1629
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
19,222✔
1630
              "source type is not a pointer");
1631
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
19,222✔
1632
              "source and destination types do not match");
1633
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
19,222✔
1634
              "count is not offset type");
1635
}
1636

1637
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
6,435✔
1638
                   mir_value_t count)
1639
{
1640
   int64_t cval;
6,435✔
1641
   if (mir_get_const(mu, count, &cval) && cval == 0)
6,435✔
1642
      return;
×
1643

1644
   mir_type_t dtype = mir_get_type(mu, dest);
6,435✔
1645
   mir_type_t elem = mir_get_pointer(mu, dtype);
6,435✔
1646

1647
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
6,435✔
1648

1649
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
6,435✔
1650
              "destination type is not a pointer");
1651
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
6,435✔
1652
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
6,435✔
1653
}
1654

1655
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
8,363✔
1656
                            mir_value_t count)
1657
{
1658
   mir_type_t ptr = mir_pointer_type(mu, type);
8,363✔
1659
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
8,363✔
1660

1661
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
8,363✔
1662
              "alloc element type cannot be array");
1663
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
8,363✔
1664

1665
   return result;
8,363✔
1666
}
1667

1668
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
3,803✔
1669
{
1670
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, MIR_NULL_STAMP);
3,803✔
1671

1672
#ifdef DEBUG
1673
   const mir_class_t class = mir_get_class(mu, type);
3,803✔
1674
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
3,803✔
1675
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1676
              "null type must be file, access, context, or pointer");
1677
#endif
1678

1679
   return result;
3,803✔
1680
}
1681

1682
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
542✔
1683
                          mir_value_t count)
1684
{
1685
   mir_type_t access = mir_access_type(mu, type);
542✔
1686

1687
   mir_value_t result;
542✔
1688
   if (mir_is_null(count))
542✔
1689
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
118✔
1690
   else
1691
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
424✔
1692

1693
#ifdef DEBUG
1694
   const mir_class_t class = mir_get_class(mu, type);
542✔
1695
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
542✔
1696
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1697
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1698
              "new type must be int, real, record, access, or uarray");
1699
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
542✔
1700
              "new count must have offset type");
1701
#endif
1702

1703
   return result;
542✔
1704
}
1705

1706
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
1,928✔
1707
{
1708
   mir_type_t type = mir_get_type(mu, access);
1,928✔
1709
   mir_stamp_t stamp = mir_get_stamp(mu, access);
1,928✔
1710
   mir_type_t pointed = mir_get_pointer(mu, type);
1,928✔
1711
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
1,928✔
1712

1713
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
1,928✔
1714
              "argument to all must be access type");
1715

1716
   return result;
1,928✔
1717
}
1718

1719
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
29,202✔
1720
{
1721
   mir_type_t type = mir_get_type(mu, array);
29,202✔
1722
   mir_type_t pointer = mir_get_pointer(mu, type);
29,202✔
1723
   mir_stamp_t stamp = mir_get_stamp(mu, array);
29,202✔
1724

1725
   if (mir_is_null(pointer))
29,202✔
1726
      pointer = mir_pointer_type(mu, type);
2,185✔
1727

1728
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
29,202✔
1729
                                    pointer, stamp, array);
1730

1731
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
29,202✔
1732
              || mir_is(mu, array, MIR_TYPE_RECORD),
1733
              "argument to address of must be array or record");
1734

1735
   return result;
29,202✔
1736
}
1737

1738
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
41,653✔
1739
                                mir_value_t offset)
1740
{
1741
   mir_type_t type = mir_get_type(mu, array);
41,653✔
1742
   mir_stamp_t stamp = mir_get_stamp(mu, array);
41,653✔
1743

1744
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
41,653✔
1745
                                    array, offset);
1746

1747
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
41,653✔
1748
              "argument to array ref must be pointer or signal");
1749
   MIR_ASSERT(mir_is_offset(mu, offset),
41,653✔
1750
              "offset argument to array ref must be offset");
1751

1752
   return result;
41,653✔
1753
}
1754

1755
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
49,741✔
1756
                                 unsigned field)
1757
{
1758
   mir_type_t pointer = mir_get_type(mu, record);
49,741✔
1759

1760
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
49,741✔
1761

1762
   mir_type_t type = MIR_NULL_TYPE;
49,741✔
1763
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
49,741✔
1764
      type = td->u.record.fields[field + td->u.record.count];
49,741✔
1765

1766
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, MIR_NULL_STAMP,
49,741✔
1767
                                    record, mir_enum(field));
1768

1769
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
49,741✔
1770
              "record ref argument must be pointer to record");
1771
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
49,741✔
1772
              "record ref argument must be pointer to record");
1773
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
49,741✔
1774

1775
   return result;
49,741✔
1776
}
1777

1778
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
35,836✔
1779
                           const mir_dim_t *dims, int ndims)
1780
{
1781
   mir_type_t type = mir_get_type(mu, data);
35,836✔
1782
   mir_stamp_t stamp = mir_get_stamp(mu, data);
35,836✔
1783

1784
   const type_data_t *td = mir_type_data(mu, type);
35,836✔
1785
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
35,836✔
1786

1787
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
35,836✔
1788

1789
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
71,672✔
1790
                                  ndims * 3 + 1);
35,836✔
1791

1792
   mir_set_arg(mu, n, 0, data);
35,836✔
1793

1794
   for (int i = 0; i < ndims; i++) {
72,242✔
1795
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
36,406✔
1796
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
36,406✔
1797
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
36,406✔
1798
   }
1799

1800
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
35,836✔
1801
              "wrapped data is not pointer or signal");
1802

1803
   for (int i = 0; i < ndims; i++) {
72,242✔
1804
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
36,406✔
1805
                 "dimension %d left bound must be integral", i + 1);
1806
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
36,406✔
1807
                 "dimension %d right bound must be integral", i + 1);
1808
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
36,406✔
1809
                 "dimension %d direction must be bool", i + 1);
1810
   }
1811

1812
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
35,836✔
1813
}
1814

1815
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
31,345✔
1816
{
1817
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
31,345✔
1818
      return mir_get_arg(mu, array, 0);
2,247✔
1819

1820
   mir_type_t type = mir_get_type(mu, array);
29,098✔
1821
   mir_type_t pointer = mir_get_pointer(mu, type);
29,098✔
1822
   mir_stamp_t stamp = mir_get_stamp(mu, array);
29,098✔
1823

1824
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
29,098✔
1825

1826
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
29,098✔
1827
              "unwrap argument must be uarray");
1828

1829
   return result;
29,098✔
1830
}
1831

1832
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
24,531✔
1833
{
1834
   mir_type_t t_offset = mir_offset_type(mu);
24,531✔
1835
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
24,531✔
1836
                                    MIR_NULL_STAMP, array,
24,531✔
1837
                                    mir_const(mu, t_offset, dim));
1838

1839
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
24,531✔
1840
              "uarray len argument must be uarrray");
1841

1842
#ifdef DEBUG
1843
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
24,531✔
1844
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
24,531✔
1845
#endif
1846

1847
   return result;
24,531✔
1848
}
1849

1850
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
56,477✔
1851
                                       mir_type_t type, int arg_index,
1852
                                       mir_value_t array, int dim)
1853
{
1854
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
56,477✔
1855
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,759✔
1856

1857
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
54,718✔
1858
                                    array, mir_enum(dim));
1859

1860
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
54,718✔
1861
              "cannot use %s with non-uarray type", mir_op_string(op));
1862

1863
#ifdef DEBUG
1864
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
54,718✔
1865
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
54,718✔
1866
#endif
1867

1868
   return result;
54,718✔
1869
}
1870

1871
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
19,723✔
1872
{
1873
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
19,723✔
1874
                              0, array, dim);
1875
}
1876

1877
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
17,088✔
1878
{
1879
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
17,088✔
1880
                              1, array, dim);
1881
}
1882

1883
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
19,666✔
1884
{
1885
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
19,666✔
1886
                              2, array, dim);
1887
}
1888

1889
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
7,130✔
1890
                                   mir_value_t right, mir_value_t dir)
1891
{
1892
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
7,130✔
1893
                                    mir_offset_type(mu), MIR_NULL_STAMP,
7,130✔
1894
                                    left, right, dir);
1895

1896
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
7,130✔
1897
                            mir_get_type(mu, right)),
1898
              "left and right are not the same type");
1899
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
7,130✔
1900
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
7,130✔
1901

1902
   return result;
7,130✔
1903
}
1904

1905
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
4,915✔
1906
                                 mir_value_t right, mir_value_t dir)
1907
{
1908
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
4,915✔
1909
                                    mir_bool_type(mu), MIR_NULL_STAMP,
4,915✔
1910
                                    left, right, dir);
1911

1912
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
4,915✔
1913
                            mir_get_type(mu, right)),
1914
              "left and right are not the same type");
1915
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
4,915✔
1916
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
4,915✔
1917

1918
   return result;
4,915✔
1919
}
1920

1921
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
42,611✔
1922
{
1923
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
42,611✔
1924
               mir_cast_value(target));
42,611✔
1925

1926
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
42,611✔
1927
}
42,611✔
1928

1929
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
39,053✔
1930
                    mir_block_t bfalse)
1931
{
1932
   int64_t tconst;
39,053✔
1933
   if (mir_get_const(mu, test, &tconst)) {
39,053✔
1934
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
33✔
1935
      return;
33✔
1936
   }
1937

1938
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
39,020✔
1939
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
39,020✔
1940

1941
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
39,020✔
1942
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
39,020✔
1943
              "invalid cond targets");
1944
}
1945

1946
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
14,294✔
1947
                             mir_value_t vtrue, mir_value_t vfalse)
1948
{
1949
   int64_t tconst;
14,294✔
1950
   if (mir_get_const(mu, test, &tconst))
14,294✔
1951
      return tconst ? vtrue : vfalse;
156✔
1952
   else if (mir_equals(vtrue, vfalse))
14,138✔
1953
      return vtrue;
1✔
1954

1955
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
14,137✔
1956
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
14,137✔
1957
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
14,137✔
1958

1959
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
14,137✔
1960
                                    vtrue, vfalse);
1961

1962
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
14,137✔
1963
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
14,137✔
1964
              "true argument to select is not expected type");
1965
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
14,137✔
1966
              "false argument to select is not expected type");
1967

1968
   return result;
14,137✔
1969
}
1970

1971
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
1972
{
1973
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
1974
                                 ninputs * 2);
1975

1976
   for (int i = 0; i < ninputs; i++)
3✔
1977
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
1978

1979
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
1980
}
1981

1982
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
1983
                   mir_block_t block, mir_value_t value)
1984
{
1985
   node_data_t *n = mir_node_data(mu, phi);
2✔
1986
   assert(n->op == MIR_OP_PHI);
2✔
1987
   assert(nth * 2 < n->nargs);
2✔
1988

1989
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
1990
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
1991

1992
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
1993

1994
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
1995
              "phi input %d has wrong type", nth);
1996

1997
#ifdef DEBUG
1998
   if (value.tag != MIR_TAG_CONST) {
2✔
1999
      const block_data_t *bd = mir_block_data(mu, block);
2✔
2000
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
2001
         if (bd->nodes[i] == value.id)
2✔
2002
         return;
2003
      }
2004

2005
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
2006
   }
2007
#endif
2008
}
2009

2010
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
781✔
2011
                    const mir_value_t *cases, const mir_block_t *blocks,
2012
                    int ncases)
2013
{
2014
   int64_t cval;
781✔
2015
   if (mir_get_const(mu, value, &cval)) {
781✔
2016
      for (int i = 0; i < ncases; i++) {
3✔
2017
         int64_t cmp;
2✔
2018
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
2019
            mir_build_jump(mu, blocks[i]);
1✔
2020
            return;
1✔
2021
         }
2022
      }
2023

2024
      mir_build_jump(mu, def);
1✔
2025
      return;
1✔
2026
   }
2027

2028
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,558✔
2029
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
779✔
2030

2031
   mir_set_arg(mu, n, 0, value);
779✔
2032
   mir_set_arg(mu, n, 1, mir_cast_value(def));
779✔
2033

2034
   for (int i = 0; i < ncases; i++) {
6,226✔
2035
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
5,447✔
2036
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
5,447✔
2037
   }
2038

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

2041
#ifdef DEBUG
2042
   mir_type_t type = mir_get_type(mu, value);
779✔
2043
   for (int i = 0; i < ncases; i++) {
6,226✔
2044
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
5,447✔
2045
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
5,447✔
2046
                 "choice and value types do not match");
2047

2048
      for (int j = 0; j < i; j++)
280,217✔
2049
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
274,770✔
2050
   }
2051
#endif
2052
}
2053

2054
void mir_build_return(mir_unit_t *mu, mir_value_t value)
66,676✔
2055
{
2056
   if (mir_is_null(value))
66,676✔
2057
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
32,668✔
2058
   else
2059
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
34,008✔
2060

2061
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
66,676✔
2062
              "wrong result type");
2063
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
66,676✔
2064
              || mir_is_null(value), "cannot return a result");
2065
}
66,676✔
2066

2067
void mir_build_wait(mir_unit_t *mu, mir_block_t target, mir_value_t time)
18,400✔
2068
{
2069
   if (mir_is_null(time))
18,400✔
2070
      mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
11,258✔
2071
                  mir_cast_value(target));
11,258✔
2072
   else
2073
      mir_build_2(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,142✔
2074
                  mir_cast_value(target), time);
7,142✔
2075

2076
   MIR_ASSERT(mir_is_null(time) || mir_is_time(mu, time),
18,400✔
2077
              "time argument to wait is not a time");
2078
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
18,400✔
2079
              "wait only allowed in process or procedure");
2080
}
18,400✔
2081

2082
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
1✔
2083
{
2084
   if (value.tag != MIR_TAG_NODE)
1✔
2085
      return;   // Only useful for keeping nodes alive
2086

2087
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
2088
}
2089

2090
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
43,981✔
2091
                            mir_stamp_t stamp, const mir_value_t *args,
2092
                            unsigned nargs)
2093
{
2094
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
43,981✔
2095

2096
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
43,981✔
2097

2098
   for (int i = 0; i < nargs; i++)
170,865✔
2099
      mir_set_arg(mu, n, i + 1, args[i]);
126,884✔
2100

2101
   if (mir_is_null(type))
43,981✔
2102
      return MIR_NULL_VALUE;
6,162✔
2103
   else
2104
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
37,819✔
2105
}
2106

2107
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
1,164✔
2108
                     const mir_value_t *args, unsigned nargs)
2109
{
2110
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
2,328✔
2111
                                 MIR_NULL_STAMP, nargs + 2);
1,164✔
2112
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
1,164✔
2113
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
1,164✔
2114

2115
   for (int i = 0; i < nargs; i++)
4,080✔
2116
      mir_set_arg(mu, n, i + 2, args[i]);
2,916✔
2117

2118
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
1,164✔
2119
              "first argument to VHDL procedure must be context pointer");
2120
}
1,164✔
2121

2122
void mir_build_resume(mir_unit_t *mu, ident_t name)
1,164✔
2123
{
2124
   mir_value_t link = mir_add_linkage(mu, name);
1,164✔
2125
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
1,164✔
2126

2127
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
1,164✔
2128
              "resume must be first op in a block");
2129
}
1,164✔
2130

2131
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
564✔
2132
                              mir_stamp_t stamp, mir_value_t locus,
2133
                              const mir_value_t *args, int nargs)
2134
{
2135
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
564✔
2136

2137
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
564✔
2138
   mir_set_arg(mu, n, 1, locus);
564✔
2139

2140
   for (int i = 0; i < nargs; i++)
664✔
2141
      mir_set_arg(mu, n, i + 2, args[i]);
100✔
2142

2143
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
564✔
2144
              "locus argument to syscall must be a debug locus");
2145

2146
   for (int i = 0; i < nargs; i++)
664✔
2147
      MIR_ASSERT(!mir_is_null(args[i]), "invalid argument to syscall");
100✔
2148

2149
   if (mir_is_null(type))
564✔
2150
      return MIR_NULL_VALUE;
512✔
2151
   else
2152
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
52✔
2153
}
2154

2155
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
760✔
2156
{
2157
   if (mir_is_null(locus))
760✔
2158
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
616✔
2159
   else
2160
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
144✔
2161

2162
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
760✔
2163
              "locus argument to unreachable must be debug locus");
2164
}
760✔
2165
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
17,773✔
2166
                                mir_value_t left, mir_value_t right,
2167
                                mir_value_t dir, mir_value_t locus,
2168
                                mir_value_t hint)
2169
{
2170
   // TODO: check if can elide bounds
2171

2172
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
17,773✔
2173
               dir, locus, hint);
2174
}
17,773✔
2175

2176
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
3,041✔
2177
                           mir_value_t right, mir_value_t dir,
2178
                           mir_value_t locus, mir_value_t hint)
2179
{
2180
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
3,041✔
2181
                       locus, hint);
2182
}
3,041✔
2183

2184
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
14,732✔
2185
                           mir_value_t right, mir_value_t dir,
2186
                           mir_value_t locus, mir_value_t hint)
2187
{
2188
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
14,732✔
2189
                       locus, hint);
2190
}
14,732✔
2191

2192
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
1,386✔
2193
{
2194
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,386✔
2195
               ptr, locus);
2196

2197
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
1,386✔
2198
              "null check argument must be an access");
2199
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,386✔
2200
              "locus argument to null check must be a debug locus");
2201
}
1,386✔
2202

2203
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
138✔
2204
{
2205
   int64_t cval;
138✔
2206
   if (mir_get_const(mu, value, &cval) && cval != 0)
138✔
2207
      return;
×
2208

2209
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
138✔
2210
               value, locus);
2211

2212
   MIR_ASSERT(mir_is_integral(mu, value),
138✔
2213
              "argument to zero check must be integral");
2214
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
138✔
2215
              "locus argument to zero check must be a debug locus");
2216
}
2217

2218
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
7,729✔
2219
                            mir_value_t locus, mir_value_t dim)
2220
{
2221
   if (mir_equals(llen, rlen))
7,729✔
2222
      return;
2223

2224
   if (mir_is_null(dim))
7,729✔
2225
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,693✔
2226
                  llen, rlen, locus);
2227
   else
2228
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
36✔
2229
                  llen, rlen, locus, dim);
2230

2231
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
7,729✔
2232
              "locus argument to length check must be a debug locus");
2233
}
2234

2235
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
669✔
2236
                              mir_value_t locus)
2237
{
2238
   int64_t cval;
669✔
2239
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
669✔
2240
      return;
×
2241

2242
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
669✔
2243
               exp, locus);
2244

2245
   MIR_ASSERT(mir_is_integral(mu, exp),
669✔
2246
              "exp argument to exponent check must be a integer");
2247
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
669✔
2248
              "locus argument to exponent check must be a debug locus");
2249
}
2250

2251
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
347✔
2252
                         mir_value_t length, mir_value_t kind,
2253
                         mir_value_t status)
2254
{
2255
   if (mir_is_null(status))
347✔
2256
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
313✔
2257
                  file, name, length, kind);
2258
   else
2259
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
34✔
2260
                  file, name, length, kind, status);
2261

2262
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
347✔
2263
              "file open first argument must be pointer to file");
2264
}
347✔
2265

2266
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
99✔
2267
                         mir_value_t inlen, mir_value_t outlen)
2268
{
2269
   if (mir_is_null(inlen))
99✔
2270
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
64✔
2271
                  file, ptr);
2272
   else if (mir_is_null(outlen))
35✔
2273
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2274
                  file, ptr, inlen);
2275
   else
2276
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
23✔
2277
                  file, ptr, inlen, outlen);
2278

2279
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
99✔
2280
              "file read first argument must have file pointer type");
2281
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
99✔
2282
              "file read pointer argument must have pointer type");
2283
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
99✔
2284
              "file read inlen argument must be integral");
2285
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
99✔
2286
              "file read outlen argument must have pointer type");
2287
}
99✔
2288

2289
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
159✔
2290
                          mir_value_t length)
2291
{
2292
   if (mir_is_null(length))
159✔
2293
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
76✔
2294
                  file, value);
2295
   else
2296
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
83✔
2297
                  file, value, length);
2298

2299
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
159✔
2300
              "file write first argument must have file pointer type");
2301
}
159✔
2302

2303
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
376✔
2304
                                      mir_value_t effective)
2305
{
2306
   mir_type_t type = mir_conversion_type(mu);
376✔
2307

2308
   mir_value_t result;
376✔
2309
   if (mir_is_null(effective) || mir_equals(effective, driving))
376✔
2310
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
352✔
2311
                           driving);
2312
   else
2313
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
24✔
2314
                           driving, effective);
2315

2316
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
376✔
2317
              "port conversion argument must be a closure");
2318
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
376✔
2319
              "port conversion argument must be a closure");
2320

2321
   return result;
376✔
2322
}
2323

2324
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
480✔
2325
                          mir_value_t count)
2326
{
2327
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
480✔
2328
               conv, nets, count);
2329

2330
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
480✔
2331
              "conv argument to convert must be a port conversion");
2332
   MIR_ASSERT(mir_is_signal(mu, nets),
480✔
2333
              "nets argument to convert must be a signal");
2334
   MIR_ASSERT(mir_is_offset(mu, count),
480✔
2335
              "count argument to convert must be offset");
2336
}
480✔
2337

2338
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
536✔
2339
                           mir_value_t count)
2340
{
2341
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
536✔
2342
               conv, nets, count);
2343

2344
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
536✔
2345
              "conv argument to convert must be a port conversion");
2346
   MIR_ASSERT(mir_is_signal(mu, nets),
536✔
2347
              "nets argument to convert must be a signal");
2348
   MIR_ASSERT(mir_is_offset(mu, count),
536✔
2349
              "count argument to convert must be offset");
2350
}
536✔
2351

2352
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
557✔
2353
                              mir_value_t target, mir_value_t count,
2354
                              mir_value_t values)
2355
{
2356
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
557✔
2357
               cf, target, count, values);
2358

2359
   MIR_ASSERT(mir_is_signal(mu, target),
557✔
2360
              "put conversion target is not signal");
2361
   MIR_ASSERT(mir_is_offset(mu, count),
557✔
2362
              "put conversion net count is not offset type");
2363
   MIR_ASSERT(!mir_is_signal(mu, values),
557✔
2364
              "signal cannot be values argument for put conversion");
2365
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
557✔
2366
              "cf argument to put conversion must be conversion function");
2367
}
557✔
2368

2369
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
21,156✔
2370
                                  mir_value_t count, mir_value_t size,
2371
                                  mir_value_t value, mir_value_t flags,
2372
                                  mir_value_t locus, mir_value_t offset)
2373
{
2374
   mir_type_t stype = mir_signal_type(mu, type);
21,156✔
2375

2376
   mir_value_t result;
21,156✔
2377
   if (mir_is_null(offset))
21,156✔
2378
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
13,699✔
2379
                           count, size, value, flags, locus);
2380
   else
2381
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
7,457✔
2382
                           count, size, value, flags, locus, offset);
2383

2384
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
21,156✔
2385
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2386
              "signal must have integer or real type");
2387
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
21,156✔
2388
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
21,156✔
2389
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
21,156✔
2390
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
21,156✔
2391
              "locus argument to init signal is not debug locus");
2392
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
21,156✔
2393
              "offset argument must be pointer or null");
2394

2395
   return result;
21,156✔
2396
}
2397

2398
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
108✔
2399
                                      mir_value_t count, mir_value_t size,
2400
                                      mir_value_t locus, mir_value_t kind,
2401
                                      mir_value_t closure, mir_value_t delay)
2402
{
2403
   mir_type_t stype = mir_signal_type(mu, type);
108✔
2404

2405
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
108✔
2406
                                    MIR_NULL_STAMP, count, size, locus,
108✔
2407
                                    kind, closure, delay);
2408

2409
   MIR_ASSERT(mir_is_offset(mu, count),
108✔
2410
              "count argument to implicit signal is not offset");
2411
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
108✔
2412
              "kind argument to implicit signal is not offset");
2413
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
108✔
2414
              "closure argument to implicit signal is not a closure");
2415
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
108✔
2416
              "locus argument to implicit signal must be a debug locus");
2417
   MIR_ASSERT(mir_is_integral(mu, delay),
108✔
2418
              "delay argument to implicit signal must be time");
2419

2420
   return result;
108✔
2421
}
2422

2423
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
12,504✔
2424
                            mir_value_t count)
2425
{
2426
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
12,504✔
2427
               target, count);
2428

2429
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
12,504✔
2430
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
12,504✔
2431
}
12,504✔
2432

2433
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
14,383✔
2434
                              mir_value_t count, mir_value_t values,
2435
                              mir_value_t reject, mir_value_t after)
2436
{
2437
   int64_t nconst;
14,383✔
2438
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
14,383✔
2439
      mir_comment(mu, "Skip empty waveform");
×
2440
      return;
×
2441
   }
2442

2443
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
14,383✔
2444
               target, count, values, reject, after);
2445

2446
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
14,383✔
2447
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
14,383✔
2448
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
14,383✔
2449
}
2450

2451
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
236✔
2452
                              mir_value_t count, mir_value_t values)
2453
{
2454
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
236✔
2455
               target, count, values);
2456

2457
   MIR_ASSERT(mir_is_signal(mu, target),
236✔
2458
              "deposit signal target is not signal");
2459
   MIR_ASSERT(mir_is_offset(mu, count),
236✔
2460
              "deposit signal count is not offset type");
2461
   MIR_ASSERT(!mir_is_signal(mu, values),
236✔
2462
              "signal cannot be values argument for deposit signal");
2463
}
236✔
2464

2465
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
19,109✔
2466
{
2467
   mir_type_t type = mir_get_type(mu, signal);
19,109✔
2468
   mir_type_t pointer = mir_get_pointer(mu, type);
19,109✔
2469
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
19,109✔
2470

2471
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
19,109✔
2472
                                    stamp, signal);
2473

2474
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
19,109✔
2475
              "argument to resolved must be signal");
2476

2477
   return result;
19,109✔
2478
}
2479

2480
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
153✔
2481
{
2482
   mir_type_t type = mir_get_type(mu, signal);
153✔
2483
   mir_type_t pointer = mir_get_pointer(mu, type);
153✔
2484
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
153✔
2485

2486
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
153✔
2487
                                    stamp, signal);
2488

2489
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
153✔
2490
              "argument to resolved must be signal");
2491

2492
   return result;
153✔
2493
}
2494

2495
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
218✔
2496
                                    mir_value_t count)
2497
{
2498
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
218✔
2499
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
218✔
2500

2501
   mir_value_t result;
218✔
2502
   if (mir_is_null(count))
218✔
2503
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
174✔
2504
   else
2505
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
44✔
2506
                           signal, count);
2507

2508
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
218✔
2509
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
218✔
2510
              "count argument must have offset type");
2511

2512
   return result;
218✔
2513
}
2514

2515
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
84✔
2516
                     mir_value_t values)
2517
{
2518
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
84✔
2519
               target, count, values);
2520

2521
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
84✔
2522
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
84✔
2523
}
84✔
2524

2525
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
40✔
2526
{
2527
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
40✔
2528
               target, count);
2529

2530
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
40✔
2531
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
40✔
2532
}
40✔
2533

2534
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
32✔
2535
                          mir_value_t reject, mir_value_t after)
2536
{
2537
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
32✔
2538
               target, count, reject, after);
2539

2540
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
32✔
2541
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
32✔
2542
}
32✔
2543

2544

2545
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
77✔
2546
                                 mir_value_t count)
2547
{
2548
   mir_type_t type = mir_time_type(mu);
77✔
2549

2550
   mir_value_t result;
77✔
2551
   if (mir_is_null(count))
77✔
2552
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
65✔
2553
   else
2554
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
12✔
2555
                           signal, count);
2556

2557
   MIR_ASSERT(mir_is_signal(mu, signal),
77✔
2558
              "signal argument to last event must have signal type");
2559
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
77✔
2560
              "length argument to last event must have offset type");
2561

2562
   return result;
77✔
2563
}
2564

2565
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
81✔
2566
                                  mir_value_t count)
2567
{
2568
   mir_type_t type = mir_time_type(mu);
81✔
2569

2570
   mir_value_t result;
81✔
2571
   if (mir_is_null(count))
81✔
2572
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
73✔
2573
                           signal);
2574
   else
2575
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
8✔
2576
                           signal, count);
2577

2578
   MIR_ASSERT(mir_is_signal(mu, signal),
81✔
2579
              "signal argument to last event must have signal type");
2580
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
81✔
2581
              "length argument to last event must have offset type");
2582

2583
   return result;
81✔
2584
}
2585

2586

2587
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
904✔
2588
                                         mir_value_t signal, mir_value_t count)
2589
{
2590
   mir_type_t t_bool = mir_bool_type(mu);
904✔
2591
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
904✔
2592
                                    signal, count);
2593

2594
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
904✔
2595
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
904✔
2596

2597
   return result;
904✔
2598
}
2599

2600
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
563✔
2601
                                 mir_value_t count)
2602
{
2603
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
563✔
2604
}
2605

2606
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
293✔
2607
                                  mir_value_t count)
2608
{
2609
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
293✔
2610
}
2611

2612
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
48✔
2613
                                   mir_value_t count)
2614
{
2615
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
48✔
2616
}
2617

2618
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
4,465✔
2619
                              mir_value_t resolution)
2620
{
2621
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,465✔
2622
               signal, resolution);
2623

2624
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
4,465✔
2625
   MIR_ASSERT(mir_points_to(mu, resolution, MIR_TYPE_RESOLUTION),
4,465✔
2626
              "resolution wrapper argument has wrong type");
2627
}
4,465✔
2628

2629
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
1,595✔
2630
                               mir_value_t source, mir_value_t count,
2631
                               mir_value_t reject, mir_value_t after)
2632
{
2633
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,595✔
2634
               target, source, count, reject, after);
2635

2636
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
1,595✔
2637
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,595✔
2638
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
1,595✔
2639
}
1,595✔
2640

2641
void mir_build_cover_stmt(mir_unit_t *mu, uint32_t tag)
1,374✔
2642
{
2643
   mir_build_1(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,374✔
2644
               mir_enum(tag));
2645
}
1,374✔
2646

2647
void mir_build_cover_branch(mir_unit_t *mu, uint32_t tag)
657✔
2648
{
2649
   mir_build_1(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
657✔
2650
               mir_enum(tag));
2651
}
657✔
2652

2653
void mir_build_cover_expr(mir_unit_t *mu, uint32_t tag)
1,142✔
2654
{
2655
   mir_build_1(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,142✔
2656
               mir_enum(tag));
2657
}
1,142✔
2658

2659
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
416✔
2660
{
2661
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
416✔
2662
               signal, mir_enum(tag));
2663

2664
   MIR_ASSERT(mir_is_signal(mu, signal),
416✔
2665
              "argument to cover toggle must be signal");
2666
}
416✔
2667

2668
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
16✔
2669
                           uint32_t tag)
2670
{
2671
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
16✔
2672
               signal, low, mir_enum(tag));
2673

2674
   MIR_ASSERT(mir_is_signal(mu, signal),
16✔
2675
              "argument to cover state must be signal");
2676
}
16✔
2677
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
27,568✔
2678
                                   mir_value_t context)
2679
{
2680
   mir_value_t link = mir_add_linkage(mu, name);
27,568✔
2681
   mir_type_t type = mir_context_type(mu, name);
27,568✔
2682

2683
   mir_value_t result;
27,568✔
2684
   if (mir_is_null(context))
27,568✔
2685
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
27,325✔
2686
                           MIR_NULL_STAMP, link);
27,325✔
2687
   else
2688
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
243✔
2689
                           MIR_NULL_STAMP, link, context);
243✔
2690

2691
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
27,568✔
2692
              "invalid package init context argument");
2693
   MIR_ASSERT(mu->kind == MIR_UNIT_INSTANCE
27,568✔
2694
              || mu->kind == MIR_UNIT_PACKAGE
2695
              || mu->kind == MIR_UNIT_THUNK,
2696
              "cannot use package init here");
2697
   MIR_ASSERT(name != mu->name, "cyclic package init");
27,568✔
2698

2699
   return result;
27,568✔
2700
}
2701

2702
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
154✔
2703
{
2704
   mir_value_t link = mir_add_linkage(mu, name);
154✔
2705
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
154✔
2706
               link, locus);
2707

2708
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
154✔
2709
              "locus argument to process init must be a debug locus");
2710
}
154✔
2711

2712
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
241✔
2713
                                     mir_value_t context, mir_value_t path_name,
2714
                                     mir_value_t inst_name)
2715
{
2716
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
241✔
2717

2718
   mir_value_t result;
241✔
2719
   if (mir_is_null(path_name) && mir_is_null(inst_name))
241✔
2720
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
171✔
2721
                           link, context);
2722
   else {
2723
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
70✔
2724
                           link, context, path_name, inst_name);
2725

2726
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
70✔
2727
                 "path name argument must be array");
2728
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
70✔
2729
                 "inst name argument must be array");
2730
   }
2731

2732
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
241✔
2733
                "protected init type must be context");
2734
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
241✔
2735
              "invalid protected init context argument");
2736

2737
   return result;
241✔
2738
}
2739

2740
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
2,129✔
2741
{
2742
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
2,129✔
2743

2744
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,129✔
2745
              "locus argument to record scope must be a debug locus");
2746
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
2,129✔
2747
              "record scope type must be record");
2748
}
2,129✔
2749

2750
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
839✔
2751
{
2752
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
839✔
2753

2754
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
839✔
2755
              "locus argument to array scope must be a debug locus");
2756
}
839✔
2757

2758
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
59✔
2759
{
2760
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
59✔
2761

2762
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
59✔
2763
              "locus argument to package scope must be a debug locus");
2764
}
59✔
2765

2766
void mir_build_pop_scope(mir_unit_t *mu)
3,027✔
2767
{
2768
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
3,027✔
2769
}
3,027✔
2770

2771
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
5,571✔
2772
                            mir_value_t locus)
2773
{
2774
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,571✔
2775
               signal, locus);
2776

2777
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
5,571✔
2778
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
5,571✔
2779
              "locus argument must have debug locus type");
2780
}
5,571✔
2781

2782
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
7,059✔
2783
                          mir_value_t count)
2784
{
2785
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,059✔
2786
               src, dst, count);
2787

2788
   MIR_ASSERT(mir_is_signal(mu, src),
7,059✔
2789
              "src argument to map signal is not a signal");
2790
   MIR_ASSERT(mir_is_signal(mu, dst),
7,059✔
2791
              "dst argument to map signal is not a signal");
2792
   MIR_ASSERT(mir_is_offset(mu, count),
7,059✔
2793
              "count argument to map signal is not offset type");
2794
}
7,059✔
2795

2796
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
252✔
2797
                         mir_value_t count)
2798
{
2799
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
252✔
2800
               src, dst, count);
2801

2802
   MIR_ASSERT(mir_is_signal(mu, dst),
252✔
2803
              "dst argument to map const is not a signal");
2804
   MIR_ASSERT(mir_is_offset(mu, count),
252✔
2805
              "count argument to map const is not offset type");
2806
}
252✔
2807

2808
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
84✔
2809
                            mir_value_t count)
2810
{
2811
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
84✔
2812
               src, dst, count);
2813

2814
   MIR_ASSERT(mir_is_signal(mu, src),
84✔
2815
              "src argument to map implicit is not a signal");
2816
   MIR_ASSERT(mir_is_signal(mu, dst),
84✔
2817
              "dst argument to map implicit is not a signal");
2818
   MIR_ASSERT(mir_is_offset(mu, count),
84✔
2819
              "count argument type to map implicit is not offset");
2820
}
84✔
2821

2822
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
62✔
2823
                                  mir_value_t right)
2824
{
2825
   mir_type_t type = mir_trigger_type(mu);
62✔
2826
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
62✔
2827
                                    MIR_NULL_STAMP, left, right);
62✔
2828

2829
   MIR_ASSERT(mir_is_signal(mu, left),
62✔
2830
              "cmp trigger left argument must be signal");
2831
   MIR_ASSERT(mir_is_integral(mu, right),
62✔
2832
              "cmp trigger right argument must be integer");
2833

2834
   return result;
62✔
2835
}
2836

2837
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
288✔
2838
                                       const mir_value_t *args, unsigned nargs)
2839
{
2840
   mir_type_t type = mir_trigger_type(mu);
288✔
2841
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
576✔
2842
                                 MIR_NULL_STAMP, nargs + 1);
288✔
2843

2844
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
288✔
2845

2846
   for (int i = 0; i < nargs; i++)
760✔
2847
      mir_set_arg(mu, n, i + 1, args[i]);
472✔
2848

2849
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
288✔
2850
}
2851

2852
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
45✔
2853
                                 mir_value_t right)
2854
{
2855
   mir_type_t type = mir_trigger_type(mu);
45✔
2856
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
45✔
2857
                                    MIR_NULL_STAMP, left, right);
45✔
2858

2859
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
45✔
2860
              "or trigger left argument must be trigger");
2861
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
45✔
2862
              "or trigger right argument must be trigger");
2863

2864
   return result;
45✔
2865
}
2866

2867
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
501✔
2868
{
2869
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
501✔
2870

2871
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
501✔
2872
              "add trigger argument must be trigger");
2873
}
501✔
2874

2875
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
14,273✔
2876
{
2877
   mir_value_t link = mir_add_linkage(mu, name);
14,273✔
2878
   mir_type_t type = mir_context_type(mu, name);
14,273✔
2879

2880
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
14,273✔
2881
                                    MIR_NULL_STAMP, link);
14,273✔
2882

2883
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
14,273✔
2884

2885
   return result;
14,273✔
2886
}
2887

2888
mir_value_t mir_build_link_var(mir_unit_t *mu, ident_t unit,
4,657✔
2889
                               mir_value_t context, ident_t name,
2890
                               mir_type_t type)
2891
{
2892
   mir_type_t pointer = mir_get_var_pointer(mu, type);
4,657✔
2893
   mir_value_t link = mir_add_linkage(mu, unit);
4,657✔
2894
   mir_value_t var = mir_add_extvar(mu, name);
4,657✔
2895
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
4,657✔
2896
                                    MIR_NULL_STAMP, link, context, var);
4,657✔
2897

2898
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
4,657✔
2899
              "first argument to link var must be context");
2900

2901
   return result;
4,657✔
2902
}
2903

2904
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
328✔
2905
                            mir_value_t length, mir_value_t locus)
2906
{
2907
   if (mir_is_null(locus))
328✔
2908
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
162✔
2909
                  spec, length);
2910
   else
2911
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
166✔
2912
                  spec, length, locus);
2913

2914
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
328✔
2915
              "spec argument to bind foreign must be a pointer");
2916
   MIR_ASSERT(mir_is_offset(mu, length),
328✔
2917
              "legnth argument to bind foreign must be offset");
2918
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
328✔
2919
              "locus argument to bind foreign value must be a debug locus");
2920
}
328✔
2921

2922
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
261✔
2923
                                    ident_t scope, mir_type_t type,
2924
                                    mir_stamp_t stamp)
2925
{
2926
   mir_type_t pointer = mir_get_var_pointer(mu, type);
261✔
2927
   mir_value_t link = mir_add_linkage(mu, scope);
261✔
2928
   mir_value_t result = mir_build_2(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
261✔
2929
                                    locus, link);
2930

2931
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
261✔
2932
              "bind external argument must be locus");
2933

2934
   return result;
261✔
2935
}
2936

2937
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
10,247✔
2938
{
2939
   mir_type_t type = MIR_NULL_TYPE;
10,247✔
2940
   if (hops == 0)
10,247✔
2941
      type = mir_self_type(mu);
1,479✔
2942
   else {
2943
      mir_shape_t *s = mu->parent;
8,768✔
2944
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
9,133✔
2945

2946
      if (s != NULL) type = s->type;
8,768✔
2947
   }
2948

2949
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
10,247✔
2950
                                    MIR_NULL_STAMP, mir_enum(hops));
10,247✔
2951

2952
   MIR_ASSERT(hops >= 0, "invalid hop count");
10,247✔
2953
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
10,247✔
2954

2955
   return result;
10,247✔
2956
}
2957

2958
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
61,356✔
2959
{
2960
   mir_type_t type = MIR_NULL_TYPE;
61,356✔
2961
   mir_value_t link = MIR_NULL_VALUE;
61,356✔
2962

2963
   mir_shape_t *s = mu->parent;
61,356✔
2964
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
75,862✔
2965

2966
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
61,356✔
2967
      type = s->slots[nth].pointer;
61,356✔
2968
      link = mir_add_linkage(mu, s->name);
61,356✔
2969
   }
2970

2971
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
61,356✔
2972
                                    mir_enum(hops), link, mir_enum(nth));
2973

2974
   MIR_ASSERT(hops > 0, "invalid hop count");
61,356✔
2975
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
61,356✔
2976

2977
   return result;
61,356✔
2978
}
2979

2980
void mir_build_sched_event(mir_unit_t *mu, mir_value_t signal,
8,059✔
2981
                           mir_value_t count)
2982
{
2983
   mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,059✔
2984
               signal, count);
2985

2986
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
8,059✔
2987
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
8,059✔
2988
}
8,059✔
2989

2990
void mir_build_clear_event(mir_unit_t *mu, mir_value_t signal,
702✔
2991
                           mir_value_t count)
2992
{
2993
   mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
702✔
2994
               signal, count);
2995

2996
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
702✔
2997
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
702✔
2998
}
702✔
2999

3000
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
64✔
3001
                                    mir_value_t context, mir_value_t locus,
3002
                                    mir_value_t bounds)
3003
{
3004
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
64✔
3005

3006
   mir_value_t result;
64✔
3007
   if (mir_is_null(bounds))
64✔
3008
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
56✔
3009
                           value, context, locus);
3010
   else
3011
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
8✔
3012
                           value, context, locus, bounds);
3013

3014
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
64✔
3015
              "invalid reflect value context argument");
3016
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
64✔
3017
              "locus argument to reflect value must be a debug locus");
3018

3019
   return result;
64✔
3020
}
3021

3022
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
56✔
3023
                                      mir_value_t locus, mir_value_t bounds)
3024
{
3025
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
56✔
3026

3027
   mir_value_t result;
56✔
3028
   if (mir_is_null(bounds))
56✔
3029
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
56✔
3030
                           context, locus);
3031
   else
3032
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
×
3033
                           context, locus, bounds);
3034

3035
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
56✔
3036
              "invalid reflect subtype context argument");
3037
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
56✔
3038
              "locus argument to reflect subtype must be a debug locus");
3039

3040
   return result;
56✔
3041
}
3042

3043
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
18,219✔
3044
                      mir_value_t length, mir_value_t severity,
3045
                      mir_value_t locus, mir_value_t hint_left,
3046
                      mir_value_t hint_right)
3047
{
3048
   int64_t value_const;
18,219✔
3049
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
18,219✔
3050
      mir_comment(mu, "Always true assertion");
×
3051
      return;
×
3052
   }
3053

3054
   if (mir_is_null(hint_left))
18,219✔
3055
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
10,459✔
3056
                  value, severity, message, length, locus);
3057
   else {
3058
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
15,520✔
3059
                                     MIR_NULL_STAMP, 7);
7,760✔
3060
      mir_set_arg(mu, n, 0, value);
7,760✔
3061
      mir_set_arg(mu, n, 1, severity);
7,760✔
3062
      mir_set_arg(mu, n, 2, message);
7,760✔
3063
      mir_set_arg(mu, n, 3, length);
7,760✔
3064
      mir_set_arg(mu, n, 4, locus);
7,760✔
3065
      mir_set_arg(mu, n, 5, hint_left);
7,760✔
3066
      mir_set_arg(mu, n, 6, hint_right);
7,760✔
3067

3068
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
7,760✔
3069
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
7,760✔
3070
   }
3071

3072
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
18,219✔
3073
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
18,219✔
3074
              "message parameter to assert is not a pointer");
3075
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
18,219✔
3076
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
18,219✔
3077
              "locus argument to report must be a debug locus");
3078
}
3079

3080
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,917✔
3081
                      mir_value_t severity, mir_value_t locus)
3082
{
3083
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,917✔
3084
               severity, message, length, locus);
3085

3086
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,917✔
3087
              "message parameter to report is not a pointer");
3088
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,917✔
3089
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,917✔
3090
              "locus argument to report must be a debug locus");
3091
}
2,917✔
3092

3093
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
1,079✔
3094
{
3095
   mir_type_t type = mir_string_type(mu);
1,079✔
3096
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
1,079✔
3097
                                    MIR_NULL_STAMP, kind);
1,079✔
3098

3099
   MIR_ASSERT(mir_is_offset(mu, kind),
1,079✔
3100
              "kind argument to instance name must be offset");
3101

3102
   return result;
1,079✔
3103
}
3104

3105
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
1,040✔
3106
                           mir_value_t strong)
3107
{
3108
   if (mir_is_null(strong))
1,040✔
3109
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
1,016✔
3110
   else
3111
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
3112
                  state, strong);
3113

3114
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
1,040✔
3115
   MIR_ASSERT(mir_is_null(strong)
1,040✔
3116
              || mir_check_type(mu, strong, mir_bool_type(mu)),
3117
                "strong argument not is not boolean");
3118
}
1,040✔
3119

3120
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_value_t context,
1,247✔
3121
                              mir_type_t atype, mir_type_t rtype)
3122
{
3123
   mir_type_t ctype = mir_closure_type(mu, atype, rtype);
1,247✔
3124
   mir_value_t link = mir_add_linkage(mu, func);
1,247✔
3125

3126
   mir_value_t result = mir_build_2(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
1,247✔
3127
                                    link, context);
3128

3129
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
1,247✔
3130
              "invalid closure context argument");
3131

3132
   return result;
1,247✔
3133
}
3134

3135
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
739✔
3136
                                         mir_value_t closure, mir_value_t nlits)
3137
{
3138
   mir_type_t rtype = mir_resolution_type(mu, type);
739✔
3139
   mir_value_t result = mir_build_2(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
739✔
3140
                                    MIR_NULL_STAMP, closure, nlits);
739✔
3141

3142
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
739✔
3143
              "first argument to resolution wrapper must be closure");
3144

3145
   return result;
739✔
3146
}
3147

3148
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
83,093✔
3149
{
3150
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
83,093✔
3151
                                  MIR_NULL_STAMP, 0);
83,093✔
3152
   n->locus = obj;
83,093✔
3153

3154
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
83,093✔
3155
}
3156

3157
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
54,624✔
3158
{
3159
   mir_type_t from = mir_get_type(mu, value);
54,624✔
3160
   if (mir_equals(from, type))
54,624✔
3161
      return value;
54,624✔
3162

3163
   const mir_class_t class = mir_get_class(mu, type);
54,068✔
3164
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
54,068✔
3165

3166
   int64_t cval;
54,068✔
3167
   if (integral && mir_get_const(mu, value, &cval))
54,068✔
3168
      return mir_const(mu, type, cval);
464✔
3169

3170
   mir_stamp_t stamp = mir_stamp_cast(mu, type, mir_get_stamp(mu, value));
53,604✔
3171

3172
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type, stamp, value);
53,604✔
3173

3174
#ifdef DEBUG
3175
   static const mir_class_t allowed[][2] = {
53,604✔
3176
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
3177
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
3178
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
3179
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
3180
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
3181
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
3182
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
3183
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC2    },
3184
   };
3185

3186
   if (value.tag == MIR_TAG_CONST)
53,604✔
3187
      return result;
71✔
3188

3189
   const mir_class_t from_k = mir_get_class(mu, from);
53,533✔
3190

3191
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
97,535✔
3192
      if (from_k == allowed[i][0] && class == allowed[i][1])
97,535✔
3193
         return result;
53,533✔
3194
   }
3195

3196
   MIR_ASSERT(false, "invalid type conversion in cast");
×
3197
#else
3198
   return result;
3199
#endif
3200
}
3201

3202
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
×
3203
{
3204
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
3205

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

© 2026 Coveralls, Inc