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

nickg / nvc / 20582222397

29 Dec 2025 08:17PM UTC coverage: 92.573% (+0.008%) from 92.565%
20582222397

push

github

nickg
Add a table ref opcode for table lookups

76 of 77 new or added lines in 5 files covered. (98.7%)

510 existing lines in 6 files now uncovered.

75818 of 81901 relevant lines covered (92.57%)

454870.08 hits per line

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

96.8
/src/vcode.c
1
//
2
//  Copyright (C) 2014-2024  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 "common.h"
21
#include "diag.h"
22
#include "hash.h"
23
#include "lib.h"
24
#include "object.h"
25
#include "printf.h"
26
#include "tree.h"
27
#include "vcode.h"
28

29
#include <assert.h>
30
#include <inttypes.h>
31
#include <string.h>
32
#include <stdlib.h>
33
#include <float.h>
34
#include <math.h>
35

36
DECLARE_AND_DEFINE_ARRAY(vcode_reg);
10,040,273✔
37
DECLARE_AND_DEFINE_ARRAY(vcode_block);
345,125✔
38
DECLARE_AND_DEFINE_ARRAY(vcode_type);
81,170✔
39

40
#define OP_HAS_TYPE(x)                                                  \
41
   (x == VCODE_OP_ALLOC || x == VCODE_OP_COPY                           \
42
    || x == VCODE_OP_CONST || x == VCODE_OP_CAST                        \
43
    || x == VCODE_OP_CONST_RECORD                                       \
44
    || x == VCODE_OP_BIND_EXTERNAL || x == VCODE_OP_ARRAY_SCOPE         \
45
    || x == VCODE_OP_RECORD_SCOPE || x == VCODE_OP_SYSCALL)
46
#define OP_HAS_ADDRESS(x)                                               \
47
   (x == VCODE_OP_LOAD || x == VCODE_OP_STORE || x == VCODE_OP_INDEX    \
48
    || x == VCODE_OP_VAR_UPREF)
49
#define OP_HAS_FUNC(x)                                                  \
50
   (x == VCODE_OP_FCALL || x == VCODE_OP_PCALL || x == VCODE_OP_RESUME  \
51
    || x == VCODE_OP_CLOSURE || x == VCODE_OP_PROTECTED_INIT            \
52
    || x == VCODE_OP_PACKAGE_INIT || x == VCODE_OP_PROCESS_INIT \
53
    || x == VCODE_OP_FUNCTION_TRIGGER || x == VCODE_OP_SYSCALL)
54
#define OP_HAS_IDENT(x)                                                 \
55
   (x == VCODE_OP_LINK_VAR || x == VCODE_OP_LINK_PACKAGE                \
56
    || x == VCODE_OP_DEBUG_LOCUS || x == VCODE_OP_BIND_EXTERNAL)
57
#define OP_HAS_OBJECT(x)                                                 \
58
   (x == VCODE_OP_DEBUG_LOCUS)
59
#define OP_HAS_REAL(x)                                                  \
60
   (x == VCODE_OP_CONST_REAL)
61
#define OP_HAS_VALUE(x)                                                 \
62
   (x == VCODE_OP_CONST || x == VCODE_OP_CONST_REP)
63
#define OP_HAS_DIM(x)                                                   \
64
   (x == VCODE_OP_UARRAY_LEFT || x == VCODE_OP_UARRAY_RIGHT             \
65
    || x == VCODE_OP_UARRAY_DIR || x == VCODE_OP_UARRAY_LEN)
66
#define OP_HAS_HOPS(x)                                                  \
67
   (x == VCODE_OP_VAR_UPREF || x == VCODE_OP_CONTEXT_UPREF)
68
#define OP_HAS_FIELD(x)                                                 \
69
   (x == VCODE_OP_RECORD_REF)
70
#define OP_HAS_CMP(x)                                                   \
71
   (x == VCODE_OP_CMP)
72
#define OP_HAS_TAG(x)                                                   \
73
   (x == VCODE_OP_COVER_STMT || x == VCODE_OP_COVER_BRANCH              \
74
    || x == VCODE_OP_COVER_TOGGLE || x == VCODE_OP_COVER_EXPR           \
75
    || x == VCODE_OP_COVER_STATE)
76
#define OP_HAS_COMMENT(x)                                               \
77
   (x == VCODE_OP_COMMENT)
78
#define OP_HAS_TARGET(x)                                                \
79
   (x == VCODE_OP_WAIT || x == VCODE_OP_JUMP || x == VCODE_OP_COND      \
80
    || x == VCODE_OP_PCALL || x == VCODE_OP_CASE)
81

82
typedef struct {
83
   vcode_op_t              kind;
84
   vcode_reg_t             result;
85
   vcode_reg_array_t       args;
86
   loc_t                   loc;
87
   vcode_type_t            type;      // OP_HAS_TYPE
88
   union {
89
      ident_t              func;      // OP_HAS_FUNC
90
      ident_t              ident;     // OP_HAS_IDENT
91
      object_t            *object;    // OP_HAS_OBJECT
92
      vcode_var_t          address;   // OP_HAS_ADDRESS
93
   };
94
   union {
95
      vcode_cmp_t          cmp;       // OP_HAS_CMP
96
      int64_t              value;     // OP_HAS_VALUE
97
      double               real;      // OP_HAS_REAL
98
      char                *comment;   // OP_HAS_COMMENT
99
      unsigned             dim;       // OP_HAS_DIM
100
      unsigned             hops;      // OP_HAS_HOPS
101
      unsigned             field;     // OP_HAS_FIELD
102
      uint32_t             tag;       // OP_HAS_TAG
103
      vcode_block_array_t  targets;   // OP_HAS_TARGET
104
   };
105
} op_t;
106

107
DECLARE_AND_DEFINE_ARRAY(op);
11,872,552✔
108

109
typedef struct {
110
   op_array_t ops;
111
   loc_t      last_loc;
112
} block_t;
113

114
typedef struct {
115
   vcode_type_t type;
116
   vcode_type_t bounds;
117
} reg_t;
118

119
typedef struct {
120
   vtype_kind_t kind;
121
   vtype_repr_t repr;
122
   union {
123
      struct {
124
         int64_t low;
125
         int64_t high;
126
      };
127
      struct {
128
         double rlow;
129
         double rhigh;
130
      };
131
      struct {
132
         unsigned      dims;
133
         unsigned      size;
134
         vcode_type_t  elem;
135
         vcode_type_t  bounds;
136
      };
137
      vcode_type_t pointed;
138
      vcode_type_t base;
139
      struct {
140
         ident_t            name;
141
         vcode_type_array_t fields;
142
      };
143
   };
144
} vtype_t;
145

146
typedef struct {
147
   vcode_type_t      type;
148
   vcode_type_t      bounds;
149
   ident_t           name;
150
   vcode_var_flags_t flags;
151
} var_t;
152

153
typedef struct {
154
   vcode_type_t type;
155
   vcode_type_t bounds;
156
   ident_t      name;
157
   vcode_reg_t  reg;
158
} param_t;
159

160
DECLARE_AND_DEFINE_ARRAY(param);
31,710✔
161
DECLARE_AND_DEFINE_ARRAY(var);
445,205✔
162
DECLARE_AND_DEFINE_ARRAY(reg);
9,658,083✔
163
DECLARE_AND_DEFINE_ARRAY(block);
137,725✔
164
DECLARE_AND_DEFINE_ARRAY(vtype);
47,465,327✔
165

166
typedef enum {
167
   UNIT_UNDEFINED     = (1 << 1),
168
} unit_flags_t;
169

170
struct _vcode_unit {
171
   vunit_kind_t   kind;
172
   vcode_unit_t   context;
173
   ident_t        name;
174
   vcode_type_t   result;
175
   block_array_t  blocks;
176
   reg_array_t    regs;
177
   vtype_array_t  types;
178
   var_array_t    vars;
179
   param_array_t  params;
180
   unsigned       depth;
181
   unit_flags_t   flags;
182
   vcode_unit_t   children;
183
   vcode_unit_t   next;
184
   object_t      *object;
185
};
186

187
#define MASK_CONTEXT(x)   ((x) >> 24)
188
#define MASK_INDEX(x)     ((x) & 0xffffff)
189
#define MAKE_HANDLE(c, i) (((c) & 0xff) << 24 | ((i) & 0xffffff))
190

191
#define VCODE_ASSERT(expr, ...) do                                      \
192
      if (unlikely(!(expr))) {                                          \
193
         vcode_dump_with_mark(vcode_block_data()->ops.count - 1,        \
194
                              NULL, NULL);                              \
195
         fatal_trace(__VA_ARGS__);                                      \
196
      } while (0)
197

198
#define VCODE_FOR_EACH_OP(name)                                 \
199
   block_t *_b = vcode_block_data();                            \
200
   op_t *name; int _i;                                          \
201
   if (_b->ops.count > 0)                                       \
202
      for (_i = _b->ops.count - 1, name = &(_b->ops.items[_i]); \
203
           _i >= 0; name = &(_b->ops.items[--_i]))
204

205
#define VCODE_FOR_EACH_MATCHING_OP(name, k) \
206
   block_t *_b = vcode_block_data();                            \
207
   op_t *name; int _i;                                          \
208
   if (_b->ops.count > 0)                                       \
209
      for (_i = 0, name = &(_b->ops.items[_i]);                 \
210
           _i < _b->ops.count; name = &(_b->ops.items[++_i]))   \
211
         if (name->kind == (k))
212

213
#define VCODE_CHECK_UNIONS 0
214

215
static __thread vcode_unit_t  active_unit  = NULL;
216
static __thread vcode_block_t active_block = VCODE_INVALID_BLOCK;
217

218
static inline int64_t sadd64(int64_t a, int64_t b)
39,036✔
219
{
220
   int64_t result;
39,036✔
221
   if (__builtin_add_overflow(a, b, &result))
39,036✔
222
      return b < 0 ? INT64_MIN : INT64_MAX;
8,264✔
223

224
   return result;
225
}
226

227
static inline int64_t ssub64(int64_t a, int64_t b)
64,710✔
228
{
229
   int64_t result;
64,710✔
230
   if (__builtin_sub_overflow(a, b, &result))
64,710✔
231
      return b > 0 ? INT64_MIN : INT64_MAX;
872✔
232

233
   return result;
234
}
235

236
static inline int64_t smul64(int64_t a, int64_t b)
14,956✔
237
{
238
   int64_t result;
14,956✔
239
   if (__builtin_mul_overflow(a, b, &result))
14,956✔
240
      return (a > 0 && b > 0) || (a < 0 && b < 0) ? INT64_MAX : INT64_MIN;
1,768✔
241

242
   return result;
243
}
244

245
static vcode_reg_t vcode_add_reg(vcode_type_t type)
1,449,352✔
246
{
247
   assert(active_unit != NULL);
1,449,352✔
248

249
   vcode_reg_t reg = active_unit->regs.count;
1,449,352✔
250
   reg_t *r = reg_array_alloc(&(active_unit->regs));
1,449,352✔
251
   memset(r, '\0', sizeof(reg_t));
1,449,352✔
252
   r->type   = type;
1,449,352✔
253
   r->bounds = type;
1,449,352✔
254

255
   return reg;
1,449,352✔
256
}
257

258
static block_t *vcode_block_data(void)
8,316,526✔
259
{
260
   assert(active_unit != NULL);
8,316,526✔
261
   assert(active_block != -1);
8,316,526✔
262
   return &(active_unit->blocks.items[active_block]);
8,316,526✔
263
}
264

265
static op_t *vcode_add_op(vcode_op_t kind)
1,862,331✔
266
{
267
   assert(active_unit != NULL);
1,862,331✔
268
   assert(active_block != VCODE_INVALID_BLOCK);
1,862,331✔
269

270
   VCODE_ASSERT(
1,862,331✔
271
      !vcode_block_finished(),
272
      "attempt to add to already finished block %d", active_block);
273

274
   block_t *block = vcode_block_data();
1,862,331✔
275

276
   op_t *op = op_array_alloc(&(block->ops));
1,862,331✔
277
   memset(op, '\0', sizeof(op_t));
1,862,331✔
278
   op->kind   = kind;
1,862,331✔
279
   op->result = VCODE_INVALID_REG;
1,862,331✔
280
   op->loc    = block->last_loc;
1,862,331✔
281

282
   return op;
1,862,331✔
283
}
284

285
static void vcode_add_arg(op_t *op, vcode_reg_t arg)
3,296,672✔
286
{
287
   vcode_reg_array_add(&(op->args), arg);
3,296,672✔
288
}
3,296,672✔
289

290
static void vcode_add_target(op_t *op, vcode_block_t block)
114,133✔
291
{
292
   vcode_block_array_add(&(op->targets), block);
114,133✔
293
}
114,133✔
294

295
static op_t *vcode_op_data(int op)
10,010,221✔
296
{
297
   assert(active_unit != NULL);
10,010,221✔
298
   assert(active_block != VCODE_INVALID_BLOCK);
10,010,221✔
299

300
   block_t *b = &(active_unit->blocks.items[active_block]);
10,010,221✔
301
   return op_array_nth_ptr(&(b->ops), op);
10,010,221✔
302
}
303

304
static op_t *vcode_find_definition(vcode_reg_t reg)
1,673,114✔
305
{
306
   for (int i = active_block; i >= 0; i--) {
1,704,430✔
307
      block_t *b = &(active_unit->blocks.items[i]);
1,703,034✔
308
      for (int j = b->ops.count - 1; j >= 0; j--) {
33,216,897✔
309
         if (b->ops.items[j].result == reg)
33,185,581✔
310
            return &(b->ops.items[j]);
1,671,718✔
311
      }
312
   }
313

314
   return NULL;
315
}
316

317
#ifdef DEBUG
318
static void vcode_assert_const(vcode_reg_t reg, const char *what)
1,656,380✔
319
{
320
   op_t *defn = vcode_find_definition(reg);
1,656,380✔
321
   VCODE_ASSERT(defn != NULL, "constant %s uses parameter r%d",
1,656,380✔
322
                what, reg);
323
   VCODE_ASSERT(defn->kind == VCODE_OP_CONST
1,656,380✔
324
                || defn->kind == VCODE_OP_CONST_REAL
325
                || defn->kind == VCODE_OP_CONST_RECORD
326
                || defn->kind == VCODE_OP_CONST_ARRAY
327
                || defn->kind == VCODE_OP_CONST_REP
328
                || defn->kind == VCODE_OP_NULL
329
                || defn->kind == VCODE_OP_UNDEFINED,
330
                "constant %s argument r%d is not constant", what, reg);
331
}
1,656,380✔
332
#endif
333

334
static reg_t *vcode_reg_data(vcode_reg_t reg)
8,208,731✔
335
{
336
   assert(active_unit != NULL);
8,208,731✔
337
   assert(reg != VCODE_INVALID_REG);
8,208,731✔
338
   return reg_array_nth_ptr(&(active_unit->regs), reg);
8,208,731✔
339
}
340

341
static vtype_t *vcode_type_data(vcode_type_t type)
8,042,337✔
342
{
343
   assert(type != VCODE_INVALID_TYPE);
8,042,337✔
344
   assert(active_unit != NULL);
8,042,337✔
345
   vcode_unit_t unit = active_unit;
8,042,337✔
346

347
   int depth = MASK_CONTEXT(type);
8,042,337✔
348
   assert(depth <= unit->depth);
8,042,337✔
349
   while (depth != unit->depth)
8,990,219✔
350
      unit = unit->context;
947,882✔
351

352
   return vtype_array_nth_ptr(&(unit->types), MASK_INDEX(type));
8,042,337✔
353
}
354

355
static var_t *vcode_var_data(vcode_var_t var)
374,537✔
356
{
357
   assert(active_unit != NULL);
374,537✔
358
   assert(var != VCODE_INVALID_VAR);
374,537✔
359

360
   return var_array_nth_ptr(&(active_unit->vars), var);
374,537✔
361
}
362

363
void vcode_heap_allocate(vcode_reg_t reg)
11,353✔
364
{
365
   op_t *defn = vcode_find_definition(reg);
16,734✔
366
   if (defn == NULL) {
16,734✔
367
      // It is always safe to return a pointer to an argument
368
      return;
369
   }
370

371
   switch (defn->kind) {
15,338✔
372
   case VCODE_OP_CONST:
373
   case VCODE_OP_CONST_REAL:
374
   case VCODE_OP_CONST_ARRAY:
375
   case VCODE_OP_CONST_REP:
376
   case VCODE_OP_NULL:
377
   case VCODE_OP_UNDEFINED:
378
   case VCODE_OP_ADDRESS_OF:
379
   case VCODE_OP_LINK_VAR:
380
   case VCODE_OP_LINK_PACKAGE:
381
   case VCODE_OP_CONTEXT_UPREF:
382
   case VCODE_OP_PACKAGE_INIT:
383
   case VCODE_OP_BIND_EXTERNAL:
384
      break;
385

386
   case VCODE_OP_ALLOC:
387
   case VCODE_OP_REFLECT_SUBTYPE:
388
   case VCODE_OP_REFLECT_VALUE:
389
      // Always allocated in mspace
390
      break;
391

392
   case VCODE_OP_INDEX:
1,221✔
393
      vcode_var_data(defn->address)->flags |= VAR_HEAP;
1,221✔
394
      break;
1,221✔
395

396
   case VCODE_OP_VAR_UPREF:
640✔
397
      {
398
         vcode_unit_t vu = vcode_active_unit();
640✔
399
         for (int i = 0; i < defn->hops; i++)
1,286✔
400
            vu = vcode_unit_context(vu);
646✔
401

402
         vcode_state_t state;
640✔
403
         vcode_state_save(&state);
640✔
404

405
         vcode_select_unit(vu);
640✔
406

407
         vcode_var_data(defn->address)->flags |= VAR_HEAP;
640✔
408

409
         vcode_state_restore(&state);
640✔
410
      }
411
      break;
640✔
412

413
   case VCODE_OP_ARRAY_REF:
478✔
414
      vcode_heap_allocate(defn->args.items[0]);
478✔
415
      break;
478✔
416

417
   case VCODE_OP_WRAP:
4,559✔
418
   case VCODE_OP_UNWRAP:
419
   case VCODE_OP_RESOLVED:
420
      vcode_heap_allocate(defn->args.items[0]);
4,559✔
421
      break;
4,559✔
422

423
   case VCODE_OP_LAST_VALUE:
424
      // Returns a pointer into the C heap
425
      break;
426

427
   case VCODE_OP_LOAD:
1,177✔
428
      {
429
         if (vcode_reg_kind(reg) != VCODE_TYPE_UARRAY)
1,177✔
430
            return;
431

432
         // Any store to this variable must be heap allocated
433
         for (int i = 0; i < active_unit->blocks.count; i++) {
18,398✔
434
            block_t *b = &(active_unit->blocks.items[i]);
17,268✔
435
            for (int j = 0; j < b->ops.count; j++) {
237,454✔
436
               op_t *op = &(b->ops.items[j]);
220,186✔
437
               if (op->kind == VCODE_OP_STORE && op->address == defn->address)
220,186✔
438
                  vcode_heap_allocate(op->args.items[0]);
1,130✔
439

440
               VCODE_ASSERT(
220,186✔
441
                  op->kind != VCODE_OP_INDEX || op->address != defn->address,
442
                  "cannot heap allocate aliased pointer r%d", reg);
443
            }
444
         }
445
      }
446
      break;
447

448
   case VCODE_OP_FCALL:
449
      for (int i = 0; i < defn->args.count; i++) {
6,271✔
450
         const vtype_kind_t rkind = vcode_reg_kind(reg);
4,574✔
451
         if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
4,574✔
452
            // Function may return a pointer to its argument
453
            vcode_heap_allocate(defn->args.items[i]);
4,473✔
454
         }
455
      }
456
      break;
457

458
   case VCODE_OP_RECORD_REF:
24✔
459
      vcode_heap_allocate(defn->args.items[0]);
24✔
460
      break;
24✔
461

462
   case VCODE_OP_SELECT:
40✔
463
      vcode_heap_allocate(defn->args.items[1]);
40✔
464
      vcode_heap_allocate(defn->args.items[2]);
40✔
465
      break;
40✔
466

467
   case VCODE_OP_LOAD_INDIRECT:
298✔
468
      {
469
         // Always OK if scalar otherwise check the pointer source
470
         const vtype_kind_t vtkind = vcode_reg_kind(reg);
298✔
471
         if (vtkind != VCODE_TYPE_INT && vtkind != VCODE_TYPE_REAL)
298✔
472
            vcode_heap_allocate(defn->args.items[0]);
280✔
473
      }
474
      break;
475

476
   case VCODE_OP_ALL:
477
      // Must have been allocated on the heap
478
      break;
479

480
   case VCODE_OP_NEW:
481
      // On the heap by definition
482
      break;
483

484
   case VCODE_OP_SUB:
485
   case VCODE_OP_MUL:
486
   case VCODE_OP_DIV:
487
   case VCODE_OP_CAST:
488
   case VCODE_OP_CMP:
489
   case VCODE_OP_OR:
490
   case VCODE_OP_NOT:
491
   case VCODE_OP_AND:
492
   case VCODE_OP_NOR:
493
   case VCODE_OP_NAND:
494
   case VCODE_OP_XOR:
495
   case VCODE_OP_XNOR:
496
   case VCODE_OP_EVENT:
497
   case VCODE_OP_ACTIVE:
498
   case VCODE_OP_UARRAY_LEN:
499
   case VCODE_OP_UARRAY_LEFT:
500
   case VCODE_OP_UARRAY_RIGHT:
501
   case VCODE_OP_UARRAY_DIR:
502
   case VCODE_OP_LAST_EVENT:
503
   case VCODE_OP_NEG:
504
   case VCODE_OP_EXP:
505
   case VCODE_OP_ABS:
506
   case VCODE_OP_MOD:
507
   case VCODE_OP_REM:
508
   case VCODE_OP_ADD:
509
   case VCODE_OP_TRAP_ADD:
510
   case VCODE_OP_TRAP_SUB:
511
   case VCODE_OP_TRAP_MUL:
512
   case VCODE_OP_TRAP_NEG:
513
   case VCODE_OP_TRAP_EXP:
514
      // Result cannot reference pointer
515
      break;
516

517
   default:
518
      VCODE_ASSERT(false, "cannot heap allocate r%d", reg);
×
519
   }
520
}
521

522
void vcode_state_save(vcode_state_t *state)
37,991✔
523
{
524
   state->unit  = active_unit;
37,991✔
525
   state->block = active_block;
37,991✔
526
}
37,991✔
527

528
void vcode_state_restore(const vcode_state_t *state)
37,991✔
529
{
530
   active_unit  = state->unit;
37,991✔
531
   active_block = state->block;
37,991✔
532
}
37,991✔
533

534
void vcode_unit_unref(vcode_unit_t unit)
50,790✔
535
{
536
   assert(unit != NULL);
50,790✔
537

538
   if (unit == active_unit)
50,790✔
539
      vcode_close();
11,166✔
540

541
   for (vcode_unit_t it = unit->children; it != NULL; it = it->next) {
64,908✔
542
      assert(it->context == unit);
14,118✔
543
      it->context = NULL;
14,118✔
544
   }
545
   unit->children = NULL;
50,790✔
546

547
   if (unit->context != NULL) {
50,790✔
548
      vcode_unit_t *it = &(unit->context->children);
13,524✔
549
      for (; *it != NULL && *it != unit; it = &((*it)->next))
36,991✔
550
         ;
551
      assert(*it != NULL);
13,524✔
552
      *it = (*it)->next;
13,524✔
553
   }
554

555
   for (unsigned i = 0; i < unit->blocks.count; i++) {
188,417✔
556
      block_t *b = &(unit->blocks.items[i]);
137,627✔
557

558
      for (unsigned j = 0; j < b->ops.count; j++) {
1,917,998✔
559
         op_t *o = &(b->ops.items[j]);
1,780,371✔
560
         if (OP_HAS_COMMENT(o->kind))
1,780,371✔
561
            free(o->comment);
197,260✔
562
         if (OP_HAS_TARGET(o->kind))
1,780,371✔
563
            free(o->targets.items);
81,090✔
564
         free(o->args.items);
1,780,371✔
565
      }
566
      free(b->ops.items);
137,627✔
567
   }
568
   free(unit->blocks.items);
50,790✔
569

570
   for (unsigned i = 0; i < unit->types.count; i++) {
707,642✔
571
      vtype_t *vt = &(unit->types.items[i]);
656,852✔
572
      if (vt->kind == VCODE_TYPE_RECORD)
656,852✔
573
         free(vt->fields.items);
5,796✔
574
   }
575
   free(unit->types.items);
50,790✔
576

577
   free(unit->regs.items);
50,790✔
578
   free(unit->vars.items);
50,790✔
579
   free(unit->params.items);
50,790✔
580
   free(unit);
50,790✔
581
}
50,790✔
582

583
vcode_unit_t vcode_unit_next(vcode_unit_t unit)
16,252✔
584
{
585
   return unit->next;
16,252✔
586
}
587

588
vcode_unit_t vcode_unit_child(vcode_unit_t unit)
15,360✔
589
{
590
   return unit->children;
15,360✔
591
}
592

593
int vcode_count_regs(void)
50,752✔
594
{
595
   assert(active_unit != NULL);
50,752✔
596
   return active_unit->regs.count;
50,752✔
597
}
598

599
vcode_type_t vcode_reg_type(vcode_reg_t reg)
5,520,824✔
600
{
601
   return vcode_reg_data(reg)->type;
5,520,824✔
602
}
603

604
vtype_kind_t vcode_reg_kind(vcode_reg_t reg)
1,392,460✔
605
{
606
   return vtype_kind(vcode_reg_type(reg));
1,392,460✔
607
}
608

609
vcode_type_t vcode_reg_bounds(vcode_reg_t reg)
453,105✔
610
{
611
   return vcode_reg_data(reg)->bounds;
453,105✔
612
}
613

614
bool vcode_reg_const(vcode_reg_t reg, int64_t *value)
871,048✔
615
{
616
   reg_t *r = vcode_reg_data(reg);
871,048✔
617

618
   vtype_kind_t kind = vtype_kind(r->type);
871,048✔
619
   if (kind != VCODE_TYPE_INT && kind != VCODE_TYPE_OFFSET)
871,048✔
620
      return false;
621

622
   vtype_t *bounds = vcode_type_data(r->bounds);
840,942✔
623

624
   VCODE_ASSERT(
840,942✔
625
      bounds->kind == VCODE_TYPE_INT || bounds->kind == VCODE_TYPE_OFFSET,
626
      "integer register r%d has non-integer bounds", reg);
627

628
   if (bounds->low == bounds->high) {
840,942✔
629
      if (value) *value = bounds->low;
472,949✔
630
      return true;
472,949✔
631
   }
632
   else
633
      return false;
634
}
635

636
void vcode_opt(void)
50,816✔
637
{
638
   // Prune assignments to unused registers
639

640
   int *uses LOCAL = xmalloc_array(active_unit->regs.count, sizeof(int));
101,632✔
641

642
   int pruned = 0;
50,816✔
643
   do {
73,148✔
644
      memset(uses, '\0', active_unit->regs.count * sizeof(int));
73,148✔
645
      pruned = 0;
73,148✔
646

647
      for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
301,546✔
648
         block_t *b = &(active_unit->blocks.items[i]);
228,398✔
649

650
         for (int j = b->ops.count - 1; j >= 0; j--) {
3,538,595✔
651
            op_t *o = &(b->ops.items[j]);
3,310,197✔
652

653
            switch (o->kind) {
3,310,197✔
654
            case VCODE_OP_FCALL:
54,858✔
655
               if (o->result == VCODE_INVALID_REG)
54,858✔
656
                  break;
657
            case VCODE_OP_CONST:
658
            case VCODE_OP_CONST_REAL:
659
            case VCODE_OP_CONST_ARRAY:
660
            case VCODE_OP_CONST_RECORD:
661
            case VCODE_OP_CONST_REP:
662
            case VCODE_OP_LOAD:
663
            case VCODE_OP_LOAD_INDIRECT:
664
            case VCODE_OP_VAR_UPREF:
665
            case VCODE_OP_ADD:
666
            case VCODE_OP_ARRAY_REF:
667
            case VCODE_OP_SUB:
668
            case VCODE_OP_MUL:
669
            case VCODE_OP_CMP:
670
            case VCODE_OP_INDEX:
671
            case VCODE_OP_WRAP:
672
            case VCODE_OP_EXP:
673
            case VCODE_OP_UNDEFINED:
674
            case VCODE_OP_UARRAY_LEN:
675
            case VCODE_OP_UARRAY_DIR:
676
            case VCODE_OP_UARRAY_LEFT:
677
            case VCODE_OP_UARRAY_RIGHT:
678
            case VCODE_OP_UNWRAP:
679
            case VCODE_OP_NULL:
680
            case VCODE_OP_ADDRESS_OF:
681
            case VCODE_OP_RANGE_NULL:
682
            case VCODE_OP_RANGE_LENGTH:
683
            case VCODE_OP_DEBUG_LOCUS:
684
            case VCODE_OP_SELECT:
685
            case VCODE_OP_CAST:
686
            case VCODE_OP_RESOLVED:
687
            case VCODE_OP_TRAP_ADD:
688
            case VCODE_OP_TRAP_SUB:
689
            case VCODE_OP_TRAP_MUL:
690
            case VCODE_OP_TRAP_EXP:
691
            case VCODE_OP_ALLOC:
692
            case VCODE_OP_FUNCTION_TRIGGER:
693
            case VCODE_OP_CMP_TRIGGER:
694
            case VCODE_OP_OR_TRIGGER:
695
               if (uses[o->result] == -1) {
2,110,052✔
696
                  vcode_dump_with_mark(j, NULL, NULL);
×
697
                  fatal_trace("definition of r%d does not dominate all uses",
698
                              o->result);
699
               }
700
               else if (uses[o->result] == 0) {
2,110,052✔
701
                  if (false DEBUG_ONLY(|| o->kind != VCODE_OP_CONST)) {
200,298✔
702
                     o->comment = xasprintf("Dead %s definition of r%d",
119,228✔
703
                                            vcode_op_string(o->kind),
704
                                            o->result);
705
                     o->kind = VCODE_OP_COMMENT;
119,228✔
706
                  }
707
                  else
708
                     o->kind = (vcode_op_t)-1;
81,070✔
709
                  vcode_reg_array_resize(&(o->args), 0, VCODE_INVALID_REG);
200,298✔
710
                  pruned++;
200,298✔
711
               }
712
               uses[o->result] = -1;
2,110,052✔
713
               break;
2,110,052✔
714

715
            default:
716
               break;
717
            }
718

719
            for (int k = 0; k < o->args.count; k++) {
9,347,502✔
720
               if (o->args.items[k] != VCODE_INVALID_REG)
6,037,305✔
721
                  uses[o->args.items[k]]++;
6,001,699✔
722
            }
723
         }
724
      }
725
   } while (pruned > 0);
73,148✔
726

727
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
188,541✔
728
      block_t *b = &(active_unit->blocks.items[i]);
137,725✔
729
      op_t *dst = &(b->ops.items[0]);
137,725✔
730
      size_t copied = 0;
137,725✔
731
      for (int j = 0; j < b->ops.count; j++) {
2,000,056✔
732
         const op_t *src = &(b->ops.items[j]);
1,862,331✔
733
         if (src->kind != (vcode_op_t)-1) {
1,862,331✔
734
            if (src != dst) {
1,781,261✔
735
               assert(dst < src);
585,387✔
736
               *dst = *src;
585,387✔
737
            }
738
            dst++;
1,781,261✔
739
            copied++;
1,781,261✔
740
         }
741
      }
742

743
      assert(copied <= b->ops.count);
137,725✔
744
      b->ops.count = copied;
137,725✔
745
   }
746
}
50,816✔
747

748
void vcode_close(void)
30,789✔
749
{
750
   active_unit  = NULL;
30,789✔
751
   active_block = -1;
30,789✔
752
}
30,789✔
753

754
int vcode_count_blocks(void)
66,384✔
755
{
756
   assert(active_unit != NULL);
66,384✔
757
   return active_unit->blocks.count;
66,384✔
758
}
759

760
int vcode_count_ops(void)
177,585✔
761
{
762
   assert(active_unit != NULL);
177,585✔
763
   assert(active_block != VCODE_INVALID_BLOCK);
177,585✔
764
   return active_unit->blocks.items[active_block].ops.count;
177,585✔
765
}
766

767
int vcode_count_vars(void)
50,764✔
768
{
769
   assert(active_unit != NULL);
50,764✔
770
   return active_unit->vars.count;
50,764✔
771
}
772

773
vcode_var_t vcode_find_var(ident_t name)
15✔
774
{
775
   assert(active_unit != NULL);
15✔
776
   for (int i = 0; i < active_unit->vars.count; i++) {
27✔
777
      if (active_unit->vars.items[i].name == name)
12✔
778
         return i;
×
779
   }
780

781
   return VCODE_INVALID_VAR;
782
}
783

784
ident_t vcode_var_name(vcode_var_t var)
75,092✔
785
{
786
   return vcode_var_data(var)->name;
75,092✔
787
}
788

789
vcode_type_t vcode_var_type(vcode_var_t var)
75,825✔
790
{
791
   return vcode_var_data(var)->type;
75,825✔
792
}
793

794
vcode_type_t vcode_var_bounds(vcode_var_t var)
3,778✔
795
{
796
   return vcode_var_data(var)->bounds;
3,778✔
797
}
798

799
vcode_var_flags_t vcode_var_flags(vcode_var_t var)
77,194✔
800
{
801
   return vcode_var_data(var)->flags;
77,194✔
802
}
803

804
vcode_op_t vcode_get_op(int op)
2,397,748✔
805
{
806
   return vcode_op_data(op)->kind;
2,397,748✔
807
}
808

809
ident_t vcode_get_func(int op)
87,402✔
810
{
811
   op_t *o = vcode_op_data(op);
87,402✔
812
   assert(OP_HAS_FUNC(o->kind));
87,402✔
813
   return o->func;
87,402✔
814
}
815

816
ident_t vcode_get_ident(int op)
13,972✔
817
{
818
   op_t *o = vcode_op_data(op);
13,972✔
819
   assert(OP_HAS_IDENT(o->kind));
13,972✔
820
   return o->ident;
13,972✔
821
}
822

823
object_t *vcode_get_object(int op)
77,089✔
824
{
825
   op_t *o = vcode_op_data(op);
77,089✔
826
   assert(OP_HAS_IDENT(o->kind));
77,089✔
827
   return o->object;
77,089✔
828
}
829

830
int64_t vcode_get_value(int op)
368,699✔
831
{
832
   op_t *o = vcode_op_data(op);
368,699✔
833
   assert(OP_HAS_VALUE(o->kind));
368,699✔
834
   return o->value;
368,699✔
835
}
836

837
double vcode_get_real(int op)
22,238✔
838
{
839
   op_t *o = vcode_op_data(op);
22,238✔
840
   assert(OP_HAS_REAL(o->kind));
22,238✔
841
   return o->real;
22,238✔
842
}
843

844
vcode_var_t vcode_get_address(int op)
182,746✔
845
{
846
   op_t *o = vcode_op_data(op);
182,746✔
847
   assert(OP_HAS_ADDRESS(o->kind));
182,746✔
848
   return o->address;
182,746✔
849
}
850

851
unsigned vcode_get_dim(int op)
64,041✔
852
{
853
   op_t *o = vcode_op_data(op);
64,041✔
854
   assert(OP_HAS_DIM(o->kind));
64,041✔
855
   return o->dim;
64,041✔
856
}
857

858
int vcode_get_hops(int op)
54,378✔
859
{
860
   op_t *o = vcode_op_data(op);
54,378✔
861
   assert(OP_HAS_HOPS(o->kind));
54,378✔
862
   return o->hops;
54,378✔
863
}
864

865
int vcode_get_field(int op)
33,156✔
866
{
867
   op_t *o = vcode_op_data(op);
33,156✔
868
   assert(OP_HAS_FIELD(o->kind));
33,156✔
869
   return o->field;
33,156✔
870
}
871

872
vcode_var_t vcode_get_type(int op)
63,172✔
873
{
874
   op_t *o = vcode_op_data(op);
63,172✔
875
   assert(OP_HAS_TYPE(o->kind));
63,172✔
876
   return o->type;
63,172✔
877
}
878

879
int vcode_count_args(int op)
244,981✔
880
{
881
   return vcode_op_data(op)->args.count;
244,981✔
882
}
883

884
vcode_reg_t vcode_get_arg(int op, int arg)
3,246,340✔
885
{
886
   op_t *o = vcode_op_data(op);
3,246,340✔
887
   return vcode_reg_array_nth(&(o->args), arg);
3,246,340✔
888
}
889

890
vcode_reg_t vcode_get_result(int op)
1,222,020✔
891
{
892
   op_t *o = vcode_op_data(op);
1,222,020✔
893
   return o->result;
1,222,020✔
894
}
895

896
vcode_cmp_t vcode_get_cmp(int op)
33,734✔
897
{
898
   op_t *o = vcode_op_data(op);
33,734✔
899
   assert(OP_HAS_CMP(o->kind));
33,734✔
900
   return o->cmp;
33,734✔
901
}
902

903
uint32_t vcode_get_tag(int op)
3,029✔
904
{
905
   op_t *o = vcode_op_data(op);
3,029✔
906
   assert(OP_HAS_TAG(o->kind));
3,029✔
907
   return o->tag;
3,029✔
908
}
909

910
const loc_t *vcode_get_loc(int op)
1,780,303✔
911
{
912
   op_t *o = vcode_op_data(op);
1,780,303✔
913
   return &(o->loc);
1,780,303✔
914
}
915

916
vcode_block_t vcode_get_target(int op, int nth)
115,173✔
917
{
918
   op_t *o = vcode_op_data(op);
115,173✔
919
   assert(OP_HAS_TARGET(o->kind));
115,173✔
920
   return vcode_block_array_nth(&(o->targets), nth);
115,173✔
921
}
922

923
bool vcode_block_empty(void)
×
924
{
925
   assert(active_unit != NULL);
×
926
   assert(active_block != VCODE_INVALID_BLOCK);
×
927

928
   return active_unit->blocks.items[active_block].ops.count == 0;
×
929
}
930

931
bool vcode_block_finished(void)
1,978,585✔
932
{
933
   assert(active_unit != NULL);
1,978,585✔
934
   assert(active_block != VCODE_INVALID_BLOCK);
1,978,585✔
935

936
   const block_t *b = &(active_unit->blocks.items[active_block]);
1,978,585✔
937
   if (b->ops.count == 0)
1,978,585✔
938
      return false;
939
   else {
940
      vcode_op_t kind = b->ops.items[b->ops.count - 1].kind;
1,792,545✔
941
      return kind == VCODE_OP_WAIT || kind == VCODE_OP_JUMP
1,792,545✔
942
         || kind == VCODE_OP_COND || kind == VCODE_OP_PCALL
1,792,527✔
943
         || kind == VCODE_OP_RETURN || kind == VCODE_OP_CASE
944
         || kind == VCODE_OP_UNREACHABLE;
3,585,072✔
945
   }
946
}
947

948
const char *vcode_op_string(vcode_op_t op)
119,228✔
949
{
950
   static const char *strs[] = {
119,228✔
951
      "cmp", "fcall", "wait", "const", "assert", "jump", "load", "store",
952
      "mul", "add", "comment", "const array", "index", "sub", "cast",
953
      "load indirect", "store indirect", "return", "sched waveform",
954
      "cond", "report", "div", "neg", "exp", "abs", "mod", "rem", "alloc",
955
      "select", "or", "wrap", "uarray left", "uarray right", "uarray dir",
956
      "unwrap", "not", "and", "event", "active", "const record", "record ref",
957
      "copy", "sched event", "pcall", "resume", "xor", "xnor", "nand", "nor",
958
      "memset", "case", "file open", "file write",
959
      "file read", "null", "new", "null check", "deallocate", "all",
960
      "const real", "last event", "debug out", "cover stmt", "cover branch",
961
      "cover toggle", "cover expr", "cover state", "uarray len", "undefined",
962
      "range null", "var upref", "resolved", "last value", "init signal",
963
      "map signal", "drive signal", "link var", "resolution wrapper",
964
      "last active", "driving", "driving value", "address of", "closure",
965
      "protected init", "context upref", "const rep", "protected free",
966
      "implicit signal", "disconnect", "link package",
967
      "index check", "debug locus", "length check", "range check", "array ref",
968
      "range length", "exponent check", "zero check", "map const",
969
      "resolve signal", "package scope", "pop scope", "alias signal",
970
      "trap add", "trap sub", "trap mul", "force", "release",
971
      "unreachable", "package init", "trap neg", "process init", "clear event",
972
      "trap exp", "enter state", "reflect value", "reflect subtype",
973
      "function trigger", "add trigger", "transfer signal",
974
      "port conversion", "convert in", "convert out", "bind foreign",
975
      "or trigger", "cmp trigger", "instance name",
976
      "map implicit", "bind external", "array scope", "record scope", "syscall",
977
      "put conversion", "dir check", "sched process", "table ref",
978
   };
979
   if ((unsigned)op >= ARRAY_LEN(strs))
119,228✔
980
      return "???";
981
   else
982
      return strs[op];
119,228✔
983
}
984

985
LCOV_EXCL_START
986
static int vcode_dump_reg(vcode_reg_t reg)
987
{
988
   if (reg == VCODE_INVALID_REG)
989
      return nvc_printf("$red$invalid$$");
990
   else
991
      return nvc_printf("$green$r%d$$", reg);
992
}
993

994
static int vcode_pretty_print_int(int64_t n)
995
{
996
   if (n == INT64_MAX)
997
      return printf("2^63-1");
998
   else if (n == INT64_MIN)
999
      return printf("-2^63");
1000
   else if (n == INT32_MAX)
1001
      return printf("2^31-1");
1002
   else if (n == INT32_MIN)
1003
      return printf("-2^31");
1004
   else
1005
      return printf("%"PRIi64, n);
1006
}
1007

1008
static int vcode_dump_one_type(vcode_type_t type)
1009
{
1010
   int col = 0;
1011
   vtype_t *vt = vcode_type_data(type);
1012
   switch (vt->kind) {
1013
   case VCODE_TYPE_INT:
1014
      if (vt->low != vt->high) {
1015
         col += vcode_pretty_print_int(vt->low);
1016
         col += printf("..");
1017
         col += vcode_pretty_print_int(vt->high);
1018
      }
1019
      else
1020
         col += vcode_pretty_print_int(vt->low);
1021
      break;
1022

1023
   case VCODE_TYPE_REAL:
1024
      if (vt->rlow == -DBL_MAX && vt->rhigh == DBL_MAX)
1025
         col += printf("%%");
1026
      else if (vt->rlow == vt->rhigh)
1027
         col += printf("%f", vt->rlow);
1028
      else
1029
         col += printf("%f..%f", vt->rlow, vt->rhigh);
1030
      break;
1031

1032
   case VCODE_TYPE_CARRAY:
1033
      {
1034
         col += printf("[%u] : ", vt->size);
1035
         col += vcode_dump_one_type(vt->elem);
1036
         if (!vtype_eq(vt->elem, vt->bounds)) {
1037
            col += printf(" => ");
1038
            col += vcode_dump_one_type(vt->bounds);
1039
         }
1040
      }
1041
      break;
1042

1043
   case VCODE_TYPE_UARRAY:
1044
      {
1045
         col += printf("[");
1046
         for (unsigned i = 0; i < vt->dims; i++)
1047
            col += printf("%s*", i > 0 ? ", " : "");
1048
         col += printf("] : ");
1049
         col += vcode_dump_one_type(vt->elem);
1050
         if (!vtype_eq(vt->elem, vt->bounds)) {
1051
            col += printf(" => ");
1052
            col += vcode_dump_one_type(vt->bounds);
1053
         }
1054
      }
1055
      break;
1056

1057
   case VCODE_TYPE_POINTER:
1058
      col += printf("@<");
1059
      col += vcode_dump_one_type(vt->pointed);
1060
      col += printf(">");
1061
      break;
1062

1063
   case VCODE_TYPE_ACCESS:
1064
      col += printf("A<");
1065
      col += vcode_dump_one_type(vt->pointed);
1066
      col += printf(">");
1067
      break;
1068

1069
   case VCODE_TYPE_SIGNAL:
1070
      col += printf("$<");
1071
      col += vcode_dump_one_type(vt->base);
1072
      col += printf(">");
1073
      break;
1074

1075
   case VCODE_TYPE_OFFSET:
1076
      col += printf("#");
1077
      break;
1078

1079
   case VCODE_TYPE_RECORD:
1080
      col += printf("%s{}", istr(vt->name));
1081
      break;
1082

1083
   case VCODE_TYPE_FILE:
1084
      col += printf("F<");
1085
      col += vcode_dump_one_type(vt->base);
1086
      col += printf(">");
1087
      break;
1088

1089
   case VCODE_TYPE_OPAQUE:
1090
      col += printf("?");
1091
      break;
1092

1093
   case VCODE_TYPE_RESOLUTION:
1094
      col += printf("R<");
1095
      col += vcode_dump_one_type(vt->base);
1096
      col += printf(">");
1097
      break;
1098

1099
   case VCODE_TYPE_CLOSURE:
1100
      col += printf("C<");
1101
      col += vcode_dump_one_type(vt->base);
1102
      col += printf(">");
1103
      break;
1104

1105
   case VCODE_TYPE_CONTEXT:
1106
      col += printf("P<%s>", istr(vt->name));
1107
      break;
1108

1109
   case VCODE_TYPE_DEBUG_LOCUS:
1110
      col += printf("D<>");
1111
      break;
1112

1113
   case VCODE_TYPE_TRIGGER:
1114
      col += printf("T<>");
1115
      break;
1116

1117
   case VCODE_TYPE_CONVERSION:
1118
      col += printf("X<>");
1119
      break;
1120
   }
1121

1122
   return col;
1123
}
1124

1125
static void vcode_dump_tab(int col, int to_col)
1126
{
1127
   if (col >= to_col)
1128
      printf(" ");
1129
   else {
1130
      while (col < to_col)
1131
         col += printf(" ");
1132
   }
1133
}
1134

1135
static void vcode_dump_comment(int col)
1136
{
1137
   vcode_dump_tab(col, 40);
1138
   nvc_printf("$cyan$// ");
1139
}
1140

1141
static void vcode_dump_type(int col, vcode_type_t type, vcode_type_t bounds)
1142
{
1143
   vcode_dump_comment(col);
1144
   vcode_dump_one_type(type);
1145
   if (!vtype_eq(type, bounds)) {
1146
      printf(" => ");
1147
      vcode_dump_one_type(bounds);
1148
   }
1149
}
1150

1151
static void vcode_dump_result_type(int col, const op_t *op)
1152
{
1153
   if (op->result != VCODE_INVALID_REG) {
1154
      reg_t *r = vcode_reg_data(op->result);
1155
      vcode_dump_type(col, r->type, r->bounds);
1156
   }
1157
}
1158

1159
static int vcode_dump_var(vcode_var_t var, int hops)
1160
{
1161
   vcode_unit_t owner = active_unit;
1162
   while (owner && hops--)
1163
      owner = owner->context;
1164

1165
   if (owner == NULL || var >= owner->vars.count)
1166
      return nvc_printf("$red$invalid$$");
1167
   else {
1168
      var_t *v = var_array_nth_ptr(&(owner->vars), var);
1169
      return nvc_printf("$magenta$%s$$", istr(v->name));
1170
   }
1171
}
1172

1173
void vcode_dump_with_mark(int mark_op, vcode_dump_fn_t callback, void *arg)
1174
{
1175
   assert(active_unit != NULL);
1176

1177
   const vcode_unit_t vu = active_unit;
1178
   vcode_block_t old_block = active_block;
1179

1180
   printf("\n");
1181
   if (vu->name != NULL)
1182
      nvc_printf("Name       $cyan$%s$$\n", istr(vu->name));
1183
   nvc_printf("Kind       $cyan$");
1184
   switch (vu->kind) {
1185
   case VCODE_UNIT_PROCESS:   printf("process"); break;
1186
   case VCODE_UNIT_FUNCTION:  printf("function"); break;
1187
   case VCODE_UNIT_PROCEDURE: printf("procedure"); break;
1188
   case VCODE_UNIT_INSTANCE:  printf("instance"); break;
1189
   case VCODE_UNIT_THUNK:     printf("thunk"); break;
1190
   case VCODE_UNIT_PACKAGE:   printf("package"); break;
1191
   case VCODE_UNIT_PROTECTED: printf("protected"); break;
1192
   case VCODE_UNIT_PROPERTY:  printf("property"); break;
1193
   }
1194
   nvc_printf("$$\n");
1195
   if (vu->context != NULL)
1196
      nvc_printf("Context    $cyan$%s$$\n", istr(vu->context->name));
1197
   printf("Blocks     %d\n", vu->blocks.count);
1198
   printf("Registers  %d\n", vu->regs.count);
1199
   printf("Types      %d\n", vu->types.count);
1200

1201
   for (int i = 0; i < vu->types.count; i++) {
1202
      const vtype_t *t = &(vu->types.items[i]);
1203
      if (t->kind == VCODE_TYPE_RECORD) {
1204
         int col = 0;
1205
         col += nvc_printf("  $magenta$%s$$", istr(t->name));
1206
         vcode_dump_tab(col, 40);
1207
         nvc_printf("$cyan${");
1208
         for (unsigned i = 0; i < t->fields.count; i++) {
1209
            if (i > 0)
1210
               printf(", ");
1211
            vcode_dump_one_type(t->fields.items[i]);
1212
         }
1213
         nvc_printf("}$$\n");
1214
      }
1215
   }
1216

1217
   printf("Variables  %d\n", vu->vars.count);
1218

1219
   for (int i = 0; i < vu->vars.count; i++) {
1220
      const var_t *v = &(vu->vars.items[i]);
1221
      int col = printf("  ");
1222
      col += nvc_printf("$magenta$%s$$", istr(v->name));
1223
      vcode_dump_type(col, v->type, v->bounds);
1224
      if (v->flags & VAR_SIGNAL)
1225
         col += printf(", signal");
1226
      if (v->flags & VAR_HEAP)
1227
         col += printf(", heap");
1228
      if (v->flags & VAR_CONST)
1229
         col += printf(", constant");
1230
      if (v->flags & VAR_TEMP)
1231
         col += printf(", temp");
1232
      nvc_printf("$$\n");
1233
   }
1234

1235
   if (vu->result != VCODE_INVALID_TYPE) {
1236
      nvc_printf("Result     $cyan$");
1237
      vcode_dump_one_type(vu->result);
1238
      nvc_printf("$$\n");
1239
   }
1240

1241
   if (vu->kind == VCODE_UNIT_FUNCTION
1242
       || vu->kind == VCODE_UNIT_PROCEDURE
1243
       || vu->kind == VCODE_UNIT_PROPERTY
1244
       || (vu->kind == VCODE_UNIT_PROTECTED && vu->params.count > 0)) {
1245

1246
      printf("Parameters %d\n", vu->params.count);
1247

1248
      for (size_t i = 0; i < vu->params.count; i++) {
1249
         const param_t *p = &(vu->params.items[i]);
1250
         int col = printf("  ");
1251
         col += vcode_dump_reg(p->reg);
1252
         while (col < 8)
1253
            col += printf(" ");
1254
         col += nvc_printf("$magenta$%s$$", istr(p->name));
1255
         vcode_dump_type(col, p->type, p->bounds);
1256
         nvc_printf("$$\n");
1257
      }
1258
   }
1259

1260
   printf("Begin\n");
1261
   for (int i = 0; i < vu->blocks.count; i++) {
1262
      active_block = i;
1263
      const block_t *b = &(vu->blocks.items[i]);
1264
      for (int j = 0; j < b->ops.count; j++) {
1265
         int col = 0;
1266
         if (j == 0)
1267
            col += nvc_printf("  $yellow$%2d:$$ ", i);
1268
         else
1269
            col += printf("      ");
1270

1271
         const op_t *op = &(b->ops.items[j]);
1272
         switch (op->kind) {
1273
         case VCODE_OP_CMP:
1274
            {
1275
               vcode_dump_reg(op->result);
1276
               printf(" := %s ", vcode_op_string(op->kind));
1277
               vcode_dump_reg(op->args.items[0]);
1278
               switch (op->cmp) {
1279
               case VCODE_CMP_EQ:  printf(" == "); break;
1280
               case VCODE_CMP_NEQ: printf(" != "); break;
1281
               case VCODE_CMP_LT:  printf(" < "); break;
1282
               case VCODE_CMP_GT:  printf(" > "); break;
1283
               case VCODE_CMP_LEQ: printf(" <= "); break;
1284
               case VCODE_CMP_GEQ: printf(" >= "); break;
1285
               }
1286
               vcode_dump_reg(op->args.items[1]);
1287
            }
1288
            break;
1289

1290
         case VCODE_OP_CONST:
1291
            {
1292
               col += vcode_dump_reg(op->result);
1293
               col += printf(" := %s %"PRIi64"",
1294
                             vcode_op_string(op->kind),
1295
                             op->value);
1296
               vcode_dump_result_type(col, op);
1297
            }
1298
            break;
1299

1300
         case VCODE_OP_CONST_REAL:
1301
            {
1302
               col += vcode_dump_reg(op->result);
1303
               col += printf(" := %s %g",
1304
                             vcode_op_string(op->kind),
1305
                             op->real);
1306
               vcode_dump_result_type(col, op);
1307
            }
1308
            break;
1309

1310
         case VCODE_OP_ALLOC:
1311
            {
1312
               col += vcode_dump_reg(op->result);
1313
               col += printf(" := %s ", vcode_op_string(op->kind));
1314
               col += vcode_dump_reg(op->args.items[0]);
1315
               vcode_dump_result_type(col, op);
1316
            }
1317
            break;
1318

1319
         case VCODE_OP_FCALL:
1320
            {
1321
               if (op->result != VCODE_INVALID_REG) {
1322
                  col += vcode_dump_reg(op->result);
1323
                  col += printf(" := ");
1324
               }
1325
               col += nvc_printf("%s $magenta$%s$$ ",
1326
                                 vcode_op_string(op->kind),
1327
                                 istr(op->func));
1328
               for (int i = 0; i < op->args.count; i++) {
1329
                  if (i > 0)
1330
                     col += printf(", ");
1331
                  col += vcode_dump_reg(op->args.items[i]);
1332
               }
1333
               vcode_dump_result_type(col, op);
1334
            }
1335
            break;
1336

1337
         case VCODE_OP_SYSCALL:
1338
            {
1339
               if (op->result != VCODE_INVALID_REG) {
1340
                  col += vcode_dump_reg(op->result);
1341
                  col += printf(" := ");
1342
               }
1343
               col += nvc_printf("%s $magenta$%s$$ ",
1344
                                   vcode_op_string(op->kind),
1345
                                   istr(op->func));
1346
               for (int i = 1; i < op->args.count; i++) {
1347
                  if (i > 1) col += printf(", ");
1348
                  col += vcode_dump_reg(op->args.items[i]);
1349
               }
1350
               if (op->args.count > 1) col += printf(" ");
1351
               col += nvc_printf("locus ");
1352
               col += vcode_dump_reg(op->args.items[0]);
1353
               vcode_dump_result_type(col, op);
1354
            }
1355
            break;
1356

1357
         case VCODE_OP_MAP_CONST:
1358
         case VCODE_OP_MAP_SIGNAL:
1359
         case VCODE_OP_MAP_IMPLICIT:
1360
            {
1361
               printf("%s ", vcode_op_string(op->kind));
1362
               vcode_dump_reg(op->args.items[0]);
1363
               printf(" to ");
1364
               vcode_dump_reg(op->args.items[1]);
1365
               printf(" count ");
1366
               vcode_dump_reg(op->args.items[2]);
1367
            }
1368
            break;
1369

1370
         case VCODE_OP_DRIVE_SIGNAL:
1371
            {
1372
               printf("%s ", vcode_op_string(op->kind));
1373
               vcode_dump_reg(op->args.items[0]);
1374
               printf(" count ");
1375
               vcode_dump_reg(op->args.items[1]);
1376
            }
1377
            break;
1378

1379
         case VCODE_OP_TRANSFER_SIGNAL:
1380
            {
1381
               printf("%s ", vcode_op_string(op->kind));
1382
               vcode_dump_reg(op->args.items[0]);
1383
               printf(" to ");
1384
               vcode_dump_reg(op->args.items[1]);
1385
               printf(" count ");
1386
               vcode_dump_reg(op->args.items[2]);
1387
               printf(" reject ");
1388
               vcode_dump_reg(op->args.items[3]);
1389
               printf(" after ");
1390
               vcode_dump_reg(op->args.items[4]);
1391
            }
1392
            break;
1393

1394
         case VCODE_OP_RESOLVE_SIGNAL:
1395
            {
1396
               printf("%s ", vcode_op_string(op->kind));
1397
               vcode_dump_reg(op->args.items[0]);
1398
               printf(" resolution ");
1399
               vcode_dump_reg(op->args.items[1]);
1400
            }
1401
            break;
1402

1403
         case VCODE_OP_PACKAGE_SCOPE:
1404
         case VCODE_OP_ARRAY_SCOPE:
1405
         case VCODE_OP_RECORD_SCOPE:
1406
            {
1407
               col += printf("%s locus ", vcode_op_string(op->kind));
1408
               col += vcode_dump_reg(op->args.items[0]);
1409
               vcode_dump_type(col, op->type, op->type);
1410
            }
1411
            break;
1412

1413
         case VCODE_OP_POP_SCOPE:
1414
            {
1415
               printf("%s", vcode_op_string(op->kind));
1416
            }
1417
            break;
1418

1419
         case VCODE_OP_INIT_SIGNAL:
1420
            {
1421
               col += vcode_dump_reg(op->result);
1422
               col += printf(" := ");
1423
               col += printf("%s count ", vcode_op_string(op->kind));
1424
               col += vcode_dump_reg(op->args.items[0]);
1425
               col += printf(" size ");
1426
               col += vcode_dump_reg(op->args.items[1]);
1427
               col += printf(" value ");
1428
               col += vcode_dump_reg(op->args.items[2]);
1429
               col += printf(" flags ");
1430
               col += vcode_dump_reg(op->args.items[3]);
1431
               col += printf(" locus ");
1432
               col += vcode_dump_reg(op->args.items[4]);
1433
               if (op->args.count > 5) {
1434
                  col += printf(" offset ");
1435
                  col += vcode_dump_reg(op->args.items[5]);
1436
               }
1437
               vcode_dump_result_type(col, op);
1438
            }
1439
            break;
1440

1441
         case VCODE_OP_IMPLICIT_SIGNAL:
1442
            {
1443
               col += vcode_dump_reg(op->result);
1444
               col += printf(" := %s count ", vcode_op_string(op->kind));
1445
               col += vcode_dump_reg(op->args.items[0]);
1446
               col += printf(" size ");
1447
               col += vcode_dump_reg(op->args.items[1]);
1448
               col += printf(" locus ");
1449
               col += vcode_dump_reg(op->args.items[2]);
1450
               col += printf(" kind ");
1451
               col += vcode_dump_reg(op->args.items[3]);
1452
               col += printf(" closure ");
1453
               col += vcode_dump_reg(op->args.items[4]);
1454
            }
1455
            break;
1456

1457
         case VCODE_OP_RESOLUTION_WRAPPER:
1458
            {
1459
               col += vcode_dump_reg(op->result);
1460
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
1461
               col += vcode_dump_reg(op->args.items[0]);
1462
               col += printf(" nlits ");
1463
               col += vcode_dump_reg(op->args.items[1]);
1464
               vcode_dump_result_type(col, op);
1465
            }
1466
            break;
1467

1468
         case VCODE_OP_CLOSURE:
1469
         case VCODE_OP_PROTECTED_INIT:
1470
            {
1471
               col += vcode_dump_reg(op->result);
1472
               col += nvc_printf(" := %s $magenta$%s$$ context ",
1473
                                 vcode_op_string(op->kind), istr(op->func));
1474
               col += vcode_dump_reg(op->args.items[0]);
1475
               if (op->args.count >= 3) {
1476
                  col += printf(" path " );
1477
                  col += vcode_dump_reg(op->args.items[1]);
1478
                  col += printf(" instance " );
1479
                  col += vcode_dump_reg(op->args.items[2]);
1480
               }
1481
               vcode_dump_result_type(col, op);
1482
            }
1483
            break;
1484

1485
         case VCODE_OP_PACKAGE_INIT:
1486
            {
1487
               col += vcode_dump_reg(op->result);
1488
               col += nvc_printf(" := %s $magenta$%s$$",
1489
                                   vcode_op_string(op->kind), istr(op->func));
1490
               if (op->args.count > 0) {
1491
                  col += printf(" context " );
1492
                  col += vcode_dump_reg(op->args.items[0]);
1493
               }
1494
               vcode_dump_result_type(col, op);
1495
            }
1496
            break;
1497

1498
         case VCODE_OP_PROCESS_INIT:
1499
            {
1500
               nvc_printf("%s $magenta$%s$$ locus ",
1501
                            vcode_op_string(op->kind), istr(op->func));
1502
               vcode_dump_reg(op->args.items[0]);
1503
            }
1504
            break;
1505

1506
         case VCODE_OP_PROTECTED_FREE:
1507
            {
1508
               printf("%s ", vcode_op_string(op->kind));
1509
               vcode_dump_reg(op->args.items[0]);
1510
            }
1511
            break;
1512

1513
         case VCODE_OP_WAIT:
1514
            {
1515
               nvc_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1516
                            op->targets.items[0]);
1517
            }
1518
            break;
1519

1520
         case VCODE_OP_SCHED_PROCESS:
1521
            {
1522
               nvc_printf("%s after ", vcode_op_string(op->kind));
1523
               vcode_dump_reg(op->args.items[0]);
1524
            }
1525
            break;
1526

1527
         case VCODE_OP_JUMP:
1528
            {
1529
               nvc_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1530
                            op->targets.items[0]);
1531
            }
1532
            break;
1533

1534
         case VCODE_OP_COND:
1535
            {
1536
               printf("%s ", vcode_op_string(op->kind));
1537
               vcode_dump_reg(op->args.items[0]);
1538
               nvc_printf(" then $yellow$%d$$ else $yellow$%d$$",
1539
                            op->targets.items[0], op->targets.items[1]);
1540
            }
1541
            break;
1542

1543
         case VCODE_OP_ASSERT:
1544
            {
1545
               printf("%s ", vcode_op_string(op->kind));
1546
               vcode_dump_reg(op->args.items[0]);
1547
               if (op->args.items[2] != VCODE_INVALID_REG) {
1548
                  printf(" report ");
1549
                  vcode_dump_reg(op->args.items[2]);
1550
                  printf(" length ");
1551
                  vcode_dump_reg(op->args.items[3]);
1552
               }
1553
               printf(" severity ");
1554
               vcode_dump_reg(op->args.items[1]);
1555
               printf(" locus ");
1556
               vcode_dump_reg(op->args.items[4]);
1557
               if (op->args.count > 5) {
1558
                  printf(" hint ");
1559
                  vcode_dump_reg(op->args.items[5]);
1560
                  printf(" ");
1561
                  vcode_dump_reg(op->args.items[6]);
1562
               }
1563
            }
1564
            break;
1565

1566
         case VCODE_OP_REPORT:
1567
            {
1568
               printf("%s ", vcode_op_string(op->kind));
1569
               vcode_dump_reg(op->args.items[1]);
1570
               printf(" length ");
1571
               vcode_dump_reg(op->args.items[2]);
1572
               printf(" severity ");
1573
               vcode_dump_reg(op->args.items[0]);
1574
               printf(" locus ");
1575
               vcode_dump_reg(op->args.items[3]);
1576
            }
1577
            break;
1578

1579
         case VCODE_OP_LOAD:
1580
            {
1581
               col += vcode_dump_reg(op->result);
1582
               col += printf(" := %s ", vcode_op_string(op->kind));
1583
               col += vcode_dump_var(op->address, 0);
1584
               vcode_dump_result_type(col, op);
1585
            }
1586
            break;
1587

1588
         case VCODE_OP_LOAD_INDIRECT:
1589
            {
1590
               col += vcode_dump_reg(op->result);
1591
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
1592
               col += vcode_dump_reg(op->args.items[0]);
1593
               vcode_dump_result_type(col, op);
1594
            }
1595
            break;
1596

1597
         case VCODE_OP_STORE:
1598
            {
1599
               vcode_dump_var(op->address, 0);
1600
               printf(" := %s ", vcode_op_string(op->kind));
1601
               vcode_dump_reg(op->args.items[0]);
1602
            }
1603
            break;
1604

1605
         case VCODE_OP_STORE_INDIRECT:
1606
            {
1607
               vcode_dump_reg(op->args.items[1]);
1608
               printf(" := %s ", vcode_op_string(op->kind));
1609
               vcode_dump_reg(op->args.items[0]);
1610
            }
1611
            break;
1612

1613
         case VCODE_OP_INDEX:
1614
            {
1615
               col += vcode_dump_reg(op->result);
1616
               col += printf(" := %s ", vcode_op_string(op->kind));
1617
               col += vcode_dump_var(op->address, 0);
1618
               if (op->args.count > 0) {
1619
                  col += printf(" + ");
1620
                  col += vcode_dump_reg(op->args.items[0]);
1621
               }
1622
               vcode_dump_result_type(col, op);
1623
            }
1624
            break;
1625

1626
         case VCODE_OP_MUL:
1627
         case VCODE_OP_ADD:
1628
         case VCODE_OP_SUB:
1629
         case VCODE_OP_DIV:
1630
         case VCODE_OP_EXP:
1631
         case VCODE_OP_MOD:
1632
         case VCODE_OP_REM:
1633
         case VCODE_OP_OR:
1634
         case VCODE_OP_AND:
1635
         case VCODE_OP_XOR:
1636
         case VCODE_OP_XNOR:
1637
         case VCODE_OP_NAND:
1638
         case VCODE_OP_NOR:
1639
            {
1640
               col += vcode_dump_reg(op->result);
1641
               col += printf(" := %s ", vcode_op_string(op->kind));
1642
               col += vcode_dump_reg(op->args.items[0]);
1643
               switch (op->kind) {
1644
               case VCODE_OP_MUL:  col += printf(" * "); break;
1645
               case VCODE_OP_ADD:  col += printf(" + "); break;
1646
               case VCODE_OP_SUB:  col += printf(" - "); break;
1647
               case VCODE_OP_DIV:  col += printf(" / "); break;
1648
               case VCODE_OP_EXP:  col += printf(" ** "); break;
1649
               case VCODE_OP_MOD:  col += printf(" %% "); break;
1650
               case VCODE_OP_REM:  col += printf(" %% "); break;
1651
               case VCODE_OP_OR:   col += printf(" || "); break;
1652
               case VCODE_OP_AND:  col += printf(" && "); break;
1653
               case VCODE_OP_XOR:  col += printf(" ^ "); break;
1654
               case VCODE_OP_XNOR: col += printf(" !^ "); break;
1655
               case VCODE_OP_NAND: col += printf(" !& "); break;
1656
               case VCODE_OP_NOR:  col += printf(" !| "); break;
1657
               default: break;
1658
               }
1659
               col += vcode_dump_reg(op->args.items[1]);
1660
               vcode_dump_result_type(col, op);
1661
            }
1662
            break;
1663

1664
         case VCODE_OP_TRAP_ADD:
1665
         case VCODE_OP_TRAP_SUB:
1666
         case VCODE_OP_TRAP_MUL:
1667
         case VCODE_OP_TRAP_EXP:
1668
            {
1669
               col += vcode_dump_reg(op->result);
1670
               col += printf(" := %s ", vcode_op_string(op->kind));
1671
               col += vcode_dump_reg(op->args.items[0]);
1672
               switch (op->kind) {
1673
               case VCODE_OP_TRAP_ADD: col += printf(" + "); break;
1674
               case VCODE_OP_TRAP_SUB: col += printf(" - "); break;
1675
               case VCODE_OP_TRAP_MUL: col += printf(" * "); break;
1676
               case VCODE_OP_TRAP_EXP: col += printf(" ** "); break;
1677
               default: break;
1678
               }
1679
               col += vcode_dump_reg(op->args.items[1]);
1680
               col += printf(" locus ");
1681
               col += vcode_dump_reg(op->args.items[2]);
1682
               vcode_dump_result_type(col, op);
1683
            }
1684
            break;
1685

1686
         case VCODE_OP_NOT:
1687
            {
1688
               col += vcode_dump_reg(op->result);
1689
               col += printf(" := %s ", vcode_op_string(op->kind));
1690
               col += vcode_dump_reg(op->args.items[0]);
1691
               vcode_dump_result_type(col, op);
1692
            }
1693
            break;
1694

1695
         case VCODE_OP_COMMENT:
1696
            {
1697
               nvc_printf("$cyan$// %s$$ ", op->comment);
1698
            }
1699
            break;
1700

1701
         case VCODE_OP_CONST_ARRAY:
1702
         case VCODE_OP_CONST_RECORD:
1703
            {
1704
               col += vcode_dump_reg(op->result);
1705
               col += printf(" := const %c",
1706
                             op->kind == VCODE_OP_CONST_ARRAY ? '[' : '{');
1707
               for (int k = 0; k < op->args.count; k++) {
1708
                  if (k > 0)
1709
                     col += printf(",");
1710
                  col += vcode_dump_reg(op->args.items[k]);
1711
               }
1712

1713
               putchar(op->kind == VCODE_OP_CONST_ARRAY ? ']' : '}');
1714
               vcode_dump_result_type(col + 1, op);
1715
            }
1716
            break;
1717

1718
         case VCODE_OP_CONST_REP:
1719
            {
1720
               col += vcode_dump_reg(op->result);
1721
               col += printf(" := const [");
1722
               col += vcode_dump_reg(op->args.items[0]);
1723
               col += printf("]*%"PRIi64, op->value);
1724
               vcode_dump_result_type(col, op);
1725
            }
1726
            break;
1727

1728
         case VCODE_OP_ADDRESS_OF:
1729
         case VCODE_OP_CAST:
1730
            {
1731
               col += vcode_dump_reg(op->result);
1732
               col += printf(" := %s ", vcode_op_string(op->kind));
1733
               col += vcode_dump_reg(op->args.items[0]);
1734
               vcode_dump_result_type(col, op);
1735
            }
1736
            break;
1737

1738
         case VCODE_OP_RETURN:
1739
            {
1740
               printf("%s ", vcode_op_string(op->kind));
1741
               if (op->args.count > 0)
1742
                  vcode_dump_reg(op->args.items[0]);
1743
            }
1744
            break;
1745

1746
         case VCODE_OP_SCHED_WAVEFORM:
1747
            {
1748
               printf("%s ", vcode_op_string(op->kind));
1749
               vcode_dump_reg(op->args.items[0]);
1750
               printf(" count ");
1751
               vcode_dump_reg(op->args.items[1]);
1752
               printf(" values ");
1753
               vcode_dump_reg(op->args.items[2]);
1754
               printf(" reject ");
1755
               vcode_dump_reg(op->args.items[3]);
1756
               printf(" after ");
1757
               vcode_dump_reg(op->args.items[4]);
1758
            }
1759
            break;
1760

1761
         case VCODE_OP_FORCE:
1762
         case VCODE_OP_RELEASE:
1763
            {
1764
               printf("%s ", vcode_op_string(op->kind));
1765
               vcode_dump_reg(op->args.items[0]);
1766
               printf(" count ");
1767
               vcode_dump_reg(op->args.items[1]);
1768
               if (op->args.count > 2) {
1769
                  printf(" values ");
1770
                  vcode_dump_reg(op->args.items[2]);
1771
               }
1772
            }
1773
            break;
1774

1775
         case VCODE_OP_DISCONNECT:
1776
            {
1777
               printf("%s ", vcode_op_string(op->kind));
1778
               vcode_dump_reg(op->args.items[0]);
1779
               printf(" count ");
1780
               vcode_dump_reg(op->args.items[1]);
1781
               printf(" reject ");
1782
               vcode_dump_reg(op->args.items[2]);
1783
               printf(" after ");
1784
               vcode_dump_reg(op->args.items[3]);
1785
            }
1786
            break;
1787

1788
         case VCODE_OP_NEG:
1789
         case VCODE_OP_TRAP_NEG:
1790
         case VCODE_OP_ABS:
1791
         case VCODE_OP_RESOLVED:
1792
         case VCODE_OP_LAST_VALUE:
1793
            {
1794
               col += vcode_dump_reg(op->result);
1795
               col += printf(" := %s ", vcode_op_string(op->kind));
1796
               col += vcode_dump_reg(op->args.items[0]);
1797
               if (op->args.count > 1) {
1798
                  col += printf(" locus ");
1799
                  col += vcode_dump_reg(op->args.items[1]);
1800
               }
1801
               vcode_dump_result_type(col, op);
1802
            }
1803
            break;
1804

1805
         case VCODE_OP_SELECT:
1806
            {
1807
               col += vcode_dump_reg(op->result);
1808
               col += printf(" := %s ", vcode_op_string(op->kind));
1809
               col += vcode_dump_reg(op->args.items[0]);
1810
               col += printf(" then ");
1811
               col += vcode_dump_reg(op->args.items[1]);
1812
               col += printf(" else ");
1813
               col += vcode_dump_reg(op->args.items[2]);
1814
               vcode_dump_result_type(col, op);
1815
            }
1816
            break;
1817

1818
         case VCODE_OP_WRAP:
1819
            {
1820
               col += vcode_dump_reg(op->result);
1821
               col += printf(" := %s ", vcode_op_string(op->kind));
1822
               col += vcode_dump_reg(op->args.items[0]);
1823
               col += printf(" [");
1824
               for (int i = 1; i < op->args.count; i += 3) {
1825
                  if (i > 1)
1826
                     col += printf(", ");
1827
                  col += vcode_dump_reg(op->args.items[i + 0]);
1828
                  col += printf(" ");
1829
                  col += vcode_dump_reg(op->args.items[i + 1]);
1830
                  col += printf(" ");
1831
                  col += vcode_dump_reg(op->args.items[i + 2]);
1832
               }
1833
               col += printf("]");
1834
               vcode_dump_result_type(col, op);
1835
            }
1836
            break;
1837

1838
         case VCODE_OP_UARRAY_LEFT:
1839
         case VCODE_OP_UARRAY_RIGHT:
1840
         case VCODE_OP_UARRAY_DIR:
1841
         case VCODE_OP_UARRAY_LEN:
1842
            {
1843
               col += vcode_dump_reg(op->result);
1844
               col += printf(" := %s ", vcode_op_string(op->kind));
1845
               col += vcode_dump_reg(op->args.items[0]);
1846
               col += printf(" dim %d", op->dim);
1847
               vcode_dump_result_type(col, op);
1848
            }
1849
            break;
1850

1851
         case VCODE_OP_UNWRAP:
1852
            {
1853
               col += vcode_dump_reg(op->result);
1854
               col += printf(" := %s ", vcode_op_string(op->kind));
1855
               col += vcode_dump_reg(op->args.items[0]);
1856
               vcode_dump_result_type(col, op);
1857
            }
1858
            break;
1859

1860
         case VCODE_OP_VAR_UPREF:
1861
            {
1862
               col += vcode_dump_reg(op->result);
1863
               col += printf(" := %s %d, ", vcode_op_string(op->kind),
1864
                             op->hops);
1865
               col += vcode_dump_var(op->address, op->hops);
1866
               vcode_dump_result_type(col, op);
1867
            }
1868
            break;
1869

1870
         case VCODE_OP_CONTEXT_UPREF:
1871
            {
1872
               col += vcode_dump_reg(op->result);
1873
               col += printf(" := %s %d", vcode_op_string(op->kind), op->hops);
1874
               vcode_dump_result_type(col, op);
1875
            }
1876
            break;
1877

1878
         case VCODE_OP_ACTIVE:
1879
         case VCODE_OP_EVENT:
1880
         case VCODE_OP_DRIVING:
1881
            {
1882
               col += vcode_dump_reg(op->result);
1883
               col += printf(" := %s ", vcode_op_string(op->kind));
1884
               col += vcode_dump_reg(op->args.items[0]);
1885
               col += printf(" length ");
1886
               col += vcode_dump_reg(op->args.items[1]);
1887
               vcode_dump_result_type(col, op);
1888
            }
1889
            break;
1890

1891
         case VCODE_OP_RECORD_REF:
1892
            {
1893
               col += vcode_dump_reg(op->result);
1894
               col += printf(" := %s ", vcode_op_string(op->kind));
1895
               col += vcode_dump_reg(op->args.items[0]);
1896
               col += printf(" field %d", op->field);
1897
               vcode_dump_result_type(col, op);
1898
            }
1899
            break;
1900

1901
         case VCODE_OP_ARRAY_REF:
1902
            {
1903
               col += vcode_dump_reg(op->result);
1904
               col += printf(" := %s ", vcode_op_string(op->kind));
1905
               col += vcode_dump_reg(op->args.items[0]);
1906
               col += printf(" offset ");
1907
               col += vcode_dump_reg(op->args.items[1]);
1908
               vcode_dump_result_type(col, op);
1909
            }
1910
            break;
1911

1912
         case VCODE_OP_TABLE_REF:
1913
            {
1914
               col += vcode_dump_reg(op->result);
1915
               col += printf(" := %s ", vcode_op_string(op->kind));
1916
               col += vcode_dump_reg(op->args.items[0]);
1917
               col += printf(" stride ");
1918
               col += vcode_dump_reg(op->args.items[1]);
1919
               col += printf(" [");
1920
               for (int i = 2; i < op->args.count; i++) {
1921
                  if (i > 2) col += printf(", ");
1922
                  col += vcode_dump_reg(op->args.items[i]);
1923
               }
1924
               col += printf("]");
1925
               vcode_dump_result_type(col, op);
1926
            }
1927
            break;
1928

1929
         case VCODE_OP_COPY:
1930
            {
1931
               vcode_dump_reg(op->args.items[0]);
1932
               printf(" := %s ", vcode_op_string(op->kind));
1933
               vcode_dump_reg(op->args.items[1]);
1934
               if (op->args.count > 2) {
1935
                  printf(" count " );
1936
                  vcode_dump_reg(op->args.items[2]);
1937
               }
1938
            }
1939
            break;
1940

1941
         case VCODE_OP_SCHED_EVENT:
1942
         case VCODE_OP_CLEAR_EVENT:
1943
            {
1944
               printf("%s on ", vcode_op_string(op->kind));
1945
               vcode_dump_reg(op->args.items[0]);
1946
               printf(" count ");
1947
               vcode_dump_reg(op->args.items[1]);
1948
            }
1949
            break;
1950

1951
         case VCODE_OP_PCALL:
1952
            {
1953
               nvc_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1954
                          istr(op->func));
1955
               for (int i = 0; i < op->args.count; i++) {
1956
                  printf("%s", i > 0 ? ", " : " ");
1957
                  vcode_dump_reg(op->args.items[i]);
1958
               }
1959
               if (op->targets.count > 0)
1960
                  nvc_printf(" resume $yellow$%d$$", op->targets.items[0]);
1961
            }
1962
            break;
1963

1964
         case VCODE_OP_RESUME:
1965
            {
1966
               nvc_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1967
                            istr(op->func));
1968
            }
1969
            break;
1970

1971
         case VCODE_OP_MEMSET:
1972
            {
1973
               vcode_dump_reg(op->args.items[0]);
1974
               printf(" := %s ", vcode_op_string(op->kind));
1975
               vcode_dump_reg(op->args.items[1]);
1976
               printf(" length ");
1977
               vcode_dump_reg(op->args.items[2]);
1978
            }
1979
            break;
1980

1981
         case VCODE_OP_CASE:
1982
            {
1983
               printf("%s ", vcode_op_string(op->kind));
1984
               vcode_dump_reg(op->args.items[0]);
1985
               nvc_printf(" default $yellow$%d$$", op->targets.items[0]);
1986
               for (int i = 1; i < op->args.count; i++) {
1987
                  printf(" [");
1988
                  vcode_dump_reg(op->args.items[i]);
1989
                  nvc_printf(" $yellow$%d$$]", op->targets.items[i]);
1990
               }
1991
            }
1992
            break;
1993

1994
         case VCODE_OP_FILE_OPEN:
1995
            {
1996
               printf("%s ", vcode_op_string(op->kind));
1997
               vcode_dump_reg(op->args.items[0]);
1998
               printf(" name ");
1999
               vcode_dump_reg(op->args.items[1]);
2000
               printf(" length ");
2001
               vcode_dump_reg(op->args.items[2]);
2002
               printf(" kind ");
2003
               vcode_dump_reg(op->args.items[3]);
2004
               if (op->args.count == 5) {
2005
                  printf(" status ");
2006
                  vcode_dump_reg(op->args.items[4]);
2007
               }
2008
            }
2009
            break;
2010

2011
         case VCODE_OP_FILE_WRITE:
2012
            {
2013
               printf("%s ", vcode_op_string(op->kind));
2014
               vcode_dump_reg(op->args.items[0]);
2015
               printf(" value ");
2016
               vcode_dump_reg(op->args.items[1]);
2017
               if (op->args.count == 3) {
2018
                  printf(" length ");
2019
                  vcode_dump_reg(op->args.items[2]);
2020
               }
2021
            }
2022
            break;
2023

2024
         case VCODE_OP_FILE_READ:
2025
            {
2026
               printf("%s ", vcode_op_string(op->kind));
2027
               vcode_dump_reg(op->args.items[0]);
2028
               printf(" ptr ");
2029
               vcode_dump_reg(op->args.items[1]);
2030
               if (op->args.count >= 3) {
2031
                  printf(" inlen ");
2032
                  vcode_dump_reg(op->args.items[2]);
2033
                  if (op->args.count >= 4) {
2034
                     printf(" outlen ");
2035
                     vcode_dump_reg(op->args.items[3]);
2036
                  }
2037
               }
2038
            }
2039
            break;
2040

2041
         case VCODE_OP_NULL:
2042
         case VCODE_OP_NEW:
2043
            {
2044
               col += vcode_dump_reg(op->result);
2045
               col += printf(" := %s", vcode_op_string(op->kind));
2046
               if (op->args.count == 1) {
2047
                  col += printf(" length ");
2048
                  col += vcode_dump_reg(op->args.items[0]);
2049
               }
2050
               vcode_dump_result_type(col, op);
2051
            }
2052
            break;
2053

2054
         case VCODE_OP_NULL_CHECK:
2055
            {
2056
               col += printf("%s ", vcode_op_string(op->kind));
2057
               col += vcode_dump_reg(op->args.items[0]);
2058
               col += printf(" locus ");
2059
               col += vcode_dump_reg(op->args.items[1]);
2060
            }
2061
            break;
2062

2063
         case VCODE_OP_DEALLOCATE:
2064
            {
2065
               col += printf("%s ", vcode_op_string(op->kind));
2066
               col += vcode_dump_reg(op->args.items[0]);
2067
            }
2068
            break;
2069

2070
         case VCODE_OP_ALL:
2071
            {
2072
               col += vcode_dump_reg(op->result);
2073
               col += printf(" := %s ", vcode_op_string(op->kind));
2074
               col += vcode_dump_reg(op->args.items[0]);
2075
               vcode_dump_result_type(col, op);
2076
            }
2077
            break;
2078

2079
         case VCODE_OP_LAST_EVENT:
2080
         case VCODE_OP_LAST_ACTIVE:
2081
         case VCODE_OP_DRIVING_VALUE:
2082
            {
2083
               col += vcode_dump_reg(op->result);
2084
               col += printf(" := %s ", vcode_op_string(op->kind));
2085
               col += vcode_dump_reg(op->args.items[0]);
2086
               if (op->args.count > 1) {
2087
                  col += printf(" length ");
2088
                  col += vcode_dump_reg(op->args.items[1]);
2089
               }
2090
               vcode_dump_result_type(col, op);
2091
            }
2092
            break;
2093

2094
         case VCODE_OP_ALIAS_SIGNAL:
2095
            {
2096
               printf("%s ", vcode_op_string(op->kind));
2097
               vcode_dump_reg(op->args.items[0]);
2098
               printf(" locus ");
2099
               vcode_dump_reg(op->args.items[1]);
2100
            }
2101
            break;
2102

2103
         case VCODE_OP_LENGTH_CHECK:
2104
            {
2105
               col += printf("%s left ", vcode_op_string(op->kind));
2106
               col += vcode_dump_reg(op->args.items[0]);
2107
               col += printf(" == right ");
2108
               col += vcode_dump_reg(op->args.items[1]);
2109
               col += printf(" locus ");
2110
               col += vcode_dump_reg(op->args.items[2]);
2111
               if (op->args.count > 3) {
2112
                  col += printf(" dim ");
2113
                  col += vcode_dump_reg(op->args.items[3]);
2114
               }
2115
            }
2116
            break;
2117

2118
         case VCODE_OP_EXPONENT_CHECK:
2119
         case VCODE_OP_ZERO_CHECK:
2120
            {
2121
               col += printf("%s ", vcode_op_string(op->kind));
2122
               col += vcode_dump_reg(op->args.items[0]);
2123
               col += printf(" locus ");
2124
               col += vcode_dump_reg(op->args.items[1]);
2125
            }
2126
            break;
2127

2128
         case VCODE_OP_INDEX_CHECK:
2129
         case VCODE_OP_RANGE_CHECK:
2130
            {
2131
               col += printf("%s ", vcode_op_string(op->kind));
2132
               col += vcode_dump_reg(op->args.items[0]);
2133
               col += printf(" left ");
2134
               col += vcode_dump_reg(op->args.items[1]);
2135
               col += printf(" right ");
2136
               col += vcode_dump_reg(op->args.items[2]);
2137
               col += printf(" dir ");
2138
               col += vcode_dump_reg(op->args.items[3]);
2139
               col += printf(" locus ");
2140
               col += vcode_dump_reg(op->args.items[4]);
2141
               if (op->args.items[5] != op->args.items[4]) {
2142
                  col += printf(" hint ");
2143
                  col += vcode_dump_reg(op->args.items[5]);
2144
               }
2145
            }
2146
            break;
2147

2148
         case VCODE_OP_DIR_CHECK:
2149
            {
2150
               col += printf("%s ", vcode_op_string(op->kind));
2151
               col += vcode_dump_reg(op->args.items[0]);
2152
               col += printf(" == ");
2153
               col += vcode_dump_reg(op->args.items[1]);
2154
               col += printf(" locus ");
2155
               col += vcode_dump_reg(op->args.items[2]);
2156
            }
2157
            break;
2158

2159
         case VCODE_OP_DEBUG_OUT:
2160
            {
2161
               col += printf("%s ", vcode_op_string(op->kind));
2162
               col += vcode_dump_reg(op->args.items[0]);
2163
            }
2164
            break;
2165

2166
         case VCODE_OP_COVER_STMT:
2167
         case VCODE_OP_COVER_BRANCH:
2168
         case VCODE_OP_COVER_EXPR:
2169
            {
2170
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2171
            }
2172
            break;
2173

2174
         case VCODE_OP_COVER_TOGGLE:
2175
         case VCODE_OP_COVER_STATE:
2176
            {
2177
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2178
               vcode_dump_reg(op->args.items[0]);
2179
            }
2180
            break;
2181

2182
         case VCODE_OP_UNDEFINED:
2183
            {
2184
               col += vcode_dump_reg(op->result);
2185
               col += printf(" := %s", vcode_op_string(op->kind));
2186
               vcode_dump_result_type(col, op);
2187
            }
2188
            break;
2189

2190
         case VCODE_OP_RANGE_LENGTH:
2191
         case VCODE_OP_RANGE_NULL:
2192
            {
2193
               col += vcode_dump_reg(op->result);
2194
               col += printf(" := %s left ", vcode_op_string(op->kind));
2195
               vcode_dump_reg(op->args.items[0]);
2196
               col += printf(" right ");
2197
               vcode_dump_reg(op->args.items[1]);
2198
               col += printf(" dir ");
2199
               col += vcode_dump_reg(op->args.items[2]);
2200
               vcode_dump_result_type(col, op);
2201
            }
2202
            break;
2203

2204
         case VCODE_OP_LINK_PACKAGE:
2205
            {
2206
               col += vcode_dump_reg(op->result);
2207
               col += nvc_printf(" := %s $magenta$%s$$",
2208
                                 vcode_op_string(op->kind), istr(op->ident));
2209
               if (op->args.count > 0) {
2210
                  col += printf(" locus ");
2211
                  col += vcode_dump_reg(op->args.items[0]);
2212
               }
2213
               vcode_dump_result_type(col, op);
2214
            }
2215
            break;
2216

2217
         case VCODE_OP_LINK_VAR:
2218
            {
2219
               col += vcode_dump_reg(op->result);
2220
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2221
               col += vcode_dump_reg(op->args.items[0]);
2222
               col += nvc_printf(" $magenta$%s$$", istr(op->ident));
2223
               vcode_dump_result_type(col, op);
2224
            }
2225
            break;
2226

2227
         case VCODE_OP_UNREACHABLE:
2228
            {
2229
               printf("%s", vcode_op_string(op->kind));
2230
               if (op->args.count > 0) {
2231
                  printf(" ");
2232
                  vcode_dump_reg(op->args.items[0]);
2233
               }
2234
            }
2235
            break;
2236

2237
         case VCODE_OP_DEBUG_LOCUS:
2238
            {
2239
               col += vcode_dump_reg(op->result);
2240
               col += nvc_printf(" := %s $magenta$", vcode_op_string(op->kind));
2241

2242
               tree_t t = tree_from_object(op->object);
2243
               if (t != NULL)
2244
                  col += printf("%s@", tree_kind_str(tree_kind(t)));
2245

2246
               col += nvc_printf("%p$$", op->object);
2247
               vcode_dump_result_type(col, op);
2248
            }
2249
            break;
2250

2251
         case VCODE_OP_ENTER_STATE:
2252
            {
2253
               printf("%s ", vcode_op_string(op->kind));
2254
               vcode_dump_reg(op->args.items[0]);
2255
               if (op->args.count > 1) {
2256
                  printf(" strong ");
2257
                  vcode_dump_reg(op->args.items[1]);
2258
               }
2259
            }
2260
            break;
2261

2262
         case VCODE_OP_REFLECT_VALUE:
2263
            {
2264
               col += vcode_dump_reg(op->result);
2265
               col += printf(" := %s ", vcode_op_string(op->kind));
2266
               vcode_dump_reg(op->args.items[0]);
2267
               col += printf(" context ");
2268
               vcode_dump_reg(op->args.items[1]);
2269
               col += printf(" locus ");
2270
               col += vcode_dump_reg(op->args.items[2]);
2271
               if (op->args.count > 3) {
2272
                  col += printf(" bounds ");
2273
                  col += vcode_dump_reg(op->args.items[3]);
2274
               }
2275
               vcode_dump_result_type(col, op);
2276
            }
2277
            break;
2278

2279
         case VCODE_OP_REFLECT_SUBTYPE:
2280
            {
2281
               col += vcode_dump_reg(op->result);
2282
               col += printf(" := %s context ", vcode_op_string(op->kind));
2283
               vcode_dump_reg(op->args.items[0]);
2284
               col += printf(" locus ");
2285
               col += vcode_dump_reg(op->args.items[1]);
2286
               if (op->args.count > 2) {
2287
                  col += printf(" bounds ");
2288
                  col += vcode_dump_reg(op->args.items[2]);
2289
               }
2290
               vcode_dump_result_type(col, op);
2291
            }
2292
            break;
2293

2294
         case VCODE_OP_FUNCTION_TRIGGER:
2295
            {
2296
               col += vcode_dump_reg(op->result);
2297
               col += nvc_printf(" := %s $magenta$%s$$ ",
2298
                                 vcode_op_string(op->kind), istr(op->func));
2299
               for (int i = 0; i < op->args.count; i++) {
2300
                  if (i > 0) col += printf(", ");
2301
                  col += vcode_dump_reg(op->args.items[i]);
2302
               }
2303
               vcode_dump_result_type(col, op);
2304
            }
2305
            break;
2306

2307
         case VCODE_OP_OR_TRIGGER:
2308
         case VCODE_OP_CMP_TRIGGER:
2309
            {
2310
               col += vcode_dump_reg(op->result);
2311
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2312
               col += vcode_dump_reg(op->args.items[0]);
2313
               if (op->kind == VCODE_OP_OR_TRIGGER)
2314
                  col += printf(" || ");
2315
               else
2316
                  col += printf(" == ");
2317
               col += vcode_dump_reg(op->args.items[1]);
2318
               vcode_dump_result_type(col, op);
2319
            }
2320
            break;
2321

2322
         case VCODE_OP_ADD_TRIGGER:
2323
            {
2324
               printf("%s ", vcode_op_string(op->kind));
2325
               vcode_dump_reg(op->args.items[0]);
2326
            }
2327
            break;
2328

2329
         case VCODE_OP_PUT_CONVERSION:
2330
            {
2331
               nvc_printf("%s ", vcode_op_string(op->kind));
2332
               vcode_dump_reg(op->args.items[0]);
2333
               printf(" signal ");
2334
               vcode_dump_reg(op->args.items[1]);
2335
               printf(" count ");
2336
               vcode_dump_reg(op->args.items[2]);
2337
               printf(" values ");
2338
               vcode_dump_reg(op->args.items[3]);
2339
            }
2340
            break;
2341

2342
         case VCODE_OP_PORT_CONVERSION:
2343
            {
2344
               col += vcode_dump_reg(op->result);
2345
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2346
               col += vcode_dump_reg(op->args.items[0]);
2347
               if (op->args.count > 1) {
2348
                  col += printf(" effective ");
2349
                  col += vcode_dump_reg(op->args.items[1]);
2350
               }
2351
               vcode_dump_result_type(col, op);
2352
            }
2353
            break;
2354

2355
         case VCODE_OP_CONVERT_IN:
2356
         case VCODE_OP_CONVERT_OUT:
2357
            {
2358
               nvc_printf("%s ", vcode_op_string(op->kind));
2359
               vcode_dump_reg(op->args.items[0]);
2360
               printf(" signal ");
2361
               vcode_dump_reg(op->args.items[1]);
2362
               printf(" count ");
2363
               vcode_dump_reg(op->args.items[2]);
2364
            }
2365
            break;
2366

2367
         case VCODE_OP_BIND_FOREIGN:
2368
            {
2369
               nvc_printf("%s ", vcode_op_string(op->kind));
2370
               vcode_dump_reg(op->args.items[0]);
2371
               printf(" length ");
2372
               vcode_dump_reg(op->args.items[1]);
2373
               if (op->args.count > 2) {
2374
                  printf(" locus ");
2375
                  vcode_dump_reg(op->args.items[1]);
2376
               }
2377
            }
2378
            break;
2379

2380
         case VCODE_OP_INSTANCE_NAME:
2381
         case VCODE_OP_BIND_EXTERNAL:
2382
            {
2383
               col += vcode_dump_reg(op->result);
2384
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2385
               col += vcode_dump_reg(op->args.items[0]);
2386
               col += nvc_printf(" scope $magenta$%s$$ ", istr(op->ident));
2387
               for (int i = 1; i < op->args.count; i++) {
2388
                  if (i > 1) col += printf(", ");
2389
                  col += vcode_dump_reg(op->args.items[i]);
2390
               }
2391
               vcode_dump_result_type(col, op);
2392
            }
2393
            break;
2394
         }
2395

2396
         if (j == mark_op && i == old_block)
2397
            nvc_printf("\t $red$<----$$");
2398

2399
         nvc_printf("$$\n");
2400

2401
         if (callback != NULL)
2402
            (*callback)(j, arg);
2403
      }
2404

2405
      if (b->ops.count == 0)
2406
         nvc_printf("  $yellow$%2d:$$ $red$Empty basic block$$\n", i);
2407
   }
2408

2409
   printf("\n");
2410
   fflush(stdout);
2411

2412
   active_block = old_block;
2413
}
2414
LCOV_EXCL_STOP
2415

2416
static inline bool vtype_eq_internal(const vtype_t *at, const vtype_t *bt)
36,193,432✔
2417
{
2418
   if (at->kind != bt->kind)
36,193,432✔
2419
      return false;
2420

2421
   switch (at->kind) {
16,161,431✔
2422
   case VCODE_TYPE_INT:
14,033,886✔
2423
      return (at->low == bt->low) && (at->high == bt->high);
26,106,462✔
2424
   case VCODE_TYPE_REAL:
929,353✔
2425
      return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
1,789,475✔
2426
   case VCODE_TYPE_CARRAY:
102,546✔
2427
      return at->size == bt->size && vtype_eq(at->elem, bt->elem);
109,873✔
2428
   case VCODE_TYPE_UARRAY:
80,964✔
2429
      return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
101,284✔
2430
   case VCODE_TYPE_POINTER:
478,200✔
2431
   case VCODE_TYPE_ACCESS:
2432
      return vtype_eq(at->pointed, bt->pointed);
478,200✔
2433
   case VCODE_TYPE_OFFSET:
2434
   case VCODE_TYPE_OPAQUE:
2435
   case VCODE_TYPE_DEBUG_LOCUS:
2436
   case VCODE_TYPE_TRIGGER:
2437
   case VCODE_TYPE_CONVERSION:
2438
      return true;
2439
   case VCODE_TYPE_RESOLUTION:
73,832✔
2440
   case VCODE_TYPE_CLOSURE:
2441
   case VCODE_TYPE_SIGNAL:
2442
   case VCODE_TYPE_FILE:
2443
      return vtype_eq(at->base, bt->base);
73,832✔
2444
   case VCODE_TYPE_RECORD:
61,661✔
2445
   case VCODE_TYPE_CONTEXT:
2446
      return at->name == bt->name;
61,661✔
2447
   default:
×
2448
      should_not_reach_here();
2449
   }
2450
}
2451

2452
bool vtype_eq(vcode_type_t a, vcode_type_t b)
4,574,217✔
2453
{
2454
   assert(active_unit != NULL);
4,574,217✔
2455

2456
   if (a == b)
4,574,217✔
2457
      return true;
2458
   else if (MASK_CONTEXT(a) == MASK_CONTEXT(b))
948,202✔
2459
      return false;   // Guaranteed by vtype_new
2460
   else {
2461
      const vtype_t *at = vcode_type_data(a);
118,696✔
2462
      const vtype_t *bt = vcode_type_data(b);
118,696✔
2463

2464
      return vtype_eq_internal(at, bt);
118,696✔
2465
   }
2466
}
2467

2468
void vcode_dump(void)
×
2469
{
2470
   vcode_dump_with_mark(-1, NULL, NULL);
×
2471
}
×
2472

2473
static vcode_type_t vtype_new(vtype_t *new)
3,348,254✔
2474
{
2475
   const int index = active_unit->types.count - 1;
3,348,254✔
2476

2477
   for (int i = 0; i < index; i++) {
36,731,954✔
2478
      const vtype_t *cmp = vtype_array_nth_ptr(&(active_unit->types), i);
36,074,736✔
2479
      if (vtype_eq_internal(new, cmp)) {
36,074,736✔
2480
         active_unit->types.count--;
2,691,036✔
2481
         return MAKE_HANDLE(active_unit->depth, i);
2,691,036✔
2482
      }
2483
   }
2484

2485
   return MAKE_HANDLE(active_unit->depth, index);
657,218✔
2486
}
2487

2488
vcode_type_t vtype_int(int64_t low, int64_t high)
2,319,508✔
2489
{
2490
   assert(active_unit != NULL);
2,319,508✔
2491

2492
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
2,319,508✔
2493
   n->kind = VCODE_TYPE_INT;
2,319,508✔
2494
   n->low  = low;
2,319,508✔
2495
   n->high = high;
2,319,508✔
2496

2497
   switch (bits_for_range(low, high)) {
2,319,508✔
2498
   case 64:
128,697✔
2499
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
128,697✔
2500
      break;
128,697✔
2501
   case 32:
623,564✔
2502
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
623,564✔
2503
      break;
623,564✔
2504
   case 16:
4,323✔
2505
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
4,323✔
2506
      break;
4,323✔
2507
   case 8:
910,730✔
2508
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
910,730✔
2509
      break;
910,730✔
2510
   case 1:
652,193✔
2511
      n->repr = VCODE_REPR_U1;
652,193✔
2512
      break;
652,193✔
2513
   case 0:
1✔
2514
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2515
      break;
1✔
2516
   default:
×
2517
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
2518
   }
2519

2520
   return vtype_new(n);
2,319,508✔
2521
}
2522

2523
vcode_type_t vtype_bool(void)
335,675✔
2524
{
2525
   return vtype_int(0, 1);
335,675✔
2526
}
2527

2528
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
56,029✔
2529
{
2530
   assert(active_unit != NULL);
56,029✔
2531

2532
   const vtype_kind_t ekind = vtype_kind(elem);
56,029✔
2533
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
56,029✔
2534
                "array types may not be nested");
2535

2536
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
56,029✔
2537
   memset(n, '\0', sizeof(vtype_t));
56,029✔
2538
   n->kind   = VCODE_TYPE_CARRAY;
56,029✔
2539
   n->elem   = elem;
56,029✔
2540
   n->bounds = bounds;
56,029✔
2541
   n->size   = MAX(size, 0);
56,029✔
2542

2543
   return vtype_new(n);
56,029✔
2544
}
2545

2546
vcode_type_t vtype_find_named_record(ident_t name)
37,676✔
2547
{
2548
   assert(active_unit != NULL);
37,676✔
2549

2550
   for (int i = 0; i < active_unit->types.count; i++) {
478,504✔
2551
      vtype_t *other = &(active_unit->types.items[i]);
466,912✔
2552
      if (other->kind == VCODE_TYPE_RECORD && other->name == name)
466,912✔
2553
         return MAKE_HANDLE(active_unit->depth, i);
26,084✔
2554
   }
2555

2556
   return VCODE_INVALID_TYPE;
2557
}
2558

2559
vcode_type_t vtype_named_record(ident_t name, const vcode_type_t *field_types,
11,592✔
2560
                                int nfields)
2561
{
2562
   assert(active_unit != NULL);
11,592✔
2563

2564
   vtype_t *data = NULL;
11,592✔
2565
   vcode_type_t handle = vtype_find_named_record(name);
11,592✔
2566
   if (handle == VCODE_INVALID_TYPE) {
11,592✔
2567
      data = vtype_array_alloc(&(active_unit->types));
5,796✔
2568
      memset(data, '\0', sizeof(vtype_t));
5,796✔
2569
      data->kind = VCODE_TYPE_RECORD;
5,796✔
2570
      data->name = name;
5,796✔
2571

2572
      handle = vtype_new(data);
5,796✔
2573
   }
2574
   else {
2575
      data = vcode_type_data(handle);
5,796✔
2576
      VCODE_ASSERT(data->fields.count == 0,
5,796✔
2577
                    "record type %s already defined", istr(name));
2578
   }
2579

2580
   vcode_type_array_resize(&(data->fields), 0, VCODE_INVALID_TYPE);
11,592✔
2581
   for (int i = 0; i < nfields; i++)
30,887✔
2582
      vcode_type_array_add(&(data->fields), field_types[i]);
19,295✔
2583

2584
   return handle;
11,592✔
2585
}
2586

2587
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
77,822✔
2588
{
2589
   assert(active_unit != NULL);
77,822✔
2590

2591
   const vtype_kind_t ekind = vtype_kind(elem);
77,822✔
2592
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
77,822✔
2593
                "array types may not be nested");
2594

2595
   VCODE_ASSERT(ndim > 0, "uarray must have at least one dimension");
77,822✔
2596

2597
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
77,822✔
2598
   memset(n, '\0', sizeof(vtype_t));
77,822✔
2599
   n->kind   = VCODE_TYPE_UARRAY;
77,822✔
2600
   n->elem   = elem;
77,822✔
2601
   n->bounds = bounds;
77,822✔
2602
   n->dims   = ndim;
77,822✔
2603

2604
   return vtype_new(n);
77,822✔
2605
}
2606

2607
vcode_type_t vtype_pointer(vcode_type_t to)
202,935✔
2608
{
2609
   assert(active_unit != NULL);
202,935✔
2610

2611
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
202,935✔
2612
   n->kind    = VCODE_TYPE_POINTER;
202,935✔
2613
   n->pointed = to;
202,935✔
2614

2615
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
202,935✔
2616
                "cannot get pointer to carray type");
2617

2618
   return vtype_new(n);
202,935✔
2619
}
2620

2621
vcode_type_t vtype_access(vcode_type_t to)
9,441✔
2622
{
2623
   assert(active_unit != NULL);
9,441✔
2624

2625
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
9,441✔
2626
   n->kind    = VCODE_TYPE_ACCESS;
9,441✔
2627
   n->pointed = to;
9,441✔
2628

2629
   return vtype_new(n);
9,441✔
2630
}
2631

2632
vcode_type_t vtype_signal(vcode_type_t base)
39,540✔
2633
{
2634
   assert(active_unit != NULL);
39,540✔
2635

2636
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
39,540✔
2637
   n->kind = VCODE_TYPE_SIGNAL;
39,540✔
2638
   n->base = base;
39,540✔
2639

2640
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
39,540✔
2641

2642
   return vtype_new(n);
39,540✔
2643
}
2644

2645
vcode_type_t vtype_resolution(vcode_type_t base)
8,323✔
2646
{
2647
   assert(active_unit != NULL);
8,323✔
2648

2649
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
8,323✔
2650
   n->kind = VCODE_TYPE_RESOLUTION;
8,323✔
2651
   n->base = base;
8,323✔
2652

2653
   return vtype_new(n);
8,323✔
2654
}
2655

2656
vcode_type_t vtype_closure(vcode_type_t result)
5,448✔
2657
{
2658
   assert(active_unit != NULL);
5,448✔
2659

2660
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
5,448✔
2661
   n->kind = VCODE_TYPE_CLOSURE;
5,448✔
2662
   n->base = result;
5,448✔
2663

2664
   return vtype_new(n);
5,448✔
2665
}
2666

2667
vcode_type_t vtype_context(ident_t name)
55,257✔
2668
{
2669
   assert(active_unit != NULL);
55,257✔
2670
   assert(name != NULL);
55,257✔
2671

2672
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
55,257✔
2673
   n->kind = VCODE_TYPE_CONTEXT;
55,257✔
2674
   n->name = name;
55,257✔
2675

2676
   return vtype_new(n);
55,257✔
2677
}
2678

2679
vcode_type_t vtype_file(vcode_type_t base)
1,856✔
2680
{
2681
   assert(active_unit != NULL);
1,856✔
2682

2683
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,856✔
2684
   n->kind = VCODE_TYPE_FILE;
1,856✔
2685
   n->base = base;
1,856✔
2686

2687
   return vtype_new(n);
1,856✔
2688
}
2689

2690
vcode_type_t vtype_offset(void)
293,447✔
2691
{
2692
   assert(active_unit != NULL);
293,447✔
2693

2694
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
293,447✔
2695
   n->kind = VCODE_TYPE_OFFSET;
293,447✔
2696
   n->low  = INT64_MIN;
293,447✔
2697
   n->high = INT64_MAX;
293,447✔
2698
   n->repr = VCODE_REPR_I64;
293,447✔
2699

2700
   return vtype_new(n);
293,447✔
2701
}
2702

2703
vcode_type_t vtype_time(void)
14,708✔
2704
{
2705
   return vtype_int(INT64_MIN, INT64_MAX);
14,708✔
2706
}
2707

2708
vcode_type_t vtype_char(void)
8,179✔
2709
{
2710
   return vtype_int(0, 255);
8,179✔
2711
}
2712

2713
vcode_type_t vtype_opaque(void)
3,474✔
2714
{
2715
   assert(active_unit != NULL);
3,474✔
2716

2717
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
3,474✔
2718
   n->kind = VCODE_TYPE_OPAQUE;
3,474✔
2719

2720
   return vtype_new(n);
3,474✔
2721
}
2722

2723
vcode_type_t vtype_debug_locus(void)
156,975✔
2724
{
2725
   assert(active_unit != NULL);
156,975✔
2726

2727
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
156,975✔
2728
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
156,975✔
2729

2730
   return vtype_new(n);
156,975✔
2731
}
2732

2733
vcode_type_t vtype_trigger(void)
386✔
2734
{
2735
   assert(active_unit != NULL);
386✔
2736

2737
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
386✔
2738
   n->kind = VCODE_TYPE_TRIGGER;
386✔
2739

2740
   return vtype_new(n);
386✔
2741
}
2742

2743
vcode_type_t vtype_conversion(void)
426✔
2744
{
2745
   assert(active_unit != NULL);
426✔
2746

2747
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
426✔
2748
   n->kind = VCODE_TYPE_CONVERSION;
426✔
2749

2750
   return vtype_new(n);
426✔
2751
}
2752

2753
vcode_type_t vtype_real(double low, double high)
111,591✔
2754
{
2755
   assert(active_unit != NULL);
111,591✔
2756

2757
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
111,591✔
2758
   n->kind  = VCODE_TYPE_REAL;
111,591✔
2759
   n->rlow  = low;
111,591✔
2760
   n->rhigh = high;
111,591✔
2761

2762
   return vtype_new(n);
111,591✔
2763
}
2764

2765
vtype_kind_t vtype_kind(vcode_type_t type)
4,837,208✔
2766
{
2767
   vtype_t *vt = vcode_type_data(type);
4,837,208✔
2768
   return vt->kind;
4,837,208✔
2769
}
2770

2771
vtype_repr_t vtype_repr(vcode_type_t type)
45,712✔
2772
{
2773
   vtype_t *vt = vcode_type_data(type);
45,712✔
2774
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
45,712✔
2775
   return vt->repr;
45,712✔
2776
}
2777

2778
vcode_type_t vtype_elem(vcode_type_t type)
161,205✔
2779
{
2780
   vtype_t *vt = vcode_type_data(type);
161,205✔
2781
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
161,205✔
2782
   return vt->elem;
161,205✔
2783
}
2784

2785
vcode_type_t vtype_base(vcode_type_t type)
52,733✔
2786
{
2787
   vtype_t *vt = vcode_type_data(type);
52,733✔
2788
   assert(vt->kind == VCODE_TYPE_SIGNAL || vt->kind == VCODE_TYPE_FILE
52,733✔
2789
          || vt->kind == VCODE_TYPE_RESOLUTION
2790
          || vt->kind == VCODE_TYPE_CLOSURE);
2791
   return vt->base;
52,733✔
2792
}
2793

2794
vcode_type_t vtype_bounds(vcode_type_t type)
22,514✔
2795
{
2796
   vtype_t *vt = vcode_type_data(type);
22,514✔
2797
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
22,514✔
2798
   return vt->bounds;
22,514✔
2799
}
2800

2801
unsigned vtype_dims(vcode_type_t type)
43,238✔
2802
{
2803
   vtype_t *vt = vcode_type_data(type);
43,238✔
2804
   assert(vt->kind == VCODE_TYPE_UARRAY);
43,238✔
2805
   return vt->dims;
43,238✔
2806
}
2807

2808
unsigned vtype_size(vcode_type_t type)
52,617✔
2809
{
2810
   vtype_t *vt = vcode_type_data(type);
52,617✔
2811
   assert(vt->kind == VCODE_TYPE_CARRAY);
52,617✔
2812
   return vt->size;
52,617✔
2813
}
2814

2815
int vtype_fields(vcode_type_t type)
8,021✔
2816
{
2817
   vtype_t *vt = vcode_type_data(type);
8,021✔
2818
   assert(vt->kind == VCODE_TYPE_RECORD);
8,021✔
2819
   return vt->fields.count;
8,021✔
2820
}
2821

2822
vcode_type_t vtype_field(vcode_type_t type, int field)
30,988✔
2823
{
2824
   vtype_t *vt = vcode_type_data(type);
30,988✔
2825
   assert(vt->kind == VCODE_TYPE_RECORD);
30,988✔
2826
   return vcode_type_array_nth(&(vt->fields), field);
30,988✔
2827
}
2828

2829
ident_t vtype_name(vcode_type_t type)
19,097✔
2830
{
2831
   vtype_t *vt = vcode_type_data(type);
19,097✔
2832
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
19,097✔
2833
   return vt->name;
19,097✔
2834
}
2835

2836
vcode_type_t vtype_pointed(vcode_type_t type)
339,191✔
2837
{
2838
   vtype_t *vt = vcode_type_data(type);
339,191✔
2839
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
339,191✔
2840
   return vt->pointed;
339,191✔
2841
}
2842

2843
int64_t vtype_low(vcode_type_t type)
247,965✔
2844
{
2845
   vtype_t *vt = vcode_type_data(type);
247,965✔
2846
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
247,965✔
2847
   return vt->low;
247,965✔
2848
}
2849

2850
int64_t vtype_high(vcode_type_t type)
245,251✔
2851
{
2852
   vtype_t *vt = vcode_type_data(type);
245,251✔
2853
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
245,251✔
2854
   return vt->high;
245,251✔
2855
}
2856

2857
static bool vtype_is_pointer(vcode_type_t type, vtype_kind_t to)
1,587✔
2858
{
2859
   return vtype_kind(type) == VCODE_TYPE_POINTER
1,587✔
2860
      && vtype_kind(vtype_pointed(type)) == to;
1,587✔
2861
}
2862

2863
bool vtype_is_scalar(vcode_type_t type)
420,633✔
2864
{
2865
   const vtype_kind_t kind = vtype_kind(type);
420,633✔
2866
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
420,633✔
2867
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
163,044✔
2868
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2869
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2870
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER
2871
      || kind == VCODE_TYPE_RESOLUTION;
420,633✔
2872
}
2873

2874
bool vtype_is_numeric(vcode_type_t type)
19,002✔
2875
{
2876
   const vtype_kind_t kind = vtype_kind(type);
19,002✔
2877
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
19,002✔
2878
      || kind == VCODE_TYPE_REAL;
19,002✔
2879
}
2880

2881
bool vtype_is_integral(vcode_type_t type)
1,046✔
2882
{
2883
   const vtype_kind_t kind = vtype_kind(type);
1,046✔
2884
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET;
1,046✔
2885
}
2886

2887
bool vtype_is_composite(vcode_type_t type)
31,919✔
2888
{
2889
   const vtype_kind_t kind = vtype_kind(type);
31,919✔
2890
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
31,919✔
2891
}
2892

2893
bool vtype_is_signal(vcode_type_t type)
154,012✔
2894
{
2895
   vtype_t *vt = vcode_type_data(type);
275,606✔
2896
   switch (vt->kind) {
275,606✔
2897
   case VCODE_TYPE_SIGNAL:
2898
      return true;
2899
   case VCODE_TYPE_POINTER:
71,644✔
2900
      return vtype_is_signal(vt->pointed);
71,644✔
2901
   case VCODE_TYPE_RECORD:
2902
      for (int i = 0; i < vt->fields.count; i++) {
34,338✔
2903
         if (vtype_is_signal(vt->fields.items[i]))
27,125✔
2904
            return true;
2905
      }
2906
      return false;
2907
   case VCODE_TYPE_UARRAY:
49,950✔
2908
   case VCODE_TYPE_CARRAY:
2909
      return vtype_is_signal(vt->elem);
49,950✔
2910
   default:
119,244✔
2911
      return false;
119,244✔
2912
   }
2913
}
2914

2915
int vtype_repr_bits(vtype_repr_t repr)
×
2916
{
2917
   switch (repr) {
×
2918
   case VCODE_REPR_U1: return 1;
2919
   case VCODE_REPR_U8: case VCODE_REPR_I8: return 8;
2920
   case VCODE_REPR_U16: case VCODE_REPR_I16: return 16;
2921
   case VCODE_REPR_U32: case VCODE_REPR_I32: return 32;
2922
   case VCODE_REPR_U64: case VCODE_REPR_I64: return 64;
2923
   default: return -1;
2924
   }
2925
}
2926

2927
bool vtype_repr_signed(vtype_repr_t repr)
×
2928
{
2929
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
×
2930
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
×
2931
}
2932

2933
static int64_t vtype_repr_low(vtype_repr_t repr)
13,722✔
2934
{
2935
   switch (repr) {
13,722✔
2936
   case VCODE_REPR_U1:
2937
   case VCODE_REPR_U8:
2938
   case VCODE_REPR_U16:
2939
   case VCODE_REPR_U32:
2940
   case VCODE_REPR_U64: return 0;
2941
   case VCODE_REPR_I8:  return INT8_MIN;
2942
   case VCODE_REPR_I16: return INT16_MIN;
2943
   case VCODE_REPR_I32: return INT32_MIN;
2944
   case VCODE_REPR_I64: return INT64_MIN;
2945
   default:             return 0;
2946
   }
2947
}
2948

2949
static uint64_t vtype_repr_high(vtype_repr_t repr)
13,722✔
2950
{
2951
   switch (repr) {
13,722✔
2952
   case VCODE_REPR_U1:  return 1;
2953
   case VCODE_REPR_U8:  return UINT8_MAX;
2954
   case VCODE_REPR_U16: return UINT16_MAX;
2955
   case VCODE_REPR_U32: return UINT32_MAX;
2956
   case VCODE_REPR_U64: return UINT64_MAX;
2957
   case VCODE_REPR_I8:  return INT8_MAX;
2958
   case VCODE_REPR_I16: return INT16_MAX;
2959
   case VCODE_REPR_I32: return INT32_MAX;
2960
   case VCODE_REPR_I64: return INT64_MAX;
2961
   default:             return 0;
2962
   }
2963
}
2964

2965
static bool vtype_clamp_to_repr(vtype_repr_t repr, int64_t *low, int64_t *high)
13,722✔
2966
{
2967
   int64_t clamp_low = vtype_repr_low(repr);
13,722✔
2968
   uint64_t clamp_high = vtype_repr_high(repr);
13,722✔
2969

2970
   if (*low >= clamp_low && *high <= clamp_high)
13,722✔
2971
      return true;
2972
   else {
2973
      *low = MAX(clamp_low, *low);
6,389✔
2974
      *high = MIN(clamp_high, *high);
6,389✔
2975
      return false;
6,389✔
2976
   }
2977
}
2978

2979
int vcode_count_params(void)
13,283✔
2980
{
2981
   assert(active_unit != NULL);
13,283✔
2982
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
13,283✔
2983
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2984
          || active_unit->kind == VCODE_UNIT_PROPERTY
2985
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2986

2987
   return active_unit->params.count;
13,283✔
2988
}
2989

2990
vcode_type_t vcode_param_type(int param)
31,424✔
2991
{
2992
   assert(active_unit != NULL);
31,424✔
2993
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
31,424✔
2994
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2995
          || active_unit->kind == VCODE_UNIT_PROPERTY
2996
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2997
   assert(param < active_unit->params.count);
31,424✔
2998

2999
   return active_unit->params.items[param].type;
31,424✔
3000
}
3001

3002
ident_t vcode_param_name(int param)
31,424✔
3003
{
3004
   assert(active_unit != NULL);
31,424✔
3005
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
31,424✔
3006
          || active_unit->kind == VCODE_UNIT_PROCEDURE
3007
          || active_unit->kind == VCODE_UNIT_PROPERTY
3008
          || active_unit->kind == VCODE_UNIT_PROTECTED);
3009
   assert(param < active_unit->params.count);
31,424✔
3010

3011
   return active_unit->params.items[param].name;
31,424✔
3012
}
3013

3014
vcode_reg_t vcode_param_reg(int param)
31,424✔
3015
{
3016
   assert(active_unit != NULL);
31,424✔
3017
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
31,424✔
3018
          || active_unit->kind == VCODE_UNIT_PROCEDURE
3019
          || active_unit->kind == VCODE_UNIT_PROPERTY
3020
          || active_unit->kind == VCODE_UNIT_PROTECTED);
3021
   assert(param < active_unit->params.count);
31,424✔
3022

3023
   return active_unit->params.items[param].reg;
31,424✔
3024
}
3025

3026
vcode_block_t emit_block(void)
137,725✔
3027
{
3028
   assert(active_unit != NULL);
137,725✔
3029

3030
   vcode_block_t bnum = active_unit->blocks.count;
137,725✔
3031

3032
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
137,725✔
3033
   memset(bptr, '\0', sizeof(block_t));
137,725✔
3034

3035
   if (active_block != VCODE_INVALID_BLOCK)
137,725✔
3036
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
86,909✔
3037
   else
3038
      bptr->last_loc = LOC_INVALID;
50,816✔
3039

3040
   return bnum;
137,725✔
3041
}
3042

3043
void vcode_select_unit(vcode_unit_t unit)
178,702✔
3044
{
3045
   active_unit  = unit;
178,702✔
3046
   active_block = VCODE_INVALID_BLOCK;
178,702✔
3047
}
178,702✔
3048

3049
void vcode_select_block(vcode_block_t block)
322,828✔
3050
{
3051
   assert(active_unit != NULL);
322,828✔
3052
   active_block = block;
322,828✔
3053
}
322,828✔
3054

3055
vcode_block_t vcode_active_block(void)
737✔
3056
{
3057
   assert(active_unit != NULL);
737✔
3058
   assert(active_block != -1);
737✔
3059
   return active_block;
737✔
3060
}
3061

3062
const loc_t *vcode_last_loc(void)
1,186,942✔
3063
{
3064
   return &(vcode_block_data()->last_loc);
1,186,942✔
3065
}
3066

3067
vcode_unit_t vcode_active_unit(void)
735✔
3068
{
3069
   assert(active_unit != NULL);
735✔
3070
   return active_unit;
735✔
3071
}
3072

3073
ident_t vcode_unit_name(vcode_unit_t vu)
156,761✔
3074
{
3075
   assert(vu != NULL);
156,761✔
3076
   return vu->name;
156,761✔
3077
}
3078

3079
bool vcode_unit_has_undefined(vcode_unit_t vu)
11,158✔
3080
{
3081
   assert(vu != NULL);
11,158✔
3082
   return !!(vu->flags & UNIT_UNDEFINED);
11,158✔
3083
}
3084

3085
int vcode_unit_depth(vcode_unit_t vu)
×
3086
{
3087
   assert(vu != NULL);
×
3088
   return vu->depth;
×
3089
}
3090

3091
void vcode_set_result(vcode_type_t type)
21,328✔
3092
{
3093
   assert(active_unit != NULL);
21,328✔
3094
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
21,328✔
3095
          || active_unit->kind == VCODE_UNIT_THUNK);
3096

3097
   active_unit->result = type;
21,328✔
3098
}
21,328✔
3099

3100
vcode_type_t vcode_unit_result(vcode_unit_t vu)
23,402✔
3101
{
3102
   assert(vu != NULL);
23,402✔
3103
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
23,402✔
3104
   return vu->result;
23,402✔
3105
}
3106

3107
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
140,757✔
3108
{
3109
   assert(vu != NULL);
140,757✔
3110
   return vu->kind;
140,757✔
3111
}
3112

3113
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
78,806✔
3114
{
3115
   assert(vu != NULL);
78,806✔
3116
   return vu->context;
78,806✔
3117
}
3118

3119
object_t *vcode_unit_object(vcode_unit_t vu)
88,150✔
3120
{
3121
   assert(vu != NULL);
88,150✔
3122
   return vu->object;
88,150✔
3123
}
3124

3125
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
61,986✔
3126
{
3127
   int hops = 0;
61,986✔
3128
   for (; (unit = unit->context); hops++)
152,503✔
3129
      ;
3130
   return hops;
61,986✔
3131
}
3132

3133
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
27,648✔
3134
{
3135
   assert(context->kind != VCODE_UNIT_THUNK);
27,648✔
3136

3137
   child->next = NULL;
27,648✔
3138
   if (context->children == NULL)
27,648✔
3139
      context->children = child;
12,436✔
3140
   else {
3141
      vcode_unit_t it;
3142
      for (it = context->children; it->next != NULL; it = it->next)
70,326✔
3143
         ;
3144
      it->next = child;
15,212✔
3145
   }
3146
}
27,648✔
3147

3148
vcode_unit_t emit_function(ident_t name, object_t *obj, vcode_unit_t context)
12,293✔
3149
{
3150
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
12,293✔
3151
   vu->kind     = VCODE_UNIT_FUNCTION;
12,293✔
3152
   vu->name     = name;
12,293✔
3153
   vu->context  = context;
12,293✔
3154
   vu->result   = VCODE_INVALID_TYPE;
12,293✔
3155
   vu->depth    = vcode_unit_calc_depth(vu);
12,293✔
3156
   vu->object   = obj;
12,293✔
3157

3158
   vcode_add_child(context, vu);
12,293✔
3159

3160
   vcode_select_unit(vu);
12,293✔
3161
   vcode_select_block(emit_block());
12,293✔
3162
   emit_debug_info(&(obj->loc));
12,293✔
3163

3164
   return vu;
12,293✔
3165
}
3166

3167
vcode_unit_t emit_procedure(ident_t name, object_t *obj, vcode_unit_t context)
216✔
3168
{
3169
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
216✔
3170
   vu->kind     = VCODE_UNIT_PROCEDURE;
216✔
3171
   vu->name     = name;
216✔
3172
   vu->context  = context;
216✔
3173
   vu->result   = VCODE_INVALID_TYPE;
216✔
3174
   vu->depth    = vcode_unit_calc_depth(vu);
216✔
3175
   vu->object   = obj;
216✔
3176

3177
   vcode_add_child(context, vu);
216✔
3178

3179
   vcode_select_unit(vu);
216✔
3180
   vcode_select_block(emit_block());
216✔
3181
   emit_debug_info(&(obj->loc));
216✔
3182

3183
   return vu;
216✔
3184
}
3185

3186
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
7,635✔
3187
{
3188
   assert(context->kind == VCODE_UNIT_INSTANCE);
7,635✔
3189

3190
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
7,635✔
3191
   vu->kind     = VCODE_UNIT_PROCESS;
7,635✔
3192
   vu->name     = name;
7,635✔
3193
   vu->context  = context;
7,635✔
3194
   vu->depth    = vcode_unit_calc_depth(vu);
7,635✔
3195
   vu->result   = VCODE_INVALID_TYPE;
7,635✔
3196
   vu->object   = obj;
7,635✔
3197

3198
   vcode_add_child(context, vu);
7,635✔
3199

3200
   vcode_select_unit(vu);
7,635✔
3201
   vcode_select_block(emit_block());
7,635✔
3202
   emit_debug_info(&(obj->loc));
7,635✔
3203

3204
   return vu;
7,635✔
3205
}
3206

3207
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
10,027✔
3208
{
3209
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
10,027✔
3210

3211
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
10,027✔
3212
   vu->kind     = VCODE_UNIT_INSTANCE;
10,027✔
3213
   vu->name     = name;
10,027✔
3214
   vu->context  = context;
10,027✔
3215
   vu->depth    = vcode_unit_calc_depth(vu);
10,027✔
3216
   vu->result   = VCODE_INVALID_TYPE;
10,027✔
3217
   vu->object   = obj;
10,027✔
3218

3219
   if (context != NULL)
10,027✔
3220
      vcode_add_child(context, vu);
6,255✔
3221

3222
   vcode_select_unit(vu);
10,027✔
3223
   vcode_select_block(emit_block());
10,027✔
3224
   emit_debug_info(&(obj->loc));
10,027✔
3225

3226
   return vu;
10,027✔
3227
}
3228

3229
vcode_unit_t emit_package(ident_t name, object_t *obj, vcode_unit_t context)
8,701✔
3230
{
3231
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,701✔
3232
   vu->kind     = VCODE_UNIT_PACKAGE;
8,701✔
3233
   vu->name     = name;
8,701✔
3234
   vu->context  = context;
8,701✔
3235
   vu->depth    = vcode_unit_calc_depth(vu);
8,701✔
3236
   vu->result   = VCODE_INVALID_TYPE;
8,701✔
3237
   vu->object   = obj;
8,701✔
3238

3239
   if (context != NULL)
8,701✔
3240
      vcode_add_child(context, vu);
189✔
3241

3242
   vcode_select_unit(vu);
8,701✔
3243
   vcode_select_block(emit_block());
8,701✔
3244
   emit_debug_info(&(obj->loc));
8,701✔
3245

3246
   return vu;
8,701✔
3247
}
3248

3249
vcode_unit_t emit_protected(ident_t name, object_t *obj, vcode_unit_t context)
534✔
3250
{
3251
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
534✔
3252
   vu->kind     = VCODE_UNIT_PROTECTED;
534✔
3253
   vu->name     = name;
534✔
3254
   vu->context  = context;
534✔
3255
   vu->depth    = vcode_unit_calc_depth(vu);
534✔
3256
   vu->result   = VCODE_INVALID_TYPE;
534✔
3257
   vu->object   = obj;
534✔
3258

3259
   if (context != NULL)
534✔
3260
      vcode_add_child(context, vu);
534✔
3261

3262
   vcode_select_unit(vu);
534✔
3263
   vcode_select_block(emit_block());
534✔
3264
   emit_debug_info(&(obj->loc));
534✔
3265

3266
   return vu;
534✔
3267
}
3268

3269
vcode_unit_t emit_property(ident_t name, object_t *obj, vcode_unit_t context)
240✔
3270
{
3271
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
240✔
3272
   vu->kind     = VCODE_UNIT_PROPERTY;
240✔
3273
   vu->name     = name;
240✔
3274
   vu->context  = context;
240✔
3275
   vu->depth    = vcode_unit_calc_depth(vu);
240✔
3276
   vu->result   = VCODE_INVALID_TYPE;
240✔
3277
   vu->object   = obj;
240✔
3278

3279
   if (context != NULL)
240✔
3280
      vcode_add_child(context, vu);
240✔
3281

3282
   vcode_select_unit(vu);
240✔
3283
   vcode_select_block(emit_block());
240✔
3284
   emit_debug_info(&(obj->loc));
240✔
3285

3286
   return vu;
240✔
3287
}
3288

3289
vcode_unit_t emit_thunk(ident_t name, object_t *obj, vcode_unit_t context)
11,170✔
3290
{
3291
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
11,170✔
3292
   vu->kind     = VCODE_UNIT_THUNK;
11,170✔
3293
   vu->name     = name;
11,170✔
3294
   vu->context  = context;
11,170✔
3295
   vu->depth    = vcode_unit_calc_depth(vu);
11,170✔
3296
   vu->result   = VCODE_INVALID_TYPE;
11,170✔
3297
   vu->depth    = vcode_unit_calc_depth(vu);
11,170✔
3298
   vu->object   = obj;
11,170✔
3299

3300
   if (context != NULL)
11,170✔
3301
      vcode_add_child(context, vu);
286✔
3302

3303
   vcode_select_unit(vu);
11,170✔
3304
   vcode_select_block(emit_block());
11,170✔
3305

3306
   return vu;
11,170✔
3307
}
3308

3309
void emit_assert(vcode_reg_t value, vcode_reg_t message, vcode_reg_t length,
14,658✔
3310
                 vcode_reg_t severity, vcode_reg_t locus, vcode_reg_t hint_left,
3311
                 vcode_reg_t hint_right)
3312
{
3313
   int64_t value_const;
14,658✔
3314
   if (vcode_reg_const(value, &value_const) && value_const != 0) {
14,658✔
3315
      emit_comment("Always true assertion on r%d", value);
30✔
3316
      return;
30✔
3317
   }
3318

3319
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
14,628✔
3320
   vcode_add_arg(op, value);
14,628✔
3321
   vcode_add_arg(op, severity);
14,628✔
3322
   vcode_add_arg(op, message);
14,628✔
3323
   vcode_add_arg(op, length);
14,628✔
3324
   vcode_add_arg(op, locus);
14,628✔
3325

3326
   if (hint_left != VCODE_INVALID_REG) {
14,628✔
3327
      vcode_add_arg(op, hint_left);
6,088✔
3328
      vcode_add_arg(op, hint_right);
6,088✔
3329

3330
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
6,088✔
3331
                   "left hint must be scalar");
3332
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
6,088✔
3333
                   "right hint must be scalar");
3334
   }
3335

3336
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
14,628✔
3337
                "value parameter to assert is not bool");
3338
   VCODE_ASSERT(message == VCODE_INVALID_REG
14,628✔
3339
                || vcode_reg_kind(message) == VCODE_TYPE_POINTER,
3340
                "message parameter to assert is not a pointer");
3341
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
14,628✔
3342
                "value parameter to assert is not bool");
3343
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
14,628✔
3344
                "locus argument to report must be a debug locus");
3345
}
3346

3347
void emit_report(vcode_reg_t message, vcode_reg_t length, vcode_reg_t severity,
2,077✔
3348
                 vcode_reg_t locus)
3349
{
3350
   op_t *op = vcode_add_op(VCODE_OP_REPORT);
2,077✔
3351
   vcode_add_arg(op, severity);
2,077✔
3352
   vcode_add_arg(op, message);
2,077✔
3353
   vcode_add_arg(op, length);
2,077✔
3354
   vcode_add_arg(op, locus);
2,077✔
3355

3356
   VCODE_ASSERT(vcode_reg_kind(message) == VCODE_TYPE_POINTER,
2,077✔
3357
                "message parameter to report is not a pointer");
3358
   VCODE_ASSERT(vtype_eq(vtype_pointed(vcode_reg_type(message)), vtype_char()),
2,077✔
3359
                "message parameter to report is not a character pointer");
3360
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,077✔
3361
                "locus argument to report must be a debug locus");
3362
}
2,077✔
3363

3364
vcode_reg_t emit_cmp(vcode_cmp_t cmp, vcode_reg_t lhs, vcode_reg_t rhs)
34,606✔
3365
{
3366
   if (lhs == rhs) {
34,606✔
3367
      if (cmp == VCODE_CMP_EQ)
398✔
3368
         return emit_const(vtype_bool(), 1);
242✔
3369
      else if (cmp == VCODE_CMP_NEQ)
156✔
3370
         return emit_const(vtype_bool(), 0);
×
3371
      else if (cmp == VCODE_CMP_LEQ || cmp == VCODE_CMP_GEQ)
156✔
3372
         return emit_const(vtype_bool(), 1);
×
3373
      else if (cmp == VCODE_CMP_LT || cmp == VCODE_CMP_GT)
156✔
3374
         return emit_const(vtype_bool(), 0);
156✔
3375
   }
3376

3377
   int64_t lconst, rconst;
34,208✔
3378
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)) {
34,208✔
3379
      switch (cmp) {
334✔
3380
      case VCODE_CMP_EQ:
312✔
3381
         return emit_const(vtype_bool(), lconst == rconst);
312✔
3382
      case VCODE_CMP_NEQ:
3✔
3383
         return emit_const(vtype_bool(), lconst != rconst);
3✔
3384
      case VCODE_CMP_LT:
9✔
3385
         return emit_const(vtype_bool(), lconst < rconst);
9✔
3386
      case VCODE_CMP_GT:
10✔
3387
         return emit_const(vtype_bool(), lconst > rconst);
10✔
3388
      case VCODE_CMP_LEQ:
×
3389
         return emit_const(vtype_bool(), lconst <= rconst);
×
3390
      case VCODE_CMP_GEQ:
×
3391
         return emit_const(vtype_bool(), lconst >= rconst);
×
3392
      default:
×
3393
         fatal_trace("cannot fold comparison %d", cmp);
3394
      }
3395
   }
3396

3397
   // Reuse any previous operation in this block with the same arguments
3398
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
662,688✔
3399
      if (other->args.count == 2 && other->args.items[0] == lhs
24,433✔
3400
          && other->args.items[1] == rhs && other->cmp == cmp)
2,276✔
3401
         return other->result;
193✔
3402
   }
3403

3404
   op_t *op = vcode_add_op(VCODE_OP_CMP);
33,681✔
3405
   vcode_add_arg(op, lhs);
33,681✔
3406
   vcode_add_arg(op, rhs);
33,681✔
3407
   op->cmp    = cmp;
33,681✔
3408
   op->result = vcode_add_reg(vtype_bool());
33,681✔
3409

3410
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
33,681✔
3411
                "arguments to cmp are not the same type");
3412

3413
   return op->result;
33,681✔
3414
}
3415

3416
vcode_reg_t emit_fcall(ident_t func, vcode_type_t type, vcode_type_t bounds,
34,291✔
3417
                       const vcode_reg_t *args, int nargs)
3418
{
3419
   op_t *o = vcode_add_op(VCODE_OP_FCALL);
34,291✔
3420
   o->func = func;
34,291✔
3421
   o->type = type;
34,291✔
3422
   for (int i = 0; i < nargs; i++)
120,566✔
3423
      vcode_add_arg(o, args[i]);
86,275✔
3424

3425
   for (int i = 0; i < nargs; i++)
120,566✔
3426
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
86,275✔
3427
                   "invalid argument to function");
3428

3429
   if (type == VCODE_INVALID_TYPE)
34,291✔
3430
      return (o->result = VCODE_INVALID_REG);
5,535✔
3431
   else {
3432
      o->result = vcode_add_reg(type);
28,756✔
3433

3434
      reg_t *rr = vcode_reg_data(o->result);
28,756✔
3435
      rr->bounds = bounds;
28,756✔
3436

3437
      return o->result;
28,756✔
3438
   }
3439
}
3440

3441
void emit_pcall(ident_t func, const vcode_reg_t *args, int nargs,
843✔
3442
                vcode_block_t resume_bb)
3443
{
3444
   op_t *o = vcode_add_op(VCODE_OP_PCALL);
843✔
3445
   o->func = func;
843✔
3446
   for (int i = 0; i < nargs; i++)
2,845✔
3447
      vcode_add_arg(o, args[i]);
2,002✔
3448

3449
   vcode_block_array_add(&(o->targets), resume_bb);
843✔
3450

3451
   for (int i = 0; i < nargs; i++)
2,845✔
3452
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
2,002✔
3453
                   "invalid argument to procedure");
3454

3455
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
843✔
3456
                "first argument to VHDL procedure must be context pointer");
3457
}
843✔
3458

3459
vcode_reg_t emit_syscall(ident_t func, vcode_type_t type, vcode_type_t bounds,
×
3460
                         vcode_reg_t locus, const vcode_reg_t *args, int nargs)
3461
{
3462
   op_t *o = vcode_add_op(VCODE_OP_SYSCALL);
×
3463
   o->func = func;
×
3464
   o->type = type;
×
3465
   vcode_add_arg(o, locus);
×
3466
   for (int i = 0; i < nargs; i++)
×
3467
      vcode_add_arg(o, args[i]);
×
3468

3469
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
×
3470
                "locus argument to syscall must be a debug locus");
3471

3472
   for (int i = 0; i < nargs; i++)
×
3473
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG, "invalid argument to syscall");
×
3474

3475
   if (type == VCODE_INVALID_TYPE)
×
3476
      return (o->result = VCODE_INVALID_REG);
×
3477
   else {
3478
      o->result = vcode_add_reg(type);
×
3479

3480
      reg_t *rr = vcode_reg_data(o->result);
×
3481
      rr->bounds = bounds;
×
3482

3483
      return o->result;
×
3484
   }
3485
}
3486

3487
vcode_reg_t emit_alloc(vcode_type_t type, vcode_type_t bounds,
7,284✔
3488
                       vcode_reg_t count)
3489
{
3490
   op_t *op = vcode_add_op(VCODE_OP_ALLOC);
7,284✔
3491
   op->type    = type;
7,284✔
3492
   op->result  = vcode_add_reg(vtype_pointer(type));
7,284✔
3493
   vcode_add_arg(op, count);
7,284✔
3494

3495
   const vtype_kind_t tkind = vtype_kind(type);
7,284✔
3496
   VCODE_ASSERT(tkind != VCODE_TYPE_CARRAY && tkind != VCODE_TYPE_UARRAY,
7,284✔
3497
                "alloca element type cannot be array");
3498
   VCODE_ASSERT(count != VCODE_INVALID_REG,
7,284✔
3499
                "alloca must have valid count argument");
3500

3501
   reg_t *r = vcode_reg_data(op->result);
7,284✔
3502
   r->bounds = bounds;
7,284✔
3503

3504
   return op->result;
7,284✔
3505
}
3506

3507
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
1,446,622✔
3508
{
3509
   // Reuse any previous constant in this block with the same type and value
3510
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
33,031,682✔
3511
      if (other->value == value && vtype_eq(type, other->type))
11,678,802✔
3512
         return other->result;
997,400✔
3513
   }
3514

3515
   op_t *op = vcode_add_op(VCODE_OP_CONST);
449,222✔
3516
   op->value  = value;
449,222✔
3517
   op->type   = type;
449,222✔
3518
   op->result = vcode_add_reg(type);
449,222✔
3519

3520
   vtype_kind_t type_kind = vtype_kind(type);
449,222✔
3521
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
449,222✔
3522
                "constant must have integer or offset type");
3523

3524
   reg_t *r = vcode_reg_data(op->result);
449,222✔
3525
   r->bounds = vtype_int(value, value);
449,222✔
3526

3527
   return op->result;
449,222✔
3528
}
3529

3530
vcode_reg_t emit_const_real(vcode_type_t type, double value)
66,690✔
3531
{
3532
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REAL) {
1,955,793✔
3533
      if (other->real == value && other->type == type)
907,873✔
3534
         return other->result;
25,295✔
3535
   }
3536

3537
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
41,395✔
3538
   op->real   = value;
41,395✔
3539
   op->type   = type;
41,395✔
3540
   op->result = vcode_add_reg(op->type);
41,395✔
3541

3542
   reg_t *r = vcode_reg_data(op->result);
41,395✔
3543
   r->bounds = vtype_real(value, value);
41,395✔
3544

3545
   return op->result;
41,395✔
3546
}
3547

3548
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
37,421✔
3549
{
3550
   vtype_kind_t kind = vtype_kind(type);
37,421✔
3551

3552
   // Reuse any previous operation in this block with the same arguments
3553
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
1,921,585✔
3554
      if (other->args.count != num)
151,430✔
3555
         continue;
90,291✔
3556
      else if (!vtype_eq(vcode_reg_type(other->result), type))
61,139✔
3557
         continue;
2,333✔
3558

3559
      bool match = true;
3560
      for (int i = 0; match && i < num; i++) {
422,388✔
3561
         if (other->args.items[i] != values[i])
363,582✔
3562
            match = false;
51,732✔
3563
      }
3564

3565
      if (match) return other->result;
58,806✔
3566
   }
3567

3568
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
30,347✔
3569
   op->result = vcode_add_reg(type);
30,347✔
3570

3571
   for (int i = 0; i < num; i++)
1,680,425✔
3572
      vcode_add_arg(op, values[i]);
1,650,078✔
3573

3574
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
30,347✔
3575
                "constant array must have constrained array type");
3576
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
30,347✔
3577
                vtype_size(type), num);
3578

3579
#ifdef DEBUG
3580
   vcode_type_t elem = vtype_elem(type);
30,347✔
3581
   for (int i = 0; i < num; i++) {
1,680,425✔
3582
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
1,650,078✔
3583
                   "wrong element type for item %d", i);
3584
      vcode_assert_const(values[i], "array");
1,650,078✔
3585
   }
3586
#endif
3587

3588
   reg_t *r = vcode_reg_data(op->result);
30,347✔
3589
   r->bounds = vtype_elem(type);
30,347✔
3590

3591
   return op->result;
30,347✔
3592
}
3593

3594
vcode_reg_t emit_const_rep(vcode_type_t type, vcode_reg_t value, int rep)
500✔
3595
{
3596
   // Reuse any previous operation in this block with the same arguments
3597
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REP) {
8,311✔
3598
      if (other->args.items[0] == value && other->value == rep)
607✔
3599
         return other->result;
198✔
3600
   }
3601

3602
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
302✔
3603
   op->value = rep;
302✔
3604
   vcode_add_arg(op, value);
302✔
3605

3606
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
302✔
3607
                "constant array must have constrained array type");
3608
   VCODE_ASSERT(rep >= 0, "repeat count must be non-negative");
302✔
3609

3610
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
302✔
3611

3612
   op->result = vcode_add_reg(type);
302✔
3613

3614
   reg_t *r = vcode_reg_data(op->result);
302✔
3615
   r->bounds = vtype_bounds(type);
302✔
3616

3617
   return op->result;
302✔
3618
}
3619

3620
vcode_reg_t emit_const_record(vcode_type_t type, vcode_reg_t *values, int num)
2,519✔
3621
{
3622
   // Reuse any previous constant in this block with the same type and value
3623
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_RECORD) {
38,739✔
3624
      if (other->args.count == num && vtype_eq(type, other->type)) {
1,534✔
3625
         bool same_regs = true;
3626
         for (int i = 0; same_regs && i < num; i++)
2,504✔
3627
            same_regs = other->args.items[i] == values[i];
1,454✔
3628

3629
         if (same_regs)
1,050✔
3630
            return other->result;
187✔
3631
      }
3632
   }
3633

3634
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
2,332✔
3635
   op->type   = type;
2,332✔
3636
   op->result = vcode_add_reg(type);
2,332✔
3637

3638
   for (int i = 0; i < num; i++)
8,332✔
3639
      vcode_add_arg(op, values[i]);
6,000✔
3640

3641
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
2,332✔
3642
                "constant record must have record type");
3643

3644
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
2,332✔
3645
                vtype_fields(type), num);
3646

3647
#ifdef DEBUG
3648
   for (int i = 0; i < num; i++) {
8,332✔
3649
      VCODE_ASSERT(vtype_eq(vtype_field(type, i), vcode_reg_type(values[i])),
6,000✔
3650
                   "wrong type for field %d", i);
3651
      vcode_assert_const(values[i], "record");
6,000✔
3652
   }
3653
#endif
3654

3655
   return op->result;
2,332✔
3656
}
3657

3658
vcode_reg_t emit_address_of(vcode_reg_t value)
38,988✔
3659
{
3660
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
1,995,808✔
3661
      if (other->args.items[0] == value)
152,430✔
3662
         return other->result;
7,069✔
3663
   }
3664

3665
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
31,919✔
3666
   vcode_add_arg(op, value);
31,919✔
3667

3668
   vcode_type_t type = vcode_reg_type(value);
31,919✔
3669
   VCODE_ASSERT(vtype_is_composite(type),
31,919✔
3670
                "address of argument must be record or array");
3671

3672
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
31,919✔
3673
      vcode_type_t elem = vtype_elem(type);
30,127✔
3674
      op->result = vcode_add_reg(vtype_pointer(elem));
30,127✔
3675

3676
      reg_t *rr = vcode_reg_data(op->result);
30,127✔
3677
      rr->bounds = elem;
30,127✔
3678

3679
      return op->result;
30,127✔
3680
   }
3681
   else
3682
      return (op->result = vcode_add_reg(vtype_pointer(type)));
1,792✔
3683
}
3684

3685
void emit_wait(vcode_block_t target)
12,821✔
3686
{
3687
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
12,821✔
3688
   vcode_add_target(op, target);
12,821✔
3689
}
12,821✔
3690

3691
void emit_jump(vcode_block_t target)
36,089✔
3692
{
3693
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
36,089✔
3694
   vcode_add_target(op, target);
36,089✔
3695

3696
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
36,089✔
3697
}
36,089✔
3698

3699
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
70,668✔
3700
                     vcode_var_flags_t flags)
3701
{
3702
   assert(active_unit != NULL);
70,668✔
3703

3704
   vcode_var_t var = active_unit->vars.count;
70,668✔
3705
   var_t *v = var_array_alloc(&(active_unit->vars));
70,668✔
3706
   memset(v, '\0', sizeof(var_t));
70,668✔
3707
   v->type     = type;
70,668✔
3708
   v->bounds   = bounds;
70,668✔
3709
   v->name     = name;
70,668✔
3710
   v->flags    = flags;
70,668✔
3711

3712
   return var;
70,668✔
3713
}
3714

3715
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
31,710✔
3716
{
3717
   assert(active_unit != NULL);
31,710✔
3718

3719
   param_t *p = param_array_alloc(&(active_unit->params));
31,710✔
3720
   memset(p, '\0', sizeof(param_t));
31,710✔
3721
   p->type   = type;
31,710✔
3722
   p->bounds = bounds;
31,710✔
3723
   p->name   = name;
31,710✔
3724
   p->reg    = vcode_add_reg(type);
31,710✔
3725

3726
   reg_t *rr = vcode_reg_data(p->reg);
31,710✔
3727
   rr->bounds = bounds;
31,710✔
3728

3729
   return p->reg;
31,710✔
3730
}
3731

3732
vcode_reg_t emit_load(vcode_var_t var)
60,230✔
3733
{
3734
   // Try scanning backwards through the block for another load or store to
3735
   // this variable
3736
   enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER;
60,230✔
3737
   vcode_reg_t fold = VCODE_INVALID_REG;
60,230✔
3738
   VCODE_FOR_EACH_OP(other) {
863,839✔
3739
      switch (state) {
819,892✔
3740
      case EAGER:
332,677✔
3741
         if (other->kind == VCODE_OP_LOAD && other->address == var)
332,677✔
3742
            return other->result;
3,806✔
3743
         else if (other->kind == VCODE_OP_STORE && other->address == var)
328,871✔
3744
            return other->args.items[0];
12,477✔
3745
         else if (other->kind == VCODE_OP_FCALL
316,394✔
3746
                  || other->kind == VCODE_OP_PCALL
316,394✔
3747
                  || other->kind == VCODE_OP_FILE_READ
3748
                  || other->kind == VCODE_OP_FILE_OPEN
3749
                  || other->kind == VCODE_OP_STORE_INDIRECT
3750
                  || other->kind == VCODE_OP_DEALLOCATE)
3751
            state = CONSERVATIVE;   // May write to variable
9,734✔
3752
         break;
3753

3754
      case CONSERVATIVE:
456,137✔
3755
         if (other->kind == VCODE_OP_LOAD && other->address == var
456,137✔
3756
             && fold == VCODE_INVALID_REG)
4,464✔
3757
            fold = other->result;
3,585✔
3758
         else if (other->kind == VCODE_OP_STORE && other->address == var
452,552✔
3759
                  && fold == VCODE_INVALID_REG)
2,408✔
3760
            fold = other->args.items[0];
2,266✔
3761
         else if (other->kind == VCODE_OP_INDEX && other->address == var)
450,286✔
3762
            state = UNSAFE;
3763
         else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0)
448,882✔
3764
            state = UNSAFE;   // Nested call captures variables
112✔
3765
         break;
3766

3767
      case UNSAFE:
3768
         break;
3769
      }
3770
   }
3771

3772
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
43,947✔
3773
      return fold;
3774

3775
   var_t *v = vcode_var_data(var);
38,478✔
3776

3777
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
38,478✔
3778
   op->address = var;
38,478✔
3779
   op->result  = vcode_add_reg(v->type);
38,478✔
3780

3781
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot load non-scalar type");
38,478✔
3782

3783
   reg_t *r = vcode_reg_data(op->result);
38,478✔
3784
   r->bounds = v->bounds;
38,478✔
3785

3786
   return op->result;
38,478✔
3787
}
3788

3789
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
93,242✔
3790
{
3791
   VCODE_FOR_EACH_OP(other) {
1,111,229✔
3792
      if (other->kind == VCODE_OP_LOAD_INDIRECT
1,048,187✔
3793
          && other->args.items[0] == reg) {
151,311✔
3794
         return other->result;
9,953✔
3795
      }
3796
      else if (other->kind == VCODE_OP_FCALL
1,038,234✔
3797
               || other->kind == VCODE_OP_PCALL
1,038,234✔
3798
               || other->kind == VCODE_OP_STORE
3799
               || other->kind == VCODE_OP_STORE_INDIRECT
3800
               || other->kind == VCODE_OP_MEMSET
3801
               || other->kind == VCODE_OP_COPY
3802
               || other->kind == VCODE_OP_FILE_READ)
3803
         break;   // May write to this pointer
3804
   }
3805

3806
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
83,289✔
3807
   vcode_add_arg(op, reg);
83,289✔
3808

3809
   vcode_type_t rtype = vcode_reg_type(reg);
83,289✔
3810

3811
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
83,289✔
3812
                "load indirect with non-pointer argument");
3813

3814
   vcode_type_t deref = vtype_pointed(rtype);
83,289✔
3815
   op->result = vcode_add_reg(deref);
83,289✔
3816

3817
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
83,289✔
3818

3819
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
83,289✔
3820

3821
   return op->result;
83,289✔
3822
}
3823

3824
void emit_store(vcode_reg_t reg, vcode_var_t var)
75,443✔
3825
{
3826
   // Any previous store to this variable in this block is dead
3827
   VCODE_FOR_EACH_OP(other) {
1,605,127✔
3828
      if (other->kind == VCODE_OP_STORE && other->address == var) {
1,544,162✔
3829
         other->kind = VCODE_OP_COMMENT;
291✔
3830
         other->comment =
582✔
3831
            xasprintf("Dead store to %s", istr(vcode_var_name(var)));
291✔
3832
         vcode_reg_array_resize(&(other->args), 0, VCODE_INVALID_REG);
291✔
3833
      }
3834
      else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL)
1,543,871✔
3835
         break;   // Needs to get variable for display
3836
      else if ((other->kind == VCODE_OP_INDEX || other->kind == VCODE_OP_LOAD)
1,537,596✔
3837
               && other->address == var)
37,576✔
3838
         break;   // Previous value may be used
3839
   }
3840

3841
   var_t *v = vcode_var_data(var);
75,443✔
3842
   reg_t *r = vcode_reg_data(reg);
75,443✔
3843

3844
   op_t *op = vcode_add_op(VCODE_OP_STORE);
75,443✔
3845
   vcode_add_arg(op, reg);
75,443✔
3846
   op->address = var;
75,443✔
3847

3848
   VCODE_ASSERT(vtype_eq(v->type, r->type),
75,443✔
3849
                "variable and stored value do not have same type");
3850
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
75,443✔
3851
}
75,443✔
3852

3853
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
14,927✔
3854
{
3855
   reg_t *p = vcode_reg_data(ptr);
14,927✔
3856
   reg_t *r = vcode_reg_data(reg);
14,927✔
3857

3858
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
14,927✔
3859
   vcode_add_arg(op, reg);
14,927✔
3860
   vcode_add_arg(op, ptr);
14,927✔
3861

3862
   VCODE_ASSERT(vtype_kind(p->type) == VCODE_TYPE_POINTER,
14,927✔
3863
                "store indirect target is not a pointer");
3864
   VCODE_ASSERT(vtype_eq(vtype_pointed(p->type), r->type),
14,927✔
3865
                "pointer and stored value do not have same type");
3866
   VCODE_ASSERT(vtype_is_scalar(r->type), "cannot store non-scalar type");
14,927✔
3867
}
14,927✔
3868

3869
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
67,033✔
3870
                              vcode_reg_t locus)
3871
{
3872
   // Reuse any previous operation in this block with the same arguments
3873
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,564,681✔
3874
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
77,090✔
3875
         return other->result;
5,878✔
3876
   }
3877

3878
   op_t *op = vcode_add_op(kind);
61,155✔
3879
   vcode_add_arg(op, lhs);
61,155✔
3880
   vcode_add_arg(op, rhs);
61,155✔
3881
   if (locus != VCODE_INVALID_REG)
61,155✔
3882
      vcode_add_arg(op, locus);
7,154✔
3883

3884
   op->result = vcode_add_reg(vcode_reg_type(lhs));
61,155✔
3885

3886
   vcode_type_t lhs_type = vcode_reg_type(lhs);
61,155✔
3887
   vcode_type_t rhs_type = vcode_reg_type(rhs);
61,155✔
3888

3889
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
61,155✔
3890
                "arguments to %s are not the same type", vcode_op_string(kind));
3891

3892
   return op->result;
61,155✔
3893
}
3894

3895
static vcode_reg_t emit_mul_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
48,066✔
3896
                               vcode_reg_t locus)
3897
{
3898
   int64_t lconst, rconst;
48,066✔
3899
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
48,066✔
3900
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
48,066✔
3901
   if (l_is_const && r_is_const)
48,066✔
3902
      return emit_const(vcode_reg_type(lhs), lconst * rconst);
22,207✔
3903
   else if (r_is_const && rconst == 1)
25,859✔
3904
      return lhs;
3905
   else if (l_is_const && lconst == 1)
4,851✔
3906
      return rhs;
3907
   else if ((r_is_const && rconst == 0) || (l_is_const && lconst == 0))
4,349✔
3908
      return emit_const(vcode_reg_type(lhs), 0);
54✔
3909

3910
   reg_t *lhs_r = vcode_reg_data(lhs);
4,295✔
3911
   reg_t *rhs_r = vcode_reg_data(rhs);
4,295✔
3912

3913
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
4,295✔
3914
   vtype_t *br = vcode_type_data(rhs_r->bounds);
4,295✔
3915

3916
   vcode_type_t vbounds;
4,295✔
3917
   if (vcode_reg_kind(lhs) == VCODE_TYPE_REAL) {
4,295✔
3918
      const double ll = bl->rlow * br->rlow;
556✔
3919
      const double lh = bl->rlow * br->rhigh;
556✔
3920
      const double hl = bl->rhigh * br->rlow;
556✔
3921
      const double hh = bl->rhigh * br->rhigh;
556✔
3922

3923
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
1,301✔
3924
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
1,387✔
3925

3926
      vbounds = vtype_real(min, max);
556✔
3927
   }
3928
   else {
3929
      const int64_t ll = smul64(bl->low, br->low);
3,739✔
3930
      const int64_t lh = smul64(bl->low, br->high);
3,739✔
3931
      const int64_t hl = smul64(bl->high, br->low);
3,739✔
3932
      const int64_t hh = smul64(bl->high, br->high);
3,739✔
3933

3934
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
3,739✔
3935
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
3,739✔
3936

3937
      if (min > INT64_MIN && max < INT64_MAX) {
3,739✔
3938
         vtype_repr_t repr = vtype_repr(lhs_r->type);
2,905✔
3939
         if (op == VCODE_OP_TRAP_MUL && vtype_clamp_to_repr(repr, &min, &max)) {
2,905✔
3940
            op = VCODE_OP_MUL;   // Cannot overflow
919✔
3941
            locus = VCODE_INVALID_REG;
919✔
3942
         }
3943
      }
3944

3945
      vbounds = vtype_int(min, max);
3,739✔
3946
   }
3947

3948
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
4,295✔
3949

3950
   if (vbounds != VCODE_INVALID_TYPE)
4,295✔
3951
      vcode_reg_data(reg)->bounds = vbounds;
4,295✔
3952

3953
   return reg;
3954
}
3955

3956
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
45,253✔
3957
{
3958
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
45,253✔
3959
}
3960

3961
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
2,813✔
3962
{
3963
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
2,813✔
3964

3965
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
2,813✔
3966
                "trapping add may only be used with integer types");
3967

3968
   return result;
2,813✔
3969
}
3970

3971
vcode_reg_t emit_div(vcode_reg_t lhs, vcode_reg_t rhs)
1,750✔
3972
{
3973
   int64_t lconst, rconst;
1,750✔
3974
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
1,750✔
3975
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
1,750✔
3976
   if (l_is_const && r_is_const && rconst != 0)
1,750✔
3977
      return emit_const(vcode_reg_type(lhs), lconst / rconst);
30✔
3978
   else if (r_is_const && rconst == 1)
1,720✔
3979
      return lhs;
3980

3981
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
1,717✔
3982

3983
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
1,717✔
3984

3985
   if (bl->kind == VCODE_TYPE_INT && r_is_const && rconst != 0) {
1,717✔
3986
      reg_t *rr = vcode_reg_data(reg);
1,324✔
3987
      rr->bounds = vtype_int(bl->low / rconst, bl->high / rconst);
1,324✔
3988
   }
3989
   else if (bl->kind == VCODE_TYPE_REAL) {
393✔
3990
      reg_t *rr = vcode_reg_data(reg);
317✔
3991
      rr->bounds = vtype_real(-INFINITY, INFINITY);
317✔
3992
   }
3993

3994
   return reg;
3995
}
3996

3997
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
141✔
3998
{
3999
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
141✔
4000
}
4001

4002
vcode_reg_t emit_trap_exp(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
411✔
4003
{
4004
   int64_t rconst;
411✔
4005
   if (vcode_reg_const(rhs, &rconst)) {
411✔
4006
      if (rconst == 0)
77✔
4007
         return emit_const(vcode_reg_type(lhs), 1);
31✔
4008
      else if (rconst == 1)
46✔
4009
         return lhs;
4010
   }
4011

4012
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
379✔
4013

4014
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
379✔
4015
                "trapping exp may only be used with integer types");
4016

4017
   return result;
4018
}
4019

4020
vcode_reg_t emit_mod(vcode_reg_t lhs, vcode_reg_t rhs)
199✔
4021
{
4022
   int64_t lconst, rconst;
199✔
4023
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
199✔
4024
       && lconst > 0 && rconst > 0)
15✔
4025
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
3✔
4026

4027
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
196✔
4028
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
196✔
4029

4030
   if (bl->low >= 0 && br->low >= 0) {
196✔
4031
      // If both arguments are non-negative then rem is equivalent and
4032
      // cheaper to compute
4033
      vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
66✔
4034

4035
      reg_t *rr = vcode_reg_data(reg);
66✔
4036
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
66✔
4037

4038
      return reg;
66✔
4039
   }
4040
   else
4041
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
130✔
4042
}
4043

4044
vcode_reg_t emit_rem(vcode_reg_t lhs, vcode_reg_t rhs)
873✔
4045
{
4046
   int64_t lconst, rconst;
873✔
4047
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
873✔
4048
       && lconst > 0 && rconst > 0)
2✔
4049
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
×
4050

4051
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
873✔
4052

4053
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
873✔
4054
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
873✔
4055

4056
   if (bl->low >= 0 && br->low >= 0) {
873✔
4057
      reg_t *rr = vcode_reg_data(reg);
489✔
4058
      rr->bounds = vtype_int(0, br->high - 1);
489✔
4059
   }
4060

4061
   return reg;
4062
}
4063

4064
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
47,997✔
4065
                               vcode_reg_t locus)
4066
{
4067
   int64_t lconst, rconst;
47,997✔
4068
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
47,997✔
4069
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
47,997✔
4070
   if (l_is_const && r_is_const)
47,997✔
4071
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
11,958✔
4072
   else if (r_is_const && rconst == 0)
36,039✔
4073
      return lhs;
4074
   else if (l_is_const && lconst == 0)
35,911✔
4075
      return rhs;
4076

4077
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
19,842✔
4078
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
19,842✔
4079
      reg_t *lhs_r = vcode_reg_data(lhs);
19,518✔
4080
      reg_t *rhs_r = vcode_reg_data(rhs);
19,518✔
4081

4082
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
19,518✔
4083
      vtype_t *br = vcode_type_data(rhs_r->bounds);
19,518✔
4084

4085
      int64_t rbl = sadd64(bl->low, br->low);
19,518✔
4086
      int64_t rbh = sadd64(bl->high, br->high);
19,518✔
4087

4088
      if (rbl > INT64_MIN && rbh < INT64_MAX) {
19,518✔
4089
         vtype_repr_t repr = vtype_repr(lhs_r->type);
11,294✔
4090
         if (op == VCODE_OP_TRAP_ADD && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
11,294✔
4091
            op = VCODE_OP_ADD;   // Cannot overflow
1,460✔
4092
            locus = VCODE_INVALID_REG;
1,460✔
4093
         }
4094
      }
4095

4096
      vbounds = vtype_int(rbl, rbh);
19,518✔
4097
   }
4098

4099
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
19,842✔
4100

4101
   if (vbounds != VCODE_INVALID_TYPE)
19,842✔
4102
      vcode_reg_data(reg)->bounds = vbounds;
19,518✔
4103

4104
   return reg;
4105
}
4106

4107
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
41,750✔
4108
{
4109
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
41,750✔
4110
}
4111

4112
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
6,247✔
4113
{
4114
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
6,247✔
4115

4116
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
6,247✔
4117
                "trapping add may only be used with integer types");
4118

4119
   return result;
6,247✔
4120
}
4121

4122
static vcode_reg_t emit_sub_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
46,165✔
4123
                               vcode_reg_t locus)
4124
{
4125
   int64_t lconst, rconst;
46,165✔
4126
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
46,165✔
4127
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
46,165✔
4128
   if (l_is_const && r_is_const)
46,165✔
4129
      return emit_const(vcode_reg_type(lhs), lconst - rconst);
8,306✔
4130
   else if (r_is_const && rconst == 0)
37,859✔
4131
      return lhs;
4132
   else if (l_is_const && lconst == 0)
33,490✔
4133
      return emit_neg(rhs);
840✔
4134

4135
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
32,650✔
4136
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
32,650✔
4137
      reg_t *lhs_r = vcode_reg_data(lhs);
32,355✔
4138
      reg_t *rhs_r = vcode_reg_data(rhs);
32,355✔
4139

4140
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
32,355✔
4141
      vtype_t *br = vcode_type_data(rhs_r->bounds);
32,355✔
4142

4143
      int64_t rbl = ssub64(bl->low, br->high);
32,355✔
4144
      int64_t rbh = ssub64(bl->high, br->low);
32,355✔
4145

4146
      if (rbl > INT64_MIN && rbh < INT64_MAX) {
32,355✔
4147
         vtype_repr_t repr = vtype_repr(lhs_r->type);
31,513✔
4148
         if (op == VCODE_OP_TRAP_SUB && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
31,513✔
4149
            op = VCODE_OP_SUB;   // Cannot overflow
4,954✔
4150
            locus = VCODE_INVALID_REG;
4,954✔
4151
         }
4152
      }
4153

4154
      vbounds = vtype_int(rbl, rbh);
32,355✔
4155
   }
4156

4157
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
32,650✔
4158

4159
   if (vbounds != VCODE_INVALID_TYPE)
32,650✔
4160
      vcode_reg_data(reg)->bounds = vbounds;
32,355✔
4161

4162
   return reg;
4163
}
4164

4165
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
39,055✔
4166
{
4167
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
39,055✔
4168
}
4169

4170
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
7,110✔
4171
{
4172
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
7,110✔
4173

4174
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
7,110✔
4175
                "trapping sub may only be used with integer types");
4176

4177
   return result;
7,110✔
4178
}
4179

4180
static void vcode_calculate_var_index_type(op_t *op, var_t *var)
70,208✔
4181
{
4182
   switch (vtype_kind(var->type)) {
70,208✔
4183
   case VCODE_TYPE_CARRAY:
21,600✔
4184
      op->type = vtype_pointer(vtype_elem(var->type));
21,600✔
4185
      op->result = vcode_add_reg(op->type);
21,600✔
4186
      vcode_reg_data(op->result)->bounds = vtype_bounds(var->type);
21,600✔
4187
      break;
21,600✔
4188

4189
   case VCODE_TYPE_RECORD:
5,761✔
4190
      op->type = vtype_pointer(var->type);
5,761✔
4191
      op->result = vcode_add_reg(op->type);
5,761✔
4192
      break;
5,761✔
4193

4194
   case VCODE_TYPE_INT:
42,847✔
4195
   case VCODE_TYPE_FILE:
4196
   case VCODE_TYPE_ACCESS:
4197
   case VCODE_TYPE_REAL:
4198
   case VCODE_TYPE_UARRAY:
4199
   case VCODE_TYPE_POINTER:
4200
   case VCODE_TYPE_SIGNAL:
4201
   case VCODE_TYPE_CONTEXT:
4202
   case VCODE_TYPE_OFFSET:
4203
   case VCODE_TYPE_TRIGGER:
4204
   case VCODE_TYPE_RESOLUTION:
4205
      op->type = vtype_pointer(var->type);
42,847✔
4206
      op->result = vcode_add_reg(op->type);
42,847✔
4207
      vcode_reg_data(op->result)->bounds = var->bounds;
42,847✔
4208
      break;
42,847✔
4209

4210
   default:
4211
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4212
                   istr(var->name));
4213
   }
4214
}
70,208✔
4215

4216
vcode_reg_t emit_index(vcode_var_t var, vcode_reg_t offset)
34,083✔
4217
{
4218
   // Try to find a previous index of this var by this offset
4219
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_INDEX) {
1,391,541✔
4220
      if (other->address == var
83,607✔
4221
          && ((offset == VCODE_INVALID_REG && other->args.count == 0)
7,217✔
4222
              || (offset != VCODE_INVALID_REG
×
4223
                  && other->args.items[0] == offset)))
×
4224
         return other->result;
7,217✔
4225
   }
4226

4227
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
26,866✔
4228
   op->address = var;
26,866✔
4229

4230
   if (offset != VCODE_INVALID_REG)
26,866✔
4231
      vcode_add_arg(op, offset);
×
4232

4233
   vcode_calculate_var_index_type(op, vcode_var_data(var));
26,866✔
4234

4235
   if (offset != VCODE_INVALID_REG)
26,866✔
4236
      VCODE_ASSERT(vtype_kind(vcode_reg_type(offset)) == VCODE_TYPE_OFFSET,
×
4237
                   "index offset r%d does not have offset type", offset);
4238

4239
   return op->result;
26,866✔
4240
}
4241

4242
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
242,938✔
4243
{
4244
   if (vtype_eq(vcode_reg_type(reg), type))
242,938✔
4245
      return reg;
242,938✔
4246

4247
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
81,795✔
4248
   vtype_kind_t to   = vtype_kind(type);
81,795✔
4249

4250
   const bool integral =
163,590✔
4251
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
81,795✔
4252
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
81,795✔
4253

4254
   int64_t value;
81,795✔
4255
   if (integral && vcode_reg_const(reg, &value))
81,795✔
4256
      return emit_const(type, value);
12,743✔
4257

4258
   // Try to find a previous cast of this register to this type
4259
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CAST) {
1,367,539✔
4260
      if (vtype_eq(other->type, type) && other->args.items[0] == reg)
139,627✔
4261
         return other->result;
15,345✔
4262
   }
4263

4264
   op_t *op = vcode_add_op(VCODE_OP_CAST);
53,707✔
4265
   vcode_add_arg(op, reg);
53,707✔
4266
   op->type   = type;
53,707✔
4267
   op->result = vcode_add_reg(type);
53,707✔
4268

4269
   static const vcode_type_t allowed[][2] = {
53,707✔
4270
      { VCODE_TYPE_INT,    VCODE_TYPE_OFFSET  },
4271
      { VCODE_TYPE_OFFSET, VCODE_TYPE_INT     },
4272
      { VCODE_TYPE_INT,    VCODE_TYPE_INT     },
4273
      { VCODE_TYPE_INT,    VCODE_TYPE_REAL    },
4274
      { VCODE_TYPE_REAL,   VCODE_TYPE_INT     },
4275
      { VCODE_TYPE_REAL,   VCODE_TYPE_REAL    },
4276
      { VCODE_TYPE_ACCESS, VCODE_TYPE_ACCESS  },
4277
   };
4278

4279
   if (integral) {
53,707✔
4280
      vtype_t *vt = vcode_type_data(type);
52,865✔
4281
      int64_t low = vt->low, high = vt->high;
52,865✔
4282

4283
      vtype_t *rt = vcode_type_data(vcode_reg_bounds(reg));
52,865✔
4284
      low = MAX(low, rt->low);
52,865✔
4285
      high = MIN(high, rt->high);
52,865✔
4286

4287
      if (bounds != VCODE_INVALID_REG) {
52,865✔
4288
         vtype_t *bt = vcode_type_data(bounds);
31,880✔
4289
         low = MAX(low, bt->low);
31,880✔
4290
         high = MIN(high, bt->high);
31,880✔
4291
      }
4292

4293
      reg_t *rr = vcode_reg_data(op->result);
52,865✔
4294
      rr->bounds = vtype_int(low, high);
52,865✔
4295
   }
4296
   else if (bounds != VCODE_INVALID_REG)
842✔
4297
      vcode_reg_data(op->result)->bounds = bounds;
842✔
4298

4299
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
94,611✔
4300
      if (from == allowed[i][0] && to == allowed[i][1])
94,611✔
4301
         return op->result;
53,707✔
4302
   }
4303

4304
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4305
}
4306

4307
void emit_return(vcode_reg_t reg)
55,203✔
4308
{
4309
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
55,203✔
4310
   if (reg != VCODE_INVALID_REG) {
55,203✔
4311
      vcode_add_arg(op, reg);
24,534✔
4312

4313
      const vtype_kind_t rkind = vcode_reg_kind(reg);
24,534✔
4314
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY)
24,534✔
4315
         vcode_heap_allocate(reg);
4,551✔
4316

4317
      VCODE_ASSERT(active_unit->kind == VCODE_UNIT_FUNCTION
24,534✔
4318
                   || active_unit->kind == VCODE_UNIT_THUNK
4319
                   || active_unit->kind == VCODE_UNIT_PROPERTY,
4320
                   "returning value fron non-function unit");
4321
      VCODE_ASSERT((active_unit->kind == VCODE_UNIT_PROPERTY
24,534✔
4322
                    && rkind == VCODE_TYPE_INT)
4323
                   || vtype_eq(active_unit->result, vcode_reg_type(reg))
4324
                   || (vtype_kind(active_unit->result) == VCODE_TYPE_ACCESS
4325
                       && rkind == VCODE_TYPE_ACCESS),
4326
                   "return value incorrect type");
4327
   }
4328
}
55,203✔
4329

4330
void emit_sched_waveform(vcode_reg_t nets, vcode_reg_t nnets,
9,208✔
4331
                         vcode_reg_t values, vcode_reg_t reject,
4332
                         vcode_reg_t after)
4333
{
4334
   int64_t nconst;
9,208✔
4335
   if (vcode_reg_const(nnets, &nconst) && nconst == 0) {
9,208✔
4336
      emit_comment("Skip empty waveform");
9✔
4337
      return;
9✔
4338
   }
4339

4340
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
9,199✔
4341
   vcode_add_arg(op, nets);
9,199✔
4342
   vcode_add_arg(op, nnets);
9,199✔
4343
   vcode_add_arg(op, values);
9,199✔
4344
   vcode_add_arg(op, reject);
9,199✔
4345
   vcode_add_arg(op, after);
9,199✔
4346

4347
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
9,199✔
4348
                "sched_waveform target is not signal");
4349
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
9,199✔
4350
                "sched_waveform net count is not offset type");
4351
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
9,199✔
4352
                "signal cannot be values argument for sched_waveform");
4353
}
4354

4355
void emit_force(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t values)
70✔
4356
{
4357
   op_t *op = vcode_add_op(VCODE_OP_FORCE);
70✔
4358
   vcode_add_arg(op, nets);
70✔
4359
   vcode_add_arg(op, nnets);
70✔
4360
   vcode_add_arg(op, values);
70✔
4361

4362
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
70✔
4363
                "force target is not signal");
4364
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
70✔
4365
                "force net count is not offset type");
4366
}
70✔
4367

4368
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
42✔
4369
{
4370
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
42✔
4371
   vcode_add_arg(op, nets);
42✔
4372
   vcode_add_arg(op, nnets);
42✔
4373

4374
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
42✔
4375
                "release target is not signal");
4376
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
42✔
4377
                "release net count is not offset type");
4378
}
42✔
4379

4380
void emit_disconnect(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t reject,
24✔
4381
                     vcode_reg_t after)
4382
{
4383
   op_t *op = vcode_add_op(VCODE_OP_DISCONNECT);
24✔
4384
   vcode_add_arg(op, nets);
24✔
4385
   vcode_add_arg(op, nnets);
24✔
4386
   vcode_add_arg(op, reject);
24✔
4387
   vcode_add_arg(op, after);
24✔
4388

4389
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
24✔
4390
                "disconnect target is not signal");
4391
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
24✔
4392
                "disconnect net count is not offset type");
4393
}
24✔
4394

4395
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
32,720✔
4396
{
4397
   int64_t tconst;
32,720✔
4398
   if (vcode_reg_const(test, &tconst)) {
32,720✔
4399
      emit_jump(!!tconst ? btrue : bfalse);
3,832✔
4400
      return;
1,955✔
4401
   }
4402

4403
   op_t *op = vcode_add_op(VCODE_OP_COND);
30,765✔
4404
   vcode_add_arg(op, test);
30,765✔
4405
   vcode_add_target(op, btrue);
30,765✔
4406
   vcode_add_target(op, bfalse);
30,765✔
4407

4408
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
30,765✔
4409
                "cond test is not a bool");
4410
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
30,765✔
4411
                "invalid cond targets");
4412
}
4413

4414
vcode_reg_t emit_neg(vcode_reg_t lhs)
6,971✔
4415
{
4416
   int64_t lconst;
6,971✔
4417
   if (vcode_reg_const(lhs, &lconst))
6,971✔
4418
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4419

4420
   op_t *op = vcode_add_op(VCODE_OP_NEG);
6,971✔
4421
   vcode_add_arg(op, lhs);
6,971✔
4422
   op->result = vcode_add_reg(vcode_reg_type(lhs));
6,971✔
4423

4424
   return op->result;
6,971✔
4425
}
4426

4427
vcode_reg_t emit_trap_neg(vcode_reg_t lhs, vcode_reg_t locus)
467✔
4428
{
4429
   int64_t lconst;
467✔
4430
   if (vcode_reg_const(lhs, &lconst) && lconst >= 0)
467✔
4431
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4432
   else if (vcode_type_data(vcode_reg_data(lhs)->bounds)->low >= 0)
467✔
4433
      return emit_neg(lhs);   // Cannot overflow
210✔
4434

4435
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
257✔
4436
   vcode_add_arg(op, lhs);
257✔
4437
   vcode_add_arg(op, locus);
257✔
4438

4439
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
257✔
4440
                "locus argument to trap neg must be a debug locus");
4441
   VCODE_ASSERT(vcode_reg_kind(lhs) == VCODE_TYPE_INT,
257✔
4442
                "trapping neg may only be used with integer types");
4443

4444
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
257✔
4445
}
4446

4447
vcode_reg_t emit_abs(vcode_reg_t lhs)
686✔
4448
{
4449
   int64_t lconst;
686✔
4450
   if (vcode_reg_const(lhs, &lconst))
686✔
4451
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4452

4453
   op_t *op = vcode_add_op(VCODE_OP_ABS);
685✔
4454
   vcode_add_arg(op, lhs);
685✔
4455
   op->result = vcode_add_reg(vcode_reg_type(lhs));
685✔
4456

4457
   return op->result;
685✔
4458
}
4459

4460
void emit_comment(const char *fmt, ...)
77,756✔
4461
{
4462
#ifndef NDEBUG
4463
   va_list ap;
77,756✔
4464
   va_start(ap, fmt);
77,756✔
4465

4466
   char *buf = xvasprintf(fmt, ap);
77,756✔
4467
   for (char *p = buf + strlen(buf) - 1;
77,756✔
4468
        p >= buf && isspace_iso88591(*p); p--)
77,756✔
4469
      *p = '\0';
×
4470

4471
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
77,756✔
4472
   va_end(ap);
77,756✔
4473
#endif
4474
}
77,756✔
4475

4476
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
18,386✔
4477
                        vcode_reg_t rfalse)
4478
{
4479
   int64_t tconst;
18,386✔
4480
   if (vcode_reg_const(test, &tconst))
18,386✔
4481
      return !!tconst ? rtrue : rfalse;
4,709✔
4482
   else if (rtrue == rfalse)
13,677✔
4483
      return rtrue;
4484

4485
   // Find a previous identical select
4486
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
297,125✔
4487
      if (other->args.items[0] == test && other->args.items[1] == rtrue
10,863✔
4488
          && other->args.items[2] == rfalse)
649✔
4489
         return other->result;
556✔
4490
   }
4491

4492
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
12,946✔
4493
   vcode_add_arg(op, test);
12,946✔
4494
   vcode_add_arg(op, rtrue);
12,946✔
4495
   vcode_add_arg(op, rfalse);
12,946✔
4496
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
12,946✔
4497

4498
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
12,946✔
4499
                "select test must have bool type");
4500
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
12,946✔
4501
                "select arguments are not the same type");
4502

4503
   return op->result;
12,946✔
4504
}
4505

4506
static vcode_reg_t emit_logical_identity(vcode_op_t op, vcode_reg_t reg, bool b)
442✔
4507
{
4508
   switch (op) {
442✔
4509
   case VCODE_OP_AND:  return b ? reg : emit_const(vtype_bool(), 0);
45✔
4510
   case VCODE_OP_OR:   return b ? emit_const(vtype_bool(), 1) : reg;
349✔
4511
   case VCODE_OP_XOR:  return b ? emit_not(reg) : reg;
12✔
4512
   case VCODE_OP_XNOR: return b ? reg : emit_not(reg);
12✔
4513
   case VCODE_OP_NAND: return b ? emit_not(reg) : emit_const(vtype_bool(), 1);
12✔
4514
   case VCODE_OP_NOR:  return b ? emit_const(vtype_bool(), 0) : emit_not(reg);
12✔
4515
   default:
×
4516
      fatal_trace("missing logicial identity for %s", vcode_op_string(op));
4517
   }
4518
}
4519

4520
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
7,415✔
4521
{
4522
   vcode_type_t vtbool = vtype_bool();
7,415✔
4523

4524
   int64_t lconst, rconst;
7,415✔
4525
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
7,415✔
4526
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
7,415✔
4527
   if (l_is_const && r_is_const) {
7,415✔
4528
      switch (op) {
6✔
4529
      case VCODE_OP_AND:  return emit_const(vtbool, lconst && rconst);
×
4530
      case VCODE_OP_OR:   return emit_const(vtbool, lconst || rconst);
×
4531
      case VCODE_OP_XOR:  return emit_const(vtbool, lconst ^ rconst);
×
4532
      case VCODE_OP_XNOR: return emit_const(vtbool, !(lconst ^ rconst));
6✔
4533
      case VCODE_OP_NAND: return emit_const(vtbool, !(lconst && rconst));
×
4534
      case VCODE_OP_NOR:  return emit_const(vtbool, !(lconst || rconst));
×
4535
      default:
×
4536
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
4537
      }
4538
   }
4539
   else if (l_is_const)
7,409✔
4540
      return emit_logical_identity(op, rhs, !!lconst);
342✔
4541
   else if (r_is_const)
7,067✔
4542
      return emit_logical_identity(op, lhs, !!rconst);
100✔
4543
   else if (lhs == rhs) {
6,967✔
4544
      switch (op) {
27✔
4545
      case VCODE_OP_AND:
4546
      case VCODE_OP_OR:
4547
         return lhs;
4548
      case VCODE_OP_NAND:
6✔
4549
      case VCODE_OP_NOR:
4550
         return emit_not(lhs);
6✔
4551
      case VCODE_OP_XOR:
3✔
4552
         return emit_const(vtbool, 0);
3✔
4553
      case VCODE_OP_XNOR:
×
4554
         return emit_const(vtbool, 1);
×
4555
      default:
×
4556
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
4557
      }
4558
   }
4559

4560
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
6,940✔
4561

4562
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
6,940✔
4563
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4564
                "arguments to %s are not boolean", vcode_op_string(op));
4565

4566
   return result;
4567
}
4568

4569
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
2,418✔
4570
{
4571
   return emit_logical(VCODE_OP_OR, lhs, rhs);
2,418✔
4572
}
4573

4574
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
4,761✔
4575
{
4576
   return emit_logical(VCODE_OP_AND, lhs, rhs);
4,761✔
4577
}
4578

4579
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
52✔
4580
{
4581
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
52✔
4582
}
4583

4584
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
53✔
4585
{
4586
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
53✔
4587
}
4588

4589
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
73✔
4590
{
4591
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
73✔
4592
}
4593

4594
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
58✔
4595
{
4596
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
58✔
4597
}
4598

4599
vcode_reg_t emit_not(vcode_reg_t arg)
2,502✔
4600
{
4601
   int64_t cval;
2,502✔
4602
   if (vcode_reg_const(arg, &cval))
2,502✔
4603
      return emit_const(vtype_bool(), !cval);
27✔
4604

4605
   op_t *op = vcode_add_op(VCODE_OP_NOT);
2,475✔
4606
   vcode_add_arg(op, arg);
2,475✔
4607

4608
   vcode_type_t vtbool = vtype_bool();
2,475✔
4609
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
2,475✔
4610
                "argument to not is not boolean");
4611

4612
   return (op->result = vcode_add_reg(vtbool));
2,475✔
4613
}
4614

4615
vcode_reg_t emit_wrap(vcode_reg_t data, const vcode_dim_t *dims, int ndims)
46,844✔
4616
{
4617
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_WRAP) {
1,730,890✔
4618
      if (other->args.count == ndims*3 + 1 && other->args.items[0] == data) {
155,900✔
4619
         bool match = true;
4620
         for (int i = 0; match && i < ndims; i++) {
22,394✔
4621
            match = other->args.items[i*3 + 1] == dims[i].left
11,229✔
4622
               && other->args.items[i*3 + 2] == dims[i].right
9,034✔
4623
               && other->args.items[i*3 + 3] == dims[i].dir;
19,996✔
4624
         }
4625
         if (match)
11,165✔
4626
            return other->result;
8,703✔
4627
      }
4628
   }
4629

4630
   op_t *op = vcode_add_op(VCODE_OP_WRAP);
38,141✔
4631
   vcode_add_arg(op, data);
38,141✔
4632
   for (int i = 0; i < ndims; i++) {
76,940✔
4633
      vcode_add_arg(op, dims[i].left);
38,799✔
4634
      vcode_add_arg(op, dims[i].right);
38,799✔
4635
      vcode_add_arg(op, dims[i].dir);
38,799✔
4636
   }
4637

4638
   vcode_type_t ptr_type = vcode_reg_type(data);
38,141✔
4639
   const vtype_kind_t ptrkind = vtype_kind(ptr_type);
38,141✔
4640
   VCODE_ASSERT(ptrkind == VCODE_TYPE_POINTER || ptrkind == VCODE_TYPE_SIGNAL,
38,141✔
4641
                "wrapped data is not pointer or signal");
4642

4643
#ifdef DEBUG
4644
   for (int i = 0; i < ndims; i++) {
76,940✔
4645
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].left)),
38,799✔
4646
                   "dimension %d left bound must be scalar", i + 1);
4647
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].right)),
38,799✔
4648
                   "dimension %d right bound must be scalar", i + 1);
4649
      VCODE_ASSERT(vtype_eq(vtype_bool(), vcode_reg_type(dims[i].dir)),
38,799✔
4650
                   "dimension %d direction must be bool", i + 1);
4651
   }
4652
#endif
4653

4654
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
76,282✔
4655
      ? vtype_pointed(ptr_type) : ptr_type;
38,141✔
4656

4657
   op->result = vcode_add_reg(
38,141✔
4658
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4659

4660
   return op->result;
38,141✔
4661
}
4662

4663
static vcode_reg_t emit_uarray_op(vcode_op_t o, vcode_type_t rtype,
103,375✔
4664
                                  vcode_reg_t array, unsigned dim,
4665
                                  unsigned arg_index)
4666
{
4667
   // Reuse any previous operation in this block with the same arguments
4668
   VCODE_FOR_EACH_OP(other) {
1,177,301✔
4669
      if (other->kind == o && other->args.items[0] == array && other->dim == dim
1,132,517✔
4670
          && (rtype == VCODE_INVALID_TYPE
23,567✔
4671
              || vtype_eq(rtype, vcode_reg_type(other->result))))
10,223✔
4672
         return other->result;
23,567✔
4673
      else if (other->kind == VCODE_OP_WRAP && other->result == array)
1,108,950✔
4674
         return other->args.items[1 + (dim * 3) + arg_index];
35,024✔
4675
   }
4676

4677
   op_t *op = vcode_add_op(o);
44,784✔
4678
   vcode_add_arg(op, array);
44,784✔
4679
   op->dim = dim;
44,784✔
4680

4681
   vcode_type_t atype = vcode_reg_type(array);
44,784✔
4682
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
44,784✔
4683
                "cannot use %s with non-uarray type", vcode_op_string(o));
4684

4685
   vtype_t *vt = vcode_type_data(atype);
44,784✔
4686
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
44,784✔
4687

4688
   if (rtype == VCODE_INVALID_TYPE)
44,784✔
4689
      rtype = vtype_offset();
28,917✔
4690

4691
   return (op->result = vcode_add_reg(rtype));
44,784✔
4692
}
4693

4694
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
38,128✔
4695
{
4696
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
38,128✔
4697
                         array, dim, 0);
4698
}
4699

4700
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
27,381✔
4701
{
4702
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
27,381✔
4703
                         array, dim, 1);
4704
}
4705

4706
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
37,866✔
4707
{
4708
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
37,866✔
4709
                         array, dim, 2);
4710
}
4711

4712
vcode_reg_t emit_uarray_len(vcode_reg_t array, unsigned dim)
46,084✔
4713
{
4714
   VCODE_FOR_EACH_OP(other) {
669,281✔
4715
      if (other->kind == VCODE_OP_UARRAY_LEN) {
647,619✔
4716
         if (other->args.items[0] == array && other->dim == dim)
41,054✔
4717
            return other->result;
9,611✔
4718
      }
4719
      else if (other->kind == VCODE_OP_WRAP && other->result == array) {
606,565✔
4720
         VCODE_ASSERT(dim < (other->args.count - 1) / 3,
14,811✔
4721
                      "array dimension %d out of bounds", dim);
4722

4723
         vcode_reg_t left_reg = other->args.items[dim * 3 + 1];
14,811✔
4724
         vcode_reg_t right_reg = other->args.items[dim * 3 + 2];
14,811✔
4725
         vcode_reg_t dir_reg = other->args.items[dim * 3 + 3];
14,811✔
4726
         return emit_range_length(left_reg, right_reg, dir_reg);
14,811✔
4727
      }
4728
   }
4729

4730
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
21,662✔
4731
   vcode_add_arg(op, array);
21,662✔
4732
   op->dim = dim;
21,662✔
4733

4734
   vcode_type_t atype = vcode_reg_type(array);
21,662✔
4735
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
21,662✔
4736
                "cannot use uarray len with non-uarray type");
4737

4738
   vtype_t *vt = vcode_type_data(atype);
21,662✔
4739
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
21,662✔
4740

4741
   op->result = vcode_add_reg(vtype_offset());
21,662✔
4742

4743
   reg_t *rr = vcode_reg_data(op->result);
21,662✔
4744
   rr->bounds = vtype_int(0, INT64_MAX);
21,662✔
4745

4746
   return op->result;
21,662✔
4747
}
4748

4749
vcode_reg_t emit_unwrap(vcode_reg_t array)
35,585✔
4750
{
4751
   VCODE_FOR_EACH_OP(other) {
1,546,461✔
4752
      if (other->kind == VCODE_OP_WRAP && other->result == array)
1,521,122✔
4753
         return other->args.items[0];
8,499✔
4754
      else if (other->kind == VCODE_OP_UNWRAP && other->args.items[0] == array)
1,512,623✔
4755
         return other->result;
1,747✔
4756
   }
4757

4758
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
25,339✔
4759
   vcode_add_arg(op, array);
25,339✔
4760

4761
   vtype_t *vt = vcode_type_data(vcode_reg_type(array));
25,339✔
4762
   VCODE_ASSERT(vt->kind == VCODE_TYPE_UARRAY,
25,339✔
4763
                "unwrap can only only be used with uarray types");
4764

4765
   vcode_type_t elem = vt->elem;
25,339✔
4766

4767
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
25,339✔
4768
      ? elem : vtype_pointer(elem);
25,339✔
4769

4770
   op->result = vcode_add_reg(rtype);
25,339✔
4771

4772
   reg_t *rr = vcode_reg_data(op->result);
25,339✔
4773
   rr->bounds = elem;
25,339✔
4774

4775
   return op->result;
25,339✔
4776
}
4777

4778
vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right,
29,534✔
4779
                            vcode_reg_t dir)
4780
{
4781
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_NULL) {
1,431,327✔
4782
      if (other->args.items[0] == left
×
4783
          && other->args.items[1] == right
×
4784
          && other->args.items[2] == dir)
×
4785
         return other->result;
×
4786
   }
4787

4788
   int64_t dir_const;
29,534✔
4789
   if (vcode_reg_const(dir, &dir_const)) {
29,534✔
4790
      vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
26,537✔
4791
      vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
26,537✔
4792

4793
      if (dir_const == RANGE_TO && lbounds->low > rbounds->high)
26,537✔
4794
         return emit_const(vtype_bool(), 1);
65✔
4795
      else if (dir_const == RANGE_TO && lbounds->high <= rbounds->low)
26,472✔
4796
         return emit_const(vtype_bool(), 0);
18,413✔
4797
      else if (dir_const == RANGE_DOWNTO && rbounds->low > lbounds->high)
8,059✔
4798
         return emit_const(vtype_bool(), 1);
619✔
4799
      else if (dir_const == RANGE_DOWNTO && rbounds->high <= lbounds->low)
7,440✔
4800
         return emit_const(vtype_bool(), 0);
1,890✔
4801
      else if (dir_const == RANGE_TO)
5,550✔
4802
         return emit_cmp(VCODE_CMP_GT, left, right);
2,837✔
4803
      else
4804
         return emit_cmp(VCODE_CMP_GT, right, left);
2,713✔
4805
   }
4806

4807
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
2,997✔
4808
   vcode_add_arg(op, left);
2,997✔
4809
   vcode_add_arg(op, right);
2,997✔
4810
   vcode_add_arg(op, dir);
2,997✔
4811

4812
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
2,997✔
4813
                "range left and right have different types");
4814
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
2,997✔
4815
                "dir argument to range length is not int");
4816

4817
   return (op->result = vcode_add_reg(vtype_bool()));
2,997✔
4818
}
4819

4820
vcode_reg_t emit_range_length(vcode_reg_t left, vcode_reg_t right,
14,849✔
4821
                              vcode_reg_t dir)
4822
{
4823
   vcode_reg_t left_array = VCODE_INVALID_REG,
14,849✔
4824
      right_array = VCODE_INVALID_REG,
14,849✔
4825
      dir_array = VCODE_INVALID_REG;
14,849✔
4826
   int left_dim = -1, right_dim = -1, dir_dim = -1;
14,849✔
4827

4828
   VCODE_FOR_EACH_OP(other) {
292,075✔
4829
      if (other->kind == VCODE_OP_RANGE_LENGTH
282,786✔
4830
          && other->args.items[0] == left
7,889✔
4831
          && other->args.items[1] == right
5,877✔
4832
          && other->args.items[2] == dir)
5,560✔
4833
         return other->result;
5,560✔
4834
      else if (other->kind == VCODE_OP_UARRAY_LEFT && other->result == left) {
277,226✔
4835
         left_array = other->args.items[0];
362✔
4836
         left_dim = other->dim;
362✔
4837
      }
4838
      else if (other->kind == VCODE_OP_UARRAY_RIGHT && other->result == right) {
276,864✔
4839
         right_array = other->args.items[0];
362✔
4840
         right_dim = other->dim;
362✔
4841
      }
4842
      else if (other->kind == VCODE_OP_UARRAY_DIR && other->result == dir) {
276,502✔
4843
         dir_array = other->args.items[0];
706✔
4844
         dir_dim = other->dim;
706✔
4845
      }
4846
   }
4847

4848
   if (left_array != VCODE_INVALID_REG && left_array == right_array
9,289✔
4849
       && right_array == dir_array && left_dim == right_dim
362✔
4850
       && right_dim == dir_dim)
362✔
4851
      return emit_uarray_len(left_array, left_dim);
362✔
4852

4853
   int64_t lconst, rconst, dconst;
8,927✔
4854
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
8,927✔
4855
       && vcode_reg_const(right, &rconst)) {
4,889✔
4856

4857
      int64_t diff;
1,846✔
4858
      if (dconst == RANGE_TO)
1,846✔
4859
         diff = rconst - lconst;
1,549✔
4860
      else
4861
         diff = lconst - rconst;
297✔
4862

4863
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
1,846✔
4864
   }
4865

4866
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
7,081✔
4867
   vcode_add_arg(op, left);
7,081✔
4868
   vcode_add_arg(op, right);
7,081✔
4869
   vcode_add_arg(op, dir);
7,081✔
4870

4871
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
7,081✔
4872
                "range left and right have different types");
4873
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
7,081✔
4874
                "dir argument to range length is not int");
4875

4876
   op->result = vcode_add_reg(vtype_offset());
7,081✔
4877

4878
   reg_t *rr = vcode_reg_data(op->result);
7,081✔
4879
   rr->bounds = vtype_int(0, INT64_MAX);
7,081✔
4880

4881
   return op->result;
7,081✔
4882
}
4883

4884
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
54,201✔
4885
{
4886
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
493,739✔
4887
      if (other->hops == hops && other->address == var)
66,257✔
4888
         return other->result;
10,859✔
4889
   }
4890

4891
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
43,342✔
4892
   op->hops    = hops;
43,342✔
4893
   op->address = var;
43,342✔
4894

4895
   VCODE_ASSERT(hops > 0, "invalid hop count");
43,342✔
4896

4897
   vcode_unit_t vu = active_unit;
43,342✔
4898
   for (int i = 0; i < hops; i++) {
95,973✔
4899
      vu = vu->context;
52,631✔
4900
      VCODE_ASSERT(vu, "hop count is greater than depth");
52,631✔
4901
   }
4902

4903
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
43,342✔
4904

4905
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
43,342✔
4906

4907
   return op->result;
43,342✔
4908
}
4909

4910
vcode_reg_t emit_init_signal(vcode_type_t type, vcode_reg_t count,
16,214✔
4911
                             vcode_reg_t size, vcode_reg_t value,
4912
                             vcode_reg_t flags, vcode_reg_t locus,
4913
                             vcode_reg_t offset)
4914
{
4915
   op_t *op = vcode_add_op(VCODE_OP_INIT_SIGNAL);
16,214✔
4916
   vcode_add_arg(op, count);
16,214✔
4917
   vcode_add_arg(op, size);
16,214✔
4918
   vcode_add_arg(op, value);
16,214✔
4919
   vcode_add_arg(op, flags);
16,214✔
4920
   vcode_add_arg(op, locus);
16,214✔
4921
   if (offset != VCODE_INVALID_REG)
16,214✔
4922
      vcode_add_arg(op, offset);
5,736✔
4923

4924
   vcode_type_t vtype = vcode_reg_type(value);
16,214✔
4925
   VCODE_ASSERT(vtype_is_scalar(type), "signal type must be scalar");
16,214✔
4926
   VCODE_ASSERT(vtype_eq(vtype, type)
16,214✔
4927
                || vtype_kind(vtype) == VCODE_TYPE_POINTER,
4928
                "init signal value type does not match signal type");
4929
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
16,214✔
4930
                "locus argument to init signal must be a debug locus");
4931
   VCODE_ASSERT(offset == VCODE_INVALID_REG
16,214✔
4932
                || vcode_reg_kind(offset) == VCODE_TYPE_POINTER,
4933
                "init signal offset argument must have pointer type");
4934

4935
   return (op->result = vcode_add_reg(vtype_signal(type)));
16,214✔
4936
}
4937

4938
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
3,388✔
4939
{
4940
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
3,388✔
4941
   vcode_add_arg(op, signal);
3,388✔
4942
   vcode_add_arg(op, resolution);
3,388✔
4943

4944
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
3,388✔
4945
                "signal argument has wrong type");
4946

4947
   vcode_type_t rtype = vcode_reg_type(resolution);
3,388✔
4948
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
3,388✔
4949
                "resolution wrapper argument must be pointer");
4950
   VCODE_ASSERT(vtype_kind(vtype_pointed(rtype)) == VCODE_TYPE_RESOLUTION,
3,388✔
4951
                "resolution wrapper argument has wrong type");
4952
}
3,388✔
4953

4954
vcode_reg_t emit_implicit_signal(vcode_type_t type, vcode_reg_t count,
75✔
4955
                                 vcode_reg_t size, vcode_reg_t locus,
4956
                                 vcode_reg_t kind, vcode_reg_t closure,
4957
                                 vcode_reg_t delay)
4958
{
4959
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_SIGNAL);
75✔
4960
   vcode_add_arg(op, count);
75✔
4961
   vcode_add_arg(op, size);
75✔
4962
   vcode_add_arg(op, locus);
75✔
4963
   vcode_add_arg(op, kind);
75✔
4964
   vcode_add_arg(op, closure);
75✔
4965
   vcode_add_arg(op, delay);
75✔
4966

4967
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
75✔
4968
                "count argument to implicit signal is not offset");
4969
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
75✔
4970
                "kind argument to implicit signal is not offset");
4971
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
75✔
4972
                "closure argument to implicit signal is not a closure");
4973
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
75✔
4974
                "locus argument to implicit signal must be a debug locus");
4975
   VCODE_ASSERT(vcode_reg_kind(delay) == VCODE_TYPE_INT,
75✔
4976
                "delay argument to implicit signal must be time");
4977

4978
   return (op->result = vcode_add_reg(vtype_signal(type)));
75✔
4979
}
4980

4981
void emit_map_signal(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
5,440✔
4982
{
4983
   op_t *op = vcode_add_op(VCODE_OP_MAP_SIGNAL);
5,440✔
4984
   vcode_add_arg(op, src);
5,440✔
4985
   vcode_add_arg(op, dst);
5,440✔
4986
   vcode_add_arg(op, count);
5,440✔
4987

4988
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
5,440✔
4989
                "src argument to map signal is not a signal");
4990
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
5,440✔
4991
                "dst argument to map signal is not a signal");
4992
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5,440✔
4993
                "count argument type to map signal is not offset");
4994
}
5,440✔
4995

4996
void emit_map_const(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
200✔
4997
{
4998
   op_t *op = vcode_add_op(VCODE_OP_MAP_CONST);
200✔
4999
   vcode_add_arg(op, src);
200✔
5000
   vcode_add_arg(op, dst);
200✔
5001
   vcode_add_arg(op, count);
200✔
5002

5003
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
200✔
5004
                "dst argument to map const is not a signal");
5005
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
200✔
5006
                "count argument type to map const is not offset");
5007
}
200✔
5008

5009
void emit_map_implicit(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
57✔
5010
{
5011
   op_t *op = vcode_add_op(VCODE_OP_MAP_IMPLICIT);
57✔
5012
   vcode_add_arg(op, src);
57✔
5013
   vcode_add_arg(op, dst);
57✔
5014
   vcode_add_arg(op, count);
57✔
5015

5016
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
57✔
5017
                "src argument to map implicit is not a signal");
5018
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
57✔
5019
                "dst argument to map implicit is not a signal");
5020
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
57✔
5021
                "count argument type to map implicit is not offset");
5022
}
57✔
5023

5024
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
7,239✔
5025
{
5026
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
91,689✔
5027
      if (other->args.items[0] == target && other->args.items[1] == count)
12,124✔
5028
         return;
5029
   }
5030

5031
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
7,236✔
5032
   vcode_add_arg(op, target);
7,236✔
5033
   vcode_add_arg(op, count);
7,236✔
5034

5035
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
7,236✔
5036
                "target argument to drive signal is not a signal");
5037
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
7,236✔
5038
                "count argument type to drive signal is not offset");
5039
}
5040

5041
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
530✔
5042
                          vcode_reg_t count, vcode_reg_t reject,
5043
                          vcode_reg_t after)
5044
{
5045
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
530✔
5046
   vcode_add_arg(op, target);
530✔
5047
   vcode_add_arg(op, source);
530✔
5048
   vcode_add_arg(op, count);
530✔
5049
   vcode_add_arg(op, reject);
530✔
5050
   vcode_add_arg(op, after);
530✔
5051

5052
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
530✔
5053
                "target argument to transfer signal is not a signal");
5054
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
530✔
5055
                "count argument type to transfer signal is not offset");
5056
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
530✔
5057
                "source argument to transfer signal is not a signal");
5058
}
530✔
5059

5060
vcode_reg_t emit_resolution_wrapper(vcode_type_t type, vcode_reg_t closure,
5,151✔
5061
                                    vcode_reg_t nlits)
5062
{
5063
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RESOLUTION_WRAPPER) {
84,332✔
5064
      if (other->args.items[0] == closure && other->args.items[1] == nlits)
11,219✔
5065
         return other->result;
×
5066
   }
5067

5068
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
5,151✔
5069
                "first argument to resolution wrapper must be closure");
5070

5071
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
5,151✔
5072
   vcode_add_arg(op, closure);
5,151✔
5073
   vcode_add_arg(op, nlits);
5,151✔
5074

5075
   return (op->result = vcode_add_reg(vtype_resolution(type)));
5,151✔
5076
}
5077

5078
vcode_reg_t emit_closure(ident_t func, vcode_reg_t context, vcode_type_t rtype)
5,448✔
5079
{
5080
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CLOSURE) {
85,484✔
5081
      if (other->func == func && other->args.items[0] == context)
11,390✔
5082
         return other->result;
×
5083
   }
5084

5085
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
5,448✔
5086
   vcode_add_arg(op, context);
5,448✔
5087
   op->func = func;
5,448✔
5088

5089
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5,448✔
5090
                "invalid closure context argument");
5091

5092
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
5,448✔
5093
}
5094

5095
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
35,358✔
5096
{
5097
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
68,340✔
5098
      if (other->func == name)
28,857✔
5099
         return other->result;
13,513✔
5100
   }
5101

5102
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
21,845✔
5103
   op->func = name;
21,845✔
5104
   if (context != VCODE_INVALID_REG)
21,845✔
5105
      vcode_add_arg(op, context);
190✔
5106

5107
   VCODE_ASSERT(context == VCODE_INVALID_REG
21,845✔
5108
                || vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5109
                "invalid protected init context argument");
5110
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_INSTANCE
21,845✔
5111
                || active_unit->kind == VCODE_UNIT_PACKAGE
5112
                || active_unit->kind == VCODE_UNIT_THUNK,
5113
                "cannot use package init here");
5114
   VCODE_ASSERT(name != active_unit->name, "cyclic package init");
21,845✔
5115

5116
   return (op->result = vcode_add_reg(vtype_context(name)));
21,845✔
5117
}
5118

5119
vcode_reg_t emit_protected_init(vcode_type_t type, vcode_reg_t context,
544✔
5120
                                vcode_reg_t path_name, vcode_reg_t inst_name)
5121
{
5122
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_INIT);
544✔
5123
   vcode_add_arg(op, context);
544✔
5124
   op->func = vtype_name(type);
544✔
5125

5126
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
544✔
5127
      vcode_add_arg(op, path_name);
414✔
5128
      vcode_add_arg(op, inst_name);
414✔
5129

5130
      VCODE_ASSERT(vcode_reg_kind(path_name) == VCODE_TYPE_UARRAY,
414✔
5131
                   "path name argument must be uarray");
5132
      VCODE_ASSERT(vcode_reg_kind(inst_name) == VCODE_TYPE_UARRAY,
414✔
5133
                   "inst name argument must be uarray");
5134
   }
5135

5136
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
544✔
5137
                "protected init type must be context");
5138
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
544✔
5139
                "invalid protected init context argument");
5140

5141
   return (op->result = vcode_add_reg(type));
544✔
5142
}
5143

5144
void emit_process_init(ident_t name, vcode_reg_t locus)
117✔
5145
{
5146
   op_t *op = vcode_add_op(VCODE_OP_PROCESS_INIT);
117✔
5147
   vcode_add_arg(op, locus);
117✔
5148
   op->func = name;
117✔
5149

5150
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
117✔
5151
                "locus argument to process init must be a debug locus");
5152
}
117✔
5153

5154
void emit_protected_free(vcode_reg_t obj)
308✔
5155
{
5156
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
308✔
5157
   vcode_add_arg(op, obj);
308✔
5158

5159
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
308✔
5160
                "protected object type must be context");
5161
}
308✔
5162

5163
vcode_reg_t emit_context_upref(int hops)
19,559✔
5164
{
5165
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
133,207✔
5166
      if (other->hops == hops)
8,731✔
5167
         return other->result;
8,683✔
5168
   }
5169

5170
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
10,876✔
5171
   op->hops = hops;
10,876✔
5172

5173
   VCODE_ASSERT(hops >= 0, "invalid hop count");
10,876✔
5174

5175
   vcode_unit_t vu = active_unit;
10,876✔
5176
   for (int i = 0; i < hops; i++) {
19,129✔
5177
      vu = vu->context;
8,253✔
5178
      VCODE_ASSERT(vu, "hop count is greater than depth");
8,253✔
5179
   }
5180

5181
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
10,876✔
5182
}
5183

5184
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
661✔
5185
                                    vcode_reg_t len)
5186
{
5187
   op_t *op = vcode_add_op(opkind);
661✔
5188
   vcode_add_arg(op, nets);
661✔
5189
   vcode_add_arg(op, len);
661✔
5190

5191
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
661✔
5192
                "argument to %s is not a signal", vcode_op_string(opkind));
5193

5194
   return (op->result = vcode_add_reg(vtype_bool()));
661✔
5195
}
5196

5197
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
444✔
5198
{
5199
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
444✔
5200
}
5201

5202
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
217✔
5203
{
5204
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
217✔
5205
}
5206

5207
vcode_reg_t emit_record_ref(vcode_reg_t record, unsigned field)
37,008✔
5208
{
5209
   // Try scanning backwards through the block for another record ref
5210
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RECORD_REF) {
2,683,014✔
5211
      if (other->args.items[0] == record && other->field == field)
503,382✔
5212
         return other->result;
3,881✔
5213
   }
5214

5215
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
33,127✔
5216
   op->field = field;
33,127✔
5217
   vcode_add_arg(op, record);
33,127✔
5218

5219
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
33,127✔
5220

5221
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
33,127✔
5222
                "argument to record ref must be a pointer");
5223

5224
   vtype_t *rtype = vcode_type_data(rptype->pointed);
33,127✔
5225
   VCODE_ASSERT(rtype->kind == VCODE_TYPE_RECORD,
33,127✔
5226
                "argument must be pointer to record or record signal");
5227

5228
   VCODE_ASSERT(field < rtype->fields.count, "invalid field %d", field);
33,127✔
5229

5230
   vcode_type_t field_type  = rtype->fields.items[field];
33,127✔
5231
   vcode_type_t bounds_type = field_type;
33,127✔
5232
   vcode_type_t result_type = field_type;
33,127✔
5233

5234
   const vtype_kind_t fkind = vtype_kind(field_type);
33,127✔
5235
   if (fkind == VCODE_TYPE_CARRAY)
33,127✔
5236
      result_type = bounds_type = vtype_elem(field_type);
4,559✔
5237
   else if (fkind == VCODE_TYPE_UARRAY) {
28,568✔
5238
      bounds_type = vtype_elem(field_type);
2,985✔
5239
      result_type = field_type;
2,985✔
5240
   }
5241

5242
   op->result = vcode_add_reg(vtype_pointer(result_type));
33,127✔
5243

5244
   reg_t *rr = vcode_reg_data(op->result);
33,127✔
5245
   rr->bounds = bounds_type;
33,127✔
5246

5247
   return op->result;
33,127✔
5248
}
5249

5250
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
33,223✔
5251
{
5252
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
1,658,263✔
5253
      if (other->args.items[0] == array && other->args.items[1] == offset)
104,250✔
5254
         return other->result;
1,215✔
5255
   }
5256

5257
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
32,008✔
5258
   vcode_add_arg(op, array);
32,008✔
5259
   vcode_add_arg(op, offset);
32,008✔
5260

5261
   vcode_type_t rtype = vcode_reg_type(array);
32,008✔
5262
   VCODE_ASSERT((vtype_kind(rtype) == VCODE_TYPE_POINTER
32,008✔
5263
                 && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY)
5264
                || vtype_kind(rtype) == VCODE_TYPE_SIGNAL,
5265
                "argument to array ref must be a pointer or signal");
5266
   VCODE_ASSERT(vcode_reg_kind(offset) == VCODE_TYPE_OFFSET,
32,008✔
5267
                "array ref offset argument must have offset type");
5268

5269
   op->result = vcode_add_reg(rtype);
32,008✔
5270

5271
   reg_t *rr = vcode_reg_data(op->result);
32,008✔
5272
   rr->bounds = vcode_reg_bounds(array);
32,008✔
5273

5274
   return op->result;
32,008✔
5275
}
5276

5277
vcode_reg_t emit_table_ref(vcode_reg_t array, vcode_reg_t stride,
725✔
5278
                           const vcode_reg_t *args, int nargs)
5279
{
5280
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_TABLE_REF) {
21,104✔
5281
      if (other->args.items[0] != array || other->args.items[1] != stride)
851✔
5282
         continue;
598✔
5283
      else if (other->args.count != nargs + 2)
253✔
NEW
5284
         continue;
×
5285

5286
      bool match = true;
5287
      for (int i = 0; i < nargs; i++)
649✔
5288
         match &= (other->args.items[i + 2] == args[i]);
396✔
5289

5290
      if (match)
253✔
5291
         return other->result;
26✔
5292
   }
5293

5294
   op_t *op = vcode_add_op(VCODE_OP_TABLE_REF);
699✔
5295
   vcode_add_arg(op, array);
699✔
5296
   vcode_add_arg(op, stride);
699✔
5297
   for (int i = 0; i < nargs; i++)
1,745✔
5298
      vcode_add_arg(op, args[i]);
1,046✔
5299

5300
   vcode_type_t rtype = vcode_reg_type(array);
699✔
5301
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER
699✔
5302
                && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY,
5303
                "argument to table ref must be a pointer or signal");
5304
   VCODE_ASSERT(vcode_reg_kind(stride) == VCODE_TYPE_OFFSET,
699✔
5305
                "table ref stride argument must have offset type");
5306

5307
   for (int i = 0; i < nargs; i++)
1,745✔
5308
      VCODE_ASSERT(vtype_is_integral(vcode_reg_type(args[i])),
1,046✔
5309
                   "table ref indices must be integral");
5310

5311
   op->result = vcode_add_reg(rtype);
699✔
5312

5313
   reg_t *rr = vcode_reg_data(op->result);
699✔
5314
   rr->bounds = vcode_reg_bounds(array);
699✔
5315

5316
   return op->result;
699✔
5317
}
5318

5319
void emit_copy(vcode_reg_t dest, vcode_reg_t src, vcode_reg_t count)
30,306✔
5320
{
5321
   int64_t cconst;
30,306✔
5322
   if (count != VCODE_INVALID_REG && vcode_reg_const(count, &cconst)
30,306✔
5323
       && cconst == 0)
20,402✔
5324
      return;
5,370✔
5325
   else if (dest == src)
29,552✔
5326
      return;
5327

5328
   op_t *op = vcode_add_op(VCODE_OP_COPY);
24,936✔
5329
   vcode_add_arg(op, dest);
24,936✔
5330
   vcode_add_arg(op, src);
24,936✔
5331
   if (count != VCODE_INVALID_REG)
24,936✔
5332
      vcode_add_arg(op, count);
23,360✔
5333

5334
   vcode_type_t dtype = vcode_reg_type(dest);
24,936✔
5335
   vcode_type_t stype = vcode_reg_type(src);
24,936✔
5336

5337
   vtype_kind_t dkind = vtype_kind(dtype);
24,936✔
5338
   vtype_kind_t skind = vtype_kind(stype);
24,936✔
5339

5340
   VCODE_ASSERT(dkind == VCODE_TYPE_POINTER || dkind == VCODE_TYPE_ACCESS,
24,936✔
5341
                "destination type is not a pointer or access");
5342
   VCODE_ASSERT(skind == VCODE_TYPE_POINTER || skind == VCODE_TYPE_ACCESS,
24,936✔
5343
                "source type is not a pointer or access");
5344
   VCODE_ASSERT(vtype_eq(dtype, stype),
24,936✔
5345
                "source and destination types do not match");
5346
   VCODE_ASSERT(count == VCODE_INVALID_REG
24,936✔
5347
                || vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5348
                "count is not offset type");
5349

5350
   op->type = vtype_pointed(dtype);
24,936✔
5351
}
5352

5353
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
4,486✔
5354
{
5355
   VCODE_FOR_EACH_OP(other) {
63,601✔
5356
      if (other->kind == VCODE_OP_CLEAR_EVENT)
59,169✔
5357
         break;
5358
      else if (other->kind == VCODE_OP_SCHED_EVENT
59,121✔
5359
               && other->args.items[0] == nets
2,600✔
5360
               && other->args.items[1] == n_elems)
9✔
5361
         return;
5362
   }
5363

5364
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
4,480✔
5365
   vcode_add_arg(op, nets);
4,480✔
5366
   vcode_add_arg(op, n_elems);
4,480✔
5367

5368
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
4,480✔
5369
                "nets argument to sched event must be signal");
5370
}
5371

5372
void emit_clear_event(vcode_reg_t nets, vcode_reg_t n_elems)
550✔
5373
{
5374
   VCODE_FOR_EACH_OP(other) {
2,524✔
5375
      if (other->kind == VCODE_OP_SCHED_EVENT)
1,974✔
5376
         break;
5377
      else if (other->kind == VCODE_OP_CLEAR_EVENT
1,974✔
5378
               && other->args.items[0] == nets
39✔
5379
               && other->args.items[1] == n_elems)
×
5380
         return;
5381
   }
5382

5383
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
550✔
5384
   vcode_add_arg(op, nets);
550✔
5385
   vcode_add_arg(op, n_elems);
550✔
5386

5387
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
550✔
5388
                "nets argument to clear event must be signal");
5389
}
5390

5391
void emit_sched_process(vcode_reg_t delay)
5,267✔
5392
{
5393
   op_t *op = vcode_add_op(VCODE_OP_SCHED_PROCESS);
5,267✔
5394
   vcode_add_arg(op, delay);
5,267✔
5395

5396
   VCODE_ASSERT(vcode_reg_kind(delay) == VCODE_TYPE_INT,
5,267✔
5397
                "delay must have integer type");
5398
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_PROCEDURE
5,267✔
5399
                || active_unit->kind == VCODE_UNIT_PROCESS,
5400
                "sched process only allowed in process or procedure");
5401
}
5,267✔
5402

5403
void emit_resume(ident_t func)
843✔
5404
{
5405
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
843✔
5406
   op->func = func;
843✔
5407

5408
   block_t *b = &(active_unit->blocks.items[active_block]);
843✔
5409
   VCODE_ASSERT(b->ops.count == 1, "resume must be first op in a block");
843✔
5410
}
843✔
5411

5412
void emit_memset(vcode_reg_t ptr, vcode_reg_t value, vcode_reg_t len)
5,513✔
5413
{
5414
   int64_t lconst;
5,513✔
5415
   if (vcode_reg_const(len, &lconst) && lconst == 0)
5,513✔
5416
      return;
32✔
5417

5418
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
5,481✔
5419
   vcode_add_arg(op, ptr);
5,481✔
5420
   vcode_add_arg(op, value);
5,481✔
5421
   vcode_add_arg(op, len);
5,481✔
5422

5423
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
5,481✔
5424
                "target of memset must have pointer type");
5425
   VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(value)),
5,481✔
5426
                "value of memset must have scalar type");
5427
   VCODE_ASSERT(vtype_kind(vcode_reg_type(len)) == VCODE_TYPE_OFFSET,
5,481✔
5428
                "length of memset must have offset type");
5429
}
5430

5431
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
647✔
5432
               const vcode_block_t *blocks, int ncases)
5433
{
5434
   int64_t cval1, cval2;
647✔
5435
   bool is_const = vcode_reg_const(value, &cval1);
647✔
5436

5437
   for (int i = 0; i < ncases; i++) {
3,696✔
5438
      bool can_fold = false;
3,052✔
5439
      if (cases[i] == value)
3,052✔
5440
         can_fold = true;
5441
      else if (is_const && vcode_reg_const(cases[i], &cval2))
3,052✔
5442
         can_fold = (cval1 == cval2);
3✔
5443

5444
      if (can_fold) {
3✔
5445
         emit_jump(blocks[i]);
3✔
5446
         return;
6✔
5447
      }
5448
   }
5449

5450
   if (is_const) {
644✔
5451
      emit_jump(def);
×
5452
      return;
×
5453
   }
5454

5455
   op_t *op = vcode_add_op(VCODE_OP_CASE);
644✔
5456
   vcode_add_arg(op, value);
644✔
5457
   vcode_add_target(op, def);
644✔
5458

5459
   for (int i = 0; i < ncases; i++) {
3,693✔
5460
      vcode_add_arg(op, cases[i]);
3,049✔
5461
      vcode_add_target(op, blocks[i]);
3,049✔
5462

5463
#ifdef DEBUG
5464
      for (int j = 0; j < i; j++)
15,620✔
5465
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
12,571✔
5466
#endif
5467
   }
5468
}
5469

5470
void emit_file_open(vcode_reg_t file, vcode_reg_t name, vcode_reg_t length,
1,236✔
5471
                    vcode_reg_t kind, vcode_reg_t status)
5472
{
5473
   op_t *op = vcode_add_op(VCODE_OP_FILE_OPEN);
1,236✔
5474
   vcode_add_arg(op, file);
1,236✔
5475
   vcode_add_arg(op, name);
1,236✔
5476
   vcode_add_arg(op, length);
1,236✔
5477
   vcode_add_arg(op, kind);
1,236✔
5478
   if (status != VCODE_INVALID_REG)
1,236✔
5479
      vcode_add_arg(op, status);
25✔
5480

5481
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
1,236✔
5482
                "file open first argument must have file pointer type");
5483
}
1,236✔
5484

5485
void emit_file_write(vcode_reg_t file, vcode_reg_t value, vcode_reg_t length)
261✔
5486
{
5487
   op_t *op = vcode_add_op(VCODE_OP_FILE_WRITE);
261✔
5488
   vcode_add_arg(op, file);
261✔
5489
   vcode_add_arg(op, value);
261✔
5490
   if (length != VCODE_INVALID_REG)
261✔
5491
      vcode_add_arg(op, length);
204✔
5492

5493
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
261✔
5494
                "file write first argument must have file pointer type");
5495
}
261✔
5496

5497
void emit_file_read(vcode_reg_t file, vcode_reg_t ptr,
90✔
5498
                    vcode_reg_t inlen, vcode_reg_t outlen)
5499
{
5500
   op_t *op = vcode_add_op(VCODE_OP_FILE_READ);
90✔
5501
   vcode_add_arg(op, file);
90✔
5502
   vcode_add_arg(op, ptr);
90✔
5503
   if (inlen != VCODE_INVALID_REG) {
90✔
5504
      vcode_add_arg(op, inlen);
42✔
5505
      if (outlen != VCODE_INVALID_REG)
42✔
5506
         vcode_add_arg(op, outlen);
33✔
5507
   }
5508

5509
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
90✔
5510
                "file read first argument must have file pointer type");
5511
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
90✔
5512
                "file read pointer argument must have pointer type");
5513
   VCODE_ASSERT(outlen == VCODE_INVALID_REG
90✔
5514
                || vtype_kind(vcode_reg_type(outlen)) == VCODE_TYPE_POINTER,
5515
                "file read outlen argument must have pointer type");
5516
}
90✔
5517

5518
vcode_reg_t emit_null(vcode_type_t type)
12,676✔
5519
{
5520
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_NULL) {
254,700✔
5521
      if (vtype_eq(vcode_reg_type(other->result), type))
7,553✔
5522
         return other->result;
4,014✔
5523
   }
5524

5525
   op_t *op = vcode_add_op(VCODE_OP_NULL);
8,662✔
5526
   op->result = vcode_add_reg(type);
8,662✔
5527

5528
   vtype_kind_t kind = vtype_kind(type);
8,662✔
5529
   VCODE_ASSERT(kind == VCODE_TYPE_POINTER || kind == VCODE_TYPE_FILE
8,662✔
5530
                || kind == VCODE_TYPE_ACCESS || kind == VCODE_TYPE_CONTEXT,
5531
                "null type must be file, access, context, or pointer");
5532

5533
   return op->result;
5534
}
5535

5536
vcode_reg_t emit_new(vcode_type_t type, vcode_reg_t length)
645✔
5537
{
5538
   op_t *op = vcode_add_op(VCODE_OP_NEW);
645✔
5539
   if (length != VCODE_INVALID_REG)
645✔
5540
      vcode_add_arg(op, length);
554✔
5541

5542
   op->result = vcode_add_reg(vtype_access(type));
645✔
5543

5544
   vtype_kind_t kind = vtype_kind(type);
645✔
5545
   VCODE_ASSERT(kind == VCODE_TYPE_INT || kind == VCODE_TYPE_RECORD
645✔
5546
                || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_ACCESS
5547
                || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_CONTEXT,
5548
                "new type must be int, real, record, access, or uarray");
5549
   VCODE_ASSERT(length == VCODE_INVALID_REG
645✔
5550
                || vtype_kind(vcode_reg_type(length)) == VCODE_TYPE_OFFSET,
5551
                "new length must have offset type");
5552

5553
   return op->result;
645✔
5554
}
5555

5556
void emit_null_check(vcode_reg_t ptr, vcode_reg_t locus)
2,917✔
5557
{
5558
   VCODE_FOR_EACH_OP(other) {
119,660✔
5559
      if (other->kind == VCODE_OP_NULL_CHECK && other->args.items[0] == ptr)
117,487✔
5560
         return;
5561
      else if (other->kind == VCODE_OP_NEW && other->result == ptr)
117,069✔
5562
         return;
5563
   }
5564

5565
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
2,173✔
5566
   vcode_add_arg(op, ptr);
2,173✔
5567
   vcode_add_arg(op, locus);
2,173✔
5568

5569
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
2,173✔
5570
                "null check argument must be an access");
5571
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,173✔
5572
                "locus argument to null check must be a debug locus");
5573
}
5574

5575
void emit_deallocate(vcode_reg_t ptr)
341✔
5576
{
5577
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
341✔
5578
   vcode_add_arg(op, ptr);
341✔
5579

5580
   vcode_type_t ptype = vcode_reg_type(ptr);
341✔
5581
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
341✔
5582
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5583
                "deallocate argument must be pointer to access");
5584
}
341✔
5585

5586
vcode_reg_t emit_all(vcode_reg_t reg)
3,562✔
5587
{
5588
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
167,406✔
5589
      if (other->args.items[0] == reg)
10,252✔
5590
         return other->result;
744✔
5591
   }
5592

5593
   op_t *op = vcode_add_op(VCODE_OP_ALL);
2,818✔
5594
   vcode_add_arg(op, reg);
2,818✔
5595

5596
   vcode_type_t vtype = vcode_reg_type(reg);
2,818✔
5597

5598
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
2,818✔
5599
                "all argument must be an access");
5600

5601
   vcode_type_t pointed = vtype_pointed(vtype);
2,818✔
5602
   op->result = vcode_add_reg(vtype_pointer(pointed));
2,818✔
5603

5604
   reg_t *rr = vcode_reg_data(op->result);
2,818✔
5605
   rr->bounds = pointed;
2,818✔
5606

5607
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
2,818✔
5608
                "cannot dereference opaque type");
5609

5610
   return op->result;
5611
}
5612

5613
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
13,666✔
5614
{
5615
   block_t *b = &(active_unit->blocks.items[active_block]);
13,666✔
5616
   for (int i = b->ops.count - 1; i >= 0; i--) {
325,558✔
5617
      const op_t *other = &(b->ops.items[i]);
312,450✔
5618
      if (other->kind == kind && other->args.items[0] == sig)
312,450✔
5619
         return other->result;
558✔
5620
   }
5621

5622
   op_t *op = vcode_add_op(kind);
13,108✔
5623
   vcode_add_arg(op, sig);
13,108✔
5624

5625
   vcode_type_t stype = vcode_reg_type(sig);
13,108✔
5626
   op->type = stype;
13,108✔
5627

5628
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
13,108✔
5629
                "argument r%d to resolved is not a signal", sig);
5630

5631
   vcode_type_t rtype = vtype_base(stype);
13,108✔
5632

5633
   const vtype_kind_t rkind = vtype_kind(rtype);
13,108✔
5634
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
13,108✔
5635
      rtype = vtype_elem(rtype);
×
5636

5637
   VCODE_ASSERT(vtype_is_scalar(rtype),
13,108✔
5638
                "resolved signal base type must be scalar");
5639

5640
   op->result = vcode_add_reg(vtype_pointer(rtype));
13,108✔
5641

5642
   reg_t *rr = vcode_reg_data(op->result);
13,108✔
5643
   rr->bounds = rtype;
13,108✔
5644

5645
   return op->result;
13,108✔
5646
}
5647

5648
vcode_reg_t emit_resolved(vcode_reg_t sig, vcode_reg_t count)
13,477✔
5649
{
5650
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
13,477✔
5651
}
5652

5653
vcode_reg_t emit_last_value(vcode_reg_t sig, vcode_reg_t count)
189✔
5654
{
5655
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
189✔
5656
}
5657

5658
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
42✔
5659
{
5660
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
42✔
5661
   vcode_add_arg(op, signal);
42✔
5662
   if (len != VCODE_INVALID_REG)
42✔
5663
      vcode_add_arg(op, len);
9✔
5664

5665
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
42✔
5666
                "signal argument to last event must have signal type");
5667
   VCODE_ASSERT(len == VCODE_INVALID_REG
42✔
5668
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5669
                "length argument to last event must have offset type");
5670

5671
   return (op->result = vcode_add_reg(vtype_time()));
42✔
5672
}
5673

5674
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
45✔
5675
{
5676
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
45✔
5677
   vcode_add_arg(op, signal);
45✔
5678
   if (len != VCODE_INVALID_REG)
45✔
5679
      vcode_add_arg(op, len);
6✔
5680

5681
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
45✔
5682
                "signal argument to last active must have signal type");
5683
   VCODE_ASSERT(len == VCODE_INVALID_REG
45✔
5684
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5685
                "length argument to last active must have offset type");
5686

5687
   return (op->result = vcode_add_reg(vtype_time()));
45✔
5688
}
5689

5690
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
4,296✔
5691
{
5692
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
4,296✔
5693
   vcode_add_arg(op, signal);
4,296✔
5694
   vcode_add_arg(op, locus);
4,296✔
5695

5696
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
4,296✔
5697
                "signal argument must have signal type");
5698
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
4,296✔
5699
                "locus argument must have debug locus type");
5700
}
4,296✔
5701

5702
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
36✔
5703
{
5704
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
36✔
5705
   vcode_add_arg(op, signal);
36✔
5706
   vcode_add_arg(op, len);
36✔
5707

5708
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5709
                "signal argument to last active must have signal type");
5710
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
36✔
5711
                "length argument to last active must have offset type");
5712

5713
   return (op->result = vcode_add_reg(vtype_bool()));
36✔
5714
}
5715

5716
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
120✔
5717
{
5718
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
120✔
5719
   vcode_add_arg(op, signal);
120✔
5720
   if (len != VCODE_INVALID_REG)
120✔
5721
      vcode_add_arg(op, len);
36✔
5722

5723
   vcode_type_t signal_type = vcode_reg_type(signal);
120✔
5724

5725
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
120✔
5726
                "signal argument to last active must have signal type");
5727
   VCODE_ASSERT(len == VCODE_INVALID_REG
120✔
5728
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5729
                "length argument to last active must have offset type");
5730

5731
   vcode_type_t base_type = vtype_base(signal_type);
120✔
5732
   op->result = vcode_add_reg(vtype_pointer(base_type));
120✔
5733

5734
   reg_t *rr = vcode_reg_data(op->result);
120✔
5735
   rr->bounds = base_type;
120✔
5736

5737
   return op->result;
120✔
5738
}
5739

5740
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
32,950✔
5741
                       vcode_reg_t dim)
5742
{
5743
   if (rlen == llen)
32,950✔
5744
      return;
5745

5746
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
198,635✔
5747
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
2,648✔
5748
         return;
5749
   }
5750

5751
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
7,244✔
5752
   vcode_add_arg(op, llen);
7,244✔
5753
   vcode_add_arg(op, rlen);
7,244✔
5754
   vcode_add_arg(op, locus);
7,244✔
5755
   if (dim != VCODE_INVALID_REG)
7,244✔
5756
      vcode_add_arg(op, dim);
27✔
5757

5758
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
7,244✔
5759
                "locus argument to length check must be a debug locus");
5760
}
5761

5762
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
411✔
5763
{
5764
   int64_t cval;
411✔
5765
   if (vcode_reg_const(exp, &cval) && cval >= 0)
411✔
5766
      return;
47✔
5767

5768
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
4,195✔
5769
      if (other->args.items[0] == exp)
12✔
5770
         return;
5771
   }
5772

5773
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
364✔
5774
   vcode_add_arg(op, exp);
364✔
5775
   vcode_add_arg(op, locus);
364✔
5776

5777
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
364✔
5778
                "exp argument to exponent check must be a integer");
5779
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
364✔
5780
                "locus argument to exponent check must be a debug locus");
5781
}
5782

5783
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
2,488✔
5784
{
5785
   int64_t cval;
2,488✔
5786
   if (vcode_reg_const(denom, &cval) && cval != 0)
2,488✔
5787
      return;
2,397✔
5788

5789
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
2,305✔
5790
      if (other->args.items[0] == denom)
48✔
5791
         return;
5792
   }
5793

5794
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
91✔
5795
   vcode_add_arg(op, denom);
91✔
5796
   vcode_add_arg(op, locus);
91✔
5797

5798
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
91✔
5799
                "denom argument to zero check must be a integer");
5800
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
91✔
5801
                "locus argument to zero check must be a debug locus");
5802
}
5803

5804
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
85,142✔
5805
                                   vcode_reg_t right, vcode_reg_t dir)
5806
{
5807
   int64_t dconst;
85,142✔
5808
   if (vcode_reg_const(dir, &dconst)) {
85,142✔
5809
      int64_t lconst, rconst;
75,218✔
5810
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
75,218✔
5811
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
50,941✔
5812
            || (dconst == RANGE_DOWNTO && rconst > lconst);
104,937✔
5813

5814
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
53,997✔
5815

5816
         const bool ok_static =
107,994✔
5817
            (dconst == RANGE_TO
5818
             && bounds->low >= lconst && bounds->high <= rconst)
50,941✔
5819
            || (dconst == RANGE_DOWNTO
9,067✔
5820
                && bounds->low >= rconst && bounds->high <= lconst)
3,056✔
5821
            || (!is_null && (reg == left || reg == right));
60,314✔
5822

5823
         return ok_static;
72,457✔
5824
      }
5825
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
21,221✔
5826
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
19,161✔
5827
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
19,161✔
5828

5829
         assert(lbounds->kind == VCODE_TYPE_REAL);
19,161✔
5830
         assert(rbounds->kind == VCODE_TYPE_REAL);
19,161✔
5831

5832
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
19,161✔
5833
         assert(bounds->kind == VCODE_TYPE_REAL);
19,161✔
5834

5835
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
19,161✔
5836
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
18,460✔
5837
            // Covers the complete double range so can never overflow
5838
            return true;
5839
         }
5840
      }
5841
   }
5842

5843
   return false;
5844
}
5845

5846
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
86,039✔
5847
                              vcode_reg_t left, vcode_reg_t right,
5848
                              vcode_reg_t dir, vcode_reg_t locus,
5849
                              vcode_reg_t hint)
5850
{
5851
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
3,665,223✔
5852
      if (other->args.items[0] == reg && other->args.items[1] == left
18,215✔
5853
          && other->args.items[2] == right && other->args.items[3] == dir)
1,063✔
5854
         return;
5855
   }
5856

5857
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
85,142✔
5858
      emit_comment("Elided bounds check for r%d", reg);
66,140✔
5859
      return;
66,140✔
5860
   }
5861

5862
   op_t *op = vcode_add_op(kind);
19,002✔
5863
   vcode_add_arg(op, reg);
19,002✔
5864
   vcode_add_arg(op, left);
19,002✔
5865
   vcode_add_arg(op, right);
19,002✔
5866
   vcode_add_arg(op, dir);
19,002✔
5867
   vcode_add_arg(op, locus);
19,002✔
5868
   vcode_add_arg(op, hint);
19,002✔
5869

5870
   VCODE_ASSERT(vtype_is_numeric(vcode_reg_type(reg)),
19,002✔
5871
                "argument to bounds check must be numeric");
5872
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
19,002✔
5873
                "locus argument to bounds check must be a debug locus");
5874
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
19,002✔
5875
                "hint argument to bounds check must be a debug locus");
5876
}
5877

5878
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
22,772✔
5879
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5880
{
5881
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
22,772✔
5882
}
22,772✔
5883

5884
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
63,267✔
5885
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5886
{
5887
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
63,267✔
5888
}
63,267✔
5889

5890
void emit_dir_check(vcode_reg_t reg, vcode_reg_t dir, vcode_reg_t locus)
3,238✔
5891
{
5892
   if (reg == dir)
3,238✔
5893
      return;
5894

5895
   op_t *op = vcode_add_op(VCODE_OP_DIR_CHECK);
2,368✔
5896
   vcode_add_arg(op, reg);
2,368✔
5897
   vcode_add_arg(op, dir);
2,368✔
5898
   vcode_add_arg(op, locus);
2,368✔
5899

5900
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,368✔
5901
                "locus argument to dir check must be a debug locus");
5902
}
5903

5904
void emit_package_scope(vcode_reg_t locus)
45✔
5905
{
5906
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_SCOPE);
45✔
5907
   vcode_add_arg(op, locus);
45✔
5908

5909
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5910
                "locus argument to package scope must be a debug locus");
5911
}
45✔
5912

5913
void emit_array_scope(vcode_reg_t locus, vcode_type_t type)
654✔
5914
{
5915
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_SCOPE);
654✔
5916
   vcode_add_arg(op, locus);
654✔
5917
   op->type = type;
654✔
5918

5919
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
654✔
5920
                "locus argument to array scope must be a debug locus");
5921
}
654✔
5922

5923
void emit_record_scope(vcode_reg_t locus, vcode_type_t type)
1,690✔
5924
{
5925
   op_t *op = vcode_add_op(VCODE_OP_RECORD_SCOPE);
1,690✔
5926
   vcode_add_arg(op, locus);
1,690✔
5927
   op->type = type;
1,690✔
5928

5929
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,690✔
5930
                "locus argument to record scope must be a debug locus");
5931
}
1,690✔
5932

5933
void emit_pop_scope(void)
2,389✔
5934
{
5935
   vcode_add_op(VCODE_OP_POP_SCOPE);
2,389✔
5936
}
2,389✔
5937

5938
vcode_reg_t emit_debug_locus(object_t *obj)
175,799✔
5939
{
5940
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
6,649,489✔
5941
      if (other->object == obj)
820,797✔
5942
         return other->result;
18,879✔
5943
   }
5944

5945
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
156,920✔
5946
   op->object = obj;
156,920✔
5947

5948
   return (op->result = vcode_add_reg(vtype_debug_locus()));
156,920✔
5949
}
5950

5951
void emit_debug_out(vcode_reg_t reg)
×
5952
{
5953
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
5954
   vcode_add_arg(op, reg);
×
5955
}
×
5956

5957
void emit_cover_stmt(uint32_t tag)
1,300✔
5958
{
5959
   op_t *op = vcode_add_op(VCODE_OP_COVER_STMT);
1,300✔
5960
   op->tag = tag;
1,300✔
5961
}
1,300✔
5962

5963
void emit_cover_branch(uint32_t tag)
499✔
5964
{
5965
   op_t *op = vcode_add_op(VCODE_OP_COVER_BRANCH);
499✔
5966
   op->tag = tag;
499✔
5967
}
499✔
5968

5969
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
312✔
5970
{
5971
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
312✔
5972
   vcode_add_arg(op, signal);
312✔
5973
   op->tag = tag;
312✔
5974
}
312✔
5975

5976
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
12✔
5977
{
5978
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
12✔
5979
   vcode_add_arg(op, signal);
12✔
5980
   vcode_add_arg(op, low);
12✔
5981
   op->tag = tag;
12✔
5982
}
12✔
5983

5984
void emit_cover_expr(uint32_t tag)
887✔
5985
{
5986
   op_t *op = vcode_add_op(VCODE_OP_COVER_EXPR);
887✔
5987
   op->tag = tag;
887✔
5988
}
887✔
5989

5990
void emit_unreachable(vcode_reg_t locus)
1,360✔
5991
{
5992
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
1,360✔
5993
   if (locus != VCODE_INVALID_REG)
1,360✔
5994
      vcode_add_arg(op, locus);
118✔
5995
}
1,360✔
5996

5997
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
63✔
5998
{
5999
   active_unit->flags |= UNIT_UNDEFINED;
63✔
6000

6001
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
63✔
6002
   op->result = vcode_add_reg(type);
63✔
6003
   vcode_reg_data(op->result)->bounds = bounds;
63✔
6004

6005
   return op->result;
63✔
6006
}
6007

6008
void emit_debug_info(const loc_t *loc)
2,459,629✔
6009
{
6010
   if (!loc_invalid_p(loc))
2,459,629✔
6011
      vcode_block_data()->last_loc = *loc;
2,437,328✔
6012
}
2,459,629✔
6013

6014
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
8,862✔
6015
{
6016
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
309,983✔
6017
      if (other->args.items[0] == context && other->ident == name)
12,156✔
6018
         return other->result;
3,985✔
6019
   }
6020

6021
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
4,877✔
6022
   vcode_add_arg(op, context);
4,877✔
6023
   op->ident = name;
4,877✔
6024

6025
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
4,877✔
6026
                "first argument to link var must be context");
6027

6028
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
4,877✔
6029
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
612✔
6030
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
612✔
6031
   }
6032
   else {
6033
      op->result = vcode_add_reg(vtype_pointer(type));
4,265✔
6034
      vcode_reg_data(op->result)->bounds = type;
4,265✔
6035
   }
6036

6037
   return op->result;
4,877✔
6038
}
6039

6040
vcode_reg_t emit_link_package(ident_t name)
12,929✔
6041
{
6042
   VCODE_FOR_EACH_OP(other) {
466,402✔
6043
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
459,700✔
6044
         return other->result;
5,682✔
6045
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
454,018✔
6046
         return other->result;
545✔
6047
   }
6048

6049
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
6,702✔
6050
   op->ident = name;
6,702✔
6051

6052
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
6,702✔
6053

6054
   return (op->result = vcode_add_reg(vtype_context(name)));
6,702✔
6055
}
6056

6057
void emit_enter_state(vcode_reg_t state, vcode_reg_t strong)
849✔
6058
{
6059
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
2,046✔
6060
      if (other->args.items[0] == state)
×
6061
         return;
6062
   }
6063

6064
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
849✔
6065
   vcode_add_arg(op, state);
849✔
6066
   if (strong != VCODE_INVALID_REG)
849✔
6067
      vcode_add_arg(op, strong);
36✔
6068

6069
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
849✔
6070
                "state must have integer type");
6071
   VCODE_ASSERT(strong == VCODE_INVALID_REG
849✔
6072
                || vtype_eq(vcode_reg_type(strong), vtype_bool()),
6073
                "strong argument not is not boolean");
6074
}
6075

6076
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
48✔
6077
                               vcode_reg_t locus, vcode_reg_t bounds)
6078
{
6079
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
48✔
6080
   vcode_add_arg(op, value);
48✔
6081
   vcode_add_arg(op, context);
48✔
6082
   vcode_add_arg(op, locus);
48✔
6083
   if (bounds != VCODE_INVALID_REG)
48✔
6084
      vcode_add_arg(op, bounds);
6✔
6085

6086
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
48✔
6087
                "invalid reflect value context argument");
6088
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
48✔
6089
                "locus argument to reflect value must be a debug locus");
6090

6091
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
48✔
6092
}
6093

6094
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
42✔
6095
                                 vcode_reg_t bounds)
6096
{
6097
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
42✔
6098
   vcode_add_arg(op, context);
42✔
6099
   vcode_add_arg(op, locus);
42✔
6100
   if (bounds != VCODE_INVALID_REG)
42✔
6101
      vcode_add_arg(op, bounds);
×
6102

6103
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
42✔
6104
                "invalid reflect value context argument");
6105
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
42✔
6106
                "locus argument to reflect value must be a debug locus");
6107

6108
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
42✔
6109
}
6110

6111
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
202✔
6112
                                  int nargs)
6113
{
6114
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
202✔
6115
   op->func = func;
202✔
6116

6117
   for (int i = 0; i < nargs; i++)
489✔
6118
      vcode_add_arg(op, args[i]);
287✔
6119

6120
   return (op->result = vcode_add_reg(vtype_trigger()));
202✔
6121
}
6122

6123
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
34✔
6124
{
6125
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
34✔
6126
   vcode_add_arg(op, left);
34✔
6127
   vcode_add_arg(op, right);
34✔
6128

6129
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
34✔
6130
                "or trigger left argument must be trigger");
6131
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
34✔
6132
                "or trigger right argument must be trigger");
6133

6134
   return (op->result = vcode_add_reg(vtype_trigger()));
34✔
6135
}
6136

6137
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
66✔
6138
{
6139
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
66✔
6140
   vcode_add_arg(op, left);
66✔
6141
   vcode_add_arg(op, right);
66✔
6142

6143
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
66✔
6144
                "cmp trigger left argument must be signal");
6145
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
66✔
6146
                "cmp trigger right argument must be integer");
6147

6148
   return (op->result = vcode_add_reg(vtype_trigger()));
66✔
6149
}
6150

6151
void emit_add_trigger(vcode_reg_t trigger)
368✔
6152
{
6153
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
368✔
6154
   vcode_add_arg(op, trigger);
368✔
6155

6156
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
368✔
6157
                "add trigger argument must be trigger");
6158
}
368✔
6159

6160
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
204✔
6161
{
6162
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
204✔
6163
   vcode_add_arg(op, driving);
204✔
6164
   if (effective != VCODE_INVALID_REG && effective != driving)
204✔
6165
      vcode_add_arg(op, effective);
18✔
6166

6167
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
204✔
6168
                "port conversion argument must be a closure");
6169
   VCODE_ASSERT(effective == VCODE_INVALID_REG
204✔
6170
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
6171
                "port conversion argument must be a closure");
6172

6173
   return (op->result = vcode_add_reg(vtype_conversion()));
204✔
6174
}
6175

6176
vcode_reg_t emit_bind_external(vcode_reg_t locus, ident_t scope,
180✔
6177
                               vcode_type_t type, vcode_type_t bounds,
6178
                               const vcode_reg_t *args, int nargs)
6179
{
6180
   op_t *op = vcode_add_op(VCODE_OP_BIND_EXTERNAL);
180✔
6181
   op->type  = type;
180✔
6182
   op->ident = scope;
180✔
6183
   vcode_add_arg(op, locus);
180✔
6184
   for (int i = 0; i < nargs; i++)
210✔
6185
      vcode_add_arg(op, args[i]);
30✔
6186

6187
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
180✔
6188
                "bind external argument must be locus");
6189

6190
   op->result = vcode_add_reg(vtype_pointer(type));
180✔
6191
   vcode_reg_data(op->result)->bounds = bounds;
180✔
6192
   return op->result;
180✔
6193
}
6194

6195
void emit_put_conversion(vcode_reg_t cf, vcode_reg_t target, vcode_reg_t count,
342✔
6196
                         vcode_reg_t values)
6197
{
6198
   op_t *op = vcode_add_op(VCODE_OP_PUT_CONVERSION);
342✔
6199
   vcode_add_arg(op, cf);
342✔
6200
   vcode_add_arg(op, target);
342✔
6201
   vcode_add_arg(op, count);
342✔
6202
   vcode_add_arg(op, values);
342✔
6203

6204
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
342✔
6205
                "put conversion target is not signal");
6206
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
342✔
6207
                "put conversion net count is not offset type");
6208
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
342✔
6209
                "signal cannot be values argument for put conversion");
6210
   VCODE_ASSERT(vcode_reg_kind(cf) == VCODE_TYPE_CONVERSION,
342✔
6211
                "cf argument to put conversion must be conversion function");
6212
}
342✔
6213

6214
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
282✔
6215
{
6216
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
282✔
6217
   vcode_add_arg(op, conv);
282✔
6218
   vcode_add_arg(op, nets);
282✔
6219
   vcode_add_arg(op, count);
282✔
6220

6221
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
282✔
6222
                "conv argument to convert must be a port conversion");
6223
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
282✔
6224
                "nets argument to convert must be a signal");
6225
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
282✔
6226
                "count argument to convert must be offset");
6227
}
282✔
6228

6229
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
324✔
6230
{
6231
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
324✔
6232
   vcode_add_arg(op, conv);
324✔
6233
   vcode_add_arg(op, nets);
324✔
6234
   vcode_add_arg(op, count);
324✔
6235

6236
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
324✔
6237
                "conv argument to convert must be a port conversion");
6238
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
324✔
6239
                "nets argument to convert must be a signal");
6240
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
324✔
6241
                "count argument to convert must be offset");
6242
}
324✔
6243

6244
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
1,011✔
6245
{
6246
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
1,011✔
6247
   vcode_add_arg(op, spec);
1,011✔
6248
   vcode_add_arg(op, length);
1,011✔
6249
   if (locus != VCODE_INVALID_REG)
1,011✔
6250
      vcode_add_arg(op, locus);
834✔
6251

6252
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
1,011✔
6253
                "spec argument to bind foreign must be a pointer");
6254
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
1,011✔
6255
                "length argument to bind foreign must be offset");
6256
   VCODE_ASSERT(locus == VCODE_INVALID_REG
1,011✔
6257
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6258
                "locus argument to bind foreign value must be a debug locus");
6259
}
1,011✔
6260

6261
vcode_reg_t emit_instance_name(vcode_reg_t kind)
767✔
6262
{
6263
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
767✔
6264
   vcode_add_arg(op, kind);
767✔
6265

6266
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
767✔
6267
                "kind argument to instance name must be offset");
6268

6269
   vcode_type_t vchar = vtype_char();
767✔
6270
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
767✔
6271
}
6272

6273
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
15,360✔
6274
{
6275
   vcode_state_t state;
15,360✔
6276
   vcode_state_save(&state);
15,360✔
6277

6278
   vcode_select_unit(vu);
15,360✔
6279

6280
   const int nblocks = vcode_count_blocks();
15,360✔
6281
   for (int i = 0; i < nblocks; i++) {
54,773✔
6282
      vcode_select_block(i);
39,413✔
6283

6284
      const int nops = vcode_count_ops();
39,413✔
6285
      for (int op = 0; op < nops; op++) {
653,563✔
6286
         switch (vcode_get_op(op)) {
614,150✔
6287
         case VCODE_OP_LINK_PACKAGE:
2,212✔
6288
            (*fn)(vcode_get_ident(op), ctx);
2,212✔
6289
            break;
2,212✔
6290
         case VCODE_OP_FCALL:
23,884✔
6291
         case VCODE_OP_PCALL:
6292
         case VCODE_OP_CLOSURE:
6293
         case VCODE_OP_PROTECTED_INIT:
6294
         case VCODE_OP_PACKAGE_INIT:
6295
         case VCODE_OP_FUNCTION_TRIGGER:
6296
            (*fn)(vcode_get_func(op), ctx);
23,884✔
6297
            break;
23,884✔
6298
         default:
6299
            break;
6300
         }
6301
      }
6302
   }
6303

6304
   vcode_state_restore(&state);
15,360✔
6305
}
15,360✔
6306

6307
#if VCODE_CHECK_UNIONS
6308
#define OP_USE_COUNT_U0(x)                                              \
6309
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6310
#define OP_USE_COUNT_U1(x)                                              \
6311
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6312
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6313
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6314

6315
__attribute__((constructor))
6316
static void vcode_check_unions(void)
6317
{
6318
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6319
   for (int i = 0; i < 256; i++) {
6320
      assert(OP_USE_COUNT_U0(i) <= 1);
6321
      assert(OP_USE_COUNT_U1(i) <= 1);
6322
   }
6323
}
6324
#endif  // VCODE_CHECK_UNIONS
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