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

nickg / nvc / 20415961579

21 Dec 2025 09:09PM UTC coverage: 92.603% (+0.007%) from 92.596%
20415961579

push

github

nickg
Switch GitHub Actions tests to MSYS2 clang64 environment

75654 of 81697 relevant lines covered (92.6%)

456403.06 hits per line

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

96.81
/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);
9,986,594✔
37
DECLARE_AND_DEFINE_ARRAY(vcode_block);
343,577✔
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,824,567✔
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);
32,204✔
161
DECLARE_AND_DEFINE_ARRAY(var);
442,484✔
162
DECLARE_AND_DEFINE_ARRAY(reg);
9,621,378✔
163
DECLARE_AND_DEFINE_ARRAY(block);
137,482✔
164
DECLARE_AND_DEFINE_ARRAY(vtype);
47,224,232✔
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,222✔
219
{
220
   int64_t result;
39,222✔
221
   if (__builtin_add_overflow(a, b, &result))
39,222✔
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,446✔
228
{
229
   int64_t result;
64,446✔
230
   if (__builtin_sub_overflow(a, b, &result))
64,446✔
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)
15,544✔
237
{
238
   int64_t result;
15,544✔
239
   if (__builtin_mul_overflow(a, b, &result))
15,544✔
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,445,448✔
246
{
247
   assert(active_unit != NULL);
1,445,448✔
248

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

255
   return reg;
1,445,448✔
256
}
257

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

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

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

274
   block_t *block = vcode_block_data();
1,856,572✔
275

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

282
   return op;
1,856,572✔
283
}
284

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

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

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

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

304
static op_t *vcode_find_definition(vcode_reg_t reg)
1,661,638✔
305
{
306
   for (int i = active_block; i >= 0; i--) {
1,692,903✔
307
      block_t *b = &(active_unit->blocks.items[i]);
1,691,510✔
308
      for (int j = b->ops.count - 1; j >= 0; j--) {
32,886,718✔
309
         if (b->ops.items[j].result == reg)
32,855,453✔
310
            return &(b->ops.items[j]);
1,660,245✔
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,644,936✔
319
{
320
   op_t *defn = vcode_find_definition(reg);
1,644,936✔
321
   VCODE_ASSERT(defn != NULL, "constant %s uses parameter r%d",
1,644,936✔
322
                what, reg);
323
   VCODE_ASSERT(defn->kind == VCODE_OP_CONST
1,644,936✔
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,644,936✔
332
#endif
333

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

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

347
   int depth = MASK_CONTEXT(type);
8,015,640✔
348
   assert(depth <= unit->depth);
8,015,640✔
349
   while (depth != unit->depth)
8,964,406✔
350
      unit = unit->context;
948,766✔
351

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

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

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

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

371
   switch (defn->kind) {
15,309✔
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,220✔
393
      vcode_var_data(defn->address)->flags |= VAR_HEAP;
1,220✔
394
      break;
1,220✔
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,549✔
418
   case VCODE_OP_UNWRAP:
419
   case VCODE_OP_RESOLVED:
420
      vcode_heap_allocate(defn->args.items[0]);
4,549✔
421
      break;
4,549✔
422

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

427
   case VCODE_OP_LOAD:
1,171✔
428
      {
429
         if (vcode_reg_kind(reg) != VCODE_TYPE_UARRAY)
1,171✔
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,356✔
434
            block_t *b = &(active_unit->blocks.items[i]);
17,232✔
435
            for (int j = 0; j < b->ops.count; j++) {
236,405✔
436
               op_t *op = &(b->ops.items[j]);
219,173✔
437
               if (op->kind == VCODE_OP_STORE && op->address == defn->address)
219,173✔
438
                  vcode_heap_allocate(op->args.items[0]);
1,124✔
439

440
               VCODE_ASSERT(
219,173✔
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,262✔
450
         const vtype_kind_t rkind = vcode_reg_kind(reg);
4,568✔
451
         if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
4,568✔
452
            // Function may return a pointer to its argument
453
            vcode_heap_allocate(defn->args.items[i]);
4,467✔
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)
38,125✔
523
{
524
   state->unit  = active_unit;
38,125✔
525
   state->block = active_block;
38,125✔
526
}
38,125✔
527

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

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

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

541
   for (vcode_unit_t it = unit->children; it != NULL; it = it->next) {
65,292✔
542
      assert(it->context == unit);
14,379✔
543
      it->context = NULL;
14,379✔
544
   }
545
   unit->children = NULL;
50,913✔
546

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

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

558
      for (unsigned j = 0; j < b->ops.count; j++) {
1,911,012✔
559
         op_t *o = &(b->ops.items[j]);
1,773,628✔
560
         if (OP_HAS_COMMENT(o->kind))
1,773,628✔
561
            free(o->comment);
197,129✔
562
         if (OP_HAS_TARGET(o->kind))
1,773,628✔
563
            free(o->targets.items);
80,753✔
564
         free(o->args.items);
1,773,628✔
565
      }
566
      free(b->ops.items);
137,384✔
567
   }
568
   free(unit->blocks.items);
50,913✔
569

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

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

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

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

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

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

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

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

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

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

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

624
   VCODE_ASSERT(
840,318✔
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,318✔
629
      if (value) *value = bounds->low;
472,252✔
630
      return true;
472,252✔
631
   }
632
   else
633
      return false;
634
}
635

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

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

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

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

650
         for (int j = b->ops.count - 1; j >= 0; j--) {
3,528,275✔
651
            op_t *o = &(b->ops.items[j]);
3,300,224✔
652

653
            switch (o->kind) {
3,300,224✔
654
            case VCODE_OP_FCALL:
55,760✔
655
               if (o->result == VCODE_INVALID_REG)
55,760✔
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,104,737✔
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,104,737✔
701
                  if (false DEBUG_ONLY(|| o->kind != VCODE_OP_CONST)) {
201,230✔
702
                     o->comment = xasprintf("Dead %s definition of r%d",
119,176✔
703
                                            vcode_op_string(o->kind),
704
                                            o->result);
705
                     o->kind = VCODE_OP_COMMENT;
119,176✔
706
                  }
707
                  else
708
                     o->kind = (vcode_op_t)-1;
82,054✔
709
                  vcode_reg_array_resize(&(o->args), 0, VCODE_INVALID_REG);
201,230✔
710
                  pruned++;
201,230✔
711
               }
712
               uses[o->result] = -1;
2,104,737✔
713
               break;
2,104,737✔
714

715
            default:
716
               break;
717
            }
718

719
            for (int k = 0; k < o->args.count; k++) {
9,303,061✔
720
               if (o->args.items[k] != VCODE_INVALID_REG)
6,002,837✔
721
                  uses[o->args.items[k]]++;
5,967,311✔
722
            }
723
         }
724
      }
725
   } while (pruned > 0);
73,473✔
726

727
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
188,421✔
728
      block_t *b = &(active_unit->blocks.items[i]);
137,482✔
729
      op_t *dst = &(b->ops.items[0]);
137,482✔
730
      size_t copied = 0;
137,482✔
731
      for (int j = 0; j < b->ops.count; j++) {
1,994,054✔
732
         const op_t *src = &(b->ops.items[j]);
1,856,572✔
733
         if (src->kind != (vcode_op_t)-1) {
1,856,572✔
734
            if (src != dst) {
1,774,518✔
735
               assert(dst < src);
583,808✔
736
               *dst = *src;
583,808✔
737
            }
738
            dst++;
1,774,518✔
739
            copied++;
1,774,518✔
740
         }
741
      }
742

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

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

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

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

767
int vcode_count_vars(void)
50,887✔
768
{
769
   assert(active_unit != NULL);
50,887✔
770
   return active_unit->vars.count;
50,887✔
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)
74,657✔
785
{
786
   return vcode_var_data(var)->name;
74,657✔
787
}
788

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

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

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

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

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

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

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

830
int64_t vcode_get_value(int op)
366,661✔
831
{
832
   op_t *o = vcode_op_data(op);
366,661✔
833
   assert(OP_HAS_VALUE(o->kind));
366,661✔
834
   return o->value;
366,661✔
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,016✔
845
{
846
   op_t *o = vcode_op_data(op);
182,016✔
847
   assert(OP_HAS_ADDRESS(o->kind));
182,016✔
848
   return o->address;
182,016✔
849
}
850

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

858
int vcode_get_hops(int op)
54,538✔
859
{
860
   op_t *o = vcode_op_data(op);
54,538✔
861
   assert(OP_HAS_HOPS(o->kind));
54,538✔
862
   return o->hops;
54,538✔
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,299✔
873
{
874
   op_t *o = vcode_op_data(op);
63,299✔
875
   assert(OP_HAS_TYPE(o->kind));
63,299✔
876
   return o->type;
63,299✔
877
}
878

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

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

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

896
vcode_cmp_t vcode_get_cmp(int op)
33,517✔
897
{
898
   op_t *o = vcode_op_data(op);
33,517✔
899
   assert(OP_HAS_CMP(o->kind));
33,517✔
900
   return o->cmp;
33,517✔
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,773,560✔
911
{
912
   op_t *o = vcode_op_data(op);
1,773,560✔
913
   return &(o->loc);
1,773,560✔
914
}
915

916
vcode_block_t vcode_get_target(int op, int nth)
114,657✔
917
{
918
   op_t *o = vcode_op_data(op);
114,657✔
919
   assert(OP_HAS_TARGET(o->kind));
114,657✔
920
   return vcode_block_array_nth(&(o->targets), nth);
114,657✔
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,972,704✔
932
{
933
   assert(active_unit != NULL);
1,972,704✔
934
   assert(active_block != VCODE_INVALID_BLOCK);
1,972,704✔
935

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

948
const char *vcode_op_string(vcode_op_t op)
119,176✔
949
{
950
   static const char *strs[] = {
119,176✔
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",
978
   };
979
   if ((unsigned)op >= ARRAY_LEN(strs))
119,176✔
980
      return "???";
981
   else
982
      return strs[op];
119,176✔
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_COPY:
1913
            {
1914
               vcode_dump_reg(op->args.items[0]);
1915
               printf(" := %s ", vcode_op_string(op->kind));
1916
               vcode_dump_reg(op->args.items[1]);
1917
               if (op->args.count > 2) {
1918
                  printf(" count " );
1919
                  vcode_dump_reg(op->args.items[2]);
1920
               }
1921
            }
1922
            break;
1923

1924
         case VCODE_OP_SCHED_EVENT:
1925
         case VCODE_OP_CLEAR_EVENT:
1926
            {
1927
               printf("%s on ", vcode_op_string(op->kind));
1928
               vcode_dump_reg(op->args.items[0]);
1929
               printf(" count ");
1930
               vcode_dump_reg(op->args.items[1]);
1931
            }
1932
            break;
1933

1934
         case VCODE_OP_PCALL:
1935
            {
1936
               nvc_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1937
                          istr(op->func));
1938
               for (int i = 0; i < op->args.count; i++) {
1939
                  printf("%s", i > 0 ? ", " : " ");
1940
                  vcode_dump_reg(op->args.items[i]);
1941
               }
1942
               if (op->targets.count > 0)
1943
                  nvc_printf(" resume $yellow$%d$$", op->targets.items[0]);
1944
            }
1945
            break;
1946

1947
         case VCODE_OP_RESUME:
1948
            {
1949
               nvc_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1950
                            istr(op->func));
1951
            }
1952
            break;
1953

1954
         case VCODE_OP_MEMSET:
1955
            {
1956
               vcode_dump_reg(op->args.items[0]);
1957
               printf(" := %s ", vcode_op_string(op->kind));
1958
               vcode_dump_reg(op->args.items[1]);
1959
               printf(" length ");
1960
               vcode_dump_reg(op->args.items[2]);
1961
            }
1962
            break;
1963

1964
         case VCODE_OP_CASE:
1965
            {
1966
               printf("%s ", vcode_op_string(op->kind));
1967
               vcode_dump_reg(op->args.items[0]);
1968
               nvc_printf(" default $yellow$%d$$", op->targets.items[0]);
1969
               for (int i = 1; i < op->args.count; i++) {
1970
                  printf(" [");
1971
                  vcode_dump_reg(op->args.items[i]);
1972
                  nvc_printf(" $yellow$%d$$]", op->targets.items[i]);
1973
               }
1974
            }
1975
            break;
1976

1977
         case VCODE_OP_FILE_OPEN:
1978
            {
1979
               printf("%s ", vcode_op_string(op->kind));
1980
               vcode_dump_reg(op->args.items[0]);
1981
               printf(" name ");
1982
               vcode_dump_reg(op->args.items[1]);
1983
               printf(" length ");
1984
               vcode_dump_reg(op->args.items[2]);
1985
               printf(" kind ");
1986
               vcode_dump_reg(op->args.items[3]);
1987
               if (op->args.count == 5) {
1988
                  printf(" status ");
1989
                  vcode_dump_reg(op->args.items[4]);
1990
               }
1991
            }
1992
            break;
1993

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

2007
         case VCODE_OP_FILE_READ:
2008
            {
2009
               printf("%s ", vcode_op_string(op->kind));
2010
               vcode_dump_reg(op->args.items[0]);
2011
               printf(" ptr ");
2012
               vcode_dump_reg(op->args.items[1]);
2013
               if (op->args.count >= 3) {
2014
                  printf(" inlen ");
2015
                  vcode_dump_reg(op->args.items[2]);
2016
                  if (op->args.count >= 4) {
2017
                     printf(" outlen ");
2018
                     vcode_dump_reg(op->args.items[3]);
2019
                  }
2020
               }
2021
            }
2022
            break;
2023

2024
         case VCODE_OP_NULL:
2025
         case VCODE_OP_NEW:
2026
            {
2027
               col += vcode_dump_reg(op->result);
2028
               col += printf(" := %s", vcode_op_string(op->kind));
2029
               if (op->args.count == 1) {
2030
                  col += printf(" length ");
2031
                  col += vcode_dump_reg(op->args.items[0]);
2032
               }
2033
               vcode_dump_result_type(col, op);
2034
            }
2035
            break;
2036

2037
         case VCODE_OP_NULL_CHECK:
2038
            {
2039
               col += printf("%s ", vcode_op_string(op->kind));
2040
               col += vcode_dump_reg(op->args.items[0]);
2041
               col += printf(" locus ");
2042
               col += vcode_dump_reg(op->args.items[1]);
2043
            }
2044
            break;
2045

2046
         case VCODE_OP_DEALLOCATE:
2047
            {
2048
               col += printf("%s ", vcode_op_string(op->kind));
2049
               col += vcode_dump_reg(op->args.items[0]);
2050
            }
2051
            break;
2052

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

2062
         case VCODE_OP_LAST_EVENT:
2063
         case VCODE_OP_LAST_ACTIVE:
2064
         case VCODE_OP_DRIVING_VALUE:
2065
            {
2066
               col += vcode_dump_reg(op->result);
2067
               col += printf(" := %s ", vcode_op_string(op->kind));
2068
               col += vcode_dump_reg(op->args.items[0]);
2069
               if (op->args.count > 1) {
2070
                  col += printf(" length ");
2071
                  col += vcode_dump_reg(op->args.items[1]);
2072
               }
2073
               vcode_dump_result_type(col, op);
2074
            }
2075
            break;
2076

2077
         case VCODE_OP_ALIAS_SIGNAL:
2078
            {
2079
               printf("%s ", vcode_op_string(op->kind));
2080
               vcode_dump_reg(op->args.items[0]);
2081
               printf(" locus ");
2082
               vcode_dump_reg(op->args.items[1]);
2083
            }
2084
            break;
2085

2086
         case VCODE_OP_LENGTH_CHECK:
2087
            {
2088
               col += printf("%s left ", vcode_op_string(op->kind));
2089
               col += vcode_dump_reg(op->args.items[0]);
2090
               col += printf(" == right ");
2091
               col += vcode_dump_reg(op->args.items[1]);
2092
               col += printf(" locus ");
2093
               col += vcode_dump_reg(op->args.items[2]);
2094
               if (op->args.count > 3) {
2095
                  col += printf(" dim ");
2096
                  col += vcode_dump_reg(op->args.items[3]);
2097
               }
2098
            }
2099
            break;
2100

2101
         case VCODE_OP_EXPONENT_CHECK:
2102
         case VCODE_OP_ZERO_CHECK:
2103
            {
2104
               col += printf("%s ", vcode_op_string(op->kind));
2105
               col += vcode_dump_reg(op->args.items[0]);
2106
               col += printf(" locus ");
2107
               col += vcode_dump_reg(op->args.items[1]);
2108
            }
2109
            break;
2110

2111
         case VCODE_OP_INDEX_CHECK:
2112
         case VCODE_OP_RANGE_CHECK:
2113
            {
2114
               col += printf("%s ", vcode_op_string(op->kind));
2115
               col += vcode_dump_reg(op->args.items[0]);
2116
               col += printf(" left ");
2117
               col += vcode_dump_reg(op->args.items[1]);
2118
               col += printf(" right ");
2119
               col += vcode_dump_reg(op->args.items[2]);
2120
               col += printf(" dir ");
2121
               col += vcode_dump_reg(op->args.items[3]);
2122
               col += printf(" locus ");
2123
               col += vcode_dump_reg(op->args.items[4]);
2124
               if (op->args.items[5] != op->args.items[4]) {
2125
                  col += printf(" hint ");
2126
                  col += vcode_dump_reg(op->args.items[5]);
2127
               }
2128
            }
2129
            break;
2130

2131
         case VCODE_OP_DIR_CHECK:
2132
            {
2133
               col += printf("%s ", vcode_op_string(op->kind));
2134
               col += vcode_dump_reg(op->args.items[0]);
2135
               col += printf(" == ");
2136
               col += vcode_dump_reg(op->args.items[1]);
2137
               col += printf(" locus ");
2138
               col += vcode_dump_reg(op->args.items[2]);
2139
            }
2140
            break;
2141

2142
         case VCODE_OP_DEBUG_OUT:
2143
            {
2144
               col += printf("%s ", vcode_op_string(op->kind));
2145
               col += vcode_dump_reg(op->args.items[0]);
2146
            }
2147
            break;
2148

2149
         case VCODE_OP_COVER_STMT:
2150
         case VCODE_OP_COVER_BRANCH:
2151
         case VCODE_OP_COVER_EXPR:
2152
            {
2153
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2154
            }
2155
            break;
2156

2157
         case VCODE_OP_COVER_TOGGLE:
2158
         case VCODE_OP_COVER_STATE:
2159
            {
2160
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2161
               vcode_dump_reg(op->args.items[0]);
2162
            }
2163
            break;
2164

2165
         case VCODE_OP_UNDEFINED:
2166
            {
2167
               col += vcode_dump_reg(op->result);
2168
               col += printf(" := %s", vcode_op_string(op->kind));
2169
               vcode_dump_result_type(col, op);
2170
            }
2171
            break;
2172

2173
         case VCODE_OP_RANGE_LENGTH:
2174
         case VCODE_OP_RANGE_NULL:
2175
            {
2176
               col += vcode_dump_reg(op->result);
2177
               col += printf(" := %s left ", vcode_op_string(op->kind));
2178
               vcode_dump_reg(op->args.items[0]);
2179
               col += printf(" right ");
2180
               vcode_dump_reg(op->args.items[1]);
2181
               col += printf(" dir ");
2182
               col += vcode_dump_reg(op->args.items[2]);
2183
               vcode_dump_result_type(col, op);
2184
            }
2185
            break;
2186

2187
         case VCODE_OP_LINK_PACKAGE:
2188
            {
2189
               col += vcode_dump_reg(op->result);
2190
               col += nvc_printf(" := %s $magenta$%s$$",
2191
                                 vcode_op_string(op->kind), istr(op->ident));
2192
               if (op->args.count > 0) {
2193
                  col += printf(" locus ");
2194
                  col += vcode_dump_reg(op->args.items[0]);
2195
               }
2196
               vcode_dump_result_type(col, op);
2197
            }
2198
            break;
2199

2200
         case VCODE_OP_LINK_VAR:
2201
            {
2202
               col += vcode_dump_reg(op->result);
2203
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2204
               col += vcode_dump_reg(op->args.items[0]);
2205
               col += nvc_printf(" $magenta$%s$$", istr(op->ident));
2206
               vcode_dump_result_type(col, op);
2207
            }
2208
            break;
2209

2210
         case VCODE_OP_UNREACHABLE:
2211
            {
2212
               printf("%s", vcode_op_string(op->kind));
2213
               if (op->args.count > 0) {
2214
                  printf(" ");
2215
                  vcode_dump_reg(op->args.items[0]);
2216
               }
2217
            }
2218
            break;
2219

2220
         case VCODE_OP_DEBUG_LOCUS:
2221
            {
2222
               col += vcode_dump_reg(op->result);
2223
               col += nvc_printf(" := %s $magenta$", vcode_op_string(op->kind));
2224

2225
               tree_t t = tree_from_object(op->object);
2226
               if (t != NULL)
2227
                  col += printf("%s@", tree_kind_str(tree_kind(t)));
2228

2229
               col += nvc_printf("%p$$", op->object);
2230
               vcode_dump_result_type(col, op);
2231
            }
2232
            break;
2233

2234
         case VCODE_OP_ENTER_STATE:
2235
            {
2236
               printf("%s ", vcode_op_string(op->kind));
2237
               vcode_dump_reg(op->args.items[0]);
2238
               if (op->args.count > 1) {
2239
                  printf(" strong ");
2240
                  vcode_dump_reg(op->args.items[1]);
2241
               }
2242
            }
2243
            break;
2244

2245
         case VCODE_OP_REFLECT_VALUE:
2246
            {
2247
               col += vcode_dump_reg(op->result);
2248
               col += printf(" := %s ", vcode_op_string(op->kind));
2249
               vcode_dump_reg(op->args.items[0]);
2250
               col += printf(" context ");
2251
               vcode_dump_reg(op->args.items[1]);
2252
               col += printf(" locus ");
2253
               col += vcode_dump_reg(op->args.items[2]);
2254
               if (op->args.count > 3) {
2255
                  col += printf(" bounds ");
2256
                  col += vcode_dump_reg(op->args.items[3]);
2257
               }
2258
               vcode_dump_result_type(col, op);
2259
            }
2260
            break;
2261

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

2277
         case VCODE_OP_FUNCTION_TRIGGER:
2278
            {
2279
               col += vcode_dump_reg(op->result);
2280
               col += nvc_printf(" := %s $magenta$%s$$ ",
2281
                                 vcode_op_string(op->kind), istr(op->func));
2282
               for (int i = 0; i < op->args.count; i++) {
2283
                  if (i > 0) col += printf(", ");
2284
                  col += vcode_dump_reg(op->args.items[i]);
2285
               }
2286
               vcode_dump_result_type(col, op);
2287
            }
2288
            break;
2289

2290
         case VCODE_OP_OR_TRIGGER:
2291
         case VCODE_OP_CMP_TRIGGER:
2292
            {
2293
               col += vcode_dump_reg(op->result);
2294
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2295
               col += vcode_dump_reg(op->args.items[0]);
2296
               if (op->kind == VCODE_OP_OR_TRIGGER)
2297
                  col += printf(" || ");
2298
               else
2299
                  col += printf(" == ");
2300
               col += vcode_dump_reg(op->args.items[1]);
2301
               vcode_dump_result_type(col, op);
2302
            }
2303
            break;
2304

2305
         case VCODE_OP_ADD_TRIGGER:
2306
            {
2307
               printf("%s ", vcode_op_string(op->kind));
2308
               vcode_dump_reg(op->args.items[0]);
2309
            }
2310
            break;
2311

2312
         case VCODE_OP_PUT_CONVERSION:
2313
            {
2314
               nvc_printf("%s ", vcode_op_string(op->kind));
2315
               vcode_dump_reg(op->args.items[0]);
2316
               printf(" signal ");
2317
               vcode_dump_reg(op->args.items[1]);
2318
               printf(" count ");
2319
               vcode_dump_reg(op->args.items[2]);
2320
               printf(" values ");
2321
               vcode_dump_reg(op->args.items[3]);
2322
            }
2323
            break;
2324

2325
         case VCODE_OP_PORT_CONVERSION:
2326
            {
2327
               col += vcode_dump_reg(op->result);
2328
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2329
               col += vcode_dump_reg(op->args.items[0]);
2330
               if (op->args.count > 1) {
2331
                  col += printf(" effective ");
2332
                  col += vcode_dump_reg(op->args.items[1]);
2333
               }
2334
               vcode_dump_result_type(col, op);
2335
            }
2336
            break;
2337

2338
         case VCODE_OP_CONVERT_IN:
2339
         case VCODE_OP_CONVERT_OUT:
2340
            {
2341
               nvc_printf("%s ", vcode_op_string(op->kind));
2342
               vcode_dump_reg(op->args.items[0]);
2343
               printf(" signal ");
2344
               vcode_dump_reg(op->args.items[1]);
2345
               printf(" count ");
2346
               vcode_dump_reg(op->args.items[2]);
2347
            }
2348
            break;
2349

2350
         case VCODE_OP_BIND_FOREIGN:
2351
            {
2352
               nvc_printf("%s ", vcode_op_string(op->kind));
2353
               vcode_dump_reg(op->args.items[0]);
2354
               printf(" length ");
2355
               vcode_dump_reg(op->args.items[1]);
2356
               if (op->args.count > 2) {
2357
                  printf(" locus ");
2358
                  vcode_dump_reg(op->args.items[1]);
2359
               }
2360
            }
2361
            break;
2362

2363
         case VCODE_OP_INSTANCE_NAME:
2364
         case VCODE_OP_BIND_EXTERNAL:
2365
            {
2366
               col += vcode_dump_reg(op->result);
2367
               col += nvc_printf(" := %s ", vcode_op_string(op->kind));
2368
               col += vcode_dump_reg(op->args.items[0]);
2369
               col += nvc_printf(" scope $magenta$%s$$ ", istr(op->ident));
2370
               for (int i = 1; i < op->args.count; i++) {
2371
                  if (i > 1) col += printf(", ");
2372
                  col += vcode_dump_reg(op->args.items[i]);
2373
               }
2374
               vcode_dump_result_type(col, op);
2375
            }
2376
            break;
2377
         }
2378

2379
         if (j == mark_op && i == old_block)
2380
            nvc_printf("\t $red$<----$$");
2381

2382
         nvc_printf("$$\n");
2383

2384
         if (callback != NULL)
2385
            (*callback)(j, arg);
2386
      }
2387

2388
      if (b->ops.count == 0)
2389
         nvc_printf("  $yellow$%2d:$$ $red$Empty basic block$$\n", i);
2390
   }
2391

2392
   printf("\n");
2393
   fflush(stdout);
2394

2395
   active_block = old_block;
2396
}
2397
LCOV_EXCL_STOP
2398

2399
static inline bool vtype_eq_internal(const vtype_t *at, const vtype_t *bt)
35,990,453✔
2400
{
2401
   if (at->kind != bt->kind)
35,990,453✔
2402
      return false;
2403

2404
   switch (at->kind) {
16,070,291✔
2405
   case VCODE_TYPE_INT:
13,948,296✔
2406
      return (at->low == bt->low) && (at->high == bt->high);
25,943,167✔
2407
   case VCODE_TYPE_REAL:
929,353✔
2408
      return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
1,789,475✔
2409
   case VCODE_TYPE_CARRAY:
101,526✔
2410
      return at->size == bt->size && vtype_eq(at->elem, bt->elem);
108,825✔
2411
   case VCODE_TYPE_UARRAY:
80,585✔
2412
      return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
100,857✔
2413
   case VCODE_TYPE_POINTER:
476,084✔
2414
   case VCODE_TYPE_ACCESS:
2415
      return vtype_eq(at->pointed, bt->pointed);
476,084✔
2416
   case VCODE_TYPE_OFFSET:
2417
   case VCODE_TYPE_OPAQUE:
2418
   case VCODE_TYPE_DEBUG_LOCUS:
2419
   case VCODE_TYPE_TRIGGER:
2420
   case VCODE_TYPE_CONVERSION:
2421
      return true;
2422
   case VCODE_TYPE_RESOLUTION:
73,673✔
2423
   case VCODE_TYPE_CLOSURE:
2424
   case VCODE_TYPE_SIGNAL:
2425
   case VCODE_TYPE_FILE:
2426
      return vtype_eq(at->base, bt->base);
73,673✔
2427
   case VCODE_TYPE_RECORD:
61,428✔
2428
   case VCODE_TYPE_CONTEXT:
2429
      return at->name == bt->name;
61,428✔
2430
   default:
×
2431
      should_not_reach_here();
2432
   }
2433
}
2434

2435
bool vtype_eq(vcode_type_t a, vcode_type_t b)
4,548,447✔
2436
{
2437
   assert(active_unit != NULL);
4,548,447✔
2438

2439
   if (a == b)
4,548,447✔
2440
      return true;
2441
   else if (MASK_CONTEXT(a) == MASK_CONTEXT(b))
945,996✔
2442
      return false;   // Guaranteed by vtype_new
2443
   else {
2444
      const vtype_t *at = vcode_type_data(a);
118,183✔
2445
      const vtype_t *bt = vcode_type_data(b);
118,183✔
2446

2447
      return vtype_eq_internal(at, bt);
118,183✔
2448
   }
2449
}
2450

2451
void vcode_dump(void)
×
2452
{
2453
   vcode_dump_with_mark(-1, NULL, NULL);
×
2454
}
×
2455

2456
static vcode_type_t vtype_new(vtype_t *new)
3,336,322✔
2457
{
2458
   const int index = active_unit->types.count - 1;
3,336,322✔
2459

2460
   for (int i = 0; i < index; i++) {
36,529,247✔
2461
      const vtype_t *cmp = vtype_array_nth_ptr(&(active_unit->types), i);
35,872,270✔
2462
      if (vtype_eq_internal(new, cmp)) {
35,872,270✔
2463
         active_unit->types.count--;
2,679,345✔
2464
         return MAKE_HANDLE(active_unit->depth, i);
2,679,345✔
2465
      }
2466
   }
2467

2468
   return MAKE_HANDLE(active_unit->depth, index);
656,977✔
2469
}
2470

2471
vcode_type_t vtype_int(int64_t low, int64_t high)
2,311,687✔
2472
{
2473
   assert(active_unit != NULL);
2,311,687✔
2474

2475
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
2,311,687✔
2476
   n->kind = VCODE_TYPE_INT;
2,311,687✔
2477
   n->low  = low;
2,311,687✔
2478
   n->high = high;
2,311,687✔
2479

2480
   switch (bits_for_range(low, high)) {
2,311,687✔
2481
   case 64:
128,417✔
2482
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
128,417✔
2483
      break;
128,417✔
2484
   case 32:
620,353✔
2485
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
620,353✔
2486
      break;
620,353✔
2487
   case 16:
4,310✔
2488
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
4,310✔
2489
      break;
4,310✔
2490
   case 8:
908,085✔
2491
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
908,085✔
2492
      break;
908,085✔
2493
   case 1:
650,521✔
2494
      n->repr = VCODE_REPR_U1;
650,521✔
2495
      break;
650,521✔
2496
   case 0:
1✔
2497
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2498
      break;
1✔
2499
   default:
×
2500
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
2501
   }
2502

2503
   return vtype_new(n);
2,311,687✔
2504
}
2505

2506
vcode_type_t vtype_bool(void)
334,179✔
2507
{
2508
   return vtype_int(0, 1);
334,179✔
2509
}
2510

2511
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
54,965✔
2512
{
2513
   assert(active_unit != NULL);
54,965✔
2514

2515
   const vtype_kind_t ekind = vtype_kind(elem);
54,965✔
2516
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
54,965✔
2517
                "array types may not be nested");
2518

2519
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
54,965✔
2520
   memset(n, '\0', sizeof(vtype_t));
54,965✔
2521
   n->kind   = VCODE_TYPE_CARRAY;
54,965✔
2522
   n->elem   = elem;
54,965✔
2523
   n->bounds = bounds;
54,965✔
2524
   n->size   = MAX(size, 0);
54,965✔
2525

2526
   return vtype_new(n);
54,965✔
2527
}
2528

2529
vcode_type_t vtype_find_named_record(ident_t name)
37,676✔
2530
{
2531
   assert(active_unit != NULL);
37,676✔
2532

2533
   for (int i = 0; i < active_unit->types.count; i++) {
478,504✔
2534
      vtype_t *other = &(active_unit->types.items[i]);
466,912✔
2535
      if (other->kind == VCODE_TYPE_RECORD && other->name == name)
466,912✔
2536
         return MAKE_HANDLE(active_unit->depth, i);
26,084✔
2537
   }
2538

2539
   return VCODE_INVALID_TYPE;
2540
}
2541

2542
vcode_type_t vtype_named_record(ident_t name, const vcode_type_t *field_types,
11,592✔
2543
                                int nfields)
2544
{
2545
   assert(active_unit != NULL);
11,592✔
2546

2547
   vtype_t *data = NULL;
11,592✔
2548
   vcode_type_t handle = vtype_find_named_record(name);
11,592✔
2549
   if (handle == VCODE_INVALID_TYPE) {
11,592✔
2550
      data = vtype_array_alloc(&(active_unit->types));
5,796✔
2551
      memset(data, '\0', sizeof(vtype_t));
5,796✔
2552
      data->kind = VCODE_TYPE_RECORD;
5,796✔
2553
      data->name = name;
5,796✔
2554

2555
      handle = vtype_new(data);
5,796✔
2556
   }
2557
   else {
2558
      data = vcode_type_data(handle);
5,796✔
2559
      VCODE_ASSERT(data->fields.count == 0,
5,796✔
2560
                    "record type %s already defined", istr(name));
2561
   }
2562

2563
   vcode_type_array_resize(&(data->fields), 0, VCODE_INVALID_TYPE);
11,592✔
2564
   for (int i = 0; i < nfields; i++)
30,887✔
2565
      vcode_type_array_add(&(data->fields), field_types[i]);
19,295✔
2566

2567
   return handle;
11,592✔
2568
}
2569

2570
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
77,405✔
2571
{
2572
   assert(active_unit != NULL);
77,405✔
2573

2574
   const vtype_kind_t ekind = vtype_kind(elem);
77,405✔
2575
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
77,405✔
2576
                "array types may not be nested");
2577

2578
   VCODE_ASSERT(ndim > 0, "uarray must have at least one dimension");
77,405✔
2579

2580
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
77,405✔
2581
   memset(n, '\0', sizeof(vtype_t));
77,405✔
2582
   n->kind   = VCODE_TYPE_UARRAY;
77,405✔
2583
   n->elem   = elem;
77,405✔
2584
   n->bounds = bounds;
77,405✔
2585
   n->dims   = ndim;
77,405✔
2586

2587
   return vtype_new(n);
77,405✔
2588
}
2589

2590
vcode_type_t vtype_pointer(vcode_type_t to)
201,892✔
2591
{
2592
   assert(active_unit != NULL);
201,892✔
2593

2594
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
201,892✔
2595
   n->kind    = VCODE_TYPE_POINTER;
201,892✔
2596
   n->pointed = to;
201,892✔
2597

2598
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
201,892✔
2599
                "cannot get pointer to carray type");
2600

2601
   return vtype_new(n);
201,892✔
2602
}
2603

2604
vcode_type_t vtype_access(vcode_type_t to)
9,390✔
2605
{
2606
   assert(active_unit != NULL);
9,390✔
2607

2608
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
9,390✔
2609
   n->kind    = VCODE_TYPE_ACCESS;
9,390✔
2610
   n->pointed = to;
9,390✔
2611

2612
   return vtype_new(n);
9,390✔
2613
}
2614

2615
vcode_type_t vtype_signal(vcode_type_t base)
39,510✔
2616
{
2617
   assert(active_unit != NULL);
39,510✔
2618

2619
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
39,510✔
2620
   n->kind = VCODE_TYPE_SIGNAL;
39,510✔
2621
   n->base = base;
39,510✔
2622

2623
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
39,510✔
2624

2625
   return vtype_new(n);
39,510✔
2626
}
2627

2628
vcode_type_t vtype_resolution(vcode_type_t base)
8,235✔
2629
{
2630
   assert(active_unit != NULL);
8,235✔
2631

2632
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
8,235✔
2633
   n->kind = VCODE_TYPE_RESOLUTION;
8,235✔
2634
   n->base = base;
8,235✔
2635

2636
   return vtype_new(n);
8,235✔
2637
}
2638

2639
vcode_type_t vtype_closure(vcode_type_t result)
5,372✔
2640
{
2641
   assert(active_unit != NULL);
5,372✔
2642

2643
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
5,372✔
2644
   n->kind = VCODE_TYPE_CLOSURE;
5,372✔
2645
   n->base = result;
5,372✔
2646

2647
   return vtype_new(n);
5,372✔
2648
}
2649

2650
vcode_type_t vtype_context(ident_t name)
55,224✔
2651
{
2652
   assert(active_unit != NULL);
55,224✔
2653
   assert(name != NULL);
55,224✔
2654

2655
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
55,224✔
2656
   n->kind = VCODE_TYPE_CONTEXT;
55,224✔
2657
   n->name = name;
55,224✔
2658

2659
   return vtype_new(n);
55,224✔
2660
}
2661

2662
vcode_type_t vtype_file(vcode_type_t base)
1,827✔
2663
{
2664
   assert(active_unit != NULL);
1,827✔
2665

2666
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,827✔
2667
   n->kind = VCODE_TYPE_FILE;
1,827✔
2668
   n->base = base;
1,827✔
2669

2670
   return vtype_new(n);
1,827✔
2671
}
2672

2673
vcode_type_t vtype_offset(void)
292,393✔
2674
{
2675
   assert(active_unit != NULL);
292,393✔
2676

2677
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
292,393✔
2678
   n->kind = VCODE_TYPE_OFFSET;
292,393✔
2679
   n->low  = INT64_MIN;
292,393✔
2680
   n->high = INT64_MAX;
292,393✔
2681
   n->repr = VCODE_REPR_I64;
292,393✔
2682

2683
   return vtype_new(n);
292,393✔
2684
}
2685

2686
vcode_type_t vtype_time(void)
14,690✔
2687
{
2688
   return vtype_int(INT64_MIN, INT64_MAX);
14,690✔
2689
}
2690

2691
vcode_type_t vtype_char(void)
8,176✔
2692
{
2693
   return vtype_int(0, 255);
8,176✔
2694
}
2695

2696
vcode_type_t vtype_opaque(void)
3,474✔
2697
{
2698
   assert(active_unit != NULL);
3,474✔
2699

2700
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
3,474✔
2701
   n->kind = VCODE_TYPE_OPAQUE;
3,474✔
2702

2703
   return vtype_new(n);
3,474✔
2704
}
2705

2706
vcode_type_t vtype_debug_locus(void)
156,749✔
2707
{
2708
   assert(active_unit != NULL);
156,749✔
2709

2710
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
156,749✔
2711
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
156,749✔
2712

2713
   return vtype_new(n);
156,749✔
2714
}
2715

2716
vcode_type_t vtype_trigger(void)
386✔
2717
{
2718
   assert(active_unit != NULL);
386✔
2719

2720
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
386✔
2721
   n->kind = VCODE_TYPE_TRIGGER;
386✔
2722

2723
   return vtype_new(n);
386✔
2724
}
2725

2726
vcode_type_t vtype_conversion(void)
426✔
2727
{
2728
   assert(active_unit != NULL);
426✔
2729

2730
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
426✔
2731
   n->kind = VCODE_TYPE_CONVERSION;
426✔
2732

2733
   return vtype_new(n);
426✔
2734
}
2735

2736
vcode_type_t vtype_real(double low, double high)
111,591✔
2737
{
2738
   assert(active_unit != NULL);
111,591✔
2739

2740
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
111,591✔
2741
   n->kind  = VCODE_TYPE_REAL;
111,591✔
2742
   n->rlow  = low;
111,591✔
2743
   n->rhigh = high;
111,591✔
2744

2745
   return vtype_new(n);
111,591✔
2746
}
2747

2748
vtype_kind_t vtype_kind(vcode_type_t type)
4,819,188✔
2749
{
2750
   vtype_t *vt = vcode_type_data(type);
4,819,188✔
2751
   return vt->kind;
4,819,188✔
2752
}
2753

2754
vtype_repr_t vtype_repr(vcode_type_t type)
45,820✔
2755
{
2756
   vtype_t *vt = vcode_type_data(type);
45,820✔
2757
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
45,820✔
2758
   return vt->repr;
45,820✔
2759
}
2760

2761
vcode_type_t vtype_elem(vcode_type_t type)
159,971✔
2762
{
2763
   vtype_t *vt = vcode_type_data(type);
159,971✔
2764
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
159,971✔
2765
   return vt->elem;
159,971✔
2766
}
2767

2768
vcode_type_t vtype_base(vcode_type_t type)
52,504✔
2769
{
2770
   vtype_t *vt = vcode_type_data(type);
52,504✔
2771
   assert(vt->kind == VCODE_TYPE_SIGNAL || vt->kind == VCODE_TYPE_FILE
52,504✔
2772
          || vt->kind == VCODE_TYPE_RESOLUTION
2773
          || vt->kind == VCODE_TYPE_CLOSURE);
2774
   return vt->base;
52,504✔
2775
}
2776

2777
vcode_type_t vtype_bounds(vcode_type_t type)
22,077✔
2778
{
2779
   vtype_t *vt = vcode_type_data(type);
22,077✔
2780
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
22,077✔
2781
   return vt->bounds;
22,077✔
2782
}
2783

2784
unsigned vtype_dims(vcode_type_t type)
43,049✔
2785
{
2786
   vtype_t *vt = vcode_type_data(type);
43,049✔
2787
   assert(vt->kind == VCODE_TYPE_UARRAY);
43,049✔
2788
   return vt->dims;
43,049✔
2789
}
2790

2791
unsigned vtype_size(vcode_type_t type)
52,308✔
2792
{
2793
   vtype_t *vt = vcode_type_data(type);
52,308✔
2794
   assert(vt->kind == VCODE_TYPE_CARRAY);
52,308✔
2795
   return vt->size;
52,308✔
2796
}
2797

2798
int vtype_fields(vcode_type_t type)
8,021✔
2799
{
2800
   vtype_t *vt = vcode_type_data(type);
8,021✔
2801
   assert(vt->kind == VCODE_TYPE_RECORD);
8,021✔
2802
   return vt->fields.count;
8,021✔
2803
}
2804

2805
vcode_type_t vtype_field(vcode_type_t type, int field)
30,988✔
2806
{
2807
   vtype_t *vt = vcode_type_data(type);
30,988✔
2808
   assert(vt->kind == VCODE_TYPE_RECORD);
30,988✔
2809
   return vcode_type_array_nth(&(vt->fields), field);
30,988✔
2810
}
2811

2812
ident_t vtype_name(vcode_type_t type)
19,298✔
2813
{
2814
   vtype_t *vt = vcode_type_data(type);
19,298✔
2815
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
19,298✔
2816
   return vt->name;
19,298✔
2817
}
2818

2819
vcode_type_t vtype_pointed(vcode_type_t type)
337,367✔
2820
{
2821
   vtype_t *vt = vcode_type_data(type);
337,367✔
2822
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
337,367✔
2823
   return vt->pointed;
337,367✔
2824
}
2825

2826
int64_t vtype_low(vcode_type_t type)
247,003✔
2827
{
2828
   vtype_t *vt = vcode_type_data(type);
247,003✔
2829
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
247,003✔
2830
   return vt->low;
247,003✔
2831
}
2832

2833
int64_t vtype_high(vcode_type_t type)
244,287✔
2834
{
2835
   vtype_t *vt = vcode_type_data(type);
244,287✔
2836
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
244,287✔
2837
   return vt->high;
244,287✔
2838
}
2839

2840
static bool vtype_is_pointer(vcode_type_t type, vtype_kind_t to)
1,564✔
2841
{
2842
   return vtype_kind(type) == VCODE_TYPE_POINTER
1,564✔
2843
      && vtype_kind(vtype_pointed(type)) == to;
1,564✔
2844
}
2845

2846
bool vtype_is_scalar(vcode_type_t type)
418,756✔
2847
{
2848
   const vtype_kind_t kind = vtype_kind(type);
418,756✔
2849
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
418,756✔
2850
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
162,670✔
2851
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2852
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2853
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER
2854
      || kind == VCODE_TYPE_RESOLUTION;
418,756✔
2855
}
2856

2857
bool vtype_is_numeric(vcode_type_t type)
18,928✔
2858
{
2859
   const vtype_kind_t kind = vtype_kind(type);
18,928✔
2860
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
18,928✔
2861
      || kind == VCODE_TYPE_REAL;
18,928✔
2862
}
2863

2864
bool vtype_is_composite(vcode_type_t type)
31,722✔
2865
{
2866
   const vtype_kind_t kind = vtype_kind(type);
31,722✔
2867
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
31,722✔
2868
}
2869

2870
bool vtype_is_signal(vcode_type_t type)
153,849✔
2871
{
2872
   vtype_t *vt = vcode_type_data(type);
275,295✔
2873
   switch (vt->kind) {
275,295✔
2874
   case VCODE_TYPE_SIGNAL:
2875
      return true;
2876
   case VCODE_TYPE_POINTER:
71,708✔
2877
      return vtype_is_signal(vt->pointed);
71,708✔
2878
   case VCODE_TYPE_RECORD:
2879
      for (int i = 0; i < vt->fields.count; i++) {
34,338✔
2880
         if (vtype_is_signal(vt->fields.items[i]))
27,125✔
2881
            return true;
2882
      }
2883
      return false;
2884
   case VCODE_TYPE_UARRAY:
49,738✔
2885
   case VCODE_TYPE_CARRAY:
2886
      return vtype_is_signal(vt->elem);
49,738✔
2887
   default:
119,096✔
2888
      return false;
119,096✔
2889
   }
2890
}
2891

2892
int vtype_repr_bits(vtype_repr_t repr)
×
2893
{
2894
   switch (repr) {
×
2895
   case VCODE_REPR_U1: return 1;
2896
   case VCODE_REPR_U8: case VCODE_REPR_I8: return 8;
2897
   case VCODE_REPR_U16: case VCODE_REPR_I16: return 16;
2898
   case VCODE_REPR_U32: case VCODE_REPR_I32: return 32;
2899
   case VCODE_REPR_U64: case VCODE_REPR_I64: return 64;
2900
   default: return -1;
2901
   }
2902
}
2903

2904
bool vtype_repr_signed(vtype_repr_t repr)
×
2905
{
2906
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
×
2907
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
×
2908
}
2909

2910
static int64_t vtype_repr_low(vtype_repr_t repr)
13,651✔
2911
{
2912
   switch (repr) {
13,651✔
2913
   case VCODE_REPR_U1:
2914
   case VCODE_REPR_U8:
2915
   case VCODE_REPR_U16:
2916
   case VCODE_REPR_U32:
2917
   case VCODE_REPR_U64: return 0;
2918
   case VCODE_REPR_I8:  return INT8_MIN;
2919
   case VCODE_REPR_I16: return INT16_MIN;
2920
   case VCODE_REPR_I32: return INT32_MIN;
2921
   case VCODE_REPR_I64: return INT64_MIN;
2922
   default:             return 0;
2923
   }
2924
}
2925

2926
static uint64_t vtype_repr_high(vtype_repr_t repr)
13,651✔
2927
{
2928
   switch (repr) {
13,651✔
2929
   case VCODE_REPR_U1:  return 1;
2930
   case VCODE_REPR_U8:  return UINT8_MAX;
2931
   case VCODE_REPR_U16: return UINT16_MAX;
2932
   case VCODE_REPR_U32: return UINT32_MAX;
2933
   case VCODE_REPR_U64: return UINT64_MAX;
2934
   case VCODE_REPR_I8:  return INT8_MAX;
2935
   case VCODE_REPR_I16: return INT16_MAX;
2936
   case VCODE_REPR_I32: return INT32_MAX;
2937
   case VCODE_REPR_I64: return INT64_MAX;
2938
   default:             return 0;
2939
   }
2940
}
2941

2942
static bool vtype_clamp_to_repr(vtype_repr_t repr, int64_t *low, int64_t *high)
13,651✔
2943
{
2944
   int64_t clamp_low = vtype_repr_low(repr);
13,651✔
2945
   uint64_t clamp_high = vtype_repr_high(repr);
13,651✔
2946

2947
   if (*low >= clamp_low && *high <= clamp_high)
13,651✔
2948
      return true;
2949
   else {
2950
      *low = MAX(clamp_low, *low);
6,356✔
2951
      *high = MIN(clamp_high, *high);
6,356✔
2952
      return false;
6,356✔
2953
   }
2954
}
2955

2956
int vcode_count_params(void)
13,481✔
2957
{
2958
   assert(active_unit != NULL);
13,481✔
2959
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
13,481✔
2960
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2961
          || active_unit->kind == VCODE_UNIT_PROPERTY
2962
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2963

2964
   return active_unit->params.count;
13,481✔
2965
}
2966

2967
vcode_type_t vcode_param_type(int param)
31,918✔
2968
{
2969
   assert(active_unit != NULL);
31,918✔
2970
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
31,918✔
2971
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2972
          || active_unit->kind == VCODE_UNIT_PROPERTY
2973
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2974
   assert(param < active_unit->params.count);
31,918✔
2975

2976
   return active_unit->params.items[param].type;
31,918✔
2977
}
2978

2979
ident_t vcode_param_name(int param)
31,918✔
2980
{
2981
   assert(active_unit != NULL);
31,918✔
2982
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
31,918✔
2983
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2984
          || active_unit->kind == VCODE_UNIT_PROPERTY
2985
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2986
   assert(param < active_unit->params.count);
31,918✔
2987

2988
   return active_unit->params.items[param].name;
31,918✔
2989
}
2990

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

3000
   return active_unit->params.items[param].reg;
31,918✔
3001
}
3002

3003
vcode_block_t emit_block(void)
137,482✔
3004
{
3005
   assert(active_unit != NULL);
137,482✔
3006

3007
   vcode_block_t bnum = active_unit->blocks.count;
137,482✔
3008

3009
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
137,482✔
3010
   memset(bptr, '\0', sizeof(block_t));
137,482✔
3011

3012
   if (active_block != VCODE_INVALID_BLOCK)
137,482✔
3013
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
86,543✔
3014
   else
3015
      bptr->last_loc = LOC_INVALID;
50,939✔
3016

3017
   return bnum;
137,482✔
3018
}
3019

3020
void vcode_select_unit(vcode_unit_t unit)
179,048✔
3021
{
3022
   active_unit  = unit;
179,048✔
3023
   active_block = VCODE_INVALID_BLOCK;
179,048✔
3024
}
179,048✔
3025

3026
void vcode_select_block(vcode_block_t block)
322,271✔
3027
{
3028
   assert(active_unit != NULL);
322,271✔
3029
   active_block = block;
322,271✔
3030
}
322,271✔
3031

3032
vcode_block_t vcode_active_block(void)
731✔
3033
{
3034
   assert(active_unit != NULL);
731✔
3035
   assert(active_block != -1);
731✔
3036
   return active_block;
731✔
3037
}
3038

3039
const loc_t *vcode_last_loc(void)
1,179,829✔
3040
{
3041
   return &(vcode_block_data()->last_loc);
1,179,829✔
3042
}
3043

3044
vcode_unit_t vcode_active_unit(void)
735✔
3045
{
3046
   assert(active_unit != NULL);
735✔
3047
   return active_unit;
735✔
3048
}
3049

3050
ident_t vcode_unit_name(vcode_unit_t vu)
157,748✔
3051
{
3052
   assert(vu != NULL);
157,748✔
3053
   return vu->name;
157,748✔
3054
}
3055

3056
bool vcode_unit_has_undefined(vcode_unit_t vu)
11,158✔
3057
{
3058
   assert(vu != NULL);
11,158✔
3059
   return !!(vu->flags & UNIT_UNDEFINED);
11,158✔
3060
}
3061

3062
int vcode_unit_depth(vcode_unit_t vu)
×
3063
{
3064
   assert(vu != NULL);
×
3065
   return vu->depth;
×
3066
}
3067

3068
void vcode_set_result(vcode_type_t type)
21,550✔
3069
{
3070
   assert(active_unit != NULL);
21,550✔
3071
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
21,550✔
3072
          || active_unit->kind == VCODE_UNIT_THUNK);
3073

3074
   active_unit->result = type;
21,550✔
3075
}
21,550✔
3076

3077
vcode_type_t vcode_unit_result(vcode_unit_t vu)
23,600✔
3078
{
3079
   assert(vu != NULL);
23,600✔
3080
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
23,600✔
3081
   return vu->result;
23,600✔
3082
}
3083

3084
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
140,905✔
3085
{
3086
   assert(vu != NULL);
140,905✔
3087
   return vu->kind;
140,905✔
3088
}
3089

3090
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
78,362✔
3091
{
3092
   assert(vu != NULL);
78,362✔
3093
   return vu->context;
78,362✔
3094
}
3095

3096
object_t *vcode_unit_object(vcode_unit_t vu)
88,228✔
3097
{
3098
   assert(vu != NULL);
88,228✔
3099
   return vu->object;
88,228✔
3100
}
3101

3102
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
62,109✔
3103
{
3104
   int hops = 0;
62,109✔
3105
   for (; (unit = unit->context); hops++)
152,806✔
3106
      ;
3107
   return hops;
62,109✔
3108
}
3109

3110
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
27,832✔
3111
{
3112
   assert(context->kind != VCODE_UNIT_THUNK);
27,832✔
3113

3114
   child->next = NULL;
27,832✔
3115
   if (context->children == NULL)
27,832✔
3116
      context->children = child;
12,411✔
3117
   else {
3118
      vcode_unit_t it;
3119
      for (it = context->children; it->next != NULL; it = it->next)
71,733✔
3120
         ;
3121
      it->next = child;
15,421✔
3122
   }
3123
}
27,832✔
3124

3125
vcode_unit_t emit_function(ident_t name, object_t *obj, vcode_unit_t context)
12,491✔
3126
{
3127
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
12,491✔
3128
   vu->kind     = VCODE_UNIT_FUNCTION;
12,491✔
3129
   vu->name     = name;
12,491✔
3130
   vu->context  = context;
12,491✔
3131
   vu->result   = VCODE_INVALID_TYPE;
12,491✔
3132
   vu->depth    = vcode_unit_calc_depth(vu);
12,491✔
3133
   vu->object   = obj;
12,491✔
3134

3135
   vcode_add_child(context, vu);
12,491✔
3136

3137
   vcode_select_unit(vu);
12,491✔
3138
   vcode_select_block(emit_block());
12,491✔
3139
   emit_debug_info(&(obj->loc));
12,491✔
3140

3141
   return vu;
12,491✔
3142
}
3143

3144
vcode_unit_t emit_procedure(ident_t name, object_t *obj, vcode_unit_t context)
216✔
3145
{
3146
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
216✔
3147
   vu->kind     = VCODE_UNIT_PROCEDURE;
216✔
3148
   vu->name     = name;
216✔
3149
   vu->context  = context;
216✔
3150
   vu->result   = VCODE_INVALID_TYPE;
216✔
3151
   vu->depth    = vcode_unit_calc_depth(vu);
216✔
3152
   vu->object   = obj;
216✔
3153

3154
   vcode_add_child(context, vu);
216✔
3155

3156
   vcode_select_unit(vu);
216✔
3157
   vcode_select_block(emit_block());
216✔
3158
   emit_debug_info(&(obj->loc));
216✔
3159

3160
   return vu;
216✔
3161
}
3162

3163
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
7,624✔
3164
{
3165
   assert(context->kind == VCODE_UNIT_INSTANCE);
7,624✔
3166

3167
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
7,624✔
3168
   vu->kind     = VCODE_UNIT_PROCESS;
7,624✔
3169
   vu->name     = name;
7,624✔
3170
   vu->context  = context;
7,624✔
3171
   vu->depth    = vcode_unit_calc_depth(vu);
7,624✔
3172
   vu->result   = VCODE_INVALID_TYPE;
7,624✔
3173
   vu->object   = obj;
7,624✔
3174

3175
   vcode_add_child(context, vu);
7,624✔
3176

3177
   vcode_select_unit(vu);
7,624✔
3178
   vcode_select_block(emit_block());
7,624✔
3179
   emit_debug_info(&(obj->loc));
7,624✔
3180

3181
   return vu;
7,624✔
3182
}
3183

3184
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
10,016✔
3185
{
3186
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
10,016✔
3187

3188
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
10,016✔
3189
   vu->kind     = VCODE_UNIT_INSTANCE;
10,016✔
3190
   vu->name     = name;
10,016✔
3191
   vu->context  = context;
10,016✔
3192
   vu->depth    = vcode_unit_calc_depth(vu);
10,016✔
3193
   vu->result   = VCODE_INVALID_TYPE;
10,016✔
3194
   vu->object   = obj;
10,016✔
3195

3196
   if (context != NULL)
10,016✔
3197
      vcode_add_child(context, vu);
6,252✔
3198

3199
   vcode_select_unit(vu);
10,016✔
3200
   vcode_select_block(emit_block());
10,016✔
3201
   emit_debug_info(&(obj->loc));
10,016✔
3202

3203
   return vu;
10,016✔
3204
}
3205

3206
vcode_unit_t emit_package(ident_t name, object_t *obj, vcode_unit_t context)
8,648✔
3207
{
3208
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,648✔
3209
   vu->kind     = VCODE_UNIT_PACKAGE;
8,648✔
3210
   vu->name     = name;
8,648✔
3211
   vu->context  = context;
8,648✔
3212
   vu->depth    = vcode_unit_calc_depth(vu);
8,648✔
3213
   vu->result   = VCODE_INVALID_TYPE;
8,648✔
3214
   vu->object   = obj;
8,648✔
3215

3216
   if (context != NULL)
8,648✔
3217
      vcode_add_child(context, vu);
189✔
3218

3219
   vcode_select_unit(vu);
8,648✔
3220
   vcode_select_block(emit_block());
8,648✔
3221
   emit_debug_info(&(obj->loc));
8,648✔
3222

3223
   return vu;
8,648✔
3224
}
3225

3226
vcode_unit_t emit_protected(ident_t name, object_t *obj, vcode_unit_t context)
534✔
3227
{
3228
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
534✔
3229
   vu->kind     = VCODE_UNIT_PROTECTED;
534✔
3230
   vu->name     = name;
534✔
3231
   vu->context  = context;
534✔
3232
   vu->depth    = vcode_unit_calc_depth(vu);
534✔
3233
   vu->result   = VCODE_INVALID_TYPE;
534✔
3234
   vu->object   = obj;
534✔
3235

3236
   if (context != NULL)
534✔
3237
      vcode_add_child(context, vu);
534✔
3238

3239
   vcode_select_unit(vu);
534✔
3240
   vcode_select_block(emit_block());
534✔
3241
   emit_debug_info(&(obj->loc));
534✔
3242

3243
   return vu;
534✔
3244
}
3245

3246
vcode_unit_t emit_property(ident_t name, object_t *obj, vcode_unit_t context)
240✔
3247
{
3248
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
240✔
3249
   vu->kind     = VCODE_UNIT_PROPERTY;
240✔
3250
   vu->name     = name;
240✔
3251
   vu->context  = context;
240✔
3252
   vu->depth    = vcode_unit_calc_depth(vu);
240✔
3253
   vu->result   = VCODE_INVALID_TYPE;
240✔
3254
   vu->object   = obj;
240✔
3255

3256
   if (context != NULL)
240✔
3257
      vcode_add_child(context, vu);
240✔
3258

3259
   vcode_select_unit(vu);
240✔
3260
   vcode_select_block(emit_block());
240✔
3261
   emit_debug_info(&(obj->loc));
240✔
3262

3263
   return vu;
240✔
3264
}
3265

3266
vcode_unit_t emit_thunk(ident_t name, object_t *obj, vcode_unit_t context)
11,170✔
3267
{
3268
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
11,170✔
3269
   vu->kind     = VCODE_UNIT_THUNK;
11,170✔
3270
   vu->name     = name;
11,170✔
3271
   vu->context  = context;
11,170✔
3272
   vu->depth    = vcode_unit_calc_depth(vu);
11,170✔
3273
   vu->result   = VCODE_INVALID_TYPE;
11,170✔
3274
   vu->depth    = vcode_unit_calc_depth(vu);
11,170✔
3275
   vu->object   = obj;
11,170✔
3276

3277
   if (context != NULL)
11,170✔
3278
      vcode_add_child(context, vu);
286✔
3279

3280
   vcode_select_unit(vu);
11,170✔
3281
   vcode_select_block(emit_block());
11,170✔
3282

3283
   return vu;
11,170✔
3284
}
3285

3286
void emit_assert(vcode_reg_t value, vcode_reg_t message, vcode_reg_t length,
14,592✔
3287
                 vcode_reg_t severity, vcode_reg_t locus, vcode_reg_t hint_left,
3288
                 vcode_reg_t hint_right)
3289
{
3290
   int64_t value_const;
14,592✔
3291
   if (vcode_reg_const(value, &value_const) && value_const != 0) {
14,592✔
3292
      emit_comment("Always true assertion on r%d", value);
30✔
3293
      return;
30✔
3294
   }
3295

3296
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
14,562✔
3297
   vcode_add_arg(op, value);
14,562✔
3298
   vcode_add_arg(op, severity);
14,562✔
3299
   vcode_add_arg(op, message);
14,562✔
3300
   vcode_add_arg(op, length);
14,562✔
3301
   vcode_add_arg(op, locus);
14,562✔
3302

3303
   if (hint_left != VCODE_INVALID_REG) {
14,562✔
3304
      vcode_add_arg(op, hint_left);
6,048✔
3305
      vcode_add_arg(op, hint_right);
6,048✔
3306

3307
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
6,048✔
3308
                   "left hint must be scalar");
3309
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
6,048✔
3310
                   "right hint must be scalar");
3311
   }
3312

3313
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
14,562✔
3314
                "value parameter to assert is not bool");
3315
   VCODE_ASSERT(message == VCODE_INVALID_REG
14,562✔
3316
                || vcode_reg_kind(message) == VCODE_TYPE_POINTER,
3317
                "message parameter to assert is not a pointer");
3318
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
14,562✔
3319
                "value parameter to assert is not bool");
3320
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
14,562✔
3321
                "locus argument to report must be a debug locus");
3322
}
3323

3324
void emit_report(vcode_reg_t message, vcode_reg_t length, vcode_reg_t severity,
2,077✔
3325
                 vcode_reg_t locus)
3326
{
3327
   op_t *op = vcode_add_op(VCODE_OP_REPORT);
2,077✔
3328
   vcode_add_arg(op, severity);
2,077✔
3329
   vcode_add_arg(op, message);
2,077✔
3330
   vcode_add_arg(op, length);
2,077✔
3331
   vcode_add_arg(op, locus);
2,077✔
3332

3333
   VCODE_ASSERT(vcode_reg_kind(message) == VCODE_TYPE_POINTER,
2,077✔
3334
                "message parameter to report is not a pointer");
3335
   VCODE_ASSERT(vtype_eq(vtype_pointed(vcode_reg_type(message)), vtype_char()),
2,077✔
3336
                "message parameter to report is not a character pointer");
3337
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,077✔
3338
                "locus argument to report must be a debug locus");
3339
}
2,077✔
3340

3341
vcode_reg_t emit_cmp(vcode_cmp_t cmp, vcode_reg_t lhs, vcode_reg_t rhs)
34,389✔
3342
{
3343
   if (lhs == rhs) {
34,389✔
3344
      if (cmp == VCODE_CMP_EQ)
398✔
3345
         return emit_const(vtype_bool(), 1);
242✔
3346
      else if (cmp == VCODE_CMP_NEQ)
156✔
3347
         return emit_const(vtype_bool(), 0);
×
3348
      else if (cmp == VCODE_CMP_LEQ || cmp == VCODE_CMP_GEQ)
156✔
3349
         return emit_const(vtype_bool(), 1);
×
3350
      else if (cmp == VCODE_CMP_LT || cmp == VCODE_CMP_GT)
156✔
3351
         return emit_const(vtype_bool(), 0);
156✔
3352
   }
3353

3354
   int64_t lconst, rconst;
33,991✔
3355
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)) {
33,991✔
3356
      switch (cmp) {
334✔
3357
      case VCODE_CMP_EQ:
312✔
3358
         return emit_const(vtype_bool(), lconst == rconst);
312✔
3359
      case VCODE_CMP_NEQ:
3✔
3360
         return emit_const(vtype_bool(), lconst != rconst);
3✔
3361
      case VCODE_CMP_LT:
9✔
3362
         return emit_const(vtype_bool(), lconst < rconst);
9✔
3363
      case VCODE_CMP_GT:
10✔
3364
         return emit_const(vtype_bool(), lconst > rconst);
10✔
3365
      case VCODE_CMP_LEQ:
×
3366
         return emit_const(vtype_bool(), lconst <= rconst);
×
3367
      case VCODE_CMP_GEQ:
×
3368
         return emit_const(vtype_bool(), lconst >= rconst);
×
3369
      default:
×
3370
         fatal_trace("cannot fold comparison %d", cmp);
3371
      }
3372
   }
3373

3374
   // Reuse any previous operation in this block with the same arguments
3375
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
658,066✔
3376
      if (other->args.count == 2 && other->args.items[0] == lhs
24,133✔
3377
          && other->args.items[1] == rhs && other->cmp == cmp)
2,246✔
3378
         return other->result;
193✔
3379
   }
3380

3381
   op_t *op = vcode_add_op(VCODE_OP_CMP);
33,464✔
3382
   vcode_add_arg(op, lhs);
33,464✔
3383
   vcode_add_arg(op, rhs);
33,464✔
3384
   op->cmp    = cmp;
33,464✔
3385
   op->result = vcode_add_reg(vtype_bool());
33,464✔
3386

3387
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
33,464✔
3388
                "arguments to cmp are not the same type");
3389

3390
   return op->result;
33,464✔
3391
}
3392

3393
vcode_reg_t emit_fcall(ident_t func, vcode_type_t type, vcode_type_t bounds,
34,772✔
3394
                       const vcode_reg_t *args, int nargs)
3395
{
3396
   op_t *o = vcode_add_op(VCODE_OP_FCALL);
34,772✔
3397
   o->func = func;
34,772✔
3398
   o->type = type;
34,772✔
3399
   for (int i = 0; i < nargs; i++)
122,197✔
3400
      vcode_add_arg(o, args[i]);
87,425✔
3401

3402
   for (int i = 0; i < nargs; i++)
122,197✔
3403
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
87,425✔
3404
                   "invalid argument to function");
3405

3406
   if (type == VCODE_INVALID_TYPE)
34,772✔
3407
      return (o->result = VCODE_INVALID_REG);
5,493✔
3408
   else {
3409
      o->result = vcode_add_reg(type);
29,279✔
3410

3411
      reg_t *rr = vcode_reg_data(o->result);
29,279✔
3412
      rr->bounds = bounds;
29,279✔
3413

3414
      return o->result;
29,279✔
3415
   }
3416
}
3417

3418
void emit_pcall(ident_t func, const vcode_reg_t *args, int nargs,
843✔
3419
                vcode_block_t resume_bb)
3420
{
3421
   op_t *o = vcode_add_op(VCODE_OP_PCALL);
843✔
3422
   o->func = func;
843✔
3423
   for (int i = 0; i < nargs; i++)
2,845✔
3424
      vcode_add_arg(o, args[i]);
2,002✔
3425

3426
   vcode_block_array_add(&(o->targets), resume_bb);
843✔
3427

3428
   for (int i = 0; i < nargs; i++)
2,845✔
3429
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
2,002✔
3430
                   "invalid argument to procedure");
3431

3432
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
843✔
3433
                "first argument to VHDL procedure must be context pointer");
3434
}
843✔
3435

3436
vcode_reg_t emit_syscall(ident_t func, vcode_type_t type, vcode_type_t bounds,
×
3437
                         vcode_reg_t locus, const vcode_reg_t *args, int nargs)
3438
{
3439
   op_t *o = vcode_add_op(VCODE_OP_SYSCALL);
×
3440
   o->func = func;
×
3441
   o->type = type;
×
3442
   vcode_add_arg(o, locus);
×
3443
   for (int i = 0; i < nargs; i++)
×
3444
      vcode_add_arg(o, args[i]);
×
3445

3446
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
×
3447
                "locus argument to syscall must be a debug locus");
3448

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

3452
   if (type == VCODE_INVALID_TYPE)
×
3453
      return (o->result = VCODE_INVALID_REG);
×
3454
   else {
3455
      o->result = vcode_add_reg(type);
×
3456

3457
      reg_t *rr = vcode_reg_data(o->result);
×
3458
      rr->bounds = bounds;
×
3459

3460
      return o->result;
×
3461
   }
3462
}
3463

3464
vcode_reg_t emit_alloc(vcode_type_t type, vcode_type_t bounds,
7,270✔
3465
                       vcode_reg_t count)
3466
{
3467
   op_t *op = vcode_add_op(VCODE_OP_ALLOC);
7,270✔
3468
   op->type    = type;
7,270✔
3469
   op->result  = vcode_add_reg(vtype_pointer(type));
7,270✔
3470
   vcode_add_arg(op, count);
7,270✔
3471

3472
   const vtype_kind_t tkind = vtype_kind(type);
7,270✔
3473
   VCODE_ASSERT(tkind != VCODE_TYPE_CARRAY && tkind != VCODE_TYPE_UARRAY,
7,270✔
3474
                "alloca element type cannot be array");
3475
   VCODE_ASSERT(count != VCODE_INVALID_REG,
7,270✔
3476
                "alloca must have valid count argument");
3477

3478
   reg_t *r = vcode_reg_data(op->result);
7,270✔
3479
   r->bounds = bounds;
7,270✔
3480

3481
   return op->result;
7,270✔
3482
}
3483

3484
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
1,436,942✔
3485
{
3486
   // Reuse any previous constant in this block with the same type and value
3487
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
32,746,831✔
3488
      if (other->value == value && vtype_eq(type, other->type))
11,578,683✔
3489
         return other->result;
988,766✔
3490
   }
3491

3492
   op_t *op = vcode_add_op(VCODE_OP_CONST);
448,176✔
3493
   op->value  = value;
448,176✔
3494
   op->type   = type;
448,176✔
3495
   op->result = vcode_add_reg(type);
448,176✔
3496

3497
   vtype_kind_t type_kind = vtype_kind(type);
448,176✔
3498
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
448,176✔
3499
                "constant must have integer or offset type");
3500

3501
   reg_t *r = vcode_reg_data(op->result);
448,176✔
3502
   r->bounds = vtype_int(value, value);
448,176✔
3503

3504
   return op->result;
448,176✔
3505
}
3506

3507
vcode_reg_t emit_const_real(vcode_type_t type, double value)
66,690✔
3508
{
3509
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REAL) {
1,955,499✔
3510
      if (other->real == value && other->type == type)
907,873✔
3511
         return other->result;
25,295✔
3512
   }
3513

3514
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
41,395✔
3515
   op->real   = value;
41,395✔
3516
   op->type   = type;
41,395✔
3517
   op->result = vcode_add_reg(op->type);
41,395✔
3518

3519
   reg_t *r = vcode_reg_data(op->result);
41,395✔
3520
   r->bounds = vtype_real(value, value);
41,395✔
3521

3522
   return op->result;
41,395✔
3523
}
3524

3525
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
37,220✔
3526
{
3527
   vtype_kind_t kind = vtype_kind(type);
37,220✔
3528

3529
   // Reuse any previous operation in this block with the same arguments
3530
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
1,910,409✔
3531
      if (other->args.count != num)
150,886✔
3532
         continue;
89,921✔
3533
      else if (!vtype_eq(vcode_reg_type(other->result), type))
60,965✔
3534
         continue;
2,298✔
3535

3536
      bool match = true;
3537
      for (int i = 0; match && i < num; i++) {
421,685✔
3538
         if (other->args.items[i] != values[i])
363,018✔
3539
            match = false;
51,597✔
3540
      }
3541

3542
      if (match) return other->result;
58,667✔
3543
   }
3544

3545
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
30,150✔
3546
   op->result = vcode_add_reg(type);
30,150✔
3547

3548
   for (int i = 0; i < num; i++)
1,668,784✔
3549
      vcode_add_arg(op, values[i]);
1,638,634✔
3550

3551
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
30,150✔
3552
                "constant array must have constrained array type");
3553
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
30,150✔
3554
                vtype_size(type), num);
3555

3556
#ifdef DEBUG
3557
   vcode_type_t elem = vtype_elem(type);
30,150✔
3558
   for (int i = 0; i < num; i++) {
1,668,784✔
3559
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
1,638,634✔
3560
                   "wrong element type for item %d", i);
3561
      vcode_assert_const(values[i], "array");
1,638,634✔
3562
   }
3563
#endif
3564

3565
   reg_t *r = vcode_reg_data(op->result);
30,150✔
3566
   r->bounds = vtype_elem(type);
30,150✔
3567

3568
   return op->result;
30,150✔
3569
}
3570

3571
vcode_reg_t emit_const_rep(vcode_type_t type, vcode_reg_t value, int rep)
500✔
3572
{
3573
   // Reuse any previous operation in this block with the same arguments
3574
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REP) {
8,311✔
3575
      if (other->args.items[0] == value && other->value == rep)
607✔
3576
         return other->result;
198✔
3577
   }
3578

3579
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
302✔
3580
   op->value = rep;
302✔
3581
   vcode_add_arg(op, value);
302✔
3582

3583
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
302✔
3584
                "constant array must have constrained array type");
3585
   VCODE_ASSERT(rep >= 0, "repeat count must be non-negative");
302✔
3586

3587
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
302✔
3588

3589
   op->result = vcode_add_reg(type);
302✔
3590

3591
   reg_t *r = vcode_reg_data(op->result);
302✔
3592
   r->bounds = vtype_bounds(type);
302✔
3593

3594
   return op->result;
302✔
3595
}
3596

3597
vcode_reg_t emit_const_record(vcode_type_t type, vcode_reg_t *values, int num)
2,519✔
3598
{
3599
   // Reuse any previous constant in this block with the same type and value
3600
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_RECORD) {
38,739✔
3601
      if (other->args.count == num && vtype_eq(type, other->type)) {
1,534✔
3602
         bool same_regs = true;
3603
         for (int i = 0; same_regs && i < num; i++)
2,504✔
3604
            same_regs = other->args.items[i] == values[i];
1,454✔
3605

3606
         if (same_regs)
1,050✔
3607
            return other->result;
187✔
3608
      }
3609
   }
3610

3611
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
2,332✔
3612
   op->type   = type;
2,332✔
3613
   op->result = vcode_add_reg(type);
2,332✔
3614

3615
   for (int i = 0; i < num; i++)
8,332✔
3616
      vcode_add_arg(op, values[i]);
6,000✔
3617

3618
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
2,332✔
3619
                "constant record must have record type");
3620

3621
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
2,332✔
3622
                vtype_fields(type), num);
3623

3624
#ifdef DEBUG
3625
   for (int i = 0; i < num; i++) {
8,332✔
3626
      VCODE_ASSERT(vtype_eq(vtype_field(type, i), vcode_reg_type(values[i])),
6,000✔
3627
                   "wrong type for field %d", i);
3628
      vcode_assert_const(values[i], "record");
6,000✔
3629
   }
3630
#endif
3631

3632
   return op->result;
2,332✔
3633
}
3634

3635
vcode_reg_t emit_address_of(vcode_reg_t value)
38,787✔
3636
{
3637
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
1,984,431✔
3638
      if (other->args.items[0] == value)
151,886✔
3639
         return other->result;
7,065✔
3640
   }
3641

3642
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
31,722✔
3643
   vcode_add_arg(op, value);
31,722✔
3644

3645
   vcode_type_t type = vcode_reg_type(value);
31,722✔
3646
   VCODE_ASSERT(vtype_is_composite(type),
31,722✔
3647
                "address of argument must be record or array");
3648

3649
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
31,722✔
3650
      vcode_type_t elem = vtype_elem(type);
29,930✔
3651
      op->result = vcode_add_reg(vtype_pointer(elem));
29,930✔
3652

3653
      reg_t *rr = vcode_reg_data(op->result);
29,930✔
3654
      rr->bounds = elem;
29,930✔
3655

3656
      return op->result;
29,930✔
3657
   }
3658
   else
3659
      return (op->result = vcode_add_reg(vtype_pointer(type)));
1,792✔
3660
}
3661

3662
void emit_wait(vcode_block_t target)
12,791✔
3663
{
3664
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
12,791✔
3665
   vcode_add_target(op, target);
12,791✔
3666
}
12,791✔
3667

3668
void emit_jump(vcode_block_t target)
35,940✔
3669
{
3670
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
35,940✔
3671
   vcode_add_target(op, target);
35,940✔
3672

3673
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
35,940✔
3674
}
35,940✔
3675

3676
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
70,238✔
3677
                     vcode_var_flags_t flags)
3678
{
3679
   assert(active_unit != NULL);
70,238✔
3680

3681
   vcode_var_t var = active_unit->vars.count;
70,238✔
3682
   var_t *v = var_array_alloc(&(active_unit->vars));
70,238✔
3683
   memset(v, '\0', sizeof(var_t));
70,238✔
3684
   v->type     = type;
70,238✔
3685
   v->bounds   = bounds;
70,238✔
3686
   v->name     = name;
70,238✔
3687
   v->flags    = flags;
70,238✔
3688

3689
   return var;
70,238✔
3690
}
3691

3692
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
32,204✔
3693
{
3694
   assert(active_unit != NULL);
32,204✔
3695

3696
   param_t *p = param_array_alloc(&(active_unit->params));
32,204✔
3697
   memset(p, '\0', sizeof(param_t));
32,204✔
3698
   p->type   = type;
32,204✔
3699
   p->bounds = bounds;
32,204✔
3700
   p->name   = name;
32,204✔
3701
   p->reg    = vcode_add_reg(type);
32,204✔
3702

3703
   reg_t *rr = vcode_reg_data(p->reg);
32,204✔
3704
   rr->bounds = bounds;
32,204✔
3705

3706
   return p->reg;
32,204✔
3707
}
3708

3709
vcode_reg_t emit_load(vcode_var_t var)
59,804✔
3710
{
3711
   // Try scanning backwards through the block for another load or store to
3712
   // this variable
3713
   enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER;
59,804✔
3714
   vcode_reg_t fold = VCODE_INVALID_REG;
59,804✔
3715
   VCODE_FOR_EACH_OP(other) {
857,393✔
3716
      switch (state) {
813,635✔
3717
      case EAGER:
322,038✔
3718
         if (other->kind == VCODE_OP_LOAD && other->address == var)
322,038✔
3719
            return other->result;
3,600✔
3720
         else if (other->kind == VCODE_OP_STORE && other->address == var)
318,438✔
3721
            return other->args.items[0];
12,446✔
3722
         else if (other->kind == VCODE_OP_FCALL
305,992✔
3723
                  || other->kind == VCODE_OP_PCALL
305,992✔
3724
                  || other->kind == VCODE_OP_FILE_READ
3725
                  || other->kind == VCODE_OP_FILE_OPEN
3726
                  || other->kind == VCODE_OP_STORE_INDIRECT
3727
                  || other->kind == VCODE_OP_DEALLOCATE)
3728
            state = CONSERVATIVE;   // May write to variable
9,889✔
3729
         break;
3730

3731
      case CONSERVATIVE:
460,786✔
3732
         if (other->kind == VCODE_OP_LOAD && other->address == var
460,786✔
3733
             && fold == VCODE_INVALID_REG)
4,567✔
3734
            fold = other->result;
3,688✔
3735
         else if (other->kind == VCODE_OP_STORE && other->address == var
457,098✔
3736
                  && fold == VCODE_INVALID_REG)
2,404✔
3737
            fold = other->args.items[0];
2,262✔
3738
         else if (other->kind == VCODE_OP_INDEX && other->address == var)
454,836✔
3739
            state = UNSAFE;
3740
         else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0)
453,456✔
3741
            state = UNSAFE;   // Nested call captures variables
112✔
3742
         break;
3743

3744
      case UNSAFE:
3745
         break;
3746
      }
3747
   }
3748

3749
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
43,758✔
3750
      return fold;
3751

3752
   var_t *v = vcode_var_data(var);
38,190✔
3753

3754
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
38,190✔
3755
   op->address = var;
38,190✔
3756
   op->result  = vcode_add_reg(v->type);
38,190✔
3757

3758
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot load non-scalar type");
38,190✔
3759

3760
   reg_t *r = vcode_reg_data(op->result);
38,190✔
3761
   r->bounds = v->bounds;
38,190✔
3762

3763
   return op->result;
38,190✔
3764
}
3765

3766
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
92,635✔
3767
{
3768
   VCODE_FOR_EACH_OP(other) {
1,101,540✔
3769
      if (other->kind == VCODE_OP_LOAD_INDIRECT
1,038,785✔
3770
          && other->args.items[0] == reg) {
149,459✔
3771
         return other->result;
9,885✔
3772
      }
3773
      else if (other->kind == VCODE_OP_FCALL
1,028,900✔
3774
               || other->kind == VCODE_OP_PCALL
1,028,900✔
3775
               || other->kind == VCODE_OP_STORE
3776
               || other->kind == VCODE_OP_STORE_INDIRECT
3777
               || other->kind == VCODE_OP_MEMSET
3778
               || other->kind == VCODE_OP_COPY
3779
               || other->kind == VCODE_OP_FILE_READ)
3780
         break;   // May write to this pointer
3781
   }
3782

3783
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
82,750✔
3784
   vcode_add_arg(op, reg);
82,750✔
3785

3786
   vcode_type_t rtype = vcode_reg_type(reg);
82,750✔
3787

3788
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
82,750✔
3789
                "load indirect with non-pointer argument");
3790

3791
   vcode_type_t deref = vtype_pointed(rtype);
82,750✔
3792
   op->result = vcode_add_reg(deref);
82,750✔
3793

3794
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
82,750✔
3795

3796
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
82,750✔
3797

3798
   return op->result;
82,750✔
3799
}
3800

3801
void emit_store(vcode_reg_t reg, vcode_var_t var)
75,011✔
3802
{
3803
   // Any previous store to this variable in this block is dead
3804
   VCODE_FOR_EACH_OP(other) {
1,594,838✔
3805
      if (other->kind == VCODE_OP_STORE && other->address == var) {
1,534,282✔
3806
         other->kind = VCODE_OP_COMMENT;
291✔
3807
         other->comment =
582✔
3808
            xasprintf("Dead store to %s", istr(vcode_var_name(var)));
291✔
3809
         vcode_reg_array_resize(&(other->args), 0, VCODE_INVALID_REG);
291✔
3810
      }
3811
      else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL)
1,533,991✔
3812
         break;   // Needs to get variable for display
3813
      else if ((other->kind == VCODE_OP_INDEX || other->kind == VCODE_OP_LOAD)
1,527,630✔
3814
               && other->address == var)
37,116✔
3815
         break;   // Previous value may be used
3816
   }
3817

3818
   var_t *v = vcode_var_data(var);
75,011✔
3819
   reg_t *r = vcode_reg_data(reg);
75,011✔
3820

3821
   op_t *op = vcode_add_op(VCODE_OP_STORE);
75,011✔
3822
   vcode_add_arg(op, reg);
75,011✔
3823
   op->address = var;
75,011✔
3824

3825
   VCODE_ASSERT(vtype_eq(v->type, r->type),
75,011✔
3826
                "variable and stored value do not have same type");
3827
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
75,011✔
3828
}
75,011✔
3829

3830
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
14,865✔
3831
{
3832
   reg_t *p = vcode_reg_data(ptr);
14,865✔
3833
   reg_t *r = vcode_reg_data(reg);
14,865✔
3834

3835
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
14,865✔
3836
   vcode_add_arg(op, reg);
14,865✔
3837
   vcode_add_arg(op, ptr);
14,865✔
3838

3839
   VCODE_ASSERT(vtype_kind(p->type) == VCODE_TYPE_POINTER,
14,865✔
3840
                "store indirect target is not a pointer");
3841
   VCODE_ASSERT(vtype_eq(vtype_pointed(p->type), r->type),
14,865✔
3842
                "pointer and stored value do not have same type");
3843
   VCODE_ASSERT(vtype_is_scalar(r->type), "cannot store non-scalar type");
14,865✔
3844
}
14,865✔
3845

3846
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
67,049✔
3847
                              vcode_reg_t locus)
3848
{
3849
   // Reuse any previous operation in this block with the same arguments
3850
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,564,092✔
3851
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
76,904✔
3852
         return other->result;
5,878✔
3853
   }
3854

3855
   op_t *op = vcode_add_op(kind);
61,171✔
3856
   vcode_add_arg(op, lhs);
61,171✔
3857
   vcode_add_arg(op, rhs);
61,171✔
3858
   if (locus != VCODE_INVALID_REG)
61,171✔
3859
      vcode_add_arg(op, locus);
7,121✔
3860

3861
   op->result = vcode_add_reg(vcode_reg_type(lhs));
61,171✔
3862

3863
   vcode_type_t lhs_type = vcode_reg_type(lhs);
61,171✔
3864
   vcode_type_t rhs_type = vcode_reg_type(rhs);
61,171✔
3865

3866
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
61,171✔
3867
                "arguments to %s are not the same type", vcode_op_string(kind));
3868

3869
   return op->result;
61,171✔
3870
}
3871

3872
static vcode_reg_t emit_mul_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
48,316✔
3873
                               vcode_reg_t locus)
3874
{
3875
   int64_t lconst, rconst;
48,316✔
3876
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
48,316✔
3877
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
48,316✔
3878
   if (l_is_const && r_is_const)
48,316✔
3879
      return emit_const(vcode_reg_type(lhs), lconst * rconst);
22,085✔
3880
   else if (r_is_const && rconst == 1)
26,231✔
3881
      return lhs;
3882
   else if (l_is_const && lconst == 1)
4,998✔
3883
      return rhs;
3884
   else if ((r_is_const && rconst == 0) || (l_is_const && lconst == 0))
4,496✔
3885
      return emit_const(vcode_reg_type(lhs), 0);
54✔
3886

3887
   reg_t *lhs_r = vcode_reg_data(lhs);
4,442✔
3888
   reg_t *rhs_r = vcode_reg_data(rhs);
4,442✔
3889

3890
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
4,442✔
3891
   vtype_t *br = vcode_type_data(rhs_r->bounds);
4,442✔
3892

3893
   vcode_type_t vbounds;
4,442✔
3894
   if (vcode_reg_kind(lhs) == VCODE_TYPE_REAL) {
4,442✔
3895
      const double ll = bl->rlow * br->rlow;
556✔
3896
      const double lh = bl->rlow * br->rhigh;
556✔
3897
      const double hl = bl->rhigh * br->rlow;
556✔
3898
      const double hh = bl->rhigh * br->rhigh;
556✔
3899

3900
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
1,301✔
3901
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
1,387✔
3902

3903
      vbounds = vtype_real(min, max);
556✔
3904
   }
3905
   else {
3906
      const int64_t ll = smul64(bl->low, br->low);
3,886✔
3907
      const int64_t lh = smul64(bl->low, br->high);
3,886✔
3908
      const int64_t hl = smul64(bl->high, br->low);
3,886✔
3909
      const int64_t hh = smul64(bl->high, br->high);
3,886✔
3910

3911
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
3,886✔
3912
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
3,886✔
3913

3914
      if (min > INT64_MIN && max < INT64_MAX) {
3,886✔
3915
         vtype_repr_t repr = vtype_repr(lhs_r->type);
3,052✔
3916
         if (op == VCODE_OP_TRAP_MUL && vtype_clamp_to_repr(repr, &min, &max)) {
3,052✔
3917
            op = VCODE_OP_MUL;   // Cannot overflow
907✔
3918
            locus = VCODE_INVALID_REG;
907✔
3919
         }
3920
      }
3921

3922
      vbounds = vtype_int(min, max);
3,886✔
3923
   }
3924

3925
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
4,442✔
3926

3927
   if (vbounds != VCODE_INVALID_TYPE)
4,442✔
3928
      vcode_reg_data(reg)->bounds = vbounds;
4,442✔
3929

3930
   return reg;
3931
}
3932

3933
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
45,515✔
3934
{
3935
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
45,515✔
3936
}
3937

3938
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
2,801✔
3939
{
3940
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
2,801✔
3941

3942
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
2,801✔
3943
                "trapping add may only be used with integer types");
3944

3945
   return result;
2,801✔
3946
}
3947

3948
vcode_reg_t emit_div(vcode_reg_t lhs, vcode_reg_t rhs)
1,738✔
3949
{
3950
   int64_t lconst, rconst;
1,738✔
3951
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
1,738✔
3952
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
1,738✔
3953
   if (l_is_const && r_is_const && rconst != 0)
1,738✔
3954
      return emit_const(vcode_reg_type(lhs), lconst / rconst);
30✔
3955
   else if (r_is_const && rconst == 1)
1,708✔
3956
      return lhs;
3957

3958
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
1,705✔
3959

3960
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
1,705✔
3961

3962
   if (bl->kind == VCODE_TYPE_INT && r_is_const && rconst != 0) {
1,705✔
3963
      reg_t *rr = vcode_reg_data(reg);
1,312✔
3964
      rr->bounds = vtype_int(bl->low / rconst, bl->high / rconst);
1,312✔
3965
   }
3966
   else if (bl->kind == VCODE_TYPE_REAL) {
393✔
3967
      reg_t *rr = vcode_reg_data(reg);
317✔
3968
      rr->bounds = vtype_real(-INFINITY, INFINITY);
317✔
3969
   }
3970

3971
   return reg;
3972
}
3973

3974
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
141✔
3975
{
3976
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
141✔
3977
}
3978

3979
vcode_reg_t emit_trap_exp(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
411✔
3980
{
3981
   int64_t rconst;
411✔
3982
   if (vcode_reg_const(rhs, &rconst)) {
411✔
3983
      if (rconst == 0)
77✔
3984
         return emit_const(vcode_reg_type(lhs), 1);
31✔
3985
      else if (rconst == 1)
46✔
3986
         return lhs;
3987
   }
3988

3989
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
379✔
3990

3991
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
379✔
3992
                "trapping exp may only be used with integer types");
3993

3994
   return result;
3995
}
3996

3997
vcode_reg_t emit_mod(vcode_reg_t lhs, vcode_reg_t rhs)
199✔
3998
{
3999
   int64_t lconst, rconst;
199✔
4000
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
199✔
4001
       && lconst > 0 && rconst > 0)
15✔
4002
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
3✔
4003

4004
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
196✔
4005
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
196✔
4006

4007
   if (bl->low >= 0 && br->low >= 0) {
196✔
4008
      // If both arguments are non-negative then rem is equivalent and
4009
      // cheaper to compute
4010
      vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
66✔
4011

4012
      reg_t *rr = vcode_reg_data(reg);
66✔
4013
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
66✔
4014

4015
      return reg;
66✔
4016
   }
4017
   else
4018
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
130✔
4019
}
4020

4021
vcode_reg_t emit_rem(vcode_reg_t lhs, vcode_reg_t rhs)
855✔
4022
{
4023
   int64_t lconst, rconst;
855✔
4024
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
855✔
4025
       && lconst > 0 && rconst > 0)
2✔
4026
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
×
4027

4028
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
855✔
4029

4030
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
855✔
4031
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
855✔
4032

4033
   if (bl->low >= 0 && br->low >= 0) {
855✔
4034
      reg_t *rr = vcode_reg_data(reg);
471✔
4035
      rr->bounds = vtype_int(0, br->high - 1);
471✔
4036
   }
4037

4038
   return reg;
4039
}
4040

4041
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
48,298✔
4042
                               vcode_reg_t locus)
4043
{
4044
   int64_t lconst, rconst;
48,298✔
4045
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
48,298✔
4046
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
48,298✔
4047
   if (l_is_const && r_is_const)
48,298✔
4048
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
11,944✔
4049
   else if (r_is_const && rconst == 0)
36,354✔
4050
      return lhs;
4051
   else if (l_is_const && lconst == 0)
36,226✔
4052
      return rhs;
4053

4054
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
19,935✔
4055
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
19,935✔
4056
      reg_t *lhs_r = vcode_reg_data(lhs);
19,611✔
4057
      reg_t *rhs_r = vcode_reg_data(rhs);
19,611✔
4058

4059
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
19,611✔
4060
      vtype_t *br = vcode_type_data(rhs_r->bounds);
19,611✔
4061

4062
      int64_t rbl = sadd64(bl->low, br->low);
19,611✔
4063
      int64_t rbh = sadd64(bl->high, br->high);
19,611✔
4064

4065
      if (rbl > INT64_MIN && rbh < INT64_MAX) {
19,611✔
4066
         vtype_repr_t repr = vtype_repr(lhs_r->type);
11,387✔
4067
         if (op == VCODE_OP_TRAP_ADD && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
11,387✔
4068
            op = VCODE_OP_ADD;   // Cannot overflow
1,448✔
4069
            locus = VCODE_INVALID_REG;
1,448✔
4070
         }
4071
      }
4072

4073
      vbounds = vtype_int(rbl, rbh);
19,611✔
4074
   }
4075

4076
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
19,935✔
4077

4078
   if (vbounds != VCODE_INVALID_TYPE)
19,935✔
4079
      vcode_reg_data(reg)->bounds = vbounds;
19,611✔
4080

4081
   return reg;
4082
}
4083

4084
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
42,096✔
4085
{
4086
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
42,096✔
4087
}
4088

4089
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
6,202✔
4090
{
4091
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
6,202✔
4092

4093
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
6,202✔
4094
                "trapping add may only be used with integer types");
4095

4096
   return result;
6,202✔
4097
}
4098

4099
static vcode_reg_t emit_sub_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
46,396✔
4100
                               vcode_reg_t locus)
4101
{
4102
   int64_t lconst, rconst;
46,396✔
4103
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
46,396✔
4104
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
46,396✔
4105
   if (l_is_const && r_is_const)
46,396✔
4106
      return emit_const(vcode_reg_type(lhs), lconst - rconst);
8,232✔
4107
   else if (r_is_const && rconst == 0)
38,164✔
4108
      return lhs;
4109
   else if (l_is_const && lconst == 0)
33,358✔
4110
      return emit_neg(rhs);
840✔
4111

4112
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
32,518✔
4113
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
32,518✔
4114
      reg_t *lhs_r = vcode_reg_data(lhs);
32,223✔
4115
      reg_t *rhs_r = vcode_reg_data(rhs);
32,223✔
4116

4117
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
32,223✔
4118
      vtype_t *br = vcode_type_data(rhs_r->bounds);
32,223✔
4119

4120
      int64_t rbl = ssub64(bl->low, br->high);
32,223✔
4121
      int64_t rbh = ssub64(bl->high, br->low);
32,223✔
4122

4123
      if (rbl > INT64_MIN && rbh < INT64_MAX) {
32,223✔
4124
         vtype_repr_t repr = vtype_repr(lhs_r->type);
31,381✔
4125
         if (op == VCODE_OP_TRAP_SUB && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
31,381✔
4126
            op = VCODE_OP_SUB;   // Cannot overflow
4,940✔
4127
            locus = VCODE_INVALID_REG;
4,940✔
4128
         }
4129
      }
4130

4131
      vbounds = vtype_int(rbl, rbh);
32,223✔
4132
   }
4133

4134
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
32,518✔
4135

4136
   if (vbounds != VCODE_INVALID_TYPE)
32,518✔
4137
      vcode_reg_data(reg)->bounds = vbounds;
32,223✔
4138

4139
   return reg;
4140
}
4141

4142
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
39,300✔
4143
{
4144
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
39,300✔
4145
}
4146

4147
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
7,096✔
4148
{
4149
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
7,096✔
4150

4151
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
7,096✔
4152
                "trapping sub may only be used with integer types");
4153

4154
   return result;
7,096✔
4155
}
4156

4157
static void vcode_calculate_var_index_type(op_t *op, var_t *var)
70,191✔
4158
{
4159
   switch (vtype_kind(var->type)) {
70,191✔
4160
   case VCODE_TYPE_CARRAY:
21,696✔
4161
      op->type = vtype_pointer(vtype_elem(var->type));
21,696✔
4162
      op->result = vcode_add_reg(op->type);
21,696✔
4163
      vcode_reg_data(op->result)->bounds = vtype_bounds(var->type);
21,696✔
4164
      break;
21,696✔
4165

4166
   case VCODE_TYPE_RECORD:
5,761✔
4167
      op->type = vtype_pointer(var->type);
5,761✔
4168
      op->result = vcode_add_reg(op->type);
5,761✔
4169
      break;
5,761✔
4170

4171
   case VCODE_TYPE_INT:
42,734✔
4172
   case VCODE_TYPE_FILE:
4173
   case VCODE_TYPE_ACCESS:
4174
   case VCODE_TYPE_REAL:
4175
   case VCODE_TYPE_UARRAY:
4176
   case VCODE_TYPE_POINTER:
4177
   case VCODE_TYPE_SIGNAL:
4178
   case VCODE_TYPE_CONTEXT:
4179
   case VCODE_TYPE_OFFSET:
4180
   case VCODE_TYPE_TRIGGER:
4181
   case VCODE_TYPE_RESOLUTION:
4182
      op->type = vtype_pointer(var->type);
42,734✔
4183
      op->result = vcode_add_reg(op->type);
42,734✔
4184
      vcode_reg_data(op->result)->bounds = var->bounds;
42,734✔
4185
      break;
42,734✔
4186

4187
   default:
4188
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4189
                   istr(var->name));
4190
   }
4191
}
70,191✔
4192

4193
vcode_reg_t emit_index(vcode_var_t var, vcode_reg_t offset)
33,783✔
4194
{
4195
   // Try to find a previous index of this var by this offset
4196
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_INDEX) {
1,380,042✔
4197
      if (other->address == var
82,933✔
4198
          && ((offset == VCODE_INVALID_REG && other->args.count == 0)
7,176✔
4199
              || (offset != VCODE_INVALID_REG
×
4200
                  && other->args.items[0] == offset)))
×
4201
         return other->result;
7,176✔
4202
   }
4203

4204
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
26,607✔
4205
   op->address = var;
26,607✔
4206

4207
   if (offset != VCODE_INVALID_REG)
26,607✔
4208
      vcode_add_arg(op, offset);
×
4209

4210
   vcode_calculate_var_index_type(op, vcode_var_data(var));
26,607✔
4211

4212
   if (offset != VCODE_INVALID_REG)
26,607✔
4213
      VCODE_ASSERT(vtype_kind(vcode_reg_type(offset)) == VCODE_TYPE_OFFSET,
×
4214
                   "index offset r%d does not have offset type", offset);
4215

4216
   return op->result;
26,607✔
4217
}
4218

4219
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
243,194✔
4220
{
4221
   if (vtype_eq(vcode_reg_type(reg), type))
243,194✔
4222
      return reg;
243,194✔
4223

4224
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
81,788✔
4225
   vtype_kind_t to   = vtype_kind(type);
81,788✔
4226

4227
   const bool integral =
163,576✔
4228
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
81,788✔
4229
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
81,788✔
4230

4231
   int64_t value;
81,788✔
4232
   if (integral && vcode_reg_const(reg, &value))
81,788✔
4233
      return emit_const(type, value);
12,662✔
4234

4235
   // Try to find a previous cast of this register to this type
4236
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CAST) {
1,367,053✔
4237
      if (vtype_eq(other->type, type) && other->args.items[0] == reg)
139,436✔
4238
         return other->result;
15,278✔
4239
   }
4240

4241
   op_t *op = vcode_add_op(VCODE_OP_CAST);
53,848✔
4242
   vcode_add_arg(op, reg);
53,848✔
4243
   op->type   = type;
53,848✔
4244
   op->result = vcode_add_reg(type);
53,848✔
4245

4246
   static const vcode_type_t allowed[][2] = {
53,848✔
4247
      { VCODE_TYPE_INT,    VCODE_TYPE_OFFSET  },
4248
      { VCODE_TYPE_OFFSET, VCODE_TYPE_INT     },
4249
      { VCODE_TYPE_INT,    VCODE_TYPE_INT     },
4250
      { VCODE_TYPE_INT,    VCODE_TYPE_REAL    },
4251
      { VCODE_TYPE_REAL,   VCODE_TYPE_INT     },
4252
      { VCODE_TYPE_REAL,   VCODE_TYPE_REAL    },
4253
      { VCODE_TYPE_ACCESS, VCODE_TYPE_ACCESS  },
4254
   };
4255

4256
   if (integral) {
53,848✔
4257
      vtype_t *vt = vcode_type_data(type);
53,006✔
4258
      int64_t low = vt->low, high = vt->high;
53,006✔
4259

4260
      vtype_t *rt = vcode_type_data(vcode_reg_bounds(reg));
53,006✔
4261
      low = MAX(low, rt->low);
53,006✔
4262
      high = MIN(high, rt->high);
53,006✔
4263

4264
      if (bounds != VCODE_INVALID_REG) {
53,006✔
4265
         vtype_t *bt = vcode_type_data(bounds);
31,698✔
4266
         low = MAX(low, bt->low);
31,698✔
4267
         high = MIN(high, bt->high);
31,698✔
4268
      }
4269

4270
      reg_t *rr = vcode_reg_data(op->result);
53,006✔
4271
      rr->bounds = vtype_int(low, high);
53,006✔
4272
   }
4273
   else if (bounds != VCODE_INVALID_REG)
842✔
4274
      vcode_reg_data(op->result)->bounds = bounds;
842✔
4275

4276
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
94,485✔
4277
      if (from == allowed[i][0] && to == allowed[i][1])
94,485✔
4278
         return op->result;
53,848✔
4279
   }
4280

4281
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4282
}
4283

4284
void emit_return(vcode_reg_t reg)
55,307✔
4285
{
4286
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
55,307✔
4287
   if (reg != VCODE_INVALID_REG) {
55,307✔
4288
      vcode_add_arg(op, reg);
24,734✔
4289

4290
      const vtype_kind_t rkind = vcode_reg_kind(reg);
24,734✔
4291
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY)
24,734✔
4292
         vcode_heap_allocate(reg);
4,541✔
4293

4294
      VCODE_ASSERT(active_unit->kind == VCODE_UNIT_FUNCTION
24,734✔
4295
                   || active_unit->kind == VCODE_UNIT_THUNK
4296
                   || active_unit->kind == VCODE_UNIT_PROPERTY,
4297
                   "returning value fron non-function unit");
4298
      VCODE_ASSERT((active_unit->kind == VCODE_UNIT_PROPERTY
24,734✔
4299
                    && rkind == VCODE_TYPE_INT)
4300
                   || vtype_eq(active_unit->result, vcode_reg_type(reg))
4301
                   || (vtype_kind(active_unit->result) == VCODE_TYPE_ACCESS
4302
                       && rkind == VCODE_TYPE_ACCESS),
4303
                   "return value incorrect type");
4304
   }
4305
}
55,307✔
4306

4307
void emit_sched_waveform(vcode_reg_t nets, vcode_reg_t nnets,
9,199✔
4308
                         vcode_reg_t values, vcode_reg_t reject,
4309
                         vcode_reg_t after)
4310
{
4311
   int64_t nconst;
9,199✔
4312
   if (vcode_reg_const(nnets, &nconst) && nconst == 0) {
9,199✔
4313
      emit_comment("Skip empty waveform");
9✔
4314
      return;
9✔
4315
   }
4316

4317
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
9,190✔
4318
   vcode_add_arg(op, nets);
9,190✔
4319
   vcode_add_arg(op, nnets);
9,190✔
4320
   vcode_add_arg(op, values);
9,190✔
4321
   vcode_add_arg(op, reject);
9,190✔
4322
   vcode_add_arg(op, after);
9,190✔
4323

4324
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
9,190✔
4325
                "sched_waveform target is not signal");
4326
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
9,190✔
4327
                "sched_waveform net count is not offset type");
4328
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
9,190✔
4329
                "signal cannot be values argument for sched_waveform");
4330
}
4331

4332
void emit_force(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t values)
70✔
4333
{
4334
   op_t *op = vcode_add_op(VCODE_OP_FORCE);
70✔
4335
   vcode_add_arg(op, nets);
70✔
4336
   vcode_add_arg(op, nnets);
70✔
4337
   vcode_add_arg(op, values);
70✔
4338

4339
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
70✔
4340
                "force target is not signal");
4341
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
70✔
4342
                "force net count is not offset type");
4343
}
70✔
4344

4345
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
42✔
4346
{
4347
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
42✔
4348
   vcode_add_arg(op, nets);
42✔
4349
   vcode_add_arg(op, nnets);
42✔
4350

4351
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
42✔
4352
                "release target is not signal");
4353
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
42✔
4354
                "release net count is not offset type");
4355
}
42✔
4356

4357
void emit_disconnect(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t reject,
24✔
4358
                     vcode_reg_t after)
4359
{
4360
   op_t *op = vcode_add_op(VCODE_OP_DISCONNECT);
24✔
4361
   vcode_add_arg(op, nets);
24✔
4362
   vcode_add_arg(op, nnets);
24✔
4363
   vcode_add_arg(op, reject);
24✔
4364
   vcode_add_arg(op, after);
24✔
4365

4366
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
24✔
4367
                "disconnect target is not signal");
4368
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
24✔
4369
                "disconnect net count is not offset type");
4370
}
24✔
4371

4372
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
32,568✔
4373
{
4374
   int64_t tconst;
32,568✔
4375
   if (vcode_reg_const(test, &tconst)) {
32,568✔
4376
      emit_jump(!!tconst ? btrue : bfalse);
3,832✔
4377
      return;
1,955✔
4378
   }
4379

4380
   op_t *op = vcode_add_op(VCODE_OP_COND);
30,613✔
4381
   vcode_add_arg(op, test);
30,613✔
4382
   vcode_add_target(op, btrue);
30,613✔
4383
   vcode_add_target(op, bfalse);
30,613✔
4384

4385
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
30,613✔
4386
                "cond test is not a bool");
4387
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
30,613✔
4388
                "invalid cond targets");
4389
}
4390

4391
vcode_reg_t emit_neg(vcode_reg_t lhs)
6,971✔
4392
{
4393
   int64_t lconst;
6,971✔
4394
   if (vcode_reg_const(lhs, &lconst))
6,971✔
4395
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4396

4397
   op_t *op = vcode_add_op(VCODE_OP_NEG);
6,971✔
4398
   vcode_add_arg(op, lhs);
6,971✔
4399
   op->result = vcode_add_reg(vcode_reg_type(lhs));
6,971✔
4400

4401
   return op->result;
6,971✔
4402
}
4403

4404
vcode_reg_t emit_trap_neg(vcode_reg_t lhs, vcode_reg_t locus)
467✔
4405
{
4406
   int64_t lconst;
467✔
4407
   if (vcode_reg_const(lhs, &lconst) && lconst >= 0)
467✔
4408
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4409
   else if (vcode_type_data(vcode_reg_data(lhs)->bounds)->low >= 0)
467✔
4410
      return emit_neg(lhs);   // Cannot overflow
210✔
4411

4412
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
257✔
4413
   vcode_add_arg(op, lhs);
257✔
4414
   vcode_add_arg(op, locus);
257✔
4415

4416
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
257✔
4417
                "locus argument to trap neg must be a debug locus");
4418
   VCODE_ASSERT(vcode_reg_kind(lhs) == VCODE_TYPE_INT,
257✔
4419
                "trapping neg may only be used with integer types");
4420

4421
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
257✔
4422
}
4423

4424
vcode_reg_t emit_abs(vcode_reg_t lhs)
686✔
4425
{
4426
   int64_t lconst;
686✔
4427
   if (vcode_reg_const(lhs, &lconst))
686✔
4428
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4429

4430
   op_t *op = vcode_add_op(VCODE_OP_ABS);
685✔
4431
   vcode_add_arg(op, lhs);
685✔
4432
   op->result = vcode_add_reg(vcode_reg_type(lhs));
685✔
4433

4434
   return op->result;
685✔
4435
}
4436

4437
void emit_comment(const char *fmt, ...)
77,677✔
4438
{
4439
#ifndef NDEBUG
4440
   va_list ap;
77,677✔
4441
   va_start(ap, fmt);
77,677✔
4442

4443
   char *buf = xvasprintf(fmt, ap);
77,677✔
4444
   for (char *p = buf + strlen(buf) - 1;
77,677✔
4445
        p >= buf && isspace_iso88591(*p); p--)
77,677✔
4446
      *p = '\0';
×
4447

4448
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
77,677✔
4449
   va_end(ap);
77,677✔
4450
#endif
4451
}
77,677✔
4452

4453
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
18,309✔
4454
                        vcode_reg_t rfalse)
4455
{
4456
   int64_t tconst;
18,309✔
4457
   if (vcode_reg_const(test, &tconst))
18,309✔
4458
      return !!tconst ? rtrue : rfalse;
4,691✔
4459
   else if (rtrue == rfalse)
13,618✔
4460
      return rtrue;
4461

4462
   // Find a previous identical select
4463
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
295,725✔
4464
      if (other->args.items[0] == test && other->args.items[1] == rtrue
10,854✔
4465
          && other->args.items[2] == rfalse)
649✔
4466
         return other->result;
556✔
4467
   }
4468

4469
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
12,887✔
4470
   vcode_add_arg(op, test);
12,887✔
4471
   vcode_add_arg(op, rtrue);
12,887✔
4472
   vcode_add_arg(op, rfalse);
12,887✔
4473
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
12,887✔
4474

4475
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
12,887✔
4476
                "select test must have bool type");
4477
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
12,887✔
4478
                "select arguments are not the same type");
4479

4480
   return op->result;
12,887✔
4481
}
4482

4483
static vcode_reg_t emit_logical_identity(vcode_op_t op, vcode_reg_t reg, bool b)
442✔
4484
{
4485
   switch (op) {
442✔
4486
   case VCODE_OP_AND:  return b ? reg : emit_const(vtype_bool(), 0);
45✔
4487
   case VCODE_OP_OR:   return b ? emit_const(vtype_bool(), 1) : reg;
349✔
4488
   case VCODE_OP_XOR:  return b ? emit_not(reg) : reg;
12✔
4489
   case VCODE_OP_XNOR: return b ? reg : emit_not(reg);
12✔
4490
   case VCODE_OP_NAND: return b ? emit_not(reg) : emit_const(vtype_bool(), 1);
12✔
4491
   case VCODE_OP_NOR:  return b ? emit_const(vtype_bool(), 0) : emit_not(reg);
12✔
4492
   default:
×
4493
      fatal_trace("missing logicial identity for %s", vcode_op_string(op));
4494
   }
4495
}
4496

4497
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
7,353✔
4498
{
4499
   vcode_type_t vtbool = vtype_bool();
7,353✔
4500

4501
   int64_t lconst, rconst;
7,353✔
4502
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
7,353✔
4503
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
7,353✔
4504
   if (l_is_const && r_is_const) {
7,353✔
4505
      switch (op) {
6✔
4506
      case VCODE_OP_AND:  return emit_const(vtbool, lconst && rconst);
×
4507
      case VCODE_OP_OR:   return emit_const(vtbool, lconst || rconst);
×
4508
      case VCODE_OP_XOR:  return emit_const(vtbool, lconst ^ rconst);
×
4509
      case VCODE_OP_XNOR: return emit_const(vtbool, !(lconst ^ rconst));
6✔
4510
      case VCODE_OP_NAND: return emit_const(vtbool, !(lconst && rconst));
×
4511
      case VCODE_OP_NOR:  return emit_const(vtbool, !(lconst || rconst));
×
4512
      default:
×
4513
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
4514
      }
4515
   }
4516
   else if (l_is_const)
7,347✔
4517
      return emit_logical_identity(op, rhs, !!lconst);
342✔
4518
   else if (r_is_const)
7,005✔
4519
      return emit_logical_identity(op, lhs, !!rconst);
100✔
4520
   else if (lhs == rhs) {
6,905✔
4521
      switch (op) {
27✔
4522
      case VCODE_OP_AND:
4523
      case VCODE_OP_OR:
4524
         return lhs;
4525
      case VCODE_OP_NAND:
6✔
4526
      case VCODE_OP_NOR:
4527
         return emit_not(lhs);
6✔
4528
      case VCODE_OP_XOR:
3✔
4529
         return emit_const(vtbool, 0);
3✔
4530
      case VCODE_OP_XNOR:
×
4531
         return emit_const(vtbool, 1);
×
4532
      default:
×
4533
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
4534
      }
4535
   }
4536

4537
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
6,878✔
4538

4539
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
6,878✔
4540
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4541
                "arguments to %s are not boolean", vcode_op_string(op));
4542

4543
   return result;
4544
}
4545

4546
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
2,392✔
4547
{
4548
   return emit_logical(VCODE_OP_OR, lhs, rhs);
2,392✔
4549
}
4550

4551
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
4,725✔
4552
{
4553
   return emit_logical(VCODE_OP_AND, lhs, rhs);
4,725✔
4554
}
4555

4556
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
52✔
4557
{
4558
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
52✔
4559
}
4560

4561
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
53✔
4562
{
4563
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
53✔
4564
}
4565

4566
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
73✔
4567
{
4568
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
73✔
4569
}
4570

4571
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
58✔
4572
{
4573
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
58✔
4574
}
4575

4576
vcode_reg_t emit_not(vcode_reg_t arg)
2,498✔
4577
{
4578
   int64_t cval;
2,498✔
4579
   if (vcode_reg_const(arg, &cval))
2,498✔
4580
      return emit_const(vtype_bool(), !cval);
27✔
4581

4582
   op_t *op = vcode_add_op(VCODE_OP_NOT);
2,471✔
4583
   vcode_add_arg(op, arg);
2,471✔
4584

4585
   vcode_type_t vtbool = vtype_bool();
2,471✔
4586
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
2,471✔
4587
                "argument to not is not boolean");
4588

4589
   return (op->result = vcode_add_reg(vtbool));
2,471✔
4590
}
4591

4592
vcode_reg_t emit_wrap(vcode_reg_t data, const vcode_dim_t *dims, int ndims)
46,653✔
4593
{
4594
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_WRAP) {
1,727,103✔
4595
      if (other->args.count == ndims*3 + 1 && other->args.items[0] == data) {
155,747✔
4596
         bool match = true;
4597
         for (int i = 0; match && i < ndims; i++) {
22,368✔
4598
            match = other->args.items[i*3 + 1] == dims[i].left
11,216✔
4599
               && other->args.items[i*3 + 2] == dims[i].right
9,021✔
4600
               && other->args.items[i*3 + 3] == dims[i].dir;
19,970✔
4601
         }
4602
         if (match)
11,152✔
4603
            return other->result;
8,690✔
4604
      }
4605
   }
4606

4607
   op_t *op = vcode_add_op(VCODE_OP_WRAP);
37,963✔
4608
   vcode_add_arg(op, data);
37,963✔
4609
   for (int i = 0; i < ndims; i++) {
76,584✔
4610
      vcode_add_arg(op, dims[i].left);
38,621✔
4611
      vcode_add_arg(op, dims[i].right);
38,621✔
4612
      vcode_add_arg(op, dims[i].dir);
38,621✔
4613
   }
4614

4615
   vcode_type_t ptr_type = vcode_reg_type(data);
37,963✔
4616
   const vtype_kind_t ptrkind = vtype_kind(ptr_type);
37,963✔
4617
   VCODE_ASSERT(ptrkind == VCODE_TYPE_POINTER || ptrkind == VCODE_TYPE_SIGNAL,
37,963✔
4618
                "wrapped data is not pointer or signal");
4619

4620
#ifdef DEBUG
4621
   for (int i = 0; i < ndims; i++) {
76,584✔
4622
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].left)),
38,621✔
4623
                   "dimension %d left bound must be scalar", i + 1);
4624
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].right)),
38,621✔
4625
                   "dimension %d right bound must be scalar", i + 1);
4626
      VCODE_ASSERT(vtype_eq(vtype_bool(), vcode_reg_type(dims[i].dir)),
38,621✔
4627
                   "dimension %d direction must be bool", i + 1);
4628
   }
4629
#endif
4630

4631
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
75,926✔
4632
      ? vtype_pointed(ptr_type) : ptr_type;
37,963✔
4633

4634
   op->result = vcode_add_reg(
37,963✔
4635
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4636

4637
   return op->result;
37,963✔
4638
}
4639

4640
static vcode_reg_t emit_uarray_op(vcode_op_t o, vcode_type_t rtype,
102,933✔
4641
                                  vcode_reg_t array, unsigned dim,
4642
                                  unsigned arg_index)
4643
{
4644
   // Reuse any previous operation in this block with the same arguments
4645
   VCODE_FOR_EACH_OP(other) {
1,168,180✔
4646
      if (other->kind == o && other->args.items[0] == array && other->dim == dim
1,123,603✔
4647
          && (rtype == VCODE_INVALID_TYPE
23,476✔
4648
              || vtype_eq(rtype, vcode_reg_type(other->result))))
10,179✔
4649
         return other->result;
23,476✔
4650
      else if (other->kind == VCODE_OP_WRAP && other->result == array)
1,100,127✔
4651
         return other->args.items[1 + (dim * 3) + arg_index];
34,880✔
4652
   }
4653

4654
   op_t *op = vcode_add_op(o);
44,577✔
4655
   vcode_add_arg(op, array);
44,577✔
4656
   op->dim = dim;
44,577✔
4657

4658
   vcode_type_t atype = vcode_reg_type(array);
44,577✔
4659
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
44,577✔
4660
                "cannot use %s with non-uarray type", vcode_op_string(o));
4661

4662
   vtype_t *vt = vcode_type_data(atype);
44,577✔
4663
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
44,577✔
4664

4665
   if (rtype == VCODE_INVALID_TYPE)
44,577✔
4666
      rtype = vtype_offset();
28,783✔
4667

4668
   return (op->result = vcode_add_reg(rtype));
44,577✔
4669
}
4670

4671
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
37,963✔
4672
{
4673
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
37,963✔
4674
                         array, dim, 0);
4675
}
4676

4677
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
27,269✔
4678
{
4679
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
27,269✔
4680
                         array, dim, 1);
4681
}
4682

4683
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
37,701✔
4684
{
4685
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
37,701✔
4686
                         array, dim, 2);
4687
}
4688

4689
vcode_reg_t emit_uarray_len(vcode_reg_t array, unsigned dim)
45,811✔
4690
{
4691
   VCODE_FOR_EACH_OP(other) {
666,894✔
4692
      if (other->kind == VCODE_OP_UARRAY_LEN) {
645,362✔
4693
         if (other->args.items[0] == array && other->dim == dim)
40,917✔
4694
            return other->result;
9,546✔
4695
      }
4696
      else if (other->kind == VCODE_OP_WRAP && other->result == array) {
604,445✔
4697
         VCODE_ASSERT(dim < (other->args.count - 1) / 3,
14,733✔
4698
                      "array dimension %d out of bounds", dim);
4699

4700
         vcode_reg_t left_reg = other->args.items[dim * 3 + 1];
14,733✔
4701
         vcode_reg_t right_reg = other->args.items[dim * 3 + 2];
14,733✔
4702
         vcode_reg_t dir_reg = other->args.items[dim * 3 + 3];
14,733✔
4703
         return emit_range_length(left_reg, right_reg, dir_reg);
14,733✔
4704
      }
4705
   }
4706

4707
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
21,532✔
4708
   vcode_add_arg(op, array);
21,532✔
4709
   op->dim = dim;
21,532✔
4710

4711
   vcode_type_t atype = vcode_reg_type(array);
21,532✔
4712
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
21,532✔
4713
                "cannot use uarray len with non-uarray type");
4714

4715
   vtype_t *vt = vcode_type_data(atype);
21,532✔
4716
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
21,532✔
4717

4718
   op->result = vcode_add_reg(vtype_offset());
21,532✔
4719

4720
   reg_t *rr = vcode_reg_data(op->result);
21,532✔
4721
   rr->bounds = vtype_int(0, INT64_MAX);
21,532✔
4722

4723
   return op->result;
21,532✔
4724
}
4725

4726
vcode_reg_t emit_unwrap(vcode_reg_t array)
35,385✔
4727
{
4728
   VCODE_FOR_EACH_OP(other) {
1,542,257✔
4729
      if (other->kind == VCODE_OP_WRAP && other->result == array)
1,517,062✔
4730
         return other->args.items[0];
8,447✔
4731
      else if (other->kind == VCODE_OP_UNWRAP && other->args.items[0] == array)
1,508,615✔
4732
         return other->result;
1,743✔
4733
   }
4734

4735
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
25,195✔
4736
   vcode_add_arg(op, array);
25,195✔
4737

4738
   vtype_t *vt = vcode_type_data(vcode_reg_type(array));
25,195✔
4739
   VCODE_ASSERT(vt->kind == VCODE_TYPE_UARRAY,
25,195✔
4740
                "unwrap can only only be used with uarray types");
4741

4742
   vcode_type_t elem = vt->elem;
25,195✔
4743

4744
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
25,195✔
4745
      ? elem : vtype_pointer(elem);
25,195✔
4746

4747
   op->result = vcode_add_reg(rtype);
25,195✔
4748

4749
   reg_t *rr = vcode_reg_data(op->result);
25,195✔
4750
   rr->bounds = elem;
25,195✔
4751

4752
   return op->result;
25,195✔
4753
}
4754

4755
vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right,
29,236✔
4756
                            vcode_reg_t dir)
4757
{
4758
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_NULL) {
1,415,902✔
4759
      if (other->args.items[0] == left
×
4760
          && other->args.items[1] == right
×
4761
          && other->args.items[2] == dir)
×
4762
         return other->result;
×
4763
   }
4764

4765
   int64_t dir_const;
29,236✔
4766
   if (vcode_reg_const(dir, &dir_const)) {
29,236✔
4767
      vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
26,250✔
4768
      vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
26,250✔
4769

4770
      if (dir_const == RANGE_TO && lbounds->low > rbounds->high)
26,250✔
4771
         return emit_const(vtype_bool(), 1);
65✔
4772
      else if (dir_const == RANGE_TO && lbounds->high <= rbounds->low)
26,185✔
4773
         return emit_const(vtype_bool(), 0);
18,248✔
4774
      else if (dir_const == RANGE_DOWNTO && rbounds->low > lbounds->high)
7,937✔
4775
         return emit_const(vtype_bool(), 1);
611✔
4776
      else if (dir_const == RANGE_DOWNTO && rbounds->high <= lbounds->low)
7,326✔
4777
         return emit_const(vtype_bool(), 0);
1,817✔
4778
      else if (dir_const == RANGE_TO)
5,509✔
4779
         return emit_cmp(VCODE_CMP_GT, left, right);
2,804✔
4780
      else
4781
         return emit_cmp(VCODE_CMP_GT, right, left);
2,705✔
4782
   }
4783

4784
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
2,986✔
4785
   vcode_add_arg(op, left);
2,986✔
4786
   vcode_add_arg(op, right);
2,986✔
4787
   vcode_add_arg(op, dir);
2,986✔
4788

4789
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
2,986✔
4790
                "range left and right have different types");
4791
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
2,986✔
4792
                "dir argument to range length is not int");
4793

4794
   return (op->result = vcode_add_reg(vtype_bool()));
2,986✔
4795
}
4796

4797
vcode_reg_t emit_range_length(vcode_reg_t left, vcode_reg_t right,
14,771✔
4798
                              vcode_reg_t dir)
4799
{
4800
   vcode_reg_t left_array = VCODE_INVALID_REG,
14,771✔
4801
      right_array = VCODE_INVALID_REG,
14,771✔
4802
      dir_array = VCODE_INVALID_REG;
14,771✔
4803
   int left_dim = -1, right_dim = -1, dir_dim = -1;
14,771✔
4804

4805
   VCODE_FOR_EACH_OP(other) {
291,201✔
4806
      if (other->kind == VCODE_OP_RANGE_LENGTH
281,951✔
4807
          && other->args.items[0] == left
7,838✔
4808
          && other->args.items[1] == right
5,838✔
4809
          && other->args.items[2] == dir)
5,521✔
4810
         return other->result;
5,521✔
4811
      else if (other->kind == VCODE_OP_UARRAY_LEFT && other->result == left) {
276,430✔
4812
         left_array = other->args.items[0];
362✔
4813
         left_dim = other->dim;
362✔
4814
      }
4815
      else if (other->kind == VCODE_OP_UARRAY_RIGHT && other->result == right) {
276,068✔
4816
         right_array = other->args.items[0];
362✔
4817
         right_dim = other->dim;
362✔
4818
      }
4819
      else if (other->kind == VCODE_OP_UARRAY_DIR && other->result == dir) {
275,706✔
4820
         dir_array = other->args.items[0];
706✔
4821
         dir_dim = other->dim;
706✔
4822
      }
4823
   }
4824

4825
   if (left_array != VCODE_INVALID_REG && left_array == right_array
9,250✔
4826
       && right_array == dir_array && left_dim == right_dim
362✔
4827
       && right_dim == dir_dim)
362✔
4828
      return emit_uarray_len(left_array, left_dim);
362✔
4829

4830
   int64_t lconst, rconst, dconst;
8,888✔
4831
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
8,888✔
4832
       && vcode_reg_const(right, &rconst)) {
4,868✔
4833

4834
      int64_t diff;
1,846✔
4835
      if (dconst == RANGE_TO)
1,846✔
4836
         diff = rconst - lconst;
1,549✔
4837
      else
4838
         diff = lconst - rconst;
297✔
4839

4840
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
1,846✔
4841
   }
4842

4843
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
7,042✔
4844
   vcode_add_arg(op, left);
7,042✔
4845
   vcode_add_arg(op, right);
7,042✔
4846
   vcode_add_arg(op, dir);
7,042✔
4847

4848
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
7,042✔
4849
                "range left and right have different types");
4850
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
7,042✔
4851
                "dir argument to range length is not int");
4852

4853
   op->result = vcode_add_reg(vtype_offset());
7,042✔
4854

4855
   reg_t *rr = vcode_reg_data(op->result);
7,042✔
4856
   rr->bounds = vtype_int(0, INT64_MAX);
7,042✔
4857

4858
   return op->result;
7,042✔
4859
}
4860

4861
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
54,443✔
4862
{
4863
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
494,008✔
4864
      if (other->hops == hops && other->address == var)
66,254✔
4865
         return other->result;
10,859✔
4866
   }
4867

4868
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
43,584✔
4869
   op->hops    = hops;
43,584✔
4870
   op->address = var;
43,584✔
4871

4872
   VCODE_ASSERT(hops > 0, "invalid hop count");
43,584✔
4873

4874
   vcode_unit_t vu = active_unit;
43,584✔
4875
   for (int i = 0; i < hops; i++) {
96,457✔
4876
      vu = vu->context;
52,873✔
4877
      VCODE_ASSERT(vu, "hop count is greater than depth");
52,873✔
4878
   }
4879

4880
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
43,584✔
4881

4882
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
43,584✔
4883

4884
   return op->result;
43,584✔
4885
}
4886

4887
vcode_reg_t emit_init_signal(vcode_type_t type, vcode_reg_t count,
16,202✔
4888
                             vcode_reg_t size, vcode_reg_t value,
4889
                             vcode_reg_t flags, vcode_reg_t locus,
4890
                             vcode_reg_t offset)
4891
{
4892
   op_t *op = vcode_add_op(VCODE_OP_INIT_SIGNAL);
16,202✔
4893
   vcode_add_arg(op, count);
16,202✔
4894
   vcode_add_arg(op, size);
16,202✔
4895
   vcode_add_arg(op, value);
16,202✔
4896
   vcode_add_arg(op, flags);
16,202✔
4897
   vcode_add_arg(op, locus);
16,202✔
4898
   if (offset != VCODE_INVALID_REG)
16,202✔
4899
      vcode_add_arg(op, offset);
5,736✔
4900

4901
   vcode_type_t vtype = vcode_reg_type(value);
16,202✔
4902
   VCODE_ASSERT(vtype_is_scalar(type), "signal type must be scalar");
16,202✔
4903
   VCODE_ASSERT(vtype_eq(vtype, type)
16,202✔
4904
                || vtype_kind(vtype) == VCODE_TYPE_POINTER,
4905
                "init signal value type does not match signal type");
4906
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
16,202✔
4907
                "locus argument to init signal must be a debug locus");
4908
   VCODE_ASSERT(offset == VCODE_INVALID_REG
16,202✔
4909
                || vcode_reg_kind(offset) == VCODE_TYPE_POINTER,
4910
                "init signal offset argument must have pointer type");
4911

4912
   return (op->result = vcode_add_reg(vtype_signal(type)));
16,202✔
4913
}
4914

4915
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
3,376✔
4916
{
4917
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
3,376✔
4918
   vcode_add_arg(op, signal);
3,376✔
4919
   vcode_add_arg(op, resolution);
3,376✔
4920

4921
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
3,376✔
4922
                "signal argument has wrong type");
4923

4924
   vcode_type_t rtype = vcode_reg_type(resolution);
3,376✔
4925
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
3,376✔
4926
                "resolution wrapper argument must be pointer");
4927
   VCODE_ASSERT(vtype_kind(vtype_pointed(rtype)) == VCODE_TYPE_RESOLUTION,
3,376✔
4928
                "resolution wrapper argument has wrong type");
4929
}
3,376✔
4930

4931
vcode_reg_t emit_implicit_signal(vcode_type_t type, vcode_reg_t count,
75✔
4932
                                 vcode_reg_t size, vcode_reg_t locus,
4933
                                 vcode_reg_t kind, vcode_reg_t closure,
4934
                                 vcode_reg_t delay)
4935
{
4936
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_SIGNAL);
75✔
4937
   vcode_add_arg(op, count);
75✔
4938
   vcode_add_arg(op, size);
75✔
4939
   vcode_add_arg(op, locus);
75✔
4940
   vcode_add_arg(op, kind);
75✔
4941
   vcode_add_arg(op, closure);
75✔
4942
   vcode_add_arg(op, delay);
75✔
4943

4944
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
75✔
4945
                "count argument to implicit signal is not offset");
4946
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
75✔
4947
                "kind argument to implicit signal is not offset");
4948
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
75✔
4949
                "closure argument to implicit signal is not a closure");
4950
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
75✔
4951
                "locus argument to implicit signal must be a debug locus");
4952
   VCODE_ASSERT(vcode_reg_kind(delay) == VCODE_TYPE_INT,
75✔
4953
                "delay argument to implicit signal must be time");
4954

4955
   return (op->result = vcode_add_reg(vtype_signal(type)));
75✔
4956
}
4957

4958
void emit_map_signal(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
5,437✔
4959
{
4960
   op_t *op = vcode_add_op(VCODE_OP_MAP_SIGNAL);
5,437✔
4961
   vcode_add_arg(op, src);
5,437✔
4962
   vcode_add_arg(op, dst);
5,437✔
4963
   vcode_add_arg(op, count);
5,437✔
4964

4965
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
5,437✔
4966
                "src argument to map signal is not a signal");
4967
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
5,437✔
4968
                "dst argument to map signal is not a signal");
4969
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5,437✔
4970
                "count argument type to map signal is not offset");
4971
}
5,437✔
4972

4973
void emit_map_const(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
200✔
4974
{
4975
   op_t *op = vcode_add_op(VCODE_OP_MAP_CONST);
200✔
4976
   vcode_add_arg(op, src);
200✔
4977
   vcode_add_arg(op, dst);
200✔
4978
   vcode_add_arg(op, count);
200✔
4979

4980
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
200✔
4981
                "dst argument to map const is not a signal");
4982
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
200✔
4983
                "count argument type to map const is not offset");
4984
}
200✔
4985

4986
void emit_map_implicit(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
57✔
4987
{
4988
   op_t *op = vcode_add_op(VCODE_OP_MAP_IMPLICIT);
57✔
4989
   vcode_add_arg(op, src);
57✔
4990
   vcode_add_arg(op, dst);
57✔
4991
   vcode_add_arg(op, count);
57✔
4992

4993
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
57✔
4994
                "src argument to map implicit is not a signal");
4995
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
57✔
4996
                "dst argument to map implicit is not a signal");
4997
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
57✔
4998
                "count argument type to map implicit is not offset");
4999
}
57✔
5000

5001
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
7,233✔
5002
{
5003
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
91,629✔
5004
      if (other->args.items[0] == target && other->args.items[1] == count)
12,121✔
5005
         return;
5006
   }
5007

5008
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
7,230✔
5009
   vcode_add_arg(op, target);
7,230✔
5010
   vcode_add_arg(op, count);
7,230✔
5011

5012
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
7,230✔
5013
                "target argument to drive signal is not a signal");
5014
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
7,230✔
5015
                "count argument type to drive signal is not offset");
5016
}
5017

5018
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
530✔
5019
                          vcode_reg_t count, vcode_reg_t reject,
5020
                          vcode_reg_t after)
5021
{
5022
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
530✔
5023
   vcode_add_arg(op, target);
530✔
5024
   vcode_add_arg(op, source);
530✔
5025
   vcode_add_arg(op, count);
530✔
5026
   vcode_add_arg(op, reject);
530✔
5027
   vcode_add_arg(op, after);
530✔
5028

5029
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
530✔
5030
                "target argument to transfer signal is not a signal");
5031
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
530✔
5032
                "count argument type to transfer signal is not offset");
5033
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
530✔
5034
                "source argument to transfer signal is not a signal");
5035
}
530✔
5036

5037
vcode_reg_t emit_resolution_wrapper(vcode_type_t type, vcode_reg_t closure,
5,075✔
5038
                                    vcode_reg_t nlits)
5039
{
5040
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RESOLUTION_WRAPPER) {
83,051✔
5041
      if (other->args.items[0] == closure && other->args.items[1] == nlits)
11,070✔
5042
         return other->result;
×
5043
   }
5044

5045
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
5,075✔
5046
                "first argument to resolution wrapper must be closure");
5047

5048
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
5,075✔
5049
   vcode_add_arg(op, closure);
5,075✔
5050
   vcode_add_arg(op, nlits);
5,075✔
5051

5052
   return (op->result = vcode_add_reg(vtype_resolution(type)));
5,075✔
5053
}
5054

5055
vcode_reg_t emit_closure(ident_t func, vcode_reg_t context, vcode_type_t rtype)
5,372✔
5056
{
5057
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CLOSURE) {
84,279✔
5058
      if (other->func == func && other->args.items[0] == context)
11,241✔
5059
         return other->result;
×
5060
   }
5061

5062
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
5,372✔
5063
   vcode_add_arg(op, context);
5,372✔
5064
   op->func = func;
5,372✔
5065

5066
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5,372✔
5067
                "invalid closure context argument");
5068

5069
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
5,372✔
5070
}
5071

5072
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
35,191✔
5073
{
5074
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
68,060✔
5075
      if (other->func == name)
28,680✔
5076
         return other->result;
13,449✔
5077
   }
5078

5079
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
21,742✔
5080
   op->func = name;
21,742✔
5081
   if (context != VCODE_INVALID_REG)
21,742✔
5082
      vcode_add_arg(op, context);
190✔
5083

5084
   VCODE_ASSERT(context == VCODE_INVALID_REG
21,742✔
5085
                || vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5086
                "invalid protected init context argument");
5087
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_INSTANCE
21,742✔
5088
                || active_unit->kind == VCODE_UNIT_PACKAGE
5089
                || active_unit->kind == VCODE_UNIT_THUNK,
5090
                "cannot use package init here");
5091
   VCODE_ASSERT(name != active_unit->name, "cyclic package init");
21,742✔
5092

5093
   return (op->result = vcode_add_reg(vtype_context(name)));
21,742✔
5094
}
5095

5096
vcode_reg_t emit_protected_init(vcode_type_t type, vcode_reg_t context,
544✔
5097
                                vcode_reg_t path_name, vcode_reg_t inst_name)
5098
{
5099
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_INIT);
544✔
5100
   vcode_add_arg(op, context);
544✔
5101
   op->func = vtype_name(type);
544✔
5102

5103
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
544✔
5104
      vcode_add_arg(op, path_name);
414✔
5105
      vcode_add_arg(op, inst_name);
414✔
5106

5107
      VCODE_ASSERT(vcode_reg_kind(path_name) == VCODE_TYPE_UARRAY,
414✔
5108
                   "path name argument must be uarray");
5109
      VCODE_ASSERT(vcode_reg_kind(inst_name) == VCODE_TYPE_UARRAY,
414✔
5110
                   "inst name argument must be uarray");
5111
   }
5112

5113
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
544✔
5114
                "protected init type must be context");
5115
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
544✔
5116
                "invalid protected init context argument");
5117

5118
   return (op->result = vcode_add_reg(type));
544✔
5119
}
5120

5121
void emit_process_init(ident_t name, vcode_reg_t locus)
117✔
5122
{
5123
   op_t *op = vcode_add_op(VCODE_OP_PROCESS_INIT);
117✔
5124
   vcode_add_arg(op, locus);
117✔
5125
   op->func = name;
117✔
5126

5127
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
117✔
5128
                "locus argument to process init must be a debug locus");
5129
}
117✔
5130

5131
void emit_protected_free(vcode_reg_t obj)
308✔
5132
{
5133
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
308✔
5134
   vcode_add_arg(op, obj);
308✔
5135

5136
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
308✔
5137
                "protected object type must be context");
5138
}
308✔
5139

5140
vcode_reg_t emit_context_upref(int hops)
19,410✔
5141
{
5142
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
132,226✔
5143
      if (other->hops == hops)
8,664✔
5144
         return other->result;
8,616✔
5145
   }
5146

5147
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
10,794✔
5148
   op->hops = hops;
10,794✔
5149

5150
   VCODE_ASSERT(hops >= 0, "invalid hop count");
10,794✔
5151

5152
   vcode_unit_t vu = active_unit;
10,794✔
5153
   for (int i = 0; i < hops; i++) {
18,994✔
5154
      vu = vu->context;
8,200✔
5155
      VCODE_ASSERT(vu, "hop count is greater than depth");
8,200✔
5156
   }
5157

5158
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
10,794✔
5159
}
5160

5161
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
661✔
5162
                                    vcode_reg_t len)
5163
{
5164
   op_t *op = vcode_add_op(opkind);
661✔
5165
   vcode_add_arg(op, nets);
661✔
5166
   vcode_add_arg(op, len);
661✔
5167

5168
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
661✔
5169
                "argument to %s is not a signal", vcode_op_string(opkind));
5170

5171
   return (op->result = vcode_add_reg(vtype_bool()));
661✔
5172
}
5173

5174
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
444✔
5175
{
5176
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
444✔
5177
}
5178

5179
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
217✔
5180
{
5181
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
217✔
5182
}
5183

5184
vcode_reg_t emit_record_ref(vcode_reg_t record, unsigned field)
37,008✔
5185
{
5186
   // Try scanning backwards through the block for another record ref
5187
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RECORD_REF) {
2,683,014✔
5188
      if (other->args.items[0] == record && other->field == field)
503,382✔
5189
         return other->result;
3,881✔
5190
   }
5191

5192
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
33,127✔
5193
   op->field = field;
33,127✔
5194
   vcode_add_arg(op, record);
33,127✔
5195

5196
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
33,127✔
5197

5198
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
33,127✔
5199
                "argument to record ref must be a pointer");
5200

5201
   vtype_t *rtype = vcode_type_data(rptype->pointed);
33,127✔
5202
   VCODE_ASSERT(rtype->kind == VCODE_TYPE_RECORD,
33,127✔
5203
                "argument must be pointer to record or record signal");
5204

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

5207
   vcode_type_t field_type  = rtype->fields.items[field];
33,127✔
5208
   vcode_type_t bounds_type = field_type;
33,127✔
5209
   vcode_type_t result_type = field_type;
33,127✔
5210

5211
   const vtype_kind_t fkind = vtype_kind(field_type);
33,127✔
5212
   if (fkind == VCODE_TYPE_CARRAY)
33,127✔
5213
      result_type = bounds_type = vtype_elem(field_type);
4,559✔
5214
   else if (fkind == VCODE_TYPE_UARRAY) {
28,568✔
5215
      bounds_type = vtype_elem(field_type);
2,985✔
5216
      result_type = field_type;
2,985✔
5217
   }
5218

5219
   op->result = vcode_add_reg(vtype_pointer(result_type));
33,127✔
5220

5221
   reg_t *rr = vcode_reg_data(op->result);
33,127✔
5222
   rr->bounds = bounds_type;
33,127✔
5223

5224
   return op->result;
33,127✔
5225
}
5226

5227
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
33,374✔
5228
{
5229
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
1,659,020✔
5230
      if (other->args.items[0] == array && other->args.items[1] == offset)
104,162✔
5231
         return other->result;
1,191✔
5232
   }
5233

5234
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
32,183✔
5235
   vcode_add_arg(op, array);
32,183✔
5236
   vcode_add_arg(op, offset);
32,183✔
5237

5238
   vcode_type_t rtype = vcode_reg_type(array);
32,183✔
5239
   VCODE_ASSERT((vtype_kind(rtype) == VCODE_TYPE_POINTER
32,183✔
5240
                 && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY)
5241
                || vtype_kind(rtype) == VCODE_TYPE_SIGNAL,
5242
                "argument to array ref must be a pointer or signal");
5243
   VCODE_ASSERT(vcode_reg_kind(offset) == VCODE_TYPE_OFFSET,
32,183✔
5244
                "array ref offset argument must have offset type");
5245

5246
   op->result = vcode_add_reg(rtype);
32,183✔
5247

5248
   reg_t *rr = vcode_reg_data(op->result);
32,183✔
5249
   rr->bounds = vcode_reg_bounds(array);
32,183✔
5250

5251
   return op->result;
32,183✔
5252
}
5253

5254
void emit_copy(vcode_reg_t dest, vcode_reg_t src, vcode_reg_t count)
30,114✔
5255
{
5256
   int64_t cconst;
30,114✔
5257
   if (count != VCODE_INVALID_REG && vcode_reg_const(count, &cconst)
30,114✔
5258
       && cconst == 0)
20,241✔
5259
      return;
5,332✔
5260
   else if (dest == src)
29,371✔
5261
      return;
5262

5263
   op_t *op = vcode_add_op(VCODE_OP_COPY);
24,782✔
5264
   vcode_add_arg(op, dest);
24,782✔
5265
   vcode_add_arg(op, src);
24,782✔
5266
   if (count != VCODE_INVALID_REG)
24,782✔
5267
      vcode_add_arg(op, count);
23,206✔
5268

5269
   vcode_type_t dtype = vcode_reg_type(dest);
24,782✔
5270
   vcode_type_t stype = vcode_reg_type(src);
24,782✔
5271

5272
   vtype_kind_t dkind = vtype_kind(dtype);
24,782✔
5273
   vtype_kind_t skind = vtype_kind(stype);
24,782✔
5274

5275
   VCODE_ASSERT(dkind == VCODE_TYPE_POINTER || dkind == VCODE_TYPE_ACCESS,
24,782✔
5276
                "destination type is not a pointer or access");
5277
   VCODE_ASSERT(skind == VCODE_TYPE_POINTER || skind == VCODE_TYPE_ACCESS,
24,782✔
5278
                "source type is not a pointer or access");
5279
   VCODE_ASSERT(vtype_eq(dtype, stype),
24,782✔
5280
                "source and destination types do not match");
5281
   VCODE_ASSERT(count == VCODE_INVALID_REG
24,782✔
5282
                || vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5283
                "count is not offset type");
5284

5285
   op->type = vtype_pointed(dtype);
24,782✔
5286
}
5287

5288
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
4,486✔
5289
{
5290
   VCODE_FOR_EACH_OP(other) {
63,601✔
5291
      if (other->kind == VCODE_OP_CLEAR_EVENT)
59,169✔
5292
         break;
5293
      else if (other->kind == VCODE_OP_SCHED_EVENT
59,121✔
5294
               && other->args.items[0] == nets
2,600✔
5295
               && other->args.items[1] == n_elems)
9✔
5296
         return;
5297
   }
5298

5299
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
4,480✔
5300
   vcode_add_arg(op, nets);
4,480✔
5301
   vcode_add_arg(op, n_elems);
4,480✔
5302

5303
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
4,480✔
5304
                "nets argument to sched event must be signal");
5305
}
5306

5307
void emit_clear_event(vcode_reg_t nets, vcode_reg_t n_elems)
550✔
5308
{
5309
   VCODE_FOR_EACH_OP(other) {
2,524✔
5310
      if (other->kind == VCODE_OP_SCHED_EVENT)
1,974✔
5311
         break;
5312
      else if (other->kind == VCODE_OP_CLEAR_EVENT
1,974✔
5313
               && other->args.items[0] == nets
39✔
5314
               && other->args.items[1] == n_elems)
×
5315
         return;
5316
   }
5317

5318
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
550✔
5319
   vcode_add_arg(op, nets);
550✔
5320
   vcode_add_arg(op, n_elems);
550✔
5321

5322
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
550✔
5323
                "nets argument to clear event must be signal");
5324
}
5325

5326
void emit_sched_process(vcode_reg_t delay)
5,248✔
5327
{
5328
   op_t *op = vcode_add_op(VCODE_OP_SCHED_PROCESS);
5,248✔
5329
   vcode_add_arg(op, delay);
5,248✔
5330

5331
   VCODE_ASSERT(vcode_reg_kind(delay) == VCODE_TYPE_INT,
5,248✔
5332
                "delay must have integer type");
5333
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_PROCEDURE
5,248✔
5334
                || active_unit->kind == VCODE_UNIT_PROCESS,
5335
                "sched process only allowed in process or procedure");
5336
}
5,248✔
5337

5338
void emit_resume(ident_t func)
843✔
5339
{
5340
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
843✔
5341
   op->func = func;
843✔
5342

5343
   block_t *b = &(active_unit->blocks.items[active_block]);
843✔
5344
   VCODE_ASSERT(b->ops.count == 1, "resume must be first op in a block");
843✔
5345
}
843✔
5346

5347
void emit_memset(vcode_reg_t ptr, vcode_reg_t value, vcode_reg_t len)
5,480✔
5348
{
5349
   int64_t lconst;
5,480✔
5350
   if (vcode_reg_const(len, &lconst) && lconst == 0)
5,480✔
5351
      return;
32✔
5352

5353
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
5,448✔
5354
   vcode_add_arg(op, ptr);
5,448✔
5355
   vcode_add_arg(op, value);
5,448✔
5356
   vcode_add_arg(op, len);
5,448✔
5357

5358
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
5,448✔
5359
                "target of memset must have pointer type");
5360
   VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(value)),
5,448✔
5361
                "value of memset must have scalar type");
5362
   VCODE_ASSERT(vtype_kind(vcode_reg_type(len)) == VCODE_TYPE_OFFSET,
5,448✔
5363
                "length of memset must have offset type");
5364
}
5365

5366
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
641✔
5367
               const vcode_block_t *blocks, int ncases)
5368
{
5369
   int64_t cval1, cval2;
641✔
5370
   bool is_const = vcode_reg_const(value, &cval1);
641✔
5371

5372
   for (int i = 0; i < ncases; i++) {
3,663✔
5373
      bool can_fold = false;
3,025✔
5374
      if (cases[i] == value)
3,025✔
5375
         can_fold = true;
5376
      else if (is_const && vcode_reg_const(cases[i], &cval2))
3,025✔
5377
         can_fold = (cval1 == cval2);
3✔
5378

5379
      if (can_fold) {
3✔
5380
         emit_jump(blocks[i]);
3✔
5381
         return;
6✔
5382
      }
5383
   }
5384

5385
   if (is_const) {
638✔
5386
      emit_jump(def);
×
5387
      return;
×
5388
   }
5389

5390
   op_t *op = vcode_add_op(VCODE_OP_CASE);
638✔
5391
   vcode_add_arg(op, value);
638✔
5392
   vcode_add_target(op, def);
638✔
5393

5394
   for (int i = 0; i < ncases; i++) {
3,660✔
5395
      vcode_add_arg(op, cases[i]);
3,022✔
5396
      vcode_add_target(op, blocks[i]);
3,022✔
5397

5398
#ifdef DEBUG
5399
      for (int j = 0; j < i; j++)
15,545✔
5400
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
12,523✔
5401
#endif
5402
   }
5403
}
5404

5405
void emit_file_open(vcode_reg_t file, vcode_reg_t name, vcode_reg_t length,
1,219✔
5406
                    vcode_reg_t kind, vcode_reg_t status)
5407
{
5408
   op_t *op = vcode_add_op(VCODE_OP_FILE_OPEN);
1,219✔
5409
   vcode_add_arg(op, file);
1,219✔
5410
   vcode_add_arg(op, name);
1,219✔
5411
   vcode_add_arg(op, length);
1,219✔
5412
   vcode_add_arg(op, kind);
1,219✔
5413
   if (status != VCODE_INVALID_REG)
1,219✔
5414
      vcode_add_arg(op, status);
25✔
5415

5416
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
1,219✔
5417
                "file open first argument must have file pointer type");
5418
}
1,219✔
5419

5420
void emit_file_write(vcode_reg_t file, vcode_reg_t value, vcode_reg_t length)
255✔
5421
{
5422
   op_t *op = vcode_add_op(VCODE_OP_FILE_WRITE);
255✔
5423
   vcode_add_arg(op, file);
255✔
5424
   vcode_add_arg(op, value);
255✔
5425
   if (length != VCODE_INVALID_REG)
255✔
5426
      vcode_add_arg(op, length);
198✔
5427

5428
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
255✔
5429
                "file write first argument must have file pointer type");
5430
}
255✔
5431

5432
void emit_file_read(vcode_reg_t file, vcode_reg_t ptr,
90✔
5433
                    vcode_reg_t inlen, vcode_reg_t outlen)
5434
{
5435
   op_t *op = vcode_add_op(VCODE_OP_FILE_READ);
90✔
5436
   vcode_add_arg(op, file);
90✔
5437
   vcode_add_arg(op, ptr);
90✔
5438
   if (inlen != VCODE_INVALID_REG) {
90✔
5439
      vcode_add_arg(op, inlen);
42✔
5440
      if (outlen != VCODE_INVALID_REG)
42✔
5441
         vcode_add_arg(op, outlen);
33✔
5442
   }
5443

5444
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
90✔
5445
                "file read first argument must have file pointer type");
5446
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
90✔
5447
                "file read pointer argument must have pointer type");
5448
   VCODE_ASSERT(outlen == VCODE_INVALID_REG
90✔
5449
                || vtype_kind(vcode_reg_type(outlen)) == VCODE_TYPE_POINTER,
5450
                "file read outlen argument must have pointer type");
5451
}
90✔
5452

5453
vcode_reg_t emit_null(vcode_type_t type)
12,627✔
5454
{
5455
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_NULL) {
254,351✔
5456
      if (vtype_eq(vcode_reg_type(other->result), type))
7,540✔
5457
         return other->result;
4,004✔
5458
   }
5459

5460
   op_t *op = vcode_add_op(VCODE_OP_NULL);
8,623✔
5461
   op->result = vcode_add_reg(type);
8,623✔
5462

5463
   vtype_kind_t kind = vtype_kind(type);
8,623✔
5464
   VCODE_ASSERT(kind == VCODE_TYPE_POINTER || kind == VCODE_TYPE_FILE
8,623✔
5465
                || kind == VCODE_TYPE_ACCESS || kind == VCODE_TYPE_CONTEXT,
5466
                "null type must be file, access, context, or pointer");
5467

5468
   return op->result;
5469
}
5470

5471
vcode_reg_t emit_new(vcode_type_t type, vcode_reg_t length)
636✔
5472
{
5473
   op_t *op = vcode_add_op(VCODE_OP_NEW);
636✔
5474
   if (length != VCODE_INVALID_REG)
636✔
5475
      vcode_add_arg(op, length);
545✔
5476

5477
   op->result = vcode_add_reg(vtype_access(type));
636✔
5478

5479
   vtype_kind_t kind = vtype_kind(type);
636✔
5480
   VCODE_ASSERT(kind == VCODE_TYPE_INT || kind == VCODE_TYPE_RECORD
636✔
5481
                || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_ACCESS
5482
                || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_CONTEXT,
5483
                "new type must be int, real, record, access, or uarray");
5484
   VCODE_ASSERT(length == VCODE_INVALID_REG
636✔
5485
                || vtype_kind(vcode_reg_type(length)) == VCODE_TYPE_OFFSET,
5486
                "new length must have offset type");
5487

5488
   return op->result;
636✔
5489
}
5490

5491
void emit_null_check(vcode_reg_t ptr, vcode_reg_t locus)
2,887✔
5492
{
5493
   VCODE_FOR_EACH_OP(other) {
119,285✔
5494
      if (other->kind == VCODE_OP_NULL_CHECK && other->args.items[0] == ptr)
117,139✔
5495
         return;
5496
      else if (other->kind == VCODE_OP_NEW && other->result == ptr)
116,721✔
5497
         return;
5498
   }
5499

5500
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
2,146✔
5501
   vcode_add_arg(op, ptr);
2,146✔
5502
   vcode_add_arg(op, locus);
2,146✔
5503

5504
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
2,146✔
5505
                "null check argument must be an access");
5506
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,146✔
5507
                "locus argument to null check must be a debug locus");
5508
}
5509

5510
void emit_deallocate(vcode_reg_t ptr)
335✔
5511
{
5512
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
335✔
5513
   vcode_add_arg(op, ptr);
335✔
5514

5515
   vcode_type_t ptype = vcode_reg_type(ptr);
335✔
5516
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
335✔
5517
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5518
                "deallocate argument must be pointer to access");
5519
}
335✔
5520

5521
vcode_reg_t emit_all(vcode_reg_t reg)
3,523✔
5522
{
5523
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
166,848✔
5524
      if (other->args.items[0] == reg)
10,225✔
5525
         return other->result;
741✔
5526
   }
5527

5528
   op_t *op = vcode_add_op(VCODE_OP_ALL);
2,782✔
5529
   vcode_add_arg(op, reg);
2,782✔
5530

5531
   vcode_type_t vtype = vcode_reg_type(reg);
2,782✔
5532

5533
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
2,782✔
5534
                "all argument must be an access");
5535

5536
   vcode_type_t pointed = vtype_pointed(vtype);
2,782✔
5537
   op->result = vcode_add_reg(vtype_pointer(pointed));
2,782✔
5538

5539
   reg_t *rr = vcode_reg_data(op->result);
2,782✔
5540
   rr->bounds = pointed;
2,782✔
5541

5542
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
2,782✔
5543
                "cannot dereference opaque type");
5544

5545
   return op->result;
5546
}
5547

5548
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
13,654✔
5549
{
5550
   block_t *b = &(active_unit->blocks.items[active_block]);
13,654✔
5551
   for (int i = b->ops.count - 1; i >= 0; i--) {
325,782✔
5552
      const op_t *other = &(b->ops.items[i]);
312,683✔
5553
      if (other->kind == kind && other->args.items[0] == sig)
312,683✔
5554
         return other->result;
555✔
5555
   }
5556

5557
   op_t *op = vcode_add_op(kind);
13,099✔
5558
   vcode_add_arg(op, sig);
13,099✔
5559

5560
   vcode_type_t stype = vcode_reg_type(sig);
13,099✔
5561
   op->type = stype;
13,099✔
5562

5563
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
13,099✔
5564
                "argument r%d to resolved is not a signal", sig);
5565

5566
   vcode_type_t rtype = vtype_base(stype);
13,099✔
5567

5568
   const vtype_kind_t rkind = vtype_kind(rtype);
13,099✔
5569
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
13,099✔
5570
      rtype = vtype_elem(rtype);
×
5571

5572
   VCODE_ASSERT(vtype_is_scalar(rtype),
13,099✔
5573
                "resolved signal base type must be scalar");
5574

5575
   op->result = vcode_add_reg(vtype_pointer(rtype));
13,099✔
5576

5577
   reg_t *rr = vcode_reg_data(op->result);
13,099✔
5578
   rr->bounds = rtype;
13,099✔
5579

5580
   return op->result;
13,099✔
5581
}
5582

5583
vcode_reg_t emit_resolved(vcode_reg_t sig, vcode_reg_t count)
13,465✔
5584
{
5585
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
13,465✔
5586
}
5587

5588
vcode_reg_t emit_last_value(vcode_reg_t sig, vcode_reg_t count)
189✔
5589
{
5590
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
189✔
5591
}
5592

5593
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
42✔
5594
{
5595
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
42✔
5596
   vcode_add_arg(op, signal);
42✔
5597
   if (len != VCODE_INVALID_REG)
42✔
5598
      vcode_add_arg(op, len);
9✔
5599

5600
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
42✔
5601
                "signal argument to last event must have signal type");
5602
   VCODE_ASSERT(len == VCODE_INVALID_REG
42✔
5603
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5604
                "length argument to last event must have offset type");
5605

5606
   return (op->result = vcode_add_reg(vtype_time()));
42✔
5607
}
5608

5609
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
45✔
5610
{
5611
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
45✔
5612
   vcode_add_arg(op, signal);
45✔
5613
   if (len != VCODE_INVALID_REG)
45✔
5614
      vcode_add_arg(op, len);
6✔
5615

5616
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
45✔
5617
                "signal argument to last active must have signal type");
5618
   VCODE_ASSERT(len == VCODE_INVALID_REG
45✔
5619
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5620
                "length argument to last active must have offset type");
5621

5622
   return (op->result = vcode_add_reg(vtype_time()));
45✔
5623
}
5624

5625
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
4,290✔
5626
{
5627
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
4,290✔
5628
   vcode_add_arg(op, signal);
4,290✔
5629
   vcode_add_arg(op, locus);
4,290✔
5630

5631
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
4,290✔
5632
                "signal argument must have signal type");
5633
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
4,290✔
5634
                "locus argument must have debug locus type");
5635
}
4,290✔
5636

5637
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
36✔
5638
{
5639
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
36✔
5640
   vcode_add_arg(op, signal);
36✔
5641
   vcode_add_arg(op, len);
36✔
5642

5643
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5644
                "signal argument to last active must have signal type");
5645
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
36✔
5646
                "length argument to last active must have offset type");
5647

5648
   return (op->result = vcode_add_reg(vtype_bool()));
36✔
5649
}
5650

5651
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
120✔
5652
{
5653
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
120✔
5654
   vcode_add_arg(op, signal);
120✔
5655
   if (len != VCODE_INVALID_REG)
120✔
5656
      vcode_add_arg(op, len);
36✔
5657

5658
   vcode_type_t signal_type = vcode_reg_type(signal);
120✔
5659

5660
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
120✔
5661
                "signal argument to last active must have signal type");
5662
   VCODE_ASSERT(len == VCODE_INVALID_REG
120✔
5663
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5664
                "length argument to last active must have offset type");
5665

5666
   vcode_type_t base_type = vtype_base(signal_type);
120✔
5667
   op->result = vcode_add_reg(vtype_pointer(base_type));
120✔
5668

5669
   reg_t *rr = vcode_reg_data(op->result);
120✔
5670
   rr->bounds = base_type;
120✔
5671

5672
   return op->result;
120✔
5673
}
5674

5675
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
32,681✔
5676
                       vcode_reg_t dim)
5677
{
5678
   if (rlen == llen)
32,681✔
5679
      return;
5680

5681
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
197,522✔
5682
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
2,640✔
5683
         return;
5684
   }
5685

5686
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
7,195✔
5687
   vcode_add_arg(op, llen);
7,195✔
5688
   vcode_add_arg(op, rlen);
7,195✔
5689
   vcode_add_arg(op, locus);
7,195✔
5690
   if (dim != VCODE_INVALID_REG)
7,195✔
5691
      vcode_add_arg(op, dim);
27✔
5692

5693
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
7,195✔
5694
                "locus argument to length check must be a debug locus");
5695
}
5696

5697
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
411✔
5698
{
5699
   int64_t cval;
411✔
5700
   if (vcode_reg_const(exp, &cval) && cval >= 0)
411✔
5701
      return;
47✔
5702

5703
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
4,195✔
5704
      if (other->args.items[0] == exp)
12✔
5705
         return;
5706
   }
5707

5708
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
364✔
5709
   vcode_add_arg(op, exp);
364✔
5710
   vcode_add_arg(op, locus);
364✔
5711

5712
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
364✔
5713
                "exp argument to exponent check must be a integer");
5714
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
364✔
5715
                "locus argument to exponent check must be a debug locus");
5716
}
5717

5718
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
2,458✔
5719
{
5720
   int64_t cval;
2,458✔
5721
   if (vcode_reg_const(denom, &cval) && cval != 0)
2,458✔
5722
      return;
2,367✔
5723

5724
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
2,305✔
5725
      if (other->args.items[0] == denom)
48✔
5726
         return;
5727
   }
5728

5729
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
91✔
5730
   vcode_add_arg(op, denom);
91✔
5731
   vcode_add_arg(op, locus);
91✔
5732

5733
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
91✔
5734
                "denom argument to zero check must be a integer");
5735
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
91✔
5736
                "locus argument to zero check must be a debug locus");
5737
}
5738

5739
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
84,993✔
5740
                                   vcode_reg_t right, vcode_reg_t dir)
5741
{
5742
   int64_t dconst;
84,993✔
5743
   if (vcode_reg_const(dir, &dconst)) {
84,993✔
5744
      int64_t lconst, rconst;
75,128✔
5745
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
75,128✔
5746
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
50,971✔
5747
            || (dconst == RANGE_DOWNTO && rconst > lconst);
104,877✔
5748

5749
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
53,907✔
5750

5751
         const bool ok_static =
107,814✔
5752
            (dconst == RANGE_TO
5753
             && bounds->low >= lconst && bounds->high <= rconst)
50,971✔
5754
            || (dconst == RANGE_DOWNTO
8,932✔
5755
                && bounds->low >= rconst && bounds->high <= lconst)
2,936✔
5756
            || (!is_null && (reg == left || reg == right));
60,209✔
5757

5758
         return ok_static;
72,367✔
5759
      }
5760
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
21,221✔
5761
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
19,161✔
5762
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
19,161✔
5763

5764
         assert(lbounds->kind == VCODE_TYPE_REAL);
19,161✔
5765
         assert(rbounds->kind == VCODE_TYPE_REAL);
19,161✔
5766

5767
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
19,161✔
5768
         assert(bounds->kind == VCODE_TYPE_REAL);
19,161✔
5769

5770
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
19,161✔
5771
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
18,460✔
5772
            // Covers the complete double range so can never overflow
5773
            return true;
5774
         }
5775
      }
5776
   }
5777

5778
   return false;
5779
}
5780

5781
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
85,887✔
5782
                              vcode_reg_t left, vcode_reg_t right,
5783
                              vcode_reg_t dir, vcode_reg_t locus,
5784
                              vcode_reg_t hint)
5785
{
5786
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
3,639,200✔
5787
      if (other->args.items[0] == reg && other->args.items[1] == left
18,189✔
5788
          && other->args.items[2] == right && other->args.items[3] == dir)
1,060✔
5789
         return;
5790
   }
5791

5792
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
84,993✔
5793
      emit_comment("Elided bounds check for r%d", reg);
66,065✔
5794
      return;
66,065✔
5795
   }
5796

5797
   op_t *op = vcode_add_op(kind);
18,928✔
5798
   vcode_add_arg(op, reg);
18,928✔
5799
   vcode_add_arg(op, left);
18,928✔
5800
   vcode_add_arg(op, right);
18,928✔
5801
   vcode_add_arg(op, dir);
18,928✔
5802
   vcode_add_arg(op, locus);
18,928✔
5803
   vcode_add_arg(op, hint);
18,928✔
5804

5805
   VCODE_ASSERT(vtype_is_numeric(vcode_reg_type(reg)),
18,928✔
5806
                "argument to bounds check must be numeric");
5807
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
18,928✔
5808
                "locus argument to bounds check must be a debug locus");
5809
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
18,928✔
5810
                "hint argument to bounds check must be a debug locus");
5811
}
5812

5813
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
22,762✔
5814
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5815
{
5816
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
22,762✔
5817
}
22,762✔
5818

5819
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
63,125✔
5820
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5821
{
5822
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
63,125✔
5823
}
63,125✔
5824

5825
void emit_dir_check(vcode_reg_t reg, vcode_reg_t dir, vcode_reg_t locus)
3,169✔
5826
{
5827
   if (reg == dir)
3,169✔
5828
      return;
5829

5830
   op_t *op = vcode_add_op(VCODE_OP_DIR_CHECK);
2,359✔
5831
   vcode_add_arg(op, reg);
2,359✔
5832
   vcode_add_arg(op, dir);
2,359✔
5833
   vcode_add_arg(op, locus);
2,359✔
5834

5835
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,359✔
5836
                "locus argument to dir check must be a debug locus");
5837
}
5838

5839
void emit_package_scope(vcode_reg_t locus)
45✔
5840
{
5841
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_SCOPE);
45✔
5842
   vcode_add_arg(op, locus);
45✔
5843

5844
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5845
                "locus argument to package scope must be a debug locus");
5846
}
45✔
5847

5848
void emit_array_scope(vcode_reg_t locus, vcode_type_t type)
654✔
5849
{
5850
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_SCOPE);
654✔
5851
   vcode_add_arg(op, locus);
654✔
5852
   op->type = type;
654✔
5853

5854
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
654✔
5855
                "locus argument to array scope must be a debug locus");
5856
}
654✔
5857

5858
void emit_record_scope(vcode_reg_t locus, vcode_type_t type)
1,690✔
5859
{
5860
   op_t *op = vcode_add_op(VCODE_OP_RECORD_SCOPE);
1,690✔
5861
   vcode_add_arg(op, locus);
1,690✔
5862
   op->type = type;
1,690✔
5863

5864
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,690✔
5865
                "locus argument to record scope must be a debug locus");
5866
}
1,690✔
5867

5868
void emit_pop_scope(void)
2,389✔
5869
{
5870
   vcode_add_op(VCODE_OP_POP_SCOPE);
2,389✔
5871
}
2,389✔
5872

5873
vcode_reg_t emit_debug_locus(object_t *obj)
175,459✔
5874
{
5875
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
6,623,498✔
5876
      if (other->object == obj)
818,732✔
5877
         return other->result;
18,765✔
5878
   }
5879

5880
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
156,694✔
5881
   op->object = obj;
156,694✔
5882

5883
   return (op->result = vcode_add_reg(vtype_debug_locus()));
156,694✔
5884
}
5885

5886
void emit_debug_out(vcode_reg_t reg)
×
5887
{
5888
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
5889
   vcode_add_arg(op, reg);
×
5890
}
×
5891

5892
void emit_cover_stmt(uint32_t tag)
1,300✔
5893
{
5894
   op_t *op = vcode_add_op(VCODE_OP_COVER_STMT);
1,300✔
5895
   op->tag = tag;
1,300✔
5896
}
1,300✔
5897

5898
void emit_cover_branch(uint32_t tag)
499✔
5899
{
5900
   op_t *op = vcode_add_op(VCODE_OP_COVER_BRANCH);
499✔
5901
   op->tag = tag;
499✔
5902
}
499✔
5903

5904
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
312✔
5905
{
5906
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
312✔
5907
   vcode_add_arg(op, signal);
312✔
5908
   op->tag = tag;
312✔
5909
}
312✔
5910

5911
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
12✔
5912
{
5913
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
12✔
5914
   vcode_add_arg(op, signal);
12✔
5915
   vcode_add_arg(op, low);
12✔
5916
   op->tag = tag;
12✔
5917
}
12✔
5918

5919
void emit_cover_expr(uint32_t tag)
887✔
5920
{
5921
   op_t *op = vcode_add_op(VCODE_OP_COVER_EXPR);
887✔
5922
   op->tag = tag;
887✔
5923
}
887✔
5924

5925
void emit_unreachable(vcode_reg_t locus)
1,350✔
5926
{
5927
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
1,350✔
5928
   if (locus != VCODE_INVALID_REG)
1,350✔
5929
      vcode_add_arg(op, locus);
115✔
5930
}
1,350✔
5931

5932
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
63✔
5933
{
5934
   active_unit->flags |= UNIT_UNDEFINED;
63✔
5935

5936
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
63✔
5937
   op->result = vcode_add_reg(type);
63✔
5938
   vcode_reg_data(op->result)->bounds = bounds;
63✔
5939

5940
   return op->result;
63✔
5941
}
5942

5943
void emit_debug_info(const loc_t *loc)
2,445,131✔
5944
{
5945
   if (!loc_invalid_p(loc))
2,445,131✔
5946
      vcode_block_data()->last_loc = *loc;
2,422,870✔
5947
}
2,445,131✔
5948

5949
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
8,117✔
5950
{
5951
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
291,908✔
5952
      if (other->args.items[0] == context && other->ident == name)
11,645✔
5953
         return other->result;
3,790✔
5954
   }
5955

5956
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
4,327✔
5957
   vcode_add_arg(op, context);
4,327✔
5958
   op->ident = name;
4,327✔
5959

5960
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
4,327✔
5961
                "first argument to link var must be context");
5962

5963
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
4,327✔
5964
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
79✔
5965
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
79✔
5966
   }
5967
   else {
5968
      op->result = vcode_add_reg(vtype_pointer(type));
4,248✔
5969
      vcode_reg_data(op->result)->bounds = type;
4,248✔
5970
   }
5971

5972
   return op->result;
4,327✔
5973
}
5974

5975
vcode_reg_t emit_link_package(ident_t name)
12,814✔
5976
{
5977
   VCODE_FOR_EACH_OP(other) {
461,955✔
5978
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
455,302✔
5979
         return other->result;
5,616✔
5980
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
449,686✔
5981
         return other->result;
545✔
5982
   }
5983

5984
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
6,653✔
5985
   op->ident = name;
6,653✔
5986

5987
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
6,653✔
5988

5989
   return (op->result = vcode_add_reg(vtype_context(name)));
6,653✔
5990
}
5991

5992
void emit_enter_state(vcode_reg_t state, vcode_reg_t strong)
849✔
5993
{
5994
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
2,046✔
5995
      if (other->args.items[0] == state)
×
5996
         return;
5997
   }
5998

5999
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
849✔
6000
   vcode_add_arg(op, state);
849✔
6001
   if (strong != VCODE_INVALID_REG)
849✔
6002
      vcode_add_arg(op, strong);
36✔
6003

6004
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
849✔
6005
                "state must have integer type");
6006
   VCODE_ASSERT(strong == VCODE_INVALID_REG
849✔
6007
                || vtype_eq(vcode_reg_type(strong), vtype_bool()),
6008
                "strong argument not is not boolean");
6009
}
6010

6011
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
48✔
6012
                               vcode_reg_t locus, vcode_reg_t bounds)
6013
{
6014
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
48✔
6015
   vcode_add_arg(op, value);
48✔
6016
   vcode_add_arg(op, context);
48✔
6017
   vcode_add_arg(op, locus);
48✔
6018
   if (bounds != VCODE_INVALID_REG)
48✔
6019
      vcode_add_arg(op, bounds);
6✔
6020

6021
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
48✔
6022
                "invalid reflect value context argument");
6023
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
48✔
6024
                "locus argument to reflect value must be a debug locus");
6025

6026
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
48✔
6027
}
6028

6029
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
42✔
6030
                                 vcode_reg_t bounds)
6031
{
6032
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
42✔
6033
   vcode_add_arg(op, context);
42✔
6034
   vcode_add_arg(op, locus);
42✔
6035
   if (bounds != VCODE_INVALID_REG)
42✔
6036
      vcode_add_arg(op, bounds);
×
6037

6038
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
42✔
6039
                "invalid reflect value context argument");
6040
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
42✔
6041
                "locus argument to reflect value must be a debug locus");
6042

6043
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
42✔
6044
}
6045

6046
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
202✔
6047
                                  int nargs)
6048
{
6049
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
202✔
6050
   op->func = func;
202✔
6051

6052
   for (int i = 0; i < nargs; i++)
489✔
6053
      vcode_add_arg(op, args[i]);
287✔
6054

6055
   return (op->result = vcode_add_reg(vtype_trigger()));
202✔
6056
}
6057

6058
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
34✔
6059
{
6060
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
34✔
6061
   vcode_add_arg(op, left);
34✔
6062
   vcode_add_arg(op, right);
34✔
6063

6064
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
34✔
6065
                "or trigger left argument must be trigger");
6066
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
34✔
6067
                "or trigger right argument must be trigger");
6068

6069
   return (op->result = vcode_add_reg(vtype_trigger()));
34✔
6070
}
6071

6072
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
66✔
6073
{
6074
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
66✔
6075
   vcode_add_arg(op, left);
66✔
6076
   vcode_add_arg(op, right);
66✔
6077

6078
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
66✔
6079
                "cmp trigger left argument must be signal");
6080
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
66✔
6081
                "cmp trigger right argument must be integer");
6082

6083
   return (op->result = vcode_add_reg(vtype_trigger()));
66✔
6084
}
6085

6086
void emit_add_trigger(vcode_reg_t trigger)
368✔
6087
{
6088
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
368✔
6089
   vcode_add_arg(op, trigger);
368✔
6090

6091
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
368✔
6092
                "add trigger argument must be trigger");
6093
}
368✔
6094

6095
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
204✔
6096
{
6097
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
204✔
6098
   vcode_add_arg(op, driving);
204✔
6099
   if (effective != VCODE_INVALID_REG && effective != driving)
204✔
6100
      vcode_add_arg(op, effective);
18✔
6101

6102
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
204✔
6103
                "port conversion argument must be a closure");
6104
   VCODE_ASSERT(effective == VCODE_INVALID_REG
204✔
6105
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
6106
                "port conversion argument must be a closure");
6107

6108
   return (op->result = vcode_add_reg(vtype_conversion()));
204✔
6109
}
6110

6111
vcode_reg_t emit_bind_external(vcode_reg_t locus, ident_t scope,
180✔
6112
                               vcode_type_t type, vcode_type_t bounds,
6113
                               const vcode_reg_t *args, int nargs)
6114
{
6115
   op_t *op = vcode_add_op(VCODE_OP_BIND_EXTERNAL);
180✔
6116
   op->type  = type;
180✔
6117
   op->ident = scope;
180✔
6118
   vcode_add_arg(op, locus);
180✔
6119
   for (int i = 0; i < nargs; i++)
210✔
6120
      vcode_add_arg(op, args[i]);
30✔
6121

6122
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
180✔
6123
                "bind external argument must be locus");
6124

6125
   op->result = vcode_add_reg(vtype_pointer(type));
180✔
6126
   vcode_reg_data(op->result)->bounds = bounds;
180✔
6127
   return op->result;
180✔
6128
}
6129

6130
void emit_put_conversion(vcode_reg_t cf, vcode_reg_t target, vcode_reg_t count,
342✔
6131
                         vcode_reg_t values)
6132
{
6133
   op_t *op = vcode_add_op(VCODE_OP_PUT_CONVERSION);
342✔
6134
   vcode_add_arg(op, cf);
342✔
6135
   vcode_add_arg(op, target);
342✔
6136
   vcode_add_arg(op, count);
342✔
6137
   vcode_add_arg(op, values);
342✔
6138

6139
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
342✔
6140
                "put conversion target is not signal");
6141
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
342✔
6142
                "put conversion net count is not offset type");
6143
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
342✔
6144
                "signal cannot be values argument for put conversion");
6145
   VCODE_ASSERT(vcode_reg_kind(cf) == VCODE_TYPE_CONVERSION,
342✔
6146
                "cf argument to put conversion must be conversion function");
6147
}
342✔
6148

6149
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
282✔
6150
{
6151
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
282✔
6152
   vcode_add_arg(op, conv);
282✔
6153
   vcode_add_arg(op, nets);
282✔
6154
   vcode_add_arg(op, count);
282✔
6155

6156
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
282✔
6157
                "conv argument to convert must be a port conversion");
6158
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
282✔
6159
                "nets argument to convert must be a signal");
6160
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
282✔
6161
                "count argument to convert must be offset");
6162
}
282✔
6163

6164
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
324✔
6165
{
6166
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
324✔
6167
   vcode_add_arg(op, conv);
324✔
6168
   vcode_add_arg(op, nets);
324✔
6169
   vcode_add_arg(op, count);
324✔
6170

6171
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
324✔
6172
                "conv argument to convert must be a port conversion");
6173
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
324✔
6174
                "nets argument to convert must be a signal");
6175
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
324✔
6176
                "count argument to convert must be offset");
6177
}
324✔
6178

6179
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
1,004✔
6180
{
6181
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
1,004✔
6182
   vcode_add_arg(op, spec);
1,004✔
6183
   vcode_add_arg(op, length);
1,004✔
6184
   if (locus != VCODE_INVALID_REG)
1,004✔
6185
      vcode_add_arg(op, locus);
830✔
6186

6187
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
1,004✔
6188
                "spec argument to bind foreign must be a pointer");
6189
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
1,004✔
6190
                "length argument to bind foreign must be offset");
6191
   VCODE_ASSERT(locus == VCODE_INVALID_REG
1,004✔
6192
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6193
                "locus argument to bind foreign value must be a debug locus");
6194
}
1,004✔
6195

6196
vcode_reg_t emit_instance_name(vcode_reg_t kind)
767✔
6197
{
6198
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
767✔
6199
   vcode_add_arg(op, kind);
767✔
6200

6201
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
767✔
6202
                "kind argument to instance name must be offset");
6203

6204
   vcode_type_t vchar = vtype_char();
767✔
6205
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
767✔
6206
}
6207

6208
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
15,349✔
6209
{
6210
   vcode_state_t state;
15,349✔
6211
   vcode_state_save(&state);
15,349✔
6212

6213
   vcode_select_unit(vu);
15,349✔
6214

6215
   const int nblocks = vcode_count_blocks();
15,349✔
6216
   for (int i = 0; i < nblocks; i++) {
54,751✔
6217
      vcode_select_block(i);
39,402✔
6218

6219
      const int nops = vcode_count_ops();
39,402✔
6220
      for (int op = 0; op < nops; op++) {
653,290✔
6221
         switch (vcode_get_op(op)) {
613,888✔
6222
         case VCODE_OP_LINK_PACKAGE:
2,209✔
6223
            (*fn)(vcode_get_ident(op), ctx);
2,209✔
6224
            break;
2,209✔
6225
         case VCODE_OP_FCALL:
23,903✔
6226
         case VCODE_OP_PCALL:
6227
         case VCODE_OP_CLOSURE:
6228
         case VCODE_OP_PROTECTED_INIT:
6229
         case VCODE_OP_PACKAGE_INIT:
6230
         case VCODE_OP_FUNCTION_TRIGGER:
6231
            (*fn)(vcode_get_func(op), ctx);
23,903✔
6232
            break;
23,903✔
6233
         default:
6234
            break;
6235
         }
6236
      }
6237
   }
6238

6239
   vcode_state_restore(&state);
15,349✔
6240
}
15,349✔
6241

6242
#if VCODE_CHECK_UNIONS
6243
#define OP_USE_COUNT_U0(x)                                              \
6244
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6245
#define OP_USE_COUNT_U1(x)                                              \
6246
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6247
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6248
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6249

6250
__attribute__((constructor))
6251
static void vcode_check_unions(void)
6252
{
6253
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6254
   for (int i = 0; i < 256; i++) {
6255
      assert(OP_USE_COUNT_U0(i) <= 1);
6256
      assert(OP_USE_COUNT_U1(i) <= 1);
6257
   }
6258
}
6259
#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

© 2025 Coveralls, Inc