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

nickg / nvc / 16099065297

06 Jul 2025 12:33PM UTC coverage: 92.335% (+0.05%) from 92.284%
16099065297

push

github

nickg
Handle underscores in Verilog decimal literals

18 of 20 new or added lines in 1 file covered. (90.0%)

598 existing lines in 16 files now uncovered.

71069 of 76969 relevant lines covered (92.33%)

566474.1 hits per line

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

96.42
/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 "tree.h"
26
#include "vcode.h"
27

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

35
DECLARE_AND_DEFINE_ARRAY(vcode_reg);
13,316,066✔
36
DECLARE_AND_DEFINE_ARRAY(vcode_block);
498,135✔
37
DECLARE_AND_DEFINE_ARRAY(vcode_type);
106,512✔
38

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

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

106
DECLARE_AND_DEFINE_ARRAY(op);
15,976,763✔
107

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

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

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

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

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

159
DECLARE_AND_DEFINE_ARRAY(param);
51,031✔
160
DECLARE_AND_DEFINE_ARRAY(var);
579,519✔
161
DECLARE_AND_DEFINE_ARRAY(reg);
12,842,106✔
162
DECLARE_AND_DEFINE_ARRAY(block);
196,839✔
163
DECLARE_AND_DEFINE_ARRAY(vtype);
112,339,940✔
164

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

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

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

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

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

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

212
#define VCODE_CHECK_UNIONS 0
213

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

217
static inline int64_t sadd64(int64_t a, int64_t b)
52,146✔
218
{
219
   int64_t result;
52,146✔
220
   if (__builtin_add_overflow(a, b, &result))
52,146✔
221
      return b < 0 ? INT64_MIN : INT64_MAX;
12,762✔
222

223
   return result;
224
}
225

226
static inline int64_t ssub64(int64_t a, int64_t b)
85,800✔
227
{
228
   int64_t result;
85,800✔
229
   if (__builtin_sub_overflow(a, b, &result))
85,800✔
230
      return b > 0 ? INT64_MIN : INT64_MAX;
1,166✔
231

232
   return result;
233
}
234

235
static inline int64_t smul64(int64_t a, int64_t b)
16,292✔
236
{
237
   int64_t result;
16,292✔
238
   if (__builtin_mul_overflow(a, b, &result))
16,292✔
239
      return (a > 0 && b > 0) || (a < 0 && b < 0) ? INT64_MAX : INT64_MIN;
3,149✔
240

241
   return result;
242
}
243

244
static vcode_reg_t vcode_add_reg(vcode_type_t type)
1,989,043✔
245
{
246
   assert(active_unit != NULL);
1,989,043✔
247

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

254
   return reg;
1,989,043✔
255
}
256

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

264
static op_t *vcode_add_op(vcode_op_t kind)
2,535,970✔
265
{
266
   assert(active_unit != NULL);
2,535,970✔
267
   assert(active_block != VCODE_INVALID_BLOCK);
2,535,970✔
268

269
   VCODE_ASSERT(
2,535,970✔
270
      !vcode_block_finished(),
271
      "attempt to add to already finished block %d", active_block);
272

273
   block_t *block = vcode_block_data();
2,535,970✔
274

275
   op_t *op = op_array_alloc(&(block->ops));
2,535,970✔
276
   memset(op, '\0', sizeof(op_t));
2,535,970✔
277
   op->kind   = kind;
2,535,970✔
278
   op->result = VCODE_INVALID_REG;
2,535,970✔
279
   op->loc    = block->last_loc;
2,535,970✔
280

281
   return op;
2,535,970✔
282
}
283

284
static void vcode_add_arg(op_t *op, vcode_reg_t arg)
4,369,675✔
285
{
286
   vcode_reg_array_add(&(op->args), arg);
4,369,675✔
287
}
4,369,675✔
288

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

294
static op_t *vcode_op_data(int op)
13,440,793✔
295
{
296
   assert(active_unit != NULL);
13,440,793✔
297
   assert(active_block != VCODE_INVALID_BLOCK);
13,440,793✔
298

299
   block_t *b = &(active_unit->blocks.items[active_block]);
13,440,793✔
300
   return op_array_nth_ptr(&(b->ops), op);
13,440,793✔
301
}
302

303
static op_t *vcode_find_definition(vcode_reg_t reg)
2,129,815✔
304
{
305
   for (int i = active_block; i >= 0; i--) {
2,179,610✔
306
      block_t *b = &(active_unit->blocks.items[i]);
2,177,311✔
307
      for (int j = b->ops.count - 1; j >= 0; j--) {
41,786,779✔
308
         if (b->ops.items[j].result == reg)
41,736,984✔
309
            return &(b->ops.items[j]);
2,127,516✔
310
      }
311
   }
312

313
   return NULL;
314
}
315

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

333
static reg_t *vcode_reg_data(vcode_reg_t reg)
10,853,063✔
334
{
335
   assert(active_unit != NULL);
10,853,063✔
336
   assert(reg != VCODE_INVALID_REG);
10,853,063✔
337
   return reg_array_nth_ptr(&(active_unit->regs), reg);
10,853,063✔
338
}
339

340
static vtype_t *vcode_type_data(vcode_type_t type)
107,893,250✔
341
{
342
   assert(type != VCODE_INVALID_TYPE);
107,893,250✔
343
   assert(active_unit != NULL);
107,893,250✔
344
   vcode_unit_t unit = active_unit;
107,893,250✔
345

346
   int depth = MASK_CONTEXT(type);
107,893,250✔
347
   assert(depth <= unit->depth);
107,893,250✔
348
   while (depth != unit->depth)
109,499,136✔
349
      unit = unit->context;
1,605,886✔
350

351
   return vtype_array_nth_ptr(&(unit->types), MASK_INDEX(type));
107,893,250✔
352
}
353

354
static var_t *vcode_var_data(vcode_var_t var)
487,559✔
355
{
356
   assert(active_unit != NULL);
487,559✔
357
   assert(var != VCODE_INVALID_VAR);
487,559✔
358

359
   return var_array_nth_ptr(&(active_unit->vars), var);
487,559✔
360
}
361

362
void vcode_heap_allocate(vcode_reg_t reg)
17,006✔
363
{
364
   op_t *defn = vcode_find_definition(reg);
24,806✔
365
   if (defn == NULL) {
24,806✔
366
      // It is always safe to return a pointer to an argument
367
      return;
368
   }
369

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

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

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

395
   case VCODE_OP_VAR_UPREF:
1,010✔
396
      {
397
         vcode_unit_t vu = vcode_active_unit();
1,010✔
398
         for (int i = 0; i < defn->hops; i++)
2,024✔
399
            vu = vcode_unit_context(vu);
1,014✔
400

401
         vcode_state_t state;
1,010✔
402
         vcode_state_save(&state);
1,010✔
403

404
         vcode_select_unit(vu);
1,010✔
405

406
         vcode_var_data(defn->address)->flags |= VAR_HEAP;
1,010✔
407

408
         vcode_state_restore(&state);
1,010✔
409
      }
410
      break;
1,010✔
411

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

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

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

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

431
         // Any store to this variable must be heap allocated
432
         for (int i = 0; i < active_unit->blocks.count; i++) {
29,252✔
433
            block_t *b = &(active_unit->blocks.items[i]);
27,398✔
434
            for (int j = 0; j < b->ops.count; j++) {
369,513✔
435
               op_t *op = &(b->ops.items[j]);
342,115✔
436
               if (op->kind == VCODE_OP_STORE && op->address == defn->address)
342,115✔
437
                  vcode_heap_allocate(op->args.items[0]);
1,854✔
438

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

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

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

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

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

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

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

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

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

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

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

533
void vcode_unit_unref(vcode_unit_t unit)
70,883✔
534
{
535
   assert(unit != NULL);
70,883✔
536

537
   if (unit == active_unit)
70,883✔
538
      vcode_close();
15,432✔
539

540
   for (vcode_unit_t it = unit->children; it != NULL; it = it->next) {
92,958✔
541
      assert(it->context == unit);
22,075✔
542
      it->context = NULL;
22,075✔
543
   }
544
   unit->children = NULL;
70,883✔
545

546
   if (unit->context != NULL) {
70,883✔
547
      vcode_unit_t *it = &(unit->context->children);
19,432✔
548
      for (; *it != NULL && *it != unit; it = &((*it)->next))
57,497✔
549
         ;
550
      assert(*it != NULL);
19,432✔
551
      *it = (*it)->next;
19,432✔
552
   }
553

554
   for (unsigned i = 0; i < unit->blocks.count; i++) {
267,684✔
555
      block_t *b = &(unit->blocks.items[i]);
196,801✔
556

557
      for (unsigned j = 0; j < b->ops.count; j++) {
2,611,759✔
558
         op_t *o = &(b->ops.items[j]);
2,414,958✔
559
         if (OP_HAS_COMMENT(o->kind))
2,414,958✔
560
            free(o->comment);
264,527✔
561
         if (OP_HAS_TARGET(o->kind))
2,414,958✔
562
            free(o->targets.items);
116,044✔
563
         free(o->args.items);
2,414,958✔
564
      }
565
      free(b->ops.items);
196,801✔
566
   }
567
   free(unit->blocks.items);
70,883✔
568

569
   for (unsigned i = 0; i < unit->types.count; i++) {
972,876✔
570
      vtype_t *vt = &(unit->types.items[i]);
901,993✔
571
      if (vt->kind == VCODE_TYPE_RECORD)
901,993✔
572
         free(vt->fields.items);
7,420✔
573
   }
574
   free(unit->types.items);
70,883✔
575

576
   free(unit->regs.items);
70,883✔
577
   free(unit->vars.items);
70,883✔
578
   free(unit->params.items);
70,883✔
579
   free(unit);
70,883✔
580
}
70,883✔
581

582
vcode_unit_t vcode_unit_next(vcode_unit_t unit)
23,274✔
583
{
584
   return unit->next;
23,274✔
585
}
586

587
vcode_unit_t vcode_unit_child(vcode_unit_t unit)
20,934✔
588
{
589
   return unit->children;
20,934✔
590
}
591

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

598
vcode_type_t vcode_reg_type(vcode_reg_t reg)
7,205,623✔
599
{
600
   return vcode_reg_data(reg)->type;
7,205,623✔
601
}
602

603
vtype_kind_t vcode_reg_kind(vcode_reg_t reg)
1,852,286✔
604
{
605
   return vtype_kind(vcode_reg_type(reg));
1,852,286✔
606
}
607

608
vcode_type_t vcode_reg_bounds(vcode_reg_t reg)
592,831✔
609
{
610
   return vcode_reg_data(reg)->bounds;
592,831✔
611
}
612

613
bool vcode_reg_const(vcode_reg_t reg, int64_t *value)
1,193,355✔
614
{
615
   reg_t *r = vcode_reg_data(reg);
1,193,355✔
616

617
   vtype_kind_t kind = vtype_kind(r->type);
1,193,355✔
618
   if (kind != VCODE_TYPE_INT && kind != VCODE_TYPE_OFFSET)
1,193,355✔
619
      return false;
620

621
   vtype_t *bounds = vcode_type_data(r->bounds);
1,151,041✔
622

623
   VCODE_ASSERT(
1,151,041✔
624
      bounds->kind == VCODE_TYPE_INT || bounds->kind == VCODE_TYPE_OFFSET,
625
      "integer register r%d has non-integer bounds", reg);
626

627
   if (bounds->low == bounds->high) {
1,151,041✔
628
      if (value) *value = bounds->low;
653,390✔
629
      return true;
653,390✔
630
   }
631
   else
632
      return false;
633
}
634

635
void vcode_opt(void)
70,905✔
636
{
637
   // Prune assignments to unused registers
638

639
   int *uses LOCAL = xmalloc_array(active_unit->regs.count, sizeof(int));
141,810✔
640

641
   int pruned = 0;
70,905✔
642
   do {
101,940✔
643
      memset(uses, '\0', active_unit->regs.count * sizeof(int));
101,940✔
644
      pruned = 0;
101,940✔
645

646
      for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
430,810✔
647
         block_t *b = &(active_unit->blocks.items[i]);
328,870✔
648

649
         for (int j = b->ops.count - 1; j >= 0; j--) {
4,853,733✔
650
            op_t *o = &(b->ops.items[j]);
4,524,863✔
651

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

714
            default:
715
               break;
716
            }
717

718
            for (int k = 0; k < o->args.count; k++) {
12,526,787✔
719
               if (o->args.items[k] != VCODE_INVALID_REG)
8,001,924✔
720
                  uses[o->args.items[k]]++;
7,938,899✔
721
            }
722
         }
723
      }
724
   } while (pruned > 0);
101,940✔
725

726
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
267,744✔
727
      block_t *b = &(active_unit->blocks.items[i]);
196,839✔
728
      op_t *dst = &(b->ops.items[0]);
196,839✔
729
      size_t copied = 0;
196,839✔
730
      for (int j = 0; j < b->ops.count; j++) {
2,732,809✔
731
         const op_t *src = &(b->ops.items[j]);
2,535,970✔
732
         if (src->kind != (vcode_op_t)-1) {
2,535,970✔
733
            if (src != dst) {
2,415,463✔
734
               assert(dst < src);
794,794✔
735
               *dst = *src;
794,794✔
736
            }
737
            dst++;
2,415,463✔
738
            copied++;
2,415,463✔
739
         }
740
      }
741

742
      assert(copied <= b->ops.count);
196,839✔
743
      b->ops.count = copied;
196,839✔
744
   }
745
}
70,905✔
746

747
void vcode_close(void)
40,737✔
748
{
749
   active_unit  = NULL;
40,737✔
750
   active_block = -1;
40,737✔
751
}
40,737✔
752

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

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

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

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

780
   return VCODE_INVALID_VAR;
781
}
782

783
ident_t vcode_var_name(vcode_var_t var)
97,171✔
784
{
785
   return vcode_var_data(var)->name;
97,171✔
786
}
787

788
vcode_type_t vcode_var_type(vcode_var_t var)
98,254✔
789
{
790
   return vcode_var_data(var)->type;
98,254✔
791
}
792

793
vcode_type_t vcode_var_bounds(vcode_var_t var)
4,508✔
794
{
795
   return vcode_var_data(var)->bounds;
4,508✔
796
}
797

798
vcode_var_flags_t vcode_var_flags(vcode_var_t var)
100,015✔
799
{
800
   return vcode_var_data(var)->flags;
100,015✔
801
}
802

803
vcode_op_t vcode_get_op(int op)
3,224,421✔
804
{
805
   return vcode_op_data(op)->kind;
3,224,421✔
806
}
807

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

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

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

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

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

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

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

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

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

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

878
int vcode_count_args(int op)
323,455✔
879
{
880
   return vcode_op_data(op)->args.count;
323,455✔
881
}
882

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

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

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

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

909
const loc_t *vcode_get_loc(int op)
2,408,554✔
910
{
911
   op_t *o = vcode_op_data(op);
2,408,554✔
912
   return &(o->loc);
2,408,554✔
913
}
914

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

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

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

930
bool vcode_block_finished(void)
2,695,180✔
931
{
932
   assert(active_unit != NULL);
2,695,180✔
933
   assert(active_block != VCODE_INVALID_BLOCK);
2,695,180✔
934

935
   const block_t *b = &(active_unit->blocks.items[active_block]);
2,695,180✔
936
   if (b->ops.count == 0)
2,695,180✔
937
      return false;
938
   else {
939
      vcode_op_t kind = b->ops.items[b->ops.count - 1].kind;
2,430,822✔
940
      return kind == VCODE_OP_WAIT || kind == VCODE_OP_JUMP
2,430,822✔
941
         || kind == VCODE_OP_COND || kind == VCODE_OP_PCALL
2,430,798✔
942
         || kind == VCODE_OP_RETURN || kind == VCODE_OP_CASE
943
         || kind == VCODE_OP_UNREACHABLE;
4,861,620✔
944
   }
945
}
946

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1121
   return col;
1122
}
1123

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1512
         case VCODE_OP_WAIT:
1513
            {
1514
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1515
                            op->targets.items[0]);
1516
               if (op->args.items[0] != VCODE_INVALID_REG) {
1517
                  printf(" for ");
1518
                  vcode_dump_reg(op->args.items[0]);
1519
               }
1520
            }
1521
            break;
1522

1523
         case VCODE_OP_JUMP:
1524
            {
1525
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1526
                            op->targets.items[0]);
1527
            }
1528
            break;
1529

1530
         case VCODE_OP_COND:
1531
            {
1532
               printf("%s ", vcode_op_string(op->kind));
1533
               vcode_dump_reg(op->args.items[0]);
1534
               color_printf(" then $yellow$%d$$ else $yellow$%d$$",
1535
                            op->targets.items[0], op->targets.items[1]);
1536
            }
1537
            break;
1538

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

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

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

1584
         case VCODE_OP_LOAD_INDIRECT:
1585
            {
1586
               col += vcode_dump_reg(op->result);
1587
               col += color_printf(" := %s ", vcode_op_string(op->kind));
1588
               col += vcode_dump_reg(op->args.items[0]);
1589
               vcode_dump_result_type(col, op);
1590
            }
1591
            break;
1592

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

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

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

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

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

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

1691
         case VCODE_OP_COMMENT:
1692
            {
1693
               color_printf("$cyan$// %s$$ ", op->comment);
1694
            }
1695
            break;
1696

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

1709
               putchar(op->kind == VCODE_OP_CONST_ARRAY ? ']' : '}');
1710
               vcode_dump_result_type(col + 1, op);
1711
            }
1712
            break;
1713

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1909
         case VCODE_OP_COPY:
1910
            {
1911
               vcode_dump_reg(op->args.items[0]);
1912
               printf(" := %s ", vcode_op_string(op->kind));
1913
               vcode_dump_reg(op->args.items[1]);
1914
               if (op->args.count > 2) {
1915
                  printf(" count " );
1916
                  vcode_dump_reg(op->args.items[2]);
1917
               }
1918
            }
1919
            break;
1920

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

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

1944
         case VCODE_OP_RESUME:
1945
            {
1946
               color_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1947
                            istr(op->func));
1948
            }
1949
            break;
1950

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2128
         case VCODE_OP_DEBUG_OUT:
2129
            {
2130
               col += printf("%s ", vcode_op_string(op->kind));
2131
               col += vcode_dump_reg(op->args.items[0]);
2132
            }
2133
            break;
2134

2135
         case VCODE_OP_COVER_STMT:
2136
         case VCODE_OP_COVER_BRANCH:
2137
         case VCODE_OP_COVER_EXPR:
2138
            {
2139
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2140
            }
2141
            break;
2142

2143
         case VCODE_OP_COVER_TOGGLE:
2144
         case VCODE_OP_COVER_STATE:
2145
            {
2146
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2147
               vcode_dump_reg(op->args.items[0]);
2148
            }
2149
            break;
2150

2151
         case VCODE_OP_UNDEFINED:
2152
            {
2153
               col += vcode_dump_reg(op->result);
2154
               col += printf(" := %s", vcode_op_string(op->kind));
2155
               vcode_dump_result_type(col, op);
2156
            }
2157
            break;
2158

2159
         case VCODE_OP_RANGE_LENGTH:
2160
         case VCODE_OP_RANGE_NULL:
2161
            {
2162
               col += vcode_dump_reg(op->result);
2163
               col += printf(" := %s left ", vcode_op_string(op->kind));
2164
               vcode_dump_reg(op->args.items[0]);
2165
               col += printf(" right ");
2166
               vcode_dump_reg(op->args.items[1]);
2167
               col += printf(" dir ");
2168
               col += vcode_dump_reg(op->args.items[2]);
2169
               vcode_dump_result_type(col, op);
2170
            }
2171
            break;
2172

2173
         case VCODE_OP_LINK_PACKAGE:
2174
            {
2175
               col += vcode_dump_reg(op->result);
2176
               col += color_printf(" := %s $magenta$%s$$",
2177
                                   vcode_op_string(op->kind), istr(op->ident));
2178
               if (op->args.count > 0) {
2179
                  col += printf(" locus ");
2180
                  col += vcode_dump_reg(op->args.items[0]);
2181
               }
2182
               vcode_dump_result_type(col, op);
2183
            }
2184
            break;
2185

2186
         case VCODE_OP_LINK_VAR:
2187
            {
2188
               col += vcode_dump_reg(op->result);
2189
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2190
               col += vcode_dump_reg(op->args.items[0]);
2191
               col += color_printf(" $magenta$%s$$", istr(op->ident));
2192
               vcode_dump_result_type(col, op);
2193
            }
2194
            break;
2195

2196
         case VCODE_OP_UNREACHABLE:
2197
            {
2198
               printf("%s", vcode_op_string(op->kind));
2199
               if (op->args.count > 0) {
2200
                  printf(" ");
2201
                  vcode_dump_reg(op->args.items[0]);
2202
               }
2203
            }
2204
            break;
2205

2206
         case VCODE_OP_DEBUG_LOCUS:
2207
            {
2208
               col += vcode_dump_reg(op->result);
2209
               col += color_printf(" := %s $magenta$",
2210
                                   vcode_op_string(op->kind));
2211

2212
               tree_t t = tree_from_object(op->object);
2213
               if (t != NULL)
2214
                  col += printf("%s@", tree_kind_str(tree_kind(t)));
2215

2216
               col += color_printf("%p$$", op->object);
2217
               vcode_dump_result_type(col, op);
2218
            }
2219
            break;
2220

2221
         case VCODE_OP_ENTER_STATE:
2222
            {
2223
               printf("%s ", vcode_op_string(op->kind));
2224
               vcode_dump_reg(op->args.items[0]);
2225
               if (op->args.count > 1) {
2226
                  printf(" strong ");
2227
                  vcode_dump_reg(op->args.items[1]);
2228
               }
2229
            }
2230
            break;
2231

2232
         case VCODE_OP_REFLECT_VALUE:
2233
            {
2234
               col += vcode_dump_reg(op->result);
2235
               col += printf(" := %s ", vcode_op_string(op->kind));
2236
               vcode_dump_reg(op->args.items[0]);
2237
               col += printf(" context ");
2238
               vcode_dump_reg(op->args.items[1]);
2239
               col += printf(" locus ");
2240
               col += vcode_dump_reg(op->args.items[2]);
2241
               if (op->args.count > 3) {
2242
                  col += printf(" bounds ");
2243
                  col += vcode_dump_reg(op->args.items[3]);
2244
               }
2245
               vcode_dump_result_type(col, op);
2246
            }
2247
            break;
2248

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

2264
         case VCODE_OP_FUNCTION_TRIGGER:
2265
            {
2266
               col += vcode_dump_reg(op->result);
2267
               col += color_printf(" := %s $magenta$%s$$ ",
2268
                                   vcode_op_string(op->kind), istr(op->func));
2269
               for (int i = 0; i < op->args.count; i++) {
2270
                  if (i > 0) col += printf(", ");
2271
                  col += vcode_dump_reg(op->args.items[i]);
2272
               }
2273
               vcode_dump_result_type(col, op);
2274
            }
2275
            break;
2276

2277
         case VCODE_OP_OR_TRIGGER:
2278
         case VCODE_OP_CMP_TRIGGER:
2279
            {
2280
               col += vcode_dump_reg(op->result);
2281
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2282
               col += vcode_dump_reg(op->args.items[0]);
2283
               if (op->kind == VCODE_OP_OR_TRIGGER)
2284
                  col += printf(" || ");
2285
               else
2286
                  col += printf(" == ");
2287
               col += vcode_dump_reg(op->args.items[1]);
2288
               vcode_dump_result_type(col, op);
2289
            }
2290
            break;
2291

2292
         case VCODE_OP_ADD_TRIGGER:
2293
            {
2294
               printf("%s ", vcode_op_string(op->kind));
2295
               vcode_dump_reg(op->args.items[0]);
2296
            }
2297
            break;
2298

2299
         case VCODE_OP_PUT_CONVERSION:
2300
            {
2301
               color_printf("%s ", vcode_op_string(op->kind));
2302
               vcode_dump_reg(op->args.items[0]);
2303
               printf(" signal ");
2304
               vcode_dump_reg(op->args.items[1]);
2305
               printf(" count ");
2306
               vcode_dump_reg(op->args.items[2]);
2307
               printf(" values ");
2308
               vcode_dump_reg(op->args.items[3]);
2309
            }
2310
            break;
2311

2312
         case VCODE_OP_PORT_CONVERSION:
2313
            {
2314
               col += vcode_dump_reg(op->result);
2315
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2316
               col += vcode_dump_reg(op->args.items[0]);
2317
               if (op->args.count > 1) {
2318
                  col += printf(" effective ");
2319
                  col += vcode_dump_reg(op->args.items[1]);
2320
               }
2321
               vcode_dump_result_type(col, op);
2322
            }
2323
            break;
2324

2325
         case VCODE_OP_CONVERT_IN:
2326
         case VCODE_OP_CONVERT_OUT:
2327
            {
2328
               color_printf("%s ", vcode_op_string(op->kind));
2329
               vcode_dump_reg(op->args.items[0]);
2330
               printf(" signal ");
2331
               vcode_dump_reg(op->args.items[1]);
2332
               printf(" count ");
2333
               vcode_dump_reg(op->args.items[2]);
2334
            }
2335
            break;
2336

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

2350
         case VCODE_OP_INSTANCE_NAME:
2351
         case VCODE_OP_BIND_EXTERNAL:
2352
            {
2353
               col += vcode_dump_reg(op->result);
2354
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2355
               col += vcode_dump_reg(op->args.items[0]);
2356
               col += color_printf(" scope $magenta$%s$$", istr(op->ident));
2357
               vcode_dump_result_type(col, op);
2358
            }
2359
            break;
2360
         }
2361

2362
         if (j == mark_op && i == old_block)
2363
            color_printf("\t $red$<----$$");
2364

2365
         color_printf("$$\n");
2366

2367
         if (callback != NULL)
2368
            (*callback)(j, arg);
2369
      }
2370

2371
      if (b->ops.count == 0)
2372
         color_printf("  $yellow$%2d:$$ $red$Empty basic block$$\n", i);
2373
   }
2374

2375
   printf("\n");
2376
   fflush(stdout);
2377

2378
   active_block = old_block;
2379
}
2380
LCOV_EXCL_STOP
2381

2382
bool vtype_eq(vcode_type_t a, vcode_type_t b)
52,564,066✔
2383
{
2384
   assert(active_unit != NULL);
53,351,702✔
2385

2386
   if (a == b)
53,351,702✔
2387
      return true;
2388
   else {
2389
      const vtype_t *at = vcode_type_data(a);
48,673,590✔
2390
      const vtype_t *bt = vcode_type_data(b);
48,673,590✔
2391

2392
      if (at->kind != bt->kind)
48,673,590✔
2393
         return false;
2394

2395
      switch (at->kind) {
21,452,598✔
2396
      case VCODE_TYPE_INT:
18,456,531✔
2397
         return (at->low == bt->low) && (at->high == bt->high);
34,361,604✔
2398
      case VCODE_TYPE_REAL:
1,311,991✔
2399
         return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
2,529,148✔
2400
      case VCODE_TYPE_CARRAY:
125,740✔
2401
         return at->size == bt->size && vtype_eq(at->elem, bt->elem);
138,485✔
2402
      case VCODE_TYPE_UARRAY:
107,105✔
2403
         return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
133,809✔
2404
      case VCODE_TYPE_POINTER:
651,521✔
2405
      case VCODE_TYPE_ACCESS:
2406
         return vtype_eq(at->pointed, bt->pointed);
651,521✔
2407
      case VCODE_TYPE_OFFSET:
2408
      case VCODE_TYPE_OPAQUE:
2409
      case VCODE_TYPE_DEBUG_LOCUS:
2410
      case VCODE_TYPE_TRIGGER:
2411
      case VCODE_TYPE_CONVERSION:
2412
         return true;
2413
      case VCODE_TYPE_RESOLUTION:
136,115✔
2414
      case VCODE_TYPE_CLOSURE:
2415
      case VCODE_TYPE_SIGNAL:
2416
      case VCODE_TYPE_FILE:
2417
         return vtype_eq(at->base, bt->base);
136,115✔
2418
      case VCODE_TYPE_RECORD:
118,555✔
2419
      case VCODE_TYPE_CONTEXT:
2420
         return at->name == bt->name;
118,555✔
2421
      }
2422

UNCOV
2423
      return false;
×
2424
   }
2425
}
2426

UNCOV
2427
void vcode_dump(void)
×
2428
{
UNCOV
2429
   vcode_dump_with_mark(-1, NULL, NULL);
×
2430
}
×
2431

2432
static vcode_type_t vtype_new(vtype_t *new)
4,446,690✔
2433
{
2434
   int index = active_unit->types.count - 1;
4,446,690✔
2435
   vcode_type_t type = MAKE_HANDLE(active_unit->depth, index);
4,446,690✔
2436

2437
   for (int i = 0; i < index; i++) {
48,253,556✔
2438
      vcode_type_t this = MAKE_HANDLE(active_unit->depth, i);
47,351,300✔
2439
      if (vtype_eq(this, type)) {
47,351,300✔
2440
         active_unit->types.count--;
3,544,434✔
2441
         return this;
3,544,434✔
2442
      }
2443
   }
2444

2445
   return type;
2446
}
2447

2448
vcode_type_t vtype_int(int64_t low, int64_t high)
3,049,902✔
2449
{
2450
   assert(active_unit != NULL);
3,049,902✔
2451

2452
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
3,049,902✔
2453
   n->kind = VCODE_TYPE_INT;
3,049,902✔
2454
   n->low  = low;
3,049,902✔
2455
   n->high = high;
3,049,902✔
2456

2457
   switch (bits_for_range(low, high)) {
3,049,902✔
2458
   case 64:
175,992✔
2459
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
175,992✔
2460
      break;
175,992✔
2461
   case 32:
851,879✔
2462
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
851,879✔
2463
      break;
851,879✔
2464
   case 16:
5,747✔
2465
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
5,747✔
2466
      break;
5,747✔
2467
   case 8:
1,123,690✔
2468
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
1,123,690✔
2469
      break;
1,123,690✔
2470
   case 1:
892,593✔
2471
      n->repr = VCODE_REPR_U1;
892,593✔
2472
      break;
892,593✔
2473
   case 0:
1✔
2474
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2475
      break;
1✔
UNCOV
2476
   default:
×
2477
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
2478
   }
2479

2480
   return vtype_new(n);
3,049,902✔
2481
}
2482

2483
vcode_type_t vtype_bool(void)
456,830✔
2484
{
2485
   return vtype_int(0, 1);
456,830✔
2486
}
2487

2488
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
68,225✔
2489
{
2490
   assert(active_unit != NULL);
68,225✔
2491

2492
   const vtype_kind_t ekind = vtype_kind(elem);
68,225✔
2493
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
68,225✔
2494
                "array types may not be nested");
2495

2496
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
68,225✔
2497
   memset(n, '\0', sizeof(vtype_t));
68,225✔
2498
   n->kind   = VCODE_TYPE_CARRAY;
68,225✔
2499
   n->elem   = elem;
68,225✔
2500
   n->bounds = bounds;
68,225✔
2501
   n->size   = MAX(size, 0);
68,225✔
2502

2503
   return vtype_new(n);
68,225✔
2504
}
2505

2506
vcode_type_t vtype_find_named_record(ident_t name)
48,749✔
2507
{
2508
   assert(active_unit != NULL);
48,749✔
2509

2510
   for (int i = 0; i < active_unit->types.count; i++) {
631,724✔
2511
      vtype_t *other = &(active_unit->types.items[i]);
616,884✔
2512
      if (other->kind == VCODE_TYPE_RECORD && other->name == name)
616,884✔
2513
         return MAKE_HANDLE(active_unit->depth, i);
33,909✔
2514
   }
2515

2516
   return VCODE_INVALID_TYPE;
2517
}
2518

2519
vcode_type_t vtype_named_record(ident_t name, const vcode_type_t *field_types,
14,840✔
2520
                                int nfields)
2521
{
2522
   assert(active_unit != NULL);
14,840✔
2523

2524
   vtype_t *data = NULL;
14,840✔
2525
   vcode_type_t handle = vtype_find_named_record(name);
14,840✔
2526
   if (handle == VCODE_INVALID_TYPE) {
14,840✔
2527
      data = vtype_array_alloc(&(active_unit->types));
7,420✔
2528
      memset(data, '\0', sizeof(vtype_t));
7,420✔
2529
      data->kind = VCODE_TYPE_RECORD;
7,420✔
2530
      data->name = name;
7,420✔
2531

2532
      handle = vtype_new(data);
7,420✔
2533
   }
2534
   else {
2535
      data = vcode_type_data(handle);
7,420✔
2536
      VCODE_ASSERT(data->fields.count == 0,
7,420✔
2537
                    "record type %s already defined", istr(name));
2538
   }
2539

2540
   vcode_type_array_resize(&(data->fields), 0, VCODE_INVALID_TYPE);
14,840✔
2541
   for (int i = 0; i < nfields; i++)
40,288✔
2542
      vcode_type_array_add(&(data->fields), field_types[i]);
25,448✔
2543

2544
   return handle;
14,840✔
2545
}
2546

2547
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
104,531✔
2548
{
2549
   assert(active_unit != NULL);
104,531✔
2550

2551
   const vtype_kind_t ekind = vtype_kind(elem);
104,531✔
2552
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
104,531✔
2553
                "array types may not be nested");
2554

2555
   VCODE_ASSERT(ndim > 0, "uarray must have at least one dimension");
104,531✔
2556

2557
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
104,531✔
2558
   memset(n, '\0', sizeof(vtype_t));
104,531✔
2559
   n->kind   = VCODE_TYPE_UARRAY;
104,531✔
2560
   n->elem   = elem;
104,531✔
2561
   n->bounds = bounds;
104,531✔
2562
   n->dims   = ndim;
104,531✔
2563

2564
   return vtype_new(n);
104,531✔
2565
}
2566

2567
vcode_type_t vtype_pointer(vcode_type_t to)
275,168✔
2568
{
2569
   assert(active_unit != NULL);
275,168✔
2570

2571
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
275,168✔
2572
   n->kind    = VCODE_TYPE_POINTER;
275,168✔
2573
   n->pointed = to;
275,168✔
2574

2575
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
275,168✔
2576
                "cannot get pointer to carray type");
2577

2578
   return vtype_new(n);
275,168✔
2579
}
2580

2581
vcode_type_t vtype_access(vcode_type_t to)
12,586✔
2582
{
2583
   assert(active_unit != NULL);
12,586✔
2584

2585
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
12,586✔
2586
   n->kind    = VCODE_TYPE_ACCESS;
12,586✔
2587
   n->pointed = to;
12,586✔
2588

2589
   return vtype_new(n);
12,586✔
2590
}
2591

2592
vcode_type_t vtype_signal(vcode_type_t base)
50,977✔
2593
{
2594
   assert(active_unit != NULL);
50,977✔
2595

2596
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
50,977✔
2597
   n->kind = VCODE_TYPE_SIGNAL;
50,977✔
2598
   n->base = base;
50,977✔
2599

2600
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
50,977✔
2601

2602
   return vtype_new(n);
50,977✔
2603
}
2604

2605
vcode_type_t vtype_resolution(vcode_type_t base)
9,891✔
2606
{
2607
   assert(active_unit != NULL);
9,891✔
2608

2609
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
9,891✔
2610
   n->kind = VCODE_TYPE_RESOLUTION;
9,891✔
2611
   n->base = base;
9,891✔
2612

2613
   return vtype_new(n);
9,891✔
2614
}
2615

2616
vcode_type_t vtype_closure(vcode_type_t result)
6,290✔
2617
{
2618
   assert(active_unit != NULL);
6,290✔
2619

2620
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
6,290✔
2621
   n->kind = VCODE_TYPE_CLOSURE;
6,290✔
2622
   n->base = result;
6,290✔
2623

2624
   return vtype_new(n);
6,290✔
2625
}
2626

2627
vcode_type_t vtype_context(ident_t name)
90,093✔
2628
{
2629
   assert(active_unit != NULL);
90,093✔
2630
   assert(name != NULL);
90,093✔
2631

2632
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
90,093✔
2633
   n->kind = VCODE_TYPE_CONTEXT;
90,093✔
2634
   n->name = name;
90,093✔
2635

2636
   return vtype_new(n);
90,093✔
2637
}
2638

2639
vcode_type_t vtype_file(vcode_type_t base)
2,355✔
2640
{
2641
   assert(active_unit != NULL);
2,355✔
2642

2643
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
2,355✔
2644
   n->kind = VCODE_TYPE_FILE;
2,355✔
2645
   n->base = base;
2,355✔
2646

2647
   return vtype_new(n);
2,355✔
2648
}
2649

2650
vcode_type_t vtype_offset(void)
408,137✔
2651
{
2652
   assert(active_unit != NULL);
408,137✔
2653

2654
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
408,137✔
2655
   n->kind = VCODE_TYPE_OFFSET;
408,137✔
2656
   n->low  = INT64_MIN;
408,137✔
2657
   n->high = INT64_MAX;
408,137✔
2658
   n->repr = VCODE_REPR_I64;
408,137✔
2659

2660
   return vtype_new(n);
408,137✔
2661
}
2662

2663
vcode_type_t vtype_time(void)
22,719✔
2664
{
2665
   return vtype_int(INT64_MIN, INT64_MAX);
22,719✔
2666
}
2667

2668
vcode_type_t vtype_char(void)
9,843✔
2669
{
2670
   return vtype_int(0, 255);
9,843✔
2671
}
2672

2673
vcode_type_t vtype_opaque(void)
4,607✔
2674
{
2675
   assert(active_unit != NULL);
4,607✔
2676

2677
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
4,607✔
2678
   n->kind = VCODE_TYPE_OPAQUE;
4,607✔
2679

2680
   return vtype_new(n);
4,607✔
2681
}
2682

2683
vcode_type_t vtype_debug_locus(void)
206,663✔
2684
{
2685
   assert(active_unit != NULL);
206,663✔
2686

2687
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
206,663✔
2688
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
206,663✔
2689

2690
   return vtype_new(n);
206,663✔
2691
}
2692

2693
vcode_type_t vtype_trigger(void)
524✔
2694
{
2695
   assert(active_unit != NULL);
524✔
2696

2697
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
524✔
2698
   n->kind = VCODE_TYPE_TRIGGER;
524✔
2699

2700
   return vtype_new(n);
524✔
2701
}
2702

2703
vcode_type_t vtype_conversion(void)
536✔
2704
{
2705
   assert(active_unit != NULL);
536✔
2706

2707
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
536✔
2708
   n->kind = VCODE_TYPE_CONVERSION;
536✔
2709

2710
   return vtype_new(n);
536✔
2711
}
2712

2713
vcode_type_t vtype_real(double low, double high)
148,785✔
2714
{
2715
   assert(active_unit != NULL);
148,785✔
2716

2717
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
148,785✔
2718
   n->kind  = VCODE_TYPE_REAL;
148,785✔
2719
   n->rlow  = low;
148,785✔
2720
   n->rhigh = high;
148,785✔
2721

2722
   return vtype_new(n);
148,785✔
2723
}
2724

2725
vtype_kind_t vtype_kind(vcode_type_t type)
6,526,819✔
2726
{
2727
   vtype_t *vt = vcode_type_data(type);
6,526,819✔
2728
   return vt->kind;
6,526,819✔
2729
}
2730

2731
vtype_repr_t vtype_repr(vcode_type_t type)
73,046✔
2732
{
2733
   vtype_t *vt = vcode_type_data(type);
73,046✔
2734
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
73,046✔
2735
   return vt->repr;
73,046✔
2736
}
2737

2738
vcode_type_t vtype_elem(vcode_type_t type)
202,127✔
2739
{
2740
   vtype_t *vt = vcode_type_data(type);
202,127✔
2741
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
202,127✔
2742
   return vt->elem;
202,127✔
2743
}
2744

2745
vcode_type_t vtype_base(vcode_type_t type)
67,928✔
2746
{
2747
   vtype_t *vt = vcode_type_data(type);
67,928✔
2748
   assert(vt->kind == VCODE_TYPE_SIGNAL || vt->kind == VCODE_TYPE_FILE
67,928✔
2749
          || vt->kind == VCODE_TYPE_RESOLUTION
2750
          || vt->kind == VCODE_TYPE_CLOSURE);
2751
   return vt->base;
67,928✔
2752
}
2753

2754
vcode_type_t vtype_bounds(vcode_type_t type)
28,836✔
2755
{
2756
   vtype_t *vt = vcode_type_data(type);
28,836✔
2757
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
28,836✔
2758
   return vt->bounds;
28,836✔
2759
}
2760

2761
unsigned vtype_dims(vcode_type_t type)
58,280✔
2762
{
2763
   vtype_t *vt = vcode_type_data(type);
58,280✔
2764
   assert(vt->kind == VCODE_TYPE_UARRAY);
58,280✔
2765
   return vt->dims;
58,280✔
2766
}
2767

2768
unsigned vtype_size(vcode_type_t type)
64,541✔
2769
{
2770
   vtype_t *vt = vcode_type_data(type);
64,541✔
2771
   assert(vt->kind == VCODE_TYPE_CARRAY);
64,541✔
2772
   return vt->size;
64,541✔
2773
}
2774

2775
int vtype_fields(vcode_type_t type)
10,329✔
2776
{
2777
   vtype_t *vt = vcode_type_data(type);
10,329✔
2778
   assert(vt->kind == VCODE_TYPE_RECORD);
10,329✔
2779
   return vt->fields.count;
10,329✔
2780
}
2781

2782
vcode_type_t vtype_field(vcode_type_t type, int field)
40,776✔
2783
{
2784
   vtype_t *vt = vcode_type_data(type);
40,776✔
2785
   assert(vt->kind == VCODE_TYPE_RECORD);
40,776✔
2786
   return vcode_type_array_nth(&(vt->fields), field);
40,776✔
2787
}
2788

2789
ident_t vtype_name(vcode_type_t type)
34,593✔
2790
{
2791
   vtype_t *vt = vcode_type_data(type);
34,593✔
2792
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
34,593✔
2793
   return vt->name;
34,593✔
2794
}
2795

2796
vcode_type_t vtype_pointed(vcode_type_t type)
468,665✔
2797
{
2798
   vtype_t *vt = vcode_type_data(type);
468,665✔
2799
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
468,665✔
2800
   return vt->pointed;
468,665✔
2801
}
2802

2803
int64_t vtype_low(vcode_type_t type)
318,758✔
2804
{
2805
   vtype_t *vt = vcode_type_data(type);
318,758✔
2806
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
318,758✔
2807
   return vt->low;
318,758✔
2808
}
2809

2810
int64_t vtype_high(vcode_type_t type)
315,029✔
2811
{
2812
   vtype_t *vt = vcode_type_data(type);
315,029✔
2813
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
315,029✔
2814
   return vt->high;
315,029✔
2815
}
2816

2817
static bool vtype_is_pointer(vcode_type_t type, vtype_kind_t to)
2,009✔
2818
{
2819
   return vtype_kind(type) == VCODE_TYPE_POINTER
2,009✔
2820
      && vtype_kind(vtype_pointed(type)) == to;
2,009✔
2821
}
2822

2823
bool vtype_is_scalar(vcode_type_t type)
571,859✔
2824
{
2825
   const vtype_kind_t kind = vtype_kind(type);
571,859✔
2826
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
571,859✔
2827
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
232,180✔
2828
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2829
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2830
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER
2831
      || kind == VCODE_TYPE_RESOLUTION;
571,859✔
2832
}
2833

2834
bool vtype_is_composite(vcode_type_t type)
38,982✔
2835
{
2836
   const vtype_kind_t kind = vtype_kind(type);
38,982✔
2837
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
38,982✔
2838
}
2839

2840
bool vtype_is_signal(vcode_type_t type)
218,312✔
2841
{
2842
   vtype_t *vt = vcode_type_data(type);
385,201✔
2843
   switch (vt->kind) {
385,201✔
2844
   case VCODE_TYPE_SIGNAL:
2845
      return true;
2846
   case VCODE_TYPE_POINTER:
98,677✔
2847
      return vtype_is_signal(vt->pointed);
98,677✔
2848
   case VCODE_TYPE_RECORD:
2849
      for (int i = 0; i < vt->fields.count; i++) {
45,616✔
2850
         if (vtype_is_signal(vt->fields.items[i]))
36,109✔
2851
            return true;
2852
      }
2853
      return false;
2854
   case VCODE_TYPE_UARRAY:
68,212✔
2855
   case VCODE_TYPE_CARRAY:
2856
      return vtype_is_signal(vt->elem);
68,212✔
2857
   default:
170,643✔
2858
      return false;
170,643✔
2859
   }
2860
}
2861

UNCOV
2862
int vtype_repr_bits(vtype_repr_t repr)
×
2863
{
UNCOV
2864
   switch (repr) {
×
2865
   case VCODE_REPR_U1: return 1;
2866
   case VCODE_REPR_U8: case VCODE_REPR_I8: return 8;
2867
   case VCODE_REPR_U16: case VCODE_REPR_I16: return 16;
2868
   case VCODE_REPR_U32: case VCODE_REPR_I32: return 32;
2869
   case VCODE_REPR_U64: case VCODE_REPR_I64: return 64;
2870
   default: return -1;
2871
   }
2872
}
2873

UNCOV
2874
bool vtype_repr_signed(vtype_repr_t repr)
×
2875
{
UNCOV
2876
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
×
2877
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
×
2878
}
2879

2880
static int64_t vtype_repr_low(vtype_repr_t repr)
15,650✔
2881
{
2882
   switch (repr) {
15,650✔
2883
   case VCODE_REPR_U1:
2884
   case VCODE_REPR_U8:
2885
   case VCODE_REPR_U16:
2886
   case VCODE_REPR_U32:
2887
   case VCODE_REPR_U64: return 0;
2888
   case VCODE_REPR_I8:  return INT8_MIN;
2889
   case VCODE_REPR_I16: return INT16_MIN;
2890
   case VCODE_REPR_I32: return INT32_MIN;
2891
   case VCODE_REPR_I64: return INT64_MIN;
2892
   default:             return 0;
2893
   }
2894
}
2895

2896
static uint64_t vtype_repr_high(vtype_repr_t repr)
15,650✔
2897
{
2898
   switch (repr) {
15,650✔
2899
   case VCODE_REPR_U1:  return 1;
2900
   case VCODE_REPR_U8:  return UINT8_MAX;
2901
   case VCODE_REPR_U16: return UINT16_MAX;
2902
   case VCODE_REPR_U32: return UINT32_MAX;
2903
   case VCODE_REPR_U64: return UINT64_MAX;
2904
   case VCODE_REPR_I8:  return INT8_MAX;
2905
   case VCODE_REPR_I16: return INT16_MAX;
2906
   case VCODE_REPR_I32: return INT32_MAX;
2907
   case VCODE_REPR_I64: return INT64_MAX;
2908
   default:             return 0;
2909
   }
2910
}
2911

2912
static bool vtype_clamp_to_repr(vtype_repr_t repr, int64_t *low, int64_t *high)
15,650✔
2913
{
2914
   int64_t clamp_low = vtype_repr_low(repr);
15,650✔
2915
   uint64_t clamp_high = vtype_repr_high(repr);
15,650✔
2916

2917
   if (*low >= clamp_low && *high <= clamp_high)
15,650✔
2918
      return true;
2919
   else {
2920
      *low = MAX(clamp_low, *low);
7,769✔
2921
      *high = MIN(clamp_high, *high);
7,769✔
2922
      return false;
7,769✔
2923
   }
2924
}
2925

2926
int vcode_count_params(void)
19,946✔
2927
{
2928
   assert(active_unit != NULL);
19,946✔
2929
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
19,946✔
2930
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2931
          || active_unit->kind == VCODE_UNIT_PROPERTY
2932
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2933

2934
   return active_unit->params.count;
19,946✔
2935
}
2936

2937
vcode_type_t vcode_param_type(int param)
49,820✔
2938
{
2939
   assert(active_unit != NULL);
49,820✔
2940
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
49,820✔
2941
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2942
          || active_unit->kind == VCODE_UNIT_PROPERTY
2943
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2944
   assert(param < active_unit->params.count);
49,820✔
2945

2946
   return active_unit->params.items[param].type;
49,820✔
2947
}
2948

2949
ident_t vcode_param_name(int param)
49,820✔
2950
{
2951
   assert(active_unit != NULL);
49,820✔
2952
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
49,820✔
2953
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2954
          || active_unit->kind == VCODE_UNIT_PROPERTY
2955
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2956
   assert(param < active_unit->params.count);
49,820✔
2957

2958
   return active_unit->params.items[param].name;
49,820✔
2959
}
2960

2961
vcode_reg_t vcode_param_reg(int param)
49,820✔
2962
{
2963
   assert(active_unit != NULL);
49,820✔
2964
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
49,820✔
2965
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2966
          || active_unit->kind == VCODE_UNIT_PROPERTY
2967
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2968
   assert(param < active_unit->params.count);
49,820✔
2969

2970
   return active_unit->params.items[param].reg;
49,820✔
2971
}
2972

2973
vcode_block_t emit_block(void)
196,839✔
2974
{
2975
   assert(active_unit != NULL);
196,839✔
2976

2977
   vcode_block_t bnum = active_unit->blocks.count;
196,839✔
2978

2979
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
196,839✔
2980
   memset(bptr, '\0', sizeof(block_t));
196,839✔
2981

2982
   if (active_block != VCODE_INVALID_BLOCK)
196,839✔
2983
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
125,934✔
2984
   else
2985
      bptr->last_loc = LOC_INVALID;
70,905✔
2986

2987
   return bnum;
196,839✔
2988
}
2989

2990
void vcode_select_unit(vcode_unit_t unit)
247,263✔
2991
{
2992
   active_unit  = unit;
247,263✔
2993
   active_block = VCODE_INVALID_BLOCK;
247,263✔
2994
}
247,263✔
2995

2996
void vcode_select_block(vcode_block_t block)
458,571✔
2997
{
2998
   assert(active_unit != NULL);
458,571✔
2999
   active_block = block;
458,571✔
3000
}
458,571✔
3001

3002
vcode_block_t vcode_active_block(void)
899✔
3003
{
3004
   assert(active_unit != NULL);
899✔
3005
   assert(active_block != -1);
899✔
3006
   return active_block;
899✔
3007
}
3008

3009
const loc_t *vcode_last_loc(void)
1,500,841✔
3010
{
3011
   return &(vcode_block_data()->last_loc);
1,500,841✔
3012
}
3013

3014
vcode_unit_t vcode_active_unit(void)
1,095✔
3015
{
3016
   assert(active_unit != NULL);
1,095✔
3017
   return active_unit;
1,095✔
3018
}
3019

3020
ident_t vcode_unit_name(vcode_unit_t vu)
207,204✔
3021
{
3022
   assert(vu != NULL);
207,204✔
3023
   return vu->name;
207,204✔
3024
}
3025

3026
bool vcode_unit_has_undefined(vcode_unit_t vu)
15,421✔
3027
{
3028
   assert(vu != NULL);
15,421✔
3029
   return !!(vu->flags & UNIT_UNDEFINED);
15,421✔
3030
}
3031

UNCOV
3032
int vcode_unit_depth(vcode_unit_t vu)
×
3033
{
UNCOV
3034
   assert(vu != NULL);
×
3035
   return vu->depth;
×
3036
}
3037

3038
void vcode_set_result(vcode_type_t type)
31,559✔
3039
{
3040
   assert(active_unit != NULL);
31,559✔
3041
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
31,559✔
3042
          || active_unit->kind == VCODE_UNIT_THUNK);
3043

3044
   active_unit->result = type;
31,559✔
3045
}
31,559✔
3046

3047
vcode_type_t vcode_unit_result(vcode_unit_t vu)
33,712✔
3048
{
3049
   assert(vu != NULL);
33,712✔
3050
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
33,712✔
3051
   return vu->result;
33,712✔
3052
}
3053

3054
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
195,502✔
3055
{
3056
   assert(vu != NULL);
195,502✔
3057
   return vu->kind;
195,502✔
3058
}
3059

3060
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
148,782✔
3061
{
3062
   assert(vu != NULL);
148,782✔
3063
   return vu->context;
148,782✔
3064
}
3065

3066
object_t *vcode_unit_object(vcode_unit_t vu)
121,674✔
3067
{
3068
   assert(vu != NULL);
121,674✔
3069
   return vu->object;
121,674✔
3070
}
3071

3072
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
86,342✔
3073
{
3074
   int hops = 0;
86,342✔
3075
   for (; (unit = unit->context); hops++)
235,468✔
3076
      ;
3077
   return hops;
86,342✔
3078
}
3079

3080
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
41,511✔
3081
{
3082
   assert(context->kind != VCODE_UNIT_THUNK);
41,511✔
3083

3084
   child->next = NULL;
41,511✔
3085
   if (context->children == NULL)
41,511✔
3086
      context->children = child;
18,688✔
3087
   else {
3088
      vcode_unit_t it;
3089
      for (it = context->children; it->next != NULL; it = it->next)
121,074✔
3090
         ;
3091
      it->next = child;
22,823✔
3092
   }
3093
}
41,511✔
3094

3095
vcode_unit_t emit_function(ident_t name, object_t *obj, vcode_unit_t context)
18,671✔
3096
{
3097
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
18,671✔
3098
   vu->kind     = VCODE_UNIT_FUNCTION;
18,671✔
3099
   vu->name     = name;
18,671✔
3100
   vu->context  = context;
18,671✔
3101
   vu->result   = VCODE_INVALID_TYPE;
18,671✔
3102
   vu->depth    = vcode_unit_calc_depth(vu);
18,671✔
3103
   vu->object   = obj;
18,671✔
3104

3105
   vcode_add_child(context, vu);
18,671✔
3106

3107
   vcode_select_unit(vu);
18,671✔
3108
   vcode_select_block(emit_block());
18,671✔
3109
   emit_debug_info(&(obj->loc));
18,671✔
3110

3111
   return vu;
18,671✔
3112
}
3113

3114
vcode_unit_t emit_procedure(ident_t name, object_t *obj, vcode_unit_t context)
274✔
3115
{
3116
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
274✔
3117
   vu->kind     = VCODE_UNIT_PROCEDURE;
274✔
3118
   vu->name     = name;
274✔
3119
   vu->context  = context;
274✔
3120
   vu->result   = VCODE_INVALID_TYPE;
274✔
3121
   vu->depth    = vcode_unit_calc_depth(vu);
274✔
3122
   vu->object   = obj;
274✔
3123

3124
   vcode_add_child(context, vu);
274✔
3125

3126
   vcode_select_unit(vu);
274✔
3127
   vcode_select_block(emit_block());
274✔
3128
   emit_debug_info(&(obj->loc));
274✔
3129

3130
   return vu;
274✔
3131
}
3132

3133
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
12,114✔
3134
{
3135
   assert(context->kind == VCODE_UNIT_INSTANCE);
12,114✔
3136

3137
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
12,114✔
3138
   vu->kind     = VCODE_UNIT_PROCESS;
12,114✔
3139
   vu->name     = name;
12,114✔
3140
   vu->context  = context;
12,114✔
3141
   vu->depth    = vcode_unit_calc_depth(vu);
12,114✔
3142
   vu->result   = VCODE_INVALID_TYPE;
12,114✔
3143
   vu->object   = obj;
12,114✔
3144

3145
   vcode_add_child(context, vu);
12,114✔
3146

3147
   vcode_select_unit(vu);
12,114✔
3148
   vcode_select_block(emit_block());
12,114✔
3149
   emit_debug_info(&(obj->loc));
12,114✔
3150

3151
   return vu;
12,114✔
3152
}
3153

3154
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
12,730✔
3155
{
3156
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
12,730✔
3157

3158
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
12,730✔
3159
   vu->kind     = VCODE_UNIT_INSTANCE;
12,730✔
3160
   vu->name     = name;
12,730✔
3161
   vu->context  = context;
12,730✔
3162
   vu->depth    = vcode_unit_calc_depth(vu);
12,730✔
3163
   vu->result   = VCODE_INVALID_TYPE;
12,730✔
3164
   vu->object   = obj;
12,730✔
3165

3166
   if (context != NULL)
12,730✔
3167
      vcode_add_child(context, vu);
7,998✔
3168

3169
   vcode_select_unit(vu);
12,730✔
3170
   vcode_select_block(emit_block());
12,730✔
3171
   emit_debug_info(&(obj->loc));
12,730✔
3172

3173
   return vu;
12,730✔
3174
}
3175

3176
vcode_unit_t emit_package(ident_t name, object_t *obj, vcode_unit_t context)
10,678✔
3177
{
3178
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
10,678✔
3179
   vu->kind     = VCODE_UNIT_PACKAGE;
10,678✔
3180
   vu->name     = name;
10,678✔
3181
   vu->context  = context;
10,678✔
3182
   vu->depth    = vcode_unit_calc_depth(vu);
10,678✔
3183
   vu->result   = VCODE_INVALID_TYPE;
10,678✔
3184
   vu->object   = obj;
10,678✔
3185

3186
   if (context != NULL)
10,678✔
3187
      vcode_add_child(context, vu);
242✔
3188

3189
   vcode_select_unit(vu);
10,678✔
3190
   vcode_select_block(emit_block());
10,678✔
3191
   emit_debug_info(&(obj->loc));
10,678✔
3192

3193
   return vu;
10,678✔
3194
}
3195

3196
vcode_unit_t emit_protected(ident_t name, object_t *obj, vcode_unit_t context)
705✔
3197
{
3198
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
705✔
3199
   vu->kind     = VCODE_UNIT_PROTECTED;
705✔
3200
   vu->name     = name;
705✔
3201
   vu->context  = context;
705✔
3202
   vu->depth    = vcode_unit_calc_depth(vu);
705✔
3203
   vu->result   = VCODE_INVALID_TYPE;
705✔
3204
   vu->object   = obj;
705✔
3205

3206
   if (context != NULL)
705✔
3207
      vcode_add_child(context, vu);
705✔
3208

3209
   vcode_select_unit(vu);
705✔
3210
   vcode_select_block(emit_block());
705✔
3211
   emit_debug_info(&(obj->loc));
705✔
3212

3213
   return vu;
705✔
3214
}
3215

3216
vcode_unit_t emit_property(ident_t name, object_t *obj, vcode_unit_t context)
296✔
3217
{
3218
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
296✔
3219
   vu->kind     = VCODE_UNIT_PROPERTY;
296✔
3220
   vu->name     = name;
296✔
3221
   vu->context  = context;
296✔
3222
   vu->depth    = vcode_unit_calc_depth(vu);
296✔
3223
   vu->result   = VCODE_INVALID_TYPE;
296✔
3224
   vu->object   = obj;
296✔
3225

3226
   if (context != NULL)
296✔
3227
      vcode_add_child(context, vu);
296✔
3228

3229
   vcode_select_unit(vu);
296✔
3230
   vcode_select_block(emit_block());
296✔
3231
   emit_debug_info(&(obj->loc));
296✔
3232

3233
   return vu;
296✔
3234
}
3235

3236
vcode_unit_t emit_thunk(ident_t name, object_t *obj, vcode_unit_t context)
15,437✔
3237
{
3238
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
15,437✔
3239
   vu->kind     = VCODE_UNIT_THUNK;
15,437✔
3240
   vu->name     = name;
15,437✔
3241
   vu->context  = context;
15,437✔
3242
   vu->depth    = vcode_unit_calc_depth(vu);
15,437✔
3243
   vu->result   = VCODE_INVALID_TYPE;
15,437✔
3244
   vu->depth    = vcode_unit_calc_depth(vu);
15,437✔
3245
   vu->object   = obj;
15,437✔
3246

3247
   if (context != NULL)
15,437✔
3248
      vcode_add_child(context, vu);
1,211✔
3249

3250
   vcode_select_unit(vu);
15,437✔
3251
   vcode_select_block(emit_block());
15,437✔
3252

3253
   return vu;
15,437✔
3254
}
3255

3256
void emit_assert(vcode_reg_t value, vcode_reg_t message, vcode_reg_t length,
18,748✔
3257
                 vcode_reg_t severity, vcode_reg_t locus, vcode_reg_t hint_left,
3258
                 vcode_reg_t hint_right)
3259
{
3260
   int64_t value_const;
18,748✔
3261
   if (vcode_reg_const(value, &value_const) && value_const != 0) {
18,748✔
3262
      emit_comment("Always true assertion on r%d", value);
40✔
3263
      return;
40✔
3264
   }
3265

3266
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
18,708✔
3267
   vcode_add_arg(op, value);
18,708✔
3268
   vcode_add_arg(op, severity);
18,708✔
3269
   vcode_add_arg(op, message);
18,708✔
3270
   vcode_add_arg(op, length);
18,708✔
3271
   vcode_add_arg(op, locus);
18,708✔
3272

3273
   if (hint_left != VCODE_INVALID_REG) {
18,708✔
3274
      vcode_add_arg(op, hint_left);
7,914✔
3275
      vcode_add_arg(op, hint_right);
7,914✔
3276

3277
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
7,914✔
3278
                   "left hint must be scalar");
3279
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
7,914✔
3280
                   "right hint must be scalar");
3281
   }
3282

3283
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
18,708✔
3284
                "value parameter to assert is not bool");
3285
   VCODE_ASSERT(message == VCODE_INVALID_REG
18,708✔
3286
                || vcode_reg_kind(message) == VCODE_TYPE_POINTER,
3287
                "message parameter to assert is not a pointer");
3288
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
18,708✔
3289
                "value parameter to assert is not bool");
3290
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
18,708✔
3291
                "locus argument to report must be a debug locus");
3292
}
3293

3294
void emit_report(vcode_reg_t message, vcode_reg_t length, vcode_reg_t severity,
2,659✔
3295
                 vcode_reg_t locus)
3296
{
3297
   op_t *op = vcode_add_op(VCODE_OP_REPORT);
2,659✔
3298
   vcode_add_arg(op, severity);
2,659✔
3299
   vcode_add_arg(op, message);
2,659✔
3300
   vcode_add_arg(op, length);
2,659✔
3301
   vcode_add_arg(op, locus);
2,659✔
3302

3303
   VCODE_ASSERT(vcode_reg_kind(message) == VCODE_TYPE_POINTER,
2,659✔
3304
                "message parameter to report is not a pointer");
3305
   VCODE_ASSERT(vtype_eq(vtype_pointed(vcode_reg_type(message)), vtype_char()),
2,659✔
3306
                "message parameter to report is not a character pointer");
3307
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,659✔
3308
                "locus argument to report must be a debug locus");
3309
}
2,659✔
3310

3311
vcode_reg_t emit_cmp(vcode_cmp_t cmp, vcode_reg_t lhs, vcode_reg_t rhs)
54,704✔
3312
{
3313
   if (lhs == rhs) {
54,704✔
3314
      if (cmp == VCODE_CMP_EQ)
1,249✔
3315
         return emit_const(vtype_bool(), 1);
1,233✔
3316
      else if (cmp == VCODE_CMP_NEQ)
16✔
UNCOV
3317
         return emit_const(vtype_bool(), 0);
×
3318
      else if (cmp == VCODE_CMP_LEQ || cmp == VCODE_CMP_GEQ)
16✔
UNCOV
3319
         return emit_const(vtype_bool(), 1);
×
3320
      else if (cmp == VCODE_CMP_LT || cmp == VCODE_CMP_GT)
16✔
3321
         return emit_const(vtype_bool(), 0);
16✔
3322
   }
3323

3324
   int64_t lconst, rconst;
53,455✔
3325
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)) {
53,455✔
3326
      switch (cmp) {
410✔
3327
      case VCODE_CMP_EQ:
397✔
3328
         return emit_const(vtype_bool(), lconst == rconst);
397✔
3329
      case VCODE_CMP_NEQ:
4✔
3330
         return emit_const(vtype_bool(), lconst != rconst);
4✔
3331
      case VCODE_CMP_LT:
4✔
3332
         return emit_const(vtype_bool(), lconst < rconst);
4✔
3333
      case VCODE_CMP_GT:
5✔
3334
         return emit_const(vtype_bool(), lconst > rconst);
5✔
UNCOV
3335
      case VCODE_CMP_LEQ:
×
UNCOV
3336
         return emit_const(vtype_bool(), lconst <= rconst);
×
UNCOV
3337
      case VCODE_CMP_GEQ:
×
UNCOV
3338
         return emit_const(vtype_bool(), lconst >= rconst);
×
UNCOV
3339
      default:
×
3340
         fatal_trace("cannot fold comparison %d", cmp);
3341
      }
3342
   }
3343

3344
   // Reuse any previous operation in this block with the same arguments
3345
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
926,028✔
3346
      if (other->args.count == 2 && other->args.items[0] == lhs
33,368✔
3347
          && other->args.items[1] == rhs && other->cmp == cmp)
2,732✔
3348
         return other->result;
257✔
3349
   }
3350

3351
   op_t *op = vcode_add_op(VCODE_OP_CMP);
52,788✔
3352
   vcode_add_arg(op, lhs);
52,788✔
3353
   vcode_add_arg(op, rhs);
52,788✔
3354
   op->cmp    = cmp;
52,788✔
3355
   op->result = vcode_add_reg(vtype_bool());
52,788✔
3356

3357
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
52,788✔
3358
                "arguments to cmp are not the same type");
3359

3360
   return op->result;
3361
}
3362

3363
vcode_reg_t emit_fcall(ident_t func, vcode_type_t type, vcode_type_t bounds,
45,750✔
3364
                       const vcode_reg_t *args, int nargs)
3365
{
3366
   op_t *o = vcode_add_op(VCODE_OP_FCALL);
45,750✔
3367
   o->func = func;
45,750✔
3368
   o->type = type;
45,750✔
3369
   for (int i = 0; i < nargs; i++)
173,218✔
3370
      vcode_add_arg(o, args[i]);
127,468✔
3371

3372
   for (int i = 0; i < nargs; i++)
173,218✔
3373
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
127,468✔
3374
                   "invalid argument to function");
3375

3376
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
45,750✔
3377
                "first argument to VHDL function must be context pointer");
3378

3379
   if (type == VCODE_INVALID_TYPE)
45,750✔
3380
      return (o->result = VCODE_INVALID_REG);
6,709✔
3381
   else {
3382
      o->result = vcode_add_reg(type);
39,041✔
3383

3384
      reg_t *rr = vcode_reg_data(o->result);
39,041✔
3385
      rr->bounds = bounds;
39,041✔
3386

3387
      return o->result;
39,041✔
3388
   }
3389
}
3390

3391
void emit_pcall(ident_t func, const vcode_reg_t *args, int nargs,
1,089✔
3392
                vcode_block_t resume_bb)
3393
{
3394
   op_t *o = vcode_add_op(VCODE_OP_PCALL);
1,089✔
3395
   o->func = func;
1,089✔
3396
   for (int i = 0; i < nargs; i++)
3,694✔
3397
      vcode_add_arg(o, args[i]);
2,605✔
3398

3399
   vcode_block_array_add(&(o->targets), resume_bb);
1,089✔
3400

3401
   for (int i = 0; i < nargs; i++)
3,694✔
3402
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
2,605✔
3403
                   "invalid argument to procedure");
3404

3405
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
1,089✔
3406
                "first argument to VHDL procedure must be context pointer");
3407
}
1,089✔
3408

UNCOV
3409
vcode_reg_t emit_syscall(ident_t func, vcode_type_t type, vcode_type_t bounds,
×
3410
                         vcode_reg_t locus, const vcode_reg_t *args, int nargs)
3411
{
UNCOV
3412
   op_t *o = vcode_add_op(VCODE_OP_SYSCALL);
×
UNCOV
3413
   o->func = func;
×
UNCOV
3414
   o->type = type;
×
UNCOV
3415
   vcode_add_arg(o, locus);
×
UNCOV
3416
   for (int i = 0; i < nargs; i++)
×
UNCOV
3417
      vcode_add_arg(o, args[i]);
×
3418

UNCOV
3419
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
×
3420
                "locus argument to syscall must be a debug locus");
3421

UNCOV
3422
   for (int i = 0; i < nargs; i++)
×
UNCOV
3423
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG, "invalid argument to syscall");
×
3424

UNCOV
3425
   if (type == VCODE_INVALID_TYPE)
×
UNCOV
3426
      return (o->result = VCODE_INVALID_REG);
×
3427
   else {
UNCOV
3428
      o->result = vcode_add_reg(type);
×
3429

UNCOV
3430
      reg_t *rr = vcode_reg_data(o->result);
×
UNCOV
3431
      rr->bounds = bounds;
×
3432

3433
      return o->result;
×
3434
   }
3435
}
3436

3437
vcode_reg_t emit_alloc(vcode_type_t type, vcode_type_t bounds,
9,218✔
3438
                       vcode_reg_t count)
3439
{
3440
   op_t *op = vcode_add_op(VCODE_OP_ALLOC);
9,218✔
3441
   op->type    = type;
9,218✔
3442
   op->result  = vcode_add_reg(vtype_pointer(type));
9,218✔
3443
   vcode_add_arg(op, count);
9,218✔
3444

3445
   const vtype_kind_t tkind = vtype_kind(type);
9,218✔
3446
   VCODE_ASSERT(tkind != VCODE_TYPE_CARRAY && tkind != VCODE_TYPE_UARRAY,
9,218✔
3447
                "alloca element type cannot be array");
3448
   VCODE_ASSERT(count != VCODE_INVALID_REG,
9,218✔
3449
                "alloca must have valid count argument");
3450

3451
   reg_t *r = vcode_reg_data(op->result);
9,218✔
3452
   r->bounds = bounds;
9,218✔
3453

3454
   return op->result;
9,218✔
3455
}
3456

3457
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
1,869,644✔
3458
{
3459
   // Reuse any previous constant in this block with the same type and value
3460
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
41,748,987✔
3461
      if (other->value == value && vtype_eq(type, other->type))
14,917,642✔
3462
         return other->result;
1,265,030✔
3463
   }
3464

3465
   op_t *op = vcode_add_op(VCODE_OP_CONST);
604,614✔
3466
   op->value  = value;
604,614✔
3467
   op->type   = type;
604,614✔
3468
   op->result = vcode_add_reg(type);
604,614✔
3469

3470
   vtype_kind_t type_kind = vtype_kind(type);
604,614✔
3471
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
604,614✔
3472
                "constant must have integer or offset type");
3473

3474
   reg_t *r = vcode_reg_data(op->result);
604,614✔
3475
   r->bounds = vtype_int(value, value);
604,614✔
3476

3477
   return op->result;
604,614✔
3478
}
3479

3480
vcode_reg_t emit_const_real(vcode_type_t type, double value)
91,024✔
3481
{
3482
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REAL) {
2,640,868✔
3483
      if (other->real == value && other->type == type)
1,254,924✔
3484
         return other->result;
36,378✔
3485
   }
3486

3487
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
54,646✔
3488
   op->real   = value;
54,646✔
3489
   op->type   = type;
54,646✔
3490
   op->result = vcode_add_reg(op->type);
54,646✔
3491

3492
   reg_t *r = vcode_reg_data(op->result);
54,646✔
3493
   r->bounds = vtype_real(value, value);
54,646✔
3494

3495
   return op->result;
54,646✔
3496
}
3497

3498
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
45,584✔
3499
{
3500
   vtype_kind_t kind = vtype_kind(type);
45,584✔
3501

3502
   // Reuse any previous operation in this block with the same arguments
3503
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
2,403,793✔
3504
      if (other->args.count != num)
189,027✔
3505
         continue;
111,976✔
3506
      else if (!vtype_eq(vcode_reg_type(other->result), type))
77,051✔
3507
         continue;
2,894✔
3508

3509
      bool match = true;
3510
      for (int i = 0; match && i < num; i++) {
560,341✔
3511
         if (other->args.items[i] != values[i])
486,184✔
3512
            match = false;
65,543✔
3513
      }
3514

3515
      if (match) return other->result;
74,157✔
3516
   }
3517

3518
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
36,970✔
3519
   op->result = vcode_add_reg(type);
36,970✔
3520

3521
   for (int i = 0; i < num; i++)
2,133,661✔
3522
      vcode_add_arg(op, values[i]);
2,096,691✔
3523

3524
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
36,970✔
3525
                "constant array must have constrained array type");
3526
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
36,970✔
3527
                vtype_size(type), num);
3528

3529
#ifdef DEBUG
3530
   vcode_type_t elem = vtype_elem(type);
36,970✔
3531
   for (int i = 0; i < num; i++) {
2,133,661✔
3532
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
2,096,691✔
3533
                   "wrong element type for item %d", i);
3534
      vcode_assert_const(values[i], "array");
2,096,691✔
3535
   }
3536
#endif
3537

3538
   reg_t *r = vcode_reg_data(op->result);
36,970✔
3539
   r->bounds = vtype_elem(type);
36,970✔
3540

3541
   return op->result;
36,970✔
3542
}
3543

3544
vcode_reg_t emit_const_rep(vcode_type_t type, vcode_reg_t value, int rep)
735✔
3545
{
3546
   // Reuse any previous operation in this block with the same arguments
3547
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REP) {
11,519✔
3548
      if (other->args.items[0] == value && other->value == rep)
1,057✔
3549
         return other->result;
312✔
3550
   }
3551

3552
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
423✔
3553
   op->value = rep;
423✔
3554
   vcode_add_arg(op, value);
423✔
3555

3556
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
423✔
3557
                "constant array must have constrained array type");
3558
   VCODE_ASSERT(rep >= 0, "repeat count must be non-negative");
423✔
3559

3560
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
423✔
3561

3562
   op->result = vcode_add_reg(type);
423✔
3563

3564
   reg_t *r = vcode_reg_data(op->result);
423✔
3565
   r->bounds = vtype_bounds(type);
423✔
3566

3567
   return op->result;
423✔
3568
}
3569

3570
vcode_reg_t emit_const_record(vcode_type_t type, vcode_reg_t *values, int num)
3,294✔
3571
{
3572
   // Reuse any previous constant in this block with the same type and value
3573
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_RECORD) {
51,969✔
3574
      if (other->args.count == num && vtype_eq(type, other->type)) {
2,091✔
3575
         bool same_regs = true;
3576
         for (int i = 0; same_regs && i < num; i++)
3,333✔
3577
            same_regs = other->args.items[i] == values[i];
1,946✔
3578

3579
         if (same_regs)
1,387✔
3580
            return other->result;
252✔
3581
      }
3582
   }
3583

3584
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
3,042✔
3585
   op->type   = type;
3,042✔
3586
   op->result = vcode_add_reg(type);
3,042✔
3587

3588
   for (int i = 0; i < num; i++)
10,937✔
3589
      vcode_add_arg(op, values[i]);
7,895✔
3590

3591
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
3,042✔
3592
                "constant record must have record type");
3593

3594
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
3,042✔
3595
                vtype_fields(type), num);
3596

3597
#ifdef DEBUG
3598
   for (int i = 0; i < num; i++) {
10,937✔
3599
      VCODE_ASSERT(vtype_eq(vtype_field(type, i), vcode_reg_type(values[i])),
7,895✔
3600
                   "wrong type for field %d", i);
3601
      vcode_assert_const(values[i], "record");
7,895✔
3602
   }
3603
#endif
3604

3605
   return op->result;
3,042✔
3606
}
3607

3608
vcode_reg_t emit_address_of(vcode_reg_t value)
47,602✔
3609
{
3610
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
2,492,605✔
3611
      if (other->args.items[0] == value)
190,393✔
3612
         return other->result;
8,620✔
3613
   }
3614

3615
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
38,982✔
3616
   vcode_add_arg(op, value);
38,982✔
3617

3618
   vcode_type_t type = vcode_reg_type(value);
38,982✔
3619
   VCODE_ASSERT(vtype_is_composite(type),
38,982✔
3620
                "address of argument must be record or array");
3621

3622
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
38,982✔
3623
      vcode_type_t elem = vtype_elem(type);
36,661✔
3624
      op->result = vcode_add_reg(vtype_pointer(elem));
36,661✔
3625

3626
      reg_t *rr = vcode_reg_data(op->result);
36,661✔
3627
      rr->bounds = elem;
36,661✔
3628

3629
      return op->result;
36,661✔
3630
   }
3631
   else
3632
      return (op->result = vcode_add_reg(vtype_pointer(type)));
2,321✔
3633
}
3634

3635
void emit_wait(vcode_block_t target, vcode_reg_t time)
17,785✔
3636
{
3637
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
17,785✔
3638
   vcode_add_target(op, target);
17,785✔
3639
   vcode_add_arg(op, time);
17,785✔
3640

3641
   VCODE_ASSERT(time == VCODE_INVALID_REG
17,785✔
3642
                || vcode_reg_kind(time) == VCODE_TYPE_INT,
3643
                "wait time must have integer type");
3644
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_PROCEDURE
17,785✔
3645
                || active_unit->kind == VCODE_UNIT_PROCESS,
3646
                "wait only allowed in process or procedure");
3647
}
17,785✔
3648

3649
void emit_jump(vcode_block_t target)
50,237✔
3650
{
3651
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
50,237✔
3652
   vcode_add_target(op, target);
50,237✔
3653

3654
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
50,237✔
3655
}
50,237✔
3656

3657
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
91,960✔
3658
                     vcode_var_flags_t flags)
3659
{
3660
   assert(active_unit != NULL);
91,960✔
3661

3662
   vcode_var_t var = active_unit->vars.count;
91,960✔
3663
   var_t *v = var_array_alloc(&(active_unit->vars));
91,960✔
3664
   memset(v, '\0', sizeof(var_t));
91,960✔
3665
   v->type     = type;
91,960✔
3666
   v->bounds   = bounds;
91,960✔
3667
   v->name     = name;
91,960✔
3668
   v->flags    = flags;
91,960✔
3669

3670
   return var;
91,960✔
3671
}
3672

3673
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
51,031✔
3674
{
3675
   assert(active_unit != NULL);
51,031✔
3676

3677
   param_t *p = param_array_alloc(&(active_unit->params));
51,031✔
3678
   memset(p, '\0', sizeof(param_t));
51,031✔
3679
   p->type   = type;
51,031✔
3680
   p->bounds = bounds;
51,031✔
3681
   p->name   = name;
51,031✔
3682
   p->reg    = vcode_add_reg(type);
51,031✔
3683

3684
   reg_t *rr = vcode_reg_data(p->reg);
51,031✔
3685
   rr->bounds = bounds;
51,031✔
3686

3687
   return p->reg;
51,031✔
3688
}
3689

3690
vcode_reg_t emit_load(vcode_var_t var)
81,057✔
3691
{
3692
   // Try scanning backwards through the block for another load or store to
3693
   // this variable
3694
   enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER;
81,057✔
3695
   vcode_reg_t fold = VCODE_INVALID_REG;
81,057✔
3696
   VCODE_FOR_EACH_OP(other) {
1,149,579✔
3697
      switch (state) {
1,090,179✔
3698
      case EAGER:
438,541✔
3699
         if (other->kind == VCODE_OP_LOAD && other->address == var)
438,541✔
3700
            return other->result;
5,129✔
3701
         else if (other->kind == VCODE_OP_STORE && other->address == var)
433,412✔
3702
            return other->args.items[0];
16,528✔
3703
         else if (other->kind == VCODE_OP_FCALL
416,884✔
3704
                  || other->kind == VCODE_OP_PCALL
416,884✔
3705
                  || other->kind == VCODE_OP_FILE_READ
3706
                  || other->kind == VCODE_OP_FILE_OPEN
3707
                  || other->kind == VCODE_OP_STORE_INDIRECT
3708
                  || other->kind == VCODE_OP_DEALLOCATE)
3709
            state = CONSERVATIVE;   // May write to variable
12,995✔
3710
         break;
3711

3712
      case CONSERVATIVE:
615,095✔
3713
         if (other->kind == VCODE_OP_LOAD && other->address == var
615,095✔
3714
             && fold == VCODE_INVALID_REG)
6,394✔
3715
            fold = other->result;
5,223✔
3716
         else if (other->kind == VCODE_OP_STORE && other->address == var
609,872✔
3717
                  && fold == VCODE_INVALID_REG)
3,202✔
3718
            fold = other->args.items[0];
3,014✔
3719
         else if (other->kind == VCODE_OP_INDEX && other->address == var)
606,858✔
3720
            state = UNSAFE;
3721
         else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0)
605,374✔
3722
            state = UNSAFE;   // Nested call captures variables
135✔
3723
         break;
3724

3725
      case UNSAFE:
3726
         break;
3727
      }
3728
   }
3729

3730
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
59,400✔
3731
      return fold;
3732

3733
   var_t *v = vcode_var_data(var);
51,660✔
3734

3735
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
51,660✔
3736
   op->address = var;
51,660✔
3737
   op->result  = vcode_add_reg(v->type);
51,660✔
3738

3739
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot load non-scalar type");
51,660✔
3740

3741
   reg_t *r = vcode_reg_data(op->result);
51,660✔
3742
   r->bounds = v->bounds;
51,660✔
3743

3744
   return op->result;
51,660✔
3745
}
3746

3747
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
131,131✔
3748
{
3749
   VCODE_FOR_EACH_OP(other) {
1,495,691✔
3750
      if (other->kind == VCODE_OP_LOAD_INDIRECT
1,403,812✔
3751
          && other->args.items[0] == reg) {
210,554✔
3752
         return other->result;
9,710✔
3753
      }
3754
      else if (other->kind == VCODE_OP_FCALL
1,394,102✔
3755
               || other->kind == VCODE_OP_PCALL
1,394,102✔
3756
               || other->kind == VCODE_OP_STORE
3757
               || other->kind == VCODE_OP_STORE_INDIRECT
3758
               || other->kind == VCODE_OP_MEMSET
3759
               || other->kind == VCODE_OP_COPY
3760
               || other->kind == VCODE_OP_FILE_READ)
3761
         break;   // May write to this pointer
3762
   }
3763

3764
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
121,421✔
3765
   vcode_add_arg(op, reg);
121,421✔
3766

3767
   vcode_type_t rtype = vcode_reg_type(reg);
121,421✔
3768

3769
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
121,421✔
3770
                "load indirect with non-pointer argument");
3771

3772
   vcode_type_t deref = vtype_pointed(rtype);
121,421✔
3773
   op->result = vcode_add_reg(deref);
121,421✔
3774

3775
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
121,421✔
3776

3777
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
121,421✔
3778

3779
   return op->result;
121,421✔
3780
}
3781

3782
void emit_store(vcode_reg_t reg, vcode_var_t var)
100,359✔
3783
{
3784
   // Any previous store to this variable in this block is dead
3785
   VCODE_FOR_EACH_OP(other) {
2,108,510✔
3786
      if (other->kind == VCODE_OP_STORE && other->address == var) {
2,026,491✔
3787
         other->kind = VCODE_OP_COMMENT;
374✔
3788
         other->comment =
748✔
3789
            xasprintf("Dead store to %s", istr(vcode_var_name(var)));
374✔
3790
         vcode_reg_array_resize(&(other->args), 0, VCODE_INVALID_REG);
374✔
3791
      }
3792
      else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL)
2,026,117✔
3793
         break;   // Needs to get variable for display
3794
      else if ((other->kind == VCODE_OP_INDEX || other->kind == VCODE_OP_LOAD)
2,018,504✔
3795
               && other->address == var)
47,923✔
3796
         break;   // Previous value may be used
3797
   }
3798

3799
   var_t *v = vcode_var_data(var);
100,359✔
3800
   reg_t *r = vcode_reg_data(reg);
100,359✔
3801

3802
   op_t *op = vcode_add_op(VCODE_OP_STORE);
100,359✔
3803
   vcode_add_arg(op, reg);
100,359✔
3804
   op->address = var;
100,359✔
3805

3806
   VCODE_ASSERT(vtype_eq(v->type, r->type),
100,359✔
3807
                "variable and stored value do not have same type");
3808
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
100,359✔
3809
}
100,359✔
3810

3811
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
19,206✔
3812
{
3813
   reg_t *p = vcode_reg_data(ptr);
19,206✔
3814
   reg_t *r = vcode_reg_data(reg);
19,206✔
3815

3816
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
19,206✔
3817
   vcode_add_arg(op, reg);
19,206✔
3818
   vcode_add_arg(op, ptr);
19,206✔
3819

3820
   VCODE_ASSERT(vtype_kind(p->type) == VCODE_TYPE_POINTER,
19,206✔
3821
                "store indirect target is not a pointer");
3822
   VCODE_ASSERT(vtype_eq(vtype_pointed(p->type), r->type),
19,206✔
3823
                "pointer and stored value do not have same type");
3824
   VCODE_ASSERT(vtype_is_scalar(r->type), "cannot store non-scalar type");
19,206✔
3825
}
19,206✔
3826

3827
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
87,735✔
3828
                              vcode_reg_t locus)
3829
{
3830
   // Reuse any previous operation in this block with the same arguments
3831
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,966,608✔
3832
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
98,407✔
3833
         return other->result;
6,080✔
3834
   }
3835

3836
   op_t *op = vcode_add_op(kind);
81,655✔
3837
   vcode_add_arg(op, lhs);
81,655✔
3838
   vcode_add_arg(op, rhs);
81,655✔
3839
   if (locus != VCODE_INVALID_REG)
81,655✔
3840
      vcode_add_arg(op, locus);
8,247✔
3841

3842
   op->result = vcode_add_reg(vcode_reg_type(lhs));
81,655✔
3843

3844
   vcode_type_t lhs_type = vcode_reg_type(lhs);
81,655✔
3845
   vcode_type_t rhs_type = vcode_reg_type(rhs);
81,655✔
3846

3847
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
81,655✔
3848
                "arguments to %s are not the same type", vcode_op_string(kind));
3849

3850
   return op->result;
3851
}
3852

3853
static vcode_reg_t emit_mul_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
65,168✔
3854
                               vcode_reg_t locus)
3855
{
3856
   int64_t lconst, rconst;
65,168✔
3857
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
65,168✔
3858
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
65,168✔
3859
   if (l_is_const && r_is_const)
65,168✔
3860
      return emit_const(vcode_reg_type(lhs), lconst * rconst);
34,248✔
3861
   else if (r_is_const && rconst == 1)
30,920✔
3862
      return lhs;
3863
   else if (l_is_const && lconst == 1)
5,809✔
3864
      return rhs;
3865
   else if ((r_is_const && rconst == 0) || (l_is_const && lconst == 0))
5,111✔
3866
      return emit_const(vcode_reg_type(lhs), 0);
76✔
3867

3868
   reg_t *lhs_r = vcode_reg_data(lhs);
5,035✔
3869
   reg_t *rhs_r = vcode_reg_data(rhs);
5,035✔
3870

3871
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
5,035✔
3872
   vtype_t *br = vcode_type_data(rhs_r->bounds);
5,035✔
3873

3874
   vcode_type_t vbounds;
5,035✔
3875
   if (vcode_reg_kind(lhs) == VCODE_TYPE_REAL) {
5,035✔
3876
      const double ll = bl->rlow * br->rlow;
962✔
3877
      const double lh = bl->rlow * br->rhigh;
962✔
3878
      const double hl = bl->rhigh * br->rlow;
962✔
3879
      const double hh = bl->rhigh * br->rhigh;
962✔
3880

3881
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
2,143✔
3882
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
2,337✔
3883

3884
      vbounds = vtype_real(min, max);
962✔
3885
   }
3886
   else {
3887
      const int64_t ll = smul64(bl->low, br->low);
4,073✔
3888
      const int64_t lh = smul64(bl->low, br->high);
4,073✔
3889
      const int64_t hl = smul64(bl->high, br->low);
4,073✔
3890
      const int64_t hh = smul64(bl->high, br->high);
4,073✔
3891

3892
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
4,073✔
3893
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
4,073✔
3894

3895
      vtype_repr_t repr = vtype_repr(lhs_r->type);
4,073✔
3896
      if (op == VCODE_OP_TRAP_MUL && vtype_clamp_to_repr(repr, &min, &max)) {
4,073✔
3897
         op = VCODE_OP_MUL;   // Cannot overflow
611✔
3898
         locus = VCODE_INVALID_REG;
611✔
3899
      }
3900

3901
      vbounds = vtype_int(min, max);
4,073✔
3902
   }
3903

3904
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
5,035✔
3905

3906
   if (vbounds != VCODE_INVALID_TYPE)
5,035✔
3907
      vcode_reg_data(reg)->bounds = vbounds;
5,035✔
3908

3909
   return reg;
3910
}
3911

3912
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
63,860✔
3913
{
3914
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
63,860✔
3915
}
3916

3917
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
1,308✔
3918
{
3919
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
1,308✔
3920

3921
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
1,308✔
3922
                "trapping add may only be used with integer types");
3923

3924
   return result;
1,308✔
3925
}
3926

3927
vcode_reg_t emit_div(vcode_reg_t lhs, vcode_reg_t rhs)
2,163✔
3928
{
3929
   int64_t lconst, rconst;
2,163✔
3930
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
2,163✔
3931
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
2,163✔
3932
   if (l_is_const && r_is_const && rconst != 0)
2,163✔
3933
      return emit_const(vcode_reg_type(lhs), lconst / rconst);
39✔
3934
   else if (r_is_const && rconst == 1)
2,124✔
3935
      return lhs;
3936

3937
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
2,120✔
3938

3939
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
2,120✔
3940

3941
   if (bl->kind == VCODE_TYPE_INT && r_is_const && rconst != 0) {
2,120✔
3942
      reg_t *rr = vcode_reg_data(reg);
1,558✔
3943
      rr->bounds = vtype_int(bl->low / rconst, bl->high / rconst);
1,558✔
3944
   }
3945
   else if (bl->kind == VCODE_TYPE_REAL) {
562✔
3946
      reg_t *rr = vcode_reg_data(reg);
462✔
3947
      rr->bounds = vtype_real(-INFINITY, INFINITY);
462✔
3948
   }
3949

3950
   return reg;
3951
}
3952

3953
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
184✔
3954
{
3955
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
184✔
3956
}
3957

3958
vcode_reg_t emit_trap_exp(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
1,062✔
3959
{
3960
   int64_t rconst;
1,062✔
3961
   if (vcode_reg_const(rhs, &rconst)) {
1,062✔
3962
      if (rconst == 0)
942✔
3963
         return emit_const(vcode_reg_type(lhs), 1);
297✔
3964
      else if (rconst == 1)
645✔
3965
         return lhs;
3966
   }
3967

3968
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
700✔
3969

3970
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
700✔
3971
                "trapping exp may only be used with integer types");
3972

3973
   return result;
3974
}
3975

3976
vcode_reg_t emit_mod(vcode_reg_t lhs, vcode_reg_t rhs)
277✔
3977
{
3978
   int64_t lconst, rconst;
277✔
3979
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
277✔
3980
       && lconst > 0 && rconst > 0)
19✔
3981
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
4✔
3982

3983
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
273✔
3984
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
273✔
3985

3986
   if (bl->low >= 0 && br->low >= 0) {
273✔
3987
      // If both arguments are non-negative then rem is equivalent and
3988
      // cheaper to compute
3989
      vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
96✔
3990

3991
      reg_t *rr = vcode_reg_data(reg);
96✔
3992
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
96✔
3993

3994
      return reg;
96✔
3995
   }
3996
   else
3997
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
177✔
3998
}
3999

4000
vcode_reg_t emit_rem(vcode_reg_t lhs, vcode_reg_t rhs)
818✔
4001
{
4002
   int64_t lconst, rconst;
818✔
4003
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
818✔
4004
       && lconst > 0 && rconst > 0)
2✔
UNCOV
4005
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
×
4006

4007
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
818✔
4008

4009
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
818✔
4010
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
818✔
4011

4012
   if (bl->low >= 0 && br->low >= 0) {
818✔
4013
      reg_t *rr = vcode_reg_data(reg);
304✔
4014
      rr->bounds = vtype_int(0, br->high - 1);
304✔
4015
   }
4016

4017
   return reg;
4018
}
4019

4020
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
67,727✔
4021
                               vcode_reg_t locus)
4022
{
4023
   int64_t lconst, rconst;
67,727✔
4024
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
67,727✔
4025
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
67,727✔
4026
   if (l_is_const && r_is_const)
67,727✔
4027
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
20,439✔
4028
   else if (r_is_const && rconst == 0)
47,288✔
4029
      return lhs;
4030
   else if (l_is_const && lconst == 0)
47,116✔
4031
      return rhs;
4032

4033
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
26,577✔
4034
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
26,577✔
4035
      reg_t *lhs_r = vcode_reg_data(lhs);
26,073✔
4036
      reg_t *rhs_r = vcode_reg_data(rhs);
26,073✔
4037

4038
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
26,073✔
4039
      vtype_t *br = vcode_type_data(rhs_r->bounds);
26,073✔
4040

4041
      int64_t rbl = sadd64(bl->low, br->low);
26,073✔
4042
      int64_t rbh = sadd64(bl->high, br->high);
26,073✔
4043

4044
      vtype_repr_t repr = vtype_repr(lhs_r->type);
26,073✔
4045
      if (op == VCODE_OP_TRAP_ADD && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
26,073✔
4046
         op = VCODE_OP_ADD;   // Cannot overflow
1,106✔
4047
         locus = VCODE_INVALID_REG;
1,106✔
4048
      }
4049

4050
      vbounds = vtype_int(rbl, rbh);
26,073✔
4051
   }
4052

4053
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
26,577✔
4054

4055
   if (vbounds != VCODE_INVALID_TYPE)
26,577✔
4056
      vcode_reg_data(reg)->bounds = vbounds;
26,073✔
4057

4058
   return reg;
4059
}
4060

4061
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
61,183✔
4062
{
4063
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
61,183✔
4064
}
4065

4066
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
6,544✔
4067
{
4068
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
6,544✔
4069

4070
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
6,544✔
4071
                "trapping add may only be used with integer types");
4072

4073
   return result;
6,544✔
4074
}
4075

4076
static vcode_reg_t emit_sub_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
65,951✔
4077
                               vcode_reg_t locus)
4078
{
4079
   int64_t lconst, rconst;
65,951✔
4080
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
65,951✔
4081
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
65,951✔
4082
   if (l_is_const && r_is_const)
65,951✔
4083
      return emit_const(vcode_reg_type(lhs), lconst - rconst);
16,217✔
4084
   else if (r_is_const && rconst == 0)
49,734✔
4085
      return lhs;
4086
   else if (l_is_const && lconst == 0)
44,945✔
4087
      return emit_neg(rhs);
1,519✔
4088

4089
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
43,426✔
4090
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
43,426✔
4091
      reg_t *lhs_r = vcode_reg_data(lhs);
42,900✔
4092
      reg_t *rhs_r = vcode_reg_data(rhs);
42,900✔
4093

4094
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
42,900✔
4095
      vtype_t *br = vcode_type_data(rhs_r->bounds);
42,900✔
4096

4097
      int64_t rbl = ssub64(bl->low, br->high);
42,900✔
4098
      int64_t rbh = ssub64(bl->high, br->low);
42,900✔
4099

4100
      vtype_repr_t repr = vtype_repr(lhs_r->type);
42,900✔
4101
      if (op == VCODE_OP_TRAP_SUB && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
42,900✔
4102
         op = VCODE_OP_SUB;   // Cannot overflow
6,164✔
4103
         locus = VCODE_INVALID_REG;
6,164✔
4104
      }
4105

4106
      vbounds = vtype_int(rbl, rbh);
42,900✔
4107
   }
4108

4109
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
43,426✔
4110

4111
   if (vbounds != VCODE_INVALID_TYPE)
43,426✔
4112
      vcode_reg_data(reg)->bounds = vbounds;
42,900✔
4113

4114
   return reg;
4115
}
4116

4117
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
57,170✔
4118
{
4119
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
57,170✔
4120
}
4121

4122
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
8,781✔
4123
{
4124
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
8,781✔
4125

4126
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
8,781✔
4127
                "trapping sub may only be used with integer types");
4128

4129
   return result;
8,781✔
4130
}
4131

4132
static void vcode_calculate_var_index_type(op_t *op, var_t *var)
94,368✔
4133
{
4134
   switch (vtype_kind(var->type)) {
94,368✔
4135
   case VCODE_TYPE_CARRAY:
28,309✔
4136
      op->type = vtype_pointer(vtype_elem(var->type));
28,309✔
4137
      op->result = vcode_add_reg(op->type);
28,309✔
4138
      vcode_reg_data(op->result)->bounds = vtype_bounds(var->type);
28,309✔
4139
      break;
28,309✔
4140

4141
   case VCODE_TYPE_RECORD:
7,816✔
4142
      op->type = vtype_pointer(var->type);
7,816✔
4143
      op->result = vcode_add_reg(op->type);
7,816✔
4144
      break;
7,816✔
4145

4146
   case VCODE_TYPE_INT:
58,243✔
4147
   case VCODE_TYPE_FILE:
4148
   case VCODE_TYPE_ACCESS:
4149
   case VCODE_TYPE_REAL:
4150
   case VCODE_TYPE_UARRAY:
4151
   case VCODE_TYPE_POINTER:
4152
   case VCODE_TYPE_SIGNAL:
4153
   case VCODE_TYPE_CONTEXT:
4154
   case VCODE_TYPE_OFFSET:
4155
   case VCODE_TYPE_TRIGGER:
4156
   case VCODE_TYPE_RESOLUTION:
4157
      op->type = vtype_pointer(var->type);
58,243✔
4158
      op->result = vcode_add_reg(op->type);
58,243✔
4159
      vcode_reg_data(op->result)->bounds = var->bounds;
58,243✔
4160
      break;
58,243✔
4161

4162
   default:
UNCOV
4163
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4164
                   istr(var->name));
4165
   }
4166
}
94,368✔
4167

4168
vcode_reg_t emit_index(vcode_var_t var, vcode_reg_t offset)
42,413✔
4169
{
4170
   // Try to find a previous index of this var by this offset
4171
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_INDEX) {
1,739,597✔
4172
      if (other->address == var
104,425✔
4173
          && ((offset == VCODE_INVALID_REG && other->args.count == 0)
9,452✔
UNCOV
4174
              || (offset != VCODE_INVALID_REG
×
UNCOV
4175
                  && other->args.items[0] == offset)))
×
4176
         return other->result;
9,452✔
4177
   }
4178

4179
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
32,961✔
4180
   op->address = var;
32,961✔
4181

4182
   if (offset != VCODE_INVALID_REG)
32,961✔
UNCOV
4183
      vcode_add_arg(op, offset);
×
4184

4185
   vcode_calculate_var_index_type(op, vcode_var_data(var));
32,961✔
4186

4187
   if (offset != VCODE_INVALID_REG)
32,961✔
UNCOV
4188
      VCODE_ASSERT(vtype_kind(vcode_reg_type(offset)) == VCODE_TYPE_OFFSET,
×
4189
                   "index offset r%d does not have offset type", offset);
4190

4191
   return op->result;
32,961✔
4192
}
4193

4194
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
327,999✔
4195
{
4196
   if (vtype_eq(vcode_reg_type(reg), type))
327,999✔
4197
      return reg;
327,999✔
4198

4199
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
116,588✔
4200
   vtype_kind_t to   = vtype_kind(type);
116,588✔
4201

4202
   const bool integral =
233,176✔
4203
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
116,588✔
4204
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
116,588✔
4205

4206
   int64_t value;
116,588✔
4207
   if (integral && vcode_reg_const(reg, &value))
116,588✔
4208
      return emit_const(type, value);
21,363✔
4209

4210
   // Try to find a previous cast of this register to this type
4211
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CAST) {
1,849,722✔
4212
      if (vtype_eq(other->type, type) && other->args.items[0] == reg)
195,658✔
4213
         return other->result;
20,924✔
4214
   }
4215

4216
   op_t *op = vcode_add_op(VCODE_OP_CAST);
74,301✔
4217
   vcode_add_arg(op, reg);
74,301✔
4218
   op->type   = type;
74,301✔
4219
   op->result = vcode_add_reg(type);
74,301✔
4220

4221
   static const vcode_type_t allowed[][2] = {
74,301✔
4222
      { VCODE_TYPE_INT,    VCODE_TYPE_OFFSET  },
4223
      { VCODE_TYPE_OFFSET, VCODE_TYPE_INT     },
4224
      { VCODE_TYPE_INT,    VCODE_TYPE_INT     },
4225
      { VCODE_TYPE_INT,    VCODE_TYPE_REAL    },
4226
      { VCODE_TYPE_REAL,   VCODE_TYPE_INT     },
4227
      { VCODE_TYPE_REAL,   VCODE_TYPE_REAL    },
4228
      { VCODE_TYPE_ACCESS, VCODE_TYPE_ACCESS  },
4229
   };
4230

4231
   if (integral) {
74,301✔
4232
      vtype_t *vt = vcode_type_data(type);
73,200✔
4233
      int64_t low = vt->low, high = vt->high;
73,200✔
4234

4235
      vtype_t *rt = vcode_type_data(vcode_reg_bounds(reg));
73,200✔
4236
      low = MAX(low, rt->low);
73,200✔
4237
      high = MIN(high, rt->high);
73,200✔
4238

4239
      if (bounds != VCODE_INVALID_REG) {
73,200✔
4240
         vtype_t *bt = vcode_type_data(bounds);
45,592✔
4241
         low = MAX(low, bt->low);
45,592✔
4242
         high = MIN(high, bt->high);
45,592✔
4243
      }
4244

4245
      reg_t *rr = vcode_reg_data(op->result);
73,200✔
4246
      rr->bounds = vtype_int(low, high);
73,200✔
4247
   }
4248
   else if (bounds != VCODE_INVALID_REG)
1,101✔
4249
      vcode_reg_data(op->result)->bounds = bounds;
1,101✔
4250

4251
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
130,856✔
4252
      if (from == allowed[i][0] && to == allowed[i][1])
130,856✔
4253
         return op->result;
74,301✔
4254
   }
4255

UNCOV
4256
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4257
}
4258

4259
void emit_return(vcode_reg_t reg)
79,072✔
4260
{
4261
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
79,072✔
4262
   if (reg != VCODE_INVALID_REG) {
79,072✔
4263
      vcode_add_arg(op, reg);
37,295✔
4264

4265
      const vtype_kind_t rkind = vcode_reg_kind(reg);
37,295✔
4266
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY)
37,295✔
4267
         vcode_heap_allocate(reg);
6,552✔
4268

4269
      VCODE_ASSERT(active_unit->kind == VCODE_UNIT_FUNCTION
37,295✔
4270
                   || active_unit->kind == VCODE_UNIT_THUNK
4271
                   || active_unit->kind == VCODE_UNIT_PROPERTY,
4272
                   "returning value fron non-function unit");
4273
      VCODE_ASSERT((active_unit->kind == VCODE_UNIT_PROPERTY
37,295✔
4274
                    && rkind == VCODE_TYPE_INT)
4275
                   || vtype_eq(active_unit->result, vcode_reg_type(reg))
4276
                   || (vtype_kind(active_unit->result) == VCODE_TYPE_ACCESS
4277
                       && rkind == VCODE_TYPE_ACCESS),
4278
                   "return value incorrect type");
4279
   }
4280
}
79,072✔
4281

4282
void emit_sched_waveform(vcode_reg_t nets, vcode_reg_t nnets,
14,210✔
4283
                         vcode_reg_t values, vcode_reg_t reject,
4284
                         vcode_reg_t after)
4285
{
4286
   int64_t nconst;
14,210✔
4287
   if (vcode_reg_const(nnets, &nconst) && nconst == 0) {
14,210✔
4288
      emit_comment("Skip empty waveform");
12✔
4289
      return;
12✔
4290
   }
4291

4292
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
14,198✔
4293
   vcode_add_arg(op, nets);
14,198✔
4294
   vcode_add_arg(op, nnets);
14,198✔
4295
   vcode_add_arg(op, values);
14,198✔
4296
   vcode_add_arg(op, reject);
14,198✔
4297
   vcode_add_arg(op, after);
14,198✔
4298

4299
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
14,198✔
4300
                "sched_waveform target is not signal");
4301
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
14,198✔
4302
                "sched_waveform net count is not offset type");
4303
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
14,198✔
4304
                "signal cannot be values argument for sched_waveform");
4305
}
4306

4307
void emit_force(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t values)
84✔
4308
{
4309
   op_t *op = vcode_add_op(VCODE_OP_FORCE);
84✔
4310
   vcode_add_arg(op, nets);
84✔
4311
   vcode_add_arg(op, nnets);
84✔
4312
   vcode_add_arg(op, values);
84✔
4313

4314
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
84✔
4315
                "force target is not signal");
4316
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
84✔
4317
                "force net count is not offset type");
4318
}
84✔
4319

4320
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
40✔
4321
{
4322
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
40✔
4323
   vcode_add_arg(op, nets);
40✔
4324
   vcode_add_arg(op, nnets);
40✔
4325

4326
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
40✔
4327
                "release target is not signal");
4328
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
40✔
4329
                "release net count is not offset type");
4330
}
40✔
4331

4332
void emit_disconnect(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t reject,
32✔
4333
                     vcode_reg_t after)
4334
{
4335
   op_t *op = vcode_add_op(VCODE_OP_DISCONNECT);
32✔
4336
   vcode_add_arg(op, nets);
32✔
4337
   vcode_add_arg(op, nnets);
32✔
4338
   vcode_add_arg(op, reject);
32✔
4339
   vcode_add_arg(op, after);
32✔
4340

4341
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
32✔
4342
                "disconnect target is not signal");
4343
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
32✔
4344
                "disconnect net count is not offset type");
4345
}
32✔
4346

4347
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
49,828✔
4348
{
4349
   int64_t tconst;
49,828✔
4350
   if (vcode_reg_const(test, &tconst)) {
49,828✔
4351
      emit_jump(!!tconst ? btrue : bfalse);
6,209✔
4352
      return;
3,678✔
4353
   }
4354

4355
   op_t *op = vcode_add_op(VCODE_OP_COND);
46,150✔
4356
   vcode_add_arg(op, test);
46,150✔
4357
   vcode_add_target(op, btrue);
46,150✔
4358
   vcode_add_target(op, bfalse);
46,150✔
4359

4360
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
46,150✔
4361
                "cond test is not a bool");
4362
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
46,150✔
4363
                "invalid cond targets");
4364
}
4365

4366
vcode_reg_t emit_neg(vcode_reg_t lhs)
9,182✔
4367
{
4368
   int64_t lconst;
9,182✔
4369
   if (vcode_reg_const(lhs, &lconst))
9,182✔
UNCOV
4370
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4371

4372
   op_t *op = vcode_add_op(VCODE_OP_NEG);
9,182✔
4373
   vcode_add_arg(op, lhs);
9,182✔
4374
   op->result = vcode_add_reg(vcode_reg_type(lhs));
9,182✔
4375

4376
   return op->result;
9,182✔
4377
}
4378

4379
vcode_reg_t emit_trap_neg(vcode_reg_t lhs, vcode_reg_t locus)
624✔
4380
{
4381
   int64_t lconst;
624✔
4382
   if (vcode_reg_const(lhs, &lconst) && lconst >= 0)
624✔
UNCOV
4383
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4384
   else if (vcode_type_data(vcode_reg_data(lhs)->bounds)->low >= 0)
624✔
4385
      return emit_neg(lhs);   // Cannot overflow
280✔
4386

4387
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
344✔
4388
   vcode_add_arg(op, lhs);
344✔
4389
   vcode_add_arg(op, locus);
344✔
4390

4391
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
344✔
4392
                "locus argument to trap neg must be a debug locus");
4393
   VCODE_ASSERT(vcode_reg_kind(lhs) == VCODE_TYPE_INT,
344✔
4394
                "trapping neg may only be used with integer types");
4395

4396
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
344✔
4397
}
4398

4399
vcode_reg_t emit_abs(vcode_reg_t lhs)
988✔
4400
{
4401
   int64_t lconst;
988✔
4402
   if (vcode_reg_const(lhs, &lconst))
988✔
4403
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4404

4405
   op_t *op = vcode_add_op(VCODE_OP_ABS);
987✔
4406
   vcode_add_arg(op, lhs);
987✔
4407
   op->result = vcode_add_reg(vcode_reg_type(lhs));
987✔
4408

4409
   return op->result;
987✔
4410
}
4411

4412
void emit_comment(const char *fmt, ...)
103,225✔
4413
{
4414
#ifndef NDEBUG
4415
   va_list ap;
103,225✔
4416
   va_start(ap, fmt);
103,225✔
4417

4418
   char *buf = xvasprintf(fmt, ap);
103,225✔
4419
   for (char *p = buf + strlen(buf) - 1;
103,225✔
4420
        p >= buf && isspace_iso88591(*p); p--)
103,225✔
UNCOV
4421
      *p = '\0';
×
4422

4423
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
103,225✔
4424
   va_end(ap);
103,225✔
4425
#endif
4426
}
103,225✔
4427

4428
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
25,899✔
4429
                        vcode_reg_t rfalse)
4430
{
4431
   int64_t tconst;
25,899✔
4432
   if (vcode_reg_const(test, &tconst))
25,899✔
4433
      return !!tconst ? rtrue : rfalse;
6,008✔
4434
   else if (rtrue == rfalse)
19,891✔
4435
      return rtrue;
4436

4437
   // Find a previous identical select
4438
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
420,781✔
4439
      if (other->args.items[0] == test && other->args.items[1] == rtrue
15,231✔
4440
          && other->args.items[2] == rfalse)
1,021✔
4441
         return other->result;
883✔
4442
   }
4443

4444
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
18,730✔
4445
   vcode_add_arg(op, test);
18,730✔
4446
   vcode_add_arg(op, rtrue);
18,730✔
4447
   vcode_add_arg(op, rfalse);
18,730✔
4448
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
18,730✔
4449

4450
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
18,730✔
4451
                "select test must have bool type");
4452
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
18,730✔
4453
                "select arguments are not the same type");
4454

4455
   return op->result;
18,730✔
4456
}
4457

4458
static vcode_reg_t emit_logical_identity(vcode_op_t op, vcode_reg_t reg, bool b)
517✔
4459
{
4460
   switch (op) {
517✔
4461
   case VCODE_OP_AND:  return b ? reg : emit_const(vtype_bool(), 0);
32✔
4462
   case VCODE_OP_OR:   return b ? emit_const(vtype_bool(), 1) : reg;
421✔
4463
   case VCODE_OP_XOR:  return b ? emit_not(reg) : reg;
16✔
4464
   case VCODE_OP_XNOR: return b ? reg : emit_not(reg);
16✔
4465
   case VCODE_OP_NAND: return b ? emit_not(reg) : emit_const(vtype_bool(), 1);
16✔
4466
   case VCODE_OP_NOR:  return b ? emit_const(vtype_bool(), 0) : emit_not(reg);
16✔
UNCOV
4467
   default:
×
4468
      fatal_trace("missing logicial identity for %s", vcode_op_string(op));
4469
   }
4470
}
4471

4472
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
9,163✔
4473
{
4474
   vcode_type_t vtbool = vtype_bool();
9,163✔
4475

4476
   int64_t lconst, rconst;
9,163✔
4477
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
9,163✔
4478
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
9,163✔
4479
   if (l_is_const && r_is_const) {
9,163✔
4480
      switch (op) {
8✔
UNCOV
4481
      case VCODE_OP_AND:  return emit_const(vtbool, lconst && rconst);
×
UNCOV
4482
      case VCODE_OP_OR:   return emit_const(vtbool, lconst || rconst);
×
UNCOV
4483
      case VCODE_OP_XOR:  return emit_const(vtbool, lconst ^ rconst);
×
4484
      case VCODE_OP_XNOR: return emit_const(vtbool, !(lconst ^ rconst));
8✔
UNCOV
4485
      case VCODE_OP_NAND: return emit_const(vtbool, !(lconst && rconst));
×
UNCOV
4486
      case VCODE_OP_NOR:  return emit_const(vtbool, !(lconst || rconst));
×
UNCOV
4487
      default:
×
4488
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
4489
      }
4490
   }
4491
   else if (l_is_const)
9,155✔
4492
      return emit_logical_identity(op, rhs, !!lconst);
412✔
4493
   else if (r_is_const)
8,743✔
4494
      return emit_logical_identity(op, lhs, !!rconst);
105✔
4495
   else if (lhs == rhs) {
8,638✔
4496
      switch (op) {
36✔
4497
      case VCODE_OP_AND:
4498
      case VCODE_OP_OR:
4499
         return lhs;
4500
      case VCODE_OP_NAND:
8✔
4501
      case VCODE_OP_NOR:
4502
         return emit_not(lhs);
8✔
4503
      case VCODE_OP_XOR:
4✔
4504
         return emit_const(vtbool, 0);
4✔
4505
      case VCODE_OP_XNOR:
×
4506
         return emit_const(vtbool, 1);
×
4507
      default:
×
4508
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
4509
      }
4510
   }
4511

4512
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
8,602✔
4513

4514
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
8,602✔
4515
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4516
                "arguments to %s are not boolean", vcode_op_string(op));
4517

4518
   return result;
4519
}
4520

4521
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
3,113✔
4522
{
4523
   return emit_logical(VCODE_OP_OR, lhs, rhs);
3,113✔
4524
}
4525

4526
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
5,730✔
4527
{
4528
   return emit_logical(VCODE_OP_AND, lhs, rhs);
5,730✔
4529
}
4530

4531
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
69✔
4532
{
4533
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
69✔
4534
}
4535

4536
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
70✔
4537
{
4538
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
70✔
4539
}
4540

4541
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
104✔
4542
{
4543
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
104✔
4544
}
4545

4546
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
77✔
4547
{
4548
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
77✔
4549
}
4550

4551
vcode_reg_t emit_not(vcode_reg_t arg)
3,388✔
4552
{
4553
   int64_t cval;
3,388✔
4554
   if (vcode_reg_const(arg, &cval))
3,388✔
4555
      return emit_const(vtype_bool(), !cval);
36✔
4556

4557
   op_t *op = vcode_add_op(VCODE_OP_NOT);
3,352✔
4558
   vcode_add_arg(op, arg);
3,352✔
4559

4560
   vcode_type_t vtbool = vtype_bool();
3,352✔
4561
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
3,352✔
4562
                "argument to not is not boolean");
4563

4564
   return (op->result = vcode_add_reg(vtbool));
3,352✔
4565
}
4566

4567
vcode_reg_t emit_wrap(vcode_reg_t data, const vcode_dim_t *dims, int ndims)
59,596✔
4568
{
4569
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_WRAP) {
2,243,109✔
4570
      if (other->args.count == ndims*3 + 1 && other->args.items[0] == data) {
203,225✔
4571
         bool match = true;
4572
         for (int i = 0; match && i < ndims; i++) {
26,003✔
4573
            match = other->args.items[i*3 + 1] == dims[i].left
13,040✔
4574
               && other->args.items[i*3 + 2] == dims[i].right
11,118✔
4575
               && other->args.items[i*3 + 3] == dims[i].dir;
23,826✔
4576
         }
4577
         if (match)
12,963✔
4578
            return other->result;
10,709✔
4579
      }
4580
   }
4581

4582
   op_t *op = vcode_add_op(VCODE_OP_WRAP);
48,887✔
4583
   vcode_add_arg(op, data);
48,887✔
4584
   for (int i = 0; i < ndims; i++) {
98,480✔
4585
      vcode_add_arg(op, dims[i].left);
49,593✔
4586
      vcode_add_arg(op, dims[i].right);
49,593✔
4587
      vcode_add_arg(op, dims[i].dir);
49,593✔
4588
   }
4589

4590
   vcode_type_t ptr_type = vcode_reg_type(data);
48,887✔
4591
   const vtype_kind_t ptrkind = vtype_kind(ptr_type);
48,887✔
4592
   VCODE_ASSERT(ptrkind == VCODE_TYPE_POINTER || ptrkind == VCODE_TYPE_SIGNAL,
48,887✔
4593
                "wrapped data is not pointer or signal");
4594

4595
#ifdef DEBUG
4596
   for (int i = 0; i < ndims; i++) {
98,480✔
4597
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].left)),
49,593✔
4598
                   "dimension %d left bound must be scalar", i + 1);
4599
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].right)),
49,593✔
4600
                   "dimension %d right bound must be scalar", i + 1);
4601
      VCODE_ASSERT(vtype_eq(vtype_bool(), vcode_reg_type(dims[i].dir)),
49,593✔
4602
                   "dimension %d direction must be bool", i + 1);
4603
   }
4604
#endif
4605

4606
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
97,774✔
4607
      ? vtype_pointed(ptr_type) : ptr_type;
48,887✔
4608

4609
   op->result = vcode_add_reg(
48,887✔
4610
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4611

4612
   return op->result;
48,887✔
4613
}
4614

4615
static vcode_reg_t emit_uarray_op(vcode_op_t o, vcode_type_t rtype,
145,620✔
4616
                                  vcode_reg_t array, unsigned dim,
4617
                                  unsigned arg_index)
4618
{
4619
   // Reuse any previous operation in this block with the same arguments
4620
   VCODE_FOR_EACH_OP(other) {
1,646,964✔
4621
      if (other->kind == o && other->args.items[0] == array && other->dim == dim
1,582,544✔
4622
          && (rtype == VCODE_INVALID_TYPE
34,159✔
4623
              || vtype_eq(rtype, vcode_reg_type(other->result))))
14,884✔
4624
         return other->result;
34,159✔
4625
      else if (other->kind == VCODE_OP_WRAP && other->result == array)
1,548,385✔
4626
         return other->args.items[1 + (dim * 3) + arg_index];
47,041✔
4627
   }
4628

4629
   op_t *op = vcode_add_op(o);
64,420✔
4630
   vcode_add_arg(op, array);
64,420✔
4631
   op->dim = dim;
64,420✔
4632

4633
   vcode_type_t atype = vcode_reg_type(array);
64,420✔
4634
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
64,420✔
4635
                "cannot use %s with non-uarray type", vcode_op_string(o));
4636

4637
   vtype_t *vt = vcode_type_data(atype);
64,420✔
4638
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
64,420✔
4639

4640
   if (rtype == VCODE_INVALID_TYPE)
64,420✔
4641
      rtype = vtype_offset();
41,627✔
4642

4643
   return (op->result = vcode_add_reg(rtype));
64,420✔
4644
}
4645

4646
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
53,847✔
4647
{
4648
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
53,847✔
4649
                         array, dim, 0);
4650
}
4651

4652
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
38,348✔
4653
{
4654
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
38,348✔
4655
                         array, dim, 1);
4656
}
4657

4658
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
53,425✔
4659
{
4660
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
53,425✔
4661
                         array, dim, 2);
4662
}
4663

4664
vcode_reg_t emit_uarray_len(vcode_reg_t array, unsigned dim)
64,377✔
4665
{
4666
   VCODE_FOR_EACH_OP(other) {
895,325✔
4667
      if (other->kind == VCODE_OP_UARRAY_LEN) {
863,477✔
4668
         if (other->args.items[0] == array && other->dim == dim)
57,171✔
4669
            return other->result;
13,053✔
4670
      }
4671
      else if (other->kind == VCODE_OP_WRAP && other->result == array) {
806,306✔
4672
         VCODE_ASSERT(dim < (other->args.count - 1) / 3,
19,476✔
4673
                      "array dimension %d out of bounds", dim);
4674

4675
         vcode_reg_t left_reg = other->args.items[dim * 3 + 1];
19,476✔
4676
         vcode_reg_t right_reg = other->args.items[dim * 3 + 2];
19,476✔
4677
         vcode_reg_t dir_reg = other->args.items[dim * 3 + 3];
19,476✔
4678
         return emit_range_length(left_reg, right_reg, dir_reg);
19,476✔
4679
      }
4680
   }
4681

4682
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
31,848✔
4683
   vcode_add_arg(op, array);
31,848✔
4684
   op->dim = dim;
31,848✔
4685

4686
   vcode_type_t atype = vcode_reg_type(array);
31,848✔
4687
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
31,848✔
4688
                "cannot use uarray len with non-uarray type");
4689

4690
   vtype_t *vt = vcode_type_data(atype);
31,848✔
4691
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
31,848✔
4692

4693
   op->result = vcode_add_reg(vtype_offset());
31,848✔
4694

4695
   reg_t *rr = vcode_reg_data(op->result);
31,848✔
4696
   rr->bounds = vtype_int(0, INT64_MAX);
31,848✔
4697

4698
   return op->result;
31,848✔
4699
}
4700

4701
vcode_reg_t emit_unwrap(vcode_reg_t array)
51,374✔
4702
{
4703
   VCODE_FOR_EACH_OP(other) {
2,083,357✔
4704
      if (other->kind == VCODE_OP_WRAP && other->result == array)
2,046,153✔
4705
         return other->args.items[0];
11,625✔
4706
      else if (other->kind == VCODE_OP_UNWRAP && other->args.items[0] == array)
2,034,528✔
4707
         return other->result;
2,545✔
4708
   }
4709

4710
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
37,204✔
4711
   vcode_add_arg(op, array);
37,204✔
4712

4713
   vtype_t *vt = vcode_type_data(vcode_reg_type(array));
37,204✔
4714
   VCODE_ASSERT(vt->kind == VCODE_TYPE_UARRAY,
37,204✔
4715
                "unwrap can only only be used with uarray types");
4716

4717
   vcode_type_t elem = vt->elem;
37,204✔
4718

4719
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
37,204✔
4720
      ? elem : vtype_pointer(elem);
37,204✔
4721

4722
   op->result = vcode_add_reg(rtype);
37,204✔
4723

4724
   reg_t *rr = vcode_reg_data(op->result);
37,204✔
4725
   rr->bounds = elem;
37,204✔
4726

4727
   return op->result;
37,204✔
4728
}
4729

4730
vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right,
37,641✔
4731
                            vcode_reg_t dir)
4732
{
4733
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_NULL) {
1,760,752✔
UNCOV
4734
      if (other->args.items[0] == left
×
UNCOV
4735
          && other->args.items[1] == right
×
UNCOV
4736
          && other->args.items[2] == dir)
×
UNCOV
4737
         return other->result;
×
4738
   }
4739

4740
   int64_t dir_const;
37,641✔
4741
   if (vcode_reg_const(dir, &dir_const)) {
37,641✔
4742
      vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
33,320✔
4743
      vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
33,320✔
4744

4745
      if (dir_const == RANGE_TO && lbounds->low > rbounds->high)
33,320✔
4746
         return emit_const(vtype_bool(), 1);
80✔
4747
      else if (dir_const == RANGE_TO && lbounds->high <= rbounds->low)
33,240✔
4748
         return emit_const(vtype_bool(), 0);
22,938✔
4749
      else if (dir_const == RANGE_DOWNTO && rbounds->low > lbounds->high)
10,302✔
4750
         return emit_const(vtype_bool(), 1);
795✔
4751
      else if (dir_const == RANGE_DOWNTO && rbounds->high <= lbounds->low)
9,507✔
4752
         return emit_const(vtype_bool(), 0);
2,369✔
4753
      else if (dir_const == RANGE_TO)
7,138✔
4754
         return emit_cmp(VCODE_CMP_GT, left, right);
3,107✔
4755
      else
4756
         return emit_cmp(VCODE_CMP_GT, right, left);
4,031✔
4757
   }
4758

4759
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
4,321✔
4760
   vcode_add_arg(op, left);
4,321✔
4761
   vcode_add_arg(op, right);
4,321✔
4762
   vcode_add_arg(op, dir);
4,321✔
4763

4764
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
4,321✔
4765
                "range left and right have different types");
4766
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
4,321✔
4767
                "dir argument to range length is not int");
4768

4769
   return (op->result = vcode_add_reg(vtype_bool()));
4,321✔
4770
}
4771

4772
vcode_reg_t emit_range_length(vcode_reg_t left, vcode_reg_t right,
19,518✔
4773
                              vcode_reg_t dir)
4774
{
4775
   vcode_reg_t left_array = VCODE_INVALID_REG,
19,518✔
4776
      right_array = VCODE_INVALID_REG,
19,518✔
4777
      dir_array = VCODE_INVALID_REG;
19,518✔
4778
   int left_dim = -1, right_dim = -1, dir_dim = -1;
19,518✔
4779

4780
   VCODE_FOR_EACH_OP(other) {
383,741✔
4781
      if (other->kind == VCODE_OP_RANGE_LENGTH
371,275✔
4782
          && other->args.items[0] == left
9,564✔
4783
          && other->args.items[1] == right
7,467✔
4784
          && other->args.items[2] == dir)
7,052✔
4785
         return other->result;
7,052✔
4786
      else if (other->kind == VCODE_OP_UARRAY_LEFT && other->result == left) {
364,223✔
4787
         left_array = other->args.items[0];
537✔
4788
         left_dim = other->dim;
537✔
4789
      }
4790
      else if (other->kind == VCODE_OP_UARRAY_RIGHT && other->result == right) {
363,686✔
4791
         right_array = other->args.items[0];
537✔
4792
         right_dim = other->dim;
537✔
4793
      }
4794
      else if (other->kind == VCODE_OP_UARRAY_DIR && other->result == dir) {
363,149✔
4795
         dir_array = other->args.items[0];
999✔
4796
         dir_dim = other->dim;
999✔
4797
      }
4798
   }
4799

4800
   if (left_array != VCODE_INVALID_REG && left_array == right_array
12,466✔
4801
       && right_array == dir_array && left_dim == right_dim
537✔
4802
       && right_dim == dir_dim)
537✔
4803
      return emit_uarray_len(left_array, left_dim);
537✔
4804

4805
   int64_t lconst, rconst, dconst;
11,929✔
4806
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
11,929✔
4807
       && vcode_reg_const(right, &rconst)) {
6,464✔
4808

4809
      int64_t diff;
2,834✔
4810
      if (dconst == RANGE_TO)
2,834✔
4811
         diff = rconst - lconst;
2,529✔
4812
      else
4813
         diff = lconst - rconst;
305✔
4814

4815
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
2,834✔
4816
   }
4817

4818
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
9,095✔
4819
   vcode_add_arg(op, left);
9,095✔
4820
   vcode_add_arg(op, right);
9,095✔
4821
   vcode_add_arg(op, dir);
9,095✔
4822

4823
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
9,095✔
4824
                "range left and right have different types");
4825
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
9,095✔
4826
                "dir argument to range length is not int");
4827

4828
   op->result = vcode_add_reg(vtype_offset());
9,095✔
4829

4830
   reg_t *rr = vcode_reg_data(op->result);
9,095✔
4831
   rr->bounds = vtype_int(0, INT64_MAX);
9,095✔
4832

4833
   return op->result;
9,095✔
4834
}
4835

4836
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
72,217✔
4837
{
4838
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
630,668✔
4839
      if (other->hops == hops && other->address == var)
83,222✔
4840
         return other->result;
10,810✔
4841
   }
4842

4843
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
61,407✔
4844
   op->hops    = hops;
61,407✔
4845
   op->address = var;
61,407✔
4846

4847
   VCODE_ASSERT(hops > 0, "invalid hop count");
61,407✔
4848

4849
   vcode_unit_t vu = active_unit;
61,407✔
4850
   for (int i = 0; i < hops; i++) {
137,231✔
4851
      vu = vu->context;
75,824✔
4852
      VCODE_ASSERT(vu, "hop count is greater than depth");
75,824✔
4853
   }
4854

4855
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
61,407✔
4856

4857
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
61,407✔
4858

4859
   return op->result;
61,407✔
4860
}
4861

4862
vcode_reg_t emit_init_signal(vcode_type_t type, vcode_reg_t count,
20,853✔
4863
                             vcode_reg_t size, vcode_reg_t value,
4864
                             vcode_reg_t flags, vcode_reg_t locus,
4865
                             vcode_reg_t offset)
4866
{
4867
   op_t *op = vcode_add_op(VCODE_OP_INIT_SIGNAL);
20,853✔
4868
   vcode_add_arg(op, count);
20,853✔
4869
   vcode_add_arg(op, size);
20,853✔
4870
   vcode_add_arg(op, value);
20,853✔
4871
   vcode_add_arg(op, flags);
20,853✔
4872
   vcode_add_arg(op, locus);
20,853✔
4873
   if (offset != VCODE_INVALID_REG)
20,853✔
4874
      vcode_add_arg(op, offset);
7,495✔
4875

4876
   vcode_type_t vtype = vcode_reg_type(value);
20,853✔
4877
   VCODE_ASSERT(vtype_is_scalar(type), "signal type must be scalar");
20,853✔
4878
   VCODE_ASSERT(vtype_eq(vtype, type)
20,853✔
4879
                || vtype_kind(vtype) == VCODE_TYPE_POINTER,
4880
                "init signal value type does not match signal type");
4881
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
20,853✔
4882
                "locus argument to init signal must be a debug locus");
4883
   VCODE_ASSERT(offset == VCODE_INVALID_REG
20,853✔
4884
                || vcode_reg_kind(offset) == VCODE_TYPE_POINTER,
4885
                "init signal offset argument must have pointer type");
4886

4887
   return (op->result = vcode_add_reg(vtype_signal(type)));
20,853✔
4888
}
4889

4890
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
4,272✔
4891
{
4892
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
4,272✔
4893
   vcode_add_arg(op, signal);
4,272✔
4894
   vcode_add_arg(op, resolution);
4,272✔
4895

4896
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
4,272✔
4897
                "signal argument has wrong type");
4898

4899
   vcode_type_t rtype = vcode_reg_type(resolution);
4,272✔
4900
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
4,272✔
4901
                "resolution wrapper argument must be pointer");
4902
   VCODE_ASSERT(vtype_kind(vtype_pointed(rtype)) == VCODE_TYPE_RESOLUTION,
4,272✔
4903
                "resolution wrapper argument has wrong type");
4904
}
4,272✔
4905

4906
vcode_reg_t emit_implicit_signal(vcode_type_t type, vcode_reg_t count,
108✔
4907
                                 vcode_reg_t size, vcode_reg_t locus,
4908
                                 vcode_reg_t kind, vcode_reg_t closure,
4909
                                 vcode_reg_t delay)
4910
{
4911
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_SIGNAL);
108✔
4912
   vcode_add_arg(op, count);
108✔
4913
   vcode_add_arg(op, size);
108✔
4914
   vcode_add_arg(op, locus);
108✔
4915
   vcode_add_arg(op, kind);
108✔
4916
   vcode_add_arg(op, closure);
108✔
4917
   vcode_add_arg(op, delay);
108✔
4918

4919
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
108✔
4920
                "count argument to implicit signal is not offset");
4921
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
108✔
4922
                "kind argument to implicit signal is not offset");
4923
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
108✔
4924
                "closure argument to implicit signal is not a closure");
4925
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
108✔
4926
                "locus argument to implicit signal must be a debug locus");
4927
   VCODE_ASSERT(vcode_reg_kind(delay) == VCODE_TYPE_INT,
108✔
4928
                "delay argument to implicit signal must be time");
4929

4930
   return (op->result = vcode_add_reg(vtype_signal(type)));
108✔
4931
}
4932

4933
void emit_map_signal(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
7,078✔
4934
{
4935
   op_t *op = vcode_add_op(VCODE_OP_MAP_SIGNAL);
7,078✔
4936
   vcode_add_arg(op, src);
7,078✔
4937
   vcode_add_arg(op, dst);
7,078✔
4938
   vcode_add_arg(op, count);
7,078✔
4939

4940
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
7,078✔
4941
                "src argument to map signal is not a signal");
4942
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
7,078✔
4943
                "dst argument to map signal is not a signal");
4944
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
7,078✔
4945
                "count argument type to map signal is not offset");
4946
}
7,078✔
4947

4948
void emit_map_const(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
248✔
4949
{
4950
   op_t *op = vcode_add_op(VCODE_OP_MAP_CONST);
248✔
4951
   vcode_add_arg(op, src);
248✔
4952
   vcode_add_arg(op, dst);
248✔
4953
   vcode_add_arg(op, count);
248✔
4954

4955
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
248✔
4956
                "dst argument to map const is not a signal");
4957
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
248✔
4958
                "count argument type to map const is not offset");
4959
}
248✔
4960

4961
void emit_map_implicit(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
84✔
4962
{
4963
   op_t *op = vcode_add_op(VCODE_OP_MAP_IMPLICIT);
84✔
4964
   vcode_add_arg(op, src);
84✔
4965
   vcode_add_arg(op, dst);
84✔
4966
   vcode_add_arg(op, count);
84✔
4967

4968
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
84✔
4969
                "src argument to map implicit is not a signal");
4970
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
84✔
4971
                "dst argument to map implicit is not a signal");
4972
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
84✔
4973
                "count argument type to map implicit is not offset");
4974
}
84✔
4975

4976
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
12,354✔
4977
{
4978
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
152,004✔
4979
      if (other->args.items[0] == target && other->args.items[1] == count)
18,353✔
4980
         return;
4981
   }
4982

4983
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
12,350✔
4984
   vcode_add_arg(op, target);
12,350✔
4985
   vcode_add_arg(op, count);
12,350✔
4986

4987
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
12,350✔
4988
                "target argument to drive signal is not a signal");
4989
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
12,350✔
4990
                "count argument type to drive signal is not offset");
4991
}
4992

4993
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
1,606✔
4994
                          vcode_reg_t count, vcode_reg_t reject,
4995
                          vcode_reg_t after)
4996
{
4997
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
1,606✔
4998
   vcode_add_arg(op, target);
1,606✔
4999
   vcode_add_arg(op, source);
1,606✔
5000
   vcode_add_arg(op, count);
1,606✔
5001
   vcode_add_arg(op, reject);
1,606✔
5002
   vcode_add_arg(op, after);
1,606✔
5003

5004
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
1,606✔
5005
                "target argument to transfer signal is not a signal");
5006
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,606✔
5007
                "count argument type to transfer signal is not offset");
5008
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
1,606✔
5009
                "source argument to transfer signal is not a signal");
5010
}
1,606✔
5011

5012
vcode_reg_t emit_resolution_wrapper(vcode_type_t type, vcode_reg_t closure,
5,902✔
5013
                                    vcode_reg_t nlits)
5014
{
5015
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RESOLUTION_WRAPPER) {
99,465✔
5016
      if (other->args.items[0] == closure && other->args.items[1] == nlits)
13,189✔
UNCOV
5017
         return other->result;
×
5018
   }
5019

5020
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
5,902✔
5021
                "first argument to resolution wrapper must be closure");
5022

5023
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
5,902✔
5024
   vcode_add_arg(op, closure);
5,902✔
5025
   vcode_add_arg(op, nlits);
5,902✔
5026

5027
   return (op->result = vcode_add_reg(vtype_resolution(type)));
5,902✔
5028
}
5029

5030
vcode_reg_t emit_closure(ident_t func, vcode_reg_t context, vcode_type_t rtype)
6,290✔
5031
{
5032
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CLOSURE) {
102,091✔
5033
      if (other->func == func && other->args.items[0] == context)
13,465✔
UNCOV
5034
         return other->result;
×
5035
   }
5036

5037
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
6,290✔
5038
   vcode_add_arg(op, context);
6,290✔
5039
   op->func = func;
6,290✔
5040

5041
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
6,290✔
5042
                "invalid closure context argument");
5043

5044
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
6,290✔
5045
}
5046

5047
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
56,340✔
5048
{
5049
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
104,137✔
5050
      if (other->func == name)
44,628✔
5051
         return other->result;
22,122✔
5052
   }
5053

5054
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
34,218✔
5055
   op->func = name;
34,218✔
5056
   if (context != VCODE_INVALID_REG)
34,218✔
5057
      vcode_add_arg(op, context);
243✔
5058

5059
   VCODE_ASSERT(context == VCODE_INVALID_REG
34,218✔
5060
                || vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5061
                "invalid protected init context argument");
5062
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_INSTANCE
34,218✔
5063
                || active_unit->kind == VCODE_UNIT_PACKAGE
5064
                || active_unit->kind == VCODE_UNIT_THUNK,
5065
                "cannot use package init here");
5066
   VCODE_ASSERT(name != active_unit->name, "cyclic package init");
34,218✔
5067

5068
   return (op->result = vcode_add_reg(vtype_context(name)));
34,218✔
5069
}
5070

5071
vcode_reg_t emit_protected_init(vcode_type_t type, vcode_reg_t context,
719✔
5072
                                vcode_reg_t path_name, vcode_reg_t inst_name)
5073
{
5074
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_INIT);
719✔
5075
   vcode_add_arg(op, context);
719✔
5076
   op->func = vtype_name(type);
719✔
5077

5078
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
719✔
5079
      vcode_add_arg(op, path_name);
548✔
5080
      vcode_add_arg(op, inst_name);
548✔
5081

5082
      VCODE_ASSERT(vcode_reg_kind(path_name) == VCODE_TYPE_UARRAY,
548✔
5083
                   "path name argument must be uarray");
5084
      VCODE_ASSERT(vcode_reg_kind(inst_name) == VCODE_TYPE_UARRAY,
548✔
5085
                   "inst name argument must be uarray");
5086
   }
5087

5088
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
719✔
5089
                "protected init type must be context");
5090
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
719✔
5091
                "invalid protected init context argument");
5092

5093
   return (op->result = vcode_add_reg(type));
719✔
5094
}
5095

5096
void emit_process_init(ident_t name, vcode_reg_t locus)
154✔
5097
{
5098
   op_t *op = vcode_add_op(VCODE_OP_PROCESS_INIT);
154✔
5099
   vcode_add_arg(op, locus);
154✔
5100
   op->func = name;
154✔
5101

5102
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
154✔
5103
                "locus argument to process init must be a debug locus");
5104
}
154✔
5105

5106
void emit_protected_free(vcode_reg_t obj)
411✔
5107
{
5108
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
411✔
5109
   vcode_add_arg(op, obj);
411✔
5110

5111
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
411✔
5112
                "protected object type must be context");
5113
}
411✔
5114

5115
vcode_reg_t emit_context_upref(int hops)
28,271✔
5116
{
5117
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
225,960✔
5118
      if (other->hops == hops)
12,565✔
5119
         return other->result;
12,489✔
5120
   }
5121

5122
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
15,782✔
5123
   op->hops = hops;
15,782✔
5124

5125
   VCODE_ASSERT(hops >= 0, "invalid hop count");
15,782✔
5126

5127
   vcode_unit_t vu = active_unit;
15,782✔
5128
   for (int i = 0; i < hops; i++) {
28,480✔
5129
      vu = vu->context;
12,698✔
5130
      VCODE_ASSERT(vu, "hop count is greater than depth");
12,698✔
5131
   }
5132

5133
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
15,782✔
5134
}
5135

5136
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
823✔
5137
                                    vcode_reg_t len)
5138
{
5139
   op_t *op = vcode_add_op(opkind);
823✔
5140
   vcode_add_arg(op, nets);
823✔
5141
   vcode_add_arg(op, len);
823✔
5142

5143
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
823✔
5144
                "argument to %s is not a signal", vcode_op_string(opkind));
5145

5146
   return (op->result = vcode_add_reg(vtype_bool()));
823✔
5147
}
5148

5149
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
530✔
5150
{
5151
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
530✔
5152
}
5153

5154
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
293✔
5155
{
5156
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
293✔
5157
}
5158

5159
vcode_reg_t emit_record_ref(vcode_reg_t record, unsigned field)
53,536✔
5160
{
5161
   // Try scanning backwards through the block for another record ref
5162
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RECORD_REF) {
3,662,034✔
5163
      if (other->args.items[0] == record && other->field == field)
687,937✔
5164
         return other->result;
5,110✔
5165
   }
5166

5167
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
48,426✔
5168
   op->field = field;
48,426✔
5169
   vcode_add_arg(op, record);
48,426✔
5170

5171
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
48,426✔
5172

5173
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
48,426✔
5174
                "argument to record ref must be a pointer");
5175

5176
   vtype_t *rtype = vcode_type_data(rptype->pointed);
48,426✔
5177
   VCODE_ASSERT(rtype->kind == VCODE_TYPE_RECORD,
48,426✔
5178
                "argument must be pointer to record or record signal");
5179

5180
   VCODE_ASSERT(field < rtype->fields.count, "invalid field %d", field);
48,426✔
5181

5182
   vcode_type_t field_type  = rtype->fields.items[field];
48,426✔
5183
   vcode_type_t bounds_type = field_type;
48,426✔
5184
   vcode_type_t result_type = field_type;
48,426✔
5185

5186
   const vtype_kind_t fkind = vtype_kind(field_type);
48,426✔
5187
   if (fkind == VCODE_TYPE_CARRAY)
48,426✔
5188
      result_type = bounds_type = vtype_elem(field_type);
6,848✔
5189
   else if (fkind == VCODE_TYPE_UARRAY) {
41,578✔
5190
      bounds_type = vtype_elem(field_type);
3,747✔
5191
      result_type = field_type;
3,747✔
5192
   }
5193

5194
   op->result = vcode_add_reg(vtype_pointer(result_type));
48,426✔
5195

5196
   reg_t *rr = vcode_reg_data(op->result);
48,426✔
5197
   rr->bounds = bounds_type;
48,426✔
5198

5199
   return op->result;
48,426✔
5200
}
5201

5202
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
51,035✔
5203
{
5204
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
2,277,886✔
5205
      if (other->args.items[0] == array && other->args.items[1] == offset)
142,521✔
5206
         return other->result;
1,762✔
5207
   }
5208

5209
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
49,273✔
5210
   vcode_add_arg(op, array);
49,273✔
5211
   vcode_add_arg(op, offset);
49,273✔
5212

5213
   vcode_type_t rtype = vcode_reg_type(array);
49,273✔
5214
   VCODE_ASSERT((vtype_kind(rtype) == VCODE_TYPE_POINTER
49,273✔
5215
                 && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY)
5216
                || vtype_kind(rtype) == VCODE_TYPE_SIGNAL,
5217
                "argument to array ref must be a pointer or signal");
5218
   VCODE_ASSERT(vcode_reg_kind(offset) == VCODE_TYPE_OFFSET,
49,273✔
5219
                "array ref offset argument must have offset type");
5220

5221
   op->result = vcode_add_reg(rtype);
49,273✔
5222

5223
   reg_t *rr = vcode_reg_data(op->result);
49,273✔
5224
   rr->bounds = vcode_reg_bounds(array);
49,273✔
5225

5226
   return op->result;
49,273✔
5227
}
5228

5229
void emit_copy(vcode_reg_t dest, vcode_reg_t src, vcode_reg_t count)
37,898✔
5230
{
5231
   int64_t cconst;
37,898✔
5232
   if (count != VCODE_INVALID_REG && vcode_reg_const(count, &cconst)
37,898✔
5233
       && cconst == 0)
24,880✔
5234
      return;
7,207✔
5235
   else if (dest == src)
36,926✔
5236
      return;
5237

5238
   op_t *op = vcode_add_op(VCODE_OP_COPY);
30,691✔
5239
   vcode_add_arg(op, dest);
30,691✔
5240
   vcode_add_arg(op, src);
30,691✔
5241
   if (count != VCODE_INVALID_REG)
30,691✔
5242
      vcode_add_arg(op, count);
28,639✔
5243

5244
   vcode_type_t dtype = vcode_reg_type(dest);
30,691✔
5245
   vcode_type_t stype = vcode_reg_type(src);
30,691✔
5246

5247
   vtype_kind_t dkind = vtype_kind(dtype);
30,691✔
5248
   vtype_kind_t skind = vtype_kind(stype);
30,691✔
5249

5250
   VCODE_ASSERT(dkind == VCODE_TYPE_POINTER || dkind == VCODE_TYPE_ACCESS,
30,691✔
5251
                "destination type is not a pointer or access");
5252
   VCODE_ASSERT(skind == VCODE_TYPE_POINTER || skind == VCODE_TYPE_ACCESS,
30,691✔
5253
                "source type is not a pointer or access");
5254
   VCODE_ASSERT(vtype_eq(dtype, stype),
30,691✔
5255
                "source and destination types do not match");
5256
   VCODE_ASSERT(count == VCODE_INVALID_REG
30,691✔
5257
                || vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5258
                "count is not offset type");
5259

5260
   op->type = vtype_pointed(dtype);
30,691✔
5261
}
5262

5263
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
7,868✔
5264
{
5265
   VCODE_FOR_EACH_OP(other) {
133,002✔
5266
      if (other->kind == VCODE_OP_CLEAR_EVENT)
125,206✔
5267
         break;
5268
      else if (other->kind == VCODE_OP_SCHED_EVENT
125,142✔
5269
               && other->args.items[0] == nets
6,509✔
5270
               && other->args.items[1] == n_elems)
12✔
5271
         return;
5272
   }
5273

5274
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
7,860✔
5275
   vcode_add_arg(op, nets);
7,860✔
5276
   vcode_add_arg(op, n_elems);
7,860✔
5277

5278
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
7,860✔
5279
                "nets argument to sched event must be signal");
5280
}
5281

5282
void emit_clear_event(vcode_reg_t nets, vcode_reg_t n_elems)
702✔
5283
{
5284
   VCODE_FOR_EACH_OP(other) {
3,223✔
5285
      if (other->kind == VCODE_OP_SCHED_EVENT)
2,521✔
5286
         break;
5287
      else if (other->kind == VCODE_OP_CLEAR_EVENT
2,521✔
5288
               && other->args.items[0] == nets
52✔
UNCOV
5289
               && other->args.items[1] == n_elems)
×
5290
         return;
5291
   }
5292

5293
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
702✔
5294
   vcode_add_arg(op, nets);
702✔
5295
   vcode_add_arg(op, n_elems);
702✔
5296

5297
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
702✔
5298
                "nets argument to clear event must be signal");
5299
}
5300

5301
void emit_resume(ident_t func)
1,089✔
5302
{
5303
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
1,089✔
5304
   op->func = func;
1,089✔
5305

5306
   block_t *b = &(active_unit->blocks.items[active_block]);
1,089✔
5307
   VCODE_ASSERT(b->ops.count == 1, "resume must be first op in a block");
1,089✔
5308
}
1,089✔
5309

5310
void emit_memset(vcode_reg_t ptr, vcode_reg_t value, vcode_reg_t len)
7,636✔
5311
{
5312
   int64_t lconst;
7,636✔
5313
   if (vcode_reg_const(len, &lconst) && lconst == 0)
7,636✔
5314
      return;
38✔
5315

5316
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
7,598✔
5317
   vcode_add_arg(op, ptr);
7,598✔
5318
   vcode_add_arg(op, value);
7,598✔
5319
   vcode_add_arg(op, len);
7,598✔
5320

5321
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
7,598✔
5322
                "target of memset must have pointer type");
5323
   VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(value)),
7,598✔
5324
                "value of memset must have scalar type");
5325
   VCODE_ASSERT(vtype_kind(vcode_reg_type(len)) == VCODE_TYPE_OFFSET,
7,598✔
5326
                "length of memset must have offset type");
5327
}
5328

5329
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
803✔
5330
               const vcode_block_t *blocks, int ncases)
5331
{
5332
   int64_t cval1, cval2;
803✔
5333
   bool is_const = vcode_reg_const(value, &cval1);
803✔
5334

5335
   for (int i = 0; i < ncases; i++) {
4,575✔
5336
      bool can_fold = false;
3,776✔
5337
      if (cases[i] == value)
3,776✔
5338
         can_fold = true;
5339
      else if (is_const && vcode_reg_const(cases[i], &cval2))
3,776✔
5340
         can_fold = (cval1 == cval2);
4✔
5341

5342
      if (can_fold) {
4✔
5343
         emit_jump(blocks[i]);
4✔
5344
         return;
8✔
5345
      }
5346
   }
5347

5348
   if (is_const) {
799✔
UNCOV
5349
      emit_jump(def);
×
UNCOV
5350
      return;
×
5351
   }
5352

5353
   op_t *op = vcode_add_op(VCODE_OP_CASE);
799✔
5354
   vcode_add_arg(op, value);
799✔
5355
   vcode_add_target(op, def);
799✔
5356

5357
   for (int i = 0; i < ncases; i++) {
4,571✔
5358
      vcode_add_arg(op, cases[i]);
3,772✔
5359
      vcode_add_target(op, blocks[i]);
3,772✔
5360

5361
#ifdef DEBUG
5362
      for (int j = 0; j < i; j++)
19,582✔
5363
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
15,810✔
5364
#endif
5365
   }
5366
}
5367

5368
void emit_file_open(vcode_reg_t file, vcode_reg_t name, vcode_reg_t length,
1,550✔
5369
                    vcode_reg_t kind, vcode_reg_t status)
5370
{
5371
   op_t *op = vcode_add_op(VCODE_OP_FILE_OPEN);
1,550✔
5372
   vcode_add_arg(op, file);
1,550✔
5373
   vcode_add_arg(op, name);
1,550✔
5374
   vcode_add_arg(op, length);
1,550✔
5375
   vcode_add_arg(op, kind);
1,550✔
5376
   if (status != VCODE_INVALID_REG)
1,550✔
5377
      vcode_add_arg(op, status);
33✔
5378

5379
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
1,550✔
5380
                "file open first argument must have file pointer type");
5381
}
1,550✔
5382

5383
void emit_file_write(vcode_reg_t file, vcode_reg_t value, vcode_reg_t length)
339✔
5384
{
5385
   op_t *op = vcode_add_op(VCODE_OP_FILE_WRITE);
339✔
5386
   vcode_add_arg(op, file);
339✔
5387
   vcode_add_arg(op, value);
339✔
5388
   if (length != VCODE_INVALID_REG)
339✔
5389
      vcode_add_arg(op, length);
263✔
5390

5391
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
339✔
5392
                "file write first argument must have file pointer type");
5393
}
339✔
5394

5395
void emit_file_read(vcode_reg_t file, vcode_reg_t ptr,
120✔
5396
                    vcode_reg_t inlen, vcode_reg_t outlen)
5397
{
5398
   op_t *op = vcode_add_op(VCODE_OP_FILE_READ);
120✔
5399
   vcode_add_arg(op, file);
120✔
5400
   vcode_add_arg(op, ptr);
120✔
5401
   if (inlen != VCODE_INVALID_REG) {
120✔
5402
      vcode_add_arg(op, inlen);
56✔
5403
      if (outlen != VCODE_INVALID_REG)
56✔
5404
         vcode_add_arg(op, outlen);
44✔
5405
   }
5406

5407
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
120✔
5408
                "file read first argument must have file pointer type");
5409
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
120✔
5410
                "file read pointer argument must have pointer type");
5411
   VCODE_ASSERT(outlen == VCODE_INVALID_REG
120✔
5412
                || vtype_kind(vcode_reg_type(outlen)) == VCODE_TYPE_POINTER,
5413
                "file read outlen argument must have pointer type");
5414
}
120✔
5415

5416
vcode_reg_t emit_null(vcode_type_t type)
16,564✔
5417
{
5418
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_NULL) {
331,799✔
5419
      if (vtype_eq(vcode_reg_type(other->result), type))
9,435✔
5420
         return other->result;
4,744✔
5421
   }
5422

5423
   op_t *op = vcode_add_op(VCODE_OP_NULL);
11,820✔
5424
   op->result = vcode_add_reg(type);
11,820✔
5425

5426
   vtype_kind_t kind = vtype_kind(type);
11,820✔
5427
   VCODE_ASSERT(kind == VCODE_TYPE_POINTER || kind == VCODE_TYPE_FILE
11,820✔
5428
                || kind == VCODE_TYPE_ACCESS || kind == VCODE_TYPE_CONTEXT,
5429
                "null type must be file, access, context, or pointer");
5430

5431
   return op->result;
5432
}
5433

5434
vcode_reg_t emit_new(vcode_type_t type, vcode_reg_t length)
854✔
5435
{
5436
   op_t *op = vcode_add_op(VCODE_OP_NEW);
854✔
5437
   if (length != VCODE_INVALID_REG)
854✔
5438
      vcode_add_arg(op, length);
736✔
5439

5440
   op->result = vcode_add_reg(vtype_access(type));
854✔
5441

5442
   vtype_kind_t kind = vtype_kind(type);
854✔
5443
   VCODE_ASSERT(kind == VCODE_TYPE_INT || kind == VCODE_TYPE_RECORD
854✔
5444
                || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_ACCESS
5445
                || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_CONTEXT,
5446
                "new type must be int, real, record, access, or uarray");
5447
   VCODE_ASSERT(length == VCODE_INVALID_REG
854✔
5448
                || vtype_kind(vcode_reg_type(length)) == VCODE_TYPE_OFFSET,
5449
                "new length must have offset type");
5450

5451
   return op->result;
854✔
5452
}
5453

5454
void emit_null_check(vcode_reg_t ptr, vcode_reg_t locus)
3,919✔
5455
{
5456
   VCODE_FOR_EACH_OP(other) {
161,625✔
5457
      if (other->kind == VCODE_OP_NULL_CHECK && other->args.items[0] == ptr)
158,724✔
5458
         return;
5459
      else if (other->kind == VCODE_OP_NEW && other->result == ptr)
158,149✔
5460
         return;
5461
   }
5462

5463
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
2,901✔
5464
   vcode_add_arg(op, ptr);
2,901✔
5465
   vcode_add_arg(op, locus);
2,901✔
5466

5467
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
2,901✔
5468
                "null check argument must be an access");
5469
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,901✔
5470
                "locus argument to null check must be a debug locus");
5471
}
5472

5473
void emit_deallocate(vcode_reg_t ptr)
459✔
5474
{
5475
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
459✔
5476
   vcode_add_arg(op, ptr);
459✔
5477

5478
   vcode_type_t ptype = vcode_reg_type(ptr);
459✔
5479
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
459✔
5480
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5481
                "deallocate argument must be pointer to access");
5482
}
459✔
5483

5484
vcode_reg_t emit_all(vcode_reg_t reg)
4,773✔
5485
{
5486
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
226,259✔
5487
      if (other->args.items[0] == reg)
13,736✔
5488
         return other->result;
1,018✔
5489
   }
5490

5491
   op_t *op = vcode_add_op(VCODE_OP_ALL);
3,755✔
5492
   vcode_add_arg(op, reg);
3,755✔
5493

5494
   vcode_type_t vtype = vcode_reg_type(reg);
3,755✔
5495

5496
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
3,755✔
5497
                "all argument must be an access");
5498

5499
   vcode_type_t pointed = vtype_pointed(vtype);
3,755✔
5500
   op->result = vcode_add_reg(vtype_pointer(pointed));
3,755✔
5501

5502
   reg_t *rr = vcode_reg_data(op->result);
3,755✔
5503
   rr->bounds = pointed;
3,755✔
5504

5505
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
3,755✔
5506
                "cannot dereference opaque type");
5507

5508
   return op->result;
5509
}
5510

5511
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
19,622✔
5512
{
5513
   block_t *b = &(active_unit->blocks.items[active_block]);
19,622✔
5514
   for (int i = b->ops.count - 1; i >= 0; i--) {
482,382✔
5515
      const op_t *other = &(b->ops.items[i]);
463,499✔
5516
      if (other->kind == kind && other->args.items[0] == sig)
463,499✔
5517
         return other->result;
739✔
5518
   }
5519

5520
   op_t *op = vcode_add_op(kind);
18,883✔
5521
   vcode_add_arg(op, sig);
18,883✔
5522

5523
   vcode_type_t stype = vcode_reg_type(sig);
18,883✔
5524
   op->type = stype;
18,883✔
5525

5526
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
18,883✔
5527
                "argument r%d to resolved is not a signal", sig);
5528

5529
   vcode_type_t rtype = vtype_base(stype);
18,883✔
5530

5531
   const vtype_kind_t rkind = vtype_kind(rtype);
18,883✔
5532
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
18,883✔
UNCOV
5533
      rtype = vtype_elem(rtype);
×
5534

5535
   VCODE_ASSERT(vtype_is_scalar(rtype),
18,883✔
5536
                "resolved signal base type must be scalar");
5537

5538
   op->result = vcode_add_reg(vtype_pointer(rtype));
18,883✔
5539

5540
   reg_t *rr = vcode_reg_data(op->result);
18,883✔
5541
   rr->bounds = rtype;
18,883✔
5542

5543
   return op->result;
18,883✔
5544
}
5545

5546
vcode_reg_t emit_resolved(vcode_reg_t sig, vcode_reg_t count)
19,397✔
5547
{
5548
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
19,397✔
5549
}
5550

5551
vcode_reg_t emit_last_value(vcode_reg_t sig, vcode_reg_t count)
225✔
5552
{
5553
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
225✔
5554
}
5555

5556
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
44✔
5557
{
5558
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
44✔
5559
   vcode_add_arg(op, signal);
44✔
5560
   if (len != VCODE_INVALID_REG)
44✔
5561
      vcode_add_arg(op, len);
12✔
5562

5563
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
44✔
5564
                "signal argument to last event must have signal type");
5565
   VCODE_ASSERT(len == VCODE_INVALID_REG
44✔
5566
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5567
                "length argument to last event must have offset type");
5568

5569
   return (op->result = vcode_add_reg(vtype_time()));
44✔
5570
}
5571

5572
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
48✔
5573
{
5574
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
48✔
5575
   vcode_add_arg(op, signal);
48✔
5576
   if (len != VCODE_INVALID_REG)
48✔
5577
      vcode_add_arg(op, len);
8✔
5578

5579
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
48✔
5580
                "signal argument to last active must have signal type");
5581
   VCODE_ASSERT(len == VCODE_INVALID_REG
48✔
5582
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5583
                "length argument to last active must have offset type");
5584

5585
   return (op->result = vcode_add_reg(vtype_time()));
48✔
5586
}
5587

5588
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
5,570✔
5589
{
5590
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
5,570✔
5591
   vcode_add_arg(op, signal);
5,570✔
5592
   vcode_add_arg(op, locus);
5,570✔
5593

5594
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
5,570✔
5595
                "signal argument must have signal type");
5596
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
5,570✔
5597
                "locus argument must have debug locus type");
5598
}
5,570✔
5599

5600
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
48✔
5601
{
5602
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
48✔
5603
   vcode_add_arg(op, signal);
48✔
5604
   vcode_add_arg(op, len);
48✔
5605

5606
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
48✔
5607
                "signal argument to last active must have signal type");
5608
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
48✔
5609
                "length argument to last active must have offset type");
5610

5611
   return (op->result = vcode_add_reg(vtype_bool()));
48✔
5612
}
5613

5614
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
152✔
5615
{
5616
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
152✔
5617
   vcode_add_arg(op, signal);
152✔
5618
   if (len != VCODE_INVALID_REG)
152✔
5619
      vcode_add_arg(op, len);
40✔
5620

5621
   vcode_type_t signal_type = vcode_reg_type(signal);
152✔
5622

5623
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
152✔
5624
                "signal argument to last active must have signal type");
5625
   VCODE_ASSERT(len == VCODE_INVALID_REG
152✔
5626
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5627
                "length argument to last active must have offset type");
5628

5629
   vcode_type_t base_type = vtype_base(signal_type);
152✔
5630
   op->result = vcode_add_reg(vtype_pointer(base_type));
152✔
5631

5632
   reg_t *rr = vcode_reg_data(op->result);
152✔
5633
   rr->bounds = base_type;
152✔
5634

5635
   return op->result;
152✔
5636
}
5637

5638
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
41,869✔
5639
                       vcode_reg_t dim)
5640
{
5641
   if (rlen == llen)
41,869✔
5642
      return;
5643

5644
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
252,562✔
5645
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
3,545✔
5646
         return;
5647
   }
5648

5649
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
9,538✔
5650
   vcode_add_arg(op, llen);
9,538✔
5651
   vcode_add_arg(op, rlen);
9,538✔
5652
   vcode_add_arg(op, locus);
9,538✔
5653
   if (dim != VCODE_INVALID_REG)
9,538✔
5654
      vcode_add_arg(op, dim);
36✔
5655

5656
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
9,538✔
5657
                "locus argument to length check must be a debug locus");
5658
}
5659

5660
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
1,062✔
5661
{
5662
   int64_t cval;
1,062✔
5663
   if (vcode_reg_const(exp, &cval) && cval >= 0)
1,062✔
5664
      return;
398✔
5665

5666
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
4,537✔
5667
      if (other->args.items[0] == exp)
16✔
5668
         return;
5669
   }
5670

5671
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
664✔
5672
   vcode_add_arg(op, exp);
664✔
5673
   vcode_add_arg(op, locus);
664✔
5674

5675
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
664✔
5676
                "exp argument to exponent check must be a integer");
5677
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
664✔
5678
                "locus argument to exponent check must be a debug locus");
5679
}
5680

5681
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
2,777✔
5682
{
5683
   int64_t cval;
2,777✔
5684
   if (vcode_reg_const(denom, &cval) && cval != 0)
2,777✔
5685
      return;
2,658✔
5686

5687
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
3,066✔
5688
      if (other->args.items[0] == denom)
64✔
5689
         return;
5690
   }
5691

5692
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
119✔
5693
   vcode_add_arg(op, denom);
119✔
5694
   vcode_add_arg(op, locus);
119✔
5695

5696
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
119✔
5697
                "denom argument to zero check must be a integer");
5698
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
119✔
5699
                "locus argument to zero check must be a debug locus");
5700
}
5701

5702
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
114,144✔
5703
                                   vcode_reg_t right, vcode_reg_t dir)
5704
{
5705
   int64_t dconst;
114,144✔
5706
   if (vcode_reg_const(dir, &dconst)) {
114,144✔
5707
      int64_t lconst, rconst;
99,742✔
5708
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
99,742✔
5709
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
65,596✔
5710
            || (dconst == RANGE_DOWNTO && rconst > lconst);
135,870✔
5711

5712
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
70,275✔
5713

5714
         const bool ok_static =
140,550✔
5715
            (dconst == RANGE_TO
5716
             && bounds->low >= lconst && bounds->high <= rconst)
65,596✔
5717
            || (dconst == RANGE_DOWNTO
12,909✔
5718
                && bounds->low >= rconst && bounds->high <= lconst)
4,679✔
5719
            || (!is_null && (reg == left || reg == right));
78,793✔
5720

5721
         return ok_static;
95,924✔
5722
      }
5723
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
29,467✔
5724
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
26,836✔
5725
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
26,836✔
5726

5727
         assert(lbounds->kind == VCODE_TYPE_REAL);
26,836✔
5728
         assert(rbounds->kind == VCODE_TYPE_REAL);
26,836✔
5729

5730
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
26,836✔
5731
         assert(bounds->kind == VCODE_TYPE_REAL);
26,836✔
5732

5733
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
26,836✔
5734
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
25,649✔
5735
            // Covers the complete double range so can never overflow
5736
            return true;
5737
         }
5738
      }
5739
   }
5740

5741
   return false;
5742
}
5743

5744
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
115,385✔
5745
                              vcode_reg_t left, vcode_reg_t right,
5746
                              vcode_reg_t dir, vcode_reg_t locus,
5747
                              vcode_reg_t hint)
5748
{
5749
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
4,677,100✔
5750
      if (other->args.items[0] == reg && other->args.items[1] == left
26,758✔
5751
          && other->args.items[2] == right && other->args.items[3] == dir)
1,435✔
5752
         return;
5753
   }
5754

5755
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
114,144✔
5756
      emit_comment("Elided bounds check for r%d", reg);
87,406✔
5757
      return;
87,406✔
5758
   }
5759

5760
   op_t *op = vcode_add_op(kind);
26,738✔
5761
   vcode_add_arg(op, reg);
26,738✔
5762
   vcode_add_arg(op, left);
26,738✔
5763
   vcode_add_arg(op, right);
26,738✔
5764
   vcode_add_arg(op, dir);
26,738✔
5765
   vcode_add_arg(op, locus);
26,738✔
5766
   vcode_add_arg(op, hint);
26,738✔
5767

5768
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
26,738✔
5769
                "locus argument to bounds check must be a debug locus");
5770
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
26,738✔
5771
                "hint argument to bounds check must be a debug locus");
5772
}
5773

5774
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
31,704✔
5775
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5776
{
5777
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
31,704✔
5778
}
31,704✔
5779

5780
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
83,681✔
5781
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5782
{
5783
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
83,681✔
5784
}
83,681✔
5785

5786
void emit_package_scope(vcode_reg_t locus)
59✔
5787
{
5788
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_SCOPE);
59✔
5789
   vcode_add_arg(op, locus);
59✔
5790

5791
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
59✔
5792
                "locus argument to package scope must be a debug locus");
5793
}
59✔
5794

5795
void emit_array_scope(vcode_reg_t locus, vcode_type_t type)
839✔
5796
{
5797
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_SCOPE);
839✔
5798
   vcode_add_arg(op, locus);
839✔
5799
   op->type = type;
839✔
5800

5801
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
839✔
5802
                "locus argument to array scope must be a debug locus");
5803
}
839✔
5804

5805
void emit_record_scope(vcode_reg_t locus, vcode_type_t type)
2,153✔
5806
{
5807
   op_t *op = vcode_add_op(VCODE_OP_RECORD_SCOPE);
2,153✔
5808
   vcode_add_arg(op, locus);
2,153✔
5809
   op->type = type;
2,153✔
5810

5811
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,153✔
5812
                "locus argument to record scope must be a debug locus");
5813
}
2,153✔
5814

5815
void emit_pop_scope(void)
3,051✔
5816
{
5817
   vcode_add_op(VCODE_OP_POP_SCOPE);
3,051✔
5818
}
3,051✔
5819

5820
vcode_reg_t emit_debug_locus(object_t *obj)
230,438✔
5821
{
5822
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
8,523,211✔
5823
      if (other->object == obj)
1,054,342✔
5824
         return other->result;
23,836✔
5825
   }
5826

5827
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
206,602✔
5828
   op->object = obj;
206,602✔
5829

5830
   return (op->result = vcode_add_reg(vtype_debug_locus()));
206,602✔
5831
}
5832

UNCOV
5833
void emit_debug_out(vcode_reg_t reg)
×
5834
{
UNCOV
5835
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
UNCOV
5836
   vcode_add_arg(op, reg);
×
UNCOV
5837
}
×
5838

5839
void emit_cover_stmt(uint32_t tag)
1,374✔
5840
{
5841
   op_t *op = vcode_add_op(VCODE_OP_COVER_STMT);
1,374✔
5842
   op->tag = tag;
1,374✔
5843
}
1,374✔
5844

5845
void emit_cover_branch(uint32_t tag)
657✔
5846
{
5847
   op_t *op = vcode_add_op(VCODE_OP_COVER_BRANCH);
657✔
5848
   op->tag = tag;
657✔
5849
}
657✔
5850

5851
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
416✔
5852
{
5853
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
416✔
5854
   vcode_add_arg(op, signal);
416✔
5855
   op->tag = tag;
416✔
5856
}
416✔
5857

5858
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
16✔
5859
{
5860
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
16✔
5861
   vcode_add_arg(op, signal);
16✔
5862
   vcode_add_arg(op, low);
16✔
5863
   op->tag = tag;
16✔
5864
}
16✔
5865

5866
void emit_cover_expr(uint32_t tag)
1,142✔
5867
{
5868
   op_t *op = vcode_add_op(VCODE_OP_COVER_EXPR);
1,142✔
5869
   op->tag = tag;
1,142✔
5870
}
1,142✔
5871

5872
void emit_unreachable(vcode_reg_t locus)
1,707✔
5873
{
5874
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
1,707✔
5875
   if (locus != VCODE_INVALID_REG)
1,707✔
5876
      vcode_add_arg(op, locus);
125✔
5877
}
1,707✔
5878

5879
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
591✔
5880
{
5881
   active_unit->flags |= UNIT_UNDEFINED;
591✔
5882

5883
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
591✔
5884
   op->result = vcode_add_reg(type);
591✔
5885
   vcode_reg_data(op->result)->bounds = bounds;
591✔
5886

5887
   return op->result;
591✔
5888
}
5889

5890
void emit_debug_info(const loc_t *loc)
3,116,075✔
5891
{
5892
   if (!loc_invalid_p(loc))
3,116,075✔
5893
      vcode_block_data()->last_loc = *loc;
3,043,480✔
5894
}
3,116,075✔
5895

5896
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
10,591✔
5897
{
5898
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
379,424✔
5899
      if (other->args.items[0] == context && other->ident == name)
15,266✔
5900
         return other->result;
4,925✔
5901
   }
5902

5903
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
5,666✔
5904
   vcode_add_arg(op, context);
5,666✔
5905
   op->ident = name;
5,666✔
5906

5907
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5,666✔
5908
                "first argument to link var must be context");
5909

5910
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
5,666✔
5911
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
104✔
5912
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
104✔
5913
   }
5914
   else {
5915
      op->result = vcode_add_reg(vtype_pointer(type));
5,562✔
5916
      vcode_reg_data(op->result)->bounds = type;
5,562✔
5917
   }
5918

5919
   return op->result;
5,666✔
5920
}
5921

5922
vcode_reg_t emit_link_package(ident_t name)
25,900✔
5923
{
5924
   VCODE_FOR_EACH_OP(other) {
826,784✔
5925
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
813,207✔
5926
         return other->result;
10,067✔
5927
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
803,140✔
5928
         return other->result;
2,256✔
5929
   }
5930

5931
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
13,577✔
5932
   op->ident = name;
13,577✔
5933

5934
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
13,577✔
5935

5936
   return (op->result = vcode_add_reg(vtype_context(name)));
13,577✔
5937
}
5938

5939
void emit_enter_state(vcode_reg_t state, vcode_reg_t strong)
1,040✔
5940
{
5941
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
2,496✔
UNCOV
5942
      if (other->args.items[0] == state)
×
5943
         return;
5944
   }
5945

5946
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
1,040✔
5947
   vcode_add_arg(op, state);
1,040✔
5948
   if (strong != VCODE_INVALID_REG)
1,040✔
5949
      vcode_add_arg(op, strong);
24✔
5950

5951
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
1,040✔
5952
                "state must have integer type");
5953
   VCODE_ASSERT(strong == VCODE_INVALID_REG
1,040✔
5954
                || vtype_eq(vcode_reg_type(strong), vtype_bool()),
5955
                "strong argument not is not boolean");
5956
}
5957

5958
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
64✔
5959
                               vcode_reg_t locus, vcode_reg_t bounds)
5960
{
5961
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
64✔
5962
   vcode_add_arg(op, value);
64✔
5963
   vcode_add_arg(op, context);
64✔
5964
   vcode_add_arg(op, locus);
64✔
5965
   if (bounds != VCODE_INVALID_REG)
64✔
5966
      vcode_add_arg(op, bounds);
8✔
5967

5968
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
64✔
5969
                "invalid reflect value context argument");
5970
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
64✔
5971
                "locus argument to reflect value must be a debug locus");
5972

5973
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
64✔
5974
}
5975

5976
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
56✔
5977
                                 vcode_reg_t bounds)
5978
{
5979
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
56✔
5980
   vcode_add_arg(op, context);
56✔
5981
   vcode_add_arg(op, locus);
56✔
5982
   if (bounds != VCODE_INVALID_REG)
56✔
UNCOV
5983
      vcode_add_arg(op, bounds);
×
5984

5985
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
56✔
5986
                "invalid reflect value context argument");
5987
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
56✔
5988
                "locus argument to reflect value must be a debug locus");
5989

5990
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
56✔
5991
}
5992

5993
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
292✔
5994
                                  int nargs)
5995
{
5996
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
292✔
5997
   op->func = func;
292✔
5998

5999
   for (int i = 0; i < nargs; i++)
772✔
6000
      vcode_add_arg(op, args[i]);
480✔
6001

6002
   return (op->result = vcode_add_reg(vtype_trigger()));
292✔
6003
}
6004

6005
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
45✔
6006
{
6007
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
45✔
6008
   vcode_add_arg(op, left);
45✔
6009
   vcode_add_arg(op, right);
45✔
6010

6011
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
45✔
6012
                "or trigger left argument must be trigger");
6013
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
45✔
6014
                "or trigger right argument must be trigger");
6015

6016
   return (op->result = vcode_add_reg(vtype_trigger()));
45✔
6017
}
6018

6019
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
87✔
6020
{
6021
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
87✔
6022
   vcode_add_arg(op, left);
87✔
6023
   vcode_add_arg(op, right);
87✔
6024

6025
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
87✔
6026
                "cmp trigger left argument must be signal");
6027
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
87✔
6028
                "cmp trigger right argument must be integer");
6029

6030
   return (op->result = vcode_add_reg(vtype_trigger()));
87✔
6031
}
6032

6033
void emit_add_trigger(vcode_reg_t trigger)
501✔
6034
{
6035
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
501✔
6036
   vcode_add_arg(op, trigger);
501✔
6037

6038
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
501✔
6039
                "add trigger argument must be trigger");
6040
}
501✔
6041

6042
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
256✔
6043
{
6044
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
256✔
6045
   vcode_add_arg(op, driving);
256✔
6046
   if (effective != VCODE_INVALID_REG && effective != driving)
256✔
6047
      vcode_add_arg(op, effective);
24✔
6048

6049
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
256✔
6050
                "port conversion argument must be a closure");
6051
   VCODE_ASSERT(effective == VCODE_INVALID_REG
256✔
6052
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
6053
                "port conversion argument must be a closure");
6054

6055
   return (op->result = vcode_add_reg(vtype_conversion()));
256✔
6056
}
6057

6058
vcode_reg_t emit_bind_external(vcode_reg_t locus, ident_t scope,
261✔
6059
                               vcode_type_t type, vcode_type_t bounds)
6060
{
6061
   op_t *op = vcode_add_op(VCODE_OP_BIND_EXTERNAL);
261✔
6062
   vcode_add_arg(op, locus);
261✔
6063
   op->type  = type;
261✔
6064
   op->ident = scope;
261✔
6065

6066
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
261✔
6067
                "bind external argument must be locus");
6068

6069
   op->result = vcode_add_reg(vtype_pointer(type));
261✔
6070
   vcode_reg_data(op->result)->bounds = bounds;
261✔
6071
   return op->result;
261✔
6072
}
6073

6074
void emit_put_conversion(vcode_reg_t cf, vcode_reg_t target, vcode_reg_t count,
440✔
6075
                         vcode_reg_t values)
6076
{
6077
   op_t *op = vcode_add_op(VCODE_OP_PUT_CONVERSION);
440✔
6078
   vcode_add_arg(op, cf);
440✔
6079
   vcode_add_arg(op, target);
440✔
6080
   vcode_add_arg(op, count);
440✔
6081
   vcode_add_arg(op, values);
440✔
6082

6083
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
440✔
6084
                "put conversion target is not signal");
6085
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
440✔
6086
                "put conversion net count is not offset type");
6087
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
440✔
6088
                "signal cannot be values argument for put conversion");
6089
   VCODE_ASSERT(vcode_reg_kind(cf) == VCODE_TYPE_CONVERSION,
440✔
6090
                "cf argument to put conversion must be conversion function");
6091
}
440✔
6092

6093
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
360✔
6094
{
6095
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
360✔
6096
   vcode_add_arg(op, conv);
360✔
6097
   vcode_add_arg(op, nets);
360✔
6098
   vcode_add_arg(op, count);
360✔
6099

6100
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
360✔
6101
                "conv argument to convert must be a port conversion");
6102
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
360✔
6103
                "nets argument to convert must be a signal");
6104
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
360✔
6105
                "count argument to convert must be offset");
6106
}
360✔
6107

6108
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
416✔
6109
{
6110
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
416✔
6111
   vcode_add_arg(op, conv);
416✔
6112
   vcode_add_arg(op, nets);
416✔
6113
   vcode_add_arg(op, count);
416✔
6114

6115
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
416✔
6116
                "conv argument to convert must be a port conversion");
6117
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
416✔
6118
                "nets argument to convert must be a signal");
6119
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
416✔
6120
                "count argument to convert must be offset");
6121
}
416✔
6122

6123
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
1,294✔
6124
{
6125
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
1,294✔
6126
   vcode_add_arg(op, spec);
1,294✔
6127
   vcode_add_arg(op, length);
1,294✔
6128
   if (locus != VCODE_INVALID_REG)
1,294✔
6129
      vcode_add_arg(op, locus);
1,062✔
6130

6131
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
1,294✔
6132
                "spec argument to bind foreign must be a pointer");
6133
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
1,294✔
6134
                "length argument to bind foreign must be offset");
6135
   VCODE_ASSERT(locus == VCODE_INVALID_REG
1,294✔
6136
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6137
                "locus argument to bind foreign value must be a debug locus");
6138
}
1,294✔
6139

6140
vcode_reg_t emit_instance_name(vcode_reg_t kind)
1,018✔
6141
{
6142
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
1,018✔
6143
   vcode_add_arg(op, kind);
1,018✔
6144

6145
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
1,018✔
6146
                "kind argument to instance name must be offset");
6147

6148
   vcode_type_t vchar = vtype_char();
1,018✔
6149
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
1,018✔
6150
}
6151

UNCOV
6152
void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count,
×
6153
                         vcode_reg_t values)
6154
{
UNCOV
6155
   op_t *op = vcode_add_op(VCODE_OP_DEPOSIT_SIGNAL);
×
UNCOV
6156
   vcode_add_arg(op, signal);
×
UNCOV
6157
   vcode_add_arg(op, count);
×
UNCOV
6158
   vcode_add_arg(op, values);
×
6159

UNCOV
6160
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
×
6161
                "deposit signal target is not signal");
UNCOV
6162
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
×
6163
                "deposit signal count is not offset type");
UNCOV
6164
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
×
6165
                "signal cannot be values argument for deposit signal");
UNCOV
6166
}
×
6167

6168
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
20,934✔
6169
{
6170
   vcode_state_t state;
20,934✔
6171
   vcode_state_save(&state);
20,934✔
6172

6173
   vcode_select_unit(vu);
20,934✔
6174

6175
   const int nblocks = vcode_count_blocks();
20,934✔
6176
   for (int i = 0; i < nblocks; i++) {
75,760✔
6177
      vcode_select_block(i);
54,826✔
6178

6179
      const int nops = vcode_count_ops();
54,826✔
6180
      for (int op = 0; op < nops; op++) {
867,580✔
6181
         switch (vcode_get_op(op)) {
812,754✔
6182
         case VCODE_OP_LINK_PACKAGE:
4,965✔
6183
            (*fn)(vcode_get_ident(op), ctx);
4,965✔
6184
            break;
4,965✔
6185
         case VCODE_OP_FCALL:
36,209✔
6186
         case VCODE_OP_PCALL:
6187
         case VCODE_OP_CLOSURE:
6188
         case VCODE_OP_PROTECTED_INIT:
6189
         case VCODE_OP_PACKAGE_INIT:
6190
         case VCODE_OP_FUNCTION_TRIGGER:
6191
            (*fn)(vcode_get_func(op), ctx);
36,209✔
6192
            break;
36,209✔
6193
         default:
6194
            break;
6195
         }
6196
      }
6197
   }
6198

6199
   vcode_state_restore(&state);
20,934✔
6200
}
20,934✔
6201

6202
#if VCODE_CHECK_UNIONS
6203
#define OP_USE_COUNT_U0(x)                                              \
6204
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6205
#define OP_USE_COUNT_U1(x)                                              \
6206
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6207
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6208
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6209

6210
__attribute__((constructor))
6211
static void vcode_check_unions(void)
6212
{
6213
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6214
   for (int i = 0; i < 256; i++) {
6215
      assert(OP_USE_COUNT_U0(i) <= 1);
6216
      assert(OP_USE_COUNT_U1(i) <= 1);
6217
   }
6218
}
6219
#endif  // VCODE_CHECK_UNIONS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc