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

nickg / nvc / 13639056006

03 Mar 2025 07:41PM UTC coverage: 92.275% (+0.2%) from 92.103%
13639056006

push

github

nickg
Add a new mid-level IR to replace vcode

4917 of 5118 new or added lines in 14 files covered. (96.07%)

12 existing lines in 4 files now uncovered.

68043 of 73739 relevant lines covered (92.28%)

484008.28 hits per line

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

96.83
/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,305,330✔
36
DECLARE_AND_DEFINE_ARRAY(vcode_block);
368,321✔
37
DECLARE_AND_DEFINE_ARRAY(vcode_type);
80,563✔
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_BIND_EXTERNAL || x == VCODE_OP_ARRAY_SCOPE         \
44
    || x == VCODE_OP_RECORD_SCOPE || x == VCODE_OP_SYSCALL)
45
#define OP_HAS_ADDRESS(x)                                               \
46
   (x == VCODE_OP_LOAD || x == VCODE_OP_STORE || x == VCODE_OP_INDEX    \
47
    || x == VCODE_OP_VAR_UPREF)
48
#define OP_HAS_FUNC(x)                                                  \
49
   (x == VCODE_OP_FCALL || x == VCODE_OP_PCALL || x == VCODE_OP_RESUME  \
50
    || x == VCODE_OP_CLOSURE || x == VCODE_OP_PROTECTED_INIT            \
51
    || x == VCODE_OP_PACKAGE_INIT || x == VCODE_OP_PROCESS_INIT \
52
    || x == VCODE_OP_FUNCTION_TRIGGER || x == VCODE_OP_SYSCALL)
53
#define OP_HAS_IDENT(x)                                                 \
54
   (x == VCODE_OP_LINK_VAR || x == VCODE_OP_LINK_PACKAGE                \
55
    || x == VCODE_OP_DEBUG_LOCUS || x == VCODE_OP_BIND_EXTERNAL)
56
#define OP_HAS_OBJECT(x)                                                 \
57
   (x == VCODE_OP_DEBUG_LOCUS)
58
#define OP_HAS_REAL(x)                                                  \
59
   (x == VCODE_OP_CONST_REAL)
60
#define OP_HAS_VALUE(x)                                                 \
61
   (x == VCODE_OP_CONST || x == VCODE_OP_CONST_REP)
62
#define OP_HAS_DIM(x)                                                   \
63
   (x == VCODE_OP_UARRAY_LEFT || x == VCODE_OP_UARRAY_RIGHT             \
64
    || x == VCODE_OP_UARRAY_DIR || x == VCODE_OP_UARRAY_LEN)
65
#define OP_HAS_HOPS(x)                                                  \
66
   (x == VCODE_OP_VAR_UPREF || x == VCODE_OP_CONTEXT_UPREF)
67
#define OP_HAS_FIELD(x)                                                 \
68
   (x == VCODE_OP_RECORD_REF)
69
#define OP_HAS_CMP(x)                                                   \
70
   (x == VCODE_OP_CMP)
71
#define OP_HAS_TAG(x)                                                   \
72
   (x == VCODE_OP_COVER_STMT || x == VCODE_OP_COVER_BRANCH              \
73
    || x == VCODE_OP_COVER_TOGGLE || x == VCODE_OP_COVER_EXPR           \
74
    || x == VCODE_OP_COVER_STATE)
75
#define OP_HAS_COMMENT(x)                                               \
76
   (x == VCODE_OP_COMMENT)
77
#define OP_HAS_TARGET(x)                                                \
78
   (x == VCODE_OP_WAIT || x == VCODE_OP_JUMP || x == VCODE_OP_COND      \
79
    || x == VCODE_OP_PCALL || x == VCODE_OP_CASE)
80

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

106
DECLARE_AND_DEFINE_ARRAY(op);
11,184,360✔
107

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

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

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

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

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

159
DECLARE_AND_DEFINE_ARRAY(param);
31,756✔
160
DECLARE_AND_DEFINE_ARRAY(var);
324,892✔
161
DECLARE_AND_DEFINE_ARRAY(reg);
7,804,886✔
162
DECLARE_AND_DEFINE_ARRAY(block);
139,266✔
163
DECLARE_AND_DEFINE_ARRAY(vtype);
70,820,677✔
164

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

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

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

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

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

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

213
#define VCODE_CHECK_UNIONS 0
214

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

218
static inline int64_t sadd64(int64_t a, int64_t b)
31,722✔
219
{
220
   int64_t result;
31,722✔
221
   if (__builtin_add_overflow(a, b, &result))
31,722✔
222
      return b < 0 ? INT64_MIN : INT64_MAX;
12,247✔
223

224
   return result;
225
}
226

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

233
   return result;
234
}
235

236
static inline int64_t smul64(int64_t a, int64_t b)
9,204✔
237
{
238
   int64_t result;
9,204✔
239
   if (__builtin_mul_overflow(a, b, &result))
9,204✔
240
      return (a > 0 && b > 0) || (a < 0 && b < 0) ? INT64_MAX : INT64_MIN;
4,681✔
241

242
   return result;
243
}
244

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

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

255
   return reg;
1,303,526✔
256
}
257

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

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

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

274
   block_t *block = vcode_block_data();
1,647,395✔
275

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

282
   return op;
1,647,395✔
283
}
284

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

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

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

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

304
static op_t *vcode_find_definition(vcode_reg_t reg)
1,200,394✔
305
{
306
   for (int i = active_block; i >= 0; i--) {
1,248,130✔
307
      block_t *b = &(active_unit->blocks.items[i]);
1,245,200✔
308
      for (int j = b->ops.count - 1; j >= 0; j--) {
16,282,934✔
309
         if (b->ops.items[j].result == reg)
16,235,198✔
310
            return &(b->ops.items[j]);
1,197,464✔
311
      }
312
   }
313

314
   return NULL;
315
}
316

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

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

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

347
   int depth = MASK_CONTEXT(type);
68,271,114✔
348
   assert(depth <= unit->depth);
68,271,114✔
349
   while (depth != unit->depth)
69,450,065✔
350
      unit = unit->context;
1,178,951✔
351

352
   return vtype_array_nth_ptr(&(unit->types), MASK_INDEX(type));
68,271,114✔
353
}
354

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

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

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

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

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

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

397
   case VCODE_OP_VAR_UPREF:
790✔
398
      {
399
         vcode_unit_t vu = vcode_active_unit();
790✔
400
         for (int i = 0; i < defn->hops; i++)
1,583✔
401
            vu = vcode_unit_context(vu);
793✔
402

403
         vcode_state_t state;
790✔
404
         vcode_state_save(&state);
790✔
405

406
         vcode_select_unit(vu);
790✔
407

408
         vcode_var_data(defn->address)->flags |= VAR_HEAP;
790✔
409
         active_unit->flags |= UNIT_ESCAPING_TLAB;
790✔
410

411
         vcode_state_restore(&state);
790✔
412
      }
413
      break;
790✔
414

415
   case VCODE_OP_ARRAY_REF:
147✔
416
      vcode_heap_allocate(defn->args.items[0]);
147✔
417
      break;
147✔
418

419
   case VCODE_OP_WRAP:
7,760✔
420
   case VCODE_OP_UNWRAP:
421
   case VCODE_OP_RESOLVED:
422
      vcode_heap_allocate(defn->args.items[0]);
7,760✔
423
      break;
7,760✔
424

425
   case VCODE_OP_LAST_VALUE:
426
      // Returns a pointer into the C heap
427
      break;
428

429
   case VCODE_OP_LOAD:
1,856✔
430
      {
431
         if (vcode_reg_kind(reg) != VCODE_TYPE_UARRAY)
1,856✔
432
            return;
433

434
         // Any store to this variable must be heap allocated
435
         for (int i = 0; i < active_unit->blocks.count; i++) {
21,517✔
436
            block_t *b = &(active_unit->blocks.items[i]);
19,907✔
437
            for (int j = 0; j < b->ops.count; j++) {
275,787✔
438
               op_t *op = &(b->ops.items[j]);
255,880✔
439
               if (op->kind == VCODE_OP_STORE && op->address == defn->address)
255,880✔
440
                  vcode_heap_allocate(op->args.items[0]);
1,610✔
441

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

450
   case VCODE_OP_FCALL:
451
      for (int i = 0; i < defn->args.count; i++) {
10,960✔
452
         const vtype_kind_t rkind = vcode_reg_kind(reg);
8,345✔
453
         if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
8,345✔
454
            // Function may return a pointer to its argument
455
            vcode_heap_allocate(defn->args.items[i]);
8,136✔
456
         }
457
      }
458
      break;
459

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

464
   case VCODE_OP_SELECT:
516✔
465
      vcode_heap_allocate(defn->args.items[1]);
516✔
466
      vcode_heap_allocate(defn->args.items[2]);
516✔
467
      break;
516✔
468

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

478
   case VCODE_OP_ALL:
479
      // Must have been allocated on the heap
480
      break;
481

482
   case VCODE_OP_NEW:
483
      // On the heap by definition
484
      break;
485

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

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

524
void vcode_state_save(vcode_state_t *state)
44,297✔
525
{
526
   state->unit  = active_unit;
44,297✔
527
   state->block = active_block;
44,297✔
528
}
44,297✔
529

530
void vcode_state_restore(const vcode_state_t *state)
44,297✔
531
{
532
   active_unit  = state->unit;
44,297✔
533
   active_block = state->block;
44,297✔
534
}
44,297✔
535

536
void vcode_unit_unref(vcode_unit_t unit)
44,764✔
537
{
538
   assert(unit != NULL);
44,764✔
539

540
   if (unit == active_unit)
44,764✔
541
      vcode_close();
12,178✔
542

543
   for (vcode_unit_t it = unit->children; it != NULL; it = it->next) {
58,582✔
544
      assert(it->context == unit);
13,818✔
545
      it->context = NULL;
13,818✔
546
   }
547
   unit->children = NULL;
44,764✔
548

549
   if (unit->context != NULL) {
44,764✔
550
      vcode_unit_t *it = &(unit->context->children);
14,178✔
551
      for (; *it != NULL && *it != unit; it = &((*it)->next))
293,464✔
552
         ;
553
      assert(*it != NULL);
14,178✔
554
      *it = (*it)->next;
14,178✔
555
   }
556

557
   for (unsigned i = 0; i < unit->blocks.count; i++) {
184,008✔
558
      block_t *b = &(unit->blocks.items[i]);
139,244✔
559

560
      for (unsigned j = 0; j < b->ops.count; j++) {
1,711,313✔
561
         op_t *o = &(b->ops.items[j]);
1,572,069✔
562
         if (OP_HAS_COMMENT(o->kind))
1,572,069✔
563
            free(o->comment);
116,129✔
564
         if (OP_HAS_TARGET(o->kind))
1,572,069✔
565
            free(o->targets.items);
85,046✔
566
         free(o->args.items);
1,572,069✔
567
      }
568
      free(b->ops.items);
139,244✔
569
   }
570
   free(unit->blocks.items);
44,764✔
571

572
   for (unsigned i = 0; i < unit->types.count; i++) {
582,981✔
573
      vtype_t *vt = &(unit->types.items[i]);
538,217✔
574
      if (vt->kind == VCODE_TYPE_RECORD)
538,217✔
575
         free(vt->fields.items);
5,778✔
576
   }
577
   free(unit->types.items);
44,764✔
578

579
   free(unit->regs.items);
44,764✔
580
   free(unit->vars.items);
44,764✔
581
   free(unit->params.items);
44,764✔
582
   free(unit);
44,764✔
583
}
44,764✔
584

585
vcode_unit_t vcode_unit_next(vcode_unit_t unit)
25,268✔
586
{
587
   return unit->next;
25,268✔
588
}
589

590
vcode_unit_t vcode_unit_child(vcode_unit_t unit)
22,588✔
591
{
592
   return unit->children;
22,588✔
593
}
594

595
int vcode_count_regs(void)
42,734✔
596
{
597
   assert(active_unit != NULL);
42,734✔
598
   return active_unit->regs.count;
42,734✔
599
}
600

601
vcode_type_t vcode_reg_type(vcode_reg_t reg)
4,406,053✔
602
{
603
   return vcode_reg_data(reg)->type;
4,406,053✔
604
}
605

606
vtype_kind_t vcode_reg_kind(vcode_reg_t reg)
1,023,197✔
607
{
608
   return vtype_kind(vcode_reg_type(reg));
1,023,197✔
609
}
610

611
vcode_type_t vcode_reg_bounds(vcode_reg_t reg)
221,994✔
612
{
613
   return vcode_reg_data(reg)->bounds;
221,994✔
614
}
615

616
bool vcode_reg_const(vcode_reg_t reg, int64_t *value)
693,212✔
617
{
618
   reg_t *r = vcode_reg_data(reg);
693,212✔
619

620
   vtype_kind_t kind = vtype_kind(r->type);
693,212✔
621
   if (kind != VCODE_TYPE_INT && kind != VCODE_TYPE_OFFSET)
693,212✔
622
      return false;
623

624
   vtype_t *bounds = vcode_type_data(r->bounds);
675,788✔
625

626
   VCODE_ASSERT(
675,788✔
627
      bounds->kind == VCODE_TYPE_INT || bounds->kind == VCODE_TYPE_OFFSET,
628
      "integer register r%d has non-integer bounds", reg);
629

630
   if (bounds->low == bounds->high) {
675,788✔
631
      if (value) *value = bounds->low;
354,194✔
632
      return true;
354,194✔
633
   }
634
   else
635
      return false;
636
}
637

638
void vcode_opt(void)
44,774✔
639
{
640
   // Prune assignments to unused registers
641

642
   int *uses LOCAL = xmalloc_array(active_unit->regs.count, sizeof(int));
89,548✔
643

644
   int pruned = 0;
44,774✔
645
   do {
60,926✔
646
      memset(uses, '\0', active_unit->regs.count * sizeof(int));
60,926✔
647
      pruned = 0;
60,926✔
648

649
      for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
287,568✔
650
         block_t *b = &(active_unit->blocks.items[i]);
226,642✔
651

652
         for (int j = b->ops.count - 1; j >= 0; j--) {
3,100,941✔
653
            op_t *o = &(b->ops.items[j]);
2,874,299✔
654

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

717
            default:
718
               break;
719
            }
720

721
            for (int k = 0; k < o->args.count; k++) {
7,790,212✔
722
               if (o->args.items[k] != VCODE_INVALID_REG)
4,915,913✔
723
                  uses[o->args.items[k]]++;
4,869,032✔
724
            }
725
         }
726
      }
727
   } while (pruned > 0);
60,926✔
728

729
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
184,040✔
730
      block_t *b = &(active_unit->blocks.items[i]);
139,266✔
731
      op_t *dst = &(b->ops.items[0]);
139,266✔
732
      size_t copied = 0;
139,266✔
733
      for (int j = 0; j < b->ops.count; j++) {
1,786,661✔
734
         const op_t *src = &(b->ops.items[j]);
1,647,395✔
735
         if (src->kind != (vcode_op_t)-1) {
1,647,395✔
736
            if (src != dst) {
1,572,438✔
737
               assert(dst < src);
419,934✔
738
               *dst = *src;
419,934✔
739
            }
740
            dst++;
1,572,438✔
741
            copied++;
1,572,438✔
742
         }
743
      }
744

745
      assert(copied <= b->ops.count);
139,266✔
746
      b->ops.count = copied;
139,266✔
747
   }
748
}
44,774✔
749

750
void vcode_close(void)
31,084✔
751
{
752
   active_unit  = NULL;
31,084✔
753
   active_block = -1;
31,084✔
754
}
31,084✔
755

756
int vcode_count_blocks(void)
72,786✔
757
{
758
   assert(active_unit != NULL);
72,786✔
759
   return active_unit->blocks.count;
72,786✔
760
}
761

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

769
int vcode_count_vars(void)
42,747✔
770
{
771
   assert(active_unit != NULL);
42,747✔
772
   return active_unit->vars.count;
42,747✔
773
}
774

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

783
   return VCODE_INVALID_VAR;
784
}
785

786
ident_t vcode_var_name(vcode_var_t var)
53,018✔
787
{
788
   return vcode_var_data(var)->name;
53,018✔
789
}
790

791
vcode_type_t vcode_var_type(vcode_var_t var)
53,849✔
792
{
793
   return vcode_var_data(var)->type;
53,849✔
794
}
795

796
vcode_type_t vcode_var_bounds(vcode_var_t var)
3,751✔
797
{
798
   return vcode_var_data(var)->bounds;
3,751✔
799
}
800

801
vcode_var_flags_t vcode_var_flags(vcode_var_t var)
55,080✔
802
{
803
   return vcode_var_data(var)->flags;
55,080✔
804
}
805

806
vcode_op_t vcode_get_op(int op)
2,951,316✔
807
{
808
   return vcode_op_data(op)->kind;
2,951,316✔
809
}
810

811
ident_t vcode_get_func(int op)
110,177✔
812
{
813
   op_t *o = vcode_op_data(op);
110,177✔
814
   assert(OP_HAS_FUNC(o->kind));
110,177✔
815
   return o->func;
110,177✔
816
}
817

818
ident_t vcode_get_ident(int op)
23,734✔
819
{
820
   op_t *o = vcode_op_data(op);
23,734✔
821
   assert(OP_HAS_IDENT(o->kind));
23,734✔
822
   return o->ident;
23,734✔
823
}
824

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

832
int64_t vcode_get_value(int op)
317,463✔
833
{
834
   op_t *o = vcode_op_data(op);
317,463✔
835
   assert(OP_HAS_VALUE(o->kind));
317,463✔
836
   return o->value;
317,463✔
837
}
838

839
double vcode_get_real(int op)
20,746✔
840
{
841
   op_t *o = vcode_op_data(op);
20,746✔
842
   assert(OP_HAS_REAL(o->kind));
20,746✔
843
   return o->real;
20,746✔
844
}
845

846
vcode_var_t vcode_get_address(int op)
150,558✔
847
{
848
   op_t *o = vcode_op_data(op);
150,558✔
849
   assert(OP_HAS_ADDRESS(o->kind));
150,558✔
850
   return o->address;
150,558✔
851
}
852

853
unsigned vcode_get_dim(int op)
69,966✔
854
{
855
   op_t *o = vcode_op_data(op);
69,966✔
856
   assert(OP_HAS_DIM(o->kind));
69,966✔
857
   return o->dim;
69,966✔
858
}
859

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

867
int vcode_get_field(int op)
37,544✔
868
{
869
   op_t *o = vcode_op_data(op);
37,544✔
870
   assert(OP_HAS_FIELD(o->kind));
37,544✔
871
   return o->field;
37,544✔
872
}
873

874
vcode_var_t vcode_get_type(int op)
57,894✔
875
{
876
   op_t *o = vcode_op_data(op);
57,894✔
877
   assert(OP_HAS_TYPE(o->kind));
57,894✔
878
   return o->type;
57,894✔
879
}
880

881
int vcode_count_args(int op)
215,144✔
882
{
883
   return vcode_op_data(op)->args.count;
215,144✔
884
}
885

886
vcode_reg_t vcode_get_arg(int op, int arg)
2,661,411✔
887
{
888
   op_t *o = vcode_op_data(op);
2,661,411✔
889
   return vcode_reg_array_nth(&(o->args), arg);
2,661,411✔
890
}
891

892
vcode_reg_t vcode_get_result(int op)
1,105,331✔
893
{
894
   op_t *o = vcode_op_data(op);
1,105,331✔
895
   return o->result;
1,105,331✔
896
}
897

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

905
uint32_t vcode_get_tag(int op)
2,706✔
906
{
907
   op_t *o = vcode_op_data(op);
2,706✔
908
   assert(OP_HAS_TAG(o->kind));
2,706✔
909
   return o->tag;
2,706✔
910
}
911

912
const loc_t *vcode_get_loc(int op)
1,538,486✔
913
{
914
   op_t *o = vcode_op_data(op);
1,538,486✔
915
   return &(o->loc);
1,538,486✔
916
}
917

918
vcode_block_t vcode_get_target(int op, int nth)
120,739✔
919
{
920
   op_t *o = vcode_op_data(op);
120,739✔
921
   assert(OP_HAS_TARGET(o->kind));
120,739✔
922
   return vcode_block_array_nth(&(o->targets), nth);
120,739✔
923
}
924

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

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

933
bool vcode_block_finished(void)
1,752,273✔
934
{
935
   assert(active_unit != NULL);
1,752,273✔
936
   assert(active_block != VCODE_INVALID_BLOCK);
1,752,273✔
937

938
   const block_t *b = &(active_unit->blocks.items[active_block]);
1,752,273✔
939
   if (b->ops.count == 0)
1,752,273✔
940
      return false;
941
   else {
942
      vcode_op_t kind = b->ops.items[b->ops.count - 1].kind;
1,569,057✔
943
      return kind == VCODE_OP_WAIT || kind == VCODE_OP_JUMP
1,569,057✔
944
         || kind == VCODE_OP_COND || kind == VCODE_OP_PCALL
1,569,033✔
945
         || kind == VCODE_OP_RETURN || kind == VCODE_OP_CASE
946
         || kind == VCODE_OP_UNREACHABLE;
3,138,090✔
947
   }
948
}
949

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

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

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

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

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

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

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

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

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

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

1077
   case VCODE_TYPE_OFFSET:
1078
      col += printf("#");
1079
      break;
1080

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

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

1091
   case VCODE_TYPE_OPAQUE:
1092
      col += printf("?");
1093
      break;
1094

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

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

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

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

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

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

1124
   return col;
1125
}
1126

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

1137
static void vcode_dump_comment(int col)
1138
{
1139
   vcode_dump_tab(col, 40);
1140
   color_printf("$cyan$// ");
1141
}
1142

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

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

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

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

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

1179
   const vcode_unit_t vu = active_unit;
1180
   vcode_block_t old_block = active_block;
1181

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

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

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

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

1238
   if (vu->result != VCODE_INVALID_TYPE) {
1239
      color_printf("Result     $cyan$");
1240
      vcode_dump_one_type(vu->result);
1241
      color_printf("$$\n");
1242
   }
1243

1244
   if (vu->kind == VCODE_UNIT_FUNCTION
1245
       || vu->kind == VCODE_UNIT_PROCEDURE
1246
       || vu->kind == VCODE_UNIT_PROPERTY
1247
       || (vu->kind == VCODE_UNIT_PROTECTED && vu->params.count > 0)) {
1248

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1416
         case VCODE_OP_POP_SCOPE:
1417
            {
1418
               printf("%s", vcode_op_string(op->kind));
1419
            }
1420
            break;
1421

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

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

1460
         case VCODE_OP_RESOLUTION_WRAPPER:
1461
            {
1462
               col += vcode_dump_reg(op->result);
1463
               col += color_printf(" := %s ", vcode_op_string(op->kind));
1464
               col += vcode_dump_reg(op->args.items[0]);
1465
               col += printf(" ileft ");
1466
               col += vcode_dump_reg(op->args.items[1]);
1467
               col += printf(" nlits ");
1468
               col += vcode_dump_reg(op->args.items[2]);
1469
               vcode_dump_result_type(col, op);
1470
            }
1471
            break;
1472

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

1490
         case VCODE_OP_PACKAGE_INIT:
1491
            {
1492
               col += vcode_dump_reg(op->result);
1493
               col += color_printf(" := %s $magenta$%s$$",
1494
                                   vcode_op_string(op->kind), istr(op->func));
1495
               if (op->args.count > 0) {
1496
                  col += printf(" context " );
1497
                  col += vcode_dump_reg(op->args.items[0]);
1498
               }
1499
               vcode_dump_result_type(col, op);
1500
            }
1501
            break;
1502

1503
         case VCODE_OP_PROCESS_INIT:
1504
            {
1505
               color_printf("%s $magenta$%s$$ locus ",
1506
                            vcode_op_string(op->kind), istr(op->func));
1507
               vcode_dump_reg(op->args.items[0]);
1508
            }
1509
            break;
1510

1511
         case VCODE_OP_PROTECTED_FREE:
1512
            {
1513
               printf("%s ", vcode_op_string(op->kind));
1514
               vcode_dump_reg(op->args.items[0]);
1515
            }
1516
            break;
1517

1518
         case VCODE_OP_WAIT:
1519
            {
1520
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1521
                            op->targets.items[0]);
1522
               if (op->args.items[0] != VCODE_INVALID_REG) {
1523
                  printf(" for ");
1524
                  vcode_dump_reg(op->args.items[0]);
1525
               }
1526
            }
1527
            break;
1528

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1808
         case VCODE_OP_SELECT:
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(" then ");
1814
               col += vcode_dump_reg(op->args.items[1]);
1815
               col += printf(" else ");
1816
               col += vcode_dump_reg(op->args.items[2]);
1817
               vcode_dump_result_type(col, op);
1818
            }
1819
            break;
1820

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

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

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

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

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

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

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

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

1915
         case VCODE_OP_COPY:
1916
            {
1917
               vcode_dump_reg(op->args.items[0]);
1918
               printf(" := %s ", vcode_op_string(op->kind));
1919
               vcode_dump_reg(op->args.items[1]);
1920
               if (op->args.count > 2) {
1921
                  printf(" count " );
1922
                  vcode_dump_reg(op->args.items[2]);
1923
               }
1924
            }
1925
            break;
1926

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

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

1950
         case VCODE_OP_RESUME:
1951
            {
1952
               color_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1953
                            istr(op->func));
1954
            }
1955
            break;
1956

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2134
         case VCODE_OP_DEBUG_OUT:
2135
            {
2136
               col += printf("%s ", vcode_op_string(op->kind));
2137
               col += vcode_dump_reg(op->args.items[0]);
2138
            }
2139
            break;
2140

2141
         case VCODE_OP_COVER_STMT:
2142
         case VCODE_OP_COVER_BRANCH:
2143
         case VCODE_OP_COVER_EXPR:
2144
            {
2145
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2146
            }
2147
            break;
2148

2149
         case VCODE_OP_COVER_TOGGLE:
2150
         case VCODE_OP_COVER_STATE:
2151
            {
2152
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2153
               vcode_dump_reg(op->args.items[0]);
2154
            }
2155
            break;
2156

2157
         case VCODE_OP_UNDEFINED:
2158
            {
2159
               col += vcode_dump_reg(op->result);
2160
               col += printf(" := %s", vcode_op_string(op->kind));
2161
               vcode_dump_result_type(col, op);
2162
            }
2163
            break;
2164

2165
         case VCODE_OP_RANGE_LENGTH:
2166
         case VCODE_OP_RANGE_NULL:
2167
            {
2168
               col += vcode_dump_reg(op->result);
2169
               col += printf(" := %s left ", vcode_op_string(op->kind));
2170
               vcode_dump_reg(op->args.items[0]);
2171
               col += printf(" right ");
2172
               vcode_dump_reg(op->args.items[1]);
2173
               col += printf(" dir ");
2174
               col += vcode_dump_reg(op->args.items[2]);
2175
               vcode_dump_result_type(col, op);
2176
            }
2177
            break;
2178

2179
         case VCODE_OP_LINK_PACKAGE:
2180
            {
2181
               col += vcode_dump_reg(op->result);
2182
               col += color_printf(" := %s $magenta$%s$$",
2183
                                   vcode_op_string(op->kind), istr(op->ident));
2184
               if (op->args.count > 0) {
2185
                  col += printf(" locus ");
2186
                  col += vcode_dump_reg(op->args.items[0]);
2187
               }
2188
               vcode_dump_result_type(col, op);
2189
            }
2190
            break;
2191

2192
         case VCODE_OP_LINK_VAR:
2193
            {
2194
               col += vcode_dump_reg(op->result);
2195
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2196
               col += vcode_dump_reg(op->args.items[0]);
2197
               col += color_printf(" $magenta$%s$$", istr(op->ident));
2198
               vcode_dump_result_type(col, op);
2199
            }
2200
            break;
2201

2202
         case VCODE_OP_UNREACHABLE:
2203
            {
2204
               printf("%s", vcode_op_string(op->kind));
2205
               if (op->args.count > 0) {
2206
                  printf(" ");
2207
                  vcode_dump_reg(op->args.items[0]);
2208
               }
2209
            }
2210
            break;
2211

2212
         case VCODE_OP_DEBUG_LOCUS:
2213
            {
2214
               col += vcode_dump_reg(op->result);
2215
               col += color_printf(" := %s $magenta$",
2216
                                   vcode_op_string(op->kind));
2217

2218
               tree_t t = tree_from_object(op->object);
2219
               if (t != NULL)
2220
                  col += printf("%s@", tree_kind_str(tree_kind(t)));
2221

2222
               col += color_printf("%p$$", op->object);
2223
               vcode_dump_result_type(col, op);
2224
            }
2225
            break;
2226

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

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

2255
         case VCODE_OP_REFLECT_SUBTYPE:
2256
            {
2257
               col += vcode_dump_reg(op->result);
2258
               col += printf(" := %s context ", vcode_op_string(op->kind));
2259
               vcode_dump_reg(op->args.items[0]);
2260
               col += printf(" locus ");
2261
               col += vcode_dump_reg(op->args.items[1]);
2262
               if (op->args.count > 2) {
2263
                  col += printf(" bounds ");
2264
                  col += vcode_dump_reg(op->args.items[2]);
2265
               }
2266
               vcode_dump_result_type(col, op);
2267
            }
2268
            break;
2269

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

2283
         case VCODE_OP_OR_TRIGGER:
2284
         case VCODE_OP_CMP_TRIGGER:
2285
            {
2286
               col += vcode_dump_reg(op->result);
2287
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2288
               col += vcode_dump_reg(op->args.items[0]);
2289
               if (op->kind == VCODE_OP_OR_TRIGGER)
2290
                  col += printf(" || ");
2291
               else
2292
                  col += printf(" == ");
2293
               col += vcode_dump_reg(op->args.items[1]);
2294
               vcode_dump_result_type(col, op);
2295
            }
2296
            break;
2297

2298
         case VCODE_OP_ADD_TRIGGER:
2299
            {
2300
               printf("%s ", vcode_op_string(op->kind));
2301
               vcode_dump_reg(op->args.items[0]);
2302
            }
2303
            break;
2304

2305
         case VCODE_OP_PUT_CONVERSION:
2306
            {
2307
               color_printf("%s ", vcode_op_string(op->kind));
2308
               vcode_dump_reg(op->args.items[0]);
2309
               printf(" signal ");
2310
               vcode_dump_reg(op->args.items[1]);
2311
               printf(" count ");
2312
               vcode_dump_reg(op->args.items[2]);
2313
               printf(" values ");
2314
               vcode_dump_reg(op->args.items[3]);
2315
            }
2316
            break;
2317

2318
         case VCODE_OP_PORT_CONVERSION:
2319
            {
2320
               col += vcode_dump_reg(op->result);
2321
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2322
               col += vcode_dump_reg(op->args.items[0]);
2323
               if (op->args.count > 1) {
2324
                  col += printf(" effective ");
2325
                  col += vcode_dump_reg(op->args.items[1]);
2326
               }
2327
               vcode_dump_result_type(col, op);
2328
            }
2329
            break;
2330

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

2343
         case VCODE_OP_BIND_FOREIGN:
2344
            {
2345
               color_printf("%s ", vcode_op_string(op->kind));
2346
               vcode_dump_reg(op->args.items[0]);
2347
               printf(" length ");
2348
               vcode_dump_reg(op->args.items[1]);
2349
               if (op->args.count > 2) {
2350
                  printf(" locus ");
2351
                  vcode_dump_reg(op->args.items[1]);
2352
               }
2353
            }
2354
            break;
2355

2356
         case VCODE_OP_INSTANCE_NAME:
2357
         case VCODE_OP_BIND_EXTERNAL:
2358
            {
2359
               col += vcode_dump_reg(op->result);
2360
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2361
               col += vcode_dump_reg(op->args.items[0]);
2362
               col += color_printf(" scope $magenta$%s$$", istr(op->ident));
2363
               vcode_dump_result_type(col, op);
2364
            }
2365
            break;
2366
         }
2367

2368
         if (j == mark_op && i == old_block)
2369
            color_printf("\t $red$<----$$");
2370

2371
         color_printf("$$\n");
2372

2373
         if (callback != NULL)
2374
            (*callback)(j, arg);
2375
      }
2376

2377
      if (b->ops.count == 0)
2378
         color_printf("  $yellow$%2d:$$ $red$Empty basic block$$\n", i);
2379
   }
2380

2381
   printf("\n");
2382
   fflush(stdout);
2383

2384
   active_block = old_block;
2385
}
2386
LCOV_EXCL_STOP
2387

2388
bool vtype_eq(vcode_type_t a, vcode_type_t b)
33,050,075✔
2389
{
2390
   assert(active_unit != NULL);
33,601,940✔
2391

2392
   if (a == b)
33,601,940✔
2393
      return true;
2394
   else {
2395
      const vtype_t *at = vcode_type_data(a);
30,964,205✔
2396
      const vtype_t *bt = vcode_type_data(b);
30,964,205✔
2397

2398
      if (at->kind != bt->kind)
30,964,205✔
2399
         return false;
2400

2401
      switch (at->kind) {
13,425,474✔
2402
      case VCODE_TYPE_INT:
11,329,352✔
2403
         return (at->low == bt->low) && (at->high == bt->high);
21,274,209✔
2404
      case VCODE_TYPE_REAL:
979,001✔
2405
         return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
1,906,282✔
2406
      case VCODE_TYPE_CARRAY:
73,872✔
2407
         return at->size == bt->size && vtype_eq(at->elem, bt->elem);
80,655✔
2408
      case VCODE_TYPE_UARRAY:
89,686✔
2409
         return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
111,650✔
2410
      case VCODE_TYPE_POINTER:
458,822✔
2411
      case VCODE_TYPE_ACCESS:
2412
         return vtype_eq(at->pointed, bt->pointed);
458,822✔
2413
      case VCODE_TYPE_OFFSET:
2414
      case VCODE_TYPE_OPAQUE:
2415
      case VCODE_TYPE_DEBUG_LOCUS:
2416
      case VCODE_TYPE_TRIGGER:
2417
      case VCODE_TYPE_CONVERSION:
2418
         return true;
2419
      case VCODE_TYPE_RESOLUTION:
93,043✔
2420
      case VCODE_TYPE_CLOSURE:
2421
      case VCODE_TYPE_SIGNAL:
2422
      case VCODE_TYPE_FILE:
2423
         return vtype_eq(at->base, bt->base);
93,043✔
2424
      case VCODE_TYPE_RECORD:
65,728✔
2425
      case VCODE_TYPE_CONTEXT:
2426
         return at->name == bt->name;
65,728✔
2427
      }
2428

2429
      return false;
×
2430
   }
2431
}
2432

2433
void vcode_dump(void)
×
2434
{
2435
   vcode_dump_with_mark(-1, NULL, NULL);
×
2436
}
×
2437

2438
static vcode_type_t vtype_new(vtype_t *new)
2,549,563✔
2439
{
2440
   int index = active_unit->types.count - 1;
2,549,563✔
2441
   vcode_type_t type = MAKE_HANDLE(active_unit->depth, index);
2,549,563✔
2442

2443
   for (int i = 0; i < index; i++) {
30,664,896✔
2444
      vcode_type_t this = MAKE_HANDLE(active_unit->depth, i);
30,126,485✔
2445
      if (vtype_eq(this, type)) {
30,126,485✔
2446
         active_unit->types.count--;
2,011,152✔
2447
         return this;
2,011,152✔
2448
      }
2449
   }
2450

2451
   return type;
2452
}
2453

2454
vcode_type_t vtype_int(int64_t low, int64_t high)
1,672,523✔
2455
{
2456
   assert(active_unit != NULL);
1,672,523✔
2457

2458
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,672,523✔
2459
   n->kind = VCODE_TYPE_INT;
1,672,523✔
2460
   n->low  = low;
1,672,523✔
2461
   n->high = high;
1,672,523✔
2462

2463
   switch (bits_for_range(low, high)) {
1,672,523✔
2464
   case 64:
129,345✔
2465
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
129,345✔
2466
      break;
129,345✔
2467
   case 32:
509,826✔
2468
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
509,826✔
2469
      break;
509,826✔
2470
   case 16:
3,524✔
2471
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
3,524✔
2472
      break;
3,524✔
2473
   case 8:
445,500✔
2474
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
445,500✔
2475
      break;
445,500✔
2476
   case 1:
584,327✔
2477
      n->repr = VCODE_REPR_U1;
584,327✔
2478
      break;
584,327✔
2479
   case 0:
1✔
2480
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2481
      break;
1✔
2482
   default:
×
2483
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
2484
   }
2485

2486
   return vtype_new(n);
1,672,523✔
2487
}
2488

2489
vcode_type_t vtype_bool(void)
293,508✔
2490
{
2491
   return vtype_int(0, 1);
293,508✔
2492
}
2493

2494
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
37,174✔
2495
{
2496
   assert(active_unit != NULL);
37,174✔
2497

2498
   const vtype_kind_t ekind = vtype_kind(elem);
37,174✔
2499
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
37,174✔
2500
                "array types may not be nested");
2501

2502
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
37,174✔
2503
   memset(n, '\0', sizeof(vtype_t));
37,174✔
2504
   n->kind   = VCODE_TYPE_CARRAY;
37,174✔
2505
   n->elem   = elem;
37,174✔
2506
   n->bounds = bounds;
37,174✔
2507
   n->size   = MAX(size, 0);
37,174✔
2508

2509
   return vtype_new(n);
37,174✔
2510
}
2511

2512
vcode_type_t vtype_find_named_record(ident_t name)
38,165✔
2513
{
2514
   assert(active_unit != NULL);
38,165✔
2515

2516
   for (int i = 0; i < active_unit->types.count; i++) {
490,541✔
2517
      vtype_t *other = &(active_unit->types.items[i]);
479,004✔
2518
      if (other->kind == VCODE_TYPE_RECORD && other->name == name)
479,004✔
2519
         return MAKE_HANDLE(active_unit->depth, i);
26,628✔
2520
   }
2521

2522
   return VCODE_INVALID_TYPE;
2523
}
2524

2525
vcode_type_t vtype_named_record(ident_t name, const vcode_type_t *field_types,
11,537✔
2526
                                int nfields)
2527
{
2528
   assert(active_unit != NULL);
11,537✔
2529

2530
   vtype_t *data = NULL;
11,537✔
2531
   vcode_type_t handle = vtype_find_named_record(name);
11,537✔
2532
   if (handle == VCODE_INVALID_TYPE) {
11,537✔
2533
      data = vtype_array_alloc(&(active_unit->types));
5,778✔
2534
      memset(data, '\0', sizeof(vtype_t));
5,778✔
2535
      data->kind = VCODE_TYPE_RECORD;
5,778✔
2536
      data->name = name;
5,778✔
2537

2538
      handle = vtype_new(data);
5,778✔
2539
   }
2540
   else {
2541
      data = vcode_type_data(handle);
5,759✔
2542
      VCODE_ASSERT(data->fields.count == 0,
5,759✔
2543
                    "record type %s already defined", istr(name));
2544
   }
2545

2546
   vcode_type_array_resize(&(data->fields), 0, VCODE_INVALID_TYPE);
11,537✔
2547
   for (int i = 0; i < nfields; i++)
30,787✔
2548
      vcode_type_array_add(&(data->fields), field_types[i]);
19,250✔
2549

2550
   return handle;
11,537✔
2551
}
2552

2553
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
84,470✔
2554
{
2555
   assert(active_unit != NULL);
84,470✔
2556

2557
   const vtype_kind_t ekind = vtype_kind(elem);
84,470✔
2558
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
84,470✔
2559
                "array types may not be nested");
2560

2561
   VCODE_ASSERT(ndim > 0, "uarray must have at least one dimension");
84,470✔
2562

2563
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
84,470✔
2564
   memset(n, '\0', sizeof(vtype_t));
84,470✔
2565
   n->kind   = VCODE_TYPE_UARRAY;
84,470✔
2566
   n->elem   = elem;
84,470✔
2567
   n->bounds = bounds;
84,470✔
2568
   n->dims   = ndim;
84,470✔
2569

2570
   return vtype_new(n);
84,470✔
2571
}
2572

2573
vcode_type_t vtype_pointer(vcode_type_t to)
188,855✔
2574
{
2575
   assert(active_unit != NULL);
188,855✔
2576

2577
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
188,855✔
2578
   n->kind    = VCODE_TYPE_POINTER;
188,855✔
2579
   n->pointed = to;
188,855✔
2580

2581
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
188,855✔
2582
                "cannot get pointer to carray type");
2583

2584
   return vtype_new(n);
188,855✔
2585
}
2586

2587
vcode_type_t vtype_access(vcode_type_t to)
4,934✔
2588
{
2589
   assert(active_unit != NULL);
4,934✔
2590

2591
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
4,934✔
2592
   n->kind    = VCODE_TYPE_ACCESS;
4,934✔
2593
   n->pointed = to;
4,934✔
2594

2595
   return vtype_new(n);
4,934✔
2596
}
2597

2598
vcode_type_t vtype_signal(vcode_type_t base)
38,788✔
2599
{
2600
   assert(active_unit != NULL);
38,788✔
2601

2602
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
38,788✔
2603
   n->kind = VCODE_TYPE_SIGNAL;
38,788✔
2604
   n->base = base;
38,788✔
2605

2606
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
38,788✔
2607

2608
   return vtype_new(n);
38,788✔
2609
}
2610

2611
vcode_type_t vtype_resolution(vcode_type_t base)
963✔
2612
{
2613
   assert(active_unit != NULL);
963✔
2614

2615
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
963✔
2616
   n->kind = VCODE_TYPE_RESOLUTION;
963✔
2617
   n->base = base;
963✔
2618

2619
   return vtype_new(n);
963✔
2620
}
2621

2622
vcode_type_t vtype_closure(vcode_type_t result)
1,335✔
2623
{
2624
   assert(active_unit != NULL);
1,335✔
2625

2626
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,335✔
2627
   n->kind = VCODE_TYPE_CLOSURE;
1,335✔
2628
   n->base = result;
1,335✔
2629

2630
   return vtype_new(n);
1,335✔
2631
}
2632

2633
vcode_type_t vtype_context(ident_t name)
52,347✔
2634
{
2635
   assert(active_unit != NULL);
52,347✔
2636
   assert(name != NULL);
52,347✔
2637

2638
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
52,347✔
2639
   n->kind = VCODE_TYPE_CONTEXT;
52,347✔
2640
   n->name = name;
52,347✔
2641

2642
   return vtype_new(n);
52,347✔
2643
}
2644

2645
vcode_type_t vtype_file(vcode_type_t base)
618✔
2646
{
2647
   assert(active_unit != NULL);
618✔
2648

2649
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
618✔
2650
   n->kind = VCODE_TYPE_FILE;
618✔
2651
   n->base = base;
618✔
2652

2653
   return vtype_new(n);
618✔
2654
}
2655

2656
vcode_type_t vtype_offset(void)
268,226✔
2657
{
2658
   assert(active_unit != NULL);
268,226✔
2659

2660
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
268,226✔
2661
   n->kind = VCODE_TYPE_OFFSET;
268,226✔
2662
   n->low  = INT64_MIN;
268,226✔
2663
   n->high = INT64_MAX;
268,226✔
2664
   n->repr = VCODE_REPR_I64;
268,226✔
2665

2666
   return vtype_new(n);
268,226✔
2667
}
2668

2669
vcode_type_t vtype_time(void)
17,438✔
2670
{
2671
   return vtype_int(INT64_MIN, INT64_MAX);
17,438✔
2672
}
2673

2674
vcode_type_t vtype_char(void)
9,309✔
2675
{
2676
   return vtype_int(0, 255);
9,309✔
2677
}
2678

2679
vcode_type_t vtype_opaque(void)
1,475✔
2680
{
2681
   assert(active_unit != NULL);
1,475✔
2682

2683
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,475✔
2684
   n->kind = VCODE_TYPE_OPAQUE;
1,475✔
2685

2686
   return vtype_new(n);
1,475✔
2687
}
2688

2689
vcode_type_t vtype_debug_locus(void)
110,378✔
2690
{
2691
   assert(active_unit != NULL);
110,378✔
2692

2693
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
110,378✔
2694
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
110,378✔
2695

2696
   return vtype_new(n);
110,378✔
2697
}
2698

2699
vcode_type_t vtype_trigger(void)
386✔
2700
{
2701
   assert(active_unit != NULL);
386✔
2702

2703
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
386✔
2704
   n->kind = VCODE_TYPE_TRIGGER;
386✔
2705

2706
   return vtype_new(n);
386✔
2707
}
2708

2709
vcode_type_t vtype_conversion(void)
576✔
2710
{
2711
   assert(active_unit != NULL);
576✔
2712

2713
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
576✔
2714
   n->kind = VCODE_TYPE_CONVERSION;
576✔
2715

2716
   return vtype_new(n);
576✔
2717
}
2718

2719
vcode_type_t vtype_real(double low, double high)
80,737✔
2720
{
2721
   assert(active_unit != NULL);
80,737✔
2722

2723
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
80,737✔
2724
   n->kind  = VCODE_TYPE_REAL;
80,737✔
2725
   n->rlow  = low;
80,737✔
2726
   n->rhigh = high;
80,737✔
2727

2728
   return vtype_new(n);
80,737✔
2729
}
2730

2731
vtype_kind_t vtype_kind(vcode_type_t type)
4,078,716✔
2732
{
2733
   vtype_t *vt = vcode_type_data(type);
4,078,716✔
2734
   return vt->kind;
4,078,716✔
2735
}
2736

2737
vtype_repr_t vtype_repr(vcode_type_t type)
40,774✔
2738
{
2739
   vtype_t *vt = vcode_type_data(type);
40,774✔
2740
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
40,774✔
2741
   return vt->repr;
40,774✔
2742
}
2743

2744
vcode_type_t vtype_elem(vcode_type_t type)
119,357✔
2745
{
2746
   vtype_t *vt = vcode_type_data(type);
119,357✔
2747
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
119,357✔
2748
   return vt->elem;
119,357✔
2749
}
2750

2751
vcode_type_t vtype_base(vcode_type_t type)
42,280✔
2752
{
2753
   vtype_t *vt = vcode_type_data(type);
42,280✔
2754
   assert(vt->kind == VCODE_TYPE_SIGNAL || vt->kind == VCODE_TYPE_FILE
42,280✔
2755
          || vt->kind == VCODE_TYPE_RESOLUTION
2756
          || vt->kind == VCODE_TYPE_CLOSURE);
2757
   return vt->base;
42,280✔
2758
}
2759

2760
vcode_type_t vtype_bounds(vcode_type_t type)
12,812✔
2761
{
2762
   vtype_t *vt = vcode_type_data(type);
12,812✔
2763
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
12,812✔
2764
   return vt->bounds;
12,812✔
2765
}
2766

2767
unsigned vtype_dims(vcode_type_t type)
48,243✔
2768
{
2769
   vtype_t *vt = vcode_type_data(type);
48,243✔
2770
   assert(vt->kind == VCODE_TYPE_UARRAY);
48,243✔
2771
   return vt->dims;
48,243✔
2772
}
2773

2774
unsigned vtype_size(vcode_type_t type)
37,681✔
2775
{
2776
   vtype_t *vt = vcode_type_data(type);
37,681✔
2777
   assert(vt->kind == VCODE_TYPE_CARRAY);
37,681✔
2778
   return vt->size;
37,681✔
2779
}
2780

2781
int vtype_fields(vcode_type_t type)
8,006✔
2782
{
2783
   vtype_t *vt = vcode_type_data(type);
8,006✔
2784
   assert(vt->kind == VCODE_TYPE_RECORD);
8,006✔
2785
   return vt->fields.count;
8,006✔
2786
}
2787

2788
vcode_type_t vtype_field(vcode_type_t type, int field)
30,526✔
2789
{
2790
   vtype_t *vt = vcode_type_data(type);
30,526✔
2791
   assert(vt->kind == VCODE_TYPE_RECORD);
30,526✔
2792
   return vcode_type_array_nth(&(vt->fields), field);
30,526✔
2793
}
2794

2795
ident_t vtype_name(vcode_type_t type)
19,885✔
2796
{
2797
   vtype_t *vt = vcode_type_data(type);
19,885✔
2798
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
19,885✔
2799
   return vt->name;
19,885✔
2800
}
2801

2802
vcode_type_t vtype_pointed(vcode_type_t type)
313,400✔
2803
{
2804
   vtype_t *vt = vcode_type_data(type);
313,400✔
2805
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
313,400✔
2806
   return vt->pointed;
313,400✔
2807
}
2808

2809
int64_t vtype_low(vcode_type_t type)
134,438✔
2810
{
2811
   vtype_t *vt = vcode_type_data(type);
134,438✔
2812
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
134,438✔
2813
   return vt->low;
134,438✔
2814
}
2815

2816
int64_t vtype_high(vcode_type_t type)
132,299✔
2817
{
2818
   vtype_t *vt = vcode_type_data(type);
132,299✔
2819
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
132,299✔
2820
   return vt->high;
132,299✔
2821
}
2822

2823
static bool vtype_is_pointer(vcode_type_t type, vtype_kind_t to)
462✔
2824
{
2825
   return vtype_kind(type) == VCODE_TYPE_POINTER
462✔
2826
      && vtype_kind(vtype_pointed(type)) == to;
462✔
2827
}
2828

2829
bool vtype_is_scalar(vcode_type_t type)
405,952✔
2830
{
2831
   const vtype_kind_t kind = vtype_kind(type);
405,952✔
2832
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
405,952✔
2833
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
162,032✔
2834
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2835
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2836
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER;
405,952✔
2837
}
2838

2839
bool vtype_is_composite(vcode_type_t type)
23,226✔
2840
{
2841
   const vtype_kind_t kind = vtype_kind(type);
23,226✔
2842
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
23,226✔
2843
}
2844

2845
bool vtype_is_signal(vcode_type_t type)
171,120✔
2846
{
2847
   vtype_t *vt = vcode_type_data(type);
302,223✔
2848
   switch (vt->kind) {
302,223✔
2849
   case VCODE_TYPE_SIGNAL:
2850
      return true;
2851
   case VCODE_TYPE_POINTER:
71,996✔
2852
      return vtype_is_signal(vt->pointed);
71,996✔
2853
   case VCODE_TYPE_RECORD:
2854
      for (int i = 0; i < vt->fields.count; i++) {
36,734✔
2855
         if (vtype_is_signal(vt->fields.items[i]))
28,705✔
2856
            return true;
2857
      }
2858
      return false;
2859
   case VCODE_TYPE_UARRAY:
59,107✔
2860
   case VCODE_TYPE_CARRAY:
2861
      return vtype_is_signal(vt->elem);
59,107✔
2862
   default:
134,762✔
2863
      return false;
134,762✔
2864
   }
2865
}
2866

UNCOV
2867
int vtype_repr_bits(vtype_repr_t repr)
×
2868
{
UNCOV
2869
   switch (repr) {
×
2870
   case VCODE_REPR_U1: return 1;
2871
   case VCODE_REPR_U8: case VCODE_REPR_I8: return 8;
2872
   case VCODE_REPR_U16: case VCODE_REPR_I16: return 16;
2873
   case VCODE_REPR_U32: case VCODE_REPR_I32: return 32;
2874
   case VCODE_REPR_U64: case VCODE_REPR_I64: return 64;
2875
   default: return -1;
2876
   }
2877
}
2878

UNCOV
2879
bool vtype_repr_signed(vtype_repr_t repr)
×
2880
{
UNCOV
2881
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
×
UNCOV
2882
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
×
2883
}
2884

2885
static int64_t vtype_repr_low(vtype_repr_t repr)
8,734✔
2886
{
2887
   switch (repr) {
8,734✔
2888
   case VCODE_REPR_U1:
2889
   case VCODE_REPR_U8:
2890
   case VCODE_REPR_U16:
2891
   case VCODE_REPR_U32:
2892
   case VCODE_REPR_U64: return 0;
2893
   case VCODE_REPR_I8:  return INT8_MIN;
2894
   case VCODE_REPR_I16: return INT16_MIN;
2895
   case VCODE_REPR_I32: return INT32_MIN;
2896
   case VCODE_REPR_I64: return INT64_MIN;
2897
   default:             return 0;
2898
   }
2899
}
2900

2901
static uint64_t vtype_repr_high(vtype_repr_t repr)
8,734✔
2902
{
2903
   switch (repr) {
8,734✔
2904
   case VCODE_REPR_U1:  return 1;
2905
   case VCODE_REPR_U8:  return UINT8_MAX;
2906
   case VCODE_REPR_U16: return UINT16_MAX;
2907
   case VCODE_REPR_U32: return UINT32_MAX;
2908
   case VCODE_REPR_U64: return UINT64_MAX;
2909
   case VCODE_REPR_I8:  return INT8_MAX;
2910
   case VCODE_REPR_I16: return INT16_MAX;
2911
   case VCODE_REPR_I32: return INT32_MAX;
2912
   case VCODE_REPR_I64: return INT64_MAX;
2913
   default:             return 0;
2914
   }
2915
}
2916

2917
static bool vtype_clamp_to_repr(vtype_repr_t repr, int64_t *low, int64_t *high)
8,734✔
2918
{
2919
   int64_t clamp_low = vtype_repr_low(repr);
8,734✔
2920
   uint64_t clamp_high = vtype_repr_high(repr);
8,734✔
2921

2922
   if (*low >= clamp_low && *high <= clamp_high)
8,734✔
2923
      return true;
2924
   else {
2925
      *low = MAX(clamp_low, *low);
4,643✔
2926
      *high = MIN(clamp_high, *high);
4,643✔
2927
      return false;
4,643✔
2928
   }
2929
}
2930

2931
int vcode_count_params(void)
11,273✔
2932
{
2933
   assert(active_unit != NULL);
11,273✔
2934
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
11,273✔
2935
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2936
          || active_unit->kind == VCODE_UNIT_PROPERTY
2937
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2938

2939
   return active_unit->params.count;
11,273✔
2940
}
2941

2942
vcode_type_t vcode_param_type(int param)
29,317✔
2943
{
2944
   assert(active_unit != NULL);
29,317✔
2945
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
29,317✔
2946
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2947
          || active_unit->kind == VCODE_UNIT_PROPERTY
2948
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2949
   assert(param < active_unit->params.count);
29,317✔
2950

2951
   return active_unit->params.items[param].type;
29,317✔
2952
}
2953

2954
ident_t vcode_param_name(int param)
29,317✔
2955
{
2956
   assert(active_unit != NULL);
29,317✔
2957
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
29,317✔
2958
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2959
          || active_unit->kind == VCODE_UNIT_PROPERTY
2960
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2961
   assert(param < active_unit->params.count);
29,317✔
2962

2963
   return active_unit->params.items[param].name;
29,317✔
2964
}
2965

2966
vcode_reg_t vcode_param_reg(int param)
29,337✔
2967
{
2968
   assert(active_unit != NULL);
29,337✔
2969
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
29,337✔
2970
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2971
          || active_unit->kind == VCODE_UNIT_PROPERTY
2972
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2973
   assert(param < active_unit->params.count);
29,337✔
2974

2975
   return active_unit->params.items[param].reg;
29,337✔
2976
}
2977

2978
vcode_block_t emit_block(void)
139,266✔
2979
{
2980
   assert(active_unit != NULL);
139,266✔
2981

2982
   vcode_block_t bnum = active_unit->blocks.count;
139,266✔
2983

2984
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
139,266✔
2985
   memset(bptr, '\0', sizeof(block_t));
139,266✔
2986

2987
   if (active_block != VCODE_INVALID_BLOCK)
139,266✔
2988
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
94,492✔
2989
   else
2990
      bptr->last_loc = LOC_INVALID;
44,774✔
2991

2992
   return bnum;
139,266✔
2993
}
2994

2995
void vcode_select_unit(vcode_unit_t unit)
178,961✔
2996
{
2997
   active_unit  = unit;
178,961✔
2998
   active_block = VCODE_INVALID_BLOCK;
178,961✔
2999
}
178,961✔
3000

3001
void vcode_select_block(vcode_block_t block)
390,753✔
3002
{
3003
   assert(active_unit != NULL);
390,753✔
3004
   active_block = block;
390,753✔
3005
}
390,753✔
3006

3007
vcode_block_t vcode_active_block(void)
628✔
3008
{
3009
   assert(active_unit != NULL);
628✔
3010
   assert(active_block != -1);
628✔
3011
   return active_block;
628✔
3012
}
3013

3014
const loc_t *vcode_last_loc(void)
658,674✔
3015
{
3016
   return &(vcode_block_data()->last_loc);
658,674✔
3017
}
3018

3019
vcode_unit_t vcode_active_unit(void)
873✔
3020
{
3021
   assert(active_unit != NULL);
873✔
3022
   return active_unit;
873✔
3023
}
3024

3025
ident_t vcode_unit_name(vcode_unit_t vu)
188,641✔
3026
{
3027
   assert(vu != NULL);
188,641✔
3028
   return vu->name;
188,641✔
3029
}
3030

3031
bool vcode_unit_has_undefined(vcode_unit_t vu)
12,372✔
3032
{
3033
   assert(vu != NULL);
12,372✔
3034
   return !!(vu->flags & UNIT_UNDEFINED);
12,372✔
3035
}
3036

3037
bool vcode_unit_has_escaping_tlab(vcode_unit_t vu)
4,725✔
3038
{
3039
   return !!(vu->flags & UNIT_ESCAPING_TLAB);
4,725✔
3040
}
3041

3042
int vcode_unit_depth(vcode_unit_t vu)
×
3043
{
3044
   assert(vu != NULL);
×
3045
   return vu->depth;
×
3046
}
3047

3048
void vcode_set_result(vcode_type_t type)
22,151✔
3049
{
3050
   assert(active_unit != NULL);
22,151✔
3051
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
22,151✔
3052
          || active_unit->kind == VCODE_UNIT_THUNK);
3053

3054
   active_unit->result = type;
22,151✔
3055
}
22,151✔
3056

3057
vcode_type_t vcode_unit_result(vcode_unit_t vu)
21,935✔
3058
{
3059
   assert(vu != NULL);
21,935✔
3060
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
21,935✔
3061
   return vu->result;
21,935✔
3062
}
3063

3064
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
163,189✔
3065
{
3066
   assert(vu != NULL);
163,189✔
3067
   return vu->kind;
163,189✔
3068
}
3069

3070
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
124,667✔
3071
{
3072
   assert(vu != NULL);
124,667✔
3073
   return vu->context;
124,667✔
3074
}
3075

3076
object_t *vcode_unit_object(vcode_unit_t vu)
77,826✔
3077
{
3078
   assert(vu != NULL);
77,826✔
3079
   return vu->object;
77,826✔
3080
}
3081

3082
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
57,155✔
3083
{
3084
   int hops = 0;
57,155✔
3085
   for (; (unit = unit->context); hops++)
146,783✔
3086
      ;
3087
   return hops;
57,155✔
3088
}
3089

3090
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
27,999✔
3091
{
3092
   assert(context->kind != VCODE_UNIT_THUNK);
27,999✔
3093

3094
   child->next = NULL;
27,999✔
3095
   if (context->children == NULL)
27,999✔
3096
      context->children = child;
11,357✔
3097
   else {
3098
      vcode_unit_t it;
3099
      for (it = context->children; it->next != NULL; it = it->next)
755,420✔
3100
         ;
3101
      it->next = child;
16,642✔
3102
   }
3103
}
27,999✔
3104

3105
vcode_unit_t emit_function(ident_t name, object_t *obj, vcode_unit_t context)
11,221✔
3106
{
3107
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
11,221✔
3108
   vu->kind     = VCODE_UNIT_FUNCTION;
11,221✔
3109
   vu->name     = name;
11,221✔
3110
   vu->context  = context;
11,221✔
3111
   vu->result   = VCODE_INVALID_TYPE;
11,221✔
3112
   vu->depth    = vcode_unit_calc_depth(vu);
11,221✔
3113
   vu->object   = obj;
11,221✔
3114

3115
   vcode_add_child(context, vu);
11,221✔
3116

3117
   vcode_select_unit(vu);
11,221✔
3118
   vcode_select_block(emit_block());
11,221✔
3119
   emit_debug_info(&(obj->loc));
11,221✔
3120

3121
   return vu;
11,221✔
3122
}
3123

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

3134
   vcode_add_child(context, vu);
254✔
3135

3136
   vcode_select_unit(vu);
254✔
3137
   vcode_select_block(emit_block());
254✔
3138
   emit_debug_info(&(obj->loc));
254✔
3139

3140
   return vu;
254✔
3141
}
3142

3143
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
9,236✔
3144
{
3145
   assert(context->kind == VCODE_UNIT_INSTANCE
9,236✔
3146
          || context->kind == VCODE_UNIT_SHAPE);
3147

3148
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
9,236✔
3149
   vu->kind     = VCODE_UNIT_PROCESS;
9,236✔
3150
   vu->name     = name;
9,236✔
3151
   vu->context  = context;
9,236✔
3152
   vu->depth    = vcode_unit_calc_depth(vu);
9,236✔
3153
   vu->result   = VCODE_INVALID_TYPE;
9,236✔
3154
   vu->object   = obj;
9,236✔
3155

3156
   vcode_add_child(context, vu);
9,236✔
3157

3158
   vcode_select_unit(vu);
9,236✔
3159
   vcode_select_block(emit_block());
9,236✔
3160
   emit_debug_info(&(obj->loc));
9,236✔
3161

3162
   return vu;
9,236✔
3163
}
3164

3165
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
9,398✔
3166
{
3167
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
9,398✔
3168

3169
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
9,398✔
3170
   vu->kind     = VCODE_UNIT_INSTANCE;
9,398✔
3171
   vu->name     = name;
9,398✔
3172
   vu->context  = context;
9,398✔
3173
   vu->depth    = vcode_unit_calc_depth(vu);
9,398✔
3174
   vu->result   = VCODE_INVALID_TYPE;
9,398✔
3175
   vu->object   = obj;
9,398✔
3176

3177
   if (context != NULL)
9,398✔
3178
      vcode_add_child(context, vu);
5,804✔
3179

3180
   vcode_select_unit(vu);
9,398✔
3181
   vcode_select_block(emit_block());
9,398✔
3182
   emit_debug_info(&(obj->loc));
9,398✔
3183

3184
   return vu;
9,398✔
3185
}
3186

3187
vcode_unit_t emit_shape(ident_t name, object_t *obj, vcode_unit_t context)
89✔
3188
{
3189
   assert(context == NULL || context->kind == VCODE_UNIT_SHAPE);
89✔
3190

3191
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
89✔
3192
   vu->kind     = VCODE_UNIT_SHAPE;
89✔
3193
   vu->name     = name;
89✔
3194
   vu->context  = context;
89✔
3195
   vu->depth    = vcode_unit_calc_depth(vu);
89✔
3196
   vu->result   = VCODE_INVALID_TYPE;
89✔
3197
   vu->object   = obj;
89✔
3198

3199
   if (context != NULL)
89✔
3200
      vcode_add_child(context, vu);
×
3201

3202
   vcode_select_unit(vu);
89✔
3203
   vcode_select_block(emit_block());
89✔
3204
   emit_debug_info(&(obj->loc));
89✔
3205

3206
   return vu;
89✔
3207
}
3208

3209
vcode_unit_t emit_package(ident_t name, object_t *obj, vcode_unit_t context)
1,810✔
3210
{
3211
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
1,810✔
3212
   vu->kind     = VCODE_UNIT_PACKAGE;
1,810✔
3213
   vu->name     = name;
1,810✔
3214
   vu->context  = context;
1,810✔
3215
   vu->depth    = vcode_unit_calc_depth(vu);
1,810✔
3216
   vu->result   = VCODE_INVALID_TYPE;
1,810✔
3217
   vu->object   = obj;
1,810✔
3218

3219
   if (context != NULL)
1,810✔
3220
      vcode_add_child(context, vu);
183✔
3221

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

3226
   return vu;
1,810✔
3227
}
3228

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

3239
   if (context != NULL)
175✔
3240
      vcode_add_child(context, vu);
175✔
3241

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

3246
   return vu;
175✔
3247
}
3248

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

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

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

3266
   return vu;
210✔
3267
}
3268

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

3280
   if (context != NULL)
12,381✔
3281
      vcode_add_child(context, vu);
916✔
3282

3283
   vcode_select_unit(vu);
12,381✔
3284
   vcode_select_block(emit_block());
12,381✔
3285

3286
   return vu;
12,381✔
3287
}
3288

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

3299
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
14,117✔
3300
   vcode_add_arg(op, value);
14,117✔
3301
   vcode_add_arg(op, severity);
14,117✔
3302
   vcode_add_arg(op, message);
14,117✔
3303
   vcode_add_arg(op, length);
14,117✔
3304
   vcode_add_arg(op, locus);
14,117✔
3305

3306
   if (hint_left != VCODE_INVALID_REG) {
14,117✔
3307
      vcode_add_arg(op, hint_left);
5,802✔
3308
      vcode_add_arg(op, hint_right);
5,802✔
3309

3310
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
5,802✔
3311
                   "left hint must be scalar");
3312
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
5,802✔
3313
                   "right hint must be scalar");
3314
   }
3315

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

3327
void emit_report(vcode_reg_t message, vcode_reg_t length, vcode_reg_t severity,
2,282✔
3328
                 vcode_reg_t locus)
3329
{
3330
   op_t *op = vcode_add_op(VCODE_OP_REPORT);
2,282✔
3331
   vcode_add_arg(op, severity);
2,282✔
3332
   vcode_add_arg(op, message);
2,282✔
3333
   vcode_add_arg(op, length);
2,282✔
3334
   vcode_add_arg(op, locus);
2,282✔
3335

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

3344
vcode_reg_t emit_cmp(vcode_cmp_t cmp, vcode_reg_t lhs, vcode_reg_t rhs)
38,722✔
3345
{
3346
   if (lhs == rhs) {
38,722✔
3347
      if (cmp == VCODE_CMP_EQ)
931✔
3348
         return emit_const(vtype_bool(), 1);
924✔
3349
      else if (cmp == VCODE_CMP_NEQ)
7✔
3350
         return emit_const(vtype_bool(), 0);
×
3351
      else if (cmp == VCODE_CMP_LEQ || cmp == VCODE_CMP_GEQ)
7✔
3352
         return emit_const(vtype_bool(), 1);
×
3353
      else if (cmp == VCODE_CMP_LT || cmp == VCODE_CMP_GT)
7✔
3354
         return emit_const(vtype_bool(), 0);
7✔
3355
   }
3356

3357
   int64_t lconst, rconst;
37,791✔
3358
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)) {
37,791✔
3359
      switch (cmp) {
515✔
3360
      case VCODE_CMP_EQ:
307✔
3361
         return emit_const(vtype_bool(), lconst == rconst);
307✔
3362
      case VCODE_CMP_NEQ:
3✔
3363
         return emit_const(vtype_bool(), lconst != rconst);
3✔
3364
      case VCODE_CMP_LT:
3✔
3365
         return emit_const(vtype_bool(), lconst < rconst);
3✔
3366
      case VCODE_CMP_GT:
202✔
3367
         return emit_const(vtype_bool(), lconst > rconst);
202✔
3368
      case VCODE_CMP_LEQ:
×
3369
         return emit_const(vtype_bool(), lconst <= rconst);
×
3370
      case VCODE_CMP_GEQ:
×
3371
         return emit_const(vtype_bool(), lconst >= rconst);
×
3372
      default:
×
3373
         fatal_trace("cannot fold comparison %d", cmp);
3374
      }
3375
   }
3376

3377
   // Reuse any previous operation in this block with the same arguments
3378
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
661,946✔
3379
      if (other->args.count == 2 && other->args.items[0] == lhs
27,518✔
3380
          && other->args.items[1] == rhs && other->cmp == cmp)
1,179✔
3381
         return other->result;
196✔
3382
   }
3383

3384
   op_t *op = vcode_add_op(VCODE_OP_CMP);
37,080✔
3385
   vcode_add_arg(op, lhs);
37,080✔
3386
   vcode_add_arg(op, rhs);
37,080✔
3387
   op->cmp    = cmp;
37,080✔
3388
   op->result = vcode_add_reg(vtype_bool());
37,080✔
3389

3390
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
37,080✔
3391
                "arguments to cmp are not the same type");
3392

3393
   return op->result;
3394
}
3395

3396
vcode_reg_t emit_fcall(ident_t func, vcode_type_t type, vcode_type_t bounds,
36,487✔
3397
                       const vcode_reg_t *args, int nargs)
3398
{
3399
   op_t *o = vcode_add_op(VCODE_OP_FCALL);
36,487✔
3400
   o->func = func;
36,487✔
3401
   o->type = type;
36,487✔
3402
   for (int i = 0; i < nargs; i++)
142,981✔
3403
      vcode_add_arg(o, args[i]);
106,494✔
3404

3405
   for (int i = 0; i < nargs; i++)
142,981✔
3406
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
106,494✔
3407
                   "invalid argument to function");
3408

3409
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
36,487✔
3410
                "first argument to VHDL function must be context pointer");
3411

3412
   if (type == VCODE_INVALID_TYPE)
36,487✔
3413
      return (o->result = VCODE_INVALID_REG);
5,007✔
3414
   else {
3415
      o->result = vcode_add_reg(type);
31,480✔
3416

3417
      reg_t *rr = vcode_reg_data(o->result);
31,480✔
3418
      rr->bounds = bounds;
31,480✔
3419

3420
      return o->result;
31,480✔
3421
   }
3422
}
3423

3424
void emit_pcall(ident_t func, const vcode_reg_t *args, int nargs,
880✔
3425
                vcode_block_t resume_bb)
3426
{
3427
   op_t *o = vcode_add_op(VCODE_OP_PCALL);
880✔
3428
   o->func = func;
880✔
3429
   for (int i = 0; i < nargs; i++)
3,121✔
3430
      vcode_add_arg(o, args[i]);
2,241✔
3431

3432
   vcode_block_array_add(&(o->targets), resume_bb);
880✔
3433

3434
   for (int i = 0; i < nargs; i++)
3,121✔
3435
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
2,241✔
3436
                   "invalid argument to procedure");
3437

3438
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
880✔
3439
                "first argument to VHDL procedure must be context pointer");
3440
}
880✔
3441

3442
vcode_reg_t emit_syscall(ident_t func, vcode_type_t type, vcode_type_t bounds,
423✔
3443
                         vcode_reg_t locus, const vcode_reg_t *args, int nargs)
3444
{
3445
   op_t *o = vcode_add_op(VCODE_OP_SYSCALL);
423✔
3446
   o->func = func;
423✔
3447
   o->type = type;
423✔
3448
   vcode_add_arg(o, locus);
423✔
3449
   for (int i = 0; i < nargs; i++)
498✔
3450
      vcode_add_arg(o, args[i]);
75✔
3451

3452
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
423✔
3453
                "locus argument to syscall must be a debug locus");
3454

3455
   for (int i = 0; i < nargs; i++)
498✔
3456
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG, "invalid argument to syscall");
75✔
3457

3458
   if (type == VCODE_INVALID_TYPE)
423✔
3459
      return (o->result = VCODE_INVALID_REG);
384✔
3460
   else {
3461
      o->result = vcode_add_reg(type);
39✔
3462

3463
      reg_t *rr = vcode_reg_data(o->result);
39✔
3464
      rr->bounds = bounds;
39✔
3465

3466
      return o->result;
39✔
3467
   }
3468
}
3469

3470
vcode_reg_t emit_alloc(vcode_type_t type, vcode_type_t bounds,
7,391✔
3471
                       vcode_reg_t count)
3472
{
3473
   op_t *op = vcode_add_op(VCODE_OP_ALLOC);
7,391✔
3474
   op->type    = type;
7,391✔
3475
   op->result  = vcode_add_reg(vtype_pointer(type));
7,391✔
3476
   vcode_add_arg(op, count);
7,391✔
3477

3478
   const vtype_kind_t tkind = vtype_kind(type);
7,391✔
3479
   VCODE_ASSERT(tkind != VCODE_TYPE_CARRAY && tkind != VCODE_TYPE_UARRAY,
7,391✔
3480
                "alloca element type cannot be array");
3481
   VCODE_ASSERT(count != VCODE_INVALID_REG,
7,391✔
3482
                "alloca must have valid count argument");
3483

3484
   reg_t *r = vcode_reg_data(op->result);
7,391✔
3485
   r->bounds = bounds;
7,391✔
3486

3487
   return op->result;
7,391✔
3488
}
3489

3490
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
987,704✔
3491
{
3492
   // Reuse any previous constant in this block with the same type and value
3493
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
20,853,903✔
3494
      if (other->value == value && vtype_eq(type, other->type))
7,717,200✔
3495
         return other->result;
588,398✔
3496
   }
3497

3498
   op_t *op = vcode_add_op(VCODE_OP_CONST);
399,306✔
3499
   op->value  = value;
399,306✔
3500
   op->type   = type;
399,306✔
3501
   op->result = vcode_add_reg(type);
399,306✔
3502

3503
   vtype_kind_t type_kind = vtype_kind(type);
399,306✔
3504
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
399,306✔
3505
                "constant must have integer or offset type");
3506

3507
   reg_t *r = vcode_reg_data(op->result);
399,306✔
3508
   r->bounds = vtype_int(value, value);
399,306✔
3509

3510
   return op->result;
399,306✔
3511
}
3512

3513
vcode_reg_t emit_const_real(vcode_type_t type, double value)
39,783✔
3514
{
3515
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REAL) {
1,491,750✔
3516
      if (other->real == value && other->type == type)
932,911✔
3517
         return other->result;
13,222✔
3518
   }
3519

3520
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
26,561✔
3521
   op->real   = value;
26,561✔
3522
   op->type   = type;
26,561✔
3523
   op->result = vcode_add_reg(op->type);
26,561✔
3524

3525
   reg_t *r = vcode_reg_data(op->result);
26,561✔
3526
   r->bounds = vtype_real(value, value);
26,561✔
3527

3528
   return op->result;
26,561✔
3529
}
3530

3531
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
27,570✔
3532
{
3533
   vtype_kind_t kind = vtype_kind(type);
27,570✔
3534

3535
   // Reuse any previous operation in this block with the same arguments
3536
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
1,160,449✔
3537
      if (other->args.count != num)
117,035✔
3538
         continue;
69,787✔
3539
      else if (!vtype_eq(vcode_reg_type(other->result), type))
47,248✔
3540
         continue;
646✔
3541

3542
      bool match = true;
3543
      for (int i = 0; match && i < num; i++) {
295,211✔
3544
         if (other->args.items[i] != values[i])
248,609✔
3545
            match = false;
40,522✔
3546
      }
3547

3548
      if (match) return other->result;
46,602✔
3549
   }
3550

3551
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
21,490✔
3552
   op->result = vcode_add_reg(type);
21,490✔
3553

3554
   for (int i = 0; i < num; i++)
1,186,866✔
3555
      vcode_add_arg(op, values[i]);
1,165,376✔
3556

3557
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
21,490✔
3558
                "constant array must have constrained array type");
3559
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
21,490✔
3560
                vtype_size(type), num);
3561

3562
#ifdef DEBUG
3563
   vcode_type_t elem = vtype_elem(type);
21,490✔
3564
   for (int i = 0; i < num; i++) {
1,186,866✔
3565
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
1,165,376✔
3566
                   "wrong element type for item %d", i);
3567
      vcode_assert_const(values[i], "array");
1,165,376✔
3568
   }
3569
#endif
3570

3571
   reg_t *r = vcode_reg_data(op->result);
21,490✔
3572
   r->bounds = vtype_elem(type);
21,490✔
3573

3574
   return op->result;
21,490✔
3575
}
3576

3577
vcode_reg_t emit_const_rep(vcode_type_t type, vcode_reg_t value, int rep)
619✔
3578
{
3579
   // Reuse any previous operation in this block with the same arguments
3580
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REP) {
9,162✔
3581
      if (other->args.items[0] == value && other->value == rep)
972✔
3582
         return other->result;
264✔
3583
   }
3584

3585
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
355✔
3586
   op->value = rep;
355✔
3587
   vcode_add_arg(op, value);
355✔
3588

3589
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
355✔
3590
                "constant array must have constrained array type");
3591

3592
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
355✔
3593

3594
   op->result = vcode_add_reg(type);
355✔
3595

3596
   reg_t *r = vcode_reg_data(op->result);
355✔
3597
   r->bounds = vtype_bounds(type);
355✔
3598

3599
   return op->result;
355✔
3600
}
3601

3602
vcode_reg_t emit_const_record(vcode_type_t type, vcode_reg_t *values, int num)
2,723✔
3603
{
3604
   // Reuse any previous constant in this block with the same type and value
3605
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_RECORD) {
39,168✔
3606
      if (other->args.count == num && vtype_eq(type, other->type)) {
1,634✔
3607
         bool same_regs = true;
3608
         for (int i = 0; same_regs && i < num; i++)
2,465✔
3609
            same_regs = other->args.items[i] == values[i];
1,475✔
3610

3611
         if (same_regs)
990✔
3612
            return other->result;
226✔
3613
      }
3614
   }
3615

3616
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
2,497✔
3617
   op->type   = type;
2,497✔
3618
   op->result = vcode_add_reg(type);
2,497✔
3619

3620
   for (int i = 0; i < num; i++)
8,767✔
3621
      vcode_add_arg(op, values[i]);
6,270✔
3622

3623
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
2,497✔
3624
                "constant record must have record type");
3625

3626
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
2,497✔
3627
                vtype_fields(type), num);
3628

3629
#ifdef DEBUG
3630
   for (int i = 0; i < num; i++) {
8,767✔
3631
      VCODE_ASSERT(vtype_eq(vtype_field(type, i), vcode_reg_type(values[i])),
6,270✔
3632
                   "wrong type for field %d", i);
3633
      vcode_assert_const(values[i], "record");
6,270✔
3634
   }
3635
#endif
3636

3637
   return op->result;
2,497✔
3638
}
3639

3640
vcode_reg_t emit_address_of(vcode_reg_t value)
29,337✔
3641
{
3642
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
1,225,570✔
3643
      if (other->args.items[0] == value)
118,259✔
3644
         return other->result;
6,111✔
3645
   }
3646

3647
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
23,226✔
3648
   vcode_add_arg(op, value);
23,226✔
3649

3650
   vcode_type_t type = vcode_reg_type(value);
23,226✔
3651
   VCODE_ASSERT(vtype_is_composite(type),
23,226✔
3652
                "address of argument must be record or array");
3653

3654
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
23,226✔
3655
      vcode_type_t elem = vtype_elem(type);
21,276✔
3656
      op->result = vcode_add_reg(vtype_pointer(elem));
21,276✔
3657

3658
      reg_t *rr = vcode_reg_data(op->result);
21,276✔
3659
      rr->bounds = elem;
21,276✔
3660

3661
      return op->result;
21,276✔
3662
   }
3663
   else
3664
      return (op->result = vcode_add_reg(vtype_pointer(type)));
1,950✔
3665
}
3666

3667
void emit_wait(vcode_block_t target, vcode_reg_t time)
13,687✔
3668
{
3669
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
13,687✔
3670
   vcode_add_target(op, target);
13,687✔
3671
   vcode_add_arg(op, time);
13,687✔
3672

3673
   VCODE_ASSERT(time == VCODE_INVALID_REG
13,687✔
3674
                || vcode_reg_kind(time) == VCODE_TYPE_INT,
3675
                "wait time must have integer type");
3676
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_PROCEDURE
13,687✔
3677
                || active_unit->kind == VCODE_UNIT_PROCESS,
3678
                "wait only allowed in process or procedure");
3679
}
13,687✔
3680

3681
void emit_jump(vcode_block_t target)
35,833✔
3682
{
3683
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
35,833✔
3684
   vcode_add_target(op, target);
35,833✔
3685

3686
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
35,833✔
3687
}
35,833✔
3688

3689
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
49,066✔
3690
                     vcode_var_flags_t flags)
3691
{
3692
   assert(active_unit != NULL);
49,066✔
3693

3694
   vcode_var_t var = active_unit->vars.count;
49,066✔
3695
   var_t *v = var_array_alloc(&(active_unit->vars));
49,066✔
3696
   memset(v, '\0', sizeof(var_t));
49,066✔
3697
   v->type     = type;
49,066✔
3698
   v->bounds   = bounds;
49,066✔
3699
   v->name     = name;
49,066✔
3700
   v->flags    = flags;
49,066✔
3701

3702
   return var;
49,066✔
3703
}
3704

3705
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
31,756✔
3706
{
3707
   assert(active_unit != NULL);
31,756✔
3708

3709
   param_t *p = param_array_alloc(&(active_unit->params));
31,756✔
3710
   memset(p, '\0', sizeof(param_t));
31,756✔
3711
   p->type   = type;
31,756✔
3712
   p->bounds = bounds;
31,756✔
3713
   p->name   = name;
31,756✔
3714
   p->reg    = vcode_add_reg(type);
31,756✔
3715

3716
   reg_t *rr = vcode_reg_data(p->reg);
31,756✔
3717
   rr->bounds = bounds;
31,756✔
3718

3719
   return p->reg;
31,756✔
3720
}
3721

3722
vcode_reg_t emit_load(vcode_var_t var)
52,137✔
3723
{
3724
   // Try scanning backwards through the block for another load or store to
3725
   // this variable
3726
   enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER;
52,137✔
3727
   vcode_reg_t fold = VCODE_INVALID_REG;
52,137✔
3728
   VCODE_FOR_EACH_OP(other) {
728,072✔
3729
      switch (state) {
690,271✔
3730
      case EAGER:
228,679✔
3731
         if (other->kind == VCODE_OP_LOAD && other->address == var)
228,679✔
3732
            return other->result;
3,041✔
3733
         else if (other->kind == VCODE_OP_STORE && other->address == var)
225,638✔
3734
            return other->args.items[0];
11,295✔
3735
         else if (other->kind == VCODE_OP_FCALL
214,343✔
3736
                  || other->kind == VCODE_OP_PCALL
214,343✔
3737
                  || other->kind == VCODE_OP_FILE_READ
3738
                  || other->kind == VCODE_OP_FILE_OPEN
3739
                  || other->kind == VCODE_OP_STORE_INDIRECT
3740
                  || other->kind == VCODE_OP_DEALLOCATE)
3741
            state = CONSERVATIVE;   // May write to variable
8,867✔
3742
         break;
3743

3744
      case CONSERVATIVE:
437,045✔
3745
         if (other->kind == VCODE_OP_LOAD && other->address == var
437,045✔
3746
             && fold == VCODE_INVALID_REG)
4,222✔
3747
            fold = other->result;
3,375✔
3748
         else if (other->kind == VCODE_OP_STORE && other->address == var
433,670✔
3749
                  && fold == VCODE_INVALID_REG)
2,579✔
3750
            fold = other->args.items[0];
2,442✔
3751
         else if (other->kind == VCODE_OP_INDEX && other->address == var)
431,228✔
3752
            state = UNSAFE;
3753
         else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0)
430,234✔
3754
            state = UNSAFE;   // Nested call captures variables
80✔
3755
         break;
3756

3757
      case UNSAFE:
3758
         break;
3759
      }
3760
   }
3761

3762
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
37,801✔
3763
      return fold;
3764

3765
   var_t *v = vcode_var_data(var);
32,331✔
3766

3767
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
32,331✔
3768
   op->address = var;
32,331✔
3769
   op->result  = vcode_add_reg(v->type);
32,331✔
3770

3771
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot load non-scalar type");
32,331✔
3772

3773
   reg_t *r = vcode_reg_data(op->result);
32,331✔
3774
   r->bounds = v->bounds;
32,331✔
3775

3776
   return op->result;
32,331✔
3777
}
3778

3779
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
95,438✔
3780
{
3781
   VCODE_FOR_EACH_OP(other) {
1,093,501✔
3782
      if (other->kind == VCODE_OP_LOAD_INDIRECT
1,026,142✔
3783
          && other->args.items[0] == reg) {
160,447✔
3784
         return other->result;
7,234✔
3785
      }
3786
      else if (other->kind == VCODE_OP_FCALL
1,018,908✔
3787
               || other->kind == VCODE_OP_PCALL
1,018,908✔
3788
               || other->kind == VCODE_OP_STORE
3789
               || other->kind == VCODE_OP_STORE_INDIRECT
3790
               || other->kind == VCODE_OP_MEMSET
3791
               || other->kind == VCODE_OP_COPY
3792
               || other->kind == VCODE_OP_FILE_READ)
3793
         break;   // May write to this pointer
3794
   }
3795

3796
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
88,204✔
3797
   vcode_add_arg(op, reg);
88,204✔
3798

3799
   vcode_type_t rtype = vcode_reg_type(reg);
88,204✔
3800

3801
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
88,204✔
3802
                "load indirect with non-pointer argument");
3803

3804
   vcode_type_t deref = vtype_pointed(rtype);
88,204✔
3805
   op->result = vcode_add_reg(deref);
88,204✔
3806

3807
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
88,204✔
3808

3809
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
88,204✔
3810

3811
   return op->result;
88,204✔
3812
}
3813

3814
void emit_store(vcode_reg_t reg, vcode_var_t var)
59,122✔
3815
{
3816
   // Any previous store to this variable in this block is dead
3817
   VCODE_FOR_EACH_OP(other) {
1,127,390✔
3818
      if (other->kind == VCODE_OP_STORE && other->address == var) {
1,080,172✔
3819
         other->kind = VCODE_OP_COMMENT;
273✔
3820
         other->comment =
546✔
3821
            xasprintf("Dead store to %s", istr(vcode_var_name(var)));
273✔
3822
         vcode_reg_array_resize(&(other->args), 0, VCODE_INVALID_REG);
273✔
3823
      }
3824
      else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL)
1,079,899✔
3825
         break;   // Needs to get variable for display
3826
      else if ((other->kind == VCODE_OP_INDEX || other->kind == VCODE_OP_LOAD)
1,073,909✔
3827
               && other->address == var)
25,169✔
3828
         break;   // Previous value may be used
3829
   }
3830

3831
   var_t *v = vcode_var_data(var);
59,122✔
3832
   reg_t *r = vcode_reg_data(reg);
59,122✔
3833

3834
   op_t *op = vcode_add_op(VCODE_OP_STORE);
59,122✔
3835
   vcode_add_arg(op, reg);
59,122✔
3836
   op->address = var;
59,122✔
3837

3838
   VCODE_ASSERT(vtype_eq(v->type, r->type),
59,122✔
3839
                "variable and stored value do not have same type");
3840
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
59,122✔
3841
}
59,122✔
3842

3843
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
13,853✔
3844
{
3845
   reg_t *p = vcode_reg_data(ptr);
13,853✔
3846
   reg_t *r = vcode_reg_data(reg);
13,853✔
3847

3848
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
13,853✔
3849
   vcode_add_arg(op, reg);
13,853✔
3850
   vcode_add_arg(op, ptr);
13,853✔
3851

3852
   VCODE_ASSERT(vtype_kind(p->type) == VCODE_TYPE_POINTER,
13,853✔
3853
                "store indirect target is not a pointer");
3854
   VCODE_ASSERT(vtype_eq(vtype_pointed(p->type), r->type),
13,853✔
3855
                "pointer and stored value do not have same type");
3856
   VCODE_ASSERT(vtype_is_scalar(r->type), "cannot store non-scalar type");
13,853✔
3857
}
13,853✔
3858

3859
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
50,659✔
3860
                              vcode_reg_t locus)
3861
{
3862
   // Reuse any previous operation in this block with the same arguments
3863
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,052,793✔
3864
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
59,397✔
3865
         return other->result;
2,885✔
3866
   }
3867

3868
   op_t *op = vcode_add_op(kind);
47,774✔
3869
   vcode_add_arg(op, lhs);
47,774✔
3870
   vcode_add_arg(op, rhs);
47,774✔
3871
   if (locus != VCODE_INVALID_REG)
47,774✔
3872
      vcode_add_arg(op, locus);
4,988✔
3873

3874
   op->result = vcode_add_reg(vcode_reg_type(lhs));
47,774✔
3875

3876
   vcode_type_t lhs_type = vcode_reg_type(lhs);
47,774✔
3877
   vcode_type_t rhs_type = vcode_reg_type(rhs);
47,774✔
3878

3879
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
47,774✔
3880
                "arguments to %s are not the same type", vcode_op_string(kind));
3881

3882
   return op->result;
3883
}
3884

3885
static vcode_reg_t emit_mul_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
34,708✔
3886
                               vcode_reg_t locus)
3887
{
3888
   int64_t lconst, rconst;
34,708✔
3889
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
34,708✔
3890
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
34,708✔
3891
   if (l_is_const && r_is_const)
34,708✔
3892
      return emit_const(vcode_reg_type(lhs), lconst * rconst);
19,448✔
3893
   else if (r_is_const && rconst == 1)
15,260✔
3894
      return lhs;
3895
   else if (l_is_const && lconst == 1)
3,594✔
3896
      return rhs;
3897
   else if ((r_is_const && rconst == 0) || (l_is_const && lconst == 0))
3,095✔
3898
      return emit_const(vcode_reg_type(lhs), 0);
54✔
3899

3900
   reg_t *lhs_r = vcode_reg_data(lhs);
3,041✔
3901
   reg_t *rhs_r = vcode_reg_data(rhs);
3,041✔
3902

3903
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
3,041✔
3904
   vtype_t *br = vcode_type_data(rhs_r->bounds);
3,041✔
3905

3906
   vcode_type_t vbounds;
3,041✔
3907
   if (vcode_reg_kind(lhs) == VCODE_TYPE_REAL) {
3,041✔
3908
      const double ll = bl->rlow * br->rlow;
740✔
3909
      const double lh = bl->rlow * br->rhigh;
740✔
3910
      const double hl = bl->rhigh * br->rlow;
740✔
3911
      const double hh = bl->rhigh * br->rhigh;
740✔
3912

3913
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
1,596✔
3914
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
1,818✔
3915

3916
      vbounds = vtype_real(min, max);
740✔
3917
   }
3918
   else {
3919
      const int64_t ll = smul64(bl->low, br->low);
2,301✔
3920
      const int64_t lh = smul64(bl->low, br->high);
2,301✔
3921
      const int64_t hl = smul64(bl->high, br->low);
2,301✔
3922
      const int64_t hh = smul64(bl->high, br->high);
2,301✔
3923

3924
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
2,301✔
3925
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
2,301✔
3926

3927
      vtype_repr_t repr = vtype_repr(lhs_r->type);
2,301✔
3928
      if (op == VCODE_OP_TRAP_MUL && vtype_clamp_to_repr(repr, &min, &max)) {
2,301✔
3929
         op = VCODE_OP_MUL;   // Cannot overflow
400✔
3930
         locus = VCODE_INVALID_REG;
400✔
3931
      }
3932

3933
      vbounds = vtype_int(min, max);
2,301✔
3934
   }
3935

3936
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
3,041✔
3937

3938
   if (vbounds != VCODE_INVALID_TYPE)
3,041✔
3939
      vcode_reg_data(reg)->bounds = vbounds;
3,041✔
3940

3941
   return reg;
3942
}
3943

3944
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
33,808✔
3945
{
3946
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
33,808✔
3947
}
3948

3949
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
900✔
3950
{
3951
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
900✔
3952

3953
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
900✔
3954
                "trapping add may only be used with integer types");
3955

3956
   return result;
900✔
3957
}
3958

3959
vcode_reg_t emit_div(vcode_reg_t lhs, vcode_reg_t rhs)
1,017✔
3960
{
3961
   int64_t lconst, rconst;
1,017✔
3962
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
1,017✔
3963
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
1,017✔
3964
   if (l_is_const && r_is_const && rconst != 0)
1,017✔
3965
      return emit_const(vcode_reg_type(lhs), lconst / rconst);
30✔
3966
   else if (r_is_const && rconst == 1)
987✔
3967
      return lhs;
3968

3969
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
986✔
3970

3971
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
986✔
3972

3973
   if (bl->kind == VCODE_TYPE_INT && r_is_const && rconst != 0) {
986✔
3974
      reg_t *rr = vcode_reg_data(reg);
693✔
3975
      rr->bounds = vtype_int(bl->low / rconst, bl->high / rconst);
693✔
3976
   }
3977
   else if (bl->kind == VCODE_TYPE_REAL) {
293✔
3978
      reg_t *rr = vcode_reg_data(reg);
225✔
3979
      rr->bounds = vtype_real(-INFINITY, INFINITY);
225✔
3980
   }
3981

3982
   return reg;
3983
}
3984

3985
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
79✔
3986
{
3987
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
79✔
3988
}
3989

3990
vcode_reg_t emit_trap_exp(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
816✔
3991
{
3992
   int64_t rconst;
816✔
3993
   if (vcode_reg_const(rhs, &rconst)) {
816✔
3994
      if (rconst == 0)
707✔
3995
         return emit_const(vcode_reg_type(lhs), 1);
223✔
3996
      else if (rconst == 1)
484✔
3997
         return lhs;
3998
   }
3999

4000
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
544✔
4001

4002
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
544✔
4003
                "trapping exp may only be used with integer types");
4004

4005
   return result;
4006
}
4007

4008
vcode_reg_t emit_mod(vcode_reg_t lhs, vcode_reg_t rhs)
222✔
4009
{
4010
   int64_t lconst, rconst;
222✔
4011
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
222✔
4012
       && lconst > 0 && rconst > 0)
15✔
4013
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
3✔
4014

4015
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
219✔
4016
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
219✔
4017

4018
   if (bl->low >= 0 && br->low >= 0) {
219✔
4019
      // If both arguments are non-negative then rem is equivalent and
4020
      // cheaper to compute
4021
      vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
48✔
4022

4023
      reg_t *rr = vcode_reg_data(reg);
48✔
4024
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
48✔
4025

4026
      return reg;
48✔
4027
   }
4028
   else
4029
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
171✔
4030
}
4031

4032
vcode_reg_t emit_rem(vcode_reg_t lhs, vcode_reg_t rhs)
89✔
4033
{
4034
   int64_t lconst, rconst;
89✔
4035
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
89✔
4036
       && lconst > 0 && rconst > 0)
2✔
4037
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
×
4038

4039
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
89✔
4040

4041
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
89✔
4042
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
89✔
4043

4044
   if (bl->low >= 0 && br->low >= 0) {
89✔
4045
      reg_t *rr = vcode_reg_data(reg);
36✔
4046
      rr->bounds = vtype_int(0, br->high - 1);
36✔
4047
   }
4048

4049
   return reg;
4050
}
4051

4052
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
43,424✔
4053
                               vcode_reg_t locus)
4054
{
4055
   int64_t lconst, rconst;
43,424✔
4056
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
43,424✔
4057
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
43,424✔
4058
   if (l_is_const && r_is_const)
43,424✔
4059
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
17,406✔
4060
   else if (r_is_const && rconst == 0)
26,018✔
4061
      return lhs;
4062
   else if (l_is_const && lconst == 0)
26,012✔
4063
      return rhs;
4064

4065
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
16,148✔
4066
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
16,148✔
4067
      reg_t *lhs_r = vcode_reg_data(lhs);
15,861✔
4068
      reg_t *rhs_r = vcode_reg_data(rhs);
15,861✔
4069

4070
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
15,861✔
4071
      vtype_t *br = vcode_type_data(rhs_r->bounds);
15,861✔
4072

4073
      int64_t rbl = sadd64(bl->low, br->low);
15,861✔
4074
      int64_t rbh = sadd64(bl->high, br->high);
15,861✔
4075

4076
      vtype_repr_t repr = vtype_repr(lhs_r->type);
15,861✔
4077
      if (op == VCODE_OP_TRAP_ADD && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
15,861✔
4078
         op = VCODE_OP_ADD;   // Cannot overflow
779✔
4079
         locus = VCODE_INVALID_REG;
779✔
4080
      }
4081

4082
      vbounds = vtype_int(rbl, rbh);
15,861✔
4083
   }
4084

4085
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
16,148✔
4086

4087
   if (vbounds != VCODE_INVALID_TYPE)
16,148✔
4088
      vcode_reg_data(reg)->bounds = vbounds;
15,861✔
4089

4090
   return reg;
4091
}
4092

4093
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
40,564✔
4094
{
4095
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
40,564✔
4096
}
4097

4098
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
2,860✔
4099
{
4100
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
2,860✔
4101

4102
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
2,860✔
4103
                "trapping add may only be used with integer types");
4104

4105
   return result;
2,860✔
4106
}
4107

4108
static vcode_reg_t emit_sub_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
39,116✔
4109
                               vcode_reg_t locus)
4110
{
4111
   int64_t lconst, rconst;
39,116✔
4112
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
39,116✔
4113
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
39,116✔
4114
   if (l_is_const && r_is_const)
39,116✔
4115
      return emit_const(vcode_reg_type(lhs), lconst - rconst);
12,721✔
4116
   else if (r_is_const && rconst == 0)
26,395✔
4117
      return lhs;
4118
   else if (l_is_const && lconst == 0)
24,220✔
4119
      return emit_neg(rhs);
1,302✔
4120

4121
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
22,918✔
4122
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
22,918✔
4123
      reg_t *lhs_r = vcode_reg_data(lhs);
22,612✔
4124
      reg_t *rhs_r = vcode_reg_data(rhs);
22,612✔
4125

4126
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
22,612✔
4127
      vtype_t *br = vcode_type_data(rhs_r->bounds);
22,612✔
4128

4129
      int64_t rbl = ssub64(bl->low, br->high);
22,612✔
4130
      int64_t rbh = ssub64(bl->high, br->low);
22,612✔
4131

4132
      vtype_repr_t repr = vtype_repr(lhs_r->type);
22,612✔
4133
      if (op == VCODE_OP_TRAP_SUB && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
22,612✔
4134
         op = VCODE_OP_SUB;   // Cannot overflow
2,912✔
4135
         locus = VCODE_INVALID_REG;
2,912✔
4136
      }
4137

4138
      vbounds = vtype_int(rbl, rbh);
22,612✔
4139
   }
4140

4141
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
22,918✔
4142

4143
   if (vbounds != VCODE_INVALID_TYPE)
22,918✔
4144
      vcode_reg_data(reg)->bounds = vbounds;
22,612✔
4145

4146
   return reg;
4147
}
4148

4149
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
33,384✔
4150
{
4151
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
33,384✔
4152
}
4153

4154
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
5,732✔
4155
{
4156
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
5,732✔
4157

4158
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
5,732✔
4159
                "trapping sub may only be used with integer types");
4160

4161
   return result;
5,732✔
4162
}
4163

4164
static void vcode_calculate_var_index_type(op_t *op, var_t *var)
62,373✔
4165
{
4166
   switch (vtype_kind(var->type)) {
62,373✔
4167
   case VCODE_TYPE_CARRAY:
12,378✔
4168
      op->type = vtype_pointer(vtype_elem(var->type));
12,378✔
4169
      op->result = vcode_add_reg(op->type);
12,378✔
4170
      vcode_reg_data(op->result)->bounds = vtype_bounds(var->type);
12,378✔
4171
      break;
12,378✔
4172

4173
   case VCODE_TYPE_RECORD:
6,437✔
4174
      op->type = vtype_pointer(var->type);
6,437✔
4175
      op->result = vcode_add_reg(op->type);
6,437✔
4176
      break;
6,437✔
4177

4178
   case VCODE_TYPE_INT:
43,558✔
4179
   case VCODE_TYPE_FILE:
4180
   case VCODE_TYPE_ACCESS:
4181
   case VCODE_TYPE_REAL:
4182
   case VCODE_TYPE_UARRAY:
4183
   case VCODE_TYPE_POINTER:
4184
   case VCODE_TYPE_SIGNAL:
4185
   case VCODE_TYPE_CONTEXT:
4186
   case VCODE_TYPE_OFFSET:
4187
   case VCODE_TYPE_TRIGGER:
4188
      op->type = vtype_pointer(var->type);
43,558✔
4189
      op->result = vcode_add_reg(op->type);
43,558✔
4190
      vcode_reg_data(op->result)->bounds = var->bounds;
43,558✔
4191
      break;
43,558✔
4192

4193
   default:
4194
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4195
                   istr(var->name));
4196
   }
4197
}
62,373✔
4198

4199
vcode_reg_t emit_index(vcode_var_t var, vcode_reg_t offset)
23,741✔
4200
{
4201
   // Try to find a previous index of this var by this offset
4202
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_INDEX) {
789,399✔
4203
      if (other->address == var
51,118✔
4204
          && ((offset == VCODE_INVALID_REG && other->args.count == 0)
7,573✔
4205
              || (offset != VCODE_INVALID_REG
×
4206
                  && other->args.items[0] == offset)))
×
4207
         return other->result;
7,573✔
4208
   }
4209

4210
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
16,168✔
4211
   op->address = var;
16,168✔
4212

4213
   if (offset != VCODE_INVALID_REG)
16,168✔
4214
      vcode_add_arg(op, offset);
×
4215

4216
   vcode_calculate_var_index_type(op, vcode_var_data(var));
16,168✔
4217

4218
   if (offset != VCODE_INVALID_REG)
16,168✔
4219
      VCODE_ASSERT(vtype_kind(vcode_reg_type(offset)) == VCODE_TYPE_OFFSET,
×
4220
                   "index offset r%d does not have offset type", offset);
4221

4222
   return op->result;
16,168✔
4223
}
4224

4225
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
206,350✔
4226
{
4227
   if (vtype_eq(vcode_reg_type(reg), type))
206,350✔
4228
      return reg;
206,350✔
4229

4230
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
77,286✔
4231
   vtype_kind_t to   = vtype_kind(type);
77,286✔
4232

4233
   const bool integral =
154,572✔
4234
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
77,286✔
4235
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
77,286✔
4236

4237
   int64_t value;
77,286✔
4238
   if (integral && vcode_reg_const(reg, &value))
77,286✔
4239
      return emit_const(type, value);
15,186✔
4240

4241
   // Try to find a previous cast of this register to this type
4242
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CAST) {
1,217,561✔
4243
      if (vtype_eq(other->type, type) && other->args.items[0] == reg)
137,321✔
4244
         return other->result;
14,392✔
4245
   }
4246

4247
   op_t *op = vcode_add_op(VCODE_OP_CAST);
47,708✔
4248
   vcode_add_arg(op, reg);
47,708✔
4249
   op->type   = type;
47,708✔
4250
   op->result = vcode_add_reg(type);
47,708✔
4251

4252
   static const vcode_type_t allowed[][2] = {
47,708✔
4253
      { VCODE_TYPE_INT,    VCODE_TYPE_OFFSET  },
4254
      { VCODE_TYPE_OFFSET, VCODE_TYPE_INT     },
4255
      { VCODE_TYPE_INT,    VCODE_TYPE_INT     },
4256
      { VCODE_TYPE_INT,    VCODE_TYPE_REAL    },
4257
      { VCODE_TYPE_REAL,   VCODE_TYPE_INT     },
4258
      { VCODE_TYPE_REAL,   VCODE_TYPE_REAL    },
4259
      { VCODE_TYPE_ACCESS, VCODE_TYPE_ACCESS  },
4260
   };
4261

4262
   if (from == VCODE_TYPE_INT && bounds == VCODE_INVALID_TYPE) {
47,708✔
4263
      reg_t *rr = vcode_reg_data(op->result);
10,260✔
4264
      rr->bounds = vcode_reg_bounds(reg);
10,260✔
4265
   }
4266
   else if (to == VCODE_TYPE_INT && bounds != VCODE_INVALID_TYPE) {
37,448✔
4267
      reg_t *rr = vcode_reg_data(op->result);
31,080✔
4268
      rr->bounds = bounds;
31,080✔
4269
   }
4270

4271
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
87,145✔
4272
      if (from == allowed[i][0] && to == allowed[i][1])
87,145✔
4273
         return op->result;
4274
   }
4275

4276
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4277
}
4278

4279
void emit_return(vcode_reg_t reg)
53,591✔
4280
{
4281
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
53,591✔
4282
   if (reg != VCODE_INVALID_REG) {
53,591✔
4283
      vcode_add_arg(op, reg);
28,875✔
4284

4285
      const vtype_kind_t rkind = vcode_reg_kind(reg);
28,875✔
4286
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
28,875✔
4287
         vcode_heap_allocate(reg);
8,082✔
4288
         active_unit->flags |= UNIT_ESCAPING_TLAB;
8,082✔
4289
      }
4290

4291
      VCODE_ASSERT(active_unit->kind == VCODE_UNIT_FUNCTION
28,875✔
4292
                   || active_unit->kind == VCODE_UNIT_THUNK
4293
                   || active_unit->kind == VCODE_UNIT_PROPERTY,
4294
                   "returning value fron non-function unit");
4295
      VCODE_ASSERT((active_unit->kind == VCODE_UNIT_PROPERTY
28,875✔
4296
                    && rkind == VCODE_TYPE_INT)
4297
                   || vtype_eq(active_unit->result, vcode_reg_type(reg))
4298
                   || (vtype_kind(active_unit->result) == VCODE_TYPE_ACCESS
4299
                       && rkind == VCODE_TYPE_ACCESS),
4300
                   "return value incorrect type");
4301
   }
4302
}
53,591✔
4303

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

4314
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
10,728✔
4315
   vcode_add_arg(op, nets);
10,728✔
4316
   vcode_add_arg(op, nnets);
10,728✔
4317
   vcode_add_arg(op, values);
10,728✔
4318
   vcode_add_arg(op, reject);
10,728✔
4319
   vcode_add_arg(op, after);
10,728✔
4320

4321
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
10,728✔
4322
                "sched_waveform target is not signal");
4323
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
10,728✔
4324
                "sched_waveform net count is not offset type");
4325
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
10,728✔
4326
                "signal cannot be values argument for sched_waveform");
4327
}
4328

4329
void emit_force(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t values)
60✔
4330
{
4331
   op_t *op = vcode_add_op(VCODE_OP_FORCE);
60✔
4332
   vcode_add_arg(op, nets);
60✔
4333
   vcode_add_arg(op, nnets);
60✔
4334
   vcode_add_arg(op, values);
60✔
4335

4336
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
60✔
4337
                "force target is not signal");
4338
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
60✔
4339
                "force net count is not offset type");
4340
}
60✔
4341

4342
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
30✔
4343
{
4344
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
30✔
4345
   vcode_add_arg(op, nets);
30✔
4346
   vcode_add_arg(op, nnets);
30✔
4347

4348
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
30✔
4349
                "release target is not signal");
4350
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
30✔
4351
                "release net count is not offset type");
4352
}
30✔
4353

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

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

4369
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
36,879✔
4370
{
4371
   int64_t tconst;
36,879✔
4372
   if (vcode_reg_const(test, &tconst)) {
36,879✔
4373
      emit_jump(!!tconst ? btrue : bfalse);
4,845✔
4374
      return;
2,861✔
4375
   }
4376

4377
   op_t *op = vcode_add_op(VCODE_OP_COND);
34,018✔
4378
   vcode_add_arg(op, test);
34,018✔
4379
   vcode_add_target(op, btrue);
34,018✔
4380
   vcode_add_target(op, bfalse);
34,018✔
4381

4382
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
34,018✔
4383
                "cond test is not a bool");
4384
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
34,018✔
4385
                "invalid cond targets");
4386
}
4387

4388
vcode_reg_t emit_neg(vcode_reg_t lhs)
7,487✔
4389
{
4390
   int64_t lconst;
7,487✔
4391
   if (vcode_reg_const(lhs, &lconst))
7,487✔
4392
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4393

4394
   op_t *op = vcode_add_op(VCODE_OP_NEG);
7,487✔
4395
   vcode_add_arg(op, lhs);
7,487✔
4396
   op->result = vcode_add_reg(vcode_reg_type(lhs));
7,487✔
4397

4398
   return op->result;
7,487✔
4399
}
4400

4401
vcode_reg_t emit_trap_neg(vcode_reg_t lhs, vcode_reg_t locus)
785✔
4402
{
4403
   int64_t lconst;
785✔
4404
   if (vcode_reg_const(lhs, &lconst) && lconst >= 0)
785✔
4405
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4406
   else if (vcode_type_data(vcode_reg_data(lhs)->bounds)->low >= 0)
785✔
4407
      return emit_neg(lhs);   // Cannot overflow
219✔
4408

4409
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
566✔
4410
   vcode_add_arg(op, lhs);
566✔
4411
   vcode_add_arg(op, locus);
566✔
4412

4413
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
566✔
4414
                "locus argument to trap neg must be a debug locus");
4415
   VCODE_ASSERT(vcode_reg_kind(lhs) == VCODE_TYPE_INT,
566✔
4416
                "trapping neg may only be used with integer types");
4417

4418
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
566✔
4419
}
4420

4421
vcode_reg_t emit_abs(vcode_reg_t lhs)
239✔
4422
{
4423
   int64_t lconst;
239✔
4424
   if (vcode_reg_const(lhs, &lconst))
239✔
4425
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4426

4427
   op_t *op = vcode_add_op(VCODE_OP_ABS);
238✔
4428
   vcode_add_arg(op, lhs);
238✔
4429
   op->result = vcode_add_reg(vcode_reg_type(lhs));
238✔
4430

4431
   return op->result;
238✔
4432
}
4433

4434
void emit_comment(const char *fmt, ...)
44,330✔
4435
{
4436
#ifndef NDEBUG
4437
   va_list ap;
44,330✔
4438
   va_start(ap, fmt);
44,330✔
4439

4440
   char *buf = xvasprintf(fmt, ap);
44,330✔
4441
   for (char *p = buf + strlen(buf) - 1;
44,330✔
4442
        p >= buf && isspace_iso88591(*p); p--)
44,330✔
4443
      *p = '\0';
×
4444

4445
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
44,330✔
4446
   va_end(ap);
44,330✔
4447
#endif
4448
}
44,330✔
4449

4450
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
18,450✔
4451
                        vcode_reg_t rfalse)
4452
{
4453
   int64_t tconst;
18,450✔
4454
   if (vcode_reg_const(test, &tconst))
18,450✔
4455
      return !!tconst ? rtrue : rfalse;
4,423✔
4456
   else if (rtrue == rfalse)
14,027✔
4457
      return rtrue;
4458

4459
   // Find a previous identical select
4460
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
301,149✔
4461
      if (other->args.items[0] == test && other->args.items[1] == rtrue
12,448✔
4462
          && other->args.items[2] == rfalse)
690✔
4463
         return other->result;
629✔
4464
   }
4465

4466
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
13,162✔
4467
   vcode_add_arg(op, test);
13,162✔
4468
   vcode_add_arg(op, rtrue);
13,162✔
4469
   vcode_add_arg(op, rfalse);
13,162✔
4470
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
13,162✔
4471

4472
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
13,162✔
4473
                "select test must have bool type");
4474
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
13,162✔
4475
                "select arguments are not the same type");
4476

4477
   return op->result;
13,162✔
4478
}
4479

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

4494
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
7,056✔
4495
{
4496
   vcode_type_t vtbool = vtype_bool();
7,056✔
4497

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

4534
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
6,635✔
4535

4536
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
6,635✔
4537
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4538
                "arguments to %s are not boolean", vcode_op_string(op));
4539

4540
   return result;
4541
}
4542

4543
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
2,136✔
4544
{
4545
   return emit_logical(VCODE_OP_OR, lhs, rhs);
2,136✔
4546
}
4547

4548
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
4,552✔
4549
{
4550
   return emit_logical(VCODE_OP_AND, lhs, rhs);
4,552✔
4551
}
4552

4553
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
80✔
4554
{
4555
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
80✔
4556
}
4557

4558
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
81✔
4559
{
4560
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
81✔
4561
}
4562

4563
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
122✔
4564
{
4565
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
122✔
4566
}
4567

4568
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
85✔
4569
{
4570
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
85✔
4571
}
4572

4573
vcode_reg_t emit_not(vcode_reg_t arg)
2,746✔
4574
{
4575
   int64_t cval;
2,746✔
4576
   if (vcode_reg_const(arg, &cval))
2,746✔
4577
      return emit_const(vtype_bool(), !cval);
27✔
4578

4579
   op_t *op = vcode_add_op(VCODE_OP_NOT);
2,719✔
4580
   vcode_add_arg(op, arg);
2,719✔
4581

4582
   vcode_type_t vtbool = vtype_bool();
2,719✔
4583
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
2,719✔
4584
                "argument to not is not boolean");
4585

4586
   return (op->result = vcode_add_reg(vtbool));
2,719✔
4587
}
4588

4589
vcode_reg_t emit_wrap(vcode_reg_t data, const vcode_dim_t *dims, int ndims)
45,918✔
4590
{
4591
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_WRAP) {
1,536,171✔
4592
      if (other->args.count == ndims*3 + 1 && other->args.items[0] == data) {
144,141✔
4593
         bool match = true;
4594
         for (int i = 0; match && i < ndims; i++) {
19,302✔
4595
            match = other->args.items[i*3 + 1] == dims[i].left
9,680✔
4596
               && other->args.items[i*3 + 2] == dims[i].right
8,210✔
4597
               && other->args.items[i*3 + 3] == dims[i].dir;
17,783✔
4598
         }
4599
         if (match)
9,622✔
4600
            return other->result;
8,045✔
4601
      }
4602
   }
4603

4604
   op_t *op = vcode_add_op(VCODE_OP_WRAP);
37,873✔
4605
   vcode_add_arg(op, data);
37,873✔
4606
   for (int i = 0; i < ndims; i++) {
76,263✔
4607
      vcode_add_arg(op, dims[i].left);
38,390✔
4608
      vcode_add_arg(op, dims[i].right);
38,390✔
4609
      vcode_add_arg(op, dims[i].dir);
38,390✔
4610
   }
4611

4612
   vcode_type_t ptr_type = vcode_reg_type(data);
37,873✔
4613
   const vtype_kind_t ptrkind = vtype_kind(ptr_type);
37,873✔
4614
   VCODE_ASSERT(ptrkind == VCODE_TYPE_POINTER || ptrkind == VCODE_TYPE_SIGNAL,
37,873✔
4615
                "wrapped data is not pointer or signal");
4616

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

4628
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
75,746✔
4629
      ? vtype_pointed(ptr_type) : ptr_type;
37,873✔
4630

4631
   op->result = vcode_add_reg(
37,873✔
4632
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4633

4634
   return op->result;
37,873✔
4635
}
4636

4637
static vcode_reg_t emit_uarray_op(vcode_op_t o, vcode_type_t rtype,
109,526✔
4638
                                  vcode_reg_t array, unsigned dim,
4639
                                  unsigned arg_index)
4640
{
4641
   // Reuse any previous operation in this block with the same arguments
4642
   VCODE_FOR_EACH_OP(other) {
1,186,832✔
4643
      if (other->kind == o && other->args.items[0] == array && other->dim == dim
1,136,376✔
4644
          && (rtype == VCODE_INVALID_TYPE
23,047✔
4645
              || vtype_eq(rtype, vcode_reg_type(other->result))))
9,697✔
4646
         return other->result;
23,047✔
4647
      else if (other->kind == VCODE_OP_WRAP && other->result == array)
1,113,329✔
4648
         return other->args.items[1 + (dim * 3) + arg_index];
36,023✔
4649
   }
4650

4651
   op_t *op = vcode_add_op(o);
50,456✔
4652
   vcode_add_arg(op, array);
50,456✔
4653
   op->dim = dim;
50,456✔
4654

4655
   vcode_type_t atype = vcode_reg_type(array);
50,456✔
4656
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
50,456✔
4657
                "cannot use %s with non-uarray type", vcode_op_string(o));
4658

4659
   vtype_t *vt = vcode_type_data(atype);
50,456✔
4660
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
50,456✔
4661

4662
   if (rtype == VCODE_INVALID_TYPE)
50,456✔
4663
      rtype = vtype_offset();
32,866✔
4664

4665
   return (op->result = vcode_add_reg(rtype));
50,456✔
4666
}
4667

4668
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
39,657✔
4669
{
4670
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
39,657✔
4671
                         array, dim, 0);
4672
}
4673

4674
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
30,531✔
4675
{
4676
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
30,531✔
4677
                         array, dim, 1);
4678
}
4679

4680
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
39,338✔
4681
{
4682
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
39,338✔
4683
                         array, dim, 2);
4684
}
4685

4686
vcode_reg_t emit_uarray_len(vcode_reg_t array, unsigned dim)
49,945✔
4687
{
4688
   VCODE_FOR_EACH_OP(other) {
523,010✔
4689
      if (other->kind == VCODE_OP_UARRAY_LEN) {
498,716✔
4690
         if (other->args.items[0] == array && other->dim == dim)
35,387✔
4691
            return other->result;
11,512✔
4692
      }
4693
      else if (other->kind == VCODE_OP_WRAP && other->result == array) {
463,329✔
4694
         VCODE_ASSERT(dim < (other->args.count - 1) / 3,
14,139✔
4695
                      "array dimension %d out of bounds", dim);
4696

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

4704
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
24,294✔
4705
   vcode_add_arg(op, array);
24,294✔
4706
   op->dim = dim;
24,294✔
4707

4708
   vcode_type_t atype = vcode_reg_type(array);
24,294✔
4709
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
24,294✔
4710
                "cannot use uarray len with non-uarray type");
4711

4712
   vtype_t *vt = vcode_type_data(atype);
24,294✔
4713
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
24,294✔
4714

4715
   return (op->result = vcode_add_reg(vtype_offset()));
24,294✔
4716
}
4717

4718
vcode_reg_t emit_unwrap(vcode_reg_t array)
38,126✔
4719
{
4720
   VCODE_FOR_EACH_OP(other) {
1,535,715✔
4721
      if (other->kind == VCODE_OP_WRAP && other->result == array)
1,508,486✔
4722
         return other->args.items[0];
9,489✔
4723
      else if (other->kind == VCODE_OP_UNWRAP && other->args.items[0] == array)
1,498,997✔
4724
         return other->result;
1,408✔
4725
   }
4726

4727
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
27,229✔
4728
   vcode_add_arg(op, array);
27,229✔
4729

4730
   vtype_t *vt = vcode_type_data(vcode_reg_type(array));
27,229✔
4731
   VCODE_ASSERT(vt->kind == VCODE_TYPE_UARRAY,
27,229✔
4732
                "unwrap can only only be used with uarray types");
4733

4734
   vcode_type_t elem = vt->elem;
27,229✔
4735

4736
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
27,229✔
4737
      ? elem : vtype_pointer(elem);
27,229✔
4738

4739
   op->result = vcode_add_reg(rtype);
27,229✔
4740

4741
   reg_t *rr = vcode_reg_data(op->result);
27,229✔
4742
   rr->bounds = elem;
27,229✔
4743

4744
   return op->result;
27,229✔
4745
}
4746

4747
vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right,
17,661✔
4748
                            vcode_reg_t dir)
4749
{
4750
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_NULL) {
549,896✔
4751
      if (other->args.items[0] == left
×
4752
          && other->args.items[1] == right
×
4753
          && other->args.items[2] == dir)
×
4754
         return other->result;
×
4755
   }
4756

4757
   int64_t dir_const;
17,661✔
4758
   if (vcode_reg_const(dir, &dir_const)) {
17,661✔
4759
      vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
12,998✔
4760
      vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
12,998✔
4761

4762
      if (dir_const == RANGE_TO && lbounds->low > rbounds->high)
12,998✔
4763
         return emit_const(vtype_bool(), 1);
50✔
4764
      else if (dir_const == RANGE_TO && lbounds->high <= rbounds->low)
12,948✔
4765
         return emit_const(vtype_bool(), 0);
6,307✔
4766
      else if (dir_const == RANGE_DOWNTO && rbounds->low > lbounds->high)
6,641✔
4767
         return emit_const(vtype_bool(), 1);
112✔
4768
      else if (dir_const == RANGE_DOWNTO && rbounds->high <= lbounds->low)
6,529✔
4769
         return emit_const(vtype_bool(), 0);
1,696✔
4770
      else if (dir_const == RANGE_TO)
4,833✔
4771
         return emit_cmp(VCODE_CMP_GT, left, right);
1,503✔
4772
      else
4773
         return emit_cmp(VCODE_CMP_GT, right, left);
3,330✔
4774
   }
4775

4776
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
4,663✔
4777
   vcode_add_arg(op, left);
4,663✔
4778
   vcode_add_arg(op, right);
4,663✔
4779
   vcode_add_arg(op, dir);
4,663✔
4780

4781
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
4,663✔
4782
                "range left and right have different types");
4783
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
4,663✔
4784
                "dir argument to range length is not int");
4785

4786
   return (op->result = vcode_add_reg(vtype_bool()));
4,663✔
4787
}
4788

4789
vcode_reg_t emit_range_length(vcode_reg_t left, vcode_reg_t right,
14,174✔
4790
                              vcode_reg_t dir)
4791
{
4792
   vcode_reg_t left_array = VCODE_INVALID_REG,
14,174✔
4793
      right_array = VCODE_INVALID_REG,
14,174✔
4794
      dir_array = VCODE_INVALID_REG;
14,174✔
4795
   int left_dim = -1, right_dim = -1, dir_dim = -1;
14,174✔
4796

4797
   VCODE_FOR_EACH_OP(other) {
297,782✔
4798
      if (other->kind == VCODE_OP_RANGE_LENGTH
287,988✔
4799
          && other->args.items[0] == left
5,881✔
4800
          && other->args.items[1] == right
4,729✔
4801
          && other->args.items[2] == dir)
4,380✔
4802
         return other->result;
4,380✔
4803
      else if (other->kind == VCODE_OP_UARRAY_LEFT && other->result == left) {
283,608✔
4804
         left_array = other->args.items[0];
332✔
4805
         left_dim = other->dim;
332✔
4806
      }
4807
      else if (other->kind == VCODE_OP_UARRAY_RIGHT && other->result == right) {
283,276✔
4808
         right_array = other->args.items[0];
332✔
4809
         right_dim = other->dim;
332✔
4810
      }
4811
      else if (other->kind == VCODE_OP_UARRAY_DIR && other->result == dir) {
282,944✔
4812
         dir_array = other->args.items[0];
1,066✔
4813
         dir_dim = other->dim;
1,066✔
4814
      }
4815
   }
4816

4817
   if (left_array != VCODE_INVALID_REG && left_array == right_array
9,794✔
4818
       && right_array == dir_array && left_dim == right_dim
332✔
4819
       && right_dim == dir_dim)
332✔
4820
      return emit_uarray_len(left_array, left_dim);
332✔
4821

4822
   int64_t lconst, rconst, dconst;
9,462✔
4823
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
9,462✔
4824
       && vcode_reg_const(right, &rconst)) {
5,299✔
4825

4826
      int64_t diff;
3,181✔
4827
      if (dconst == RANGE_TO)
3,181✔
4828
         diff = rconst - lconst;
2,861✔
4829
      else
4830
         diff = lconst - rconst;
320✔
4831

4832
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
3,181✔
4833
   }
4834

4835
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
6,281✔
4836
   vcode_add_arg(op, left);
6,281✔
4837
   vcode_add_arg(op, right);
6,281✔
4838
   vcode_add_arg(op, dir);
6,281✔
4839

4840
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
6,281✔
4841
                "range left and right have different types");
4842
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
6,281✔
4843
                "dir argument to range length is not int");
4844

4845
   return (op->result = vcode_add_reg(vtype_offset()));
6,281✔
4846
}
4847

4848
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
53,777✔
4849
{
4850
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
458,755✔
4851
      if (other->hops == hops && other->address == var)
61,973✔
4852
         return other->result;
7,572✔
4853
   }
4854

4855
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
46,205✔
4856
   op->hops    = hops;
46,205✔
4857
   op->address = var;
46,205✔
4858

4859
   VCODE_ASSERT(hops > 0, "invalid hop count");
46,205✔
4860

4861
   vcode_unit_t vu = active_unit;
46,205✔
4862
   for (int i = 0; i < hops; i++) {
103,162✔
4863
      vu = vu->context;
56,957✔
4864
      VCODE_ASSERT(vu, "hop count is greater than depth");
56,957✔
4865
   }
4866

4867
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
46,205✔
4868

4869
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
46,205✔
4870

4871
   return op->result;
46,205✔
4872
}
4873

4874
vcode_reg_t emit_init_signal(vcode_type_t type, vcode_reg_t count,
15,841✔
4875
                             vcode_reg_t size, vcode_reg_t value,
4876
                             vcode_reg_t flags, vcode_reg_t locus,
4877
                             vcode_reg_t offset)
4878
{
4879
   op_t *op = vcode_add_op(VCODE_OP_INIT_SIGNAL);
15,841✔
4880
   vcode_add_arg(op, count);
15,841✔
4881
   vcode_add_arg(op, size);
15,841✔
4882
   vcode_add_arg(op, value);
15,841✔
4883
   vcode_add_arg(op, flags);
15,841✔
4884
   vcode_add_arg(op, locus);
15,841✔
4885
   if (offset != VCODE_INVALID_REG)
15,841✔
4886
      vcode_add_arg(op, offset);
5,589✔
4887

4888
   vcode_type_t vtype = vcode_reg_type(value);
15,841✔
4889
   VCODE_ASSERT(vtype_is_scalar(type), "signal type must be scalar");
15,841✔
4890
   VCODE_ASSERT(vtype_eq(vtype, type)
15,841✔
4891
                || vtype_kind(vtype) == VCODE_TYPE_POINTER,
4892
                "init signal value type does not match signal type");
4893
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
15,841✔
4894
                "locus argument to init signal must be a debug locus");
4895
   VCODE_ASSERT(offset == VCODE_INVALID_REG
15,841✔
4896
                || vcode_reg_kind(offset) == VCODE_TYPE_POINTER,
4897
                "init signal offset argument must have pointer type");
4898

4899
   return (op->result = vcode_add_reg(vtype_signal(type)));
15,841✔
4900
}
4901

4902
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
3,323✔
4903
{
4904
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
3,323✔
4905
   vcode_add_arg(op, signal);
3,323✔
4906
   vcode_add_arg(op, resolution);
3,323✔
4907

4908
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
3,323✔
4909
                "signal argument has wrong type");
4910
   VCODE_ASSERT(vcode_reg_kind(resolution) == VCODE_TYPE_RESOLUTION,
3,323✔
4911
                "resolution wrapper argument has wrong type");
4912
}
3,323✔
4913

4914
vcode_reg_t emit_implicit_signal(vcode_type_t type, vcode_reg_t count,
75✔
4915
                                 vcode_reg_t size, vcode_reg_t locus,
4916
                                 vcode_reg_t kind, vcode_reg_t closure,
4917
                                 vcode_reg_t delay)
4918
{
4919
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_SIGNAL);
75✔
4920
   vcode_add_arg(op, count);
75✔
4921
   vcode_add_arg(op, size);
75✔
4922
   vcode_add_arg(op, locus);
75✔
4923
   vcode_add_arg(op, kind);
75✔
4924
   vcode_add_arg(op, closure);
75✔
4925
   vcode_add_arg(op, delay);
75✔
4926

4927
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
75✔
4928
                "count argument to implicit signal is not offset");
4929
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
75✔
4930
                "kind argument to implicit signal is not offset");
4931
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
75✔
4932
                "closure argument to implicit signal is not a closure");
4933
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
75✔
4934
                "locus argument to implicit signal must be a debug locus");
4935
   VCODE_ASSERT(vcode_reg_kind(delay) == VCODE_TYPE_INT,
75✔
4936
                "delay argument to implicit signal must be time");
4937

4938
   return (op->result = vcode_add_reg(vtype_signal(type)));
75✔
4939
}
4940

4941
void emit_map_signal(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
5,302✔
4942
{
4943
   op_t *op = vcode_add_op(VCODE_OP_MAP_SIGNAL);
5,302✔
4944
   vcode_add_arg(op, src);
5,302✔
4945
   vcode_add_arg(op, dst);
5,302✔
4946
   vcode_add_arg(op, count);
5,302✔
4947

4948
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
5,302✔
4949
                "src argument to map signal is not a signal");
4950
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
5,302✔
4951
                "dst argument to map signal is not a signal");
4952
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5,302✔
4953
                "count argument type to map signal is not offset");
4954
}
5,302✔
4955

4956
void emit_map_const(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
219✔
4957
{
4958
   op_t *op = vcode_add_op(VCODE_OP_MAP_CONST);
219✔
4959
   vcode_add_arg(op, src);
219✔
4960
   vcode_add_arg(op, dst);
219✔
4961
   vcode_add_arg(op, count);
219✔
4962

4963
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
219✔
4964
                "dst argument to map const is not a signal");
4965
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
219✔
4966
                "count argument type to map const is not offset");
4967
}
219✔
4968

4969
void emit_map_implicit(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
57✔
4970
{
4971
   op_t *op = vcode_add_op(VCODE_OP_MAP_IMPLICIT);
57✔
4972
   vcode_add_arg(op, src);
57✔
4973
   vcode_add_arg(op, dst);
57✔
4974
   vcode_add_arg(op, count);
57✔
4975

4976
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
57✔
4977
                "src argument to map implicit is not a signal");
4978
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
57✔
4979
                "dst argument to map implicit is not a signal");
4980
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
57✔
4981
                "count argument type to map implicit is not offset");
4982
}
57✔
4983

4984
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
9,375✔
4985
{
4986
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
114,820✔
4987
      if (other->args.items[0] == target && other->args.items[1] == count)
13,835✔
4988
         return;
4989
   }
4990

4991
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
9,351✔
4992
   vcode_add_arg(op, target);
9,351✔
4993
   vcode_add_arg(op, count);
9,351✔
4994

4995
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
9,351✔
4996
                "target argument to drive signal is not a signal");
4997
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
9,351✔
4998
                "count argument type to drive signal is not offset");
4999
}
5000

5001
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
1,209✔
5002
                          vcode_reg_t count, vcode_reg_t reject,
5003
                          vcode_reg_t after)
5004
{
5005
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
1,209✔
5006
   vcode_add_arg(op, target);
1,209✔
5007
   vcode_add_arg(op, source);
1,209✔
5008
   vcode_add_arg(op, count);
1,209✔
5009
   vcode_add_arg(op, reject);
1,209✔
5010
   vcode_add_arg(op, after);
1,209✔
5011

5012
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
1,209✔
5013
                "target argument to transfer signal is not a signal");
5014
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,209✔
5015
                "count argument type to transfer signal is not offset");
5016
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
1,209✔
5017
                "source argument to transfer signal is not a signal");
5018
}
1,209✔
5019

5020
vcode_reg_t emit_resolution_wrapper(vcode_type_t type, vcode_reg_t closure,
3,209✔
5021
                                    vcode_reg_t ileft, vcode_reg_t nlits)
5022
{
5023
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RESOLUTION_WRAPPER) {
134,016✔
5024
      if (other->args.items[0] == closure
2,249✔
5025
          && other->args.items[1] == ileft
2,246✔
5026
          && other->args.items[2] == nlits)
2,246✔
5027
         return other->result;
2,246✔
5028
   }
5029

5030
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
963✔
5031
                "first argument to resolution wrapper must be closure");
5032

5033
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
963✔
5034
   vcode_add_arg(op, closure);
963✔
5035
   vcode_add_arg(op, ileft);
963✔
5036
   vcode_add_arg(op, nlits);
963✔
5037

5038
   return (op->result = vcode_add_reg(vtype_resolution(type)));
963✔
5039
}
5040

5041
vcode_reg_t emit_closure(ident_t func, vcode_reg_t context, vcode_type_t atype,
3,581✔
5042
                         vcode_type_t rtype)
5043
{
5044
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CLOSURE) {
140,279✔
5045
      if (other->func == func && other->args.items[0] == context)
2,687✔
5046
         return other->result;
2,246✔
5047
   }
5048

5049
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
1,335✔
5050
   vcode_add_arg(op, context);
1,335✔
5051
   op->func = func;
1,335✔
5052
   op->type = atype;
1,335✔
5053

5054
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
1,335✔
5055
                "invalid closure context argument");
5056

5057
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
1,335✔
5058
}
5059

5060
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
30,735✔
5061
{
5062
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
46,963✔
5063
      if (other->func == name)
23,350✔
5064
         return other->result;
12,908✔
5065
   }
5066

5067
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
17,827✔
5068
   op->func = name;
17,827✔
5069
   if (context != VCODE_INVALID_REG)
17,827✔
5070
      vcode_add_arg(op, context);
183✔
5071

5072
   VCODE_ASSERT(context == VCODE_INVALID_REG
17,827✔
5073
                || vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
5074
                "invalid protected init context argument");
5075
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_INSTANCE
17,827✔
5076
                || active_unit->kind == VCODE_UNIT_PACKAGE
5077
                || active_unit->kind == VCODE_UNIT_THUNK,
5078
                "cannot use package init here");
5079
   VCODE_ASSERT(name != active_unit->name, "cyclic package init");
17,827✔
5080

5081
   return (op->result = vcode_add_reg(vtype_context(name)));
17,827✔
5082
}
5083

5084
vcode_reg_t emit_protected_init(vcode_type_t type, vcode_reg_t context,
163✔
5085
                                vcode_reg_t path_name, vcode_reg_t inst_name)
5086
{
5087
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_INIT);
163✔
5088
   vcode_add_arg(op, context);
163✔
5089
   op->func = vtype_name(type);
163✔
5090

5091
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
163✔
5092
      vcode_add_arg(op, path_name);
38✔
5093
      vcode_add_arg(op, inst_name);
38✔
5094

5095
      VCODE_ASSERT(vcode_reg_kind(path_name) == VCODE_TYPE_UARRAY,
38✔
5096
                   "path name argument must be uarray");
5097
      VCODE_ASSERT(vcode_reg_kind(inst_name) == VCODE_TYPE_UARRAY,
38✔
5098
                   "inst name argument must be uarray");
5099
   }
5100

5101
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
163✔
5102
                "protected init type must be context");
5103
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
163✔
5104
                "invalid protected init context argument");
5105

5106
   return (op->result = vcode_add_reg(type));
163✔
5107
}
5108

5109
void emit_process_init(ident_t name, vcode_reg_t locus)
112✔
5110
{
5111
   op_t *op = vcode_add_op(VCODE_OP_PROCESS_INIT);
112✔
5112
   vcode_add_arg(op, locus);
112✔
5113
   op->func = name;
112✔
5114

5115
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
112✔
5116
                "locus argument to process init must be a debug locus");
5117
}
112✔
5118

5119
void emit_protected_free(vcode_reg_t obj)
7✔
5120
{
5121
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
7✔
5122
   vcode_add_arg(op, obj);
7✔
5123

5124
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
7✔
5125
                "protected object type must be context");
5126
}
7✔
5127

5128
vcode_reg_t emit_context_upref(int hops)
15,728✔
5129
{
5130
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
108,510✔
5131
      if (other->hops == hops)
7,044✔
5132
         return other->result;
6,985✔
5133
   }
5134

5135
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
8,743✔
5136
   op->hops = hops;
8,743✔
5137

5138
   VCODE_ASSERT(hops >= 0, "invalid hop count");
8,743✔
5139

5140
   vcode_unit_t vu = active_unit;
8,743✔
5141
   for (int i = 0; i < hops; i++) {
16,756✔
5142
      vu = vu->context;
8,013✔
5143
      VCODE_ASSERT(vu, "hop count is greater than depth");
8,013✔
5144
   }
5145

5146
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
8,743✔
5147
}
5148

5149
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
652✔
5150
                                    vcode_reg_t len)
5151
{
5152
   op_t *op = vcode_add_op(opkind);
652✔
5153
   vcode_add_arg(op, nets);
652✔
5154
   vcode_add_arg(op, len);
652✔
5155

5156
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
652✔
5157
                "argument to %s is not a signal", vcode_op_string(opkind));
5158

5159
   return (op->result = vcode_add_reg(vtype_bool()));
652✔
5160
}
5161

5162
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
432✔
5163
{
5164
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
432✔
5165
}
5166

5167
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
220✔
5168
{
5169
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
220✔
5170
}
5171

5172
vcode_reg_t emit_record_ref(vcode_reg_t record, unsigned field)
41,563✔
5173
{
5174
   // Try scanning backwards through the block for another record ref
5175
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RECORD_REF) {
2,770,494✔
5176
      if (other->args.items[0] == record && other->field == field)
517,104✔
5177
         return other->result;
3,875✔
5178
   }
5179

5180
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
37,688✔
5181
   op->field = field;
37,688✔
5182
   vcode_add_arg(op, record);
37,688✔
5183

5184
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
37,688✔
5185

5186
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
37,688✔
5187
                "argument to record ref must be a pointer");
5188

5189
   vtype_t *rtype = vcode_type_data(rptype->pointed);
37,688✔
5190
   VCODE_ASSERT(rtype->kind == VCODE_TYPE_RECORD,
37,688✔
5191
                "argument must be pointer to record or record signal");
5192

5193
   VCODE_ASSERT(field < rtype->fields.count, "invalid field %d", field);
37,688✔
5194

5195
   vcode_type_t field_type  = rtype->fields.items[field];
37,688✔
5196
   vcode_type_t bounds_type = field_type;
37,688✔
5197
   vcode_type_t result_type = field_type;
37,688✔
5198

5199
   const vtype_kind_t fkind = vtype_kind(field_type);
37,688✔
5200
   if (fkind == VCODE_TYPE_CARRAY)
37,688✔
5201
      result_type = bounds_type = vtype_elem(field_type);
5,141✔
5202
   else if (fkind == VCODE_TYPE_UARRAY) {
32,547✔
5203
      bounds_type = vtype_elem(field_type);
2,718✔
5204
      result_type = field_type;
2,718✔
5205
   }
5206

5207
   op->result = vcode_add_reg(vtype_pointer(result_type));
37,688✔
5208

5209
   reg_t *rr = vcode_reg_data(op->result);
37,688✔
5210
   rr->bounds = bounds_type;
37,688✔
5211

5212
   return op->result;
37,688✔
5213
}
5214

5215
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
35,686✔
5216
{
5217
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
1,665,896✔
5218
      if (other->args.items[0] == array && other->args.items[1] == offset)
98,454✔
5219
         return other->result;
1,177✔
5220
   }
5221

5222
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
34,509✔
5223
   vcode_add_arg(op, array);
34,509✔
5224
   vcode_add_arg(op, offset);
34,509✔
5225

5226
   vcode_type_t rtype = vcode_reg_type(array);
34,509✔
5227
   VCODE_ASSERT((vtype_kind(rtype) == VCODE_TYPE_POINTER
34,509✔
5228
                 && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY)
5229
                || vtype_kind(rtype) == VCODE_TYPE_SIGNAL,
5230
                "argument to array ref must be a pointer or signal");
5231
   VCODE_ASSERT(vcode_reg_kind(offset) == VCODE_TYPE_OFFSET,
34,509✔
5232
                "array ref offset argument must have offset type");
5233

5234
   op->result = vcode_add_reg(rtype);
34,509✔
5235

5236
   reg_t *rr = vcode_reg_data(op->result);
34,509✔
5237
   rr->bounds = vcode_reg_bounds(array);
34,509✔
5238

5239
   return op->result;
34,509✔
5240
}
5241

5242
void emit_copy(vcode_reg_t dest, vcode_reg_t src, vcode_reg_t count)
21,043✔
5243
{
5244
   int64_t cconst;
21,043✔
5245
   if (count != VCODE_INVALID_REG && vcode_reg_const(count, &cconst)
21,043✔
5246
       && cconst == 0)
10,725✔
5247
      return;
4,937✔
5248
   else if (dest == src)
20,875✔
5249
      return;
5250

5251
   op_t *op = vcode_add_op(VCODE_OP_COPY);
16,106✔
5252
   vcode_add_arg(op, dest);
16,106✔
5253
   vcode_add_arg(op, src);
16,106✔
5254
   if (count != VCODE_INVALID_REG)
16,106✔
5255
      vcode_add_arg(op, count);
14,280✔
5256

5257
   vcode_type_t dtype = vcode_reg_type(dest);
16,106✔
5258
   vcode_type_t stype = vcode_reg_type(src);
16,106✔
5259

5260
   vtype_kind_t dkind = vtype_kind(dtype);
16,106✔
5261
   vtype_kind_t skind = vtype_kind(stype);
16,106✔
5262

5263
   VCODE_ASSERT(dkind == VCODE_TYPE_POINTER || dkind == VCODE_TYPE_ACCESS,
16,106✔
5264
                "destination type is not a pointer or access");
5265
   VCODE_ASSERT(skind == VCODE_TYPE_POINTER || skind == VCODE_TYPE_ACCESS,
16,106✔
5266
                "source type is not a pointer or access");
5267
   VCODE_ASSERT(vtype_eq(dtype, stype),
16,106✔
5268
                "source and destination types do not match");
5269
   VCODE_ASSERT(count == VCODE_INVALID_REG
16,106✔
5270
                || vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
5271
                "count is not offset type");
5272

5273
   op->type = vtype_pointed(dtype);
16,106✔
5274
}
5275

5276
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
5,910✔
5277
{
5278
   VCODE_FOR_EACH_OP(other) {
98,412✔
5279
      if (other->kind == VCODE_OP_CLEAR_EVENT)
92,538✔
5280
         break;
5281
      else if (other->kind == VCODE_OP_SCHED_EVENT
92,508✔
5282
               && other->args.items[0] == nets
4,765✔
5283
               && other->args.items[1] == n_elems)
9✔
5284
         return;
5285
   }
5286

5287
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
5,904✔
5288
   vcode_add_arg(op, nets);
5,904✔
5289
   vcode_add_arg(op, n_elems);
5,904✔
5290

5291
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
5,904✔
5292
                "nets argument to sched event must be signal");
5293
}
5294

5295
void emit_clear_event(vcode_reg_t nets, vcode_reg_t n_elems)
507✔
5296
{
5297
   VCODE_FOR_EACH_OP(other) {
2,340✔
5298
      if (other->kind == VCODE_OP_SCHED_EVENT)
1,833✔
5299
         break;
5300
      else if (other->kind == VCODE_OP_CLEAR_EVENT
1,833✔
5301
               && other->args.items[0] == nets
39✔
5302
               && other->args.items[1] == n_elems)
×
5303
         return;
5304
   }
5305

5306
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
507✔
5307
   vcode_add_arg(op, nets);
507✔
5308
   vcode_add_arg(op, n_elems);
507✔
5309

5310
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
507✔
5311
                "nets argument to clear event must be signal");
5312
}
5313

5314
void emit_resume(ident_t func)
880✔
5315
{
5316
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
880✔
5317
   op->func = func;
880✔
5318

5319
   block_t *b = &(active_unit->blocks.items[active_block]);
880✔
5320
   VCODE_ASSERT(b->ops.count == 1, "resume must be first op in a block");
880✔
5321
}
880✔
5322

5323
void emit_memset(vcode_reg_t ptr, vcode_reg_t value, vcode_reg_t len)
5,684✔
5324
{
5325
   int64_t lconst;
5,684✔
5326
   if (vcode_reg_const(len, &lconst) && lconst == 0)
5,684✔
5327
      return;
29✔
5328

5329
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
5,655✔
5330
   vcode_add_arg(op, ptr);
5,655✔
5331
   vcode_add_arg(op, value);
5,655✔
5332
   vcode_add_arg(op, len);
5,655✔
5333

5334
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
5,655✔
5335
                "target of memset must have pointer type");
5336
   VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(value)),
5,655✔
5337
                "value of memset must have scalar type");
5338
   VCODE_ASSERT(vtype_kind(vcode_reg_type(len)) == VCODE_TYPE_OFFSET,
5,655✔
5339
                "length of memset must have offset type");
5340
}
5341

5342
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
644✔
5343
               const vcode_block_t *blocks, int ncases)
5344
{
5345
   int64_t cval1, cval2;
644✔
5346
   bool is_const = vcode_reg_const(value, &cval1);
644✔
5347

5348
   for (int i = 0; i < ncases; i++) {
5,359✔
5349
      bool can_fold = false;
4,719✔
5350
      if (cases[i] == value)
4,719✔
5351
         can_fold = true;
5352
      else if (is_const && vcode_reg_const(cases[i], &cval2))
4,719✔
5353
         can_fold = (cval1 == cval2);
4✔
5354

5355
      if (can_fold) {
4✔
5356
         emit_jump(blocks[i]);
4✔
5357
         return;
8✔
5358
      }
5359
   }
5360

5361
   if (is_const) {
640✔
5362
      emit_jump(def);
×
5363
      return;
×
5364
   }
5365

5366
   op_t *op = vcode_add_op(VCODE_OP_CASE);
640✔
5367
   vcode_add_arg(op, value);
640✔
5368
   vcode_add_target(op, def);
640✔
5369

5370
   for (int i = 0; i < ncases; i++) {
5,355✔
5371
      vcode_add_arg(op, cases[i]);
4,715✔
5372
      vcode_add_target(op, blocks[i]);
4,715✔
5373

5374
#ifdef DEBUG
5375
      for (int j = 0; j < i; j++)
245,211✔
5376
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
240,496✔
5377
#endif
5378
   }
5379
}
5380

5381
void emit_file_open(vcode_reg_t file, vcode_reg_t name, vcode_reg_t length,
262✔
5382
                    vcode_reg_t kind, vcode_reg_t status)
5383
{
5384
   op_t *op = vcode_add_op(VCODE_OP_FILE_OPEN);
262✔
5385
   vcode_add_arg(op, file);
262✔
5386
   vcode_add_arg(op, name);
262✔
5387
   vcode_add_arg(op, length);
262✔
5388
   vcode_add_arg(op, kind);
262✔
5389
   if (status != VCODE_INVALID_REG)
262✔
5390
      vcode_add_arg(op, status);
26✔
5391

5392
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
262✔
5393
                "file open first argument must have file pointer type");
5394
}
262✔
5395

5396
void emit_file_write(vcode_reg_t file, vcode_reg_t value, vcode_reg_t length)
125✔
5397
{
5398
   op_t *op = vcode_add_op(VCODE_OP_FILE_WRITE);
125✔
5399
   vcode_add_arg(op, file);
125✔
5400
   vcode_add_arg(op, value);
125✔
5401
   if (length != VCODE_INVALID_REG)
125✔
5402
      vcode_add_arg(op, length);
68✔
5403

5404
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
125✔
5405
                "file write first argument must have file pointer type");
5406
}
125✔
5407

5408
void emit_file_read(vcode_reg_t file, vcode_reg_t ptr,
75✔
5409
                    vcode_reg_t inlen, vcode_reg_t outlen)
5410
{
5411
   op_t *op = vcode_add_op(VCODE_OP_FILE_READ);
75✔
5412
   vcode_add_arg(op, file);
75✔
5413
   vcode_add_arg(op, ptr);
75✔
5414
   if (inlen != VCODE_INVALID_REG) {
75✔
5415
      vcode_add_arg(op, inlen);
27✔
5416
      if (outlen != VCODE_INVALID_REG)
27✔
5417
         vcode_add_arg(op, outlen);
18✔
5418
   }
5419

5420
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
75✔
5421
                "file read first argument must have file pointer type");
5422
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_POINTER,
75✔
5423
                "file read pointer argument must have pointer type");
5424
   VCODE_ASSERT(outlen == VCODE_INVALID_REG
75✔
5425
                || vtype_kind(vcode_reg_type(outlen)) == VCODE_TYPE_POINTER,
5426
                "file read outlen argument must have pointer type");
5427
}
75✔
5428

5429
vcode_reg_t emit_null(vcode_type_t type)
9,450✔
5430
{
5431
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_NULL) {
219,268✔
5432
      if (vtype_eq(vcode_reg_type(other->result), type))
4,800✔
5433
         return other->result;
2,380✔
5434
   }
5435

5436
   op_t *op = vcode_add_op(VCODE_OP_NULL);
7,070✔
5437
   op->result = vcode_add_reg(type);
7,070✔
5438

5439
   vtype_kind_t kind = vtype_kind(type);
7,070✔
5440
   VCODE_ASSERT(kind == VCODE_TYPE_POINTER || kind == VCODE_TYPE_FILE
7,070✔
5441
                || kind == VCODE_TYPE_ACCESS || kind == VCODE_TYPE_CONTEXT,
5442
                "null type must be file, access, context, or pointer");
5443

5444
   return op->result;
5445
}
5446

5447
vcode_reg_t emit_new(vcode_type_t type, vcode_reg_t length)
428✔
5448
{
5449
   op_t *op = vcode_add_op(VCODE_OP_NEW);
428✔
5450
   if (length != VCODE_INVALID_REG)
428✔
5451
      vcode_add_arg(op, length);
337✔
5452

5453
   op->result = vcode_add_reg(vtype_access(type));
428✔
5454

5455
   vtype_kind_t kind = vtype_kind(type);
428✔
5456
   VCODE_ASSERT(kind == VCODE_TYPE_INT || kind == VCODE_TYPE_RECORD
428✔
5457
                || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_ACCESS
5458
                || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_CONTEXT,
5459
                "new type must be int, real, record, access, or uarray");
5460
   VCODE_ASSERT(length == VCODE_INVALID_REG
428✔
5461
                || vtype_kind(vcode_reg_type(length)) == VCODE_TYPE_OFFSET,
5462
                "new length must have offset type");
5463

5464
   return op->result;
428✔
5465
}
5466

5467
void emit_null_check(vcode_reg_t ptr, vcode_reg_t locus)
1,755✔
5468
{
5469
   VCODE_FOR_EACH_OP(other) {
104,961✔
5470
      if (other->kind == VCODE_OP_NULL_CHECK && other->args.items[0] == ptr)
103,838✔
5471
         return;
5472
      else if (other->kind == VCODE_OP_NEW && other->result == ptr)
103,461✔
5473
         return;
5474
   }
5475

5476
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
1,123✔
5477
   vcode_add_arg(op, ptr);
1,123✔
5478
   vcode_add_arg(op, locus);
1,123✔
5479

5480
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
1,123✔
5481
                "null check argument must be an access");
5482
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,123✔
5483
                "locus argument to null check must be a debug locus");
5484
}
5485

5486
void emit_deallocate(vcode_reg_t ptr)
207✔
5487
{
5488
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
207✔
5489
   vcode_add_arg(op, ptr);
207✔
5490

5491
   vcode_type_t ptype = vcode_reg_type(ptr);
207✔
5492
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
207✔
5493
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5494
                "deallocate argument must be pointer to access");
5495
}
207✔
5496

5497
vcode_reg_t emit_all(vcode_reg_t reg)
2,183✔
5498
{
5499
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
146,087✔
5500
      if (other->args.items[0] == reg)
9,251✔
5501
         return other->result;
632✔
5502
   }
5503

5504
   op_t *op = vcode_add_op(VCODE_OP_ALL);
1,551✔
5505
   vcode_add_arg(op, reg);
1,551✔
5506

5507
   vcode_type_t vtype = vcode_reg_type(reg);
1,551✔
5508

5509
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
1,551✔
5510
                "all argument must be an access");
5511

5512
   vcode_type_t pointed = vtype_pointed(vtype);
1,551✔
5513
   op->result = vcode_add_reg(vtype_pointer(pointed));
1,551✔
5514

5515
   reg_t *rr = vcode_reg_data(op->result);
1,551✔
5516
   rr->bounds = pointed;
1,551✔
5517

5518
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
1,551✔
5519
                "cannot dereference opaque type");
5520

5521
   return op->result;
5522
}
5523

5524
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
14,923✔
5525
{
5526
   block_t *b = &(active_unit->blocks.items[active_block]);
14,923✔
5527
   for (int i = b->ops.count - 1; i >= 0; i--) {
366,846✔
5528
      const op_t *other = &(b->ops.items[i]);
352,481✔
5529
      if (other->kind == kind && other->args.items[0] == sig)
352,481✔
5530
         return other->result;
558✔
5531
   }
5532

5533
   op_t *op = vcode_add_op(kind);
14,365✔
5534
   vcode_add_arg(op, sig);
14,365✔
5535

5536
   vcode_type_t stype = vcode_reg_type(sig);
14,365✔
5537
   op->type = stype;
14,365✔
5538

5539
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
14,365✔
5540
                "argument r%d to resolved is not a signal", sig);
5541

5542
   vcode_type_t rtype = vtype_base(stype);
14,365✔
5543

5544
   const vtype_kind_t rkind = vtype_kind(rtype);
14,365✔
5545
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
14,365✔
5546
      rtype = vtype_elem(rtype);
×
5547

5548
   VCODE_ASSERT(vtype_is_scalar(rtype),
14,365✔
5549
                "resolved signal base type must be scalar");
5550

5551
   op->result = vcode_add_reg(vtype_pointer(rtype));
14,365✔
5552

5553
   reg_t *rr = vcode_reg_data(op->result);
14,365✔
5554
   rr->bounds = rtype;
14,365✔
5555

5556
   return op->result;
14,365✔
5557
}
5558

5559
vcode_reg_t emit_resolved(vcode_reg_t sig, vcode_reg_t count)
14,828✔
5560
{
5561
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
14,828✔
5562
}
5563

5564
vcode_reg_t emit_last_value(vcode_reg_t sig, vcode_reg_t count)
95✔
5565
{
5566
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
95✔
5567
}
5568

5569
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
33✔
5570
{
5571
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
33✔
5572
   vcode_add_arg(op, signal);
33✔
5573
   if (len != VCODE_INVALID_REG)
33✔
5574
      vcode_add_arg(op, len);
9✔
5575

5576
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
33✔
5577
                "signal argument to last event must have signal type");
5578
   VCODE_ASSERT(len == VCODE_INVALID_REG
33✔
5579
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5580
                "length argument to last event must have offset type");
5581

5582
   return (op->result = vcode_add_reg(vtype_time()));
33✔
5583
}
5584

5585
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
36✔
5586
{
5587
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
36✔
5588
   vcode_add_arg(op, signal);
36✔
5589
   if (len != VCODE_INVALID_REG)
36✔
5590
      vcode_add_arg(op, len);
6✔
5591

5592
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5593
                "signal argument to last active must have signal type");
5594
   VCODE_ASSERT(len == VCODE_INVALID_REG
36✔
5595
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5596
                "length argument to last active must have offset type");
5597

5598
   return (op->result = vcode_add_reg(vtype_time()));
36✔
5599
}
5600

5601
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
4,202✔
5602
{
5603
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
4,202✔
5604
   vcode_add_arg(op, signal);
4,202✔
5605
   vcode_add_arg(op, locus);
4,202✔
5606

5607
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
4,202✔
5608
                "signal argument must have signal type");
5609
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
4,202✔
5610
                "locus argument must have debug locus type");
5611
}
4,202✔
5612

5613
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
36✔
5614
{
5615
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
36✔
5616
   vcode_add_arg(op, signal);
36✔
5617
   vcode_add_arg(op, len);
36✔
5618

5619
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5620
                "signal argument to last active must have signal type");
5621
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
36✔
5622
                "length argument to last active must have offset type");
5623

5624
   return (op->result = vcode_add_reg(vtype_bool()));
36✔
5625
}
5626

5627
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
140✔
5628
{
5629
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
140✔
5630
   vcode_add_arg(op, signal);
140✔
5631
   if (len != VCODE_INVALID_REG)
140✔
5632
      vcode_add_arg(op, len);
33✔
5633

5634
   vcode_type_t signal_type = vcode_reg_type(signal);
140✔
5635

5636
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
140✔
5637
                "signal argument to last active must have signal type");
5638
   VCODE_ASSERT(len == VCODE_INVALID_REG
140✔
5639
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5640
                "length argument to last active must have offset type");
5641

5642
   vcode_type_t base_type = vtype_base(signal_type);
140✔
5643
   op->result = vcode_add_reg(vtype_pointer(base_type));
140✔
5644

5645
   reg_t *rr = vcode_reg_data(op->result);
140✔
5646
   rr->bounds = base_type;
140✔
5647

5648
   return op->result;
140✔
5649
}
5650

5651
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
22,012✔
5652
                       vcode_reg_t dim)
5653
{
5654
   if (rlen == llen)
22,012✔
5655
      return;
5656

5657
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
186,530✔
5658
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
2,851✔
5659
         return;
5660
   }
5661

5662
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
6,803✔
5663
   vcode_add_arg(op, llen);
6,803✔
5664
   vcode_add_arg(op, rlen);
6,803✔
5665
   vcode_add_arg(op, locus);
6,803✔
5666
   if (dim != VCODE_INVALID_REG)
6,803✔
5667
      vcode_add_arg(op, dim);
24✔
5668

5669
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,803✔
5670
                "locus argument to length check must be a debug locus");
5671
}
5672

5673
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
816✔
5674
{
5675
   int64_t cval;
816✔
5676
   if (vcode_reg_const(exp, &cval) && cval >= 0)
816✔
5677
      return;
299✔
5678

5679
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
3,254✔
5680
      if (other->args.items[0] == exp)
12✔
5681
         return;
5682
   }
5683

5684
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
517✔
5685
   vcode_add_arg(op, exp);
517✔
5686
   vcode_add_arg(op, locus);
517✔
5687

5688
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
517✔
5689
                "exp argument to exponent check must be a integer");
5690
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
517✔
5691
                "locus argument to exponent check must be a debug locus");
5692
}
5693

5694
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
1,067✔
5695
{
5696
   int64_t cval;
1,067✔
5697
   if (vcode_reg_const(denom, &cval) && cval != 0)
1,067✔
5698
      return;
964✔
5699

5700
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
2,886✔
5701
      if (other->args.items[0] == denom)
56✔
5702
         return;
5703
   }
5704

5705
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
103✔
5706
   vcode_add_arg(op, denom);
103✔
5707
   vcode_add_arg(op, locus);
103✔
5708

5709
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
103✔
5710
                "denom argument to zero check must be a integer");
5711
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
103✔
5712
                "locus argument to zero check must be a debug locus");
5713
}
5714

5715
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
48,888✔
5716
                                   vcode_reg_t right, vcode_reg_t dir)
5717
{
5718
   int64_t dconst;
48,888✔
5719
   if (vcode_reg_const(dir, &dconst)) {
48,888✔
5720
      int64_t lconst, rconst;
39,969✔
5721
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
39,969✔
5722
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
30,059✔
5723
            || (dconst == RANGE_DOWNTO && rconst > lconst);
63,548✔
5724

5725
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
33,490✔
5726

5727
         const bool ok_static =
66,980✔
5728
            (dconst == RANGE_TO
5729
             && bounds->low >= lconst && bounds->high <= rconst)
30,059✔
5730
            || (dconst == RANGE_DOWNTO
7,899✔
5731
                && bounds->low >= rconst && bounds->high <= lconst)
3,431✔
5732
            || (!is_null && (reg == left || reg == right));
38,168✔
5733

5734
         return ok_static;
39,171✔
5735
      }
5736
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
6,479✔
5737
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
6,087✔
5738
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
6,087✔
5739

5740
         assert(lbounds->kind == VCODE_TYPE_REAL);
6,087✔
5741
         assert(rbounds->kind == VCODE_TYPE_REAL);
6,087✔
5742

5743
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
6,087✔
5744
         assert(bounds->kind == VCODE_TYPE_REAL);
6,087✔
5745

5746
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
6,087✔
5747
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
5,681✔
5748
            // Covers the complete double range so can never overflow
5749
            return true;
5750
         }
5751
      }
5752
   }
5753

5754
   return false;
5755
}
5756

5757
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
49,461✔
5758
                              vcode_reg_t left, vcode_reg_t right,
5759
                              vcode_reg_t dir, vcode_reg_t locus,
5760
                              vcode_reg_t hint)
5761
{
5762
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
2,344,769✔
5763
      if (other->args.items[0] == reg && other->args.items[1] == left
13,353✔
5764
          && other->args.items[2] == right && other->args.items[3] == dir)
579✔
5765
         return;
5766
   }
5767

5768
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
48,888✔
5769
      emit_comment("Elided bounds check for r%d", reg);
34,493✔
5770
      return;
34,493✔
5771
   }
5772

5773
   op_t *op = vcode_add_op(kind);
14,395✔
5774
   vcode_add_arg(op, reg);
14,395✔
5775
   vcode_add_arg(op, left);
14,395✔
5776
   vcode_add_arg(op, right);
14,395✔
5777
   vcode_add_arg(op, dir);
14,395✔
5778
   vcode_add_arg(op, locus);
14,395✔
5779
   vcode_add_arg(op, hint);
14,395✔
5780

5781
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
14,395✔
5782
                "locus argument to bounds check must be a debug locus");
5783
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
14,395✔
5784
                "hint argument to bounds check must be a debug locus");
5785
}
5786

5787
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
8,819✔
5788
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5789
{
5790
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
8,819✔
5791
}
8,819✔
5792

5793
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
40,642✔
5794
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5795
{
5796
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
40,642✔
5797
}
40,642✔
5798

5799
void emit_package_scope(vcode_reg_t locus)
45✔
5800
{
5801
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_SCOPE);
45✔
5802
   vcode_add_arg(op, locus);
45✔
5803

5804
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5805
                "locus argument to package scope must be a debug locus");
5806
}
45✔
5807

5808
void emit_array_scope(vcode_reg_t locus, vcode_type_t type)
632✔
5809
{
5810
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_SCOPE);
632✔
5811
   vcode_add_arg(op, locus);
632✔
5812
   op->type = type;
632✔
5813

5814
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
632✔
5815
                "locus argument to array scope must be a debug locus");
5816
}
632✔
5817

5818
void emit_record_scope(vcode_reg_t locus, vcode_type_t type)
1,596✔
5819
{
5820
   op_t *op = vcode_add_op(VCODE_OP_RECORD_SCOPE);
1,596✔
5821
   vcode_add_arg(op, locus);
1,596✔
5822
   op->type = type;
1,596✔
5823

5824
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,596✔
5825
                "locus argument to record scope must be a debug locus");
5826
}
1,596✔
5827

5828
void emit_pop_scope(void)
2,273✔
5829
{
5830
   vcode_add_op(VCODE_OP_POP_SCOPE);
2,273✔
5831
}
2,273✔
5832

5833
vcode_reg_t emit_debug_locus(object_t *obj)
120,484✔
5834
{
5835
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
6,461,945✔
5836
      if (other->object == obj)
980,607✔
5837
         return other->result;
10,152✔
5838
   }
5839

5840
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
110,332✔
5841
   op->object = obj;
110,332✔
5842

5843
   return (op->result = vcode_add_reg(vtype_debug_locus()));
110,332✔
5844
}
5845

5846
void emit_debug_out(vcode_reg_t reg)
×
5847
{
5848
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
5849
   vcode_add_arg(op, reg);
×
5850
}
×
5851

5852
void emit_cover_stmt(uint32_t tag)
1,006✔
5853
{
5854
   op_t *op = vcode_add_op(VCODE_OP_COVER_STMT);
1,006✔
5855
   op->tag = tag;
1,006✔
5856
}
1,006✔
5857

5858
void emit_cover_branch(uint32_t tag)
495✔
5859
{
5860
   op_t *op = vcode_add_op(VCODE_OP_COVER_BRANCH);
495✔
5861
   op->tag = tag;
495✔
5862
}
495✔
5863

5864
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
313✔
5865
{
5866
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
313✔
5867
   vcode_add_arg(op, signal);
313✔
5868
   op->tag = tag;
313✔
5869
}
313✔
5870

5871
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
12✔
5872
{
5873
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
12✔
5874
   vcode_add_arg(op, signal);
12✔
5875
   vcode_add_arg(op, low);
12✔
5876
   op->tag = tag;
12✔
5877
}
12✔
5878

5879
void emit_cover_expr(uint32_t tag)
856✔
5880
{
5881
   op_t *op = vcode_add_op(VCODE_OP_COVER_EXPR);
856✔
5882
   op->tag = tag;
856✔
5883
}
856✔
5884

5885
void emit_unreachable(vcode_reg_t locus)
617✔
5886
{
5887
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
617✔
5888
   if (locus != VCODE_INVALID_REG)
617✔
5889
      vcode_add_arg(op, locus);
137✔
5890
}
617✔
5891

5892
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
1,457✔
5893
{
5894
   active_unit->flags |= UNIT_UNDEFINED;
1,457✔
5895

5896
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
1,457✔
5897
   op->result = vcode_add_reg(type);
1,457✔
5898
   vcode_reg_data(op->result)->bounds = bounds;
1,457✔
5899

5900
   return op->result;
1,457✔
5901
}
5902

5903
void emit_debug_info(const loc_t *loc)
1,373,161✔
5904
{
5905
   if (!loc_invalid_p(loc))
1,373,161✔
5906
      vcode_block_data()->last_loc = *loc;
1,345,230✔
5907
}
1,373,161✔
5908

5909
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
4,174✔
5910
{
5911
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
155,819✔
5912
      if (other->args.items[0] == context && other->ident == name)
8,878✔
5913
         return other->result;
1,640✔
5914
   }
5915

5916
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
2,534✔
5917
   vcode_add_arg(op, context);
2,534✔
5918
   op->ident = name;
2,534✔
5919

5920
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
2,534✔
5921
                "first argument to link var must be context");
5922

5923
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
2,534✔
5924
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
79✔
5925
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
79✔
5926
   }
5927
   else {
5928
      op->result = vcode_add_reg(vtype_pointer(type));
2,455✔
5929
      vcode_reg_data(op->result)->bounds = type;
2,455✔
5930
   }
5931

5932
   return op->result;
2,534✔
5933
}
5934

5935
vcode_reg_t emit_link_package(ident_t name)
24,888✔
5936
{
5937
   VCODE_FOR_EACH_OP(other) {
1,119,656✔
5938
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
1,108,139✔
5939
         return other->result;
8,018✔
5940
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
1,100,121✔
5941
         return other->result;
5,353✔
5942
   }
5943

5944
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
11,517✔
5945
   op->ident = name;
11,517✔
5946

5947
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
11,517✔
5948

5949
   return (op->result = vcode_add_reg(vtype_context(name)));
11,517✔
5950
}
5951

5952
void emit_enter_state(vcode_reg_t state, vcode_reg_t strong)
768✔
5953
{
5954
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
1,836✔
5955
      if (other->args.items[0] == state)
×
5956
         return;
5957
   }
5958

5959
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
768✔
5960
   vcode_add_arg(op, state);
768✔
5961
   if (strong != VCODE_INVALID_REG)
768✔
5962
      vcode_add_arg(op, strong);
18✔
5963

5964
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
768✔
5965
                "state must have integer type");
5966
   VCODE_ASSERT(strong == VCODE_INVALID_REG
768✔
5967
                || vtype_eq(vcode_reg_type(strong), vtype_bool()),
5968
                "strong argument not is not boolean");
5969
}
5970

5971
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
45✔
5972
                               vcode_reg_t locus, vcode_reg_t bounds)
5973
{
5974
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
45✔
5975
   vcode_add_arg(op, value);
45✔
5976
   vcode_add_arg(op, context);
45✔
5977
   vcode_add_arg(op, locus);
45✔
5978
   if (bounds != VCODE_INVALID_REG)
45✔
5979
      vcode_add_arg(op, bounds);
6✔
5980

5981
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
45✔
5982
                "invalid reflect value context argument");
5983
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5984
                "locus argument to reflect value must be a debug locus");
5985

5986
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
45✔
5987
}
5988

5989
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
42✔
5990
                                 vcode_reg_t bounds)
5991
{
5992
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
42✔
5993
   vcode_add_arg(op, context);
42✔
5994
   vcode_add_arg(op, locus);
42✔
5995
   if (bounds != VCODE_INVALID_REG)
42✔
5996
      vcode_add_arg(op, bounds);
×
5997

5998
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
42✔
5999
                "invalid reflect value context argument");
6000
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
42✔
6001
                "locus argument to reflect value must be a debug locus");
6002

6003
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
42✔
6004
}
6005

6006
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
217✔
6007
                                  int nargs)
6008
{
6009
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
217✔
6010
   op->func = func;
217✔
6011

6012
   for (int i = 0; i < nargs; i++)
576✔
6013
      vcode_add_arg(op, args[i]);
359✔
6014

6015
   return (op->result = vcode_add_reg(vtype_trigger()));
217✔
6016
}
6017

6018
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
34✔
6019
{
6020
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
34✔
6021
   vcode_add_arg(op, left);
34✔
6022
   vcode_add_arg(op, right);
34✔
6023

6024
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
34✔
6025
                "or trigger left argument must be trigger");
6026
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
34✔
6027
                "or trigger right argument must be trigger");
6028

6029
   return (op->result = vcode_add_reg(vtype_trigger()));
34✔
6030
}
6031

6032
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
63✔
6033
{
6034
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
63✔
6035
   vcode_add_arg(op, left);
63✔
6036
   vcode_add_arg(op, right);
63✔
6037

6038
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
63✔
6039
                "cmp trigger left argument must be signal");
6040
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
63✔
6041
                "cmp trigger right argument must be integer");
6042

6043
   return (op->result = vcode_add_reg(vtype_trigger()));
63✔
6044
}
6045

6046
void emit_add_trigger(vcode_reg_t trigger)
365✔
6047
{
6048
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
365✔
6049
   vcode_add_arg(op, trigger);
365✔
6050

6051
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
365✔
6052
                "add trigger argument must be trigger");
6053
}
365✔
6054

6055
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
279✔
6056
{
6057
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
279✔
6058
   vcode_add_arg(op, driving);
279✔
6059
   if (effective != VCODE_INVALID_REG && effective != driving)
279✔
6060
      vcode_add_arg(op, effective);
18✔
6061

6062
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
279✔
6063
                "port conversion argument must be a closure");
6064
   VCODE_ASSERT(effective == VCODE_INVALID_REG
279✔
6065
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
6066
                "port conversion argument must be a closure");
6067

6068
   return (op->result = vcode_add_reg(vtype_conversion()));
279✔
6069
}
6070

6071
vcode_reg_t emit_bind_external(vcode_reg_t locus, ident_t scope,
200✔
6072
                               vcode_type_t type, vcode_type_t bounds)
6073
{
6074
   op_t *op = vcode_add_op(VCODE_OP_BIND_EXTERNAL);
200✔
6075
   vcode_add_arg(op, locus);
200✔
6076
   op->type  = type;
200✔
6077
   op->ident = scope;
200✔
6078

6079
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
200✔
6080
                "bind external argument must be locus");
6081

6082
   op->result = vcode_add_reg(vtype_pointer(type));
200✔
6083
   vcode_reg_data(op->result)->bounds = bounds;
200✔
6084
   return op->result;
200✔
6085
}
6086

6087
void emit_put_conversion(vcode_reg_t cf, vcode_reg_t target, vcode_reg_t count,
414✔
6088
                         vcode_reg_t values)
6089
{
6090
   op_t *op = vcode_add_op(VCODE_OP_PUT_CONVERSION);
414✔
6091
   vcode_add_arg(op, cf);
414✔
6092
   vcode_add_arg(op, target);
414✔
6093
   vcode_add_arg(op, count);
414✔
6094
   vcode_add_arg(op, values);
414✔
6095

6096
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
414✔
6097
                "put conversion target is not signal");
6098
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
414✔
6099
                "put conversion net count is not offset type");
6100
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
414✔
6101
                "signal cannot be values argument for put conversion");
6102
   VCODE_ASSERT(vcode_reg_kind(cf) == VCODE_TYPE_CONVERSION,
414✔
6103
                "cf argument to put conversion must be conversion function");
6104
}
414✔
6105

6106
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
354✔
6107
{
6108
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
354✔
6109
   vcode_add_arg(op, conv);
354✔
6110
   vcode_add_arg(op, nets);
354✔
6111
   vcode_add_arg(op, count);
354✔
6112

6113
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
354✔
6114
                "conv argument to convert must be a port conversion");
6115
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
354✔
6116
                "nets argument to convert must be a signal");
6117
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
354✔
6118
                "count argument to convert must be offset");
6119
}
354✔
6120

6121
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
396✔
6122
{
6123
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
396✔
6124
   vcode_add_arg(op, conv);
396✔
6125
   vcode_add_arg(op, nets);
396✔
6126
   vcode_add_arg(op, count);
396✔
6127

6128
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
396✔
6129
                "conv argument to convert must be a port conversion");
6130
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
396✔
6131
                "nets argument to convert must be a signal");
6132
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
396✔
6133
                "count argument to convert must be offset");
6134
}
396✔
6135

6136
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
276✔
6137
{
6138
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
276✔
6139
   vcode_add_arg(op, spec);
276✔
6140
   vcode_add_arg(op, length);
276✔
6141
   if (locus != VCODE_INVALID_REG)
276✔
6142
      vcode_add_arg(op, locus);
141✔
6143

6144
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
276✔
6145
                "spec argument to bind foreign must be a pointer");
6146
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
276✔
6147
                "length argument to bind foreign must be offset");
6148
   VCODE_ASSERT(locus == VCODE_INVALID_REG
276✔
6149
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6150
                "locus argument to bind foreign value must be a debug locus");
6151
}
276✔
6152

6153
vcode_reg_t emit_instance_name(vcode_reg_t kind)
812✔
6154
{
6155
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
812✔
6156
   vcode_add_arg(op, kind);
812✔
6157

6158
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
812✔
6159
                "kind argument to instance name must be offset");
6160

6161
   vcode_type_t vchar = vtype_char();
812✔
6162
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
812✔
6163
}
6164

6165
void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count,
177✔
6166
                         vcode_reg_t values)
6167
{
6168
   op_t *op = vcode_add_op(VCODE_OP_DEPOSIT_SIGNAL);
177✔
6169
   vcode_add_arg(op, signal);
177✔
6170
   vcode_add_arg(op, count);
177✔
6171
   vcode_add_arg(op, values);
177✔
6172

6173
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
177✔
6174
                "deposit signal target is not signal");
6175
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
177✔
6176
                "deposit signal count is not offset type");
6177
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
177✔
6178
                "signal cannot be values argument for deposit signal");
6179
}
177✔
6180

6181
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
29,797✔
6182
{
6183
   vcode_state_t state;
29,797✔
6184
   vcode_state_save(&state);
29,797✔
6185

6186
   vcode_select_unit(vu);
29,797✔
6187

6188
   const int nblocks = vcode_count_blocks();
29,797✔
6189
   for (int i = 0; i < nblocks; i++) {
139,688✔
6190
      vcode_select_block(i);
109,891✔
6191

6192
      const int nops = vcode_count_ops();
109,891✔
6193
      for (int op = 0; op < nops; op++) {
1,519,741✔
6194
         switch (vcode_get_op(op)) {
1,409,850✔
6195
         case VCODE_OP_LINK_PACKAGE:
9,589✔
6196
            (*fn)(vcode_get_ident(op), ctx);
9,589✔
6197
            break;
9,589✔
6198
         case VCODE_OP_FCALL:
52,811✔
6199
         case VCODE_OP_PCALL:
6200
         case VCODE_OP_CLOSURE:
6201
         case VCODE_OP_PROTECTED_INIT:
6202
         case VCODE_OP_PACKAGE_INIT:
6203
         case VCODE_OP_FUNCTION_TRIGGER:
6204
            (*fn)(vcode_get_func(op), ctx);
52,811✔
6205
            break;
52,811✔
6206
         default:
6207
            break;
6208
         }
6209
      }
6210
   }
6211

6212
   vcode_state_restore(&state);
29,797✔
6213
}
29,797✔
6214

6215
#ifdef DEBUG
6216
static void shape_mismatch(vcode_unit_t vu, vcode_unit_t shape,
×
6217
                           const char *fmt, ...)
6218
{
6219
   vcode_select_unit(vu);
×
6220
   vcode_dump();
×
6221

6222
   vcode_select_unit(shape);
×
6223
   vcode_dump();
×
6224

6225
   va_list ap;
×
6226
   va_start(ap, fmt);
×
6227

6228
   diag_t *d = diag_new(DIAG_FATAL, NULL);
×
6229
   diag_printf(d, "instance %s does not match shape %s", istr(vu->name),
×
6230
               istr(shape->name));
6231
   diag_vhint(d, NULL, fmt, ap);
×
6232
   diag_emit(d);
×
6233

6234
   va_end(ap);
×
6235

6236
   fatal_exit(1);
×
6237
}
6238
#endif
6239

6240
void vcode_check_shape(vcode_unit_t vu, vcode_unit_t shape)
90✔
6241
{
6242
#ifdef DEBUG
6243
   assert(shape->kind == VCODE_UNIT_SHAPE);
90✔
6244
   assert(vu->kind == VCODE_UNIT_INSTANCE);
90✔
6245

6246
   if (shape->vars.count <= vu->vars.count) {
90✔
6247
      for (int i = 0; i < shape->vars.count; i++) {
371✔
6248
         var_t *v = var_array_nth_ptr(&(vu->vars), i);
281✔
6249
         var_t *s = var_array_nth_ptr(&(shape->vars), i);
281✔
6250

6251
         if (v->name != s->name)
281✔
6252
            shape_mismatch(vu, shape, "var %d name %s != %s", i, istr(v->name),
×
6253
                           istr(s->name));
6254
         else if (v->flags != s->flags)
281✔
6255
            shape_mismatch(vu, shape, "var %d flags %x != %x", i, v->flags,
×
6256
                           s->flags);
6257
         // XXX: not possible to compare types at the moment
6258
      }
6259
   }
6260
   else
6261
      shape_mismatch(vu, shape, "shape vars %d > unit vars %d",
×
6262
                     shape->vars.count, vu->vars.count);
6263

6264
   if (shape->context != NULL)
90✔
6265
      vcode_check_shape(vu->context, shape->context);
×
6266
#endif
6267
}
90✔
6268

6269
#if VCODE_CHECK_UNIONS
6270
#define OP_USE_COUNT_U0(x)                                              \
6271
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6272
#define OP_USE_COUNT_U1(x)                                              \
6273
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6274
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6275
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6276

6277
__attribute__((constructor))
6278
static void vcode_check_unions(void)
6279
{
6280
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6281
   for (int i = 0; i < 256; i++) {
6282
      assert(OP_USE_COUNT_U0(i) <= 1);
6283
      assert(OP_USE_COUNT_U1(i) <= 1);
6284
   }
6285
}
6286
#endif  // VCODE_CHECK_UNIONS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc