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

nickg / nvc / 9963260920

16 Jul 2024 07:57PM UTC coverage: 91.551% (-0.03%) from 91.579%
9963260920

Pull #918

github

web-flow
Merge 6ebfc99d4 into 457a93782
Pull Request #918: Cover items to counters

439 of 468 new or added lines in 8 files covered. (93.8%)

98 existing lines in 4 files now uncovered.

56858 of 62105 relevant lines covered (91.55%)

674219.12 hits per line

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

96.47
/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);
8,114,702✔
36
DECLARE_AND_DEFINE_ARRAY(vcode_block);
374,400✔
37
DECLARE_AND_DEFINE_ARRAY(vcode_type);
250,617✔
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 || x == VCODE_OP_CLOSURE              \
43
    || x == VCODE_OP_PUSH_SCOPE)
44
#define OP_HAS_ADDRESS(x)                                               \
45
   (x == VCODE_OP_LOAD || x == VCODE_OP_STORE || x == VCODE_OP_INDEX    \
46
    || x == VCODE_OP_VAR_UPREF)
47
#define OP_HAS_FUNC(x)                                                  \
48
   (x == VCODE_OP_FCALL || x == VCODE_OP_PCALL || x == VCODE_OP_RESUME  \
49
    || x == VCODE_OP_CLOSURE || x == VCODE_OP_PROTECTED_INIT            \
50
    || x == VCODE_OP_PACKAGE_INIT || x == VCODE_OP_PROCESS_INIT \
51
    || x == VCODE_OP_FUNCTION_TRIGGER)
52
#define OP_HAS_IDENT(x)                                                 \
53
   (x == VCODE_OP_LINK_VAR || x == VCODE_OP_LINK_PACKAGE                \
54
    || x == VCODE_OP_DEBUG_LOCUS || x == VCODE_OP_LINK_INSTANCE)
55
#define OP_HAS_REAL(x)                                                  \
56
   (x == VCODE_OP_CONST_REAL)
57
#define OP_HAS_VALUE(x)                                                 \
58
   (x == VCODE_OP_CONST || x == VCODE_OP_CONST_REP                      \
59
    || x == VCODE_OP_DEBUG_LOCUS)
60
#define OP_HAS_DIM(x)                                                   \
61
   (x == VCODE_OP_UARRAY_LEFT || x == VCODE_OP_UARRAY_RIGHT             \
62
    || x == VCODE_OP_UARRAY_DIR || x == VCODE_OP_UARRAY_LEN)
63
#define OP_HAS_HOPS(x)                                                  \
64
   (x == VCODE_OP_VAR_UPREF || x == VCODE_OP_CONTEXT_UPREF)
65
#define OP_HAS_FIELD(x)                                                 \
66
   (x == VCODE_OP_RECORD_REF)
67
#define OP_HAS_CMP(x)                                                   \
68
   (x == VCODE_OP_CMP)
69
#define OP_HAS_TAG(x)                                                   \
70
   (x == VCODE_OP_COVER_INCREMENT || x == VCODE_OP_COVER_TOGGLE         \
71
    || x == VCODE_OP_COVER_STATE)
72
#define OP_HAS_COMMENT(x)                                               \
73
   (x == VCODE_OP_COMMENT)
74
#define OP_HAS_TARGET(x)                                                \
75
   (x == VCODE_OP_WAIT || x == VCODE_OP_JUMP || x == VCODE_OP_COND      \
76
    || x == VCODE_OP_PCALL || x == VCODE_OP_CASE)
77

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

102
DECLARE_AND_DEFINE_ARRAY(op);
12,271,488✔
103

104
typedef struct {
105
   op_array_t ops;
106
   loc_t      last_loc;
107
} block_t;
108

109
typedef struct {
110
   vcode_type_t type;
111
   vcode_type_t bounds;
112
} reg_t;
113

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

141
typedef struct {
142
   vcode_type_t      type;
143
   vcode_type_t      bounds;
144
   ident_t           name;
145
   vcode_var_flags_t flags;
146
} var_t;
147

148
typedef struct {
149
   vcode_type_t type;
150
   vcode_type_t bounds;
151
   ident_t      name;
152
   vcode_reg_t  reg;
153
} param_t;
154

155
DECLARE_AND_DEFINE_ARRAY(param);
30,279✔
156
DECLARE_AND_DEFINE_ARRAY(var);
364,864✔
157
DECLARE_AND_DEFINE_ARRAY(reg);
7,727,470✔
158
DECLARE_AND_DEFINE_ARRAY(block);
131,444✔
159
DECLARE_AND_DEFINE_ARRAY(vtype);
70,700,183✔
160

161
typedef enum {
162
   UNIT_UNDEFINED     = (1 << 1),
163
   UNIT_ESCAPING_TLAB = (1 << 2)
164
} unit_flags_t;
165

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

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

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

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

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

209
#define VCODE_CHECK_UNIONS 0
210

211
static __thread vcode_unit_t  active_unit  = NULL;
212
static __thread vcode_block_t active_block = VCODE_INVALID_BLOCK;
213

214
static inline int64_t sadd64(int64_t a, int64_t b)
30,258✔
215
{
216
   int64_t result;
30,258✔
217
   if (__builtin_add_overflow(a, b, &result))
30,258✔
218
      return b < 0 ? INT64_MIN : INT64_MAX;
11,580✔
219

220
   return result;
221
}
222

223
static inline int64_t ssub64(int64_t a, int64_t b)
44,688✔
224
{
225
   int64_t result;
44,688✔
226
   if (__builtin_sub_overflow(a, b, &result))
44,688✔
227
      return b > 0 ? INT64_MIN : INT64_MAX;
4,229✔
228

229
   return result;
230
}
231

232
static inline int64_t smul64(int64_t a, int64_t b)
8,636✔
233
{
234
   int64_t result;
8,636✔
235
   if (__builtin_mul_overflow(a, b, &result))
8,636✔
236
      return (a > 0 && b > 0) || (a < 0 && b < 0) ? INT64_MAX : INT64_MIN;
4,325✔
237

238
   return result;
239
}
240

241
static vcode_reg_t vcode_add_reg(vcode_type_t type)
1,242,330✔
242
{
243
   assert(active_unit != NULL);
1,242,330✔
244

245
   vcode_reg_t reg = active_unit->regs.count;
1,242,330✔
246
   reg_t *r = reg_array_alloc(&(active_unit->regs));
1,242,330✔
247
   memset(r, '\0', sizeof(reg_t));
1,242,330✔
248
   r->type   = type;
1,242,330✔
249
   r->bounds = type;
1,242,330✔
250

251
   return reg;
1,242,330✔
252
}
253

254
static block_t *vcode_block_data(void)
5,562,352✔
255
{
256
   assert(active_unit != NULL);
5,562,352✔
257
   assert(active_block != -1);
5,562,352✔
258
   return &(active_unit->blocks.items[active_block]);
5,562,352✔
259
}
260

261
static op_t *vcode_add_op(vcode_op_t kind)
1,568,246✔
262
{
263
   assert(active_unit != NULL);
1,568,246✔
264
   assert(active_block != VCODE_INVALID_BLOCK);
1,568,246✔
265

266
   VCODE_ASSERT(
1,568,246✔
267
      !vcode_block_finished(),
268
      "attempt to add to already finished block %d", active_block);
269

270
   block_t *block = vcode_block_data();
1,568,246✔
271

272
   op_t *op = op_array_alloc(&(block->ops));
1,568,246✔
273
   memset(op, '\0', sizeof(op_t));
1,568,246✔
274
   op->kind   = kind;
1,568,246✔
275
   op->result = VCODE_INVALID_REG;
1,568,246✔
276
   op->loc    = block->last_loc;
1,568,246✔
277

278
   return op;
1,568,246✔
279
}
280

281
static void vcode_add_arg(op_t *op, vcode_reg_t arg)
2,632,932✔
282
{
283
   vcode_reg_array_add(&(op->args), arg);
2,632,932✔
284
}
2,632,932✔
285

286
static void vcode_add_target(op_t *op, vcode_block_t block)
117,010✔
287
{
288
   vcode_block_array_add(&(op->targets), block);
117,010✔
289
}
117,010✔
290

291
static op_t *vcode_op_data(int op)
10,703,242✔
292
{
293
   assert(active_unit != NULL);
10,703,242✔
294
   assert(active_block != VCODE_INVALID_BLOCK);
10,703,242✔
295

296
   block_t *b = &(active_unit->blocks.items[active_block]);
10,703,242✔
297
   return op_array_nth_ptr(&(b->ops), op);
10,703,242✔
298
}
299

300
static op_t *vcode_find_definition(vcode_reg_t reg)
1,175,686✔
301
{
302
   for (int i = active_block; i >= 0; i--) {
1,224,852✔
303
      block_t *b = &(active_unit->blocks.items[i]);
1,221,884✔
304
      for (int j = b->ops.count - 1; j >= 0; j--) {
15,629,452✔
305
         if (b->ops.items[j].result == reg)
15,580,286✔
306
            return &(b->ops.items[j]);
1,172,718✔
307
      }
308
   }
309

310
   return NULL;
311
}
312

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

330
static reg_t *vcode_reg_data(vcode_reg_t reg)
6,485,140✔
331
{
332
   assert(active_unit != NULL);
6,485,140✔
333
   assert(reg != VCODE_INVALID_REG);
6,485,140✔
334
   return reg_array_nth_ptr(&(active_unit->regs), reg);
6,485,140✔
335
}
336

337
static vtype_t *vcode_type_data(vcode_type_t type)
68,262,242✔
338
{
339
   assert(type != VCODE_INVALID_TYPE);
68,262,242✔
340
   assert(active_unit != NULL);
68,262,242✔
341
   vcode_unit_t unit = active_unit;
68,262,242✔
342

343
   int depth = MASK_CONTEXT(type);
68,262,242✔
344
   assert(depth <= unit->depth);
68,262,242✔
345
   while (depth != unit->depth)
69,814,297✔
346
      unit = unit->context;
1,552,055✔
347

348
   return vtype_array_nth_ptr(&(unit->types), MASK_INDEX(type));
68,262,242✔
349
}
350

351
static var_t *vcode_var_data(vcode_var_t var)
318,648✔
352
{
353
   assert(active_unit != NULL);
318,648✔
354
   assert(var != VCODE_INVALID_VAR);
318,648✔
355

356
   return var_array_nth_ptr(&(active_unit->vars), var);
318,648✔
357
}
358

359
void vcode_heap_allocate(vcode_reg_t reg)
19,970✔
360
{
361
   op_t *defn = vcode_find_definition(reg);
28,803✔
362
   if (defn == NULL) {
28,803✔
363
      // It is always safe to return a pointer to an argument
364
      return;
365
   }
366

367
   switch (defn->kind) {
25,835✔
368
   case VCODE_OP_CONST:
369
   case VCODE_OP_CONST_REAL:
370
   case VCODE_OP_CONST_ARRAY:
371
   case VCODE_OP_CONST_REP:
372
   case VCODE_OP_NULL:
373
   case VCODE_OP_UNDEFINED:
374
   case VCODE_OP_ADDRESS_OF:
375
   case VCODE_OP_LINK_VAR:
376
   case VCODE_OP_LINK_PACKAGE:
377
   case VCODE_OP_CONTEXT_UPREF:
378
   case VCODE_OP_PACKAGE_INIT:
379
      break;
380

381
   case VCODE_OP_ALLOC:
382
   case VCODE_OP_REFLECT_SUBTYPE:
383
   case VCODE_OP_REFLECT_VALUE:
384
      // Always allocated in mspace
385
      break;
386

387
   case VCODE_OP_INDEX:
1,006✔
388
      vcode_var_data(defn->address)->flags |= VAR_HEAP;
1,006✔
389
      active_unit->flags |= UNIT_ESCAPING_TLAB;
1,006✔
390
      break;
1,006✔
391

392
   case VCODE_OP_VAR_UPREF:
736✔
393
      {
394
         vcode_unit_t vu = vcode_active_unit();
736✔
395
         for (int i = 0; i < defn->hops; i++)
1,472✔
396
            vu = vcode_unit_context(vu);
736✔
397

398
         vcode_state_t state;
736✔
399
         vcode_state_save(&state);
736✔
400

401
         vcode_select_unit(vu);
736✔
402

403
         vcode_var_data(defn->address)->flags |= VAR_HEAP;
736✔
404
         active_unit->flags |= UNIT_ESCAPING_TLAB;
736✔
405

406
         vcode_state_restore(&state);
736✔
407
      }
408
      break;
736✔
409

410
   case VCODE_OP_ARRAY_REF:
147✔
411
      vcode_heap_allocate(defn->args.items[0]);
147✔
412
      break;
147✔
413

414
   case VCODE_OP_WRAP:
7,973✔
415
   case VCODE_OP_UNWRAP:
416
   case VCODE_OP_RESOLVED:
417
      vcode_heap_allocate(defn->args.items[0]);
7,973✔
418
      break;
7,973✔
419

420
   case VCODE_OP_LAST_VALUE:
421
      // Returns a pointer into the C heap
422
      break;
423

424
   case VCODE_OP_LOAD:
1,919✔
425
      {
426
         if (vcode_reg_kind(reg) != VCODE_TYPE_UARRAY)
1,919✔
427
            return;
428

429
         // Any store to this variable must be heap allocated
430
         for (int i = 0; i < active_unit->blocks.count; i++) {
22,270✔
431
            block_t *b = &(active_unit->blocks.items[i]);
20,594✔
432
            for (int j = 0; j < b->ops.count; j++) {
283,883✔
433
               op_t *op = &(b->ops.items[j]);
263,289✔
434
               if (op->kind == VCODE_OP_STORE && op->address == defn->address)
263,289✔
435
                  vcode_heap_allocate(op->args.items[0]);
1,676✔
436

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

445
   case VCODE_OP_FCALL:
446
      for (int i = 0; i < defn->args.count; i++) {
11,350✔
447
         const vtype_kind_t rkind = vcode_reg_kind(reg);
8,623✔
448
         if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
8,623✔
449
            // Function may return a pointer to its argument
450
            vcode_heap_allocate(defn->args.items[i]);
8,411✔
451
         }
452
      }
453
      break;
454

455
   case VCODE_OP_RECORD_REF:
24✔
456
      vcode_heap_allocate(defn->args.items[0]);
24✔
457
      break;
24✔
458

459
   case VCODE_OP_SELECT:
516✔
460
      vcode_heap_allocate(defn->args.items[1]);
516✔
461
      vcode_heap_allocate(defn->args.items[2]);
516✔
462
      break;
516✔
463

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

473
   case VCODE_OP_ALL:
474
      // Must have been allocated on the heap
475
      break;
476

477
   case VCODE_OP_NEW:
478
      // On the heap by definition
479
      break;
480

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

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

519
void vcode_state_save(vcode_state_t *state)
84,858✔
520
{
521
   state->unit  = active_unit;
84,858✔
522
   state->block = active_block;
84,858✔
523
}
84,858✔
524

525
void vcode_state_restore(const vcode_state_t *state)
84,858✔
526
{
527
   active_unit  = state->unit;
84,858✔
528
   active_block = state->block;
84,858✔
529
}
84,858✔
530

531
void vcode_unit_unref(vcode_unit_t unit)
41,905✔
532
{
533
   assert(unit != NULL);
41,905✔
534

535
   if (unit == active_unit)
41,905✔
536
      vcode_close();
11,646✔
537

538
   for (vcode_unit_t it = unit->children; it != NULL; it = it->next) {
54,195✔
539
      assert(it->context == unit);
12,290✔
540
      it->context = NULL;
12,290✔
541
   }
542
   unit->children = NULL;
41,905✔
543

544
   if (unit->context != NULL) {
41,905✔
545
      vcode_unit_t *it = &(unit->context->children);
13,834✔
546
      for (; *it != NULL && *it != unit; it = &((*it)->next))
285,165✔
547
         ;
548
      assert(*it != NULL);
13,834✔
549
      *it = (*it)->next;
13,834✔
550
   }
551

552
   for (unsigned i = 0; i < unit->blocks.count; i++) {
173,328✔
553
      block_t *b = &(unit->blocks.items[i]);
131,423✔
554

555
      for (unsigned j = 0; j < b->ops.count; j++) {
1,626,629✔
556
         op_t *o = &(b->ops.items[j]);
1,495,206✔
557
         if (OP_HAS_COMMENT(o->kind))
1,495,206✔
558
            free(o->comment);
116,429✔
559
         if (OP_HAS_TARGET(o->kind))
1,495,206✔
560
            free(o->targets.items);
80,625✔
561
         free(o->args.items);
1,495,206✔
562
      }
563
      free(b->ops.items);
131,423✔
564
   }
565
   free(unit->blocks.items);
41,905✔
566

567
   for (unsigned i = 0; i < unit->types.count; i++) {
550,332✔
568
      vtype_t *vt = &(unit->types.items[i]);
508,427✔
569
      if (vt->kind == VCODE_TYPE_RECORD)
508,427✔
570
         free(vt->fields.items);
5,223✔
571
   }
572
   free(unit->types.items);
41,905✔
573

574
   free(unit->regs.items);
41,905✔
575
   free(unit->vars.items);
41,905✔
576
   free(unit->params.items);
41,905✔
577
   free(unit);
41,905✔
578
}
41,905✔
579

580
vcode_unit_t vcode_unit_next(vcode_unit_t unit)
23,007✔
581
{
582
   return unit->next;
23,007✔
583
}
584

585
vcode_unit_t vcode_unit_child(vcode_unit_t unit)
20,948✔
586
{
587
   return unit->children;
20,948✔
588
}
589

590
int vcode_count_regs(void)
39,745✔
591
{
592
   assert(active_unit != NULL);
39,745✔
593
   return active_unit->regs.count;
39,745✔
594
}
595

596
vcode_type_t vcode_reg_type(vcode_reg_t reg)
4,479,448✔
597
{
598
   return vcode_reg_data(reg)->type;
4,479,448✔
599
}
600

601
vtype_kind_t vcode_reg_kind(vcode_reg_t reg)
1,110,090✔
602
{
603
   return vtype_kind(vcode_reg_type(reg));
1,110,090✔
604
}
605

606
vcode_type_t vcode_reg_bounds(vcode_reg_t reg)
210,210✔
607
{
608
   return vcode_reg_data(reg)->bounds;
210,210✔
609
}
610

611
bool vcode_reg_const(vcode_reg_t reg, int64_t *value)
680,652✔
612
{
613
   reg_t *r = vcode_reg_data(reg);
680,652✔
614

615
   vtype_kind_t kind = vtype_kind(r->type);
680,652✔
616
   if (kind != VCODE_TYPE_INT && kind != VCODE_TYPE_OFFSET)
680,652✔
617
      return false;
618

619
   vtype_t *bounds = vcode_type_data(r->bounds);
663,743✔
620

621
   VCODE_ASSERT(
663,743✔
622
      bounds->kind == VCODE_TYPE_INT || bounds->kind == VCODE_TYPE_OFFSET,
623
      "integer register r%d has non-integer bounds", reg);
624

625
   if (bounds->low == bounds->high) {
663,743✔
626
      if (value) *value = bounds->low;
351,310✔
627
      return true;
351,310✔
628
   }
629
   else
630
      return false;
631
}
632

633
void vcode_opt(void)
41,914✔
634
{
635
   // Prune assignments to unused registers
636

637
   int *uses LOCAL = xmalloc_array(active_unit->regs.count, sizeof(int));
83,828✔
638

639
   int pruned = 0;
41,914✔
640
   do {
56,814✔
641
      memset(uses, '\0', active_unit->regs.count * sizeof(int));
56,814✔
642
      pruned = 0;
56,814✔
643

644
      for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
269,878✔
645
         block_t *b = &(active_unit->blocks.items[i]);
213,064✔
646

647
         for (int j = b->ops.count - 1; j >= 0; j--) {
2,957,752✔
648
            op_t *o = &(b->ops.items[j]);
2,744,688✔
649

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

712
            default:
713
               break;
714
            }
715

716
            for (int k = 0; k < o->args.count; k++) {
7,466,954✔
717
               if (o->args.items[k] != VCODE_INVALID_REG)
4,722,266✔
718
                  uses[o->args.items[k]]++;
4,679,311✔
719
            }
720
         }
721
      }
722
   } while (pruned > 0);
56,814✔
723

724
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
173,358✔
725
      block_t *b = &(active_unit->blocks.items[i]);
131,444✔
726
      op_t *dst = &(b->ops.items[0]);
131,444✔
727
      size_t copied = 0;
131,444✔
728
      for (int j = 0; j < b->ops.count; j++) {
1,699,690✔
729
         const op_t *src = &(b->ops.items[j]);
1,568,246✔
730
         if (src->kind != (vcode_op_t)-1) {
1,568,246✔
731
            if (src != dst) {
1,495,572✔
732
               assert(dst < src);
412,131✔
733
               *dst = *src;
412,131✔
734
            }
735
            dst++;
1,495,572✔
736
            copied++;
1,495,572✔
737
         }
738
      }
739

740
      assert(copied <= b->ops.count);
131,444✔
741
      b->ops.count = copied;
131,444✔
742
   }
743
}
41,914✔
744

745
void vcode_close(void)
29,306✔
746
{
747
   active_unit  = NULL;
29,306✔
748
   active_block = -1;
29,306✔
749
}
29,306✔
750

751
int vcode_count_blocks(void)
111,261✔
752
{
753
   assert(active_unit != NULL);
111,261✔
754
   return active_unit->blocks.count;
111,261✔
755
}
756

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

764
int vcode_count_vars(void)
79,502✔
765
{
766
   assert(active_unit != NULL);
79,502✔
767
   return active_unit->vars.count;
79,502✔
768
}
769

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

778
   return VCODE_INVALID_VAR;
779
}
780

781
ident_t vcode_var_name(vcode_var_t var)
36,259✔
782
{
783
   return vcode_var_data(var)->name;
36,259✔
784
}
785

786
vcode_type_t vcode_var_type(vcode_var_t var)
138,573✔
787
{
788
   return vcode_var_data(var)->type;
138,573✔
789
}
790

791
vcode_type_t vcode_var_bounds(vcode_var_t var)
3,651✔
792
{
793
   return vcode_var_data(var)->bounds;
3,651✔
794
}
795

796
vcode_var_flags_t vcode_var_flags(vcode_var_t var)
35,854✔
797
{
798
   return vcode_var_data(var)->flags;
35,854✔
799
}
800

801
vcode_op_t vcode_get_op(int op)
4,299,763✔
802
{
803
   return vcode_op_data(op)->kind;
4,299,763✔
804
}
805

806
ident_t vcode_get_func(int op)
103,269✔
807
{
808
   op_t *o = vcode_op_data(op);
103,269✔
809
   assert(OP_HAS_FUNC(o->kind));
103,269✔
810
   return o->func;
103,269✔
811
}
812

813
ident_t vcode_get_ident(int op)
84,145✔
814
{
815
   op_t *o = vcode_op_data(op);
84,145✔
816
   assert(OP_HAS_IDENT(o->kind));
84,145✔
817
   return o->ident;
84,145✔
818
}
819

820
int64_t vcode_get_value(int op)
363,608✔
821
{
822
   op_t *o = vcode_op_data(op);
363,608✔
823
   assert(OP_HAS_VALUE(o->kind));
363,608✔
824
   return o->value;
363,608✔
825
}
826

827
double vcode_get_real(int op)
20,680✔
828
{
829
   op_t *o = vcode_op_data(op);
20,680✔
830
   assert(OP_HAS_REAL(o->kind));
20,680✔
831
   return o->real;
20,680✔
832
}
833

834
vcode_var_t vcode_get_address(int op)
140,342✔
835
{
836
   op_t *o = vcode_op_data(op);
140,342✔
837
   assert(OP_HAS_ADDRESS(o->kind));
140,342✔
838
   return o->address;
140,342✔
839
}
840

841
unsigned vcode_get_dim(int op)
68,423✔
842
{
843
   op_t *o = vcode_op_data(op);
68,423✔
844
   assert(OP_HAS_DIM(o->kind));
68,423✔
845
   return o->dim;
68,423✔
846
}
847

848
int vcode_get_hops(int op)
57,220✔
849
{
850
   op_t *o = vcode_op_data(op);
57,220✔
851
   assert(OP_HAS_HOPS(o->kind));
57,220✔
852
   return o->hops;
57,220✔
853
}
854

855
int vcode_get_field(int op)
34,429✔
856
{
857
   op_t *o = vcode_op_data(op);
34,429✔
858
   assert(OP_HAS_FIELD(o->kind));
34,429✔
859
   return o->field;
34,429✔
860
}
861

862
vcode_var_t vcode_get_type(int op)
17,231✔
863
{
864
   op_t *o = vcode_op_data(op);
17,231✔
865
   assert(OP_HAS_TYPE(o->kind));
17,231✔
866
   return o->type;
17,231✔
867
}
868

869
int vcode_count_args(int op)
181,934✔
870
{
871
   return vcode_op_data(op)->args.count;
181,934✔
872
}
873

874
vcode_reg_t vcode_get_arg(int op, int arg)
2,701,827✔
875
{
876
   op_t *o = vcode_op_data(op);
2,701,827✔
877
   return vcode_reg_array_nth(&(o->args), arg);
2,701,827✔
878
}
879

880
vcode_reg_t vcode_get_result(int op)
1,079,824✔
881
{
882
   op_t *o = vcode_op_data(op);
1,079,824✔
883
   return o->result;
1,079,824✔
884
}
885

886
vcode_cmp_t vcode_get_cmp(int op)
32,272✔
887
{
888
   op_t *o = vcode_op_data(op);
32,272✔
889
   assert(OP_HAS_CMP(o->kind));
32,272✔
890
   return o->cmp;
32,272✔
891
}
892

893
uint32_t vcode_get_tag(int op)
2,397✔
894
{
895
   op_t *o = vcode_op_data(op);
2,397✔
896
   assert(OP_HAS_TAG(o->kind));
2,397✔
897
   return o->tag;
2,397✔
898
}
899

900
const loc_t *vcode_get_loc(int op)
1,377,052✔
901
{
902
   op_t *o = vcode_op_data(op);
1,377,052✔
903
   return &(o->loc);
1,377,052✔
904
}
905

906
vcode_block_t vcode_get_target(int op, int nth)
138,826✔
907
{
908
   op_t *o = vcode_op_data(op);
138,826✔
909
   assert(OP_HAS_TARGET(o->kind));
138,826✔
910
   return vcode_block_array_nth(&(o->targets), nth);
138,826✔
911
}
912

UNCOV
913
bool vcode_block_empty(void)
×
914
{
UNCOV
915
   assert(active_unit != NULL);
×
916
   assert(active_block != VCODE_INVALID_BLOCK);
×
917

UNCOV
918
   return active_unit->blocks.items[active_block].ops.count == 0;
×
919
}
920

921
bool vcode_block_finished(void)
1,669,424✔
922
{
923
   assert(active_unit != NULL);
1,669,424✔
924
   assert(active_block != VCODE_INVALID_BLOCK);
1,669,424✔
925

926
   const block_t *b = &(active_unit->blocks.items[active_block]);
1,669,424✔
927
   if (b->ops.count == 0)
1,669,424✔
928
      return false;
929
   else {
930
      vcode_op_t kind = b->ops.items[b->ops.count - 1].kind;
1,495,552✔
931
      return kind == VCODE_OP_WAIT || kind == VCODE_OP_JUMP
1,495,552✔
932
         || kind == VCODE_OP_COND || kind == VCODE_OP_PCALL
1,495,423✔
933
         || kind == VCODE_OP_RETURN || kind == VCODE_OP_CASE
934
         || kind == VCODE_OP_UNREACHABLE;
2,990,975✔
935
   }
936
}
937

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

974
LCOV_EXCL_START
975
static int vcode_dump_reg(vcode_reg_t reg)
976
{
977
   if (reg == VCODE_INVALID_REG)
978
      return color_printf("$red$invalid$$");
979
   else
980
      return color_printf("$green$r%d$$", reg);
981
}
982

983
static int vcode_pretty_print_int(int64_t n)
984
{
985
   if (n == INT64_MAX)
986
      return printf("2^63-1");
987
   else if (n == INT64_MIN)
988
      return printf("-2^63");
989
   else if (n == INT32_MAX)
990
      return printf("2^31-1");
991
   else if (n == INT32_MIN)
992
      return printf("-2^31");
993
   else
994
      return printf("%"PRIi64, n);
995
}
996

997
static int vcode_dump_one_type(vcode_type_t type)
998
{
999
   int col = 0;
1000
   vtype_t *vt = vcode_type_data(type);
1001
   switch (vt->kind) {
1002
   case VCODE_TYPE_INT:
1003
      if (vt->low != vt->high) {
1004
         col += vcode_pretty_print_int(vt->low);
1005
         col += printf("..");
1006
         col += vcode_pretty_print_int(vt->high);
1007
      }
1008
      else
1009
         col += vcode_pretty_print_int(vt->low);
1010
      break;
1011

1012
   case VCODE_TYPE_REAL:
1013
      if (vt->rlow == -DBL_MAX && vt->rhigh == DBL_MAX)
1014
         col += printf("%%");
1015
      else if (vt->rlow == vt->rhigh)
1016
         col += printf("%f", vt->rlow);
1017
      else
1018
         col += printf("%f..%f", vt->rlow, vt->rhigh);
1019
      break;
1020

1021
   case VCODE_TYPE_CARRAY:
1022
      {
1023
         col += printf("[%u] : ", vt->size);
1024
         col += vcode_dump_one_type(vt->elem);
1025
         if (!vtype_eq(vt->elem, vt->bounds)) {
1026
            col += printf(" => ");
1027
            col += vcode_dump_one_type(vt->bounds);
1028
         }
1029
      }
1030
      break;
1031

1032
   case VCODE_TYPE_UARRAY:
1033
      {
1034
         col += printf("[");
1035
         for (unsigned i = 0; i < vt->dims; i++)
1036
            col += printf("%s*", i > 0 ? ", " : "");
1037
         col += printf("] : ");
1038
         col += vcode_dump_one_type(vt->elem);
1039
         if (!vtype_eq(vt->elem, vt->bounds)) {
1040
            col += printf(" => ");
1041
            col += vcode_dump_one_type(vt->bounds);
1042
         }
1043
      }
1044
      break;
1045

1046
   case VCODE_TYPE_POINTER:
1047
      col += printf("@<");
1048
      col += vcode_dump_one_type(vt->pointed);
1049
      col += printf(">");
1050
      break;
1051

1052
   case VCODE_TYPE_ACCESS:
1053
      col += printf("A<");
1054
      col += vcode_dump_one_type(vt->pointed);
1055
      col += printf(">");
1056
      break;
1057

1058
   case VCODE_TYPE_SIGNAL:
1059
      col += printf("$<");
1060
      col += vcode_dump_one_type(vt->base);
1061
      col += printf(">");
1062
      break;
1063

1064
   case VCODE_TYPE_OFFSET:
1065
      col += printf("#");
1066
      break;
1067

1068
   case VCODE_TYPE_RECORD:
1069
      col += printf("%s{}", istr(vt->name));
1070
      break;
1071

1072
   case VCODE_TYPE_FILE:
1073
      col += printf("F<");
1074
      col += vcode_dump_one_type(vt->base);
1075
      col += printf(">");
1076
      break;
1077

1078
   case VCODE_TYPE_OPAQUE:
1079
      col += printf("?");
1080
      break;
1081

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

1088
   case VCODE_TYPE_CLOSURE:
1089
      col += printf("C<");
1090
      col += vcode_dump_one_type(vt->base);
1091
      col += printf(">");
1092
      break;
1093

1094
   case VCODE_TYPE_CONTEXT:
1095
      col += printf("P<%s>", istr(vt->name));
1096
      break;
1097

1098
   case VCODE_TYPE_DEBUG_LOCUS:
1099
      col += printf("D<>");
1100
      break;
1101

1102
   case VCODE_TYPE_TRIGGER:
1103
      col += printf("T<>");
1104
      break;
1105

1106
   case VCODE_TYPE_CONVERSION:
1107
      col += printf("X<>");
1108
      break;
1109
   }
1110

1111
   return col;
1112
}
1113

1114
static void vcode_dump_tab(int col, int to_col)
1115
{
1116
   if (col >= to_col)
1117
      printf(" ");
1118
   else {
1119
      while (col < to_col)
1120
         col += printf(" ");
1121
   }
1122
}
1123

1124
static void vcode_dump_comment(int col)
1125
{
1126
   vcode_dump_tab(col, 40);
1127
   color_printf("$cyan$// ");
1128
}
1129

1130
static void vcode_dump_type(int col, vcode_type_t type, vcode_type_t bounds)
1131
{
1132
   vcode_dump_comment(col);
1133
   vcode_dump_one_type(type);
1134
   if (!vtype_eq(type, bounds)) {
1135
      printf(" => ");
1136
      vcode_dump_one_type(bounds);
1137
   }
1138
}
1139

1140
static void vcode_dump_result_type(int col, const op_t *op)
1141
{
1142
   if (op->result != VCODE_INVALID_REG) {
1143
      reg_t *r = vcode_reg_data(op->result);
1144
      vcode_dump_type(col, r->type, r->bounds);
1145
   }
1146
}
1147

1148
static int vcode_dump_var(vcode_var_t var, int hops)
1149
{
1150
   vcode_unit_t owner = active_unit;
1151
   while (owner && hops--)
1152
      owner = owner->context;
1153

1154
   if (owner == NULL || var >= owner->vars.count)
1155
      return color_printf("$red$invalid$$");
1156
   else {
1157
      var_t *v = var_array_nth_ptr(&(owner->vars), var);
1158
      return color_printf("$magenta$%s$$", istr(v->name));
1159
   }
1160
}
1161

1162
void vcode_dump_with_mark(int mark_op, vcode_dump_fn_t callback, void *arg)
1163
{
1164
   assert(active_unit != NULL);
1165

1166
   const vcode_unit_t vu = active_unit;
1167
   vcode_block_t old_block = active_block;
1168

1169
   printf("\n");
1170
   if (vu->name != NULL)
1171
      color_printf("Name       $cyan$%s$$\n", istr(vu->name));
1172
   color_printf("Kind       $cyan$");
1173
   switch (vu->kind) {
1174
   case VCODE_UNIT_PROCESS:   printf("process"); break;
1175
   case VCODE_UNIT_FUNCTION:  printf("function"); break;
1176
   case VCODE_UNIT_PROCEDURE: printf("procedure"); break;
1177
   case VCODE_UNIT_INSTANCE:  printf("instance"); break;
1178
   case VCODE_UNIT_THUNK:     printf("thunk"); break;
1179
   case VCODE_UNIT_PACKAGE:   printf("package"); break;
1180
   case VCODE_UNIT_PROTECTED: printf("protected"); break;
1181
   case VCODE_UNIT_PROPERTY:  printf("property"); break;
1182
   case VCODE_UNIT_SHAPE:     printf("shape"); break;
1183
   }
1184
   color_printf("$$\n");
1185
   if (vu->context != NULL)
1186
      color_printf("Context    $cyan$%s$$\n", istr(vu->context->name));
1187
   printf("Blocks     %d\n", vu->blocks.count);
1188
   printf("Registers  %d\n", vu->regs.count);
1189
   printf("Types      %d\n", vu->types.count);
1190

1191
   for (int i = 0; i < vu->types.count; i++) {
1192
      const vtype_t *t = &(vu->types.items[i]);
1193
      if (t->kind == VCODE_TYPE_RECORD) {
1194
         int col = 0;
1195
         col += color_printf("  $magenta$%s$$", istr(t->name));
1196
         vcode_dump_tab(col, 40);
1197
         color_printf("$cyan${");
1198
         for (unsigned i = 0; i < t->fields.count; i++) {
1199
            if (i > 0)
1200
               printf(", ");
1201
            vcode_dump_one_type(t->fields.items[i]);
1202
         }
1203
         color_printf("}$$\n");
1204
      }
1205
   }
1206

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

1209
   for (int i = 0; i < vu->vars.count; i++) {
1210
      const var_t *v = &(vu->vars.items[i]);
1211
      int col = printf("  ");
1212
      col += color_printf("$magenta$%s$$", istr(v->name));
1213
      vcode_dump_type(col, v->type, v->bounds);
1214
      if (v->flags & VAR_SIGNAL)
1215
         col += printf(", signal");
1216
      if (v->flags & VAR_HEAP)
1217
         col += printf(", heap");
1218
      if (v->flags & VAR_CONST)
1219
         col += printf(", constant");
1220
      if (v->flags & VAR_TEMP)
1221
         col += printf(", temp");
1222
      color_printf("$$\n");
1223
   }
1224

1225
   if (vu->result != VCODE_INVALID_TYPE) {
1226
      color_printf("Result     $cyan$");
1227
      vcode_dump_one_type(vu->result);
1228
      color_printf("$$\n");
1229
   }
1230

1231
   if (vu->kind == VCODE_UNIT_FUNCTION
1232
       || vu->kind == VCODE_UNIT_PROCEDURE
1233
       || vu->kind == VCODE_UNIT_PROPERTY
1234
       || (vu->kind == VCODE_UNIT_PROTECTED && vu->params.count > 0)) {
1235

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

1238
      for (size_t i = 0; i < vu->params.count; i++) {
1239
         const param_t *p = &(vu->params.items[i]);
1240
         int col = printf("  ");
1241
         col += vcode_dump_reg(p->reg);
1242
         while (col < 8)
1243
            col += printf(" ");
1244
         col += color_printf("$magenta$%s$$", istr(p->name));
1245
         vcode_dump_type(col, p->type, p->bounds);
1246
         color_printf("$$\n");
1247
      }
1248
   }
1249

1250
   printf("Begin\n");
1251
   for (int i = 0; i < vu->blocks.count; i++) {
1252
      active_block = i;
1253
      const block_t *b = &(vu->blocks.items[i]);
1254
      for (int j = 0; j < b->ops.count; j++) {
1255
         int col = 0;
1256
         if (j == 0)
1257
            col += color_printf("  $yellow$%2d:$$ ", i);
1258
         else
1259
            col += printf("      ");
1260

1261
         const op_t *op = &(b->ops.items[j]);
1262
         switch (op->kind) {
1263
         case VCODE_OP_CMP:
1264
            {
1265
               vcode_dump_reg(op->result);
1266
               printf(" := %s ", vcode_op_string(op->kind));
1267
               vcode_dump_reg(op->args.items[0]);
1268
               switch (op->cmp) {
1269
               case VCODE_CMP_EQ:  printf(" == "); break;
1270
               case VCODE_CMP_NEQ: printf(" != "); break;
1271
               case VCODE_CMP_LT:  printf(" < "); break;
1272
               case VCODE_CMP_GT:  printf(" > "); break;
1273
               case VCODE_CMP_LEQ: printf(" <= "); break;
1274
               case VCODE_CMP_GEQ: printf(" >= "); break;
1275
               }
1276
               vcode_dump_reg(op->args.items[1]);
1277
            }
1278
            break;
1279

1280
         case VCODE_OP_CONST:
1281
            {
1282
               col += vcode_dump_reg(op->result);
1283
               col += printf(" := %s %"PRIi64"",
1284
                             vcode_op_string(op->kind),
1285
                             op->value);
1286
               vcode_dump_result_type(col, op);
1287
            }
1288
            break;
1289

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

1300
         case VCODE_OP_ALLOC:
1301
            {
1302
               col += vcode_dump_reg(op->result);
1303
               col += printf(" := %s ", vcode_op_string(op->kind));
1304
               col += vcode_dump_reg(op->args.items[0]);
1305
               vcode_dump_result_type(col, op);
1306
            }
1307
            break;
1308

1309
         case VCODE_OP_FCALL:
1310
            {
1311
               if (op->result != VCODE_INVALID_REG) {
1312
                  col += vcode_dump_reg(op->result);
1313
                  col += printf(" := ");
1314
               }
1315
               col += color_printf("%s $magenta$%s$$ ",
1316
                                   vcode_op_string(op->kind),
1317
                                   istr(op->func));
1318
               for (int i = 0; i < op->args.count; i++) {
1319
                  if (i > 0)
1320
                     col += printf(", ");
1321
                  col += vcode_dump_reg(op->args.items[i]);
1322
               }
1323
               vcode_dump_result_type(col, op);
1324
            }
1325
            break;
1326

1327
         case VCODE_OP_MAP_CONST:
1328
         case VCODE_OP_MAP_SIGNAL:
1329
         case VCODE_OP_MAP_TRANSACTION:
1330
            {
1331
               printf("%s ", vcode_op_string(op->kind));
1332
               vcode_dump_reg(op->args.items[0]);
1333
               printf(" to ");
1334
               vcode_dump_reg(op->args.items[1]);
1335
               printf(" count ");
1336
               vcode_dump_reg(op->args.items[2]);
1337
            }
1338
            break;
1339

1340
         case VCODE_OP_DRIVE_SIGNAL:
1341
            {
1342
               printf("%s ", vcode_op_string(op->kind));
1343
               vcode_dump_reg(op->args.items[0]);
1344
               printf(" count ");
1345
               vcode_dump_reg(op->args.items[1]);
1346
            }
1347
            break;
1348

1349
         case VCODE_OP_TRANSFER_SIGNAL:
1350
            {
1351
               printf("%s ", vcode_op_string(op->kind));
1352
               vcode_dump_reg(op->args.items[0]);
1353
               printf(" to ");
1354
               vcode_dump_reg(op->args.items[1]);
1355
               printf(" count ");
1356
               vcode_dump_reg(op->args.items[2]);
1357
               printf(" reject ");
1358
               vcode_dump_reg(op->args.items[3]);
1359
               printf(" after ");
1360
               vcode_dump_reg(op->args.items[4]);
1361
            }
1362
            break;
1363

1364
         case VCODE_OP_RESOLVE_SIGNAL:
1365
            {
1366
               printf("%s ", vcode_op_string(op->kind));
1367
               vcode_dump_reg(op->args.items[0]);
1368
               printf(" resolution ");
1369
               vcode_dump_reg(op->args.items[1]);
1370
            }
1371
            break;
1372

1373
         case VCODE_OP_PUSH_SCOPE:
1374
            {
1375
               printf("%s locus ", vcode_op_string(op->kind));
1376
               vcode_dump_reg(op->args.items[0]);
1377
            }
1378
            break;
1379

1380
         case VCODE_OP_POP_SCOPE:
1381
            {
1382
               printf("%s", vcode_op_string(op->kind));
1383
            }
1384
            break;
1385

1386
         case VCODE_OP_INIT_SIGNAL:
1387
            {
1388
               col += vcode_dump_reg(op->result);
1389
               col += printf(" := ");
1390
               col += printf("%s count ", vcode_op_string(op->kind));
1391
               col += vcode_dump_reg(op->args.items[0]);
1392
               col += printf(" size ");
1393
               col += vcode_dump_reg(op->args.items[1]);
1394
               col += printf(" value ");
1395
               col += vcode_dump_reg(op->args.items[2]);
1396
               col += printf(" flags ");
1397
               col += vcode_dump_reg(op->args.items[3]);
1398
               col += printf(" locus ");
1399
               col += vcode_dump_reg(op->args.items[4]);
1400
               if (op->args.count > 5) {
1401
                  col += printf(" offset ");
1402
                  col += vcode_dump_reg(op->args.items[5]);
1403
               }
1404
               vcode_dump_result_type(col, op);
1405
            }
1406
            break;
1407

1408
         case VCODE_OP_IMPLICIT_SIGNAL:
1409
            {
1410
               col += vcode_dump_reg(op->result);
1411
               col += printf(" := %s count ", vcode_op_string(op->kind));
1412
               col += vcode_dump_reg(op->args.items[0]);
1413
               col += printf(" size ");
1414
               col += vcode_dump_reg(op->args.items[1]);
1415
               col += printf(" locus ");
1416
               col += vcode_dump_reg(op->args.items[2]);
1417
               col += printf(" kind ");
1418
               col += vcode_dump_reg(op->args.items[3]);
1419
               col += printf(" closure ");
1420
               col += vcode_dump_reg(op->args.items[4]);
1421
            }
1422
            break;
1423

1424
         case VCODE_OP_RESOLUTION_WRAPPER:
1425
            {
1426
               col += vcode_dump_reg(op->result);
1427
               col += color_printf(" := %s ", vcode_op_string(op->kind));
1428
               col += vcode_dump_reg(op->args.items[0]);
1429
               col += printf(" ileft ");
1430
               col += vcode_dump_reg(op->args.items[1]);
1431
               col += printf(" nlits ");
1432
               col += vcode_dump_reg(op->args.items[2]);
1433
               vcode_dump_result_type(col, op);
1434
            }
1435
            break;
1436

1437
         case VCODE_OP_CLOSURE:
1438
         case VCODE_OP_PROTECTED_INIT:
1439
            {
1440
               col += vcode_dump_reg(op->result);
1441
               col += color_printf(" := %s $magenta$%s$$ context ",
1442
                                   vcode_op_string(op->kind), istr(op->func));
1443
               col += vcode_dump_reg(op->args.items[0]);
1444
               if (op->args.count >= 3) {
1445
                  col += printf(" path " );
1446
                  col += vcode_dump_reg(op->args.items[1]);
1447
                  col += printf(" instance " );
1448
                  col += vcode_dump_reg(op->args.items[2]);
1449
               }
1450
               vcode_dump_result_type(col, op);
1451
            }
1452
            break;
1453

1454
         case VCODE_OP_PACKAGE_INIT:
1455
            {
1456
               col += vcode_dump_reg(op->result);
1457
               col += color_printf(" := %s $magenta$%s$$",
1458
                                   vcode_op_string(op->kind), istr(op->func));
1459
               if (op->args.count > 0) {
1460
                  col += printf(" context " );
1461
                  col += vcode_dump_reg(op->args.items[0]);
1462
               }
1463
               vcode_dump_result_type(col, op);
1464
            }
1465
            break;
1466

1467
         case VCODE_OP_PROCESS_INIT:
1468
            {
1469
               color_printf("%s $magenta$%s$$ locus ",
1470
                            vcode_op_string(op->kind), istr(op->func));
1471
               vcode_dump_reg(op->args.items[0]);
1472
            }
1473
            break;
1474

1475
         case VCODE_OP_PROTECTED_FREE:
1476
            {
1477
               printf("%s ", vcode_op_string(op->kind));
1478
               vcode_dump_reg(op->args.items[0]);
1479
            }
1480
            break;
1481

1482
         case VCODE_OP_WAIT:
1483
            {
1484
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1485
                            op->targets.items[0]);
1486
               if (op->args.items[0] != VCODE_INVALID_REG) {
1487
                  printf(" for ");
1488
                  vcode_dump_reg(op->args.items[0]);
1489
               }
1490
            }
1491
            break;
1492

1493
         case VCODE_OP_JUMP:
1494
            {
1495
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1496
                            op->targets.items[0]);
1497
            }
1498
            break;
1499

1500
         case VCODE_OP_COND:
1501
            {
1502
               printf("%s ", vcode_op_string(op->kind));
1503
               vcode_dump_reg(op->args.items[0]);
1504
               color_printf(" then $yellow$%d$$ else $yellow$%d$$",
1505
                            op->targets.items[0], op->targets.items[1]);
1506
            }
1507
            break;
1508

1509
         case VCODE_OP_ASSERT:
1510
            {
1511
               printf("%s ", vcode_op_string(op->kind));
1512
               vcode_dump_reg(op->args.items[0]);
1513
               if (op->args.items[2] != VCODE_INVALID_REG) {
1514
                  printf(" report ");
1515
                  vcode_dump_reg(op->args.items[2]);
1516
                  printf(" length ");
1517
                  vcode_dump_reg(op->args.items[3]);
1518
               }
1519
               printf(" severity ");
1520
               vcode_dump_reg(op->args.items[1]);
1521
               printf(" locus ");
1522
               vcode_dump_reg(op->args.items[4]);
1523
               if (op->args.count > 5) {
1524
                  printf(" hint ");
1525
                  vcode_dump_reg(op->args.items[5]);
1526
                  printf(" ");
1527
                  vcode_dump_reg(op->args.items[6]);
1528
               }
1529
            }
1530
            break;
1531

1532
         case VCODE_OP_REPORT:
1533
            {
1534
               printf("%s ", vcode_op_string(op->kind));
1535
               vcode_dump_reg(op->args.items[1]);
1536
               printf(" length ");
1537
               vcode_dump_reg(op->args.items[2]);
1538
               printf(" severity ");
1539
               vcode_dump_reg(op->args.items[0]);
1540
               printf(" locus ");
1541
               vcode_dump_reg(op->args.items[3]);
1542
            }
1543
            break;
1544

1545
         case VCODE_OP_LOAD:
1546
            {
1547
               col += vcode_dump_reg(op->result);
1548
               col += printf(" := %s ", vcode_op_string(op->kind));
1549
               col += vcode_dump_var(op->address, 0);
1550
               vcode_dump_result_type(col, op);
1551
            }
1552
            break;
1553

1554
         case VCODE_OP_LOAD_INDIRECT:
1555
            {
1556
               col += vcode_dump_reg(op->result);
1557
               col += color_printf(" := %s ", vcode_op_string(op->kind));
1558
               col += vcode_dump_reg(op->args.items[0]);
1559
               vcode_dump_result_type(col, op);
1560
            }
1561
            break;
1562

1563
         case VCODE_OP_STORE:
1564
            {
1565
               vcode_dump_var(op->address, 0);
1566
               printf(" := %s ", vcode_op_string(op->kind));
1567
               vcode_dump_reg(op->args.items[0]);
1568
            }
1569
            break;
1570

1571
         case VCODE_OP_STORE_INDIRECT:
1572
            {
1573
               vcode_dump_reg(op->args.items[1]);
1574
               printf(" := %s ", vcode_op_string(op->kind));
1575
               vcode_dump_reg(op->args.items[0]);
1576
            }
1577
            break;
1578

1579
         case VCODE_OP_INDEX:
1580
            {
1581
               col += vcode_dump_reg(op->result);
1582
               col += printf(" := %s ", vcode_op_string(op->kind));
1583
               col += vcode_dump_var(op->address, 0);
1584
               if (op->args.count > 0) {
1585
                  col += printf(" + ");
1586
                  col += vcode_dump_reg(op->args.items[0]);
1587
               }
1588
               vcode_dump_result_type(col, op);
1589
            }
1590
            break;
1591

1592
         case VCODE_OP_MUL:
1593
         case VCODE_OP_ADD:
1594
         case VCODE_OP_SUB:
1595
         case VCODE_OP_DIV:
1596
         case VCODE_OP_EXP:
1597
         case VCODE_OP_MOD:
1598
         case VCODE_OP_REM:
1599
         case VCODE_OP_OR:
1600
         case VCODE_OP_AND:
1601
         case VCODE_OP_XOR:
1602
         case VCODE_OP_XNOR:
1603
         case VCODE_OP_NAND:
1604
         case VCODE_OP_NOR:
1605
            {
1606
               col += vcode_dump_reg(op->result);
1607
               col += printf(" := %s ", vcode_op_string(op->kind));
1608
               col += vcode_dump_reg(op->args.items[0]);
1609
               switch (op->kind) {
1610
               case VCODE_OP_MUL:  col += printf(" * "); break;
1611
               case VCODE_OP_ADD:  col += printf(" + "); break;
1612
               case VCODE_OP_SUB:  col += printf(" - "); break;
1613
               case VCODE_OP_DIV:  col += printf(" / "); break;
1614
               case VCODE_OP_EXP:  col += printf(" ** "); break;
1615
               case VCODE_OP_MOD:  col += printf(" %% "); break;
1616
               case VCODE_OP_REM:  col += printf(" %% "); break;
1617
               case VCODE_OP_OR:   col += printf(" || "); break;
1618
               case VCODE_OP_AND:  col += printf(" && "); break;
1619
               case VCODE_OP_XOR:  col += printf(" ^ "); break;
1620
               case VCODE_OP_XNOR: col += printf(" !^ "); break;
1621
               case VCODE_OP_NAND: col += printf(" !& "); break;
1622
               case VCODE_OP_NOR:  col += printf(" !| "); break;
1623
               default: break;
1624
               }
1625
               col += vcode_dump_reg(op->args.items[1]);
1626
               vcode_dump_result_type(col, op);
1627
            }
1628
            break;
1629

1630
         case VCODE_OP_TRAP_ADD:
1631
         case VCODE_OP_TRAP_SUB:
1632
         case VCODE_OP_TRAP_MUL:
1633
         case VCODE_OP_TRAP_EXP:
1634
            {
1635
               col += vcode_dump_reg(op->result);
1636
               col += printf(" := %s ", vcode_op_string(op->kind));
1637
               col += vcode_dump_reg(op->args.items[0]);
1638
               switch (op->kind) {
1639
               case VCODE_OP_TRAP_ADD: col += printf(" + "); break;
1640
               case VCODE_OP_TRAP_SUB: col += printf(" - "); break;
1641
               case VCODE_OP_TRAP_MUL: col += printf(" * "); break;
1642
               case VCODE_OP_TRAP_EXP: col += printf(" ** "); break;
1643
               default: break;
1644
               }
1645
               col += vcode_dump_reg(op->args.items[1]);
1646
               col += printf(" locus ");
1647
               col += vcode_dump_reg(op->args.items[2]);
1648
               vcode_dump_result_type(col, op);
1649
            }
1650
            break;
1651

1652
         case VCODE_OP_NOT:
1653
            {
1654
               col += vcode_dump_reg(op->result);
1655
               col += printf(" := %s ", vcode_op_string(op->kind));
1656
               col += vcode_dump_reg(op->args.items[0]);
1657
               vcode_dump_result_type(col, op);
1658
            }
1659
            break;
1660

1661
         case VCODE_OP_COMMENT:
1662
            {
1663
               color_printf("$cyan$// %s$$ ", op->comment);
1664
            }
1665
            break;
1666

1667
         case VCODE_OP_CONST_ARRAY:
1668
         case VCODE_OP_CONST_RECORD:
1669
            {
1670
               col += vcode_dump_reg(op->result);
1671
               col += printf(" := const %c",
1672
                             op->kind == VCODE_OP_CONST_ARRAY ? '[' : '{');
1673
               for (int k = 0; k < op->args.count; k++) {
1674
                  if (k > 0)
1675
                     col += printf(",");
1676
                  col += vcode_dump_reg(op->args.items[k]);
1677
               }
1678

1679
               putchar(op->kind == VCODE_OP_CONST_ARRAY ? ']' : '}');
1680
               vcode_dump_result_type(col + 1, op);
1681
            }
1682
            break;
1683

1684
         case VCODE_OP_CONST_REP:
1685
            {
1686
               col += vcode_dump_reg(op->result);
1687
               col += printf(" := const [");
1688
               col += vcode_dump_reg(op->args.items[0]);
1689
               col += printf("]*%"PRIi64, op->value);
1690
               vcode_dump_result_type(col, op);
1691
            }
1692
            break;
1693

1694
         case VCODE_OP_ADDRESS_OF:
1695
         case VCODE_OP_CAST:
1696
            {
1697
               col += vcode_dump_reg(op->result);
1698
               col += printf(" := %s ", vcode_op_string(op->kind));
1699
               col += vcode_dump_reg(op->args.items[0]);
1700
               vcode_dump_result_type(col, op);
1701
            }
1702
            break;
1703

1704
         case VCODE_OP_RETURN:
1705
            {
1706
               printf("%s ", vcode_op_string(op->kind));
1707
               if (op->args.count > 0)
1708
                  vcode_dump_reg(op->args.items[0]);
1709
            }
1710
            break;
1711

1712
         case VCODE_OP_SCHED_WAVEFORM:
1713
            {
1714
               printf("%s ", vcode_op_string(op->kind));
1715
               vcode_dump_reg(op->args.items[0]);
1716
               printf(" count ");
1717
               vcode_dump_reg(op->args.items[1]);
1718
               printf(" values ");
1719
               vcode_dump_reg(op->args.items[2]);
1720
               printf(" reject ");
1721
               vcode_dump_reg(op->args.items[3]);
1722
               printf(" after ");
1723
               vcode_dump_reg(op->args.items[4]);
1724
            }
1725
            break;
1726

1727
         case VCODE_OP_FORCE:
1728
         case VCODE_OP_RELEASE:
1729
         case VCODE_OP_DEPOSIT_SIGNAL:
1730
            {
1731
               printf("%s ", vcode_op_string(op->kind));
1732
               vcode_dump_reg(op->args.items[0]);
1733
               printf(" count ");
1734
               vcode_dump_reg(op->args.items[1]);
1735
               if (op->args.count > 2) {
1736
                  printf(" values ");
1737
                  vcode_dump_reg(op->args.items[2]);
1738
               }
1739
            }
1740
            break;
1741

1742
         case VCODE_OP_DISCONNECT:
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(" reject ");
1749
               vcode_dump_reg(op->args.items[2]);
1750
               printf(" after ");
1751
               vcode_dump_reg(op->args.items[3]);
1752
            }
1753
            break;
1754

1755
         case VCODE_OP_NEG:
1756
         case VCODE_OP_TRAP_NEG:
1757
         case VCODE_OP_ABS:
1758
         case VCODE_OP_RESOLVED:
1759
         case VCODE_OP_LAST_VALUE:
1760
            {
1761
               col += vcode_dump_reg(op->result);
1762
               col += printf(" := %s ", vcode_op_string(op->kind));
1763
               col += vcode_dump_reg(op->args.items[0]);
1764
               if (op->args.count > 1) {
1765
                  col += printf(" locus ");
1766
                  col += vcode_dump_reg(op->args.items[1]);
1767
               }
1768
               vcode_dump_result_type(col, op);
1769
            }
1770
            break;
1771

1772
         case VCODE_OP_SELECT:
1773
            {
1774
               col += vcode_dump_reg(op->result);
1775
               col += printf(" := %s ", vcode_op_string(op->kind));
1776
               col += vcode_dump_reg(op->args.items[0]);
1777
               col += printf(" then ");
1778
               col += vcode_dump_reg(op->args.items[1]);
1779
               col += printf(" else ");
1780
               col += vcode_dump_reg(op->args.items[2]);
1781
               vcode_dump_result_type(col, op);
1782
            }
1783
            break;
1784

1785
         case VCODE_OP_WRAP:
1786
            {
1787
               col += vcode_dump_reg(op->result);
1788
               col += printf(" := %s ", vcode_op_string(op->kind));
1789
               col += vcode_dump_reg(op->args.items[0]);
1790
               col += printf(" [");
1791
               for (int i = 1; i < op->args.count; i += 3) {
1792
                  if (i > 1)
1793
                     col += printf(", ");
1794
                  col += vcode_dump_reg(op->args.items[i + 0]);
1795
                  col += printf(" ");
1796
                  col += vcode_dump_reg(op->args.items[i + 1]);
1797
                  col += printf(" ");
1798
                  col += vcode_dump_reg(op->args.items[i + 2]);
1799
               }
1800
               col += printf("]");
1801
               vcode_dump_result_type(col, op);
1802
            }
1803
            break;
1804

1805
         case VCODE_OP_UARRAY_LEFT:
1806
         case VCODE_OP_UARRAY_RIGHT:
1807
         case VCODE_OP_UARRAY_DIR:
1808
         case VCODE_OP_UARRAY_LEN:
1809
            {
1810
               col += vcode_dump_reg(op->result);
1811
               col += printf(" := %s ", vcode_op_string(op->kind));
1812
               col += vcode_dump_reg(op->args.items[0]);
1813
               col += printf(" dim %d", op->dim);
1814
               vcode_dump_result_type(col, op);
1815
            }
1816
            break;
1817

1818
         case VCODE_OP_UNWRAP:
1819
            {
1820
               col += vcode_dump_reg(op->result);
1821
               col += printf(" := %s ", vcode_op_string(op->kind));
1822
               col += vcode_dump_reg(op->args.items[0]);
1823
               vcode_dump_result_type(col, op);
1824
            }
1825
            break;
1826

1827
         case VCODE_OP_VAR_UPREF:
1828
            {
1829
               col += vcode_dump_reg(op->result);
1830
               col += printf(" := %s %d, ", vcode_op_string(op->kind),
1831
                             op->hops);
1832
               col += vcode_dump_var(op->address, op->hops);
1833
               vcode_dump_result_type(col, op);
1834
            }
1835
            break;
1836

1837
         case VCODE_OP_CONTEXT_UPREF:
1838
            {
1839
               col += vcode_dump_reg(op->result);
1840
               col += printf(" := %s %d", vcode_op_string(op->kind), op->hops);
1841
               vcode_dump_result_type(col, op);
1842
            }
1843
            break;
1844

1845
         case VCODE_OP_ACTIVE:
1846
         case VCODE_OP_EVENT:
1847
         case VCODE_OP_DRIVING:
1848
            {
1849
               col += vcode_dump_reg(op->result);
1850
               col += printf(" := %s ", vcode_op_string(op->kind));
1851
               col += vcode_dump_reg(op->args.items[0]);
1852
               col += printf(" length ");
1853
               col += vcode_dump_reg(op->args.items[1]);
1854
               vcode_dump_result_type(col, op);
1855
            }
1856
            break;
1857

1858
         case VCODE_OP_RECORD_REF:
1859
            {
1860
               col += vcode_dump_reg(op->result);
1861
               col += printf(" := %s ", vcode_op_string(op->kind));
1862
               col += vcode_dump_reg(op->args.items[0]);
1863
               col += printf(" field %d", op->field);
1864
               vcode_dump_result_type(col, op);
1865
            }
1866
            break;
1867

1868
         case VCODE_OP_ARRAY_REF:
1869
            {
1870
               col += vcode_dump_reg(op->result);
1871
               col += printf(" := %s ", vcode_op_string(op->kind));
1872
               col += vcode_dump_reg(op->args.items[0]);
1873
               col += printf(" offset ");
1874
               col += vcode_dump_reg(op->args.items[1]);
1875
               vcode_dump_result_type(col, op);
1876
            }
1877
            break;
1878

1879
         case VCODE_OP_COPY:
1880
            {
1881
               vcode_dump_reg(op->args.items[0]);
1882
               printf(" := %s ", vcode_op_string(op->kind));
1883
               vcode_dump_reg(op->args.items[1]);
1884
               if (op->args.count > 2) {
1885
                  printf(" count " );
1886
                  vcode_dump_reg(op->args.items[2]);
1887
               }
1888
            }
1889
            break;
1890

1891
         case VCODE_OP_SCHED_EVENT:
1892
         case VCODE_OP_CLEAR_EVENT:
1893
            {
1894
               printf("%s on ", vcode_op_string(op->kind));
1895
               vcode_dump_reg(op->args.items[0]);
1896
               printf(" count ");
1897
               vcode_dump_reg(op->args.items[1]);
1898
            }
1899
            break;
1900

1901
         case VCODE_OP_IMPLICIT_EVENT:
1902
            {
1903
               printf("%s on ", vcode_op_string(op->kind));
1904
               vcode_dump_reg(op->args.items[0]);
1905
               printf(" count ");
1906
               vcode_dump_reg(op->args.items[1]);
1907
               printf(" wake ");
1908
               vcode_dump_reg(op->args.items[2]);
1909
            }
1910
            break;
1911

1912
         case VCODE_OP_PCALL:
1913
            {
1914
               color_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1915
                            istr(op->func));
1916
               for (int i = 0; i < op->args.count; i++) {
1917
                  printf("%s", i > 0 ? ", " : " ");
1918
                  vcode_dump_reg(op->args.items[i]);
1919
               }
1920
               if (op->targets.count > 0)
1921
                  color_printf(" resume $yellow$%d$$", op->targets.items[0]);
1922
            }
1923
            break;
1924

1925
         case VCODE_OP_RESUME:
1926
            {
1927
               color_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1928
                            istr(op->func));
1929
            }
1930
            break;
1931

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

1942
         case VCODE_OP_CASE:
1943
            {
1944
               printf("%s ", vcode_op_string(op->kind));
1945
               vcode_dump_reg(op->args.items[0]);
1946
               color_printf(" default $yellow$%d$$", op->targets.items[0]);
1947
               for (int i = 1; i < op->args.count; i++) {
1948
                  printf(" [");
1949
                  vcode_dump_reg(op->args.items[i]);
1950
                  color_printf(" $yellow$%d$$]", op->targets.items[i]);
1951
               }
1952
            }
1953
            break;
1954

1955
         case VCODE_OP_FILE_OPEN:
1956
            {
1957
               printf("%s ", vcode_op_string(op->kind));
1958
               vcode_dump_reg(op->args.items[0]);
1959
               printf(" name ");
1960
               vcode_dump_reg(op->args.items[1]);
1961
               printf(" length ");
1962
               vcode_dump_reg(op->args.items[2]);
1963
               printf(" kind ");
1964
               vcode_dump_reg(op->args.items[3]);
1965
               if (op->args.count == 5) {
1966
                  printf(" status ");
1967
                  vcode_dump_reg(op->args.items[4]);
1968
               }
1969
            }
1970
            break;
1971

1972
         case VCODE_OP_FILE_WRITE:
1973
            {
1974
               printf("%s ", vcode_op_string(op->kind));
1975
               vcode_dump_reg(op->args.items[0]);
1976
               printf(" value ");
1977
               vcode_dump_reg(op->args.items[1]);
1978
               if (op->args.count == 3) {
1979
                  printf(" length ");
1980
                  vcode_dump_reg(op->args.items[2]);
1981
               }
1982
            }
1983
            break;
1984

1985
         case VCODE_OP_FILE_READ:
1986
            {
1987
               printf("%s ", vcode_op_string(op->kind));
1988
               vcode_dump_reg(op->args.items[0]);
1989
               printf(" ptr ");
1990
               vcode_dump_reg(op->args.items[1]);
1991
               if (op->args.count >= 3) {
1992
                  printf(" inlen ");
1993
                  vcode_dump_reg(op->args.items[2]);
1994
                  if (op->args.count >= 4) {
1995
                     printf(" outlen ");
1996
                     vcode_dump_reg(op->args.items[3]);
1997
                  }
1998
               }
1999
            }
2000
            break;
2001

2002
         case VCODE_OP_NULL:
2003
         case VCODE_OP_NEW:
2004
            {
2005
               col += vcode_dump_reg(op->result);
2006
               col += printf(" := %s", vcode_op_string(op->kind));
2007
               if (op->args.count == 1) {
2008
                  col += printf(" length ");
2009
                  col += vcode_dump_reg(op->args.items[0]);
2010
               }
2011
               vcode_dump_result_type(col, op);
2012
            }
2013
            break;
2014

2015
         case VCODE_OP_NULL_CHECK:
2016
            {
2017
               col += printf("%s ", vcode_op_string(op->kind));
2018
               col += vcode_dump_reg(op->args.items[0]);
2019
               col += printf(" locus ");
2020
               col += vcode_dump_reg(op->args.items[1]);
2021
            }
2022
            break;
2023

2024
         case VCODE_OP_DEALLOCATE:
2025
            {
2026
               col += printf("%s ", vcode_op_string(op->kind));
2027
               col += vcode_dump_reg(op->args.items[0]);
2028
            }
2029
            break;
2030

2031
         case VCODE_OP_ALL:
2032
            {
2033
               col += vcode_dump_reg(op->result);
2034
               col += printf(" := %s ", vcode_op_string(op->kind));
2035
               col += vcode_dump_reg(op->args.items[0]);
2036
               vcode_dump_result_type(col, op);
2037
            }
2038
            break;
2039

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

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

2064
         case VCODE_OP_LENGTH_CHECK:
2065
            {
2066
               col += printf("%s left ", vcode_op_string(op->kind));
2067
               col += vcode_dump_reg(op->args.items[0]);
2068
               col += printf(" == right ");
2069
               col += vcode_dump_reg(op->args.items[1]);
2070
               col += printf(" locus ");
2071
               col += vcode_dump_reg(op->args.items[2]);
2072
               if (op->args.count > 3) {
2073
                  col += printf(" dim ");
2074
                  col += vcode_dump_reg(op->args.items[3]);
2075
               }
2076
            }
2077
            break;
2078

2079
         case VCODE_OP_EXPONENT_CHECK:
2080
         case VCODE_OP_ZERO_CHECK:
2081
            {
2082
               col += printf("%s ", vcode_op_string(op->kind));
2083
               col += vcode_dump_reg(op->args.items[0]);
2084
               col += printf(" locus ");
2085
               col += vcode_dump_reg(op->args.items[1]);
2086
            }
2087
            break;
2088

2089
         case VCODE_OP_INDEX_CHECK:
2090
         case VCODE_OP_RANGE_CHECK:
2091
            {
2092
               col += printf("%s ", vcode_op_string(op->kind));
2093
               col += vcode_dump_reg(op->args.items[0]);
2094
               col += printf(" left ");
2095
               col += vcode_dump_reg(op->args.items[1]);
2096
               col += printf(" right ");
2097
               col += vcode_dump_reg(op->args.items[2]);
2098
               col += printf(" dir ");
2099
               col += vcode_dump_reg(op->args.items[3]);
2100
               col += printf(" locus ");
2101
               col += vcode_dump_reg(op->args.items[4]);
2102
               if (op->args.items[5] != op->args.items[4]) {
2103
                  col += printf(" hint ");
2104
                  col += vcode_dump_reg(op->args.items[5]);
2105
               }
2106
            }
2107
            break;
2108

2109
         case VCODE_OP_DEBUG_OUT:
2110
            {
2111
               col += printf("%s ", vcode_op_string(op->kind));
2112
               col += vcode_dump_reg(op->args.items[0]);
2113
            }
2114
            break;
2115

2116
         case VCODE_OP_COVER_INCREMENT:
2117
            {
2118
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2119
            }
2120
            break;
2121

2122
         case VCODE_OP_COVER_TOGGLE:
2123
         case VCODE_OP_COVER_STATE:
2124
            {
2125
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2126
               vcode_dump_reg(op->args.items[0]);
2127
            }
2128
            break;
2129

2130
         case VCODE_OP_UNDEFINED:
2131
            {
2132
               col += vcode_dump_reg(op->result);
2133
               col += printf(" := %s", vcode_op_string(op->kind));
2134
               vcode_dump_result_type(col, op);
2135
            }
2136
            break;
2137

2138
         case VCODE_OP_RANGE_LENGTH:
2139
         case VCODE_OP_RANGE_NULL:
2140
            {
2141
               col += vcode_dump_reg(op->result);
2142
               col += printf(" := %s left ", vcode_op_string(op->kind));
2143
               vcode_dump_reg(op->args.items[0]);
2144
               col += printf(" right ");
2145
               vcode_dump_reg(op->args.items[1]);
2146
               col += printf(" dir ");
2147
               col += vcode_dump_reg(op->args.items[2]);
2148
               vcode_dump_result_type(col, op);
2149
            }
2150
            break;
2151

2152
         case VCODE_OP_LINK_PACKAGE:
2153
         case VCODE_OP_LINK_INSTANCE:
2154
            {
2155
               col += vcode_dump_reg(op->result);
2156
               col += color_printf(" := %s $magenta$%s$$",
2157
                                   vcode_op_string(op->kind), istr(op->ident));
2158
               if (op->args.count > 0) {
2159
                  col += printf(" locus ");
2160
                  col += vcode_dump_reg(op->args.items[0]);
2161
               }
2162
               vcode_dump_result_type(col, op);
2163
            }
2164
            break;
2165

2166
         case VCODE_OP_LINK_VAR:
2167
            {
2168
               col += vcode_dump_reg(op->result);
2169
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2170
               col += vcode_dump_reg(op->args.items[0]);
2171
               col += color_printf(" $magenta$%s$$", istr(op->ident));
2172
               vcode_dump_result_type(col, op);
2173
            }
2174
            break;
2175

2176
         case VCODE_OP_UNREACHABLE:
2177
            {
2178
               printf("%s", vcode_op_string(op->kind));
2179
               if (op->args.count > 0) {
2180
                  printf(" ");
2181
                  vcode_dump_reg(op->args.items[0]);
2182
               }
2183
            }
2184
            break;
2185

2186
         case VCODE_OP_DEBUG_LOCUS:
2187
            {
2188
               col += vcode_dump_reg(op->result);
2189
               col += color_printf(" := %s $magenta$%s$$%+"PRIi64,
2190
                                   vcode_op_string(op->kind),
2191
                                   istr(op->ident), op->value);
2192
               vcode_dump_result_type(col, op);
2193
            }
2194
            break;
2195

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

2203
         case VCODE_OP_REFLECT_VALUE:
2204
            {
2205
               col += vcode_dump_reg(op->result);
2206
               col += printf(" := %s ", vcode_op_string(op->kind));
2207
               vcode_dump_reg(op->args.items[0]);
2208
               col += printf(" context ");
2209
               vcode_dump_reg(op->args.items[1]);
2210
               col += printf(" locus ");
2211
               col += vcode_dump_reg(op->args.items[2]);
2212
               if (op->args.count > 3) {
2213
                  col += printf(" bounds ");
2214
                  col += vcode_dump_reg(op->args.items[3]);
2215
               }
2216
               vcode_dump_result_type(col, op);
2217
            }
2218
            break;
2219

2220
         case VCODE_OP_REFLECT_SUBTYPE:
2221
            {
2222
               col += vcode_dump_reg(op->result);
2223
               col += printf(" := %s context ", vcode_op_string(op->kind));
2224
               vcode_dump_reg(op->args.items[0]);
2225
               col += printf(" locus ");
2226
               col += vcode_dump_reg(op->args.items[1]);
2227
               if (op->args.count > 2) {
2228
                  col += printf(" bounds ");
2229
                  col += vcode_dump_reg(op->args.items[2]);
2230
               }
2231
               vcode_dump_result_type(col, op);
2232
            }
2233
            break;
2234

2235
         case VCODE_OP_FUNCTION_TRIGGER:
2236
            {
2237
               col += vcode_dump_reg(op->result);
2238
               col += color_printf(" := %s $magenta$%s$$ ",
2239
                                   vcode_op_string(op->kind), istr(op->func));
2240
               for (int i = 0; i < op->args.count; i++) {
2241
                  if (i > 0) col += printf(", ");
2242
                  col += vcode_dump_reg(op->args.items[i]);
2243
               }
2244
               vcode_dump_result_type(col, op);
2245
            }
2246
            break;
2247

2248
         case VCODE_OP_OR_TRIGGER:
2249
         case VCODE_OP_CMP_TRIGGER:
2250
            {
2251
               col += vcode_dump_reg(op->result);
2252
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2253
               col += vcode_dump_reg(op->args.items[0]);
2254
               if (op->kind == VCODE_OP_OR_TRIGGER)
2255
                  col += printf(" || ");
2256
               else
2257
                  col += printf(" == ");
2258
               col += vcode_dump_reg(op->args.items[1]);
2259
               vcode_dump_result_type(col, op);
2260
            }
2261
            break;
2262

2263
         case VCODE_OP_ADD_TRIGGER:
2264
            {
2265
               printf("%s ", vcode_op_string(op->kind));
2266
               vcode_dump_reg(op->args.items[0]);
2267
            }
2268
            break;
2269

2270
         case VCODE_OP_PORT_CONVERSION:
2271
            {
2272
               col += vcode_dump_reg(op->result);
2273
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2274
               col += vcode_dump_reg(op->args.items[0]);
2275
               if (op->args.count > 1) {
2276
                  col += printf(" effective ");
2277
                  col += vcode_dump_reg(op->args.items[1]);
2278
               }
2279
               vcode_dump_result_type(col, op);
2280
            }
2281
            break;
2282

2283
         case VCODE_OP_CONVERT_IN:
2284
         case VCODE_OP_CONVERT_OUT:
2285
            {
2286
               color_printf("%s ", vcode_op_string(op->kind));
2287
               vcode_dump_reg(op->args.items[0]);
2288
               printf(" signal ");
2289
               vcode_dump_reg(op->args.items[1]);
2290
               printf(" count ");
2291
               vcode_dump_reg(op->args.items[2]);
2292
            }
2293
            break;
2294

2295
         case VCODE_OP_BIND_FOREIGN:
2296
            {
2297
               color_printf("%s ", vcode_op_string(op->kind));
2298
               vcode_dump_reg(op->args.items[0]);
2299
               printf(" length ");
2300
               vcode_dump_reg(op->args.items[1]);
2301
               if (op->args.count > 2) {
2302
                  printf(" locus ");
2303
                  vcode_dump_reg(op->args.items[1]);
2304
               }
2305
            }
2306
            break;
2307

2308
         case VCODE_OP_INSTANCE_NAME:
2309
            {
2310
               col += vcode_dump_reg(op->result);
2311
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2312
               col += vcode_dump_reg(op->args.items[0]);
2313
               vcode_dump_result_type(col, op);
2314
            }
2315
            break;
2316
         }
2317

2318
         if (j == mark_op && i == old_block)
2319
            color_printf("\t $red$<----$$");
2320

2321
         color_printf("$$\n");
2322

2323
         if (callback != NULL)
2324
            (*callback)(j, arg);
2325
      }
2326

2327
      if (b->ops.count == 0)
2328
         color_printf("  $yellow$%2d:$$ $red$Empty basic block$$\n", i);
2329
   }
2330

2331
   printf("\n");
2332
   fflush(stdout);
2333

2334
   active_block = old_block;
2335
}
2336
LCOV_EXCL_STOP
2337

2338
bool vtype_eq(vcode_type_t a, vcode_type_t b)
31,889,429✔
2339
{
2340
   assert(active_unit != NULL);
32,397,256✔
2341

2342
   if (a == b)
32,397,256✔
2343
      return true;
2344
   else {
2345
      const vtype_t *at = vcode_type_data(a);
29,868,043✔
2346
      const vtype_t *bt = vcode_type_data(b);
29,868,043✔
2347

2348
      if (at->kind != bt->kind)
29,868,043✔
2349
         return false;
2350

2351
      switch (at->kind) {
13,029,863✔
2352
      case VCODE_TYPE_INT:
10,997,842✔
2353
         return (at->low == bt->low) && (at->high == bt->high);
20,664,866✔
2354
      case VCODE_TYPE_REAL:
977,885✔
2355
         return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
1,904,680✔
2356
      case VCODE_TYPE_CARRAY:
71,775✔
2357
         return at->size == bt->size && vtype_eq(at->elem, bt->elem);
78,158✔
2358
      case VCODE_TYPE_UARRAY:
89,189✔
2359
         return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
111,266✔
2360
      case VCODE_TYPE_POINTER:
427,909✔
2361
      case VCODE_TYPE_ACCESS:
2362
         return vtype_eq(at->pointed, bt->pointed);
427,909✔
2363
      case VCODE_TYPE_OFFSET:
2364
      case VCODE_TYPE_OPAQUE:
2365
      case VCODE_TYPE_DEBUG_LOCUS:
2366
      case VCODE_TYPE_TRIGGER:
2367
      case VCODE_TYPE_CONVERSION:
2368
         return true;
2369
      case VCODE_TYPE_RESOLUTION:
79,918✔
2370
      case VCODE_TYPE_CLOSURE:
2371
      case VCODE_TYPE_SIGNAL:
2372
      case VCODE_TYPE_FILE:
2373
         return vtype_eq(at->base, bt->base);
79,918✔
2374
      case VCODE_TYPE_RECORD:
62,718✔
2375
      case VCODE_TYPE_CONTEXT:
2376
         return at->name == bt->name;
62,718✔
2377
      }
2378

UNCOV
2379
      return false;
×
2380
   }
2381
}
2382

UNCOV
2383
void vcode_dump(void)
×
2384
{
UNCOV
2385
   vcode_dump_with_mark(-1, NULL, NULL);
×
2386
}
×
2387

2388
static vcode_type_t vtype_new(vtype_t *new)
2,437,941✔
2389
{
2390
   int index = active_unit->types.count - 1;
2,437,941✔
2391
   vcode_type_t type = MAKE_HANDLE(active_unit->depth, index);
2,437,941✔
2392

2393
   for (int i = 0; i < index; i++) {
29,589,615✔
2394
      vcode_type_t this = MAKE_HANDLE(active_unit->depth, i);
29,080,996✔
2395
      if (vtype_eq(this, type)) {
29,080,996✔
2396
         active_unit->types.count--;
1,929,322✔
2397
         return this;
1,929,322✔
2398
      }
2399
   }
2400

2401
   return type;
2402
}
2403

2404
vcode_type_t vtype_int(int64_t low, int64_t high)
1,604,441✔
2405
{
2406
   assert(active_unit != NULL);
1,604,441✔
2407

2408
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,604,441✔
2409
   n->kind = VCODE_TYPE_INT;
1,604,441✔
2410
   n->low  = low;
1,604,441✔
2411
   n->high = high;
1,604,441✔
2412

2413
   switch (bits_for_range(low, high)) {
1,604,441✔
2414
   case 64:
122,899✔
2415
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
122,899✔
2416
      break;
122,899✔
2417
   case 32:
498,504✔
2418
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
498,504✔
2419
      break;
498,504✔
2420
   case 16:
3,250✔
2421
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
3,250✔
2422
      break;
3,250✔
2423
   case 8:
422,605✔
2424
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
422,605✔
2425
      break;
422,605✔
2426
   case 1:
557,182✔
2427
      n->repr = VCODE_REPR_U1;
557,182✔
2428
      break;
557,182✔
2429
   case 0:
1✔
2430
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2431
      break;
1✔
UNCOV
2432
   default:
×
UNCOV
2433
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
×
2434
   }
2435

2436
   return vtype_new(n);
1,604,441✔
2437
}
2438

2439
vcode_type_t vtype_bool(void)
281,244✔
2440
{
2441
   return vtype_int(0, 1);
281,244✔
2442
}
2443

2444
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
35,651✔
2445
{
2446
   assert(active_unit != NULL);
35,651✔
2447

2448
   const vtype_kind_t ekind = vtype_kind(elem);
35,651✔
2449
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
35,651✔
2450
                "array types may not be nested");
2451

2452
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
35,651✔
2453
   memset(n, '\0', sizeof(vtype_t));
35,651✔
2454
   n->kind   = VCODE_TYPE_CARRAY;
35,651✔
2455
   n->elem   = elem;
35,651✔
2456
   n->bounds = bounds;
35,651✔
2457
   n->size   = MAX(size, 0);
35,651✔
2458

2459
   return vtype_new(n);
35,651✔
2460
}
2461

2462
vcode_type_t vtype_find_named_record(ident_t name)
35,459✔
2463
{
2464
   assert(active_unit != NULL);
35,459✔
2465

2466
   for (int i = 0; i < active_unit->types.count; i++) {
475,792✔
2467
      vtype_t *other = &(active_unit->types.items[i]);
465,364✔
2468
      if (other->kind == VCODE_TYPE_RECORD && other->name == name)
465,364✔
2469
         return MAKE_HANDLE(active_unit->depth, i);
25,031✔
2470
   }
2471

2472
   return VCODE_INVALID_TYPE;
2473
}
2474

2475
vcode_type_t vtype_named_record(ident_t name, const vcode_type_t *field_types,
10,428✔
2476
                                int nfields)
2477
{
2478
   assert(active_unit != NULL);
10,428✔
2479

2480
   vtype_t *data = NULL;
10,428✔
2481
   vcode_type_t handle = vtype_find_named_record(name);
10,428✔
2482
   if (handle == VCODE_INVALID_TYPE) {
10,428✔
2483
      data = vtype_array_alloc(&(active_unit->types));
5,223✔
2484
      memset(data, '\0', sizeof(vtype_t));
5,223✔
2485
      data->kind = VCODE_TYPE_RECORD;
5,223✔
2486
      data->name = name;
5,223✔
2487

2488
      handle = vtype_new(data);
5,223✔
2489
   }
2490
   else {
2491
      data = vcode_type_data(handle);
5,205✔
2492
      VCODE_ASSERT(data->fields.count == 0,
5,205✔
2493
                    "record type %s already defined", istr(name));
2494
   }
2495

2496
   vcode_type_array_resize(&(data->fields), 0, VCODE_INVALID_TYPE);
10,428✔
2497
   for (int i = 0; i < nfields; i++)
28,552✔
2498
      vcode_type_array_add(&(data->fields), field_types[i]);
18,124✔
2499

2500
   return handle;
10,428✔
2501
}
2502

2503
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
83,428✔
2504
{
2505
   assert(active_unit != NULL);
83,428✔
2506

2507
   const vtype_kind_t ekind = vtype_kind(elem);
83,428✔
2508
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
83,428✔
2509
                "array types may not be nested");
2510

2511
   VCODE_ASSERT(ndim > 0, "uarray must have at least one dimension");
83,428✔
2512

2513
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
83,428✔
2514
   memset(n, '\0', sizeof(vtype_t));
83,428✔
2515
   n->kind   = VCODE_TYPE_UARRAY;
83,428✔
2516
   n->elem   = elem;
83,428✔
2517
   n->bounds = bounds;
83,428✔
2518
   n->dims   = ndim;
83,428✔
2519

2520
   return vtype_new(n);
83,428✔
2521
}
2522

2523
vcode_type_t vtype_pointer(vcode_type_t to)
176,376✔
2524
{
2525
   assert(active_unit != NULL);
176,376✔
2526

2527
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
176,376✔
2528
   n->kind    = VCODE_TYPE_POINTER;
176,376✔
2529
   n->pointed = to;
176,376✔
2530

2531
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
176,376✔
2532
                "cannot get pointer to carray type");
2533

2534
   return vtype_new(n);
176,376✔
2535
}
2536

2537
vcode_type_t vtype_access(vcode_type_t to)
4,816✔
2538
{
2539
   assert(active_unit != NULL);
4,816✔
2540

2541
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
4,816✔
2542
   n->kind    = VCODE_TYPE_ACCESS;
4,816✔
2543
   n->pointed = to;
4,816✔
2544

2545
   return vtype_new(n);
4,816✔
2546
}
2547

2548
vcode_type_t vtype_signal(vcode_type_t base)
32,413✔
2549
{
2550
   assert(active_unit != NULL);
32,413✔
2551

2552
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
32,413✔
2553
   n->kind = VCODE_TYPE_SIGNAL;
32,413✔
2554
   n->base = base;
32,413✔
2555

2556
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
32,413✔
2557

2558
   return vtype_new(n);
32,413✔
2559
}
2560

2561
vcode_type_t vtype_resolution(vcode_type_t base)
783✔
2562
{
2563
   assert(active_unit != NULL);
783✔
2564

2565
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
783✔
2566
   n->kind = VCODE_TYPE_RESOLUTION;
783✔
2567
   n->base = base;
783✔
2568

2569
   return vtype_new(n);
783✔
2570
}
2571

2572
vcode_type_t vtype_closure(vcode_type_t result)
965✔
2573
{
2574
   assert(active_unit != NULL);
965✔
2575

2576
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
965✔
2577
   n->kind = VCODE_TYPE_CLOSURE;
965✔
2578
   n->base = result;
965✔
2579

2580
   return vtype_new(n);
965✔
2581
}
2582

2583
vcode_type_t vtype_context(ident_t name)
49,324✔
2584
{
2585
   assert(active_unit != NULL);
49,324✔
2586
   assert(name != NULL);
49,324✔
2587

2588
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
49,324✔
2589
   n->kind = VCODE_TYPE_CONTEXT;
49,324✔
2590
   n->name = name;
49,324✔
2591

2592
   return vtype_new(n);
49,324✔
2593
}
2594

2595
vcode_type_t vtype_file(vcode_type_t base)
582✔
2596
{
2597
   assert(active_unit != NULL);
582✔
2598

2599
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
582✔
2600
   n->kind = VCODE_TYPE_FILE;
582✔
2601
   n->base = base;
582✔
2602

2603
   return vtype_new(n);
582✔
2604
}
2605

2606
vcode_type_t vtype_offset(void)
252,744✔
2607
{
2608
   assert(active_unit != NULL);
252,744✔
2609

2610
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
252,744✔
2611
   n->kind = VCODE_TYPE_OFFSET;
252,744✔
2612
   n->low  = INT64_MIN;
252,744✔
2613
   n->high = INT64_MAX;
252,744✔
2614
   n->repr = VCODE_REPR_I64;
252,744✔
2615

2616
   return vtype_new(n);
252,744✔
2617
}
2618

2619
vcode_type_t vtype_time(void)
15,876✔
2620
{
2621
   return vtype_int(INT64_MIN, INT64_MAX);
15,876✔
2622
}
2623

2624
vcode_type_t vtype_char(void)
9,202✔
2625
{
2626
   return vtype_int(0, 255);
9,202✔
2627
}
2628

2629
vcode_type_t vtype_opaque(void)
1,118✔
2630
{
2631
   assert(active_unit != NULL);
1,118✔
2632

2633
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,118✔
2634
   n->kind = VCODE_TYPE_OPAQUE;
1,118✔
2635

2636
   return vtype_new(n);
1,118✔
2637
}
2638

2639
vcode_type_t vtype_debug_locus(void)
109,842✔
2640
{
2641
   assert(active_unit != NULL);
109,842✔
2642

2643
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
109,842✔
2644
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
109,842✔
2645

2646
   return vtype_new(n);
109,842✔
2647
}
2648

2649
vcode_type_t vtype_trigger(void)
293✔
2650
{
2651
   assert(active_unit != NULL);
293✔
2652

2653
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
293✔
2654
   n->kind = VCODE_TYPE_TRIGGER;
293✔
2655

2656
   return vtype_new(n);
293✔
2657
}
2658

2659
vcode_type_t vtype_conversion(void)
180✔
2660
{
2661
   assert(active_unit != NULL);
180✔
2662

2663
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
180✔
2664
   n->kind = VCODE_TYPE_CONVERSION;
180✔
2665

2666
   return vtype_new(n);
180✔
2667
}
2668

2669
vcode_type_t vtype_real(double low, double high)
79,762✔
2670
{
2671
   assert(active_unit != NULL);
79,762✔
2672

2673
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
79,762✔
2674
   n->kind  = VCODE_TYPE_REAL;
79,762✔
2675
   n->rlow  = low;
79,762✔
2676
   n->rhigh = high;
79,762✔
2677

2678
   return vtype_new(n);
79,762✔
2679
}
2680

2681
vtype_kind_t vtype_kind(vcode_type_t type)
5,499,902✔
2682
{
2683
   vtype_t *vt = vcode_type_data(type);
5,499,902✔
2684
   return vt->kind;
5,499,902✔
2685
}
2686

2687
vtype_repr_t vtype_repr(vcode_type_t type)
449,728✔
2688
{
2689
   vtype_t *vt = vcode_type_data(type);
449,728✔
2690
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
449,728✔
2691
   return vt->repr;
449,728✔
2692
}
2693

2694
vcode_type_t vtype_elem(vcode_type_t type)
347,773✔
2695
{
2696
   vtype_t *vt = vcode_type_data(type);
347,773✔
2697
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
347,773✔
2698
   return vt->elem;
347,773✔
2699
}
2700

2701
vcode_type_t vtype_base(vcode_type_t type)
13,176✔
2702
{
2703
   vtype_t *vt = vcode_type_data(type);
13,176✔
2704
   assert(vt->kind == VCODE_TYPE_SIGNAL || vt->kind == VCODE_TYPE_FILE
13,176✔
2705
          || vt->kind == VCODE_TYPE_RESOLUTION
2706
          || vt->kind == VCODE_TYPE_CLOSURE);
2707
   return vt->base;
13,176✔
2708
}
2709

2710
vcode_type_t vtype_bounds(vcode_type_t type)
12,267✔
2711
{
2712
   vtype_t *vt = vcode_type_data(type);
12,267✔
2713
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
12,267✔
2714
   return vt->bounds;
12,267✔
2715
}
2716

2717
unsigned vtype_dims(vcode_type_t type)
134,327✔
2718
{
2719
   vtype_t *vt = vcode_type_data(type);
134,327✔
2720
   assert(vt->kind == VCODE_TYPE_UARRAY);
134,327✔
2721
   return vt->dims;
134,327✔
2722
}
2723

2724
unsigned vtype_size(vcode_type_t type)
74,601✔
2725
{
2726
   vtype_t *vt = vcode_type_data(type);
74,601✔
2727
   assert(vt->kind == VCODE_TYPE_CARRAY);
74,601✔
2728
   return vt->size;
74,601✔
2729
}
2730

2731
int vtype_fields(vcode_type_t type)
25,249✔
2732
{
2733
   vtype_t *vt = vcode_type_data(type);
25,249✔
2734
   assert(vt->kind == VCODE_TYPE_RECORD);
25,249✔
2735
   return vt->fields.count;
25,249✔
2736
}
2737

2738
vcode_type_t vtype_field(vcode_type_t type, int field)
203,941✔
2739
{
2740
   vtype_t *vt = vcode_type_data(type);
203,941✔
2741
   assert(vt->kind == VCODE_TYPE_RECORD);
203,941✔
2742
   return vcode_type_array_nth(&(vt->fields), field);
203,941✔
2743
}
2744

2745
ident_t vtype_name(vcode_type_t type)
2,731✔
2746
{
2747
   vtype_t *vt = vcode_type_data(type);
2,731✔
2748
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
2,731✔
2749
   return vt->name;
2,731✔
2750
}
2751

2752
vcode_type_t vtype_pointed(vcode_type_t type)
366,104✔
2753
{
2754
   vtype_t *vt = vcode_type_data(type);
366,104✔
2755
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
366,104✔
2756
   return vt->pointed;
366,104✔
2757
}
2758

2759
int64_t vtype_low(vcode_type_t type)
55,662✔
2760
{
2761
   vtype_t *vt = vcode_type_data(type);
55,662✔
2762
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
55,662✔
2763
   return vt->low;
55,662✔
2764
}
2765

2766
int64_t vtype_high(vcode_type_t type)
53,585✔
2767
{
2768
   vtype_t *vt = vcode_type_data(type);
53,585✔
2769
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
53,585✔
2770
   return vt->high;
53,585✔
2771
}
2772

2773
static bool vtype_is_pointer(vcode_type_t type, vtype_kind_t to)
441✔
2774
{
2775
   return vtype_kind(type) == VCODE_TYPE_POINTER
441✔
2776
      && vtype_kind(vtype_pointed(type)) == to;
441✔
2777
}
2778

2779
bool vtype_is_scalar(vcode_type_t type)
373,960✔
2780
{
2781
   const vtype_kind_t kind = vtype_kind(type);
373,960✔
2782
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
373,960✔
2783
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
150,032✔
2784
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2785
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2786
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER;
373,960✔
2787
}
2788

2789
bool vtype_is_composite(vcode_type_t type)
22,570✔
2790
{
2791
   const vtype_kind_t kind = vtype_kind(type);
22,570✔
2792
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
22,570✔
2793
}
2794

2795
bool vtype_is_signal(vcode_type_t type)
163,868✔
2796
{
2797
   vtype_t *vt = vcode_type_data(type);
291,987✔
2798
   switch (vt->kind) {
291,987✔
2799
   case VCODE_TYPE_SIGNAL:
2800
      return true;
2801
   case VCODE_TYPE_POINTER:
69,743✔
2802
      return vtype_is_signal(vt->pointed);
69,743✔
2803
   case VCODE_TYPE_RECORD:
2804
      for (int i = 0; i < vt->fields.count; i++) {
35,945✔
2805
         if (vtype_is_signal(vt->fields.items[i]))
28,084✔
2806
            return true;
2807
      }
2808
      return false;
2809
   case VCODE_TYPE_UARRAY:
58,376✔
2810
   case VCODE_TYPE_CARRAY:
2811
      return vtype_is_signal(vt->elem);
58,376✔
2812
   default:
135,231✔
2813
      return false;
135,231✔
2814
   }
2815
}
2816

2817
int vtype_repr_bits(vtype_repr_t repr)
356,342✔
2818
{
2819
   switch (repr) {
356,342✔
2820
   case VCODE_REPR_U1: return 1;
2821
   case VCODE_REPR_U8: case VCODE_REPR_I8: return 8;
2822
   case VCODE_REPR_U16: case VCODE_REPR_I16: return 16;
2823
   case VCODE_REPR_U32: case VCODE_REPR_I32: return 32;
2824
   case VCODE_REPR_U64: case VCODE_REPR_I64: return 64;
2825
   default: return -1;
2826
   }
2827
}
2828

2829
bool vtype_repr_signed(vtype_repr_t repr)
44,179✔
2830
{
2831
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
44,179✔
2832
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
44,179✔
2833
}
2834

2835
static int64_t vtype_repr_low(vtype_repr_t repr)
8,756✔
2836
{
2837
   switch (repr) {
8,756✔
2838
   case VCODE_REPR_U1:
2839
   case VCODE_REPR_U8:
2840
   case VCODE_REPR_U16:
2841
   case VCODE_REPR_U32:
2842
   case VCODE_REPR_U64: return 0;
2843
   case VCODE_REPR_I8:  return INT8_MIN;
2844
   case VCODE_REPR_I16: return INT16_MIN;
2845
   case VCODE_REPR_I32: return INT32_MIN;
2846
   case VCODE_REPR_I64: return INT64_MIN;
2847
   default:             return 0;
2848
   }
2849
}
2850

2851
static uint64_t vtype_repr_high(vtype_repr_t repr)
8,756✔
2852
{
2853
   switch (repr) {
8,756✔
2854
   case VCODE_REPR_U1:  return 1;
2855
   case VCODE_REPR_U8:  return UINT8_MAX;
2856
   case VCODE_REPR_U16: return UINT16_MAX;
2857
   case VCODE_REPR_U32: return UINT32_MAX;
2858
   case VCODE_REPR_U64: return UINT64_MAX;
2859
   case VCODE_REPR_I8:  return INT8_MAX;
2860
   case VCODE_REPR_I16: return INT16_MAX;
2861
   case VCODE_REPR_I32: return INT32_MAX;
2862
   case VCODE_REPR_I64: return INT64_MAX;
2863
   default:             return 0;
2864
   }
2865
}
2866

2867
static bool vtype_clamp_to_repr(vtype_repr_t repr, int64_t *low, int64_t *high)
8,756✔
2868
{
2869
   int64_t clamp_low = vtype_repr_low(repr);
8,756✔
2870
   uint64_t clamp_high = vtype_repr_high(repr);
8,756✔
2871

2872
   if (*low >= clamp_low && *high <= clamp_high)
8,756✔
2873
      return true;
2874
   else {
2875
      *low = MAX(clamp_low, *low);
4,656✔
2876
      *high = MIN(clamp_high, *high);
4,656✔
2877
      return false;
4,656✔
2878
   }
2879
}
2880

2881
int vcode_count_params(void)
10,764✔
2882
{
2883
   assert(active_unit != NULL);
10,764✔
2884
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
10,764✔
2885
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2886
          || active_unit->kind == VCODE_UNIT_PROPERTY
2887
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2888

2889
   return active_unit->params.count;
10,764✔
2890
}
2891

2892
vcode_type_t vcode_param_type(int param)
28,318✔
2893
{
2894
   assert(active_unit != NULL);
28,318✔
2895
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
28,318✔
2896
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2897
          || active_unit->kind == VCODE_UNIT_PROPERTY
2898
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2899
   assert(param < active_unit->params.count);
28,318✔
2900

2901
   return active_unit->params.items[param].type;
28,318✔
2902
}
2903

2904
vcode_reg_t vcode_param_reg(int param)
36,021✔
2905
{
2906
   assert(active_unit != NULL);
36,021✔
2907
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
36,021✔
2908
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2909
          || active_unit->kind == VCODE_UNIT_PROPERTY
2910
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2911
   assert(param < active_unit->params.count);
36,021✔
2912

2913
   return active_unit->params.items[param].reg;
36,021✔
2914
}
2915

2916
vcode_block_t emit_block(void)
131,444✔
2917
{
2918
   assert(active_unit != NULL);
131,444✔
2919

2920
   vcode_block_t bnum = active_unit->blocks.count;
131,444✔
2921

2922
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
131,444✔
2923
   memset(bptr, '\0', sizeof(block_t));
131,444✔
2924

2925
   if (active_block != VCODE_INVALID_BLOCK)
131,444✔
2926
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
89,530✔
2927
   else
2928
      bptr->last_loc = LOC_INVALID;
41,914✔
2929

2930
   return bnum;
131,444✔
2931
}
2932

2933
void vcode_select_unit(vcode_unit_t unit)
167,486✔
2934
{
2935
   active_unit  = unit;
167,486✔
2936
   active_block = VCODE_INVALID_BLOCK;
167,486✔
2937
}
167,486✔
2938

2939
void vcode_select_block(vcode_block_t block)
546,928✔
2940
{
2941
   assert(active_unit != NULL);
546,928✔
2942
   active_block = block;
546,928✔
2943
}
546,928✔
2944

2945
vcode_block_t vcode_active_block(void)
1,408,859✔
2946
{
2947
   assert(active_unit != NULL);
1,408,859✔
2948
   assert(active_block != -1);
1,408,859✔
2949
   return active_block;
1,408,859✔
2950
}
2951

2952
const loc_t *vcode_last_loc(void)
632,451✔
2953
{
2954
   return &(vcode_block_data()->last_loc);
632,451✔
2955
}
2956

2957
vcode_unit_t vcode_active_unit(void)
813✔
2958
{
2959
   assert(active_unit != NULL);
813✔
2960
   return active_unit;
813✔
2961
}
2962

2963
ident_t vcode_unit_name(vcode_unit_t vu)
150,627✔
2964
{
2965
   assert(vu != NULL);
150,627✔
2966
   return vu->name;
150,627✔
2967
}
2968

2969
bool vcode_unit_has_undefined(vcode_unit_t vu)
11,845✔
2970
{
2971
   assert(vu != NULL);
11,845✔
2972
   return !!(vu->flags & UNIT_UNDEFINED);
11,845✔
2973
}
2974

2975
bool vcode_unit_has_escaping_tlab(vcode_unit_t vu)
4,665✔
2976
{
2977
   return !!(vu->flags & UNIT_ESCAPING_TLAB);
4,665✔
2978
}
2979

UNCOV
2980
int vcode_unit_depth(vcode_unit_t vu)
×
2981
{
UNCOV
2982
   assert(vu != NULL);
×
2983
   return vu->depth;
×
2984
}
2985

2986
void vcode_set_result(vcode_type_t type)
21,089✔
2987
{
2988
   assert(active_unit != NULL);
21,089✔
2989
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
21,089✔
2990
          || active_unit->kind == VCODE_UNIT_THUNK);
2991

2992
   active_unit->result = type;
21,089✔
2993
}
21,089✔
2994

2995
vcode_type_t vcode_unit_result(vcode_unit_t vu)
31,025✔
2996
{
2997
   assert(vu != NULL);
31,025✔
2998
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
31,025✔
2999
   return vu->result;
31,025✔
3000
}
3001

3002
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
345,574✔
3003
{
3004
   assert(vu != NULL);
345,574✔
3005
   return vu->kind;
345,574✔
3006
}
3007

3008
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
128,339✔
3009
{
3010
   assert(vu != NULL);
128,339✔
3011
   return vu->context;
128,339✔
3012
}
3013

3014
void vcode_unit_object(vcode_unit_t vu, ident_t *module, ptrdiff_t *offset)
72,478✔
3015
{
3016
   assert(vu != NULL);
72,478✔
3017
   *module = vu->module;
72,478✔
3018
   *offset = vu->offset;
72,478✔
3019
}
72,478✔
3020

3021
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
53,768✔
3022
{
3023
   int hops = 0;
53,768✔
3024
   for (; (unit = unit->context); hops++)
131,273✔
3025
      ;
3026
   return hops;
53,768✔
3027
}
3028

3029
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
26,127✔
3030
{
3031
   assert(context->kind != VCODE_UNIT_THUNK);
26,127✔
3032

3033
   child->next = NULL;
26,127✔
3034
   if (context->children == NULL)
26,127✔
3035
      context->children = child;
10,543✔
3036
   else {
3037
      vcode_unit_t it;
3038
      for (it = context->children; it->next != NULL; it = it->next)
747,585✔
3039
         ;
3040
      it->next = child;
15,584✔
3041
   }
3042
}
26,127✔
3043

3044
vcode_unit_t emit_function(ident_t name, object_t *obj, vcode_unit_t context)
10,634✔
3045
{
3046
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
10,634✔
3047
   vu->kind     = VCODE_UNIT_FUNCTION;
10,634✔
3048
   vu->name     = name;
10,634✔
3049
   vu->context  = context;
10,634✔
3050
   vu->result   = VCODE_INVALID_TYPE;
10,634✔
3051
   vu->depth    = vcode_unit_calc_depth(vu);
10,634✔
3052

3053
   object_locus(obj, &vu->module, &vu->offset);
10,634✔
3054

3055
   vcode_add_child(context, vu);
10,634✔
3056

3057
   vcode_select_unit(vu);
10,634✔
3058
   vcode_select_block(emit_block());
10,634✔
3059
   emit_debug_info(&(obj->loc));
10,634✔
3060

3061
   return vu;
10,634✔
3062
}
3063

3064
vcode_unit_t emit_procedure(ident_t name, object_t *obj, vcode_unit_t context)
235✔
3065
{
3066
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
235✔
3067
   vu->kind     = VCODE_UNIT_PROCEDURE;
235✔
3068
   vu->name     = name;
235✔
3069
   vu->context  = context;
235✔
3070
   vu->result   = VCODE_INVALID_TYPE;
235✔
3071
   vu->depth    = vcode_unit_calc_depth(vu);
235✔
3072

3073
   object_locus(obj, &vu->module, &vu->offset);
235✔
3074

3075
   vcode_add_child(context, vu);
235✔
3076

3077
   vcode_select_unit(vu);
235✔
3078
   vcode_select_block(emit_block());
235✔
3079
   emit_debug_info(&(obj->loc));
235✔
3080

3081
   return vu;
235✔
3082
}
3083

3084
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
8,532✔
3085
{
3086
   assert(context->kind == VCODE_UNIT_INSTANCE
8,532✔
3087
          || context->kind == VCODE_UNIT_SHAPE);
3088

3089
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,532✔
3090
   vu->kind     = VCODE_UNIT_PROCESS;
8,532✔
3091
   vu->name     = name;
8,532✔
3092
   vu->context  = context;
8,532✔
3093
   vu->depth    = vcode_unit_calc_depth(vu);
8,532✔
3094
   vu->result   = VCODE_INVALID_TYPE;
8,532✔
3095

3096
   object_locus(obj, &vu->module, &vu->offset);
8,532✔
3097

3098
   vcode_add_child(context, vu);
8,532✔
3099

3100
   vcode_select_unit(vu);
8,532✔
3101
   vcode_select_block(emit_block());
8,532✔
3102
   emit_debug_info(&(obj->loc));
8,532✔
3103

3104
   return vu;
8,532✔
3105
}
3106

3107
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
8,663✔
3108
{
3109
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
8,663✔
3110

3111
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,663✔
3112
   vu->kind     = VCODE_UNIT_INSTANCE;
8,663✔
3113
   vu->name     = name;
8,663✔
3114
   vu->context  = context;
8,663✔
3115
   vu->depth    = vcode_unit_calc_depth(vu);
8,663✔
3116
   vu->result   = VCODE_INVALID_TYPE;
8,663✔
3117

3118
   object_locus(obj, &vu->module, &vu->offset);
8,663✔
3119

3120
   if (context != NULL)
8,663✔
3121
      vcode_add_child(context, vu);
5,379✔
3122

3123
   vcode_select_unit(vu);
8,663✔
3124
   vcode_select_block(emit_block());
8,663✔
3125
   emit_debug_info(&(obj->loc));
8,663✔
3126

3127
   return vu;
8,663✔
3128
}
3129

3130
vcode_unit_t emit_shape(ident_t name, object_t *obj, vcode_unit_t context)
51✔
3131
{
3132
   assert(context == NULL || context->kind == VCODE_UNIT_SHAPE);
51✔
3133

3134
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
51✔
3135
   vu->kind     = VCODE_UNIT_SHAPE;
51✔
3136
   vu->name     = name;
51✔
3137
   vu->context  = context;
51✔
3138
   vu->depth    = vcode_unit_calc_depth(vu);
51✔
3139
   vu->result   = VCODE_INVALID_TYPE;
51✔
3140

3141
   object_locus(obj, &vu->module, &vu->offset);
51✔
3142

3143
   if (context != NULL)
51✔
UNCOV
3144
      vcode_add_child(context, vu);
×
3145

3146
   vcode_select_unit(vu);
51✔
3147
   vcode_select_block(emit_block());
51✔
3148
   emit_debug_info(&(obj->loc));
51✔
3149

3150
   return vu;
51✔
3151
}
3152

3153
vcode_unit_t emit_package(ident_t name, object_t *obj, vcode_unit_t context)
1,671✔
3154
{
3155
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
1,671✔
3156
   vu->kind     = VCODE_UNIT_PACKAGE;
1,671✔
3157
   vu->name     = name;
1,671✔
3158
   vu->context  = context;
1,671✔
3159
   vu->depth    = vcode_unit_calc_depth(vu);
1,671✔
3160
   vu->result   = VCODE_INVALID_TYPE;
1,671✔
3161

3162
   object_locus(obj, &vu->module, &vu->offset);
1,671✔
3163

3164
   if (context != NULL)
1,671✔
3165
      vcode_add_child(context, vu);
170✔
3166

3167
   vcode_select_unit(vu);
1,671✔
3168
   vcode_select_block(emit_block());
1,671✔
3169
   emit_debug_info(&(obj->loc));
1,671✔
3170

3171
   return vu;
1,671✔
3172
}
3173

3174
vcode_unit_t emit_protected(ident_t name, object_t *obj, vcode_unit_t context)
166✔
3175
{
3176
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
166✔
3177
   vu->kind     = VCODE_UNIT_PROTECTED;
166✔
3178
   vu->name     = name;
166✔
3179
   vu->context  = context;
166✔
3180
   vu->depth    = vcode_unit_calc_depth(vu);
166✔
3181
   vu->result   = VCODE_INVALID_TYPE;
166✔
3182

3183
   object_locus(obj, &vu->module, &vu->offset);
166✔
3184

3185
   if (context != NULL)
166✔
3186
      vcode_add_child(context, vu);
166✔
3187

3188
   vcode_select_unit(vu);
166✔
3189
   vcode_select_block(emit_block());
166✔
3190
   emit_debug_info(&(obj->loc));
166✔
3191

3192
   return vu;
166✔
3193
}
3194

3195
vcode_unit_t emit_property(ident_t name, object_t *obj, vcode_unit_t context)
108✔
3196
{
3197
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
108✔
3198
   vu->kind     = VCODE_UNIT_PROPERTY;
108✔
3199
   vu->name     = name;
108✔
3200
   vu->context  = context;
108✔
3201
   vu->depth    = vcode_unit_calc_depth(vu);
108✔
3202
   vu->result   = VCODE_INVALID_TYPE;
108✔
3203

3204
   object_locus(obj, &vu->module, &vu->offset);
108✔
3205

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

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

3213
   return vu;
108✔
3214
}
3215

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

3226
   object_locus(obj, &vu->module, &vu->offset);
11,854✔
3227

3228
   if (context != NULL)
11,854✔
3229
      vcode_add_child(context, vu);
903✔
3230

3231
   vcode_select_unit(vu);
11,854✔
3232
   vcode_select_block(emit_block());
11,854✔
3233

3234
   return vu;
11,854✔
3235
}
3236

3237
void emit_assert(vcode_reg_t value, vcode_reg_t message, vcode_reg_t length,
13,209✔
3238
                 vcode_reg_t severity, vcode_reg_t locus, vcode_reg_t hint_left,
3239
                 vcode_reg_t hint_right)
3240
{
3241
   int64_t value_const;
13,209✔
3242
   if (vcode_reg_const(value, &value_const) && value_const != 0) {
13,209✔
UNCOV
3243
      emit_comment("Always true assertion on r%d", value);
×
UNCOV
3244
      return;
×
3245
   }
3246

3247
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
13,209✔
3248
   vcode_add_arg(op, value);
13,209✔
3249
   vcode_add_arg(op, severity);
13,209✔
3250
   vcode_add_arg(op, message);
13,209✔
3251
   vcode_add_arg(op, length);
13,209✔
3252
   vcode_add_arg(op, locus);
13,209✔
3253

3254
   if (hint_left != VCODE_INVALID_REG) {
13,209✔
3255
      vcode_add_arg(op, hint_left);
5,473✔
3256
      vcode_add_arg(op, hint_right);
5,473✔
3257

3258
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
5,473✔
3259
                   "left hint must be scalar");
3260
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
5,473✔
3261
                   "right hint must be scalar");
3262
   }
3263

3264
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
13,209✔
3265
                "value parameter to assert is not bool");
3266
   VCODE_ASSERT(message == VCODE_INVALID_REG
13,209✔
3267
                || vcode_reg_kind(message) == VCODE_TYPE_POINTER,
3268
                "message parameter to assert is not a pointer");
3269
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
13,209✔
3270
                "value parameter to assert is not bool");
3271
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
13,209✔
3272
                "locus argument to report must be a debug locus");
3273
}
3274

3275
void emit_report(vcode_reg_t message, vcode_reg_t length, vcode_reg_t severity,
2,171✔
3276
                 vcode_reg_t locus)
3277
{
3278
   op_t *op = vcode_add_op(VCODE_OP_REPORT);
2,171✔
3279
   vcode_add_arg(op, severity);
2,171✔
3280
   vcode_add_arg(op, message);
2,171✔
3281
   vcode_add_arg(op, length);
2,171✔
3282
   vcode_add_arg(op, locus);
2,171✔
3283

3284
   VCODE_ASSERT(vcode_reg_kind(message) == VCODE_TYPE_POINTER,
2,171✔
3285
                "message parameter to report is not a pointer");
3286
   VCODE_ASSERT(vtype_eq(vtype_pointed(vcode_reg_type(message)), vtype_char()),
2,171✔
3287
                "message parameter to report is not a character pointer");
3288
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,171✔
3289
                "locus argument to report must be a debug locus");
3290
}
2,171✔
3291

3292
vcode_reg_t emit_cmp(vcode_cmp_t cmp, vcode_reg_t lhs, vcode_reg_t rhs)
37,316✔
3293
{
3294
   if (lhs == rhs) {
37,316✔
3295
      if (cmp == VCODE_CMP_EQ)
928✔
3296
         return emit_const(vtype_bool(), 1);
921✔
3297
      else if (cmp == VCODE_CMP_NEQ)
7✔
UNCOV
3298
         return emit_const(vtype_bool(), 0);
×
3299
      else if (cmp == VCODE_CMP_LEQ || cmp == VCODE_CMP_GEQ)
7✔
UNCOV
3300
         return emit_const(vtype_bool(), 1);
×
3301
      else if (cmp == VCODE_CMP_LT || cmp == VCODE_CMP_GT)
7✔
3302
         return emit_const(vtype_bool(), 0);
7✔
3303
   }
3304

3305
   int64_t lconst, rconst;
36,388✔
3306
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)) {
36,388✔
3307
      switch (cmp) {
428✔
3308
      case VCODE_CMP_EQ:
244✔
3309
         return emit_const(vtype_bool(), lconst == rconst);
244✔
UNCOV
3310
      case VCODE_CMP_NEQ:
×
UNCOV
3311
         return emit_const(vtype_bool(), lconst != rconst);
×
3312
      case VCODE_CMP_LT:
3✔
3313
         return emit_const(vtype_bool(), lconst < rconst);
3✔
3314
      case VCODE_CMP_GT:
181✔
3315
         return emit_const(vtype_bool(), lconst > rconst);
181✔
UNCOV
3316
      case VCODE_CMP_LEQ:
×
UNCOV
3317
         return emit_const(vtype_bool(), lconst <= rconst);
×
UNCOV
3318
      case VCODE_CMP_GEQ:
×
3319
         return emit_const(vtype_bool(), lconst >= rconst);
×
3320
      default:
×
3321
         fatal_trace("cannot fold comparison %d", cmp);
×
3322
      }
3323
   }
3324

3325
   // Reuse any previous operation in this block with the same arguments
3326
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
646,826✔
3327
      if (other->args.count == 2 && other->args.items[0] == lhs
27,010✔
3328
          && other->args.items[1] == rhs && other->cmp == cmp)
1,124✔
3329
         return other->result;
185✔
3330
   }
3331

3332
   op_t *op = vcode_add_op(VCODE_OP_CMP);
35,775✔
3333
   vcode_add_arg(op, lhs);
35,775✔
3334
   vcode_add_arg(op, rhs);
35,775✔
3335
   op->cmp    = cmp;
35,775✔
3336
   op->result = vcode_add_reg(vtype_bool());
35,775✔
3337

3338
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
35,775✔
3339
                "arguments to cmp are not the same type");
3340

3341
   return op->result;
3342
}
3343

3344
vcode_reg_t emit_fcall(ident_t func, vcode_type_t type, vcode_type_t bounds,
34,897✔
3345
                       const vcode_reg_t *args, int nargs)
3346
{
3347
   op_t *o = vcode_add_op(VCODE_OP_FCALL);
34,897✔
3348
   o->func = func;
34,897✔
3349
   o->type = type;
34,897✔
3350
   for (int i = 0; i < nargs; i++)
137,280✔
3351
      vcode_add_arg(o, args[i]);
102,383✔
3352

3353
   for (int i = 0; i < nargs; i++)
137,280✔
3354
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
102,383✔
3355
                   "invalid argument to function");
3356

3357
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
34,897✔
3358
                "first argument to VHDL function must be context pointer");
3359

3360
   if (type == VCODE_INVALID_TYPE)
34,897✔
3361
      return (o->result = VCODE_INVALID_REG);
4,986✔
3362
   else {
3363
      o->result = vcode_add_reg(type);
29,911✔
3364

3365
      reg_t *rr = vcode_reg_data(o->result);
29,911✔
3366
      rr->bounds = bounds;
29,911✔
3367

3368
      return o->result;
29,911✔
3369
   }
3370
}
3371

3372
void emit_pcall(ident_t func, const vcode_reg_t *args, int nargs,
777✔
3373
                vcode_block_t resume_bb)
3374
{
3375
   op_t *o = vcode_add_op(VCODE_OP_PCALL);
777✔
3376
   o->func = func;
777✔
3377
   for (int i = 0; i < nargs; i++)
2,752✔
3378
      vcode_add_arg(o, args[i]);
1,975✔
3379

3380
   vcode_block_array_add(&(o->targets), resume_bb);
777✔
3381

3382
   for (int i = 0; i < nargs; i++)
2,752✔
3383
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
1,975✔
3384
                   "invalid argument to procedure");
3385

3386
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
777✔
3387
                "first argument to VHDL procedure must be context pointer");
3388
}
777✔
3389

3390
vcode_reg_t emit_alloc(vcode_type_t type, vcode_type_t bounds,
7,406✔
3391
                       vcode_reg_t count)
3392
{
3393
   op_t *op = vcode_add_op(VCODE_OP_ALLOC);
7,406✔
3394
   op->type    = type;
7,406✔
3395
   op->result  = vcode_add_reg(vtype_pointer(type));
7,406✔
3396
   vcode_add_arg(op, count);
7,406✔
3397

3398
   const vtype_kind_t tkind = vtype_kind(type);
7,406✔
3399
   VCODE_ASSERT(tkind != VCODE_TYPE_CARRAY && tkind != VCODE_TYPE_UARRAY,
7,406✔
3400
                "alloca element type cannot be array");
3401
   VCODE_ASSERT(count != VCODE_INVALID_REG,
7,406✔
3402
                "alloca must have valid count argument");
3403

3404
   reg_t *r = vcode_reg_data(op->result);
7,406✔
3405
   r->bounds = bounds;
7,406✔
3406

3407
   return op->result;
7,406✔
3408
}
3409

3410
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
926,895✔
3411
{
3412
   // Reuse any previous constant in this block with the same type and value
3413
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
19,978,698✔
3414
      if (other->value == value && vtype_eq(type, other->type))
7,496,287✔
3415
         return other->result;
544,603✔
3416
   }
3417

3418
   op_t *op = vcode_add_op(VCODE_OP_CONST);
382,292✔
3419
   op->value  = value;
382,292✔
3420
   op->type   = type;
382,292✔
3421
   op->result = vcode_add_reg(type);
382,292✔
3422

3423
   vtype_kind_t type_kind = vtype_kind(type);
382,292✔
3424
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
382,292✔
3425
                "constant must have integer or offset type");
3426

3427
   reg_t *r = vcode_reg_data(op->result);
382,292✔
3428
   r->bounds = vtype_int(value, value);
382,292✔
3429

3430
   return op->result;
382,292✔
3431
}
3432

3433
vcode_reg_t emit_const_real(vcode_type_t type, double value)
39,150✔
3434
{
3435
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REAL) {
1,431,825✔
3436
      if (other->real == value && other->type == type)
932,155✔
3437
         return other->result;
12,826✔
3438
   }
3439

3440
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
26,324✔
3441
   op->real   = value;
26,324✔
3442
   op->type   = type;
26,324✔
3443
   op->result = vcode_add_reg(op->type);
26,324✔
3444

3445
   reg_t *r = vcode_reg_data(op->result);
26,324✔
3446
   r->bounds = vtype_real(value, value);
26,324✔
3447

3448
   return op->result;
26,324✔
3449
}
3450

3451
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
26,394✔
3452
{
3453
   vtype_kind_t kind = vtype_kind(type);
26,394✔
3454

3455
   // Reuse any previous operation in this block with the same arguments
3456
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
1,126,392✔
3457
      if (other->args.count != num)
115,036✔
3458
         continue;
69,022✔
3459
      else if (!vtype_eq(vcode_reg_type(other->result), type))
46,014✔
3460
         continue;
586✔
3461

3462
      bool match = true;
3463
      for (int i = 0; match && i < num; i++) {
287,601✔
3464
         if (other->args.items[i] != values[i])
242,173✔
3465
            match = false;
39,423✔
3466
      }
3467

3468
      if (match) return other->result;
45,428✔
3469
   }
3470

3471
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
20,389✔
3472
   op->result = vcode_add_reg(type);
20,389✔
3473

3474
   for (int i = 0; i < num; i++)
1,159,354✔
3475
      vcode_add_arg(op, values[i]);
1,138,965✔
3476

3477
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
20,389✔
3478
                "constant array must have constrained array type");
3479
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
20,389✔
3480
                vtype_size(type), num);
3481

3482
#ifdef DEBUG
3483
   vcode_type_t elem = vtype_elem(type);
20,389✔
3484
   for (int i = 0; i < num; i++) {
1,159,354✔
3485
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
1,138,965✔
3486
                   "wrong element type for item %d", i);
3487
      vcode_assert_const(values[i], "array");
1,138,965✔
3488
   }
3489
#endif
3490

3491
   reg_t *r = vcode_reg_data(op->result);
20,389✔
3492
   r->bounds = vtype_elem(type);
20,389✔
3493

3494
   return op->result;
20,389✔
3495
}
3496

3497
vcode_reg_t emit_const_rep(vcode_type_t type, vcode_reg_t value, int rep)
1,031✔
3498
{
3499
   // Reuse any previous operation in this block with the same arguments
3500
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REP) {
21,520✔
3501
      if (other->args.items[0] == value && other->value == rep)
1,005✔
3502
         return other->result;
291✔
3503
   }
3504

3505
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
740✔
3506
   op->value = rep;
740✔
3507
   vcode_add_arg(op, value);
740✔
3508

3509
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
740✔
3510
                "constant array must have constrained array type");
3511

3512
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
740✔
3513

3514
   op->result = vcode_add_reg(type);
740✔
3515

3516
   reg_t *r = vcode_reg_data(op->result);
740✔
3517
   r->bounds = vtype_bounds(type);
740✔
3518

3519
   return op->result;
740✔
3520
}
3521

3522
vcode_reg_t emit_const_record(vcode_type_t type, vcode_reg_t *values, int num)
2,716✔
3523
{
3524
   // Reuse any previous constant in this block with the same type and value
3525
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_RECORD) {
56,751✔
3526
      if (other->args.count == num && vtype_eq(type, other->type)) {
1,571✔
3527
         bool same_regs = true;
3528
         for (int i = 0; same_regs && i < num; i++)
2,336✔
3529
            same_regs = other->args.items[i] == values[i];
1,406✔
3530

3531
         if (same_regs)
930✔
3532
            return other->result;
217✔
3533
      }
3534
   }
3535

3536
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
2,499✔
3537
   op->type   = type;
2,499✔
3538
   op->result = vcode_add_reg(type);
2,499✔
3539

3540
   for (int i = 0; i < num; i++)
9,677✔
3541
      vcode_add_arg(op, values[i]);
7,178✔
3542

3543
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
2,499✔
3544
                "constant record must have record type");
3545

3546
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
2,499✔
3547
                vtype_fields(type), num);
3548

3549
#ifdef DEBUG
3550
   for (int i = 0; i < num; i++) {
9,677✔
3551
      VCODE_ASSERT(vtype_eq(vtype_field(type, i), vcode_reg_type(values[i])),
7,178✔
3552
                   "wrong type for field %d", i);
3553
      vcode_assert_const(values[i], "record");
7,178✔
3554
   }
3555
#endif
3556

3557
   return op->result;
2,499✔
3558
}
3559

3560
vcode_reg_t emit_address_of(vcode_reg_t value)
28,606✔
3561
{
3562
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
1,220,437✔
3563
      if (other->args.items[0] == value)
116,379✔
3564
         return other->result;
6,036✔
3565
   }
3566

3567
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
22,570✔
3568
   vcode_add_arg(op, value);
22,570✔
3569

3570
   vcode_type_t type = vcode_reg_type(value);
22,570✔
3571
   VCODE_ASSERT(vtype_is_composite(type),
22,570✔
3572
                "address of argument must be record or array");
3573

3574
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
22,570✔
3575
      vcode_type_t elem = vtype_elem(type);
20,569✔
3576
      op->result = vcode_add_reg(vtype_pointer(elem));
20,569✔
3577

3578
      reg_t *rr = vcode_reg_data(op->result);
20,569✔
3579
      rr->bounds = elem;
20,569✔
3580

3581
      return op->result;
20,569✔
3582
   }
3583
   else
3584
      return (op->result = vcode_add_reg(vtype_pointer(type)));
2,001✔
3585
}
3586

3587
void emit_wait(vcode_block_t target, vcode_reg_t time)
12,443✔
3588
{
3589
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
12,443✔
3590
   vcode_add_target(op, target);
12,443✔
3591
   vcode_add_arg(op, time);
12,443✔
3592

3593
   VCODE_ASSERT(time == VCODE_INVALID_REG
12,443✔
3594
                || vcode_reg_kind(time) == VCODE_TYPE_INT,
3595
                "wait time must have integer type");
3596
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_PROCEDURE
12,443✔
3597
                || active_unit->kind == VCODE_UNIT_PROCESS,
3598
                "wait only allowed in process or procedure");
3599
}
12,443✔
3600

3601
void emit_jump(vcode_block_t target)
34,176✔
3602
{
3603
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
34,176✔
3604
   vcode_add_target(op, target);
34,176✔
3605

3606
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
34,176✔
3607
}
34,176✔
3608

3609
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
45,932✔
3610
                     vcode_var_flags_t flags)
3611
{
3612
   assert(active_unit != NULL);
45,932✔
3613

3614
   vcode_var_t var = active_unit->vars.count;
45,932✔
3615
   var_t *v = var_array_alloc(&(active_unit->vars));
45,932✔
3616
   memset(v, '\0', sizeof(var_t));
45,932✔
3617
   v->type     = type;
45,932✔
3618
   v->bounds   = bounds;
45,932✔
3619
   v->name     = name;
45,932✔
3620
   v->flags    = flags;
45,932✔
3621

3622
   return var;
45,932✔
3623
}
3624

3625
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
30,279✔
3626
{
3627
   assert(active_unit != NULL);
30,279✔
3628

3629
   param_t *p = param_array_alloc(&(active_unit->params));
30,279✔
3630
   memset(p, '\0', sizeof(param_t));
30,279✔
3631
   p->type   = type;
30,279✔
3632
   p->bounds = bounds;
30,279✔
3633
   p->name   = name;
30,279✔
3634
   p->reg    = vcode_add_reg(type);
30,279✔
3635

3636
   reg_t *rr = vcode_reg_data(p->reg);
30,279✔
3637
   rr->bounds = bounds;
30,279✔
3638

3639
   return p->reg;
30,279✔
3640
}
3641

3642
vcode_reg_t emit_load(vcode_var_t var)
52,961✔
3643
{
3644
   // Try scanning backwards through the block for another load or store to
3645
   // this variable
3646
   enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER;
52,961✔
3647
   vcode_reg_t fold = VCODE_INVALID_REG;
52,961✔
3648
   VCODE_FOR_EACH_OP(other) {
616,694✔
3649
      switch (state) {
580,583✔
3650
      case EAGER:
317,178✔
3651
         if (other->kind == VCODE_OP_LOAD && other->address == var)
317,178✔
3652
            return other->result;
3,073✔
3653
         else if (other->kind == VCODE_OP_STORE && other->address == var)
314,105✔
3654
            return other->args.items[0];
13,777✔
3655
         else if (other->kind == VCODE_OP_FCALL
300,328✔
3656
                  || other->kind == VCODE_OP_PCALL
300,328✔
3657
                  || other->kind == VCODE_OP_FILE_READ
3658
                  || other->kind == VCODE_OP_FILE_OPEN
3659
                  || other->kind == VCODE_OP_STORE_INDIRECT
3660
                  || other->kind == VCODE_OP_DEALLOCATE)
3661
            state = CONSERVATIVE;   // May write to variable
7,666✔
3662
         break;
3663

3664
      case CONSERVATIVE:
239,407✔
3665
         if (other->kind == VCODE_OP_LOAD && other->address == var
239,407✔
3666
             && fold == VCODE_INVALID_REG)
4,304✔
3667
            fold = other->result;
3,457✔
3668
         else if (other->kind == VCODE_OP_STORE && other->address == var
235,950✔
3669
                  && fold == VCODE_INVALID_REG)
1,339✔
3670
            fold = other->args.items[0];
1,208✔
3671
         else if (other->kind == VCODE_OP_INDEX && other->address == var)
234,742✔
3672
            state = UNSAFE;
3673
         else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0)
233,781✔
3674
            state = UNSAFE;   // Nested call captures variables
80✔
3675
         break;
3676

3677
      case UNSAFE:
3678
         break;
3679
      }
3680
   }
3681

3682
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
36,111✔
3683
      return fold;
3684

3685
   var_t *v = vcode_var_data(var);
31,793✔
3686

3687
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
31,793✔
3688
   op->address = var;
31,793✔
3689
   op->result  = vcode_add_reg(v->type);
31,793✔
3690

3691
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot load non-scalar type");
31,793✔
3692

3693
   reg_t *r = vcode_reg_data(op->result);
31,793✔
3694
   r->bounds = v->bounds;
31,793✔
3695

3696
   return op->result;
31,793✔
3697
}
3698

3699
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
85,710✔
3700
{
3701
   VCODE_FOR_EACH_OP(other) {
1,025,374✔
3702
      if (other->kind == VCODE_OP_LOAD_INDIRECT
965,255✔
3703
          && other->args.items[0] == reg) {
138,577✔
3704
         return other->result;
6,880✔
3705
      }
3706
      else if (other->kind == VCODE_OP_FCALL
958,375✔
3707
               || other->kind == VCODE_OP_PCALL
958,375✔
3708
               || other->kind == VCODE_OP_STORE
3709
               || other->kind == VCODE_OP_STORE_INDIRECT
3710
               || other->kind == VCODE_OP_MEMSET
3711
               || other->kind == VCODE_OP_COPY
3712
               || other->kind == VCODE_OP_FILE_READ)
3713
         break;   // May write to this pointer
3714
   }
3715

3716
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
78,830✔
3717
   vcode_add_arg(op, reg);
78,830✔
3718

3719
   vcode_type_t rtype = vcode_reg_type(reg);
78,830✔
3720

3721
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
78,830✔
3722
                "load indirect with non-pointer argument");
3723

3724
   vcode_type_t deref = vtype_pointed(rtype);
78,830✔
3725
   op->result = vcode_add_reg(deref);
78,830✔
3726

3727
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
78,830✔
3728

3729
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
78,830✔
3730

3731
   return op->result;
78,830✔
3732
}
3733

3734
void emit_store(vcode_reg_t reg, vcode_var_t var)
56,278✔
3735
{
3736
   // Any previous store to this variable in this block is dead
3737
   VCODE_FOR_EACH_OP(other) {
1,089,078✔
3738
      if (other->kind == VCODE_OP_STORE && other->address == var) {
1,044,313✔
3739
         other->kind = VCODE_OP_COMMENT;
255✔
3740
         other->comment =
510✔
3741
            xasprintf("Dead store to %s", istr(vcode_var_name(var)));
255✔
3742
         vcode_reg_array_resize(&(other->args), 0, VCODE_INVALID_REG);
255✔
3743
      }
3744
      else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL)
1,044,058✔
3745
         break;   // Needs to get variable for display
3746
      else if ((other->kind == VCODE_OP_INDEX || other->kind == VCODE_OP_LOAD)
1,038,288✔
3747
               && other->address == var)
23,114✔
3748
         break;   // Previous value may be used
3749
   }
3750

3751
   var_t *v = vcode_var_data(var);
56,278✔
3752
   reg_t *r = vcode_reg_data(reg);
56,278✔
3753

3754
   op_t *op = vcode_add_op(VCODE_OP_STORE);
56,278✔
3755
   vcode_add_arg(op, reg);
56,278✔
3756
   op->address = var;
56,278✔
3757

3758
   VCODE_ASSERT(vtype_eq(v->type, r->type),
56,278✔
3759
                "variable and stored value do not have same type");
3760
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
56,278✔
3761
}
56,278✔
3762

3763
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
11,800✔
3764
{
3765
   reg_t *p = vcode_reg_data(ptr);
11,800✔
3766
   reg_t *r = vcode_reg_data(reg);
11,800✔
3767

3768
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
11,800✔
3769
   vcode_add_arg(op, reg);
11,800✔
3770
   vcode_add_arg(op, ptr);
11,800✔
3771

3772
   VCODE_ASSERT(vtype_kind(p->type) == VCODE_TYPE_POINTER,
11,800✔
3773
                "store indirect target is not a pointer");
3774
   VCODE_ASSERT(vtype_eq(vtype_pointed(p->type), r->type),
11,800✔
3775
                "pointer and stored value do not have same type");
3776
   VCODE_ASSERT(vtype_is_scalar(r->type), "cannot store non-scalar type");
11,800✔
3777
}
11,800✔
3778

3779
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
48,737✔
3780
                              vcode_reg_t locus)
3781
{
3782
   // Reuse any previous operation in this block with the same arguments
3783
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,026,852✔
3784
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
58,310✔
3785
         return other->result;
3,058✔
3786
   }
3787

3788
   op_t *op = vcode_add_op(kind);
45,679✔
3789
   vcode_add_arg(op, lhs);
45,679✔
3790
   vcode_add_arg(op, rhs);
45,679✔
3791
   if (locus != VCODE_INVALID_REG)
45,679✔
3792
      vcode_add_arg(op, locus);
4,896✔
3793

3794
   op->result = vcode_add_reg(vcode_reg_type(lhs));
45,679✔
3795

3796
   vcode_type_t lhs_type = vcode_reg_type(lhs);
45,679✔
3797
   vcode_type_t rhs_type = vcode_reg_type(rhs);
45,679✔
3798

3799
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
45,679✔
3800
                "arguments to %s are not the same type", vcode_op_string(kind));
3801

3802
   return op->result;
3803
}
3804

3805
static vcode_reg_t emit_mul_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
33,757✔
3806
                               vcode_reg_t locus)
3807
{
3808
   int64_t lconst, rconst;
33,757✔
3809
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
33,757✔
3810
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
33,757✔
3811
   if (l_is_const && r_is_const)
33,757✔
3812
      return emit_const(vcode_reg_type(lhs), lconst * rconst);
18,969✔
3813
   else if (r_is_const && rconst == 1)
14,788✔
3814
      return lhs;
3815
   else if (l_is_const && lconst == 1)
3,369✔
3816
      return rhs;
3817
   else if ((r_is_const && rconst == 0) || (l_is_const && lconst == 0))
2,941✔
3818
      return emit_const(vcode_reg_type(lhs), 0);
42✔
3819

3820
   reg_t *lhs_r = vcode_reg_data(lhs);
2,899✔
3821
   reg_t *rhs_r = vcode_reg_data(rhs);
2,899✔
3822

3823
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
2,899✔
3824
   vtype_t *br = vcode_type_data(rhs_r->bounds);
2,899✔
3825

3826
   vcode_type_t vbounds;
2,899✔
3827
   if (vcode_reg_kind(lhs) == VCODE_TYPE_REAL) {
2,899✔
3828
      const double ll = bl->rlow * br->rlow;
740✔
3829
      const double lh = bl->rlow * br->rhigh;
740✔
3830
      const double hl = bl->rhigh * br->rlow;
740✔
3831
      const double hh = bl->rhigh * br->rhigh;
740✔
3832

3833
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
1,596✔
3834
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
1,818✔
3835

3836
      vbounds = vtype_real(min, max);
740✔
3837
   }
3838
   else {
3839
      const int64_t ll = smul64(bl->low, br->low);
2,159✔
3840
      const int64_t lh = smul64(bl->low, br->high);
2,159✔
3841
      const int64_t hl = smul64(bl->high, br->low);
2,159✔
3842
      const int64_t hh = smul64(bl->high, br->high);
2,159✔
3843

3844
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
2,159✔
3845
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
2,159✔
3846

3847
      vtype_repr_t repr = vtype_repr(lhs_r->type);
2,159✔
3848
      if (op == VCODE_OP_TRAP_MUL && vtype_clamp_to_repr(repr, &min, &max)) {
2,159✔
3849
         op = VCODE_OP_MUL;   // Cannot overflow
379✔
3850
         locus = VCODE_INVALID_REG;
379✔
3851
      }
3852

3853
      vbounds = vtype_int(min, max);
2,159✔
3854
   }
3855

3856
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
2,899✔
3857

3858
   if (vbounds != VCODE_INVALID_TYPE)
2,899✔
3859
      vcode_reg_data(reg)->bounds = vbounds;
2,899✔
3860

3861
   return reg;
3862
}
3863

3864
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
32,911✔
3865
{
3866
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
32,911✔
3867
}
3868

3869
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
846✔
3870
{
3871
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
846✔
3872

3873
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
846✔
3874
                "trapping add may only be used with integer types");
3875

3876
   return result;
846✔
3877
}
3878

3879
vcode_reg_t emit_div(vcode_reg_t lhs, vcode_reg_t rhs)
1,001✔
3880
{
3881
   int64_t lconst, rconst;
1,001✔
3882
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
1,001✔
3883
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
1,001✔
3884
   if (l_is_const && r_is_const && rconst != 0)
1,001✔
3885
      return emit_const(vcode_reg_type(lhs), lconst / rconst);
32✔
3886
   else if (r_is_const && rconst == 1)
969✔
3887
      return lhs;
3888

3889
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
968✔
3890

3891
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
968✔
3892

3893
   if (bl->kind == VCODE_TYPE_INT && r_is_const && rconst != 0) {
968✔
3894
      reg_t *rr = vcode_reg_data(reg);
675✔
3895
      rr->bounds = vtype_int(bl->low / rconst, bl->high / rconst);
675✔
3896
   }
3897
   else if (bl->kind == VCODE_TYPE_REAL) {
293✔
3898
      reg_t *rr = vcode_reg_data(reg);
225✔
3899
      rr->bounds = vtype_real(-INFINITY, INFINITY);
225✔
3900
   }
3901

3902
   return reg;
3903
}
3904

3905
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
79✔
3906
{
3907
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
79✔
3908
}
3909

3910
vcode_reg_t emit_trap_exp(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
1,572✔
3911
{
3912
   int64_t rconst;
1,572✔
3913
   if (vcode_reg_const(rhs, &rconst)) {
1,572✔
3914
      if (rconst == 0)
1,463✔
3915
         return emit_const(vcode_reg_type(lhs), 1);
799✔
3916
      else if (rconst == 1)
664✔
3917
         return lhs;
3918
   }
3919

3920
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
580✔
3921

3922
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
580✔
3923
                "trapping exp may only be used with integer types");
3924

3925
   return result;
3926
}
3927

3928
vcode_reg_t emit_mod(vcode_reg_t lhs, vcode_reg_t rhs)
199✔
3929
{
3930
   int64_t lconst, rconst;
199✔
3931
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
199✔
3932
       && lconst > 0 && rconst > 0)
15✔
3933
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
3✔
3934

3935
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
196✔
3936
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
196✔
3937

3938
   if (bl->low >= 0 && br->low >= 0) {
196✔
3939
      // If both arguments are non-negative then rem is equivalent and
3940
      // cheaper to compute
3941
      vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
28✔
3942

3943
      reg_t *rr = vcode_reg_data(reg);
28✔
3944
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
28✔
3945

3946
      return reg;
28✔
3947
   }
3948
   else
3949
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
168✔
3950
}
3951

3952
vcode_reg_t emit_rem(vcode_reg_t lhs, vcode_reg_t rhs)
74✔
3953
{
3954
   int64_t lconst, rconst;
74✔
3955
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
74✔
3956
       && lconst > 0 && rconst > 0)
2✔
UNCOV
3957
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
×
3958

3959
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
74✔
3960

3961
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
74✔
3962
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
74✔
3963

3964
   if (bl->low >= 0 && br->low >= 0) {
74✔
3965
      reg_t *rr = vcode_reg_data(reg);
15✔
3966
      rr->bounds = vtype_int(0, br->high - 1);
15✔
3967
   }
3968

3969
   return reg;
3970
}
3971

3972
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
42,227✔
3973
                               vcode_reg_t locus)
3974
{
3975
   int64_t lconst, rconst;
42,227✔
3976
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
42,227✔
3977
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
42,227✔
3978
   if (l_is_const && r_is_const)
42,227✔
3979
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
17,265✔
3980
   else if (r_is_const && rconst == 0)
24,962✔
3981
      return lhs;
3982
   else if (l_is_const && lconst == 0)
24,956✔
3983
      return rhs;
3984

3985
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
15,416✔
3986
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
15,416✔
3987
      reg_t *lhs_r = vcode_reg_data(lhs);
15,129✔
3988
      reg_t *rhs_r = vcode_reg_data(rhs);
15,129✔
3989

3990
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
15,129✔
3991
      vtype_t *br = vcode_type_data(rhs_r->bounds);
15,129✔
3992

3993
      int64_t rbl = sadd64(bl->low, br->low);
15,129✔
3994
      int64_t rbh = sadd64(bl->high, br->high);
15,129✔
3995

3996
      vtype_repr_t repr = vtype_repr(lhs_r->type);
15,129✔
3997
      if (op == VCODE_OP_TRAP_ADD && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
15,129✔
3998
         op = VCODE_OP_ADD;   // Cannot overflow
752✔
3999
         locus = VCODE_INVALID_REG;
752✔
4000
      }
4001

4002
      vbounds = vtype_int(rbl, rbh);
15,129✔
4003
   }
4004

4005
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
15,416✔
4006

4007
   if (vbounds != VCODE_INVALID_TYPE)
15,416✔
4008
      vcode_reg_data(reg)->bounds = vbounds;
15,129✔
4009

4010
   return reg;
4011
}
4012

4013
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
39,433✔
4014
{
4015
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
39,433✔
4016
}
4017

4018
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
2,794✔
4019
{
4020
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
2,794✔
4021

4022
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
2,794✔
4023
                "trapping add may only be used with integer types");
4024

4025
   return result;
2,794✔
4026
}
4027

4028
static vcode_reg_t emit_sub_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
39,319✔
4029
                               vcode_reg_t locus)
4030
{
4031
   int64_t lconst, rconst;
39,319✔
4032
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
39,319✔
4033
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
39,319✔
4034
   if (l_is_const && r_is_const)
39,319✔
4035
      return emit_const(vcode_reg_type(lhs), lconst - rconst);
13,299✔
4036
   else if (r_is_const && rconst == 0)
26,020✔
4037
      return lhs;
4038
   else if (l_is_const && lconst == 0)
23,904✔
4039
      return emit_neg(rhs);
1,254✔
4040

4041
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
22,650✔
4042
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
22,650✔
4043
      reg_t *lhs_r = vcode_reg_data(lhs);
22,344✔
4044
      reg_t *rhs_r = vcode_reg_data(rhs);
22,344✔
4045

4046
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
22,344✔
4047
      vtype_t *br = vcode_type_data(rhs_r->bounds);
22,344✔
4048

4049
      int64_t rbl = ssub64(bl->low, br->high);
22,344✔
4050
      int64_t rbh = ssub64(bl->high, br->low);
22,344✔
4051

4052
      vtype_repr_t repr = vtype_repr(lhs_r->type);
22,344✔
4053
      if (op == VCODE_OP_TRAP_SUB && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
22,344✔
4054
         op = VCODE_OP_SUB;   // Cannot overflow
2,969✔
4055
         locus = VCODE_INVALID_REG;
2,969✔
4056
      }
4057

4058
      vbounds = vtype_int(rbl, rbh);
22,344✔
4059
   }
4060

4061
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
22,650✔
4062

4063
   if (vbounds != VCODE_INVALID_TYPE)
22,650✔
4064
      vcode_reg_data(reg)->bounds = vbounds;
22,344✔
4065

4066
   return reg;
4067
}
4068

4069
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
32,702✔
4070
{
4071
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
32,702✔
4072
}
4073

4074
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
6,617✔
4075
{
4076
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
6,617✔
4077

4078
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
6,617✔
4079
                "trapping sub may only be used with integer types");
4080

4081
   return result;
6,617✔
4082
}
4083

4084
static void vcode_calculate_var_index_type(op_t *op, var_t *var)
55,941✔
4085
{
4086
   switch (vtype_kind(var->type)) {
55,941✔
4087
   case VCODE_TYPE_CARRAY:
11,448✔
4088
      op->type = vtype_pointer(vtype_elem(var->type));
11,448✔
4089
      op->result = vcode_add_reg(op->type);
11,448✔
4090
      vcode_reg_data(op->result)->bounds = vtype_bounds(var->type);
11,448✔
4091
      break;
11,448✔
4092

4093
   case VCODE_TYPE_RECORD:
5,968✔
4094
      op->type = vtype_pointer(var->type);
5,968✔
4095
      op->result = vcode_add_reg(op->type);
5,968✔
4096
      break;
5,968✔
4097

4098
   case VCODE_TYPE_INT:
38,525✔
4099
   case VCODE_TYPE_FILE:
4100
   case VCODE_TYPE_ACCESS:
4101
   case VCODE_TYPE_REAL:
4102
   case VCODE_TYPE_UARRAY:
4103
   case VCODE_TYPE_POINTER:
4104
   case VCODE_TYPE_SIGNAL:
4105
   case VCODE_TYPE_CONTEXT:
4106
   case VCODE_TYPE_OFFSET:
4107
   case VCODE_TYPE_TRIGGER:
4108
      op->type = vtype_pointer(var->type);
38,525✔
4109
      op->result = vcode_add_reg(op->type);
38,525✔
4110
      vcode_reg_data(op->result)->bounds = var->bounds;
38,525✔
4111
      break;
38,525✔
4112

4113
   default:
UNCOV
4114
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4115
                   istr(var->name));
4116
   }
4117
}
55,941✔
4118

4119
vcode_reg_t emit_index(vcode_var_t var, vcode_reg_t offset)
21,435✔
4120
{
4121
   // Try to find a previous index of this var by this offset
4122
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_INDEX) {
738,572✔
4123
      if (other->address == var
46,498✔
4124
          && ((offset == VCODE_INVALID_REG && other->args.count == 0)
6,937✔
UNCOV
4125
              || (offset != VCODE_INVALID_REG
×
UNCOV
4126
                  && other->args.items[0] == offset)))
×
4127
         return other->result;
6,937✔
4128
   }
4129

4130
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
14,498✔
4131
   op->address = var;
14,498✔
4132

4133
   if (offset != VCODE_INVALID_REG)
14,498✔
UNCOV
4134
      vcode_add_arg(op, offset);
×
4135

4136
   vcode_calculate_var_index_type(op, vcode_var_data(var));
14,498✔
4137

4138
   if (offset != VCODE_INVALID_REG)
14,498✔
UNCOV
4139
      VCODE_ASSERT(vtype_kind(vcode_reg_type(offset)) == VCODE_TYPE_OFFSET,
×
4140
                   "index offset r%d does not have offset type", offset);
4141

4142
   return op->result;
14,498✔
4143
}
4144

4145
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
202,606✔
4146
{
4147
   if (vtype_eq(vcode_reg_type(reg), type))
202,606✔
4148
      return reg;
202,606✔
4149

4150
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
76,016✔
4151
   vtype_kind_t to   = vtype_kind(type);
76,016✔
4152

4153
   const bool integral =
152,032✔
4154
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
76,016✔
4155
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
76,016✔
4156

4157
   int64_t value;
76,016✔
4158
   if (integral && vcode_reg_const(reg, &value))
76,016✔
4159
      return emit_const(type, value);
14,447✔
4160

4161
   // Try to find a previous cast of this register to this type
4162
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CAST) {
1,211,405✔
4163
      if (vtype_eq(other->type, type) && other->args.items[0] == reg)
137,015✔
4164
         return other->result;
14,517✔
4165
   }
4166

4167
   op_t *op = vcode_add_op(VCODE_OP_CAST);
47,052✔
4168
   vcode_add_arg(op, reg);
47,052✔
4169
   op->type   = type;
47,052✔
4170
   op->result = vcode_add_reg(type);
47,052✔
4171

4172
   static const vcode_type_t allowed[][2] = {
47,052✔
4173
      { VCODE_TYPE_INT,    VCODE_TYPE_OFFSET  },
4174
      { VCODE_TYPE_OFFSET, VCODE_TYPE_INT     },
4175
      { VCODE_TYPE_INT,    VCODE_TYPE_INT     },
4176
      { VCODE_TYPE_INT,    VCODE_TYPE_REAL    },
4177
      { VCODE_TYPE_REAL,   VCODE_TYPE_INT     },
4178
      { VCODE_TYPE_REAL,   VCODE_TYPE_REAL    },
4179
      { VCODE_TYPE_ACCESS, VCODE_TYPE_ACCESS  },
4180
   };
4181

4182
   if (from == VCODE_TYPE_INT && bounds == VCODE_INVALID_TYPE) {
47,052✔
4183
      reg_t *rr = vcode_reg_data(op->result);
9,987✔
4184
      rr->bounds = vcode_reg_bounds(reg);
9,987✔
4185
   }
4186
   else if (to == VCODE_TYPE_INT && bounds != VCODE_INVALID_TYPE) {
37,065✔
4187
      reg_t *rr = vcode_reg_data(op->result);
30,654✔
4188
      rr->bounds = bounds;
30,654✔
4189
   }
4190

4191
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
86,047✔
4192
      if (from == allowed[i][0] && to == allowed[i][1])
86,047✔
4193
         return op->result;
4194
   }
4195

UNCOV
4196
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4197
}
4198

4199
void emit_return(vcode_reg_t reg)
50,295✔
4200
{
4201
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
50,295✔
4202
   if (reg != VCODE_INVALID_REG) {
50,295✔
4203
      vcode_add_arg(op, reg);
27,803✔
4204

4205
      const vtype_kind_t rkind = vcode_reg_kind(reg);
27,803✔
4206
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
27,803✔
4207
         vcode_heap_allocate(reg);
8,169✔
4208
         active_unit->flags |= UNIT_ESCAPING_TLAB;
8,169✔
4209
      }
4210

4211
      VCODE_ASSERT(active_unit->kind == VCODE_UNIT_FUNCTION
27,803✔
4212
                   || active_unit->kind == VCODE_UNIT_THUNK
4213
                   || active_unit->kind == VCODE_UNIT_PROPERTY,
4214
                   "returning value fron non-function unit");
4215
      VCODE_ASSERT((active_unit->kind == VCODE_UNIT_PROPERTY
27,803✔
4216
                    && rkind == VCODE_TYPE_INT)
4217
                   || vtype_eq(active_unit->result, vcode_reg_type(reg))
4218
                   || (vtype_kind(active_unit->result) == VCODE_TYPE_ACCESS
4219
                       && rkind == VCODE_TYPE_ACCESS),
4220
                   "return value incorrect type");
4221
   }
4222
}
50,295✔
4223

4224
void emit_sched_waveform(vcode_reg_t nets, vcode_reg_t nnets,
9,885✔
4225
                         vcode_reg_t values, vcode_reg_t reject,
4226
                         vcode_reg_t after)
4227
{
4228
   int64_t nconst;
9,885✔
4229
   if (vcode_reg_const(nnets, &nconst) && nconst == 0) {
9,885✔
4230
      emit_comment("Skip empty waveform");
6✔
4231
      return;
6✔
4232
   }
4233

4234
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
9,879✔
4235
   vcode_add_arg(op, nets);
9,879✔
4236
   vcode_add_arg(op, nnets);
9,879✔
4237
   vcode_add_arg(op, values);
9,879✔
4238
   vcode_add_arg(op, reject);
9,879✔
4239
   vcode_add_arg(op, after);
9,879✔
4240

4241
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
9,879✔
4242
                "sched_waveform target is not signal");
4243
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
9,879✔
4244
                "sched_waveform net count is not offset type");
4245
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
9,879✔
4246
                "signal cannot be values argument for sched_waveform");
4247
}
4248

4249
void emit_force(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t values)
54✔
4250
{
4251
   op_t *op = vcode_add_op(VCODE_OP_FORCE);
54✔
4252
   vcode_add_arg(op, nets);
54✔
4253
   vcode_add_arg(op, nnets);
54✔
4254
   vcode_add_arg(op, values);
54✔
4255

4256
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
54✔
4257
                "force target is not signal");
4258
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
54✔
4259
                "force net count is not offset type");
4260
}
54✔
4261

4262
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
30✔
4263
{
4264
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
30✔
4265
   vcode_add_arg(op, nets);
30✔
4266
   vcode_add_arg(op, nnets);
30✔
4267

4268
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
30✔
4269
                "release target is not signal");
4270
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
30✔
4271
                "release net count is not offset type");
4272
}
30✔
4273

4274
void emit_disconnect(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t reject,
21✔
4275
                     vcode_reg_t after)
4276
{
4277
   op_t *op = vcode_add_op(VCODE_OP_DISCONNECT);
21✔
4278
   vcode_add_arg(op, nets);
21✔
4279
   vcode_add_arg(op, nnets);
21✔
4280
   vcode_add_arg(op, reject);
21✔
4281
   vcode_add_arg(op, after);
21✔
4282

4283
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
21✔
4284
                "disconnect target is not signal");
4285
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
21✔
4286
                "disconnect net count is not offset type");
4287
}
21✔
4288

4289
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
35,428✔
4290
{
4291
   int64_t tconst;
35,428✔
4292
   if (vcode_reg_const(test, &tconst)) {
35,428✔
4293
      emit_jump(!!tconst ? btrue : bfalse);
4,585✔
4294
      return;
2,725✔
4295
   }
4296

4297
   op_t *op = vcode_add_op(VCODE_OP_COND);
32,703✔
4298
   vcode_add_arg(op, test);
32,703✔
4299
   vcode_add_target(op, btrue);
32,703✔
4300
   vcode_add_target(op, bfalse);
32,703✔
4301

4302
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
32,703✔
4303
                "cond test is not a bool");
4304
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
32,703✔
4305
                "invalid cond targets");
4306
}
4307

4308
vcode_reg_t emit_neg(vcode_reg_t lhs)
7,433✔
4309
{
4310
   int64_t lconst;
7,433✔
4311
   if (vcode_reg_const(lhs, &lconst))
7,433✔
UNCOV
4312
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4313

4314
   op_t *op = vcode_add_op(VCODE_OP_NEG);
7,433✔
4315
   vcode_add_arg(op, lhs);
7,433✔
4316
   op->result = vcode_add_reg(vcode_reg_type(lhs));
7,433✔
4317

4318
   return op->result;
7,433✔
4319
}
4320

4321
vcode_reg_t emit_trap_neg(vcode_reg_t lhs, vcode_reg_t locus)
785✔
4322
{
4323
   int64_t lconst;
785✔
4324
   if (vcode_reg_const(lhs, &lconst) && lconst >= 0)
785✔
UNCOV
4325
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4326
   else if (vcode_type_data(vcode_reg_data(lhs)->bounds)->low >= 0)
785✔
4327
      return emit_neg(lhs);   // Cannot overflow
222✔
4328

4329
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
563✔
4330
   vcode_add_arg(op, lhs);
563✔
4331
   vcode_add_arg(op, locus);
563✔
4332

4333
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
563✔
4334
                "locus argument to trap neg must be a debug locus");
4335
   VCODE_ASSERT(vcode_reg_kind(lhs) == VCODE_TYPE_INT,
563✔
4336
                "trapping neg may only be used with integer types");
4337

4338
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
563✔
4339
}
4340

4341
vcode_reg_t emit_abs(vcode_reg_t lhs)
245✔
4342
{
4343
   int64_t lconst;
245✔
4344
   if (vcode_reg_const(lhs, &lconst))
245✔
4345
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4346

4347
   op_t *op = vcode_add_op(VCODE_OP_ABS);
244✔
4348
   vcode_add_arg(op, lhs);
244✔
4349
   op->result = vcode_add_reg(vcode_reg_type(lhs));
244✔
4350

4351
   return op->result;
244✔
4352
}
4353

4354
void emit_comment(const char *fmt, ...)
42,107✔
4355
{
4356
#ifndef NDEBUG
4357
   va_list ap;
42,107✔
4358
   va_start(ap, fmt);
42,107✔
4359

4360
   char *buf = xvasprintf(fmt, ap);
42,107✔
4361
   for (char *p = buf + strlen(buf) - 1;
42,107✔
4362
        p >= buf && isspace_iso88591(*p); p--)
42,107✔
UNCOV
4363
      *p = '\0';
×
4364

4365
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
42,107✔
4366
   va_end(ap);
42,107✔
4367
#endif
4368
}
42,107✔
4369

4370
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
18,045✔
4371
                        vcode_reg_t rfalse)
4372
{
4373
   int64_t tconst;
18,045✔
4374
   if (vcode_reg_const(test, &tconst))
18,045✔
4375
      return !!tconst ? rtrue : rfalse;
4,252✔
4376
   else if (rtrue == rfalse)
13,793✔
4377
      return rtrue;
4378

4379
   // Find a previous identical select
4380
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
299,286✔
4381
      if (other->args.items[0] == test && other->args.items[1] == rtrue
12,447✔
4382
          && other->args.items[2] == rfalse)
714✔
4383
         return other->result;
659✔
4384
   }
4385

4386
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
12,895✔
4387
   vcode_add_arg(op, test);
12,895✔
4388
   vcode_add_arg(op, rtrue);
12,895✔
4389
   vcode_add_arg(op, rfalse);
12,895✔
4390
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
12,895✔
4391

4392
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
12,895✔
4393
                "select test must have bool type");
4394
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
12,895✔
4395
                "select arguments are not the same type");
4396

4397
   return op->result;
12,895✔
4398
}
4399

4400
static vcode_reg_t emit_logical_identity(vcode_op_t op, vcode_reg_t reg, bool b)
91✔
4401
{
4402
   switch (op) {
91✔
4403
   case VCODE_OP_AND:  return b ? reg : emit_const(vtype_bool(), 0);
24✔
4404
   case VCODE_OP_OR:   return b ? emit_const(vtype_bool(), 1) : reg;
19✔
4405
   case VCODE_OP_XOR:  return b ? emit_not(reg) : reg;
12✔
4406
   case VCODE_OP_XNOR: return b ? reg : emit_not(reg);
12✔
4407
   case VCODE_OP_NAND: return b ? emit_not(reg) : emit_const(vtype_bool(), 1);
12✔
4408
   case VCODE_OP_NOR:  return b ? emit_const(vtype_bool(), 0) : emit_not(reg);
12✔
UNCOV
4409
   default:
×
UNCOV
4410
      fatal_trace("missing logicial identity for %s", vcode_op_string(op));
×
4411
   }
4412
}
4413

4414
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
5,987✔
4415
{
4416
   vcode_type_t vtbool = vtype_bool();
5,987✔
4417

4418
   int64_t lconst, rconst;
5,987✔
4419
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
5,987✔
4420
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
5,987✔
4421
   if (l_is_const && r_is_const) {
5,987✔
4422
      switch (op) {
6✔
UNCOV
4423
      case VCODE_OP_AND:  return emit_const(vtbool, lconst && rconst);
×
UNCOV
4424
      case VCODE_OP_OR:   return emit_const(vtbool, lconst || rconst);
×
UNCOV
4425
      case VCODE_OP_XOR:  return emit_const(vtbool, lconst ^ rconst);
×
4426
      case VCODE_OP_XNOR: return emit_const(vtbool, !(lconst ^ rconst));
6✔
4427
      case VCODE_OP_NAND: return emit_const(vtbool, !(lconst && rconst));
×
4428
      case VCODE_OP_NOR:  return emit_const(vtbool, !(lconst || rconst));
×
UNCOV
4429
      default:
×
4430
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
×
4431
      }
4432
   }
4433
   else if (l_is_const)
5,981✔
4434
      return emit_logical_identity(op, rhs, !!lconst);
12✔
4435
   else if (r_is_const)
5,969✔
4436
      return emit_logical_identity(op, lhs, !!rconst);
79✔
4437
   else if (lhs == rhs) {
5,890✔
4438
      switch (op) {
15✔
4439
      case VCODE_OP_AND:
4440
      case VCODE_OP_OR:
4441
         return lhs;
4442
      case VCODE_OP_NAND:
6✔
4443
      case VCODE_OP_NOR:
4444
         return emit_not(lhs);
6✔
4445
      case VCODE_OP_XOR:
3✔
4446
         return emit_const(vtbool, 0);
3✔
UNCOV
4447
      case VCODE_OP_XNOR:
×
UNCOV
4448
         return emit_const(vtbool, 1);
×
UNCOV
4449
      default:
×
4450
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
×
4451
      }
4452
   }
4453

4454
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
5,875✔
4455

4456
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
5,875✔
4457
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4458
                "arguments to %s are not boolean", vcode_op_string(op));
4459

4460
   return result;
4461
}
4462

4463
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
1,525✔
4464
{
4465
   return emit_logical(VCODE_OP_OR, lhs, rhs);
1,525✔
4466
}
4467

4468
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
4,094✔
4469
{
4470
   return emit_logical(VCODE_OP_AND, lhs, rhs);
4,094✔
4471
}
4472

4473
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
80✔
4474
{
4475
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
80✔
4476
}
4477

4478
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
81✔
4479
{
4480
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
81✔
4481
}
4482

4483
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
122✔
4484
{
4485
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
122✔
4486
}
4487

4488
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
85✔
4489
{
4490
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
85✔
4491
}
4492

4493
vcode_reg_t emit_not(vcode_reg_t arg)
2,243✔
4494
{
4495
   int64_t cval;
2,243✔
4496
   if (vcode_reg_const(arg, &cval))
2,243✔
4497
      return emit_const(vtype_bool(), !cval);
27✔
4498

4499
   op_t *op = vcode_add_op(VCODE_OP_NOT);
2,216✔
4500
   vcode_add_arg(op, arg);
2,216✔
4501

4502
   vcode_type_t vtbool = vtype_bool();
2,216✔
4503
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
2,216✔
4504
                "argument to not is not boolean");
4505

4506
   return (op->result = vcode_add_reg(vtbool));
2,216✔
4507
}
4508

4509
vcode_reg_t emit_wrap(vcode_reg_t data, const vcode_dim_t *dims, int ndims)
45,732✔
4510
{
4511
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_WRAP) {
1,520,454✔
4512
      if (other->args.count == ndims*3 + 1 && other->args.items[0] == data) {
142,820✔
4513
         bool match = true;
4514
         for (int i = 0; match && i < ndims; i++) {
20,402✔
4515
            match = other->args.items[i*3 + 1] == dims[i].left
10,221✔
4516
               && other->args.items[i*3 + 2] == dims[i].right
8,897✔
4517
               && other->args.items[i*3 + 3] == dims[i].dir;
18,982✔
4518
         }
4519
         if (match)
10,181✔
4520
            return other->result;
8,721✔
4521
      }
4522
   }
4523

4524
   op_t *op = vcode_add_op(VCODE_OP_WRAP);
37,011✔
4525
   vcode_add_arg(op, data);
37,011✔
4526
   for (int i = 0; i < ndims; i++) {
74,451✔
4527
      vcode_add_arg(op, dims[i].left);
37,440✔
4528
      vcode_add_arg(op, dims[i].right);
37,440✔
4529
      vcode_add_arg(op, dims[i].dir);
37,440✔
4530
   }
4531

4532
   vcode_type_t ptr_type = vcode_reg_type(data);
37,011✔
4533
   const vtype_kind_t ptrkind = vtype_kind(ptr_type);
37,011✔
4534
   VCODE_ASSERT(ptrkind == VCODE_TYPE_POINTER || ptrkind == VCODE_TYPE_SIGNAL,
37,011✔
4535
                "wrapped data is not pointer or signal");
4536

4537
#ifdef DEBUG
4538
   for (int i = 0; i < ndims; i++) {
74,451✔
4539
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].left)),
37,440✔
4540
                   "dimension %d left bound must be scalar", i + 1);
4541
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].right)),
37,440✔
4542
                   "dimension %d right bound must be scalar", i + 1);
4543
      VCODE_ASSERT(vtype_eq(vtype_bool(), vcode_reg_type(dims[i].dir)),
37,440✔
4544
                   "dimension %d direction must be bool", i + 1);
4545
   }
4546
#endif
4547

4548
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
74,022✔
4549
      ? vtype_pointed(ptr_type) : ptr_type;
37,011✔
4550

4551
   op->result = vcode_add_reg(
37,011✔
4552
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4553

4554
   return op->result;
37,011✔
4555
}
4556

4557
static vcode_reg_t emit_uarray_op(vcode_op_t o, vcode_type_t rtype,
107,539✔
4558
                                  vcode_reg_t array, unsigned dim,
4559
                                  unsigned arg_index)
4560
{
4561
   // Reuse any previous operation in this block with the same arguments
4562
   VCODE_FOR_EACH_OP(other) {
1,163,268✔
4563
      if (other->kind == o && other->args.items[0] == array && other->dim == dim
1,113,771✔
4564
          && (rtype == VCODE_INVALID_TYPE
22,727✔
4565
              || vtype_eq(rtype, vcode_reg_type(other->result))))
9,536✔
4566
         return other->result;
22,727✔
4567
      else if (other->kind == VCODE_OP_WRAP && other->result == array)
1,091,044✔
4568
         return other->args.items[1 + (dim * 3) + arg_index];
35,315✔
4569
   }
4570

4571
   op_t *op = vcode_add_op(o);
49,497✔
4572
   vcode_add_arg(op, array);
49,497✔
4573
   op->dim = dim;
49,497✔
4574

4575
   vcode_type_t atype = vcode_reg_type(array);
49,497✔
4576
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
49,497✔
4577
                "cannot use %s with non-uarray type", vcode_op_string(o));
4578

4579
   vtype_t *vt = vcode_type_data(atype);
49,497✔
4580
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
49,497✔
4581

4582
   if (rtype == VCODE_INVALID_TYPE)
49,497✔
4583
      rtype = vtype_offset();
32,232✔
4584

4585
   return (op->result = vcode_add_reg(rtype));
49,497✔
4586
}
4587

4588
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
38,933✔
4589
{
4590
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
38,933✔
4591
                         array, dim, 0);
4592
}
4593

4594
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
29,992✔
4595
{
4596
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
29,992✔
4597
                         array, dim, 1);
4598
}
4599

4600
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
38,614✔
4601
{
4602
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
38,614✔
4603
                         array, dim, 2);
4604
}
4605

4606
vcode_reg_t emit_uarray_len(vcode_reg_t array, unsigned dim)
49,241✔
4607
{
4608
   VCODE_FOR_EACH_OP(other) {
518,229✔
4609
      if (other->kind == VCODE_OP_UARRAY_LEN) {
494,378✔
4610
         if (other->args.items[0] == array && other->dim == dim)
34,448✔
4611
            return other->result;
10,956✔
4612
      }
4613
      else if (other->kind == VCODE_OP_WRAP && other->result == array) {
459,930✔
4614
         VCODE_ASSERT(dim < (other->args.count - 1) / 3,
14,434✔
4615
                      "array dimension %d out of bounds", dim);
4616

4617
         vcode_reg_t left_reg = other->args.items[dim * 3 + 1];
14,434✔
4618
         vcode_reg_t right_reg = other->args.items[dim * 3 + 2];
14,434✔
4619
         vcode_reg_t dir_reg = other->args.items[dim * 3 + 3];
14,434✔
4620
         return emit_range_length(left_reg, right_reg, dir_reg);
14,434✔
4621
      }
4622
   }
4623

4624
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
23,851✔
4625
   vcode_add_arg(op, array);
23,851✔
4626
   op->dim = dim;
23,851✔
4627

4628
   vcode_type_t atype = vcode_reg_type(array);
23,851✔
4629
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
23,851✔
4630
                "cannot use uarray len with non-uarray type");
4631

4632
   vtype_t *vt = vcode_type_data(atype);
23,851✔
4633
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
23,851✔
4634

4635
   return (op->result = vcode_add_reg(vtype_offset()));
23,851✔
4636
}
4637

4638
vcode_reg_t emit_unwrap(vcode_reg_t array)
37,384✔
4639
{
4640
   VCODE_FOR_EACH_OP(other) {
1,521,713✔
4641
      if (other->kind == VCODE_OP_WRAP && other->result == array)
1,495,235✔
4642
         return other->args.items[0];
9,444✔
4643
      else if (other->kind == VCODE_OP_UNWRAP && other->args.items[0] == array)
1,485,791✔
4644
         return other->result;
1,462✔
4645
   }
4646

4647
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
26,478✔
4648
   vcode_add_arg(op, array);
26,478✔
4649

4650
   vtype_t *vt = vcode_type_data(vcode_reg_type(array));
26,478✔
4651
   VCODE_ASSERT(vt->kind == VCODE_TYPE_UARRAY,
26,478✔
4652
                "unwrap can only only be used with uarray types");
4653

4654
   vcode_type_t elem = vt->elem;
26,478✔
4655

4656
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
26,478✔
4657
      ? elem : vtype_pointer(elem);
26,478✔
4658

4659
   op->result = vcode_add_reg(rtype);
26,478✔
4660

4661
   reg_t *rr = vcode_reg_data(op->result);
26,478✔
4662
   rr->bounds = elem;
26,478✔
4663

4664
   return op->result;
26,478✔
4665
}
4666

4667
vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right,
16,948✔
4668
                            vcode_reg_t dir)
4669
{
4670
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_NULL) {
516,858✔
UNCOV
4671
      if (other->args.items[0] == left
×
UNCOV
4672
          && other->args.items[1] == right
×
UNCOV
4673
          && other->args.items[2] == dir)
×
4674
         return other->result;
×
4675
   }
4676

4677
   int64_t dir_const;
16,948✔
4678
   if (vcode_reg_const(dir, &dir_const)) {
16,948✔
4679
      vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
12,248✔
4680
      vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
12,248✔
4681

4682
      if (dir_const == RANGE_TO && lbounds->low > rbounds->high)
12,248✔
4683
         return emit_const(vtype_bool(), 1);
38✔
4684
      else if (dir_const == RANGE_TO && lbounds->high <= rbounds->low)
12,210✔
4685
         return emit_const(vtype_bool(), 0);
5,787✔
4686
      else if (dir_const == RANGE_DOWNTO && rbounds->low > lbounds->high)
6,423✔
4687
         return emit_const(vtype_bool(), 1);
92✔
4688
      else if (dir_const == RANGE_DOWNTO && rbounds->high <= lbounds->low)
6,331✔
4689
         return emit_const(vtype_bool(), 0);
1,505✔
4690
      else if (dir_const == RANGE_TO)
4,826✔
4691
         return emit_cmp(VCODE_CMP_GT, left, right);
1,456✔
4692
      else
4693
         return emit_cmp(VCODE_CMP_GT, right, left);
3,370✔
4694
   }
4695

4696
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
4,700✔
4697
   vcode_add_arg(op, left);
4,700✔
4698
   vcode_add_arg(op, right);
4,700✔
4699
   vcode_add_arg(op, dir);
4,700✔
4700

4701
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
4,700✔
4702
                "range left and right have different types");
4703
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
4,700✔
4704
                "dir argument to range length is not int");
4705

4706
   return (op->result = vcode_add_reg(vtype_bool()));
4,700✔
4707
}
4708

4709
vcode_reg_t emit_range_length(vcode_reg_t left, vcode_reg_t right,
14,468✔
4710
                              vcode_reg_t dir)
4711
{
4712
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_LENGTH) {
351,752✔
4713
      if (other->args.items[0] == left
6,045✔
4714
          && other->args.items[1] == right
4,759✔
4715
          && other->args.items[2] == dir)
4,472✔
4716
         return other->result;
4,472✔
4717
   }
4718

4719
   int64_t lconst, rconst, dconst;
9,996✔
4720
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
9,996✔
4721
       && vcode_reg_const(right, &rconst)) {
5,652✔
4722

4723
      int64_t diff;
3,705✔
4724
      if (dconst == RANGE_TO)
3,705✔
4725
         diff = rconst - lconst;
3,459✔
4726
      else
4727
         diff = lconst - rconst;
246✔
4728

4729
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
3,705✔
4730
   }
4731

4732
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
6,291✔
4733
   vcode_add_arg(op, left);
6,291✔
4734
   vcode_add_arg(op, right);
6,291✔
4735
   vcode_add_arg(op, dir);
6,291✔
4736

4737
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
6,291✔
4738
                "range left and right have different types");
4739
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
6,291✔
4740
                "dir argument to range length is not int");
4741

4742
   return (op->result = vcode_add_reg(vtype_offset()));
6,291✔
4743
}
4744

4745
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
48,693✔
4746
{
4747
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
437,004✔
4748
      if (other->hops == hops && other->address == var)
59,097✔
4749
         return other->result;
7,250✔
4750
   }
4751

4752
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
41,443✔
4753
   op->hops    = hops;
41,443✔
4754
   op->address = var;
41,443✔
4755

4756
   VCODE_ASSERT(hops > 0, "invalid hop count");
41,443✔
4757

4758
   vcode_unit_t vu = active_unit;
41,443✔
4759
   for (int i = 0; i < hops; i++) {
93,354✔
4760
      vu = vu->context;
51,911✔
4761
      VCODE_ASSERT(vu, "hop count is greater than depth");
51,911✔
4762
   }
4763

4764
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
41,443✔
4765

4766
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
41,443✔
4767

4768
   return op->result;
41,443✔
4769
}
4770

4771
vcode_reg_t emit_init_signal(vcode_type_t type, vcode_reg_t count,
10,979✔
4772
                             vcode_reg_t size, vcode_reg_t value,
4773
                             vcode_reg_t flags, vcode_reg_t locus,
4774
                             vcode_reg_t offset)
4775
{
4776
   op_t *op = vcode_add_op(VCODE_OP_INIT_SIGNAL);
10,979✔
4777
   vcode_add_arg(op, count);
10,979✔
4778
   vcode_add_arg(op, size);
10,979✔
4779
   vcode_add_arg(op, value);
10,979✔
4780
   vcode_add_arg(op, flags);
10,979✔
4781
   vcode_add_arg(op, locus);
10,979✔
4782
   if (offset != VCODE_INVALID_REG)
10,979✔
4783
      vcode_add_arg(op, offset);
4,283✔
4784

4785
   vcode_type_t vtype = vcode_reg_type(value);
10,979✔
4786
   VCODE_ASSERT(vtype_is_scalar(type), "signal type must be scalar");
10,979✔
4787
   VCODE_ASSERT(vtype_eq(vtype, type)
10,979✔
4788
                || vtype_kind(vtype) == VCODE_TYPE_POINTER,
4789
                "init signal value type does not match signal type");
4790
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
10,979✔
4791
                "locus argument to init signal must be a debug locus");
4792
   VCODE_ASSERT(offset == VCODE_INVALID_REG
10,979✔
4793
                || vcode_reg_kind(offset) == VCODE_TYPE_POINTER,
4794
                "init signal offset argument must have pointer type");
4795

4796
   return (op->result = vcode_add_reg(vtype_signal(type)));
10,979✔
4797
}
4798

4799
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
2,869✔
4800
{
4801
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
2,869✔
4802
   vcode_add_arg(op, signal);
2,869✔
4803
   vcode_add_arg(op, resolution);
2,869✔
4804

4805
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
2,869✔
4806
                "signal argument has wrong type");
4807
   VCODE_ASSERT(vcode_reg_kind(resolution) == VCODE_TYPE_RESOLUTION,
2,869✔
4808
                "resolution wrapper argument has wrong type");
4809
}
2,869✔
4810

4811
vcode_reg_t emit_implicit_signal(vcode_type_t type, vcode_reg_t count,
21✔
4812
                                 vcode_reg_t size, vcode_reg_t locus,
4813
                                 vcode_reg_t kind, vcode_reg_t closure)
4814
{
4815
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_SIGNAL);
21✔
4816
   vcode_add_arg(op, count);
21✔
4817
   vcode_add_arg(op, size);
21✔
4818
   vcode_add_arg(op, locus);
21✔
4819
   vcode_add_arg(op, kind);
21✔
4820
   vcode_add_arg(op, closure);
21✔
4821

4822
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
21✔
4823
                "count argument to implicit signal is not offset");
4824
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
21✔
4825
                "kind argument to implicit signal is not offset");
4826
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
21✔
4827
                "closure argument to implicit signal is not a closure");
4828
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
21✔
4829
                "locus argument to implicit signal must be a debug locus");
4830

4831
   return (op->result = vcode_add_reg(vtype_signal(type)));
21✔
4832
}
4833

4834
void emit_map_signal(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
1,284✔
4835
{
4836
   op_t *op = vcode_add_op(VCODE_OP_MAP_SIGNAL);
1,284✔
4837
   vcode_add_arg(op, src);
1,284✔
4838
   vcode_add_arg(op, dst);
1,284✔
4839
   vcode_add_arg(op, count);
1,284✔
4840

4841
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
1,284✔
4842
                "src argument to map signal is not a signal");
4843
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
1,284✔
4844
                "dst argument to map signal is not a signal");
4845
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,284✔
4846
                "count argument type to map signal is not offset");
4847
}
1,284✔
4848

4849
void emit_map_const(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
4,137✔
4850
{
4851
   op_t *op = vcode_add_op(VCODE_OP_MAP_CONST);
4,137✔
4852
   vcode_add_arg(op, src);
4,137✔
4853
   vcode_add_arg(op, dst);
4,137✔
4854
   vcode_add_arg(op, count);
4,137✔
4855

4856
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
4,137✔
4857
                "dst argument to map const is not a signal");
4858
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
4,137✔
4859
                "count argument type to map const is not offset");
4860
}
4,137✔
4861

4862
void emit_map_transaction(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
21✔
4863
{
4864
   op_t *op = vcode_add_op(VCODE_OP_MAP_TRANSACTION);
21✔
4865
   vcode_add_arg(op, src);
21✔
4866
   vcode_add_arg(op, dst);
21✔
4867
   vcode_add_arg(op, count);
21✔
4868

4869
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
21✔
4870
                "src argument to map transaction is not a signal");
4871
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
21✔
4872
                "dst argument to map transaction is not a signal");
4873
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
21✔
4874
                "count argument type to transaction is not offset");
4875
}
21✔
4876

4877
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
8,759✔
4878
{
4879
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
110,586✔
4880
      if (other->args.items[0] == target && other->args.items[1] == count)
13,631✔
4881
         return;
4882
   }
4883

4884
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
8,744✔
4885
   vcode_add_arg(op, target);
8,744✔
4886
   vcode_add_arg(op, count);
8,744✔
4887

4888
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
8,744✔
4889
                "target argument to drive signal is not a signal");
4890
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
8,744✔
4891
                "count argument type to drive signal is not offset");
4892
}
4893

4894
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
1,188✔
4895
                          vcode_reg_t count, vcode_reg_t reject,
4896
                          vcode_reg_t after)
4897
{
4898
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
1,188✔
4899
   vcode_add_arg(op, target);
1,188✔
4900
   vcode_add_arg(op, source);
1,188✔
4901
   vcode_add_arg(op, count);
1,188✔
4902
   vcode_add_arg(op, reject);
1,188✔
4903
   vcode_add_arg(op, after);
1,188✔
4904

4905
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
1,188✔
4906
                "target argument to transfer signal is not a signal");
4907
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,188✔
4908
                "count argument type to transfer signal is not offset");
4909
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
1,188✔
4910
                "source argument to transfer signal is not a signal");
4911
}
1,188✔
4912

4913
vcode_reg_t emit_resolution_wrapper(vcode_type_t type, vcode_reg_t closure,
2,755✔
4914
                                    vcode_reg_t ileft, vcode_reg_t nlits)
4915
{
4916
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RESOLUTION_WRAPPER) {
127,372✔
4917
      if (other->args.items[0] == closure
1,975✔
4918
          && other->args.items[1] == ileft
1,972✔
4919
          && other->args.items[2] == nlits)
1,972✔
4920
         return other->result;
1,972✔
4921
   }
4922

4923
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
783✔
4924
                "first argument to resolution wrapper must be closure");
4925

4926
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
783✔
4927
   vcode_add_arg(op, closure);
783✔
4928
   vcode_add_arg(op, ileft);
783✔
4929
   vcode_add_arg(op, nlits);
783✔
4930

4931
   return (op->result = vcode_add_reg(vtype_resolution(type)));
783✔
4932
}
4933

4934
vcode_reg_t emit_closure(ident_t func, vcode_reg_t context, vcode_type_t atype,
2,971✔
4935
                         vcode_type_t rtype)
4936
{
4937
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CLOSURE) {
129,192✔
4938
      if (other->func == func && other->args.items[0] == context)
2,124✔
4939
         return other->result;
2,006✔
4940
   }
4941

4942
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
965✔
4943
   vcode_add_arg(op, context);
965✔
4944
   op->func = func;
965✔
4945
   op->type = atype;
965✔
4946

4947
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
965✔
4948
                "invalid closure context argument");
4949

4950
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
965✔
4951
}
4952

4953
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
28,734✔
4954
{
4955
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
43,779✔
4956
      if (other->func == name)
21,700✔
4957
         return other->result;
12,028✔
4958
   }
4959

4960
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
16,706✔
4961
   op->func = name;
16,706✔
4962
   if (context != VCODE_INVALID_REG)
16,706✔
4963
      vcode_add_arg(op, context);
170✔
4964

4965
   VCODE_ASSERT(context == VCODE_INVALID_REG
16,706✔
4966
                || vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
4967
                "invalid protected init context argument");
4968
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_INSTANCE
16,706✔
4969
                || active_unit->kind == VCODE_UNIT_PACKAGE
4970
                || active_unit->kind == VCODE_UNIT_THUNK,
4971
                "cannot use package init here");
4972
   VCODE_ASSERT(name != active_unit->name, "cyclic package init");
16,706✔
4973

4974
   return (op->result = vcode_add_reg(vtype_context(name)));
16,706✔
4975
}
4976

4977
vcode_reg_t emit_protected_init(vcode_type_t type, vcode_reg_t context,
154✔
4978
                                vcode_reg_t path_name, vcode_reg_t inst_name)
4979
{
4980
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_INIT);
154✔
4981
   vcode_add_arg(op, context);
154✔
4982
   op->func = vtype_name(type);
154✔
4983

4984
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
154✔
4985
      vcode_add_arg(op, path_name);
32✔
4986
      vcode_add_arg(op, inst_name);
32✔
4987

4988
      VCODE_ASSERT(vcode_reg_kind(path_name) == VCODE_TYPE_UARRAY,
32✔
4989
                   "path name argument must be uarray");
4990
      VCODE_ASSERT(vcode_reg_kind(inst_name) == VCODE_TYPE_UARRAY,
32✔
4991
                   "inst name argument must be uarray");
4992
   }
4993

4994
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
154✔
4995
                "protected init type must be context");
4996
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
154✔
4997
                "invalid protected init context argument");
4998

4999
   return (op->result = vcode_add_reg(type));
154✔
5000
}
5001

5002
void emit_process_init(ident_t name, vcode_reg_t locus)
70✔
5003
{
5004
   op_t *op = vcode_add_op(VCODE_OP_PROCESS_INIT);
70✔
5005
   vcode_add_arg(op, locus);
70✔
5006
   op->func = name;
70✔
5007

5008
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
70✔
5009
                "locus argument to process init must be a debug locus");
5010
}
70✔
5011

5012
void emit_protected_free(vcode_reg_t obj)
7✔
5013
{
5014
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
7✔
5015
   vcode_add_arg(op, obj);
7✔
5016

5017
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
7✔
5018
                "protected object type must be context");
5019
}
7✔
5020

5021
vcode_reg_t emit_context_upref(int hops)
15,050✔
5022
{
5023
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
98,964✔
5024
      if (other->hops == hops)
6,800✔
5025
         return other->result;
6,741✔
5026
   }
5027

5028
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
8,309✔
5029
   op->hops = hops;
8,309✔
5030

5031
   VCODE_ASSERT(hops >= 0, "invalid hop count");
8,309✔
5032

5033
   vcode_unit_t vu = active_unit;
8,309✔
5034
   for (int i = 0; i < hops; i++) {
15,968✔
5035
      vu = vu->context;
7,659✔
5036
      VCODE_ASSERT(vu, "hop count is greater than depth");
7,659✔
5037
   }
5038

5039
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
8,309✔
5040
}
5041

5042
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
497✔
5043
                                    vcode_reg_t len)
5044
{
5045
   op_t *op = vcode_add_op(opkind);
497✔
5046
   vcode_add_arg(op, nets);
497✔
5047
   vcode_add_arg(op, len);
497✔
5048

5049
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
497✔
5050
                "argument to %s is not a signal", vcode_op_string(opkind));
5051

5052
   return (op->result = vcode_add_reg(vtype_bool()));
497✔
5053
}
5054

5055
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
307✔
5056
{
5057
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
307✔
5058
}
5059

5060
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
190✔
5061
{
5062
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
190✔
5063
}
5064

5065
vcode_reg_t emit_record_ref(vcode_reg_t record, unsigned field)
37,219✔
5066
{
5067
   // Try scanning backwards through the block for another record ref
5068
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RECORD_REF) {
2,309,712✔
5069
      if (other->args.items[0] == record && other->field == field)
474,955✔
5070
         return other->result;
2,595✔
5071
   }
5072

5073
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
34,624✔
5074
   op->field = field;
34,624✔
5075
   vcode_add_arg(op, record);
34,624✔
5076

5077
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
34,624✔
5078

5079
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
34,624✔
5080
                "argument to record ref must be a pointer");
5081

5082
   vtype_t *rtype = vcode_type_data(rptype->pointed);
34,624✔
5083
   VCODE_ASSERT(rtype->kind == VCODE_TYPE_RECORD,
34,624✔
5084
                "argument must be pointer to record or record signal");
5085

5086
   VCODE_ASSERT(field < rtype->fields.count, "invalid field %d", field);
34,624✔
5087

5088
   vcode_type_t field_type  = rtype->fields.items[field];
34,624✔
5089
   vcode_type_t bounds_type = field_type;
34,624✔
5090
   vcode_type_t result_type = field_type;
34,624✔
5091

5092
   const vtype_kind_t fkind = vtype_kind(field_type);
34,624✔
5093
   if (fkind == VCODE_TYPE_CARRAY)
34,624✔
5094
      result_type = bounds_type = vtype_elem(field_type);
4,907✔
5095
   else if (fkind == VCODE_TYPE_UARRAY) {
29,717✔
5096
      bounds_type = vtype_elem(field_type);
2,469✔
5097
      result_type = field_type;
2,469✔
5098
   }
5099

5100
   op->result = vcode_add_reg(vtype_pointer(result_type));
34,624✔
5101

5102
   reg_t *rr = vcode_reg_data(op->result);
34,624✔
5103
   rr->bounds = bounds_type;
34,624✔
5104

5105
   return op->result;
34,624✔
5106
}
5107

5108
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
34,664✔
5109
{
5110
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
1,649,724✔
5111
      if (other->args.items[0] == array && other->args.items[1] == offset)
97,797✔
5112
         return other->result;
1,174✔
5113
   }
5114

5115
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
33,490✔
5116
   vcode_add_arg(op, array);
33,490✔
5117
   vcode_add_arg(op, offset);
33,490✔
5118

5119
   vcode_type_t rtype = vcode_reg_type(array);
33,490✔
5120
   VCODE_ASSERT((vtype_kind(rtype) == VCODE_TYPE_POINTER
33,490✔
5121
                 && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY)
5122
                || vtype_kind(rtype) == VCODE_TYPE_SIGNAL,
5123
                "argument to array ref must be a pointer or signal");
5124
   VCODE_ASSERT(vcode_reg_kind(offset) == VCODE_TYPE_OFFSET,
33,490✔
5125
                "array ref offset argument must have offset type");
5126

5127
   op->result = vcode_add_reg(rtype);
33,490✔
5128

5129
   reg_t *rr = vcode_reg_data(op->result);
33,490✔
5130
   rr->bounds = vcode_reg_bounds(array);
33,490✔
5131

5132
   return op->result;
33,490✔
5133
}
5134

5135
void emit_copy(vcode_reg_t dest, vcode_reg_t src, vcode_reg_t count)
20,279✔
5136
{
5137
   int64_t cconst;
20,279✔
5138
   if (count != VCODE_INVALID_REG && vcode_reg_const(count, &cconst)
20,279✔
5139
       && cconst == 0)
9,920✔
5140
      return;
4,768✔
5141
   else if (dest == src)
20,137✔
5142
      return;
5143

5144
   op_t *op = vcode_add_op(VCODE_OP_COPY);
15,511✔
5145
   vcode_add_arg(op, dest);
15,511✔
5146
   vcode_add_arg(op, src);
15,511✔
5147
   if (count != VCODE_INVALID_REG)
15,511✔
5148
      vcode_add_arg(op, count);
13,571✔
5149

5150
   vcode_type_t dtype = vcode_reg_type(dest);
15,511✔
5151
   vcode_type_t stype = vcode_reg_type(src);
15,511✔
5152

5153
   vtype_kind_t dkind = vtype_kind(dtype);
15,511✔
5154
   vtype_kind_t skind = vtype_kind(stype);
15,511✔
5155

5156
   VCODE_ASSERT(dkind == VCODE_TYPE_POINTER || dkind == VCODE_TYPE_ACCESS,
15,511✔
5157
                "destination type is not a pointer or access");
5158
   VCODE_ASSERT(skind == VCODE_TYPE_POINTER || skind == VCODE_TYPE_ACCESS,
15,511✔
5159
                "source type is not a pointer or access");
5160
   VCODE_ASSERT(vtype_eq(dtype, stype),
15,511✔
5161
                "source and destination types do not match");
5162
   VCODE_ASSERT(count == VCODE_INVALID_REG
15,511✔
5163
                || vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5164
                "count is not offset type");
5165

5166
   op->type = vtype_pointed(dtype);
15,511✔
5167
}
5168

5169
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
5,405✔
5170
{
5171
   VCODE_FOR_EACH_OP(other) {
95,037✔
5172
      if (other->kind == VCODE_OP_CLEAR_EVENT)
89,668✔
5173
         break;
5174
      else if (other->kind == VCODE_OP_SCHED_EVENT
89,638✔
5175
               && other->args.items[0] == nets
4,690✔
5176
               && other->args.items[1] == n_elems)
9✔
5177
         return;
5178
   }
5179

5180
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
5,399✔
5181
   vcode_add_arg(op, nets);
5,399✔
5182
   vcode_add_arg(op, n_elems);
5,399✔
5183

5184
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
5,399✔
5185
                "nets argument to sched event must be signal");
5186
}
5187

5188
void emit_implicit_event(vcode_reg_t nets, vcode_reg_t count, vcode_reg_t wake)
18✔
5189
{
5190
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_IMPLICIT_EVENT) {
189✔
UNCOV
5191
      if (other->args.items[0] == nets && other->args.items[1] == count
×
UNCOV
5192
          && other->args.items[1] == wake)
×
5193
         return;
5194
   }
5195

5196
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_EVENT);
18✔
5197
   vcode_add_arg(op, nets);
18✔
5198
   vcode_add_arg(op, count);
18✔
5199
   vcode_add_arg(op, wake);
18✔
5200

5201
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
18✔
5202
                "nets argument to implicit event must be signal");
5203
   VCODE_ASSERT(vcode_reg_kind(wake) == VCODE_TYPE_SIGNAL,
18✔
5204
                "wake argument to implicit event must be signal");
5205
}
5206

5207
void emit_clear_event(vcode_reg_t nets, vcode_reg_t n_elems)
468✔
5208
{
5209
   VCODE_FOR_EACH_OP(other) {
2,183✔
5210
      if (other->kind == VCODE_OP_SCHED_EVENT)
1,715✔
5211
         break;
5212
      else if (other->kind == VCODE_OP_CLEAR_EVENT
1,715✔
5213
               && other->args.items[0] == nets
39✔
UNCOV
5214
               && other->args.items[1] == n_elems)
×
5215
         return;
5216
   }
5217

5218
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
468✔
5219
   vcode_add_arg(op, nets);
468✔
5220
   vcode_add_arg(op, n_elems);
468✔
5221

5222
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
468✔
5223
                "nets argument to clear event must be signal");
5224
}
5225

5226
void emit_resume(ident_t func)
777✔
5227
{
5228
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
777✔
5229
   op->func = func;
777✔
5230

5231
   block_t *b = &(active_unit->blocks.items[active_block]);
777✔
5232
   VCODE_ASSERT(b->ops.count == 1, "resume must be first op in a block");
777✔
5233
}
777✔
5234

5235
void emit_memset(vcode_reg_t ptr, vcode_reg_t value, vcode_reg_t len)
5,665✔
5236
{
5237
   int64_t lconst;
5,665✔
5238
   if (vcode_reg_const(len, &lconst) && lconst == 0)
5,665✔
5239
      return;
17✔
5240

5241
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
5,648✔
5242
   vcode_add_arg(op, ptr);
5,648✔
5243
   vcode_add_arg(op, value);
5,648✔
5244
   vcode_add_arg(op, len);
5,648✔
5245

5246
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
5,648✔
5247
                "target of memset must have pointer type");
5248
   VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(value)),
5,648✔
5249
                "value of memset must have scalar type");
5250
   VCODE_ASSERT(vtype_kind(vcode_reg_type(len)) == VCODE_TYPE_OFFSET,
5,648✔
5251
                "length of memset must have offset type");
5252
}
5253

5254
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
542✔
5255
               const vcode_block_t *blocks, int ncases)
5256
{
5257
   int64_t cval1, cval2;
542✔
5258
   bool is_const = vcode_reg_const(value, &cval1);
542✔
5259

5260
   for (int i = 0; i < ncases; i++) {
4,989✔
5261
      bool can_fold = false;
4,451✔
5262
      if (cases[i] == value)
4,451✔
5263
         can_fold = true;
5264
      else if (is_const && vcode_reg_const(cases[i], &cval2))
4,451✔
5265
         can_fold = (cval1 == cval2);
4✔
5266

5267
      if (can_fold) {
4✔
5268
         emit_jump(blocks[i]);
4✔
5269
         return;
8✔
5270
      }
5271
   }
5272

5273
   if (is_const) {
538✔
UNCOV
5274
      emit_jump(def);
×
UNCOV
5275
      return;
×
5276
   }
5277

5278
   op_t *op = vcode_add_op(VCODE_OP_CASE);
538✔
5279
   vcode_add_arg(op, value);
538✔
5280
   vcode_add_target(op, def);
538✔
5281

5282
   for (int i = 0; i < ncases; i++) {
4,985✔
5283
      vcode_add_arg(op, cases[i]);
4,447✔
5284
      vcode_add_target(op, blocks[i]);
4,447✔
5285

5286
#ifdef DEBUG
5287
      for (int j = 0; j < i; j++)
245,350✔
5288
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
240,903✔
5289
#endif
5290
   }
5291
}
5292

5293
void emit_file_open(vcode_reg_t file, vcode_reg_t name, vcode_reg_t length,
241✔
5294
                    vcode_reg_t kind, vcode_reg_t status)
5295
{
5296
   op_t *op = vcode_add_op(VCODE_OP_FILE_OPEN);
241✔
5297
   vcode_add_arg(op, file);
241✔
5298
   vcode_add_arg(op, name);
241✔
5299
   vcode_add_arg(op, length);
241✔
5300
   vcode_add_arg(op, kind);
241✔
5301
   if (status != VCODE_INVALID_REG)
241✔
5302
      vcode_add_arg(op, status);
26✔
5303

5304
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
241✔
5305
                "file open first argument must have file pointer type");
5306
}
241✔
5307

5308
void emit_file_write(vcode_reg_t file, vcode_reg_t value, vcode_reg_t length)
125✔
5309
{
5310
   op_t *op = vcode_add_op(VCODE_OP_FILE_WRITE);
125✔
5311
   vcode_add_arg(op, file);
125✔
5312
   vcode_add_arg(op, value);
125✔
5313
   if (length != VCODE_INVALID_REG)
125✔
5314
      vcode_add_arg(op, length);
68✔
5315

5316
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
125✔
5317
                "file write first argument must have file pointer type");
5318
}
125✔
5319

5320
void emit_file_read(vcode_reg_t file, vcode_reg_t ptr,
75✔
5321
                    vcode_reg_t inlen, vcode_reg_t outlen)
5322
{
5323
   op_t *op = vcode_add_op(VCODE_OP_FILE_READ);
75✔
5324
   vcode_add_arg(op, file);
75✔
5325
   vcode_add_arg(op, ptr);
75✔
5326
   if (inlen != VCODE_INVALID_REG) {
75✔
5327
      vcode_add_arg(op, inlen);
27✔
5328
      if (outlen != VCODE_INVALID_REG)
27✔
5329
         vcode_add_arg(op, outlen);
18✔
5330
   }
5331

5332
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
75✔
5333
                "file read first argument must have file pointer type");
5334
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
75✔
5335
                "file read pointer argument must have pointer type");
5336
   VCODE_ASSERT(outlen == VCODE_INVALID_REG
75✔
5337
                || vtype_kind(vcode_reg_type(outlen)) == VCODE_TYPE_POINTER,
5338
                "file read outlen argument must have pointer type");
5339
}
75✔
5340

5341
vcode_reg_t emit_null(vcode_type_t type)
9,896✔
5342
{
5343
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_NULL) {
219,880✔
5344
      if (vtype_eq(vcode_reg_type(other->result), type))
5,554✔
5345
         return other->result;
3,233✔
5346
   }
5347

5348
   op_t *op = vcode_add_op(VCODE_OP_NULL);
6,663✔
5349
   op->result = vcode_add_reg(type);
6,663✔
5350

5351
   vtype_kind_t kind = vtype_kind(type);
6,663✔
5352
   VCODE_ASSERT(kind == VCODE_TYPE_POINTER || kind == VCODE_TYPE_FILE
6,663✔
5353
                || kind == VCODE_TYPE_ACCESS || kind == VCODE_TYPE_CONTEXT,
5354
                "null type must be file, access, context, or pointer");
5355

5356
   return op->result;
5357
}
5358

5359
vcode_reg_t emit_new(vcode_type_t type, vcode_reg_t length)
422✔
5360
{
5361
   op_t *op = vcode_add_op(VCODE_OP_NEW);
422✔
5362
   if (length != VCODE_INVALID_REG)
422✔
5363
      vcode_add_arg(op, length);
331✔
5364

5365
   op->result = vcode_add_reg(vtype_access(type));
422✔
5366

5367
   vtype_kind_t kind = vtype_kind(type);
422✔
5368
   VCODE_ASSERT(kind == VCODE_TYPE_INT || kind == VCODE_TYPE_RECORD
422✔
5369
                || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_ACCESS
5370
                || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_CONTEXT,
5371
                "new type must be int, real, record, access, or uarray");
5372
   VCODE_ASSERT(length == VCODE_INVALID_REG
422✔
5373
                || vtype_kind(vcode_reg_type(length)) == VCODE_TYPE_OFFSET,
5374
                "new length must have offset type");
5375

5376
   return op->result;
422✔
5377
}
5378

5379
void emit_null_check(vcode_reg_t ptr, vcode_reg_t locus)
1,755✔
5380
{
5381
   VCODE_FOR_EACH_OP(other) {
104,964✔
5382
      if (other->kind == VCODE_OP_NULL_CHECK && other->args.items[0] == ptr)
103,841✔
5383
         return;
5384
      else if (other->kind == VCODE_OP_NEW && other->result == ptr)
103,464✔
5385
         return;
5386
   }
5387

5388
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
1,123✔
5389
   vcode_add_arg(op, ptr);
1,123✔
5390
   vcode_add_arg(op, locus);
1,123✔
5391

5392
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
1,123✔
5393
                "null check argument must be an access");
5394
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,123✔
5395
                "locus argument to null check must be a debug locus");
5396
}
5397

5398
void emit_deallocate(vcode_reg_t ptr)
207✔
5399
{
5400
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
207✔
5401
   vcode_add_arg(op, ptr);
207✔
5402

5403
   vcode_type_t ptype = vcode_reg_type(ptr);
207✔
5404
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
207✔
5405
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5406
                "deallocate argument must be pointer to access");
5407
}
207✔
5408

5409
vcode_reg_t emit_all(vcode_reg_t reg)
2,177✔
5410
{
5411
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
146,040✔
5412
      if (other->args.items[0] == reg)
9,251✔
5413
         return other->result;
632✔
5414
   }
5415

5416
   op_t *op = vcode_add_op(VCODE_OP_ALL);
1,545✔
5417
   vcode_add_arg(op, reg);
1,545✔
5418

5419
   vcode_type_t vtype = vcode_reg_type(reg);
1,545✔
5420

5421
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
1,545✔
5422
                "all argument must be an access");
5423

5424
   vcode_type_t pointed = vtype_pointed(vtype);
1,545✔
5425
   op->result = vcode_add_reg(vtype_pointer(pointed));
1,545✔
5426

5427
   reg_t *rr = vcode_reg_data(op->result);
1,545✔
5428
   rr->bounds = pointed;
1,545✔
5429

5430
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
1,545✔
5431
                "cannot dereference opaque type");
5432

5433
   return op->result;
5434
}
5435

5436
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
12,905✔
5437
{
5438
   block_t *b = &(active_unit->blocks.items[active_block]);
12,905✔
5439
   for (int i = b->ops.count - 1; i >= 0; i--) {
350,753✔
5440
      const op_t *other = &(b->ops.items[i]);
338,384✔
5441
      if (other->kind == kind && other->args.items[0] == sig)
338,384✔
5442
         return other->result;
536✔
5443
   }
5444

5445
   op_t *op = vcode_add_op(kind);
12,369✔
5446
   vcode_add_arg(op, sig);
12,369✔
5447

5448
   vcode_type_t stype = vcode_reg_type(sig);
12,369✔
5449
   op->type = stype;
12,369✔
5450

5451
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
12,369✔
5452
                "argument r%d to resolved is not a signal", sig);
5453

5454
   vcode_type_t rtype = vtype_base(stype);
12,369✔
5455

5456
   const vtype_kind_t rkind = vtype_kind(rtype);
12,369✔
5457
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
12,369✔
UNCOV
5458
      rtype = vtype_elem(rtype);
×
5459

5460
   VCODE_ASSERT(vtype_is_scalar(rtype),
12,369✔
5461
                "resolved signal base type must be scalar");
5462

5463
   op->result = vcode_add_reg(vtype_pointer(rtype));
12,369✔
5464

5465
   reg_t *rr = vcode_reg_data(op->result);
12,369✔
5466
   rr->bounds = rtype;
12,369✔
5467

5468
   return op->result;
12,369✔
5469
}
5470

5471
vcode_reg_t emit_resolved(vcode_reg_t sig)
12,864✔
5472
{
5473
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
12,864✔
5474
}
5475

5476
vcode_reg_t emit_last_value(vcode_reg_t sig)
41✔
5477
{
5478
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
41✔
5479
}
5480

5481
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
42✔
5482
{
5483
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
42✔
5484
   vcode_add_arg(op, signal);
42✔
5485
   if (len != VCODE_INVALID_REG)
42✔
5486
      vcode_add_arg(op, len);
30✔
5487

5488
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
42✔
5489
                "signal argument to last event must have signal type");
5490
   VCODE_ASSERT(len == VCODE_INVALID_REG
42✔
5491
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5492
                "length argument to last event must have offset type");
5493

5494
   return (op->result = vcode_add_reg(vtype_time()));
42✔
5495
}
5496

5497
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
36✔
5498
{
5499
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
36✔
5500
   vcode_add_arg(op, signal);
36✔
5501
   if (len != VCODE_INVALID_REG)
36✔
5502
      vcode_add_arg(op, len);
27✔
5503

5504
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5505
                "signal argument to last active must have signal type");
5506
   VCODE_ASSERT(len == VCODE_INVALID_REG
36✔
5507
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5508
                "length argument to last active must have offset type");
5509

5510
   return (op->result = vcode_add_reg(vtype_time()));
36✔
5511
}
5512

5513
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
6,919✔
5514
{
5515
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
6,919✔
5516
   vcode_add_arg(op, signal);
6,919✔
5517
   vcode_add_arg(op, locus);
6,919✔
5518

5519
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
6,919✔
5520
                "signal argument must have signal type");
5521
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,919✔
5522
                "locus argument must have debug locus type");
5523
}
6,919✔
5524

5525
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
30✔
5526
{
5527
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
30✔
5528
   vcode_add_arg(op, signal);
30✔
5529
   vcode_add_arg(op, len);
30✔
5530

5531
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
30✔
5532
                "signal argument to last active must have signal type");
5533
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
30✔
5534
                "length argument to last active must have offset type");
5535

5536
   return (op->result = vcode_add_reg(vtype_bool()));
30✔
5537
}
5538

5539
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
24✔
5540
{
5541
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
24✔
5542
   vcode_add_arg(op, signal);
24✔
5543
   if (len != VCODE_INVALID_REG)
24✔
5544
      vcode_add_arg(op, len);
3✔
5545

5546
   vcode_type_t signal_type = vcode_reg_type(signal);
24✔
5547

5548
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
24✔
5549
                "signal argument to last active must have signal type");
5550
   VCODE_ASSERT(len == VCODE_INVALID_REG
24✔
5551
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5552
                "length argument to last active must have offset type");
5553

5554
   vcode_type_t base_type = vtype_base(signal_type);
24✔
5555
   op->result = vcode_add_reg(vtype_pointer(base_type));
24✔
5556

5557
   reg_t *rr = vcode_reg_data(op->result);
24✔
5558
   rr->bounds = base_type;
24✔
5559

5560
   return op->result;
24✔
5561
}
5562

5563
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
21,444✔
5564
                       vcode_reg_t dim)
5565
{
5566
   if (rlen == llen)
21,444✔
5567
      return;
5568

5569
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
181,954✔
5570
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
2,810✔
5571
         return;
5572
   }
5573

5574
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
6,707✔
5575
   vcode_add_arg(op, llen);
6,707✔
5576
   vcode_add_arg(op, rlen);
6,707✔
5577
   vcode_add_arg(op, locus);
6,707✔
5578
   if (dim != VCODE_INVALID_REG)
6,707✔
5579
      vcode_add_arg(op, dim);
24✔
5580

5581
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,707✔
5582
                "locus argument to length check must be a debug locus");
5583
}
5584

5585
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
1,572✔
5586
{
5587
   int64_t cval;
1,572✔
5588
   if (vcode_reg_const(exp, &cval) && cval >= 0)
1,572✔
5589
      return;
1,055✔
5590

5591
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
3,290✔
5592
      if (other->args.items[0] == exp)
12✔
5593
         return;
5594
   }
5595

5596
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
517✔
5597
   vcode_add_arg(op, exp);
517✔
5598
   vcode_add_arg(op, locus);
517✔
5599

5600
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
517✔
5601
                "exp argument to exponent check must be a integer");
5602
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
517✔
5603
                "locus argument to exponent check must be a debug locus");
5604
}
5605

5606
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
1,013✔
5607
{
5608
   int64_t cval;
1,013✔
5609
   if (vcode_reg_const(denom, &cval) && cval != 0)
1,013✔
5610
      return;
910✔
5611

5612
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
2,886✔
5613
      if (other->args.items[0] == denom)
56✔
5614
         return;
5615
   }
5616

5617
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
103✔
5618
   vcode_add_arg(op, denom);
103✔
5619
   vcode_add_arg(op, locus);
103✔
5620

5621
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
103✔
5622
                "denom argument to zero check must be a integer");
5623
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
103✔
5624
                "locus argument to zero check must be a debug locus");
5625
}
5626

5627
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
47,106✔
5628
                                   vcode_reg_t right, vcode_reg_t dir)
5629
{
5630
   int64_t dconst;
47,106✔
5631
   if (vcode_reg_const(dir, &dconst)) {
47,106✔
5632
      int64_t lconst, rconst;
38,334✔
5633
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
38,334✔
5634
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
28,940✔
5635
            || (dconst == RANGE_DOWNTO && rconst > lconst);
61,092✔
5636

5637
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
32,153✔
5638

5639
         const bool ok_static =
64,306✔
5640
            (dconst == RANGE_TO
5641
             && bounds->low >= lconst && bounds->high <= rconst)
28,940✔
5642
            || (dconst == RANGE_DOWNTO
7,608✔
5643
                && bounds->low >= rconst && bounds->high <= lconst)
3,213✔
5644
            || (!is_null && (reg == left || reg == right));
36,740✔
5645

5646
         return ok_static;
37,552✔
5647
      }
5648
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
6,181✔
5649
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
5,805✔
5650
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
5,805✔
5651

5652
         assert(lbounds->kind == VCODE_TYPE_REAL);
5,805✔
5653
         assert(rbounds->kind == VCODE_TYPE_REAL);
5,805✔
5654

5655
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
5,805✔
5656
         assert(bounds->kind == VCODE_TYPE_REAL);
5,805✔
5657

5658
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
5,805✔
5659
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
5,399✔
5660
            // Covers the complete double range so can never overflow
5661
            return true;
5662
         }
5663
      }
5664
   }
5665

5666
   return false;
5667
}
5668

5669
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
47,699✔
5670
                              vcode_reg_t left, vcode_reg_t right,
5671
                              vcode_reg_t dir, vcode_reg_t locus,
5672
                              vcode_reg_t hint)
5673
{
5674
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
2,242,129✔
5675
      if (other->args.items[0] == reg && other->args.items[1] == left
13,508✔
5676
          && other->args.items[2] == right && other->args.items[3] == dir)
599✔
5677
         return;
5678
   }
5679

5680
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
47,106✔
5681
      emit_comment("Elided bounds check for r%d", reg);
32,965✔
5682
      return;
32,965✔
5683
   }
5684

5685
   op_t *op = vcode_add_op(kind);
14,141✔
5686
   vcode_add_arg(op, reg);
14,141✔
5687
   vcode_add_arg(op, left);
14,141✔
5688
   vcode_add_arg(op, right);
14,141✔
5689
   vcode_add_arg(op, dir);
14,141✔
5690
   vcode_add_arg(op, locus);
14,141✔
5691
   vcode_add_arg(op, hint);
14,141✔
5692

5693
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
14,141✔
5694
                "locus argument to bounds check must be a debug locus");
5695
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
14,141✔
5696
                "hint argument to bounds check must be a debug locus");
5697
}
5698

5699
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
8,454✔
5700
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5701
{
5702
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
8,454✔
5703
}
8,454✔
5704

5705
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
39,245✔
5706
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5707
{
5708
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
39,245✔
5709
}
39,245✔
5710

5711
void emit_push_scope(vcode_reg_t locus, vcode_type_t type)
1,947✔
5712
{
5713
   op_t *op = vcode_add_op(VCODE_OP_PUSH_SCOPE);
1,947✔
5714
   vcode_add_arg(op, locus);
1,947✔
5715
   op->type = type;
1,947✔
5716

5717
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,947✔
5718
                "locus argument to push scope must be a debug locus");
5719
}
1,947✔
5720

5721
void emit_pop_scope(void)
1,947✔
5722
{
5723
   vcode_add_op(VCODE_OP_POP_SCOPE);
1,947✔
5724
}
1,947✔
5725

5726
vcode_reg_t emit_debug_locus(ident_t unit, ptrdiff_t offset)
116,961✔
5727
{
5728
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
6,275,104✔
5729
      if (other->ident == unit && other->tag == offset)
986,673✔
5730
         return other->result;
7,165✔
5731
   }
5732

5733
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
109,796✔
5734
   op->ident = unit;
109,796✔
5735
   op->value = offset;
109,796✔
5736

5737
   return (op->result = vcode_add_reg(vtype_debug_locus()));
109,796✔
5738
}
5739

UNCOV
5740
void emit_debug_out(vcode_reg_t reg)
×
5741
{
UNCOV
5742
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
5743
   vcode_add_arg(op, reg);
×
UNCOV
5744
}
×
5745

5746
void emit_cover_increment(uint32_t tag)
2,117✔
5747
{
5748
   op_t *op = vcode_add_op(VCODE_OP_COVER_INCREMENT);
2,117✔
5749
   op->tag = tag;
2,117✔
5750
}
2,117✔
5751

5752
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
312✔
5753
{
5754
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
312✔
5755
   vcode_add_arg(op, signal);
312✔
5756
   op->tag = tag;
312✔
5757
}
312✔
5758

5759
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
12✔
5760
{
5761
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
12✔
5762
   vcode_add_arg(op, signal);
12✔
5763
   vcode_add_arg(op, low);
12✔
5764
   op->tag = tag;
12✔
5765
}
12✔
5766

5767
void emit_unreachable(vcode_reg_t locus)
512✔
5768
{
5769
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
512✔
5770
   if (locus != VCODE_INVALID_REG)
512✔
5771
      vcode_add_arg(op, locus);
153✔
5772
}
512✔
5773

5774
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
1,504✔
5775
{
5776
   active_unit->flags |= UNIT_UNDEFINED;
1,504✔
5777

5778
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
1,504✔
5779
   op->result = vcode_add_reg(type);
1,504✔
5780
   vcode_reg_data(op->result)->bounds = bounds;
1,504✔
5781

5782
   return op->result;
1,504✔
5783
}
5784

5785
void emit_debug_info(const loc_t *loc)
1,316,543✔
5786
{
5787
   if (!loc_invalid_p(loc))
1,316,543✔
5788
      vcode_block_data()->last_loc = *loc;
1,290,922✔
5789
}
1,316,543✔
5790

5791
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
4,142✔
5792
{
5793
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
157,092✔
5794
      if (other->args.items[0] == context && other->ident == name)
8,806✔
5795
         return other->result;
1,553✔
5796
   }
5797

5798
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
2,589✔
5799
   vcode_add_arg(op, context);
2,589✔
5800
   op->ident = name;
2,589✔
5801

5802
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
2,589✔
5803
                "first argument to link var must be context");
5804

5805
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
2,589✔
5806
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
79✔
5807
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
79✔
5808
   }
5809
   else {
5810
      op->result = vcode_add_reg(vtype_pointer(type));
2,510✔
5811
      vcode_reg_data(op->result)->bounds = type;
2,510✔
5812
   }
5813

5814
   return op->result;
2,589✔
5815
}
5816

5817
vcode_reg_t emit_link_package(ident_t name)
23,021✔
5818
{
5819
   VCODE_FOR_EACH_OP(other) {
1,088,315✔
5820
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
1,077,604✔
5821
         return other->result;
7,440✔
5822
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
1,070,164✔
5823
         return other->result;
4,870✔
5824
   }
5825

5826
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
10,711✔
5827
   op->ident = name;
10,711✔
5828

5829
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
10,711✔
5830

5831
   return (op->result = vcode_add_reg(vtype_context(name)));
10,711✔
5832
}
5833

5834
vcode_reg_t emit_link_instance(ident_t name, vcode_reg_t locus)
130✔
5835
{
5836
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_INSTANCE) {
352✔
5837
      if (other->ident == name)
34✔
5838
         return other->result;
25✔
5839
   }
5840

5841
   op_t *op = vcode_add_op(VCODE_OP_LINK_INSTANCE);
105✔
5842
   vcode_add_arg(op, locus);
105✔
5843
   op->ident = name;
105✔
5844

5845
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
105✔
5846
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
105✔
5847
                "locus argument to link instance must be a debug locus");
5848

5849
   return (op->result = vcode_add_reg(vtype_context(name)));
105✔
5850
}
5851

5852
void emit_enter_state(vcode_reg_t state)
435✔
5853
{
5854
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
1,350✔
5855
      if (other->args.items[0] == state)
54✔
5856
         return;
5857
   }
5858

5859
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
435✔
5860
   vcode_add_arg(op, state);
435✔
5861

5862
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
435✔
5863
                "state must have integer type");
5864
}
5865

5866
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
45✔
5867
                               vcode_reg_t locus, vcode_reg_t bounds)
5868
{
5869
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
45✔
5870
   vcode_add_arg(op, value);
45✔
5871
   vcode_add_arg(op, context);
45✔
5872
   vcode_add_arg(op, locus);
45✔
5873
   if (bounds != VCODE_INVALID_REG)
45✔
5874
      vcode_add_arg(op, bounds);
6✔
5875

5876
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
45✔
5877
                "invalid reflect value context argument");
5878
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5879
                "locus argument to reflect value must be a debug locus");
5880

5881
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
45✔
5882
}
5883

5884
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
42✔
5885
                                 vcode_reg_t bounds)
5886
{
5887
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
42✔
5888
   vcode_add_arg(op, context);
42✔
5889
   vcode_add_arg(op, locus);
42✔
5890
   if (bounds != VCODE_INVALID_REG)
42✔
UNCOV
5891
      vcode_add_arg(op, bounds);
×
5892

5893
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
42✔
5894
                "invalid reflect value context argument");
5895
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
42✔
5896
                "locus argument to reflect value must be a debug locus");
5897

5898
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
42✔
5899
}
5900

5901
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
169✔
5902
                                  int nargs)
5903
{
5904
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
169✔
5905
   op->func = func;
169✔
5906

5907
   for (int i = 0; i < nargs; i++)
477✔
5908
      vcode_add_arg(op, args[i]);
308✔
5909

5910
   return (op->result = vcode_add_reg(vtype_trigger()));
169✔
5911
}
5912

5913
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
31✔
5914
{
5915
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
31✔
5916
   vcode_add_arg(op, left);
31✔
5917
   vcode_add_arg(op, right);
31✔
5918

5919
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
31✔
5920
                "or trigger left argument must be trigger");
5921
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
31✔
5922
                "or trigger right argument must be trigger");
5923

5924
   return (op->result = vcode_add_reg(vtype_trigger()));
31✔
5925
}
5926

5927
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
63✔
5928
{
5929
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
63✔
5930
   vcode_add_arg(op, left);
63✔
5931
   vcode_add_arg(op, right);
63✔
5932

5933
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
63✔
5934
                "cmp trigger left argument must be signal");
5935
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
63✔
5936
                "cmp trigger right argument must be integer");
5937

5938
   return (op->result = vcode_add_reg(vtype_trigger()));
63✔
5939
}
5940

5941
void emit_add_trigger(vcode_reg_t trigger)
263✔
5942
{
5943
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
263✔
5944
   vcode_add_arg(op, trigger);
263✔
5945

5946
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
263✔
5947
                "add trigger argument must be trigger");
5948
}
263✔
5949

5950
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
180✔
5951
{
5952
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
180✔
5953
   vcode_add_arg(op, driving);
180✔
5954
   if (effective != VCODE_INVALID_REG && effective != driving)
180✔
5955
      vcode_add_arg(op, effective);
15✔
5956

5957
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
180✔
5958
                "port conversion argument must be a closure");
5959
   VCODE_ASSERT(effective == VCODE_INVALID_REG
180✔
5960
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
5961
                "port conversion argument must be a closure");
5962

5963
   return (op->result = vcode_add_reg(vtype_conversion()));
180✔
5964
}
5965

5966
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
252✔
5967
{
5968
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
252✔
5969
   vcode_add_arg(op, conv);
252✔
5970
   vcode_add_arg(op, nets);
252✔
5971
   vcode_add_arg(op, count);
252✔
5972

5973
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
252✔
5974
                "conv argument to convert must be a port conversion");
5975
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
252✔
5976
                "nets argument to convert must be a signal");
5977
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
252✔
5978
                "count argument to convert must be offset");
5979
}
252✔
5980

5981
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
294✔
5982
{
5983
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
294✔
5984
   vcode_add_arg(op, conv);
294✔
5985
   vcode_add_arg(op, nets);
294✔
5986
   vcode_add_arg(op, count);
294✔
5987

5988
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
294✔
5989
                "conv argument to convert must be a port conversion");
5990
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
294✔
5991
                "nets argument to convert must be a signal");
5992
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
294✔
5993
                "count argument to convert must be offset");
5994
}
294✔
5995

5996
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
251✔
5997
{
5998
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
251✔
5999
   vcode_add_arg(op, spec);
251✔
6000
   vcode_add_arg(op, length);
251✔
6001
   if (locus != VCODE_INVALID_REG)
251✔
6002
      vcode_add_arg(op, locus);
116✔
6003

6004
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
251✔
6005
                "spec argument to bind foreign must be a pointer");
6006
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
251✔
6007
                "length argument to bind foreign must be offset");
6008
   VCODE_ASSERT(locus == VCODE_INVALID_REG
251✔
6009
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6010
                "locus argument to bind foreign value must be a debug locus");
6011
}
251✔
6012

6013
vcode_reg_t emit_instance_name(vcode_reg_t kind)
777✔
6014
{
6015
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
777✔
6016
   vcode_add_arg(op, kind);
777✔
6017

6018
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
777✔
6019
                "kind argument to instance name must be offset");
6020

6021
   vcode_type_t vchar = vtype_char();
777✔
6022
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
777✔
6023
}
6024

6025
void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count,
87✔
6026
                         vcode_reg_t values)
6027
{
6028
   op_t *op = vcode_add_op(VCODE_OP_DEPOSIT_SIGNAL);
87✔
6029
   vcode_add_arg(op, signal);
87✔
6030
   vcode_add_arg(op, count);
87✔
6031
   vcode_add_arg(op, values);
87✔
6032

6033
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
87✔
6034
                "deposit signal target is not signal");
6035
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
87✔
6036
                "deposit signal count is not offset type");
6037
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
87✔
6038
                "signal cannot be values argument for deposit signal");
6039
}
87✔
6040

6041
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
28,006✔
6042
{
6043
   vcode_state_t state;
28,006✔
6044
   vcode_state_save(&state);
28,006✔
6045

6046
   vcode_select_unit(vu);
28,006✔
6047

6048
   const int nblocks = vcode_count_blocks();
28,006✔
6049
   for (int i = 0; i < nblocks; i++) {
133,501✔
6050
      vcode_select_block(i);
105,495✔
6051

6052
      const int nops = vcode_count_ops();
105,495✔
6053
      for (int op = 0; op < nops; op++) {
1,458,081✔
6054
         switch (vcode_get_op(op)) {
1,352,586✔
6055
         case VCODE_OP_LINK_PACKAGE:
9,158✔
6056
            (*fn)(vcode_get_ident(op), ctx);
9,158✔
6057
            break;
9,158✔
6058
         case VCODE_OP_FCALL:
49,881✔
6059
         case VCODE_OP_PCALL:
6060
         case VCODE_OP_CLOSURE:
6061
         case VCODE_OP_PROTECTED_INIT:
6062
         case VCODE_OP_PACKAGE_INIT:
6063
         case VCODE_OP_FUNCTION_TRIGGER:
6064
            (*fn)(vcode_get_func(op), ctx);
49,881✔
6065
            break;
49,881✔
6066
         default:
6067
            break;
6068
         }
6069
      }
6070
   }
6071

6072
   vcode_state_restore(&state);
28,006✔
6073
}
28,006✔
6074

6075
#ifdef DEBUG
UNCOV
6076
static void shape_mismatch(vcode_unit_t vu, vcode_unit_t shape,
×
6077
                           const char *fmt, ...)
6078
{
UNCOV
6079
   vcode_select_unit(vu);
×
UNCOV
6080
   vcode_dump();
×
6081

UNCOV
6082
   vcode_select_unit(shape);
×
UNCOV
6083
   vcode_dump();
×
6084

UNCOV
6085
   va_list ap;
×
UNCOV
6086
   va_start(ap, fmt);
×
6087

UNCOV
6088
   diag_t *d = diag_new(DIAG_FATAL, NULL);
×
UNCOV
6089
   diag_printf(d, "instance %s does not match shape %s", istr(vu->name),
×
6090
               istr(shape->name));
6091
   diag_stacktrace(d, true);
×
UNCOV
6092
   diag_vhint(d, NULL, fmt, ap);
×
UNCOV
6093
   diag_emit(d);
×
6094

6095
   va_end(ap);
×
6096

6097
   fatal_exit(1);
×
6098
}
6099
#endif
6100

6101
void vcode_check_shape(vcode_unit_t vu, vcode_unit_t shape)
51✔
6102
{
6103
#ifdef DEBUG
6104
   assert(shape->kind == VCODE_UNIT_SHAPE);
51✔
6105
   assert(vu->kind == VCODE_UNIT_INSTANCE);
51✔
6106

6107
   if (shape->vars.count <= vu->vars.count) {
51✔
6108
      for (int i = 0; i < shape->vars.count; i++) {
193✔
6109
         var_t *v = var_array_nth_ptr(&(vu->vars), i);
142✔
6110
         var_t *s = var_array_nth_ptr(&(shape->vars), i);
142✔
6111

6112
         if (v->name != s->name)
142✔
UNCOV
6113
            shape_mismatch(vu, shape, "var %d name %s != %s", i, istr(v->name),
×
6114
                           istr(s->name));
6115
         else if (v->flags != s->flags)
142✔
UNCOV
6116
            shape_mismatch(vu, shape, "var %d flags %x != %x", i, v->flags,
×
6117
                           s->flags);
6118
         // XXX: not possible to compare types at the moment
6119
      }
6120
   }
6121
   else
UNCOV
6122
      shape_mismatch(vu, shape, "shape vars %d > unit vars %d",
×
6123
                     shape->vars.count, vu->vars.count);
6124

6125
   if (shape->context != NULL)
51✔
UNCOV
6126
      vcode_check_shape(vu->context, shape->context);
×
6127
#endif
6128
}
51✔
6129

6130
#if VCODE_CHECK_UNIONS
6131
#define OP_USE_COUNT_U0(x)                                              \
6132
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6133
#define OP_USE_COUNT_U1(x)                                              \
6134
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6135
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6136
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6137

6138
__attribute__((constructor))
6139
static void vcode_check_unions(void)
6140
{
6141
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6142
   for (int i = 0; i < 256; i++) {
6143
      assert(OP_USE_COUNT_U0(i) <= 1);
6144
      assert(OP_USE_COUNT_U1(i) <= 1);
6145
   }
6146
}
6147
#endif  // VCODE_CHECK_UNIONS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc