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

nickg / nvc / 9727088862

29 Jun 2024 09:36PM UTC coverage: 91.568%. Remained the same
9727088862

push

github

nickg
Crash when dumping waveform with PSL enabled. Fixes #904

56815 of 62047 relevant lines covered (91.57%)

665873.68 hits per line

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

96.51
/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,111,438✔
36
DECLARE_AND_DEFINE_ARRAY(vcode_block);
366,334✔
37
DECLARE_AND_DEFINE_ARRAY(vcode_type);
250,617✔
38

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

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

103
DECLARE_AND_DEFINE_ARRAY(op);
12,249,140✔
104

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

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

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

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

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

156
DECLARE_AND_DEFINE_ARRAY(param);
30,255✔
157
DECLARE_AND_DEFINE_ARRAY(var);
364,371✔
158
DECLARE_AND_DEFINE_ARRAY(reg);
7,735,829✔
159
DECLARE_AND_DEFINE_ARRAY(block);
129,530✔
160
DECLARE_AND_DEFINE_ARRAY(vtype);
70,685,351✔
161

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

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

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

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

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

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

210
#define VCODE_CHECK_UNIONS 0
211

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

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

221
   return result;
222
}
223

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

230
   return result;
231
}
232

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

239
   return result;
240
}
241

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

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

252
   return reg;
1,241,655✔
253
}
254

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

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

267
   VCODE_ASSERT(
1,564,628✔
268
      !vcode_block_finished(),
269
      "attempt to add to already finished block %d", active_block);
270

271
   block_t *block = vcode_block_data();
1,564,628✔
272

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

279
   return op;
1,564,628✔
280
}
281

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

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

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

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

301
static op_t *vcode_find_definition(vcode_reg_t reg)
1,175,587✔
302
{
303
   for (int i = active_block; i >= 0; i--) {
1,224,753✔
304
      block_t *b = &(active_unit->blocks.items[i]);
1,221,785✔
305
      for (int j = b->ops.count - 1; j >= 0; j--) {
15,628,906✔
306
         if (b->ops.items[j].result == reg)
15,579,740✔
307
            return &(b->ops.items[j]);
1,172,619✔
308
      }
309
   }
310

311
   return NULL;
312
}
313

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

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

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

344
   int depth = MASK_CONTEXT(type);
68,250,547✔
345
   assert(depth <= unit->depth);
68,250,547✔
346
   while (depth != unit->depth)
69,799,340✔
347
      unit = unit->context;
1,548,793✔
348

349
   return vtype_array_nth_ptr(&(unit->types), MASK_INDEX(type));
68,250,547✔
350
}
351

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

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

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

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

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

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

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

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

402
         vcode_select_unit(vu);
736✔
403

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

536
   if (unit == active_unit)
41,809✔
537
      vcode_close();
11,640✔
538

539
   for (vcode_unit_t it = unit->children; it != NULL; it = it->next) {
54,453✔
540
      assert(it->context == unit);
12,644✔
541
      it->context = NULL;
12,644✔
542
   }
543
   unit->children = NULL;
41,809✔
544

545
   if (unit->context != NULL) {
41,809✔
546
      vcode_unit_t *it = &(unit->context->children);
13,413✔
547
      for (; *it != NULL && *it != unit; it = &((*it)->next))
262,552✔
548
         ;
549
      assert(*it != NULL);
13,413✔
550
      *it = (*it)->next;
13,413✔
551
   }
552

553
   for (unsigned i = 0; i < unit->blocks.count; i++) {
171,318✔
554
      block_t *b = &(unit->blocks.items[i]);
129,509✔
555

556
      for (unsigned j = 0; j < b->ops.count; j++) {
1,621,325✔
557
         op_t *o = &(b->ops.items[j]);
1,491,816✔
558
         if (OP_HAS_COMMENT(o->kind))
1,491,816✔
559
            free(o->comment);
116,309✔
560
         if (OP_HAS_TARGET(o->kind))
1,491,816✔
561
            free(o->targets.items);
78,828✔
562
         free(o->args.items);
1,491,816✔
563
      }
564
      free(b->ops.items);
129,509✔
565
   }
566
   free(unit->blocks.items);
41,809✔
567

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

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

581
vcode_unit_t vcode_unit_next(vcode_unit_t unit)
22,920✔
582
{
583
   return unit->next;
22,920✔
584
}
585

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

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

597
vcode_type_t vcode_reg_type(vcode_reg_t reg)
4,489,250✔
598
{
599
   return vcode_reg_data(reg)->type;
4,489,250✔
600
}
601

602
vtype_kind_t vcode_reg_kind(vcode_reg_t reg)
1,119,957✔
603
{
604
   return vtype_kind(vcode_reg_type(reg));
1,119,957✔
605
}
606

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

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

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

620
   vtype_t *bounds = vcode_type_data(r->bounds);
663,436✔
621

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

626
   if (bounds->low == bounds->high) {
663,436✔
627
      if (value) *value = bounds->low;
350,831✔
628
      return true;
350,831✔
629
   }
630
   else
631
      return false;
632
}
633

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

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

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

645
      for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
266,293✔
646
         block_t *b = &(active_unit->blocks.items[i]);
209,737✔
647

648
         for (int j = b->ops.count - 1; j >= 0; j--) {
2,943,910✔
649
            op_t *o = &(b->ops.items[j]);
2,734,173✔
650

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

713
            default:
714
               break;
715
            }
716

717
            for (int k = 0; k < o->args.count; k++) {
7,449,538✔
718
               if (o->args.items[k] != VCODE_INVALID_REG)
4,715,365✔
719
                  uses[o->args.items[k]]++;
4,672,648✔
720
            }
721
         }
722
      }
723
   } while (pruned > 0);
56,556✔
724

725
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
171,348✔
726
      block_t *b = &(active_unit->blocks.items[i]);
129,530✔
727
      op_t *dst = &(b->ops.items[0]);
129,530✔
728
      size_t copied = 0;
129,530✔
729
      for (int j = 0; j < b->ops.count; j++) {
1,694,158✔
730
         const op_t *src = &(b->ops.items[j]);
1,564,628✔
731
         if (src->kind != (vcode_op_t)-1) {
1,564,628✔
732
            if (src != dst) {
1,492,182✔
733
               assert(dst < src);
410,139✔
734
               *dst = *src;
410,139✔
735
            }
736
            dst++;
1,492,182✔
737
            copied++;
1,492,182✔
738
         }
739
      }
740

741
      assert(copied <= b->ops.count);
129,530✔
742
      b->ops.count = copied;
129,530✔
743
   }
744
}
41,818✔
745

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

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

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

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

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

779
   return VCODE_INVALID_VAR;
780
}
781

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

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

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

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

802
vcode_op_t vcode_get_op(int op)
4,290,142✔
803
{
804
   return vcode_op_data(op)->kind;
4,290,142✔
805
}
806

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

922
bool vcode_block_finished(void)
1,665,595✔
923
{
924
   assert(active_unit != NULL);
1,665,595✔
925
   assert(active_block != VCODE_INVALID_BLOCK);
1,665,595✔
926

927
   const block_t *b = &(active_unit->blocks.items[active_block]);
1,665,595✔
928
   if (b->ops.count == 0)
1,665,595✔
929
      return false;
930
   else {
931
      vcode_op_t kind = b->ops.items[b->ops.count - 1].kind;
1,493,748✔
932
      return kind == VCODE_OP_WAIT || kind == VCODE_OP_JUMP
1,493,748✔
933
         || kind == VCODE_OP_COND || kind == VCODE_OP_PCALL
1,493,619✔
934
         || kind == VCODE_OP_RETURN || kind == VCODE_OP_CASE
935
         || kind == VCODE_OP_UNREACHABLE;
2,987,367✔
936
   }
937
}
938

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1111
   return col;
1112
}
1113

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1349
         case VCODE_OP_DRIVE_SIGNAL:
1350
            {
1351
               printf("%s ", vcode_op_string(op->kind));
1352
               vcode_dump_reg(op->args.items[0]);
1353
               printf(" count ");
1354
               vcode_dump_reg(op->args.items[1]);
1355
            }
1356
            break;
1357

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

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

1382
         case VCODE_OP_PUSH_SCOPE:
1383
            {
1384
               printf("%s locus ", vcode_op_string(op->kind));
1385
               vcode_dump_reg(op->args.items[0]);
1386
            }
1387
            break;
1388

1389
         case VCODE_OP_POP_SCOPE:
1390
            {
1391
               printf("%s", vcode_op_string(op->kind));
1392
            }
1393
            break;
1394

1395
         case VCODE_OP_INIT_SIGNAL:
1396
            {
1397
               col += vcode_dump_reg(op->result);
1398
               col += printf(" := ");
1399
               col += printf("%s count ", vcode_op_string(op->kind));
1400
               col += vcode_dump_reg(op->args.items[0]);
1401
               col += printf(" size ");
1402
               col += vcode_dump_reg(op->args.items[1]);
1403
               col += printf(" value ");
1404
               col += vcode_dump_reg(op->args.items[2]);
1405
               col += printf(" flags ");
1406
               col += vcode_dump_reg(op->args.items[3]);
1407
               col += printf(" locus ");
1408
               col += vcode_dump_reg(op->args.items[4]);
1409
               if (op->args.count > 5) {
1410
                  col += printf(" offset ");
1411
                  col += vcode_dump_reg(op->args.items[5]);
1412
               }
1413
               vcode_dump_result_type(col, op);
1414
            }
1415
            break;
1416

1417
         case VCODE_OP_IMPLICIT_SIGNAL:
1418
            {
1419
               col += vcode_dump_reg(op->result);
1420
               col += printf(" := %s count ", vcode_op_string(op->kind));
1421
               col += vcode_dump_reg(op->args.items[0]);
1422
               col += printf(" size ");
1423
               col += vcode_dump_reg(op->args.items[1]);
1424
               col += printf(" locus ");
1425
               col += vcode_dump_reg(op->args.items[2]);
1426
               col += printf(" kind ");
1427
               col += vcode_dump_reg(op->args.items[3]);
1428
               col += printf(" closure ");
1429
               col += vcode_dump_reg(op->args.items[4]);
1430
            }
1431
            break;
1432

1433
         case VCODE_OP_RESOLUTION_WRAPPER:
1434
            {
1435
               col += vcode_dump_reg(op->result);
1436
               col += color_printf(" := %s ", vcode_op_string(op->kind));
1437
               col += vcode_dump_reg(op->args.items[0]);
1438
               col += printf(" ileft ");
1439
               col += vcode_dump_reg(op->args.items[1]);
1440
               col += printf(" nlits ");
1441
               col += vcode_dump_reg(op->args.items[2]);
1442
               vcode_dump_result_type(col, op);
1443
            }
1444
            break;
1445

1446
         case VCODE_OP_CLOSURE:
1447
         case VCODE_OP_PROTECTED_INIT:
1448
            {
1449
               col += vcode_dump_reg(op->result);
1450
               col += color_printf(" := %s $magenta$%s$$ context ",
1451
                                   vcode_op_string(op->kind), istr(op->func));
1452
               col += vcode_dump_reg(op->args.items[0]);
1453
               if (op->args.count >= 3) {
1454
                  col += printf(" path " );
1455
                  col += vcode_dump_reg(op->args.items[1]);
1456
                  col += printf(" instance " );
1457
                  col += vcode_dump_reg(op->args.items[2]);
1458
               }
1459
               vcode_dump_result_type(col, op);
1460
            }
1461
            break;
1462

1463
         case VCODE_OP_PACKAGE_INIT:
1464
            {
1465
               col += vcode_dump_reg(op->result);
1466
               col += color_printf(" := %s $magenta$%s$$",
1467
                                   vcode_op_string(op->kind), istr(op->func));
1468
               if (op->args.count > 0) {
1469
                  col += printf(" context " );
1470
                  col += vcode_dump_reg(op->args.items[0]);
1471
               }
1472
               vcode_dump_result_type(col, op);
1473
            }
1474
            break;
1475

1476
         case VCODE_OP_PROCESS_INIT:
1477
            {
1478
               color_printf("%s $magenta$%s$$ locus ",
1479
                            vcode_op_string(op->kind), istr(op->func));
1480
               vcode_dump_reg(op->args.items[0]);
1481
            }
1482
            break;
1483

1484
         case VCODE_OP_PROTECTED_FREE:
1485
            {
1486
               printf("%s ", vcode_op_string(op->kind));
1487
               vcode_dump_reg(op->args.items[0]);
1488
            }
1489
            break;
1490

1491
         case VCODE_OP_WAIT:
1492
            {
1493
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1494
                            op->targets.items[0]);
1495
               if (op->args.items[0] != VCODE_INVALID_REG) {
1496
                  printf(" for ");
1497
                  vcode_dump_reg(op->args.items[0]);
1498
               }
1499
            }
1500
            break;
1501

1502
         case VCODE_OP_JUMP:
1503
            {
1504
               color_printf("%s $yellow$%d$$", vcode_op_string(op->kind),
1505
                            op->targets.items[0]);
1506
            }
1507
            break;
1508

1509
         case VCODE_OP_COND:
1510
            {
1511
               printf("%s ", vcode_op_string(op->kind));
1512
               vcode_dump_reg(op->args.items[0]);
1513
               color_printf(" then $yellow$%d$$ else $yellow$%d$$",
1514
                            op->targets.items[0], op->targets.items[1]);
1515
            }
1516
            break;
1517

1518
         case VCODE_OP_ASSERT:
1519
            {
1520
               printf("%s ", vcode_op_string(op->kind));
1521
               vcode_dump_reg(op->args.items[0]);
1522
               if (op->args.items[2] != VCODE_INVALID_REG) {
1523
                  printf(" report ");
1524
                  vcode_dump_reg(op->args.items[2]);
1525
                  printf(" length ");
1526
                  vcode_dump_reg(op->args.items[3]);
1527
               }
1528
               printf(" severity ");
1529
               vcode_dump_reg(op->args.items[1]);
1530
               printf(" locus ");
1531
               vcode_dump_reg(op->args.items[4]);
1532
               if (op->args.count > 5) {
1533
                  printf(" hint ");
1534
                  vcode_dump_reg(op->args.items[5]);
1535
                  printf(" ");
1536
                  vcode_dump_reg(op->args.items[6]);
1537
               }
1538
            }
1539
            break;
1540

1541
         case VCODE_OP_REPORT:
1542
            {
1543
               printf("%s ", vcode_op_string(op->kind));
1544
               vcode_dump_reg(op->args.items[1]);
1545
               printf(" length ");
1546
               vcode_dump_reg(op->args.items[2]);
1547
               printf(" severity ");
1548
               vcode_dump_reg(op->args.items[0]);
1549
               printf(" locus ");
1550
               vcode_dump_reg(op->args.items[3]);
1551
            }
1552
            break;
1553

1554
         case VCODE_OP_LOAD:
1555
            {
1556
               col += vcode_dump_reg(op->result);
1557
               col += printf(" := %s ", vcode_op_string(op->kind));
1558
               col += vcode_dump_var(op->address, 0);
1559
               vcode_dump_result_type(col, op);
1560
            }
1561
            break;
1562

1563
         case VCODE_OP_LOAD_INDIRECT:
1564
            {
1565
               col += vcode_dump_reg(op->result);
1566
               col += color_printf(" := %s ", vcode_op_string(op->kind));
1567
               col += vcode_dump_reg(op->args.items[0]);
1568
               vcode_dump_result_type(col, op);
1569
            }
1570
            break;
1571

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

1580
         case VCODE_OP_STORE_INDIRECT:
1581
            {
1582
               vcode_dump_reg(op->args.items[1]);
1583
               printf(" := %s ", vcode_op_string(op->kind));
1584
               vcode_dump_reg(op->args.items[0]);
1585
            }
1586
            break;
1587

1588
         case VCODE_OP_INDEX:
1589
            {
1590
               col += vcode_dump_reg(op->result);
1591
               col += printf(" := %s ", vcode_op_string(op->kind));
1592
               col += vcode_dump_var(op->address, 0);
1593
               if (op->args.count > 0) {
1594
                  col += printf(" + ");
1595
                  col += vcode_dump_reg(op->args.items[0]);
1596
               }
1597
               vcode_dump_result_type(col, op);
1598
            }
1599
            break;
1600

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

1639
         case VCODE_OP_TRAP_ADD:
1640
         case VCODE_OP_TRAP_SUB:
1641
         case VCODE_OP_TRAP_MUL:
1642
         case VCODE_OP_TRAP_EXP:
1643
            {
1644
               col += vcode_dump_reg(op->result);
1645
               col += printf(" := %s ", vcode_op_string(op->kind));
1646
               col += vcode_dump_reg(op->args.items[0]);
1647
               switch (op->kind) {
1648
               case VCODE_OP_TRAP_ADD: col += printf(" + "); break;
1649
               case VCODE_OP_TRAP_SUB: col += printf(" - "); break;
1650
               case VCODE_OP_TRAP_MUL: col += printf(" * "); break;
1651
               case VCODE_OP_TRAP_EXP: col += printf(" ** "); break;
1652
               default: break;
1653
               }
1654
               col += vcode_dump_reg(op->args.items[1]);
1655
               col += printf(" locus ");
1656
               col += vcode_dump_reg(op->args.items[2]);
1657
               vcode_dump_result_type(col, op);
1658
            }
1659
            break;
1660

1661
         case VCODE_OP_NOT:
1662
            {
1663
               col += vcode_dump_reg(op->result);
1664
               col += printf(" := %s ", vcode_op_string(op->kind));
1665
               col += vcode_dump_reg(op->args.items[0]);
1666
               vcode_dump_result_type(col, op);
1667
            }
1668
            break;
1669

1670
         case VCODE_OP_COMMENT:
1671
            {
1672
               color_printf("$cyan$// %s$$ ", op->comment);
1673
            }
1674
            break;
1675

1676
         case VCODE_OP_CONST_ARRAY:
1677
         case VCODE_OP_CONST_RECORD:
1678
            {
1679
               col += vcode_dump_reg(op->result);
1680
               col += printf(" := const %c",
1681
                             op->kind == VCODE_OP_CONST_ARRAY ? '[' : '{');
1682
               for (int k = 0; k < op->args.count; k++) {
1683
                  if (k > 0)
1684
                     col += printf(",");
1685
                  col += vcode_dump_reg(op->args.items[k]);
1686
               }
1687

1688
               putchar(op->kind == VCODE_OP_CONST_ARRAY ? ']' : '}');
1689
               vcode_dump_result_type(col + 1, op);
1690
            }
1691
            break;
1692

1693
         case VCODE_OP_CONST_REP:
1694
            {
1695
               col += vcode_dump_reg(op->result);
1696
               col += printf(" := const [");
1697
               col += vcode_dump_reg(op->args.items[0]);
1698
               col += printf("]*%"PRIi64, op->value);
1699
               vcode_dump_result_type(col, op);
1700
            }
1701
            break;
1702

1703
         case VCODE_OP_ADDRESS_OF:
1704
         case VCODE_OP_CAST:
1705
            {
1706
               col += vcode_dump_reg(op->result);
1707
               col += printf(" := %s ", vcode_op_string(op->kind));
1708
               col += vcode_dump_reg(op->args.items[0]);
1709
               vcode_dump_result_type(col, op);
1710
            }
1711
            break;
1712

1713
         case VCODE_OP_RETURN:
1714
            {
1715
               printf("%s ", vcode_op_string(op->kind));
1716
               if (op->args.count > 0)
1717
                  vcode_dump_reg(op->args.items[0]);
1718
            }
1719
            break;
1720

1721
         case VCODE_OP_SCHED_WAVEFORM:
1722
            {
1723
               printf("%s ", vcode_op_string(op->kind));
1724
               vcode_dump_reg(op->args.items[0]);
1725
               printf(" count ");
1726
               vcode_dump_reg(op->args.items[1]);
1727
               printf(" values ");
1728
               vcode_dump_reg(op->args.items[2]);
1729
               printf(" reject ");
1730
               vcode_dump_reg(op->args.items[3]);
1731
               printf(" after ");
1732
               vcode_dump_reg(op->args.items[4]);
1733
            }
1734
            break;
1735

1736
         case VCODE_OP_FORCE:
1737
         case VCODE_OP_RELEASE:
1738
         case VCODE_OP_DEPOSIT_SIGNAL:
1739
            {
1740
               printf("%s ", vcode_op_string(op->kind));
1741
               vcode_dump_reg(op->args.items[0]);
1742
               printf(" count ");
1743
               vcode_dump_reg(op->args.items[1]);
1744
               if (op->args.count > 2) {
1745
                  printf(" values ");
1746
                  vcode_dump_reg(op->args.items[2]);
1747
               }
1748
            }
1749
            break;
1750

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

1764
         case VCODE_OP_NEG:
1765
         case VCODE_OP_TRAP_NEG:
1766
         case VCODE_OP_ABS:
1767
         case VCODE_OP_RESOLVED:
1768
         case VCODE_OP_LAST_VALUE:
1769
            {
1770
               col += vcode_dump_reg(op->result);
1771
               col += printf(" := %s ", vcode_op_string(op->kind));
1772
               col += vcode_dump_reg(op->args.items[0]);
1773
               if (op->args.count > 1) {
1774
                  col += printf(" locus ");
1775
                  col += vcode_dump_reg(op->args.items[1]);
1776
               }
1777
               vcode_dump_result_type(col, op);
1778
            }
1779
            break;
1780

1781
         case VCODE_OP_SELECT:
1782
            {
1783
               col += vcode_dump_reg(op->result);
1784
               col += printf(" := %s ", vcode_op_string(op->kind));
1785
               col += vcode_dump_reg(op->args.items[0]);
1786
               col += printf(" then ");
1787
               col += vcode_dump_reg(op->args.items[1]);
1788
               col += printf(" else ");
1789
               col += vcode_dump_reg(op->args.items[2]);
1790
               vcode_dump_result_type(col, op);
1791
            }
1792
            break;
1793

1794
         case VCODE_OP_WRAP:
1795
            {
1796
               col += vcode_dump_reg(op->result);
1797
               col += printf(" := %s ", vcode_op_string(op->kind));
1798
               col += vcode_dump_reg(op->args.items[0]);
1799
               col += printf(" [");
1800
               for (int i = 1; i < op->args.count; i += 3) {
1801
                  if (i > 1)
1802
                     col += printf(", ");
1803
                  col += vcode_dump_reg(op->args.items[i + 0]);
1804
                  col += printf(" ");
1805
                  col += vcode_dump_reg(op->args.items[i + 1]);
1806
                  col += printf(" ");
1807
                  col += vcode_dump_reg(op->args.items[i + 2]);
1808
               }
1809
               col += printf("]");
1810
               vcode_dump_result_type(col, op);
1811
            }
1812
            break;
1813

1814
         case VCODE_OP_UARRAY_LEFT:
1815
         case VCODE_OP_UARRAY_RIGHT:
1816
         case VCODE_OP_UARRAY_DIR:
1817
         case VCODE_OP_UARRAY_LEN:
1818
            {
1819
               col += vcode_dump_reg(op->result);
1820
               col += printf(" := %s ", vcode_op_string(op->kind));
1821
               col += vcode_dump_reg(op->args.items[0]);
1822
               col += printf(" dim %d", op->dim);
1823
               vcode_dump_result_type(col, op);
1824
            }
1825
            break;
1826

1827
         case VCODE_OP_UNWRAP:
1828
            {
1829
               col += vcode_dump_reg(op->result);
1830
               col += printf(" := %s ", vcode_op_string(op->kind));
1831
               col += vcode_dump_reg(op->args.items[0]);
1832
               vcode_dump_result_type(col, op);
1833
            }
1834
            break;
1835

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

1846
         case VCODE_OP_CONTEXT_UPREF:
1847
            {
1848
               col += vcode_dump_reg(op->result);
1849
               col += printf(" := %s %d", vcode_op_string(op->kind), op->hops);
1850
               vcode_dump_result_type(col, op);
1851
            }
1852
            break;
1853

1854
         case VCODE_OP_ACTIVE:
1855
         case VCODE_OP_EVENT:
1856
         case VCODE_OP_DRIVING:
1857
            {
1858
               col += vcode_dump_reg(op->result);
1859
               col += printf(" := %s ", vcode_op_string(op->kind));
1860
               col += vcode_dump_reg(op->args.items[0]);
1861
               col += printf(" length ");
1862
               col += vcode_dump_reg(op->args.items[1]);
1863
               vcode_dump_result_type(col, op);
1864
            }
1865
            break;
1866

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

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

1888
         case VCODE_OP_COPY:
1889
            {
1890
               vcode_dump_reg(op->args.items[0]);
1891
               printf(" := %s ", vcode_op_string(op->kind));
1892
               vcode_dump_reg(op->args.items[1]);
1893
               if (op->args.count > 2) {
1894
                  printf(" count " );
1895
                  vcode_dump_reg(op->args.items[2]);
1896
               }
1897
            }
1898
            break;
1899

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

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

1921
         case VCODE_OP_PCALL:
1922
            {
1923
               color_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1924
                            istr(op->func));
1925
               for (int i = 0; i < op->args.count; i++) {
1926
                  printf("%s", i > 0 ? ", " : " ");
1927
                  vcode_dump_reg(op->args.items[i]);
1928
               }
1929
               if (op->targets.count > 0)
1930
                  color_printf(" resume $yellow$%d$$", op->targets.items[0]);
1931
            }
1932
            break;
1933

1934
         case VCODE_OP_RESUME:
1935
            {
1936
               color_printf("%s $magenta$%s$$", vcode_op_string(op->kind),
1937
                            istr(op->func));
1938
            }
1939
            break;
1940

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

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

1964
         case VCODE_OP_FILE_OPEN:
1965
            {
1966
               printf("%s ", vcode_op_string(op->kind));
1967
               vcode_dump_reg(op->args.items[0]);
1968
               printf(" name ");
1969
               vcode_dump_reg(op->args.items[1]);
1970
               printf(" length ");
1971
               vcode_dump_reg(op->args.items[2]);
1972
               printf(" kind ");
1973
               vcode_dump_reg(op->args.items[3]);
1974
               if (op->args.count == 5) {
1975
                  printf(" status ");
1976
                  vcode_dump_reg(op->args.items[4]);
1977
               }
1978
            }
1979
            break;
1980

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

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

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

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

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

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

2049
         case VCODE_OP_LAST_EVENT:
2050
         case VCODE_OP_LAST_ACTIVE:
2051
         case VCODE_OP_DRIVING_VALUE:
2052
            {
2053
               col += vcode_dump_reg(op->result);
2054
               col += printf(" := %s ", vcode_op_string(op->kind));
2055
               col += vcode_dump_reg(op->args.items[0]);
2056
               if (op->args.count > 1) {
2057
                  col += printf(" length ");
2058
                  col += vcode_dump_reg(op->args.items[1]);
2059
               }
2060
               vcode_dump_result_type(col, op);
2061
            }
2062
            break;
2063

2064
         case VCODE_OP_ALIAS_SIGNAL:
2065
            {
2066
               printf("%s ", vcode_op_string(op->kind));
2067
               vcode_dump_reg(op->args.items[0]);
2068
               printf(" locus ");
2069
               vcode_dump_reg(op->args.items[1]);
2070
            }
2071
            break;
2072

2073
         case VCODE_OP_LENGTH_CHECK:
2074
            {
2075
               col += printf("%s left ", vcode_op_string(op->kind));
2076
               col += vcode_dump_reg(op->args.items[0]);
2077
               col += printf(" == right ");
2078
               col += vcode_dump_reg(op->args.items[1]);
2079
               col += printf(" locus ");
2080
               col += vcode_dump_reg(op->args.items[2]);
2081
               if (op->args.count > 3) {
2082
                  col += printf(" dim ");
2083
                  col += vcode_dump_reg(op->args.items[3]);
2084
               }
2085
            }
2086
            break;
2087

2088
         case VCODE_OP_EXPONENT_CHECK:
2089
         case VCODE_OP_ZERO_CHECK:
2090
            {
2091
               col += printf("%s ", vcode_op_string(op->kind));
2092
               col += vcode_dump_reg(op->args.items[0]);
2093
               col += printf(" locus ");
2094
               col += vcode_dump_reg(op->args.items[1]);
2095
            }
2096
            break;
2097

2098
         case VCODE_OP_INDEX_CHECK:
2099
         case VCODE_OP_RANGE_CHECK:
2100
            {
2101
               col += printf("%s ", vcode_op_string(op->kind));
2102
               col += vcode_dump_reg(op->args.items[0]);
2103
               col += printf(" left ");
2104
               col += vcode_dump_reg(op->args.items[1]);
2105
               col += printf(" right ");
2106
               col += vcode_dump_reg(op->args.items[2]);
2107
               col += printf(" dir ");
2108
               col += vcode_dump_reg(op->args.items[3]);
2109
               col += printf(" locus ");
2110
               col += vcode_dump_reg(op->args.items[4]);
2111
               if (op->args.items[5] != op->args.items[4]) {
2112
                  col += printf(" hint ");
2113
                  col += vcode_dump_reg(op->args.items[5]);
2114
               }
2115
            }
2116
            break;
2117

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

2125
         case VCODE_OP_COVER_STMT:
2126
         case VCODE_OP_COVER_BRANCH:
2127
            {
2128
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2129
            }
2130
            break;
2131

2132
         case VCODE_OP_COVER_TOGGLE:
2133
         case VCODE_OP_COVER_EXPR:
2134
         case VCODE_OP_COVER_STATE:
2135
            {
2136
               printf("%s %u ", vcode_op_string(op->kind), op->tag);
2137
               vcode_dump_reg(op->args.items[0]);
2138
            }
2139
            break;
2140

2141
         case VCODE_OP_UNDEFINED:
2142
            {
2143
               col += vcode_dump_reg(op->result);
2144
               col += printf(" := %s", vcode_op_string(op->kind));
2145
               vcode_dump_result_type(col, op);
2146
            }
2147
            break;
2148

2149
         case VCODE_OP_RANGE_LENGTH:
2150
         case VCODE_OP_RANGE_NULL:
2151
            {
2152
               col += vcode_dump_reg(op->result);
2153
               col += printf(" := %s left ", vcode_op_string(op->kind));
2154
               vcode_dump_reg(op->args.items[0]);
2155
               col += printf(" right ");
2156
               vcode_dump_reg(op->args.items[1]);
2157
               col += printf(" dir ");
2158
               col += vcode_dump_reg(op->args.items[2]);
2159
               vcode_dump_result_type(col, op);
2160
            }
2161
            break;
2162

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

2177
         case VCODE_OP_LINK_VAR:
2178
            {
2179
               col += vcode_dump_reg(op->result);
2180
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2181
               col += vcode_dump_reg(op->args.items[0]);
2182
               col += color_printf(" $magenta$%s$$", istr(op->ident));
2183
               vcode_dump_result_type(col, op);
2184
            }
2185
            break;
2186

2187
         case VCODE_OP_UNREACHABLE:
2188
            {
2189
               printf("%s", vcode_op_string(op->kind));
2190
               if (op->args.count > 0) {
2191
                  printf(" ");
2192
                  vcode_dump_reg(op->args.items[0]);
2193
               }
2194
            }
2195
            break;
2196

2197
         case VCODE_OP_DEBUG_LOCUS:
2198
            {
2199
               col += vcode_dump_reg(op->result);
2200
               col += color_printf(" := %s $magenta$%s$$%+"PRIi64,
2201
                                   vcode_op_string(op->kind),
2202
                                   istr(op->ident), op->value);
2203
               vcode_dump_result_type(col, op);
2204
            }
2205
            break;
2206

2207
         case VCODE_OP_ENTER_STATE:
2208
            {
2209
               printf("%s ", vcode_op_string(op->kind));
2210
               vcode_dump_reg(op->args.items[0]);
2211
            }
2212
            break;
2213

2214
         case VCODE_OP_REFLECT_VALUE:
2215
            {
2216
               col += vcode_dump_reg(op->result);
2217
               col += printf(" := %s ", vcode_op_string(op->kind));
2218
               vcode_dump_reg(op->args.items[0]);
2219
               col += printf(" context ");
2220
               vcode_dump_reg(op->args.items[1]);
2221
               col += printf(" locus ");
2222
               col += vcode_dump_reg(op->args.items[2]);
2223
               if (op->args.count > 3) {
2224
                  col += printf(" bounds ");
2225
                  col += vcode_dump_reg(op->args.items[3]);
2226
               }
2227
               vcode_dump_result_type(col, op);
2228
            }
2229
            break;
2230

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

2246
         case VCODE_OP_FUNCTION_TRIGGER:
2247
            {
2248
               col += vcode_dump_reg(op->result);
2249
               col += color_printf(" := %s $magenta$%s$$ ",
2250
                                   vcode_op_string(op->kind), istr(op->func));
2251
               for (int i = 0; i < op->args.count; i++) {
2252
                  if (i > 0) col += printf(", ");
2253
                  col += vcode_dump_reg(op->args.items[i]);
2254
               }
2255
               vcode_dump_result_type(col, op);
2256
            }
2257
            break;
2258

2259
         case VCODE_OP_OR_TRIGGER:
2260
         case VCODE_OP_CMP_TRIGGER:
2261
            {
2262
               col += vcode_dump_reg(op->result);
2263
               col += color_printf(" := %s ", vcode_op_string(op->kind));
2264
               col += vcode_dump_reg(op->args.items[0]);
2265
               if (op->kind == VCODE_OP_OR_TRIGGER)
2266
                  col += printf(" || ");
2267
               else
2268
                  col += printf(" == ");
2269
               col += vcode_dump_reg(op->args.items[1]);
2270
               vcode_dump_result_type(col, op);
2271
            }
2272
            break;
2273

2274
         case VCODE_OP_ADD_TRIGGER:
2275
            {
2276
               printf("%s ", vcode_op_string(op->kind));
2277
               vcode_dump_reg(op->args.items[0]);
2278
            }
2279
            break;
2280

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

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

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

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

2329
         if (j == mark_op && i == old_block)
2330
            color_printf("\t $red$<----$$");
2331

2332
         color_printf("$$\n");
2333

2334
         if (callback != NULL)
2335
            (*callback)(j, arg);
2336
      }
2337

2338
      if (b->ops.count == 0)
2339
         color_printf("  $yellow$%2d:$$ $red$Empty basic block$$\n", i);
2340
   }
2341

2342
   printf("\n");
2343
   fflush(stdout);
2344

2345
   active_block = old_block;
2346
}
2347
LCOV_EXCL_STOP
2348

2349
bool vtype_eq(vcode_type_t a, vcode_type_t b)
31,880,265✔
2350
{
2351
   assert(active_unit != NULL);
32,387,661✔
2352

2353
   if (a == b)
32,387,661✔
2354
      return true;
2355
   else {
2356
      const vtype_t *at = vcode_type_data(a);
29,859,523✔
2357
      const vtype_t *bt = vcode_type_data(b);
29,859,523✔
2358

2359
      if (at->kind != bt->kind)
29,859,523✔
2360
         return false;
2361

2362
      switch (at->kind) {
13,031,610✔
2363
      case VCODE_TYPE_INT:
11,000,678✔
2364
         return (at->low == bt->low) && (at->high == bt->high);
20,672,879✔
2365
      case VCODE_TYPE_REAL:
977,885✔
2366
         return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
1,904,680✔
2367
      case VCODE_TYPE_CARRAY:
71,745✔
2368
         return at->size == bt->size && vtype_eq(at->elem, bt->elem);
78,116✔
2369
      case VCODE_TYPE_UARRAY:
89,132✔
2370
         return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
111,203✔
2371
      case VCODE_TYPE_POINTER:
427,618✔
2372
      case VCODE_TYPE_ACCESS:
2373
         return vtype_eq(at->pointed, bt->pointed);
427,618✔
2374
      case VCODE_TYPE_OFFSET:
2375
      case VCODE_TYPE_OPAQUE:
2376
      case VCODE_TYPE_DEBUG_LOCUS:
2377
      case VCODE_TYPE_TRIGGER:
2378
      case VCODE_TYPE_CONVERSION:
2379
         return true;
2380
      case VCODE_TYPE_RESOLUTION:
79,778✔
2381
      case VCODE_TYPE_CLOSURE:
2382
      case VCODE_TYPE_SIGNAL:
2383
      case VCODE_TYPE_FILE:
2384
         return vtype_eq(at->base, bt->base);
79,778✔
2385
      case VCODE_TYPE_RECORD:
62,686✔
2386
      case VCODE_TYPE_CONTEXT:
2387
         return at->name == bt->name;
62,686✔
2388
      }
2389

2390
      return false;
×
2391
   }
2392
}
2393

2394
void vcode_dump(void)
×
2395
{
2396
   vcode_dump_with_mark(-1, NULL, NULL);
×
2397
}
×
2398

2399
static vcode_type_t vtype_new(vtype_t *new)
2,434,804✔
2400
{
2401
   int index = active_unit->types.count - 1;
2,434,804✔
2402
   vcode_type_t type = MAKE_HANDLE(active_unit->depth, index);
2,434,804✔
2403

2404
   for (int i = 0; i < index; i++) {
29,581,768✔
2405
      vcode_type_t this = MAKE_HANDLE(active_unit->depth, i);
29,073,143✔
2406
      if (vtype_eq(this, type)) {
29,073,143✔
2407
         active_unit->types.count--;
1,926,179✔
2408
         return this;
1,926,179✔
2409
      }
2410
   }
2411

2412
   return type;
2413
}
2414

2415
vcode_type_t vtype_int(int64_t low, int64_t high)
1,602,585✔
2416
{
2417
   assert(active_unit != NULL);
1,602,585✔
2418

2419
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,602,585✔
2420
   n->kind = VCODE_TYPE_INT;
1,602,585✔
2421
   n->low  = low;
1,602,585✔
2422
   n->high = high;
1,602,585✔
2423

2424
   switch (bits_for_range(low, high)) {
1,602,585✔
2425
   case 64:
122,906✔
2426
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
122,906✔
2427
      break;
122,906✔
2428
   case 32:
498,025✔
2429
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
498,025✔
2430
      break;
498,025✔
2431
   case 16:
3,244✔
2432
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
3,244✔
2433
      break;
3,244✔
2434
   case 8:
422,720✔
2435
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
422,720✔
2436
      break;
422,720✔
2437
   case 1:
555,689✔
2438
      n->repr = VCODE_REPR_U1;
555,689✔
2439
      break;
555,689✔
2440
   case 0:
1✔
2441
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2442
      break;
1✔
2443
   default:
×
2444
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
×
2445
   }
2446

2447
   return vtype_new(n);
1,602,585✔
2448
}
2449

2450
vcode_type_t vtype_bool(void)
280,400✔
2451
{
2452
   return vtype_int(0, 1);
280,400✔
2453
}
2454

2455
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
35,618✔
2456
{
2457
   assert(active_unit != NULL);
35,618✔
2458

2459
   const vtype_kind_t ekind = vtype_kind(elem);
35,618✔
2460
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
35,618✔
2461
                "array types may not be nested");
2462

2463
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
35,618✔
2464
   memset(n, '\0', sizeof(vtype_t));
35,618✔
2465
   n->kind   = VCODE_TYPE_CARRAY;
35,618✔
2466
   n->elem   = elem;
35,618✔
2467
   n->bounds = bounds;
35,618✔
2468
   n->size   = MAX(size, 0);
35,618✔
2469

2470
   return vtype_new(n);
35,618✔
2471
}
2472

2473
vcode_type_t vtype_find_named_record(ident_t name)
35,459✔
2474
{
2475
   assert(active_unit != NULL);
35,459✔
2476

2477
   for (int i = 0; i < active_unit->types.count; i++) {
475,792✔
2478
      vtype_t *other = &(active_unit->types.items[i]);
465,364✔
2479
      if (other->kind == VCODE_TYPE_RECORD && other->name == name)
465,364✔
2480
         return MAKE_HANDLE(active_unit->depth, i);
25,031✔
2481
   }
2482

2483
   return VCODE_INVALID_TYPE;
2484
}
2485

2486
vcode_type_t vtype_named_record(ident_t name, const vcode_type_t *field_types,
10,428✔
2487
                                int nfields)
2488
{
2489
   assert(active_unit != NULL);
10,428✔
2490

2491
   vtype_t *data = NULL;
10,428✔
2492
   vcode_type_t handle = vtype_find_named_record(name);
10,428✔
2493
   if (handle == VCODE_INVALID_TYPE) {
10,428✔
2494
      data = vtype_array_alloc(&(active_unit->types));
5,223✔
2495
      memset(data, '\0', sizeof(vtype_t));
5,223✔
2496
      data->kind = VCODE_TYPE_RECORD;
5,223✔
2497
      data->name = name;
5,223✔
2498

2499
      handle = vtype_new(data);
5,223✔
2500
   }
2501
   else {
2502
      data = vcode_type_data(handle);
5,205✔
2503
      VCODE_ASSERT(data->fields.count == 0,
5,205✔
2504
                    "record type %s already defined", istr(name));
2505
   }
2506

2507
   vcode_type_array_resize(&(data->fields), 0, VCODE_INVALID_TYPE);
10,428✔
2508
   for (int i = 0; i < nfields; i++)
28,552✔
2509
      vcode_type_array_add(&(data->fields), field_types[i]);
18,124✔
2510

2511
   return handle;
10,428✔
2512
}
2513

2514
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
83,350✔
2515
{
2516
   assert(active_unit != NULL);
83,350✔
2517

2518
   const vtype_kind_t ekind = vtype_kind(elem);
83,350✔
2519
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
83,350✔
2520
                "array types may not be nested");
2521

2522
   VCODE_ASSERT(ndim > 0, "uarray must have at least one dimension");
83,350✔
2523

2524
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
83,350✔
2525
   memset(n, '\0', sizeof(vtype_t));
83,350✔
2526
   n->kind   = VCODE_TYPE_UARRAY;
83,350✔
2527
   n->elem   = elem;
83,350✔
2528
   n->bounds = bounds;
83,350✔
2529
   n->dims   = ndim;
83,350✔
2530

2531
   return vtype_new(n);
83,350✔
2532
}
2533

2534
vcode_type_t vtype_pointer(vcode_type_t to)
176,130✔
2535
{
2536
   assert(active_unit != NULL);
176,130✔
2537

2538
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
176,130✔
2539
   n->kind    = VCODE_TYPE_POINTER;
176,130✔
2540
   n->pointed = to;
176,130✔
2541

2542
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
176,130✔
2543
                "cannot get pointer to carray type");
2544

2545
   return vtype_new(n);
176,130✔
2546
}
2547

2548
vcode_type_t vtype_access(vcode_type_t to)
4,816✔
2549
{
2550
   assert(active_unit != NULL);
4,816✔
2551

2552
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
4,816✔
2553
   n->kind    = VCODE_TYPE_ACCESS;
4,816✔
2554
   n->pointed = to;
4,816✔
2555

2556
   return vtype_new(n);
4,816✔
2557
}
2558

2559
vcode_type_t vtype_signal(vcode_type_t base)
32,280✔
2560
{
2561
   assert(active_unit != NULL);
32,280✔
2562

2563
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
32,280✔
2564
   n->kind = VCODE_TYPE_SIGNAL;
32,280✔
2565
   n->base = base;
32,280✔
2566

2567
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
32,280✔
2568

2569
   return vtype_new(n);
32,280✔
2570
}
2571

2572
vcode_type_t vtype_resolution(vcode_type_t base)
774✔
2573
{
2574
   assert(active_unit != NULL);
774✔
2575

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

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

2583
vcode_type_t vtype_closure(vcode_type_t result)
965✔
2584
{
2585
   assert(active_unit != NULL);
965✔
2586

2587
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
965✔
2588
   n->kind = VCODE_TYPE_CLOSURE;
965✔
2589
   n->base = result;
965✔
2590

2591
   return vtype_new(n);
965✔
2592
}
2593

2594
vcode_type_t vtype_context(ident_t name)
49,242✔
2595
{
2596
   assert(active_unit != NULL);
49,242✔
2597
   assert(name != NULL);
49,242✔
2598

2599
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
49,242✔
2600
   n->kind = VCODE_TYPE_CONTEXT;
49,242✔
2601
   n->name = name;
49,242✔
2602

2603
   return vtype_new(n);
49,242✔
2604
}
2605

2606
vcode_type_t vtype_file(vcode_type_t base)
582✔
2607
{
2608
   assert(active_unit != NULL);
582✔
2609

2610
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
582✔
2611
   n->kind = VCODE_TYPE_FILE;
582✔
2612
   n->base = base;
582✔
2613

2614
   return vtype_new(n);
582✔
2615
}
2616

2617
vcode_type_t vtype_offset(void)
252,221✔
2618
{
2619
   assert(active_unit != NULL);
252,221✔
2620

2621
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
252,221✔
2622
   n->kind = VCODE_TYPE_OFFSET;
252,221✔
2623
   n->low  = INT64_MIN;
252,221✔
2624
   n->high = INT64_MAX;
252,221✔
2625
   n->repr = VCODE_REPR_I64;
252,221✔
2626

2627
   return vtype_new(n);
252,221✔
2628
}
2629

2630
vcode_type_t vtype_time(void)
15,801✔
2631
{
2632
   return vtype_int(INT64_MIN, INT64_MAX);
15,801✔
2633
}
2634

2635
vcode_type_t vtype_char(void)
9,202✔
2636
{
2637
   return vtype_int(0, 255);
9,202✔
2638
}
2639

2640
vcode_type_t vtype_opaque(void)
1,118✔
2641
{
2642
   assert(active_unit != NULL);
1,118✔
2643

2644
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,118✔
2645
   n->kind = VCODE_TYPE_OPAQUE;
1,118✔
2646

2647
   return vtype_new(n);
1,118✔
2648
}
2649

2650
vcode_type_t vtype_debug_locus(void)
109,671✔
2651
{
2652
   assert(active_unit != NULL);
109,671✔
2653

2654
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
109,671✔
2655
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
109,671✔
2656

2657
   return vtype_new(n);
109,671✔
2658
}
2659

2660
vcode_type_t vtype_trigger(void)
287✔
2661
{
2662
   assert(active_unit != NULL);
287✔
2663

2664
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
287✔
2665
   n->kind = VCODE_TYPE_TRIGGER;
287✔
2666

2667
   return vtype_new(n);
287✔
2668
}
2669

2670
vcode_type_t vtype_conversion(void)
180✔
2671
{
2672
   assert(active_unit != NULL);
180✔
2673

2674
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
180✔
2675
   n->kind = VCODE_TYPE_CONVERSION;
180✔
2676

2677
   return vtype_new(n);
180✔
2678
}
2679

2680
vcode_type_t vtype_real(double low, double high)
79,762✔
2681
{
2682
   assert(active_unit != NULL);
79,762✔
2683

2684
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
79,762✔
2685
   n->kind  = VCODE_TYPE_REAL;
79,762✔
2686
   n->rlow  = low;
79,762✔
2687
   n->rhigh = high;
79,762✔
2688

2689
   return vtype_new(n);
79,762✔
2690
}
2691

2692
vtype_kind_t vtype_kind(vcode_type_t type)
5,506,394✔
2693
{
2694
   vtype_t *vt = vcode_type_data(type);
5,506,394✔
2695
   return vt->kind;
5,506,394✔
2696
}
2697

2698
vtype_repr_t vtype_repr(vcode_type_t type)
449,754✔
2699
{
2700
   vtype_t *vt = vcode_type_data(type);
449,754✔
2701
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
449,754✔
2702
   return vt->repr;
449,754✔
2703
}
2704

2705
vcode_type_t vtype_elem(vcode_type_t type)
347,563✔
2706
{
2707
   vtype_t *vt = vcode_type_data(type);
347,563✔
2708
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
347,563✔
2709
   return vt->elem;
347,563✔
2710
}
2711

2712
vcode_type_t vtype_base(vcode_type_t type)
13,139✔
2713
{
2714
   vtype_t *vt = vcode_type_data(type);
13,139✔
2715
   assert(vt->kind == VCODE_TYPE_SIGNAL || vt->kind == VCODE_TYPE_FILE
13,139✔
2716
          || vt->kind == VCODE_TYPE_RESOLUTION
2717
          || vt->kind == VCODE_TYPE_CLOSURE);
2718
   return vt->base;
13,139✔
2719
}
2720

2721
vcode_type_t vtype_bounds(vcode_type_t type)
12,267✔
2722
{
2723
   vtype_t *vt = vcode_type_data(type);
12,267✔
2724
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
12,267✔
2725
   return vt->bounds;
12,267✔
2726
}
2727

2728
unsigned vtype_dims(vcode_type_t type)
134,261✔
2729
{
2730
   vtype_t *vt = vcode_type_data(type);
134,261✔
2731
   assert(vt->kind == VCODE_TYPE_UARRAY);
134,261✔
2732
   return vt->dims;
134,261✔
2733
}
2734

2735
unsigned vtype_size(vcode_type_t type)
74,535✔
2736
{
2737
   vtype_t *vt = vcode_type_data(type);
74,535✔
2738
   assert(vt->kind == VCODE_TYPE_CARRAY);
74,535✔
2739
   return vt->size;
74,535✔
2740
}
2741

2742
int vtype_fields(vcode_type_t type)
25,249✔
2743
{
2744
   vtype_t *vt = vcode_type_data(type);
25,249✔
2745
   assert(vt->kind == VCODE_TYPE_RECORD);
25,249✔
2746
   return vt->fields.count;
25,249✔
2747
}
2748

2749
vcode_type_t vtype_field(vcode_type_t type, int field)
203,941✔
2750
{
2751
   vtype_t *vt = vcode_type_data(type);
203,941✔
2752
   assert(vt->kind == VCODE_TYPE_RECORD);
203,941✔
2753
   return vcode_type_array_nth(&(vt->fields), field);
203,941✔
2754
}
2755

2756
ident_t vtype_name(vcode_type_t type)
2,716✔
2757
{
2758
   vtype_t *vt = vcode_type_data(type);
2,716✔
2759
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
2,716✔
2760
   return vt->name;
2,716✔
2761
}
2762

2763
vcode_type_t vtype_pointed(vcode_type_t type)
365,584✔
2764
{
2765
   vtype_t *vt = vcode_type_data(type);
365,584✔
2766
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
365,584✔
2767
   return vt->pointed;
365,584✔
2768
}
2769

2770
int64_t vtype_low(vcode_type_t type)
55,570✔
2771
{
2772
   vtype_t *vt = vcode_type_data(type);
55,570✔
2773
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
55,570✔
2774
   return vt->low;
55,570✔
2775
}
2776

2777
int64_t vtype_high(vcode_type_t type)
53,505✔
2778
{
2779
   vtype_t *vt = vcode_type_data(type);
53,505✔
2780
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
53,505✔
2781
   return vt->high;
53,505✔
2782
}
2783

2784
static bool vtype_is_pointer(vcode_type_t type, vtype_kind_t to)
441✔
2785
{
2786
   return vtype_kind(type) == VCODE_TYPE_POINTER
441✔
2787
      && vtype_kind(vtype_pointed(type)) == to;
441✔
2788
}
2789

2790
bool vtype_is_scalar(vcode_type_t type)
373,154✔
2791
{
2792
   const vtype_kind_t kind = vtype_kind(type);
373,154✔
2793
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
373,154✔
2794
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
149,603✔
2795
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2796
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2797
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER;
373,154✔
2798
}
2799

2800
bool vtype_is_composite(vcode_type_t type)
22,537✔
2801
{
2802
   const vtype_kind_t kind = vtype_kind(type);
22,537✔
2803
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
22,537✔
2804
}
2805

2806
bool vtype_is_signal(vcode_type_t type)
163,706✔
2807
{
2808
   vtype_t *vt = vcode_type_data(type);
291,741✔
2809
   switch (vt->kind) {
291,741✔
2810
   case VCODE_TYPE_SIGNAL:
2811
      return true;
2812
   case VCODE_TYPE_POINTER:
69,665✔
2813
      return vtype_is_signal(vt->pointed);
69,665✔
2814
   case VCODE_TYPE_RECORD:
2815
      for (int i = 0; i < vt->fields.count; i++) {
35,945✔
2816
         if (vtype_is_signal(vt->fields.items[i]))
28,084✔
2817
            return true;
2818
      }
2819
      return false;
2820
   case VCODE_TYPE_UARRAY:
58,370✔
2821
   case VCODE_TYPE_CARRAY:
2822
      return vtype_is_signal(vt->elem);
58,370✔
2823
   default:
135,102✔
2824
      return false;
135,102✔
2825
   }
2826
}
2827

2828
int vtype_repr_bits(vtype_repr_t repr)
356,138✔
2829
{
2830
   switch (repr) {
356,138✔
2831
   case VCODE_REPR_U1: return 1;
2832
   case VCODE_REPR_U8: case VCODE_REPR_I8: return 8;
2833
   case VCODE_REPR_U16: case VCODE_REPR_I16: return 16;
2834
   case VCODE_REPR_U32: case VCODE_REPR_I32: return 32;
2835
   case VCODE_REPR_U64: case VCODE_REPR_I64: return 64;
2836
   default: return -1;
2837
   }
2838
}
2839

2840
bool vtype_repr_signed(vtype_repr_t repr)
44,137✔
2841
{
2842
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
44,137✔
2843
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
44,137✔
2844
}
2845

2846
static int64_t vtype_repr_low(vtype_repr_t repr)
8,744✔
2847
{
2848
   switch (repr) {
8,744✔
2849
   case VCODE_REPR_U1:
2850
   case VCODE_REPR_U8:
2851
   case VCODE_REPR_U16:
2852
   case VCODE_REPR_U32:
2853
   case VCODE_REPR_U64: return 0;
2854
   case VCODE_REPR_I8:  return INT8_MIN;
2855
   case VCODE_REPR_I16: return INT16_MIN;
2856
   case VCODE_REPR_I32: return INT32_MIN;
2857
   case VCODE_REPR_I64: return INT64_MIN;
2858
   default:             return 0;
2859
   }
2860
}
2861

2862
static uint64_t vtype_repr_high(vtype_repr_t repr)
8,744✔
2863
{
2864
   switch (repr) {
8,744✔
2865
   case VCODE_REPR_U1:  return 1;
2866
   case VCODE_REPR_U8:  return UINT8_MAX;
2867
   case VCODE_REPR_U16: return UINT16_MAX;
2868
   case VCODE_REPR_U32: return UINT32_MAX;
2869
   case VCODE_REPR_U64: return UINT64_MAX;
2870
   case VCODE_REPR_I8:  return INT8_MAX;
2871
   case VCODE_REPR_I16: return INT16_MAX;
2872
   case VCODE_REPR_I32: return INT32_MAX;
2873
   case VCODE_REPR_I64: return INT64_MAX;
2874
   default:             return 0;
2875
   }
2876
}
2877

2878
static bool vtype_clamp_to_repr(vtype_repr_t repr, int64_t *low, int64_t *high)
8,744✔
2879
{
2880
   int64_t clamp_low = vtype_repr_low(repr);
8,744✔
2881
   uint64_t clamp_high = vtype_repr_high(repr);
8,744✔
2882

2883
   if (*low >= clamp_low && *high <= clamp_high)
8,744✔
2884
      return true;
2885
   else {
2886
      *low = MAX(clamp_low, *low);
4,647✔
2887
      *high = MIN(clamp_high, *high);
4,647✔
2888
      return false;
4,647✔
2889
   }
2890
}
2891

2892
int vcode_count_params(void)
10,758✔
2893
{
2894
   assert(active_unit != NULL);
10,758✔
2895
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
10,758✔
2896
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2897
          || active_unit->kind == VCODE_UNIT_PROPERTY
2898
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2899

2900
   return active_unit->params.count;
10,758✔
2901
}
2902

2903
vcode_type_t vcode_param_type(int param)
28,294✔
2904
{
2905
   assert(active_unit != NULL);
28,294✔
2906
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
28,294✔
2907
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2908
          || active_unit->kind == VCODE_UNIT_PROPERTY
2909
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2910
   assert(param < active_unit->params.count);
28,294✔
2911

2912
   return active_unit->params.items[param].type;
28,294✔
2913
}
2914

2915
vcode_reg_t vcode_param_reg(int param)
35,991✔
2916
{
2917
   assert(active_unit != NULL);
35,991✔
2918
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
35,991✔
2919
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2920
          || active_unit->kind == VCODE_UNIT_PROPERTY
2921
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2922
   assert(param < active_unit->params.count);
35,991✔
2923

2924
   return active_unit->params.items[param].reg;
35,991✔
2925
}
2926

2927
vcode_block_t emit_block(void)
129,530✔
2928
{
2929
   assert(active_unit != NULL);
129,530✔
2930

2931
   vcode_block_t bnum = active_unit->blocks.count;
129,530✔
2932

2933
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
129,530✔
2934
   memset(bptr, '\0', sizeof(block_t));
129,530✔
2935

2936
   if (active_block != VCODE_INVALID_BLOCK)
129,530✔
2937
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
87,712✔
2938
   else
2939
      bptr->last_loc = LOC_INVALID;
41,818✔
2940

2941
   return bnum;
129,530✔
2942
}
2943

2944
void vcode_select_unit(vcode_unit_t unit)
167,080✔
2945
{
2946
   active_unit  = unit;
167,080✔
2947
   active_block = VCODE_INVALID_BLOCK;
167,080✔
2948
}
167,080✔
2949

2950
void vcode_select_block(vcode_block_t block)
539,485✔
2951
{
2952
   assert(active_unit != NULL);
539,485✔
2953
   active_block = block;
539,485✔
2954
}
539,485✔
2955

2956
vcode_block_t vcode_active_block(void)
1,404,758✔
2957
{
2958
   assert(active_unit != NULL);
1,404,758✔
2959
   assert(active_block != -1);
1,404,758✔
2960
   return active_block;
1,404,758✔
2961
}
2962

2963
const loc_t *vcode_last_loc(void)
642,647✔
2964
{
2965
   return &(vcode_block_data()->last_loc);
642,647✔
2966
}
2967

2968
vcode_unit_t vcode_active_unit(void)
812✔
2969
{
2970
   assert(active_unit != NULL);
812✔
2971
   return active_unit;
812✔
2972
}
2973

2974
ident_t vcode_unit_name(vcode_unit_t vu)
150,255✔
2975
{
2976
   assert(vu != NULL);
150,255✔
2977
   return vu->name;
150,255✔
2978
}
2979

2980
bool vcode_unit_has_undefined(vcode_unit_t vu)
11,839✔
2981
{
2982
   assert(vu != NULL);
11,839✔
2983
   return !!(vu->flags & UNIT_UNDEFINED);
11,839✔
2984
}
2985

2986
bool vcode_unit_has_escaping_tlab(vcode_unit_t vu)
4,665✔
2987
{
2988
   return !!(vu->flags & UNIT_ESCAPING_TLAB);
4,665✔
2989
}
2990

2991
int vcode_unit_depth(vcode_unit_t vu)
×
2992
{
2993
   assert(vu != NULL);
×
2994
   return vu->depth;
×
2995
}
2996

2997
void vcode_set_result(vcode_type_t type)
21,080✔
2998
{
2999
   assert(active_unit != NULL);
21,080✔
3000
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
21,080✔
3001
          || active_unit->kind == VCODE_UNIT_THUNK);
3002

3003
   active_unit->result = type;
21,080✔
3004
}
21,080✔
3005

3006
vcode_type_t vcode_unit_result(vcode_unit_t vu)
31,013✔
3007
{
3008
   assert(vu != NULL);
31,013✔
3009
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
31,013✔
3010
   return vu->result;
31,013✔
3011
}
3012

3013
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
344,787✔
3014
{
3015
   assert(vu != NULL);
344,787✔
3016
   return vu->kind;
344,787✔
3017
}
3018

3019
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
128,118✔
3020
{
3021
   assert(vu != NULL);
128,118✔
3022
   return vu->context;
128,118✔
3023
}
3024

3025
void vcode_unit_object(vcode_unit_t vu, ident_t *module, ptrdiff_t *offset)
72,292✔
3026
{
3027
   assert(vu != NULL);
72,292✔
3028
   *module = vu->module;
72,292✔
3029
   *offset = vu->offset;
72,292✔
3030
}
72,292✔
3031

3032
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
53,666✔
3033
{
3034
   int hops = 0;
53,666✔
3035
   for (; (unit = unit->context); hops++)
131,085✔
3036
      ;
3037
   return hops;
53,666✔
3038
}
3039

3040
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
26,060✔
3041
{
3042
   assert(context->kind != VCODE_UNIT_THUNK);
26,060✔
3043

3044
   child->next = NULL;
26,060✔
3045
   if (context->children == NULL)
26,060✔
3046
      context->children = child;
10,507✔
3047
   else {
3048
      vcode_unit_t it;
3049
      for (it = context->children; it->next != NULL; it = it->next)
747,530✔
3050
         ;
3051
      it->next = child;
15,553✔
3052
   }
3053
}
26,060✔
3054

3055
vcode_unit_t emit_function(ident_t name, object_t *obj, vcode_unit_t context)
10,631✔
3056
{
3057
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
10,631✔
3058
   vu->kind     = VCODE_UNIT_FUNCTION;
10,631✔
3059
   vu->name     = name;
10,631✔
3060
   vu->context  = context;
10,631✔
3061
   vu->result   = VCODE_INVALID_TYPE;
10,631✔
3062
   vu->depth    = vcode_unit_calc_depth(vu);
10,631✔
3063

3064
   object_locus(obj, &vu->module, &vu->offset);
10,631✔
3065

3066
   vcode_add_child(context, vu);
10,631✔
3067

3068
   vcode_select_unit(vu);
10,631✔
3069
   vcode_select_block(emit_block());
10,631✔
3070
   emit_debug_info(&(obj->loc));
10,631✔
3071

3072
   return vu;
10,631✔
3073
}
3074

3075
vcode_unit_t emit_procedure(ident_t name, object_t *obj, vcode_unit_t context)
235✔
3076
{
3077
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
235✔
3078
   vu->kind     = VCODE_UNIT_PROCEDURE;
235✔
3079
   vu->name     = name;
235✔
3080
   vu->context  = context;
235✔
3081
   vu->result   = VCODE_INVALID_TYPE;
235✔
3082
   vu->depth    = vcode_unit_calc_depth(vu);
235✔
3083

3084
   object_locus(obj, &vu->module, &vu->offset);
235✔
3085

3086
   vcode_add_child(context, vu);
235✔
3087

3088
   vcode_select_unit(vu);
235✔
3089
   vcode_select_block(emit_block());
235✔
3090
   emit_debug_info(&(obj->loc));
235✔
3091

3092
   return vu;
235✔
3093
}
3094

3095
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
8,489✔
3096
{
3097
   assert(context->kind == VCODE_UNIT_INSTANCE
8,489✔
3098
          || context->kind == VCODE_UNIT_SHAPE);
3099

3100
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,489✔
3101
   vu->kind     = VCODE_UNIT_PROCESS;
8,489✔
3102
   vu->name     = name;
8,489✔
3103
   vu->context  = context;
8,489✔
3104
   vu->depth    = vcode_unit_calc_depth(vu);
8,489✔
3105
   vu->result   = VCODE_INVALID_TYPE;
8,489✔
3106

3107
   object_locus(obj, &vu->module, &vu->offset);
8,489✔
3108

3109
   vcode_add_child(context, vu);
8,489✔
3110

3111
   vcode_select_unit(vu);
8,489✔
3112
   vcode_select_block(emit_block());
8,489✔
3113
   emit_debug_info(&(obj->loc));
8,489✔
3114

3115
   return vu;
8,489✔
3116
}
3117

3118
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
8,626✔
3119
{
3120
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
8,626✔
3121

3122
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,626✔
3123
   vu->kind     = VCODE_UNIT_INSTANCE;
8,626✔
3124
   vu->name     = name;
8,626✔
3125
   vu->context  = context;
8,626✔
3126
   vu->depth    = vcode_unit_calc_depth(vu);
8,626✔
3127
   vu->result   = VCODE_INVALID_TYPE;
8,626✔
3128

3129
   object_locus(obj, &vu->module, &vu->offset);
8,626✔
3130

3131
   if (context != NULL)
8,626✔
3132
      vcode_add_child(context, vu);
5,361✔
3133

3134
   vcode_select_unit(vu);
8,626✔
3135
   vcode_select_block(emit_block());
8,626✔
3136
   emit_debug_info(&(obj->loc));
8,626✔
3137

3138
   return vu;
8,626✔
3139
}
3140

3141
vcode_unit_t emit_shape(ident_t name, object_t *obj, vcode_unit_t context)
51✔
3142
{
3143
   assert(context == NULL || context->kind == VCODE_UNIT_SHAPE);
51✔
3144

3145
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
51✔
3146
   vu->kind     = VCODE_UNIT_SHAPE;
51✔
3147
   vu->name     = name;
51✔
3148
   vu->context  = context;
51✔
3149
   vu->depth    = vcode_unit_calc_depth(vu);
51✔
3150
   vu->result   = VCODE_INVALID_TYPE;
51✔
3151

3152
   object_locus(obj, &vu->module, &vu->offset);
51✔
3153

3154
   if (context != NULL)
51✔
3155
      vcode_add_child(context, vu);
×
3156

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

3161
   return vu;
51✔
3162
}
3163

3164
vcode_unit_t emit_package(ident_t name, object_t *obj, vcode_unit_t context)
1,667✔
3165
{
3166
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
1,667✔
3167
   vu->kind     = VCODE_UNIT_PACKAGE;
1,667✔
3168
   vu->name     = name;
1,667✔
3169
   vu->context  = context;
1,667✔
3170
   vu->depth    = vcode_unit_calc_depth(vu);
1,667✔
3171
   vu->result   = VCODE_INVALID_TYPE;
1,667✔
3172

3173
   object_locus(obj, &vu->module, &vu->offset);
1,667✔
3174

3175
   if (context != NULL)
1,667✔
3176
      vcode_add_child(context, vu);
170✔
3177

3178
   vcode_select_unit(vu);
1,667✔
3179
   vcode_select_block(emit_block());
1,667✔
3180
   emit_debug_info(&(obj->loc));
1,667✔
3181

3182
   return vu;
1,667✔
3183
}
3184

3185
vcode_unit_t emit_protected(ident_t name, object_t *obj, vcode_unit_t context)
166✔
3186
{
3187
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
166✔
3188
   vu->kind     = VCODE_UNIT_PROTECTED;
166✔
3189
   vu->name     = name;
166✔
3190
   vu->context  = context;
166✔
3191
   vu->depth    = vcode_unit_calc_depth(vu);
166✔
3192
   vu->result   = VCODE_INVALID_TYPE;
166✔
3193

3194
   object_locus(obj, &vu->module, &vu->offset);
166✔
3195

3196
   if (context != NULL)
166✔
3197
      vcode_add_child(context, vu);
166✔
3198

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

3203
   return vu;
166✔
3204
}
3205

3206
vcode_unit_t emit_property(ident_t name, object_t *obj, vcode_unit_t context)
105✔
3207
{
3208
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
105✔
3209
   vu->kind     = VCODE_UNIT_PROPERTY;
105✔
3210
   vu->name     = name;
105✔
3211
   vu->context  = context;
105✔
3212
   vu->depth    = vcode_unit_calc_depth(vu);
105✔
3213
   vu->result   = VCODE_INVALID_TYPE;
105✔
3214

3215
   object_locus(obj, &vu->module, &vu->offset);
105✔
3216

3217
   if (context != NULL)
105✔
3218
      vcode_add_child(context, vu);
105✔
3219

3220
   vcode_select_unit(vu);
105✔
3221
   vcode_select_block(emit_block());
105✔
3222
   emit_debug_info(&(obj->loc));
105✔
3223

3224
   return vu;
105✔
3225
}
3226

3227
vcode_unit_t emit_thunk(ident_t name, object_t *obj, vcode_unit_t context)
11,848✔
3228
{
3229
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
11,848✔
3230
   vu->kind     = VCODE_UNIT_THUNK;
11,848✔
3231
   vu->name     = name;
11,848✔
3232
   vu->context  = context;
11,848✔
3233
   vu->depth    = vcode_unit_calc_depth(vu);
11,848✔
3234
   vu->result   = VCODE_INVALID_TYPE;
11,848✔
3235
   vu->depth    = vcode_unit_calc_depth(vu);
11,848✔
3236

3237
   object_locus(obj, &vu->module, &vu->offset);
11,848✔
3238

3239
   if (context != NULL)
11,848✔
3240
      vcode_add_child(context, vu);
903✔
3241

3242
   vcode_select_unit(vu);
11,848✔
3243
   vcode_select_block(emit_block());
11,848✔
3244

3245
   return vu;
11,848✔
3246
}
3247

3248
void emit_assert(vcode_reg_t value, vcode_reg_t message, vcode_reg_t length,
13,188✔
3249
                 vcode_reg_t severity, vcode_reg_t locus, vcode_reg_t hint_left,
3250
                 vcode_reg_t hint_right)
3251
{
3252
   int64_t value_const;
13,188✔
3253
   if (vcode_reg_const(value, &value_const) && value_const != 0) {
13,188✔
3254
      emit_comment("Always true assertion on r%d", value);
×
3255
      return;
×
3256
   }
3257

3258
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
13,188✔
3259
   vcode_add_arg(op, value);
13,188✔
3260
   vcode_add_arg(op, severity);
13,188✔
3261
   vcode_add_arg(op, message);
13,188✔
3262
   vcode_add_arg(op, length);
13,188✔
3263
   vcode_add_arg(op, locus);
13,188✔
3264

3265
   if (hint_left != VCODE_INVALID_REG) {
13,188✔
3266
      vcode_add_arg(op, hint_left);
5,470✔
3267
      vcode_add_arg(op, hint_right);
5,470✔
3268

3269
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
5,470✔
3270
                   "left hint must be scalar");
3271
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
5,470✔
3272
                   "right hint must be scalar");
3273
   }
3274

3275
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
13,188✔
3276
                "value parameter to assert is not bool");
3277
   VCODE_ASSERT(message == VCODE_INVALID_REG
13,188✔
3278
                || vcode_reg_kind(message) == VCODE_TYPE_POINTER,
3279
                "message parameter to assert is not a pointer");
3280
   VCODE_ASSERT(vtype_eq(vcode_reg_type(value), vtype_bool()),
13,188✔
3281
                "value parameter to assert is not bool");
3282
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
13,188✔
3283
                "locus argument to report must be a debug locus");
3284
}
3285

3286
void emit_report(vcode_reg_t message, vcode_reg_t length, vcode_reg_t severity,
2,171✔
3287
                 vcode_reg_t locus)
3288
{
3289
   op_t *op = vcode_add_op(VCODE_OP_REPORT);
2,171✔
3290
   vcode_add_arg(op, severity);
2,171✔
3291
   vcode_add_arg(op, message);
2,171✔
3292
   vcode_add_arg(op, length);
2,171✔
3293
   vcode_add_arg(op, locus);
2,171✔
3294

3295
   VCODE_ASSERT(vcode_reg_kind(message) == VCODE_TYPE_POINTER,
2,171✔
3296
                "message parameter to report is not a pointer");
3297
   VCODE_ASSERT(vtype_eq(vtype_pointed(vcode_reg_type(message)), vtype_char()),
2,171✔
3298
                "message parameter to report is not a character pointer");
3299
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
2,171✔
3300
                "locus argument to report must be a debug locus");
3301
}
2,171✔
3302

3303
vcode_reg_t emit_cmp(vcode_cmp_t cmp, vcode_reg_t lhs, vcode_reg_t rhs)
37,271✔
3304
{
3305
   if (lhs == rhs) {
37,271✔
3306
      if (cmp == VCODE_CMP_EQ)
928✔
3307
         return emit_const(vtype_bool(), 1);
921✔
3308
      else if (cmp == VCODE_CMP_NEQ)
7✔
3309
         return emit_const(vtype_bool(), 0);
×
3310
      else if (cmp == VCODE_CMP_LEQ || cmp == VCODE_CMP_GEQ)
7✔
3311
         return emit_const(vtype_bool(), 1);
×
3312
      else if (cmp == VCODE_CMP_LT || cmp == VCODE_CMP_GT)
7✔
3313
         return emit_const(vtype_bool(), 0);
7✔
3314
   }
3315

3316
   int64_t lconst, rconst;
36,343✔
3317
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)) {
36,343✔
3318
      switch (cmp) {
428✔
3319
      case VCODE_CMP_EQ:
244✔
3320
         return emit_const(vtype_bool(), lconst == rconst);
244✔
3321
      case VCODE_CMP_NEQ:
×
3322
         return emit_const(vtype_bool(), lconst != rconst);
×
3323
      case VCODE_CMP_LT:
3✔
3324
         return emit_const(vtype_bool(), lconst < rconst);
3✔
3325
      case VCODE_CMP_GT:
181✔
3326
         return emit_const(vtype_bool(), lconst > rconst);
181✔
3327
      case VCODE_CMP_LEQ:
×
3328
         return emit_const(vtype_bool(), lconst <= rconst);
×
3329
      case VCODE_CMP_GEQ:
×
3330
         return emit_const(vtype_bool(), lconst >= rconst);
×
3331
      default:
×
3332
         fatal_trace("cannot fold comparison %d", cmp);
×
3333
      }
3334
   }
3335

3336
   // Reuse any previous operation in this block with the same arguments
3337
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
652,598✔
3338
      if (other->args.count == 2 && other->args.items[0] == lhs
27,554✔
3339
          && other->args.items[1] == rhs && other->cmp == cmp)
1,485✔
3340
         return other->result;
356✔
3341
   }
3342

3343
   op_t *op = vcode_add_op(VCODE_OP_CMP);
35,559✔
3344
   vcode_add_arg(op, lhs);
35,559✔
3345
   vcode_add_arg(op, rhs);
35,559✔
3346
   op->cmp    = cmp;
35,559✔
3347
   op->result = vcode_add_reg(vtype_bool());
35,559✔
3348

3349
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
35,559✔
3350
                "arguments to cmp are not the same type");
3351

3352
   return op->result;
3353
}
3354

3355
vcode_reg_t emit_fcall(ident_t func, vcode_type_t type, vcode_type_t bounds,
34,882✔
3356
                       const vcode_reg_t *args, int nargs)
3357
{
3358
   op_t *o = vcode_add_op(VCODE_OP_FCALL);
34,882✔
3359
   o->func = func;
34,882✔
3360
   o->type = type;
34,882✔
3361
   for (int i = 0; i < nargs; i++)
137,220✔
3362
      vcode_add_arg(o, args[i]);
102,338✔
3363

3364
   for (int i = 0; i < nargs; i++)
137,220✔
3365
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
102,338✔
3366
                   "invalid argument to function");
3367

3368
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
34,882✔
3369
                "first argument to VHDL function must be context pointer");
3370

3371
   if (type == VCODE_INVALID_TYPE)
34,882✔
3372
      return (o->result = VCODE_INVALID_REG);
4,986✔
3373
   else {
3374
      o->result = vcode_add_reg(type);
29,896✔
3375

3376
      reg_t *rr = vcode_reg_data(o->result);
29,896✔
3377
      rr->bounds = bounds;
29,896✔
3378

3379
      return o->result;
29,896✔
3380
   }
3381
}
3382

3383
void emit_pcall(ident_t func, const vcode_reg_t *args, int nargs,
777✔
3384
                vcode_block_t resume_bb)
3385
{
3386
   op_t *o = vcode_add_op(VCODE_OP_PCALL);
777✔
3387
   o->func = func;
777✔
3388
   for (int i = 0; i < nargs; i++)
2,752✔
3389
      vcode_add_arg(o, args[i]);
1,975✔
3390

3391
   vcode_block_array_add(&(o->targets), resume_bb);
777✔
3392

3393
   for (int i = 0; i < nargs; i++)
2,752✔
3394
      VCODE_ASSERT(args[i] != VCODE_INVALID_REG,
1,975✔
3395
                   "invalid argument to procedure");
3396

3397
   VCODE_ASSERT(nargs > 0 && vcode_reg_kind(args[0]) == VCODE_TYPE_CONTEXT,
777✔
3398
                "first argument to VHDL procedure must be context pointer");
3399
}
777✔
3400

3401
vcode_reg_t emit_alloc(vcode_type_t type, vcode_type_t bounds,
7,406✔
3402
                       vcode_reg_t count)
3403
{
3404
   op_t *op = vcode_add_op(VCODE_OP_ALLOC);
7,406✔
3405
   op->type    = type;
7,406✔
3406
   op->result  = vcode_add_reg(vtype_pointer(type));
7,406✔
3407
   vcode_add_arg(op, count);
7,406✔
3408

3409
   const vtype_kind_t tkind = vtype_kind(type);
7,406✔
3410
   VCODE_ASSERT(tkind != VCODE_TYPE_CARRAY && tkind != VCODE_TYPE_UARRAY,
7,406✔
3411
                "alloca element type cannot be array");
3412
   VCODE_ASSERT(count != VCODE_INVALID_REG,
7,406✔
3413
                "alloca must have valid count argument");
3414

3415
   reg_t *r = vcode_reg_data(op->result);
7,406✔
3416
   r->bounds = bounds;
7,406✔
3417

3418
   return op->result;
7,406✔
3419
}
3420

3421
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
926,228✔
3422
{
3423
   // Reuse any previous constant in this block with the same type and value
3424
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
19,985,133✔
3425
      if (other->value == value && vtype_eq(type, other->type))
7,495,788✔
3426
         return other->result;
544,115✔
3427
   }
3428

3429
   op_t *op = vcode_add_op(VCODE_OP_CONST);
382,113✔
3430
   op->value  = value;
382,113✔
3431
   op->type   = type;
382,113✔
3432
   op->result = vcode_add_reg(type);
382,113✔
3433

3434
   vtype_kind_t type_kind = vtype_kind(type);
382,113✔
3435
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
382,113✔
3436
                "constant must have integer or offset type");
3437

3438
   reg_t *r = vcode_reg_data(op->result);
382,113✔
3439
   r->bounds = vtype_int(value, value);
382,113✔
3440

3441
   return op->result;
382,113✔
3442
}
3443

3444
vcode_reg_t emit_const_real(vcode_type_t type, double value)
39,150✔
3445
{
3446
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REAL) {
1,431,825✔
3447
      if (other->real == value && other->type == type)
932,155✔
3448
         return other->result;
12,826✔
3449
   }
3450

3451
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
26,324✔
3452
   op->real   = value;
26,324✔
3453
   op->type   = type;
26,324✔
3454
   op->result = vcode_add_reg(op->type);
26,324✔
3455

3456
   reg_t *r = vcode_reg_data(op->result);
26,324✔
3457
   r->bounds = vtype_real(value, value);
26,324✔
3458

3459
   return op->result;
26,324✔
3460
}
3461

3462
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
26,361✔
3463
{
3464
   vtype_kind_t kind = vtype_kind(type);
26,361✔
3465

3466
   // Reuse any previous operation in this block with the same arguments
3467
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
1,125,963✔
3468
      if (other->args.count != num)
115,024✔
3469
         continue;
69,022✔
3470
      else if (!vtype_eq(vcode_reg_type(other->result), type))
46,002✔
3471
         continue;
580✔
3472

3473
      bool match = true;
3474
      for (int i = 0; match && i < num; i++) {
287,583✔
3475
         if (other->args.items[i] != values[i])
242,161✔
3476
            match = false;
39,417✔
3477
      }
3478

3479
      if (match) return other->result;
45,422✔
3480
   }
3481

3482
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
20,356✔
3483
   op->result = vcode_add_reg(type);
20,356✔
3484

3485
   for (int i = 0; i < num; i++)
1,159,222✔
3486
      vcode_add_arg(op, values[i]);
1,138,866✔
3487

3488
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
20,356✔
3489
                "constant array must have constrained array type");
3490
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
20,356✔
3491
                vtype_size(type), num);
3492

3493
#ifdef DEBUG
3494
   vcode_type_t elem = vtype_elem(type);
20,356✔
3495
   for (int i = 0; i < num; i++) {
1,159,222✔
3496
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
1,138,866✔
3497
                   "wrong element type for item %d", i);
3498
      vcode_assert_const(values[i], "array");
1,138,866✔
3499
   }
3500
#endif
3501

3502
   reg_t *r = vcode_reg_data(op->result);
20,356✔
3503
   r->bounds = vtype_elem(type);
20,356✔
3504

3505
   return op->result;
20,356✔
3506
}
3507

3508
vcode_reg_t emit_const_rep(vcode_type_t type, vcode_reg_t value, int rep)
1,031✔
3509
{
3510
   // Reuse any previous operation in this block with the same arguments
3511
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_REP) {
21,520✔
3512
      if (other->args.items[0] == value && other->value == rep)
1,005✔
3513
         return other->result;
291✔
3514
   }
3515

3516
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
740✔
3517
   op->value = rep;
740✔
3518
   vcode_add_arg(op, value);
740✔
3519

3520
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
740✔
3521
                "constant array must have constrained array type");
3522

3523
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
740✔
3524

3525
   op->result = vcode_add_reg(type);
740✔
3526

3527
   reg_t *r = vcode_reg_data(op->result);
740✔
3528
   r->bounds = vtype_bounds(type);
740✔
3529

3530
   return op->result;
740✔
3531
}
3532

3533
vcode_reg_t emit_const_record(vcode_type_t type, vcode_reg_t *values, int num)
2,716✔
3534
{
3535
   // Reuse any previous constant in this block with the same type and value
3536
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_RECORD) {
56,751✔
3537
      if (other->args.count == num && vtype_eq(type, other->type)) {
1,571✔
3538
         bool same_regs = true;
3539
         for (int i = 0; same_regs && i < num; i++)
2,336✔
3540
            same_regs = other->args.items[i] == values[i];
1,406✔
3541

3542
         if (same_regs)
930✔
3543
            return other->result;
217✔
3544
      }
3545
   }
3546

3547
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
2,499✔
3548
   op->type   = type;
2,499✔
3549
   op->result = vcode_add_reg(type);
2,499✔
3550

3551
   for (int i = 0; i < num; i++)
9,677✔
3552
      vcode_add_arg(op, values[i]);
7,178✔
3553

3554
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
2,499✔
3555
                "constant record must have record type");
3556

3557
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
2,499✔
3558
                vtype_fields(type), num);
3559

3560
#ifdef DEBUG
3561
   for (int i = 0; i < num; i++) {
9,677✔
3562
      VCODE_ASSERT(vtype_eq(vtype_field(type, i), vcode_reg_type(values[i])),
7,178✔
3563
                   "wrong type for field %d", i);
3564
      vcode_assert_const(values[i], "record");
7,178✔
3565
   }
3566
#endif
3567

3568
   return op->result;
2,499✔
3569
}
3570

3571
vcode_reg_t emit_address_of(vcode_reg_t value)
28,573✔
3572
{
3573
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
1,219,975✔
3574
      if (other->args.items[0] == value)
116,367✔
3575
         return other->result;
6,036✔
3576
   }
3577

3578
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
22,537✔
3579
   vcode_add_arg(op, value);
22,537✔
3580

3581
   vcode_type_t type = vcode_reg_type(value);
22,537✔
3582
   VCODE_ASSERT(vtype_is_composite(type),
22,537✔
3583
                "address of argument must be record or array");
3584

3585
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
22,537✔
3586
      vcode_type_t elem = vtype_elem(type);
20,536✔
3587
      op->result = vcode_add_reg(vtype_pointer(elem));
20,536✔
3588

3589
      reg_t *rr = vcode_reg_data(op->result);
20,536✔
3590
      rr->bounds = elem;
20,536✔
3591

3592
      return op->result;
20,536✔
3593
   }
3594
   else
3595
      return (op->result = vcode_add_reg(vtype_pointer(type)));
2,001✔
3596
}
3597

3598
void emit_wait(vcode_block_t target, vcode_reg_t time)
12,376✔
3599
{
3600
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
12,376✔
3601
   vcode_add_target(op, target);
12,376✔
3602
   vcode_add_arg(op, time);
12,376✔
3603

3604
   VCODE_ASSERT(time == VCODE_INVALID_REG
12,376✔
3605
                || vcode_reg_kind(time) == VCODE_TYPE_INT,
3606
                "wait time must have integer type");
3607
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_PROCEDURE
12,376✔
3608
                || active_unit->kind == VCODE_UNIT_PROCESS,
3609
                "wait only allowed in process or procedure");
3610
}
12,376✔
3611

3612
void emit_jump(vcode_block_t target)
33,296✔
3613
{
3614
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
33,296✔
3615
   vcode_add_target(op, target);
33,296✔
3616

3617
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
33,296✔
3618
}
33,296✔
3619

3620
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
45,850✔
3621
                     vcode_var_flags_t flags)
3622
{
3623
   assert(active_unit != NULL);
45,850✔
3624

3625
   vcode_var_t var = active_unit->vars.count;
45,850✔
3626
   var_t *v = var_array_alloc(&(active_unit->vars));
45,850✔
3627
   memset(v, '\0', sizeof(var_t));
45,850✔
3628
   v->type     = type;
45,850✔
3629
   v->bounds   = bounds;
45,850✔
3630
   v->name     = name;
45,850✔
3631
   v->flags    = flags;
45,850✔
3632

3633
   return var;
45,850✔
3634
}
3635

3636
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
30,255✔
3637
{
3638
   assert(active_unit != NULL);
30,255✔
3639

3640
   param_t *p = param_array_alloc(&(active_unit->params));
30,255✔
3641
   memset(p, '\0', sizeof(param_t));
30,255✔
3642
   p->type   = type;
30,255✔
3643
   p->bounds = bounds;
30,255✔
3644
   p->name   = name;
30,255✔
3645
   p->reg    = vcode_add_reg(type);
30,255✔
3646

3647
   reg_t *rr = vcode_reg_data(p->reg);
30,255✔
3648
   rr->bounds = bounds;
30,255✔
3649

3650
   return p->reg;
30,255✔
3651
}
3652

3653
vcode_reg_t emit_load(vcode_var_t var)
52,937✔
3654
{
3655
   // Try scanning backwards through the block for another load or store to
3656
   // this variable
3657
   enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER;
52,937✔
3658
   vcode_reg_t fold = VCODE_INVALID_REG;
52,937✔
3659
   VCODE_FOR_EACH_OP(other) {
616,622✔
3660
      switch (state) {
580,525✔
3661
      case EAGER:
317,141✔
3662
         if (other->kind == VCODE_OP_LOAD && other->address == var)
317,141✔
3663
            return other->result;
3,073✔
3664
         else if (other->kind == VCODE_OP_STORE && other->address == var)
314,068✔
3665
            return other->args.items[0];
13,767✔
3666
         else if (other->kind == VCODE_OP_FCALL
300,301✔
3667
                  || other->kind == VCODE_OP_PCALL
300,301✔
3668
                  || other->kind == VCODE_OP_FILE_READ
3669
                  || other->kind == VCODE_OP_FILE_OPEN
3670
                  || other->kind == VCODE_OP_STORE_INDIRECT
3671
                  || other->kind == VCODE_OP_DEALLOCATE)
3672
            state = CONSERVATIVE;   // May write to variable
7,663✔
3673
         break;
3674

3675
      case CONSERVATIVE:
239,386✔
3676
         if (other->kind == VCODE_OP_LOAD && other->address == var
239,386✔
3677
             && fold == VCODE_INVALID_REG)
4,304✔
3678
            fold = other->result;
3,457✔
3679
         else if (other->kind == VCODE_OP_STORE && other->address == var
235,929✔
3680
                  && fold == VCODE_INVALID_REG)
1,336✔
3681
            fold = other->args.items[0];
1,205✔
3682
         else if (other->kind == VCODE_OP_INDEX && other->address == var)
234,724✔
3683
            state = UNSAFE;
3684
         else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0)
233,763✔
3685
            state = UNSAFE;   // Nested call captures variables
80✔
3686
         break;
3687

3688
      case UNSAFE:
3689
         break;
3690
      }
3691
   }
3692

3693
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
36,097✔
3694
      return fold;
3695

3696
   var_t *v = vcode_var_data(var);
31,782✔
3697

3698
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
31,782✔
3699
   op->address = var;
31,782✔
3700
   op->result  = vcode_add_reg(v->type);
31,782✔
3701

3702
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot load non-scalar type");
31,782✔
3703

3704
   reg_t *r = vcode_reg_data(op->result);
31,782✔
3705
   r->bounds = v->bounds;
31,782✔
3706

3707
   return op->result;
31,782✔
3708
}
3709

3710
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
85,493✔
3711
{
3712
   VCODE_FOR_EACH_OP(other) {
1,024,143✔
3713
      if (other->kind == VCODE_OP_LOAD_INDIRECT
964,192✔
3714
          && other->args.items[0] == reg) {
138,498✔
3715
         return other->result;
6,861✔
3716
      }
3717
      else if (other->kind == VCODE_OP_FCALL
957,331✔
3718
               || other->kind == VCODE_OP_PCALL
957,331✔
3719
               || other->kind == VCODE_OP_STORE
3720
               || other->kind == VCODE_OP_STORE_INDIRECT
3721
               || other->kind == VCODE_OP_MEMSET
3722
               || other->kind == VCODE_OP_COPY
3723
               || other->kind == VCODE_OP_FILE_READ)
3724
         break;   // May write to this pointer
3725
   }
3726

3727
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
78,632✔
3728
   vcode_add_arg(op, reg);
78,632✔
3729

3730
   vcode_type_t rtype = vcode_reg_type(reg);
78,632✔
3731

3732
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
78,632✔
3733
                "load indirect with non-pointer argument");
3734

3735
   vcode_type_t deref = vtype_pointed(rtype);
78,632✔
3736
   op->result = vcode_add_reg(deref);
78,632✔
3737

3738
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
78,632✔
3739

3740
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
78,632✔
3741

3742
   return op->result;
78,632✔
3743
}
3744

3745
void emit_store(vcode_reg_t reg, vcode_var_t var)
56,187✔
3746
{
3747
   // Any previous store to this variable in this block is dead
3748
   VCODE_FOR_EACH_OP(other) {
1,088,407✔
3749
      if (other->kind == VCODE_OP_STORE && other->address == var) {
1,043,733✔
3750
         other->kind = VCODE_OP_COMMENT;
255✔
3751
         other->comment =
510✔
3752
            xasprintf("Dead store to %s", istr(vcode_var_name(var)));
255✔
3753
         vcode_reg_array_resize(&(other->args), 0, VCODE_INVALID_REG);
255✔
3754
      }
3755
      else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL)
1,043,478✔
3756
         break;   // Needs to get variable for display
3757
      else if ((other->kind == VCODE_OP_INDEX || other->kind == VCODE_OP_LOAD)
1,037,708✔
3758
               && other->address == var)
23,114✔
3759
         break;   // Previous value may be used
3760
   }
3761

3762
   var_t *v = vcode_var_data(var);
56,187✔
3763
   reg_t *r = vcode_reg_data(reg);
56,187✔
3764

3765
   op_t *op = vcode_add_op(VCODE_OP_STORE);
56,187✔
3766
   vcode_add_arg(op, reg);
56,187✔
3767
   op->address = var;
56,187✔
3768

3769
   VCODE_ASSERT(vtype_eq(v->type, r->type),
56,187✔
3770
                "variable and stored value do not have same type");
3771
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
56,187✔
3772
}
56,187✔
3773

3774
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
11,800✔
3775
{
3776
   reg_t *p = vcode_reg_data(ptr);
11,800✔
3777
   reg_t *r = vcode_reg_data(reg);
11,800✔
3778

3779
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
11,800✔
3780
   vcode_add_arg(op, reg);
11,800✔
3781
   vcode_add_arg(op, ptr);
11,800✔
3782

3783
   VCODE_ASSERT(vtype_kind(p->type) == VCODE_TYPE_POINTER,
11,800✔
3784
                "store indirect target is not a pointer");
3785
   VCODE_ASSERT(vtype_eq(vtype_pointed(p->type), r->type),
11,800✔
3786
                "pointer and stored value do not have same type");
3787
   VCODE_ASSERT(vtype_is_scalar(r->type), "cannot store non-scalar type");
11,800✔
3788
}
11,800✔
3789

3790
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
49,009✔
3791
                              vcode_reg_t locus)
3792
{
3793
   // Reuse any previous operation in this block with the same arguments
3794
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,042,320✔
3795
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
59,028✔
3796
         return other->result;
3,076✔
3797
   }
3798

3799
   op_t *op = vcode_add_op(kind);
45,933✔
3800
   vcode_add_arg(op, lhs);
45,933✔
3801
   vcode_add_arg(op, rhs);
45,933✔
3802
   if (locus != VCODE_INVALID_REG)
45,933✔
3803
      vcode_add_arg(op, locus);
4,887✔
3804

3805
   op->result = vcode_add_reg(vcode_reg_type(lhs));
45,933✔
3806

3807
   vcode_type_t lhs_type = vcode_reg_type(lhs);
45,933✔
3808
   vcode_type_t rhs_type = vcode_reg_type(rhs);
45,933✔
3809

3810
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
45,933✔
3811
                "arguments to %s are not the same type", vcode_op_string(kind));
3812

3813
   return op->result;
3814
}
3815

3816
static vcode_reg_t emit_mul_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
33,712✔
3817
                               vcode_reg_t locus)
3818
{
3819
   int64_t lconst, rconst;
33,712✔
3820
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
33,712✔
3821
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
33,712✔
3822
   if (l_is_const && r_is_const)
33,712✔
3823
      return emit_const(vcode_reg_type(lhs), lconst * rconst);
18,927✔
3824
   else if (r_is_const && rconst == 1)
14,785✔
3825
      return lhs;
3826
   else if (l_is_const && lconst == 1)
3,369✔
3827
      return rhs;
3828
   else if ((r_is_const && rconst == 0) || (l_is_const && lconst == 0))
2,941✔
3829
      return emit_const(vcode_reg_type(lhs), 0);
42✔
3830

3831
   reg_t *lhs_r = vcode_reg_data(lhs);
2,899✔
3832
   reg_t *rhs_r = vcode_reg_data(rhs);
2,899✔
3833

3834
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
2,899✔
3835
   vtype_t *br = vcode_type_data(rhs_r->bounds);
2,899✔
3836

3837
   vcode_type_t vbounds;
2,899✔
3838
   if (vcode_reg_kind(lhs) == VCODE_TYPE_REAL) {
2,899✔
3839
      const double ll = bl->rlow * br->rlow;
740✔
3840
      const double lh = bl->rlow * br->rhigh;
740✔
3841
      const double hl = bl->rhigh * br->rlow;
740✔
3842
      const double hh = bl->rhigh * br->rhigh;
740✔
3843

3844
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
1,596✔
3845
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
1,818✔
3846

3847
      vbounds = vtype_real(min, max);
740✔
3848
   }
3849
   else {
3850
      const int64_t ll = smul64(bl->low, br->low);
2,159✔
3851
      const int64_t lh = smul64(bl->low, br->high);
2,159✔
3852
      const int64_t hl = smul64(bl->high, br->low);
2,159✔
3853
      const int64_t hh = smul64(bl->high, br->high);
2,159✔
3854

3855
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
2,159✔
3856
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
2,159✔
3857

3858
      vtype_repr_t repr = vtype_repr(lhs_r->type);
2,159✔
3859
      if (op == VCODE_OP_TRAP_MUL && vtype_clamp_to_repr(repr, &min, &max)) {
2,159✔
3860
         op = VCODE_OP_MUL;   // Cannot overflow
379✔
3861
         locus = VCODE_INVALID_REG;
379✔
3862
      }
3863

3864
      vbounds = vtype_int(min, max);
2,159✔
3865
   }
3866

3867
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
2,899✔
3868

3869
   if (vbounds != VCODE_INVALID_TYPE)
2,899✔
3870
      vcode_reg_data(reg)->bounds = vbounds;
2,899✔
3871

3872
   return reg;
3873
}
3874

3875
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
32,866✔
3876
{
3877
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
32,866✔
3878
}
3879

3880
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
846✔
3881
{
3882
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
846✔
3883

3884
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
846✔
3885
                "trapping add may only be used with integer types");
3886

3887
   return result;
846✔
3888
}
3889

3890
vcode_reg_t emit_div(vcode_reg_t lhs, vcode_reg_t rhs)
1,001✔
3891
{
3892
   int64_t lconst, rconst;
1,001✔
3893
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
1,001✔
3894
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
1,001✔
3895
   if (l_is_const && r_is_const && rconst != 0)
1,001✔
3896
      return emit_const(vcode_reg_type(lhs), lconst / rconst);
32✔
3897
   else if (r_is_const && rconst == 1)
969✔
3898
      return lhs;
3899

3900
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
968✔
3901

3902
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
968✔
3903

3904
   if (bl->kind == VCODE_TYPE_INT && r_is_const && rconst != 0) {
968✔
3905
      reg_t *rr = vcode_reg_data(reg);
675✔
3906
      rr->bounds = vtype_int(bl->low / rconst, bl->high / rconst);
675✔
3907
   }
3908
   else if (bl->kind == VCODE_TYPE_REAL) {
293✔
3909
      reg_t *rr = vcode_reg_data(reg);
225✔
3910
      rr->bounds = vtype_real(-INFINITY, INFINITY);
225✔
3911
   }
3912

3913
   return reg;
3914
}
3915

3916
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
79✔
3917
{
3918
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
79✔
3919
}
3920

3921
vcode_reg_t emit_trap_exp(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
1,572✔
3922
{
3923
   int64_t rconst;
1,572✔
3924
   if (vcode_reg_const(rhs, &rconst)) {
1,572✔
3925
      if (rconst == 0)
1,463✔
3926
         return emit_const(vcode_reg_type(lhs), 1);
799✔
3927
      else if (rconst == 1)
664✔
3928
         return lhs;
3929
   }
3930

3931
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
580✔
3932

3933
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
580✔
3934
                "trapping exp may only be used with integer types");
3935

3936
   return result;
3937
}
3938

3939
vcode_reg_t emit_mod(vcode_reg_t lhs, vcode_reg_t rhs)
199✔
3940
{
3941
   int64_t lconst, rconst;
199✔
3942
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
199✔
3943
       && lconst > 0 && rconst > 0)
15✔
3944
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
3✔
3945

3946
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
196✔
3947
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
196✔
3948

3949
   if (bl->low >= 0 && br->low >= 0) {
196✔
3950
      // If both arguments are non-negative then rem is equivalent and
3951
      // cheaper to compute
3952
      vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
28✔
3953

3954
      reg_t *rr = vcode_reg_data(reg);
28✔
3955
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
28✔
3956

3957
      return reg;
28✔
3958
   }
3959
   else
3960
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
168✔
3961
}
3962

3963
vcode_reg_t emit_rem(vcode_reg_t lhs, vcode_reg_t rhs)
74✔
3964
{
3965
   int64_t lconst, rconst;
74✔
3966
   if (vcode_reg_const(lhs, &lconst) && vcode_reg_const(rhs, &rconst)
74✔
3967
       && lconst > 0 && rconst > 0)
2✔
3968
      return emit_const(vcode_reg_type(lhs), lconst % rconst);
×
3969

3970
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
74✔
3971

3972
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
74✔
3973
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
74✔
3974

3975
   if (bl->low >= 0 && br->low >= 0) {
74✔
3976
      reg_t *rr = vcode_reg_data(reg);
15✔
3977
      rr->bounds = vtype_int(0, br->high - 1);
15✔
3978
   }
3979

3980
   return reg;
3981
}
3982

3983
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
42,596✔
3984
                               vcode_reg_t locus)
3985
{
3986
   int64_t lconst, rconst;
42,596✔
3987
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
42,596✔
3988
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
42,596✔
3989
   if (l_is_const && r_is_const)
42,596✔
3990
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
17,226✔
3991
   else if (r_is_const && rconst == 0)
25,370✔
3992
      return lhs;
3993
   else if (l_is_const && lconst == 0)
25,364✔
3994
      return rhs;
3995

3996
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
15,697✔
3997
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
15,697✔
3998
      reg_t *lhs_r = vcode_reg_data(lhs);
15,410✔
3999
      reg_t *rhs_r = vcode_reg_data(rhs);
15,410✔
4000

4001
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
15,410✔
4002
      vtype_t *br = vcode_type_data(rhs_r->bounds);
15,410✔
4003

4004
      int64_t rbl = sadd64(bl->low, br->low);
15,410✔
4005
      int64_t rbh = sadd64(bl->high, br->high);
15,410✔
4006

4007
      vtype_repr_t repr = vtype_repr(lhs_r->type);
15,410✔
4008
      if (op == VCODE_OP_TRAP_ADD && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
15,410✔
4009
         op = VCODE_OP_ADD;   // Cannot overflow
752✔
4010
         locus = VCODE_INVALID_REG;
752✔
4011
      }
4012

4013
      vbounds = vtype_int(rbl, rbh);
15,410✔
4014
   }
4015

4016
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
15,697✔
4017

4018
   if (vbounds != VCODE_INVALID_TYPE)
15,697✔
4019
      vcode_reg_data(reg)->bounds = vbounds;
15,410✔
4020

4021
   return reg;
4022
}
4023

4024
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
39,811✔
4025
{
4026
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
39,811✔
4027
}
4028

4029
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
2,785✔
4030
{
4031
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
2,785✔
4032

4033
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
2,785✔
4034
                "trapping add may only be used with integer types");
4035

4036
   return result;
2,785✔
4037
}
4038

4039
static vcode_reg_t emit_sub_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
39,271✔
4040
                               vcode_reg_t locus)
4041
{
4042
   int64_t lconst, rconst;
39,271✔
4043
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
39,271✔
4044
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
39,271✔
4045
   if (l_is_const && r_is_const)
39,271✔
4046
      return emit_const(vcode_reg_type(lhs), lconst - rconst);
13,257✔
4047
   else if (r_is_const && rconst == 0)
26,014✔
4048
      return lhs;
4049
   else if (l_is_const && lconst == 0)
23,901✔
4050
      return emit_neg(rhs);
1,254✔
4051

4052
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
22,647✔
4053
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
22,647✔
4054
      reg_t *lhs_r = vcode_reg_data(lhs);
22,341✔
4055
      reg_t *rhs_r = vcode_reg_data(rhs);
22,341✔
4056

4057
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
22,341✔
4058
      vtype_t *br = vcode_type_data(rhs_r->bounds);
22,341✔
4059

4060
      int64_t rbl = ssub64(bl->low, br->high);
22,341✔
4061
      int64_t rbh = ssub64(bl->high, br->low);
22,341✔
4062

4063
      vtype_repr_t repr = vtype_repr(lhs_r->type);
22,341✔
4064
      if (op == VCODE_OP_TRAP_SUB && vtype_clamp_to_repr(repr, &rbl, &rbh)) {
22,341✔
4065
         op = VCODE_OP_SUB;   // Cannot overflow
2,966✔
4066
         locus = VCODE_INVALID_REG;
2,966✔
4067
      }
4068

4069
      vbounds = vtype_int(rbl, rbh);
22,341✔
4070
   }
4071

4072
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
22,647✔
4073

4074
   if (vbounds != VCODE_INVALID_TYPE)
22,647✔
4075
      vcode_reg_data(reg)->bounds = vbounds;
22,341✔
4076

4077
   return reg;
4078
}
4079

4080
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
32,657✔
4081
{
4082
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
32,657✔
4083
}
4084

4085
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
6,614✔
4086
{
4087
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
6,614✔
4088

4089
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
6,614✔
4090
                "trapping sub may only be used with integer types");
4091

4092
   return result;
6,614✔
4093
}
4094

4095
static void vcode_calculate_var_index_type(op_t *op, var_t *var)
55,783✔
4096
{
4097
   switch (vtype_kind(var->type)) {
55,783✔
4098
   case VCODE_TYPE_CARRAY:
11,448✔
4099
      op->type = vtype_pointer(vtype_elem(var->type));
11,448✔
4100
      op->result = vcode_add_reg(op->type);
11,448✔
4101
      vcode_reg_data(op->result)->bounds = vtype_bounds(var->type);
11,448✔
4102
      break;
11,448✔
4103

4104
   case VCODE_TYPE_RECORD:
5,968✔
4105
      op->type = vtype_pointer(var->type);
5,968✔
4106
      op->result = vcode_add_reg(op->type);
5,968✔
4107
      break;
5,968✔
4108

4109
   case VCODE_TYPE_INT:
38,367✔
4110
   case VCODE_TYPE_FILE:
4111
   case VCODE_TYPE_ACCESS:
4112
   case VCODE_TYPE_REAL:
4113
   case VCODE_TYPE_UARRAY:
4114
   case VCODE_TYPE_POINTER:
4115
   case VCODE_TYPE_SIGNAL:
4116
   case VCODE_TYPE_CONTEXT:
4117
   case VCODE_TYPE_OFFSET:
4118
   case VCODE_TYPE_TRIGGER:
4119
      op->type = vtype_pointer(var->type);
38,367✔
4120
      op->result = vcode_add_reg(op->type);
38,367✔
4121
      vcode_reg_data(op->result)->bounds = var->bounds;
38,367✔
4122
      break;
38,367✔
4123

4124
   default:
4125
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4126
                   istr(var->name));
4127
   }
4128
}
55,783✔
4129

4130
vcode_reg_t emit_index(vcode_var_t var, vcode_reg_t offset)
21,435✔
4131
{
4132
   // Try to find a previous index of this var by this offset
4133
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_INDEX) {
738,578✔
4134
      if (other->address == var
46,498✔
4135
          && ((offset == VCODE_INVALID_REG && other->args.count == 0)
6,937✔
4136
              || (offset != VCODE_INVALID_REG
×
4137
                  && other->args.items[0] == offset)))
×
4138
         return other->result;
6,937✔
4139
   }
4140

4141
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
14,498✔
4142
   op->address = var;
14,498✔
4143

4144
   if (offset != VCODE_INVALID_REG)
14,498✔
4145
      vcode_add_arg(op, offset);
×
4146

4147
   vcode_calculate_var_index_type(op, vcode_var_data(var));
14,498✔
4148

4149
   if (offset != VCODE_INVALID_REG)
14,498✔
4150
      VCODE_ASSERT(vtype_kind(vcode_reg_type(offset)) == VCODE_TYPE_OFFSET,
×
4151
                   "index offset r%d does not have offset type", offset);
4152

4153
   return op->result;
14,498✔
4154
}
4155

4156
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
202,342✔
4157
{
4158
   if (vtype_eq(vcode_reg_type(reg), type))
202,342✔
4159
      return reg;
202,342✔
4160

4161
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
75,959✔
4162
   vtype_kind_t to   = vtype_kind(type);
75,959✔
4163

4164
   const bool integral =
151,918✔
4165
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
75,959✔
4166
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
75,959✔
4167

4168
   int64_t value;
75,959✔
4169
   if (integral && vcode_reg_const(reg, &value))
75,959✔
4170
      return emit_const(type, value);
14,399✔
4171

4172
   // Try to find a previous cast of this register to this type
4173
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CAST) {
1,211,321✔
4174
      if (vtype_eq(other->type, type) && other->args.items[0] == reg)
137,012✔
4175
         return other->result;
14,517✔
4176
   }
4177

4178
   op_t *op = vcode_add_op(VCODE_OP_CAST);
47,043✔
4179
   vcode_add_arg(op, reg);
47,043✔
4180
   op->type   = type;
47,043✔
4181
   op->result = vcode_add_reg(type);
47,043✔
4182

4183
   static const vcode_type_t allowed[][2] = {
47,043✔
4184
      { VCODE_TYPE_INT,    VCODE_TYPE_OFFSET  },
4185
      { VCODE_TYPE_OFFSET, VCODE_TYPE_INT     },
4186
      { VCODE_TYPE_INT,    VCODE_TYPE_INT     },
4187
      { VCODE_TYPE_INT,    VCODE_TYPE_REAL    },
4188
      { VCODE_TYPE_REAL,   VCODE_TYPE_INT     },
4189
      { VCODE_TYPE_REAL,   VCODE_TYPE_REAL    },
4190
      { VCODE_TYPE_ACCESS, VCODE_TYPE_ACCESS  },
4191
   };
4192

4193
   if (from == VCODE_TYPE_INT && bounds == VCODE_INVALID_TYPE) {
47,043✔
4194
      reg_t *rr = vcode_reg_data(op->result);
9,984✔
4195
      rr->bounds = vcode_reg_bounds(reg);
9,984✔
4196
   }
4197
   else if (to == VCODE_TYPE_INT && bounds != VCODE_INVALID_TYPE) {
37,059✔
4198
      reg_t *rr = vcode_reg_data(op->result);
30,651✔
4199
      rr->bounds = bounds;
30,651✔
4200
   }
4201

4202
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
86,029✔
4203
      if (from == allowed[i][0] && to == allowed[i][1])
86,029✔
4204
         return op->result;
4205
   }
4206

4207
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4208
}
4209

4210
void emit_return(vcode_reg_t reg)
50,181✔
4211
{
4212
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
50,181✔
4213
   if (reg != VCODE_INVALID_REG) {
50,181✔
4214
      vcode_add_arg(op, reg);
27,785✔
4215

4216
      const vtype_kind_t rkind = vcode_reg_kind(reg);
27,785✔
4217
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
27,785✔
4218
         vcode_heap_allocate(reg);
8,169✔
4219
         active_unit->flags |= UNIT_ESCAPING_TLAB;
8,169✔
4220
      }
4221

4222
      VCODE_ASSERT(active_unit->kind == VCODE_UNIT_FUNCTION
27,785✔
4223
                   || active_unit->kind == VCODE_UNIT_THUNK
4224
                   || active_unit->kind == VCODE_UNIT_PROPERTY,
4225
                   "returning value fron non-function unit");
4226
      VCODE_ASSERT((active_unit->kind == VCODE_UNIT_PROPERTY
27,785✔
4227
                    && rkind == VCODE_TYPE_INT)
4228
                   || vtype_eq(active_unit->result, vcode_reg_type(reg))
4229
                   || (vtype_kind(active_unit->result) == VCODE_TYPE_ACCESS
4230
                       && rkind == VCODE_TYPE_ACCESS),
4231
                   "return value incorrect type");
4232
   }
4233
}
50,181✔
4234

4235
void emit_sched_waveform(vcode_reg_t nets, vcode_reg_t nnets,
9,819✔
4236
                         vcode_reg_t values, vcode_reg_t reject,
4237
                         vcode_reg_t after)
4238
{
4239
   int64_t nconst;
9,819✔
4240
   if (vcode_reg_const(nnets, &nconst) && nconst == 0) {
9,819✔
4241
      emit_comment("Skip empty waveform");
6✔
4242
      return;
6✔
4243
   }
4244

4245
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
9,813✔
4246
   vcode_add_arg(op, nets);
9,813✔
4247
   vcode_add_arg(op, nnets);
9,813✔
4248
   vcode_add_arg(op, values);
9,813✔
4249
   vcode_add_arg(op, reject);
9,813✔
4250
   vcode_add_arg(op, after);
9,813✔
4251

4252
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
9,813✔
4253
                "sched_waveform target is not signal");
4254
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
9,813✔
4255
                "sched_waveform net count is not offset type");
4256
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
9,813✔
4257
                "signal cannot be values argument for sched_waveform");
4258
}
4259

4260
void emit_force(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t values)
54✔
4261
{
4262
   op_t *op = vcode_add_op(VCODE_OP_FORCE);
54✔
4263
   vcode_add_arg(op, nets);
54✔
4264
   vcode_add_arg(op, nnets);
54✔
4265
   vcode_add_arg(op, values);
54✔
4266

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

4273
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
30✔
4274
{
4275
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
30✔
4276
   vcode_add_arg(op, nets);
30✔
4277
   vcode_add_arg(op, nnets);
30✔
4278

4279
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
30✔
4280
                "release target is not signal");
4281
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
30✔
4282
                "release net count is not offset type");
4283
}
30✔
4284

4285
void emit_disconnect(vcode_reg_t nets, vcode_reg_t nnets, vcode_reg_t reject,
21✔
4286
                     vcode_reg_t after)
4287
{
4288
   op_t *op = vcode_add_op(VCODE_OP_DISCONNECT);
21✔
4289
   vcode_add_arg(op, nets);
21✔
4290
   vcode_add_arg(op, nnets);
21✔
4291
   vcode_add_arg(op, reject);
21✔
4292
   vcode_add_arg(op, after);
21✔
4293

4294
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
21✔
4295
                "disconnect target is not signal");
4296
   VCODE_ASSERT(vcode_reg_kind(nnets) == VCODE_TYPE_OFFSET,
21✔
4297
                "disconnect net count is not offset type");
4298
}
21✔
4299

4300
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
34,575✔
4301
{
4302
   int64_t tconst;
34,575✔
4303
   if (vcode_reg_const(test, &tconst)) {
34,575✔
4304
      emit_jump(!!tconst ? btrue : bfalse);
4,573✔
4305
      return;
2,719✔
4306
   }
4307

4308
   op_t *op = vcode_add_op(VCODE_OP_COND);
31,856✔
4309
   vcode_add_arg(op, test);
31,856✔
4310
   vcode_add_target(op, btrue);
31,856✔
4311
   vcode_add_target(op, bfalse);
31,856✔
4312

4313
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
31,856✔
4314
                "cond test is not a bool");
4315
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
31,856✔
4316
                "invalid cond targets");
4317
}
4318

4319
vcode_reg_t emit_neg(vcode_reg_t lhs)
7,433✔
4320
{
4321
   int64_t lconst;
7,433✔
4322
   if (vcode_reg_const(lhs, &lconst))
7,433✔
4323
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4324

4325
   op_t *op = vcode_add_op(VCODE_OP_NEG);
7,433✔
4326
   vcode_add_arg(op, lhs);
7,433✔
4327
   op->result = vcode_add_reg(vcode_reg_type(lhs));
7,433✔
4328

4329
   return op->result;
7,433✔
4330
}
4331

4332
vcode_reg_t emit_trap_neg(vcode_reg_t lhs, vcode_reg_t locus)
785✔
4333
{
4334
   int64_t lconst;
785✔
4335
   if (vcode_reg_const(lhs, &lconst) && lconst >= 0)
785✔
4336
      return emit_const(vcode_reg_type(lhs), -lconst);
×
4337
   else if (vcode_type_data(vcode_reg_data(lhs)->bounds)->low >= 0)
785✔
4338
      return emit_neg(lhs);   // Cannot overflow
222✔
4339

4340
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
563✔
4341
   vcode_add_arg(op, lhs);
563✔
4342
   vcode_add_arg(op, locus);
563✔
4343

4344
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
563✔
4345
                "locus argument to trap neg must be a debug locus");
4346
   VCODE_ASSERT(vcode_reg_kind(lhs) == VCODE_TYPE_INT,
563✔
4347
                "trapping neg may only be used with integer types");
4348

4349
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
563✔
4350
}
4351

4352
vcode_reg_t emit_abs(vcode_reg_t lhs)
245✔
4353
{
4354
   int64_t lconst;
245✔
4355
   if (vcode_reg_const(lhs, &lconst))
245✔
4356
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4357

4358
   op_t *op = vcode_add_op(VCODE_OP_ABS);
244✔
4359
   vcode_add_arg(op, lhs);
244✔
4360
   op->result = vcode_add_reg(vcode_reg_type(lhs));
244✔
4361

4362
   return op->result;
244✔
4363
}
4364

4365
void emit_comment(const char *fmt, ...)
42,059✔
4366
{
4367
#ifndef NDEBUG
4368
   va_list ap;
42,059✔
4369
   va_start(ap, fmt);
42,059✔
4370

4371
   char *buf = xvasprintf(fmt, ap);
42,059✔
4372
   for (char *p = buf + strlen(buf) - 1;
42,059✔
4373
        p >= buf && isspace_iso88591(*p); p--)
42,059✔
4374
      *p = '\0';
×
4375

4376
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
42,059✔
4377
   va_end(ap);
42,059✔
4378
#endif
4379
}
42,059✔
4380

4381
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
18,665✔
4382
                        vcode_reg_t rfalse)
4383
{
4384
   int64_t tconst;
18,665✔
4385
   if (vcode_reg_const(test, &tconst))
18,665✔
4386
      return !!tconst ? rtrue : rfalse;
4,252✔
4387
   else if (rtrue == rfalse)
14,413✔
4388
      return rtrue;
4389

4390
   // Find a previous identical select
4391
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
312,272✔
4392
      if (other->args.items[0] == test && other->args.items[1] == rtrue
13,024✔
4393
          && other->args.items[2] == rfalse)
714✔
4394
         return other->result;
659✔
4395
   }
4396

4397
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
13,515✔
4398
   vcode_add_arg(op, test);
13,515✔
4399
   vcode_add_arg(op, rtrue);
13,515✔
4400
   vcode_add_arg(op, rfalse);
13,515✔
4401
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
13,515✔
4402

4403
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
13,515✔
4404
                "select test must have bool type");
4405
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
13,515✔
4406
                "select arguments are not the same type");
4407

4408
   return op->result;
13,515✔
4409
}
4410

4411
static vcode_reg_t emit_logical_identity(vcode_op_t op, vcode_reg_t reg, bool b)
91✔
4412
{
4413
   switch (op) {
91✔
4414
   case VCODE_OP_AND:  return b ? reg : emit_const(vtype_bool(), 0);
24✔
4415
   case VCODE_OP_OR:   return b ? emit_const(vtype_bool(), 1) : reg;
19✔
4416
   case VCODE_OP_XOR:  return b ? emit_not(reg) : reg;
12✔
4417
   case VCODE_OP_XNOR: return b ? reg : emit_not(reg);
12✔
4418
   case VCODE_OP_NAND: return b ? emit_not(reg) : emit_const(vtype_bool(), 1);
12✔
4419
   case VCODE_OP_NOR:  return b ? emit_const(vtype_bool(), 0) : emit_not(reg);
12✔
4420
   default:
×
4421
      fatal_trace("missing logicial identity for %s", vcode_op_string(op));
×
4422
   }
4423
}
4424

4425
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
5,981✔
4426
{
4427
   vcode_type_t vtbool = vtype_bool();
5,981✔
4428

4429
   int64_t lconst, rconst;
5,981✔
4430
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
5,981✔
4431
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
5,981✔
4432
   if (l_is_const && r_is_const) {
5,981✔
4433
      switch (op) {
6✔
4434
      case VCODE_OP_AND:  return emit_const(vtbool, lconst && rconst);
×
4435
      case VCODE_OP_OR:   return emit_const(vtbool, lconst || rconst);
×
4436
      case VCODE_OP_XOR:  return emit_const(vtbool, lconst ^ rconst);
×
4437
      case VCODE_OP_XNOR: return emit_const(vtbool, !(lconst ^ rconst));
6✔
4438
      case VCODE_OP_NAND: return emit_const(vtbool, !(lconst && rconst));
×
4439
      case VCODE_OP_NOR:  return emit_const(vtbool, !(lconst || rconst));
×
4440
      default:
×
4441
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
×
4442
      }
4443
   }
4444
   else if (l_is_const)
5,975✔
4445
      return emit_logical_identity(op, rhs, !!lconst);
12✔
4446
   else if (r_is_const)
5,963✔
4447
      return emit_logical_identity(op, lhs, !!rconst);
79✔
4448
   else if (lhs == rhs) {
5,884✔
4449
      switch (op) {
15✔
4450
      case VCODE_OP_AND:
4451
      case VCODE_OP_OR:
4452
         return lhs;
4453
      case VCODE_OP_NAND:
6✔
4454
      case VCODE_OP_NOR:
4455
         return emit_not(lhs);
6✔
4456
      case VCODE_OP_XOR:
3✔
4457
         return emit_const(vtbool, 0);
3✔
4458
      case VCODE_OP_XNOR:
×
4459
         return emit_const(vtbool, 1);
×
4460
      default:
×
4461
         fatal_trace("cannot constant fold logical %s", vcode_op_string(op));
×
4462
      }
4463
   }
4464

4465
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
5,869✔
4466

4467
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
5,869✔
4468
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4469
                "arguments to %s are not boolean", vcode_op_string(op));
4470

4471
   return result;
4472
}
4473

4474
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
1,525✔
4475
{
4476
   return emit_logical(VCODE_OP_OR, lhs, rhs);
1,525✔
4477
}
4478

4479
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
4,088✔
4480
{
4481
   return emit_logical(VCODE_OP_AND, lhs, rhs);
4,088✔
4482
}
4483

4484
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
80✔
4485
{
4486
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
80✔
4487
}
4488

4489
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
81✔
4490
{
4491
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
81✔
4492
}
4493

4494
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
122✔
4495
{
4496
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
122✔
4497
}
4498

4499
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
85✔
4500
{
4501
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
85✔
4502
}
4503

4504
vcode_reg_t emit_not(vcode_reg_t arg)
2,055✔
4505
{
4506
   int64_t cval;
2,055✔
4507
   if (vcode_reg_const(arg, &cval))
2,055✔
4508
      return emit_const(vtype_bool(), !cval);
27✔
4509

4510
   op_t *op = vcode_add_op(VCODE_OP_NOT);
2,028✔
4511
   vcode_add_arg(op, arg);
2,028✔
4512

4513
   vcode_type_t vtbool = vtype_bool();
2,028✔
4514
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
2,028✔
4515
                "argument to not is not boolean");
4516

4517
   return (op->result = vcode_add_reg(vtbool));
2,028✔
4518
}
4519

4520
vcode_reg_t emit_wrap(vcode_reg_t data, const vcode_dim_t *dims, int ndims)
45,690✔
4521
{
4522
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_WRAP) {
1,519,905✔
4523
      if (other->args.count == ndims*3 + 1 && other->args.items[0] == data) {
142,787✔
4524
         bool match = true;
4525
         for (int i = 0; match && i < ndims; i++) {
20,402✔
4526
            match = other->args.items[i*3 + 1] == dims[i].left
10,221✔
4527
               && other->args.items[i*3 + 2] == dims[i].right
8,897✔
4528
               && other->args.items[i*3 + 3] == dims[i].dir;
18,982✔
4529
         }
4530
         if (match)
10,181✔
4531
            return other->result;
8,721✔
4532
      }
4533
   }
4534

4535
   op_t *op = vcode_add_op(VCODE_OP_WRAP);
36,969✔
4536
   vcode_add_arg(op, data);
36,969✔
4537
   for (int i = 0; i < ndims; i++) {
74,367✔
4538
      vcode_add_arg(op, dims[i].left);
37,398✔
4539
      vcode_add_arg(op, dims[i].right);
37,398✔
4540
      vcode_add_arg(op, dims[i].dir);
37,398✔
4541
   }
4542

4543
   vcode_type_t ptr_type = vcode_reg_type(data);
36,969✔
4544
   const vtype_kind_t ptrkind = vtype_kind(ptr_type);
36,969✔
4545
   VCODE_ASSERT(ptrkind == VCODE_TYPE_POINTER || ptrkind == VCODE_TYPE_SIGNAL,
36,969✔
4546
                "wrapped data is not pointer or signal");
4547

4548
#ifdef DEBUG
4549
   for (int i = 0; i < ndims; i++) {
74,367✔
4550
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].left)),
37,398✔
4551
                   "dimension %d left bound must be scalar", i + 1);
4552
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(dims[i].right)),
37,398✔
4553
                   "dimension %d right bound must be scalar", i + 1);
4554
      VCODE_ASSERT(vtype_eq(vtype_bool(), vcode_reg_type(dims[i].dir)),
37,398✔
4555
                   "dimension %d direction must be bool", i + 1);
4556
   }
4557
#endif
4558

4559
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
73,938✔
4560
      ? vtype_pointed(ptr_type) : ptr_type;
36,969✔
4561

4562
   op->result = vcode_add_reg(
36,969✔
4563
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4564

4565
   return op->result;
36,969✔
4566
}
4567

4568
static vcode_reg_t emit_uarray_op(vcode_op_t o, vcode_type_t rtype,
107,521✔
4569
                                  vcode_reg_t array, unsigned dim,
4570
                                  unsigned arg_index)
4571
{
4572
   // Reuse any previous operation in this block with the same arguments
4573
   VCODE_FOR_EACH_OP(other) {
1,163,115✔
4574
      if (other->kind == o && other->args.items[0] == array && other->dim == dim
1,113,618✔
4575
          && (rtype == VCODE_INVALID_TYPE
22,727✔
4576
              || vtype_eq(rtype, vcode_reg_type(other->result))))
9,536✔
4577
         return other->result;
22,727✔
4578
      else if (other->kind == VCODE_OP_WRAP && other->result == array)
1,090,891✔
4579
         return other->args.items[1 + (dim * 3) + arg_index];
35,297✔
4580
   }
4581

4582
   op_t *op = vcode_add_op(o);
49,497✔
4583
   vcode_add_arg(op, array);
49,497✔
4584
   op->dim = dim;
49,497✔
4585

4586
   vcode_type_t atype = vcode_reg_type(array);
49,497✔
4587
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
49,497✔
4588
                "cannot use %s with non-uarray type", vcode_op_string(o));
4589

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

4593
   if (rtype == VCODE_INVALID_TYPE)
49,497✔
4594
      rtype = vtype_offset();
32,232✔
4595

4596
   return (op->result = vcode_add_reg(rtype));
49,497✔
4597
}
4598

4599
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
38,927✔
4600
{
4601
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
38,927✔
4602
                         array, dim, 0);
4603
}
4604

4605
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
29,986✔
4606
{
4607
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
29,986✔
4608
                         array, dim, 1);
4609
}
4610

4611
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
38,608✔
4612
{
4613
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
38,608✔
4614
                         array, dim, 2);
4615
}
4616

4617
vcode_reg_t emit_uarray_len(vcode_reg_t array, unsigned dim)
49,205✔
4618
{
4619
   VCODE_FOR_EACH_OP(other) {
518,067✔
4620
      if (other->kind == VCODE_OP_UARRAY_LEN) {
494,234✔
4621
         if (other->args.items[0] == array && other->dim == dim)
34,439✔
4622
            return other->result;
10,953✔
4623
      }
4624
      else if (other->kind == VCODE_OP_WRAP && other->result == array) {
459,795✔
4625
         VCODE_ASSERT(dim < (other->args.count - 1) / 3,
14,419✔
4626
                      "array dimension %d out of bounds", dim);
4627

4628
         vcode_reg_t left_reg = other->args.items[dim * 3 + 1];
14,419✔
4629
         vcode_reg_t right_reg = other->args.items[dim * 3 + 2];
14,419✔
4630
         vcode_reg_t dir_reg = other->args.items[dim * 3 + 3];
14,419✔
4631
         return emit_range_length(left_reg, right_reg, dir_reg);
14,419✔
4632
      }
4633
   }
4634

4635
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
23,833✔
4636
   vcode_add_arg(op, array);
23,833✔
4637
   op->dim = dim;
23,833✔
4638

4639
   vcode_type_t atype = vcode_reg_type(array);
23,833✔
4640
   VCODE_ASSERT(vtype_kind(atype) == VCODE_TYPE_UARRAY,
23,833✔
4641
                "cannot use uarray len with non-uarray type");
4642

4643
   vtype_t *vt = vcode_type_data(atype);
23,833✔
4644
   VCODE_ASSERT(dim < vt->dims, "invalid dimension %d", dim);
23,833✔
4645

4646
   return (op->result = vcode_add_reg(vtype_offset()));
23,833✔
4647
}
4648

4649
vcode_reg_t emit_unwrap(vcode_reg_t array)
37,360✔
4650
{
4651
   VCODE_FOR_EACH_OP(other) {
1,521,626✔
4652
      if (other->kind == VCODE_OP_WRAP && other->result == array)
1,495,163✔
4653
         return other->args.items[0];
9,438✔
4654
      else if (other->kind == VCODE_OP_UNWRAP && other->args.items[0] == array)
1,485,725✔
4655
         return other->result;
1,459✔
4656
   }
4657

4658
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
26,463✔
4659
   vcode_add_arg(op, array);
26,463✔
4660

4661
   vtype_t *vt = vcode_type_data(vcode_reg_type(array));
26,463✔
4662
   VCODE_ASSERT(vt->kind == VCODE_TYPE_UARRAY,
26,463✔
4663
                "unwrap can only only be used with uarray types");
4664

4665
   vcode_type_t elem = vt->elem;
26,463✔
4666

4667
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
26,463✔
4668
      ? elem : vtype_pointer(elem);
26,463✔
4669

4670
   op->result = vcode_add_reg(rtype);
26,463✔
4671

4672
   reg_t *rr = vcode_reg_data(op->result);
26,463✔
4673
   rr->bounds = elem;
26,463✔
4674

4675
   return op->result;
26,463✔
4676
}
4677

4678
vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right,
16,945✔
4679
                            vcode_reg_t dir)
4680
{
4681
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_NULL) {
516,846✔
4682
      if (other->args.items[0] == left
×
4683
          && other->args.items[1] == right
×
4684
          && other->args.items[2] == dir)
×
4685
         return other->result;
×
4686
   }
4687

4688
   int64_t dir_const;
16,945✔
4689
   if (vcode_reg_const(dir, &dir_const)) {
16,945✔
4690
      vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
12,245✔
4691
      vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
12,245✔
4692

4693
      if (dir_const == RANGE_TO && lbounds->low > rbounds->high)
12,245✔
4694
         return emit_const(vtype_bool(), 1);
38✔
4695
      else if (dir_const == RANGE_TO && lbounds->high <= rbounds->low)
12,207✔
4696
         return emit_const(vtype_bool(), 0);
5,784✔
4697
      else if (dir_const == RANGE_DOWNTO && rbounds->low > lbounds->high)
6,423✔
4698
         return emit_const(vtype_bool(), 1);
92✔
4699
      else if (dir_const == RANGE_DOWNTO && rbounds->high <= lbounds->low)
6,331✔
4700
         return emit_const(vtype_bool(), 0);
1,505✔
4701
      else if (dir_const == RANGE_TO)
4,826✔
4702
         return emit_cmp(VCODE_CMP_GT, left, right);
1,456✔
4703
      else
4704
         return emit_cmp(VCODE_CMP_GT, right, left);
3,370✔
4705
   }
4706

4707
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
4,700✔
4708
   vcode_add_arg(op, left);
4,700✔
4709
   vcode_add_arg(op, right);
4,700✔
4710
   vcode_add_arg(op, dir);
4,700✔
4711

4712
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
4,700✔
4713
                "range left and right have different types");
4714
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
4,700✔
4715
                "dir argument to range length is not int");
4716

4717
   return (op->result = vcode_add_reg(vtype_bool()));
4,700✔
4718
}
4719

4720
vcode_reg_t emit_range_length(vcode_reg_t left, vcode_reg_t right,
14,453✔
4721
                              vcode_reg_t dir)
4722
{
4723
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RANGE_LENGTH) {
351,359✔
4724
      if (other->args.items[0] == left
6,045✔
4725
          && other->args.items[1] == right
4,759✔
4726
          && other->args.items[2] == dir)
4,472✔
4727
         return other->result;
4,472✔
4728
   }
4729

4730
   int64_t lconst, rconst, dconst;
9,981✔
4731
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
9,981✔
4732
       && vcode_reg_const(right, &rconst)) {
5,637✔
4733

4734
      int64_t diff;
3,690✔
4735
      if (dconst == RANGE_TO)
3,690✔
4736
         diff = rconst - lconst;
3,444✔
4737
      else
4738
         diff = lconst - rconst;
246✔
4739

4740
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
3,690✔
4741
   }
4742

4743
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
6,291✔
4744
   vcode_add_arg(op, left);
6,291✔
4745
   vcode_add_arg(op, right);
6,291✔
4746
   vcode_add_arg(op, dir);
6,291✔
4747

4748
   VCODE_ASSERT(vtype_eq(vcode_reg_type(left), vcode_reg_type(right)),
6,291✔
4749
                "range left and right have different types");
4750
   VCODE_ASSERT(vcode_reg_kind(dir) == VCODE_TYPE_INT,
6,291✔
4751
                "dir argument to range length is not int");
4752

4753
   return (op->result = vcode_add_reg(vtype_offset()));
6,291✔
4754
}
4755

4756
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
48,515✔
4757
{
4758
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
436,229✔
4759
      if (other->hops == hops && other->address == var)
59,023✔
4760
         return other->result;
7,230✔
4761
   }
4762

4763
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
41,285✔
4764
   op->hops    = hops;
41,285✔
4765
   op->address = var;
41,285✔
4766

4767
   VCODE_ASSERT(hops > 0, "invalid hop count");
41,285✔
4768

4769
   vcode_unit_t vu = active_unit;
41,285✔
4770
   for (int i = 0; i < hops; i++) {
93,017✔
4771
      vu = vu->context;
51,732✔
4772
      VCODE_ASSERT(vu, "hop count is greater than depth");
51,732✔
4773
   }
4774

4775
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
41,285✔
4776

4777
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
41,285✔
4778

4779
   return op->result;
41,285✔
4780
}
4781

4782
vcode_reg_t emit_init_signal(vcode_type_t type, vcode_reg_t count,
10,914✔
4783
                             vcode_reg_t size, vcode_reg_t value,
4784
                             vcode_reg_t flags, vcode_reg_t locus,
4785
                             vcode_reg_t offset)
4786
{
4787
   op_t *op = vcode_add_op(VCODE_OP_INIT_SIGNAL);
10,914✔
4788
   vcode_add_arg(op, count);
10,914✔
4789
   vcode_add_arg(op, size);
10,914✔
4790
   vcode_add_arg(op, value);
10,914✔
4791
   vcode_add_arg(op, flags);
10,914✔
4792
   vcode_add_arg(op, locus);
10,914✔
4793
   if (offset != VCODE_INVALID_REG)
10,914✔
4794
      vcode_add_arg(op, offset);
4,283✔
4795

4796
   vcode_type_t vtype = vcode_reg_type(value);
10,914✔
4797
   VCODE_ASSERT(vtype_is_scalar(type), "signal type must be scalar");
10,914✔
4798
   VCODE_ASSERT(vtype_eq(vtype, type)
10,914✔
4799
                || vtype_kind(vtype) == VCODE_TYPE_POINTER,
4800
                "init signal value type does not match signal type");
4801
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
10,914✔
4802
                "locus argument to init signal must be a debug locus");
4803
   VCODE_ASSERT(offset == VCODE_INVALID_REG
10,914✔
4804
                || vcode_reg_kind(offset) == VCODE_TYPE_POINTER,
4805
                "init signal offset argument must have pointer type");
4806

4807
   return (op->result = vcode_add_reg(vtype_signal(type)));
10,914✔
4808
}
4809

4810
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
2,854✔
4811
{
4812
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
2,854✔
4813
   vcode_add_arg(op, signal);
2,854✔
4814
   vcode_add_arg(op, resolution);
2,854✔
4815

4816
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
2,854✔
4817
                "signal argument has wrong type");
4818
   VCODE_ASSERT(vcode_reg_kind(resolution) == VCODE_TYPE_RESOLUTION,
2,854✔
4819
                "resolution wrapper argument has wrong type");
4820
}
2,854✔
4821

4822
vcode_reg_t emit_implicit_signal(vcode_type_t type, vcode_reg_t count,
30✔
4823
                                 vcode_reg_t size, vcode_reg_t locus,
4824
                                 vcode_reg_t kind, vcode_reg_t closure)
4825
{
4826
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_SIGNAL);
30✔
4827
   vcode_add_arg(op, count);
30✔
4828
   vcode_add_arg(op, size);
30✔
4829
   vcode_add_arg(op, locus);
30✔
4830
   vcode_add_arg(op, kind);
30✔
4831
   vcode_add_arg(op, closure);
30✔
4832

4833
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
30✔
4834
                "count argument to implicit signal is not offset");
4835
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
30✔
4836
                "kind argument to implicit signal is not offset");
4837
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
30✔
4838
                "closure argument to implicit signal is not a closure");
4839
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
30✔
4840
                "locus argument to implicit signal must be a debug locus");
4841

4842
   return (op->result = vcode_add_reg(vtype_signal(type)));
30✔
4843
}
4844

4845
void emit_map_signal(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
1,278✔
4846
{
4847
   op_t *op = vcode_add_op(VCODE_OP_MAP_SIGNAL);
1,278✔
4848
   vcode_add_arg(op, src);
1,278✔
4849
   vcode_add_arg(op, dst);
1,278✔
4850
   vcode_add_arg(op, count);
1,278✔
4851

4852
   VCODE_ASSERT(vcode_reg_kind(src) == VCODE_TYPE_SIGNAL,
1,278✔
4853
                "src argument to map signal is not a signal");
4854
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
1,278✔
4855
                "dst argument to map signal is not a signal");
4856
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,278✔
4857
                "count argument type to map signal is not offset");
4858
}
1,278✔
4859

4860
void emit_map_const(vcode_reg_t src, vcode_reg_t dst, vcode_reg_t count)
4,137✔
4861
{
4862
   op_t *op = vcode_add_op(VCODE_OP_MAP_CONST);
4,137✔
4863
   vcode_add_arg(op, src);
4,137✔
4864
   vcode_add_arg(op, dst);
4,137✔
4865
   vcode_add_arg(op, count);
4,137✔
4866

4867
   VCODE_ASSERT(vcode_reg_kind(dst) == VCODE_TYPE_SIGNAL,
4,137✔
4868
                "dst argument to map const is not a signal");
4869
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
4,137✔
4870
                "count argument type to map const is not offset");
4871
}
4,137✔
4872

4873
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
8,714✔
4874
{
4875
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
110,295✔
4876
      if (other->args.items[0] == target && other->args.items[1] == count)
13,622✔
4877
         return;
4878
   }
4879

4880
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
8,699✔
4881
   vcode_add_arg(op, target);
8,699✔
4882
   vcode_add_arg(op, count);
8,699✔
4883

4884
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
8,699✔
4885
                "target argument to drive signal is not a signal");
4886
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
8,699✔
4887
                "count argument type to drive signal is not offset");
4888
}
4889

4890
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
1,182✔
4891
                          vcode_reg_t count, vcode_reg_t reject,
4892
                          vcode_reg_t after)
4893
{
4894
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
1,182✔
4895
   vcode_add_arg(op, target);
1,182✔
4896
   vcode_add_arg(op, source);
1,182✔
4897
   vcode_add_arg(op, count);
1,182✔
4898
   vcode_add_arg(op, reject);
1,182✔
4899
   vcode_add_arg(op, after);
1,182✔
4900

4901
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
1,182✔
4902
                "target argument to transfer signal is not a signal");
4903
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,182✔
4904
                "count argument type to transfer signal is not offset");
4905
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
1,182✔
4906
                "source argument to transfer signal is not a signal");
4907
}
1,182✔
4908

4909
vcode_reg_t emit_resolution_wrapper(vcode_type_t type, vcode_reg_t closure,
2,740✔
4910
                                    vcode_reg_t ileft, vcode_reg_t nlits)
4911
{
4912
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_RESOLUTION_WRAPPER) {
127,243✔
4913
      if (other->args.items[0] == closure
1,969✔
4914
          && other->args.items[1] == ileft
1,966✔
4915
          && other->args.items[2] == nlits)
1,966✔
4916
         return other->result;
1,966✔
4917
   }
4918

4919
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
774✔
4920
                "first argument to resolution wrapper must be closure");
4921

4922
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
774✔
4923
   vcode_add_arg(op, closure);
774✔
4924
   vcode_add_arg(op, ileft);
774✔
4925
   vcode_add_arg(op, nlits);
774✔
4926

4927
   return (op->result = vcode_add_reg(vtype_resolution(type)));
774✔
4928
}
4929

4930
vcode_reg_t emit_closure(ident_t func, vcode_reg_t context, vcode_type_t atype,
2,965✔
4931
                         vcode_type_t rtype)
4932
{
4933
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CLOSURE) {
129,225✔
4934
      if (other->func == func && other->args.items[0] == context)
2,118✔
4935
         return other->result;
2,000✔
4936
   }
4937

4938
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
965✔
4939
   vcode_add_arg(op, context);
965✔
4940
   op->func = func;
965✔
4941
   op->type = atype;
965✔
4942

4943
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
965✔
4944
                "invalid closure context argument");
4945

4946
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
965✔
4947
}
4948

4949
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
28,657✔
4950
{
4951
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
43,700✔
4952
      if (other->func == name)
21,667✔
4953
         return other->result;
11,997✔
4954
   }
4955

4956
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
16,660✔
4957
   op->func = name;
16,660✔
4958
   if (context != VCODE_INVALID_REG)
16,660✔
4959
      vcode_add_arg(op, context);
170✔
4960

4961
   VCODE_ASSERT(context == VCODE_INVALID_REG
16,660✔
4962
                || vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
4963
                "invalid protected init context argument");
4964
   VCODE_ASSERT(active_unit->kind == VCODE_UNIT_INSTANCE
16,660✔
4965
                || active_unit->kind == VCODE_UNIT_PACKAGE
4966
                || active_unit->kind == VCODE_UNIT_THUNK,
4967
                "cannot use package init here");
4968
   VCODE_ASSERT(name != active_unit->name, "cyclic package init");
16,660✔
4969

4970
   return (op->result = vcode_add_reg(vtype_context(name)));
16,660✔
4971
}
4972

4973
vcode_reg_t emit_protected_init(vcode_type_t type, vcode_reg_t context,
154✔
4974
                                vcode_reg_t path_name, vcode_reg_t inst_name)
4975
{
4976
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_INIT);
154✔
4977
   vcode_add_arg(op, context);
154✔
4978
   op->func = vtype_name(type);
154✔
4979

4980
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
154✔
4981
      vcode_add_arg(op, path_name);
32✔
4982
      vcode_add_arg(op, inst_name);
32✔
4983

4984
      VCODE_ASSERT(vcode_reg_kind(path_name) == VCODE_TYPE_UARRAY,
32✔
4985
                   "path name argument must be uarray");
4986
      VCODE_ASSERT(vcode_reg_kind(inst_name) == VCODE_TYPE_UARRAY,
32✔
4987
                   "inst name argument must be uarray");
4988
   }
4989

4990
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
154✔
4991
                "protected init type must be context");
4992
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
154✔
4993
                "invalid protected init context argument");
4994

4995
   return (op->result = vcode_add_reg(type));
154✔
4996
}
4997

4998
void emit_process_init(ident_t name, vcode_reg_t locus)
70✔
4999
{
5000
   op_t *op = vcode_add_op(VCODE_OP_PROCESS_INIT);
70✔
5001
   vcode_add_arg(op, locus);
70✔
5002
   op->func = name;
70✔
5003

5004
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
70✔
5005
                "locus argument to process init must be a debug locus");
5006
}
70✔
5007

5008
void emit_protected_free(vcode_reg_t obj)
7✔
5009
{
5010
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
7✔
5011
   vcode_add_arg(op, obj);
7✔
5012

5013
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
7✔
5014
                "protected object type must be context");
5015
}
7✔
5016

5017
vcode_reg_t emit_context_upref(int hops)
15,038✔
5018
{
5019
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
99,051✔
5020
      if (other->hops == hops)
6,800✔
5021
         return other->result;
6,741✔
5022
   }
5023

5024
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
8,297✔
5025
   op->hops = hops;
8,297✔
5026

5027
   VCODE_ASSERT(hops >= 0, "invalid hop count");
8,297✔
5028

5029
   vcode_unit_t vu = active_unit;
8,297✔
5030
   for (int i = 0; i < hops; i++) {
15,941✔
5031
      vu = vu->context;
7,644✔
5032
      VCODE_ASSERT(vu, "hop count is greater than depth");
7,644✔
5033
   }
5034

5035
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
8,297✔
5036
}
5037

5038
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
494✔
5039
                                    vcode_reg_t len)
5040
{
5041
   op_t *op = vcode_add_op(opkind);
494✔
5042
   vcode_add_arg(op, nets);
494✔
5043
   vcode_add_arg(op, len);
494✔
5044

5045
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
494✔
5046
                "argument to %s is not a signal", vcode_op_string(opkind));
5047

5048
   return (op->result = vcode_add_reg(vtype_bool()));
494✔
5049
}
5050

5051
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
304✔
5052
{
5053
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
304✔
5054
}
5055

5056
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
190✔
5057
{
5058
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
190✔
5059
}
5060

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

5069
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
34,624✔
5070
   op->field = field;
34,624✔
5071
   vcode_add_arg(op, record);
34,624✔
5072

5073
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
34,624✔
5074

5075
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
34,624✔
5076
                "argument to record ref must be a pointer");
5077

5078
   vtype_t *rtype = vcode_type_data(rptype->pointed);
34,624✔
5079
   VCODE_ASSERT(rtype->kind == VCODE_TYPE_RECORD,
34,624✔
5080
                "argument must be pointer to record or record signal");
5081

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

5084
   vcode_type_t field_type  = rtype->fields.items[field];
34,624✔
5085
   vcode_type_t bounds_type = field_type;
34,624✔
5086
   vcode_type_t result_type = field_type;
34,624✔
5087

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

5096
   op->result = vcode_add_reg(vtype_pointer(result_type));
34,624✔
5097

5098
   reg_t *rr = vcode_reg_data(op->result);
34,624✔
5099
   rr->bounds = bounds_type;
34,624✔
5100

5101
   return op->result;
34,624✔
5102
}
5103

5104
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
34,607✔
5105
{
5106
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
1,649,007✔
5107
      if (other->args.items[0] == array && other->args.items[1] == offset)
97,782✔
5108
         return other->result;
1,165✔
5109
   }
5110

5111
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
33,442✔
5112
   vcode_add_arg(op, array);
33,442✔
5113
   vcode_add_arg(op, offset);
33,442✔
5114

5115
   vcode_type_t rtype = vcode_reg_type(array);
33,442✔
5116
   VCODE_ASSERT((vtype_kind(rtype) == VCODE_TYPE_POINTER
33,442✔
5117
                 && vtype_kind(vtype_pointed(rtype)) != VCODE_TYPE_UARRAY)
5118
                || vtype_kind(rtype) == VCODE_TYPE_SIGNAL,
5119
                "argument to array ref must be a pointer or signal");
5120
   VCODE_ASSERT(vcode_reg_kind(offset) == VCODE_TYPE_OFFSET,
33,442✔
5121
                "array ref offset argument must have offset type");
5122

5123
   op->result = vcode_add_reg(rtype);
33,442✔
5124

5125
   reg_t *rr = vcode_reg_data(op->result);
33,442✔
5126
   rr->bounds = vcode_reg_bounds(array);
33,442✔
5127

5128
   return op->result;
33,442✔
5129
}
5130

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

5140
   op_t *op = vcode_add_op(VCODE_OP_COPY);
15,511✔
5141
   vcode_add_arg(op, dest);
15,511✔
5142
   vcode_add_arg(op, src);
15,511✔
5143
   if (count != VCODE_INVALID_REG)
15,511✔
5144
      vcode_add_arg(op, count);
13,571✔
5145

5146
   vcode_type_t dtype = vcode_reg_type(dest);
15,511✔
5147
   vcode_type_t stype = vcode_reg_type(src);
15,511✔
5148

5149
   vtype_kind_t dkind = vtype_kind(dtype);
15,511✔
5150
   vtype_kind_t skind = vtype_kind(stype);
15,511✔
5151

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

5162
   op->type = vtype_pointed(dtype);
15,511✔
5163
}
5164

5165
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
5,386✔
5166
{
5167
   VCODE_FOR_EACH_OP(other) {
94,959✔
5168
      if (other->kind == VCODE_OP_CLEAR_EVENT)
89,606✔
5169
         break;
5170
      else if (other->kind == VCODE_OP_SCHED_EVENT
89,576✔
5171
               && other->args.items[0] == nets
4,687✔
5172
               && other->args.items[1] == n_elems)
6✔
5173
         return;
5174
   }
5175

5176
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
5,383✔
5177
   vcode_add_arg(op, nets);
5,383✔
5178
   vcode_add_arg(op, n_elems);
5,383✔
5179

5180
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
5,383✔
5181
                "nets argument to sched event must be signal");
5182
}
5183

5184
void emit_implicit_event(vcode_reg_t nets, vcode_reg_t count, vcode_reg_t wake)
30✔
5185
{
5186
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_IMPLICIT_EVENT) {
465✔
5187
      if (other->args.items[0] == nets && other->args.items[1] == count
3✔
5188
          && other->args.items[1] == wake)
×
5189
         return;
5190
   }
5191

5192
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_EVENT);
30✔
5193
   vcode_add_arg(op, nets);
30✔
5194
   vcode_add_arg(op, count);
30✔
5195
   vcode_add_arg(op, wake);
30✔
5196

5197
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
30✔
5198
                "nets argument to implicit event must be signal");
5199
   VCODE_ASSERT(vcode_reg_kind(wake) == VCODE_TYPE_SIGNAL,
30✔
5200
                "wake argument to implicit event must be signal");
5201
}
5202

5203
void emit_clear_event(vcode_reg_t nets, vcode_reg_t n_elems)
458✔
5204
{
5205
   VCODE_FOR_EACH_OP(other) {
2,144✔
5206
      if (other->kind == VCODE_OP_SCHED_EVENT)
1,686✔
5207
         break;
5208
      else if (other->kind == VCODE_OP_CLEAR_EVENT
1,686✔
5209
               && other->args.items[0] == nets
39✔
5210
               && other->args.items[1] == n_elems)
×
5211
         return;
5212
   }
5213

5214
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
458✔
5215
   vcode_add_arg(op, nets);
458✔
5216
   vcode_add_arg(op, n_elems);
458✔
5217

5218
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
458✔
5219
                "nets argument to clear event must be signal");
5220
}
5221

5222
void emit_resume(ident_t func)
777✔
5223
{
5224
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
777✔
5225
   op->func = func;
777✔
5226

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

5231
void emit_memset(vcode_reg_t ptr, vcode_reg_t value, vcode_reg_t len)
5,665✔
5232
{
5233
   int64_t lconst;
5,665✔
5234
   if (vcode_reg_const(len, &lconst) && lconst == 0)
5,665✔
5235
      return;
17✔
5236

5237
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
5,648✔
5238
   vcode_add_arg(op, ptr);
5,648✔
5239
   vcode_add_arg(op, value);
5,648✔
5240
   vcode_add_arg(op, len);
5,648✔
5241

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

5250
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
539✔
5251
               const vcode_block_t *blocks, int ncases)
5252
{
5253
   int64_t cval1, cval2;
539✔
5254
   bool is_const = vcode_reg_const(value, &cval1);
539✔
5255

5256
   for (int i = 0; i < ncases; i++) {
4,980✔
5257
      bool can_fold = false;
4,445✔
5258
      if (cases[i] == value)
4,445✔
5259
         can_fold = true;
5260
      else if (is_const && vcode_reg_const(cases[i], &cval2))
4,445✔
5261
         can_fold = (cval1 == cval2);
4✔
5262

5263
      if (can_fold) {
4✔
5264
         emit_jump(blocks[i]);
4✔
5265
         return;
8✔
5266
      }
5267
   }
5268

5269
   if (is_const) {
535✔
5270
      emit_jump(def);
×
5271
      return;
×
5272
   }
5273

5274
   op_t *op = vcode_add_op(VCODE_OP_CASE);
535✔
5275
   vcode_add_arg(op, value);
535✔
5276
   vcode_add_target(op, def);
535✔
5277

5278
   for (int i = 0; i < ncases; i++) {
4,976✔
5279
      vcode_add_arg(op, cases[i]);
4,441✔
5280
      vcode_add_target(op, blocks[i]);
4,441✔
5281

5282
#ifdef DEBUG
5283
      for (int j = 0; j < i; j++)
245,341✔
5284
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
240,900✔
5285
#endif
5286
   }
5287
}
5288

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

5300
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
241✔
5301
                "file open first argument must have file pointer type");
5302
}
241✔
5303

5304
void emit_file_write(vcode_reg_t file, vcode_reg_t value, vcode_reg_t length)
125✔
5305
{
5306
   op_t *op = vcode_add_op(VCODE_OP_FILE_WRITE);
125✔
5307
   vcode_add_arg(op, file);
125✔
5308
   vcode_add_arg(op, value);
125✔
5309
   if (length != VCODE_INVALID_REG)
125✔
5310
      vcode_add_arg(op, length);
68✔
5311

5312
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
125✔
5313
                "file write first argument must have file pointer type");
5314
}
125✔
5315

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

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

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

5344
   op_t *op = vcode_add_op(VCODE_OP_NULL);
6,663✔
5345
   op->result = vcode_add_reg(type);
6,663✔
5346

5347
   vtype_kind_t kind = vtype_kind(type);
6,663✔
5348
   VCODE_ASSERT(kind == VCODE_TYPE_POINTER || kind == VCODE_TYPE_FILE
6,663✔
5349
                || kind == VCODE_TYPE_ACCESS || kind == VCODE_TYPE_CONTEXT,
5350
                "null type must be file, access, context, or pointer");
5351

5352
   return op->result;
5353
}
5354

5355
vcode_reg_t emit_new(vcode_type_t type, vcode_reg_t length)
422✔
5356
{
5357
   op_t *op = vcode_add_op(VCODE_OP_NEW);
422✔
5358
   if (length != VCODE_INVALID_REG)
422✔
5359
      vcode_add_arg(op, length);
331✔
5360

5361
   op->result = vcode_add_reg(vtype_access(type));
422✔
5362

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

5372
   return op->result;
422✔
5373
}
5374

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

5384
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
1,123✔
5385
   vcode_add_arg(op, ptr);
1,123✔
5386
   vcode_add_arg(op, locus);
1,123✔
5387

5388
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
1,123✔
5389
                "null check argument must be an access");
5390
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,123✔
5391
                "locus argument to null check must be a debug locus");
5392
}
5393

5394
void emit_deallocate(vcode_reg_t ptr)
207✔
5395
{
5396
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
207✔
5397
   vcode_add_arg(op, ptr);
207✔
5398

5399
   vcode_type_t ptype = vcode_reg_type(ptr);
207✔
5400
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
207✔
5401
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5402
                "deallocate argument must be pointer to access");
5403
}
207✔
5404

5405
vcode_reg_t emit_all(vcode_reg_t reg)
2,177✔
5406
{
5407
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
146,040✔
5408
      if (other->args.items[0] == reg)
9,251✔
5409
         return other->result;
632✔
5410
   }
5411

5412
   op_t *op = vcode_add_op(VCODE_OP_ALL);
1,545✔
5413
   vcode_add_arg(op, reg);
1,545✔
5414

5415
   vcode_type_t vtype = vcode_reg_type(reg);
1,545✔
5416

5417
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
1,545✔
5418
                "all argument must be an access");
5419

5420
   vcode_type_t pointed = vtype_pointed(vtype);
1,545✔
5421
   op->result = vcode_add_reg(vtype_pointer(pointed));
1,545✔
5422

5423
   reg_t *rr = vcode_reg_data(op->result);
1,545✔
5424
   rr->bounds = pointed;
1,545✔
5425

5426
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
1,545✔
5427
                "cannot dereference opaque type");
5428

5429
   return op->result;
5430
}
5431

5432
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
12,878✔
5433
{
5434
   block_t *b = &(active_unit->blocks.items[active_block]);
12,878✔
5435
   for (int i = b->ops.count - 1; i >= 0; i--) {
350,358✔
5436
      const op_t *other = &(b->ops.items[i]);
338,017✔
5437
      if (other->kind == kind && other->args.items[0] == sig)
338,017✔
5438
         return other->result;
537✔
5439
   }
5440

5441
   op_t *op = vcode_add_op(kind);
12,341✔
5442
   vcode_add_arg(op, sig);
12,341✔
5443

5444
   vcode_type_t stype = vcode_reg_type(sig);
12,341✔
5445
   op->type = stype;
12,341✔
5446

5447
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
12,341✔
5448
                "argument r%d to resolved is not a signal", sig);
5449

5450
   vcode_type_t rtype = vtype_base(stype);
12,341✔
5451

5452
   const vtype_kind_t rkind = vtype_kind(rtype);
12,341✔
5453
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
12,341✔
5454
      rtype = vtype_elem(rtype);
×
5455

5456
   VCODE_ASSERT(vtype_is_scalar(rtype),
12,341✔
5457
                "resolved signal base type must be scalar");
5458

5459
   op->result = vcode_add_reg(vtype_pointer(rtype));
12,341✔
5460

5461
   reg_t *rr = vcode_reg_data(op->result);
12,341✔
5462
   rr->bounds = rtype;
12,341✔
5463

5464
   return op->result;
12,341✔
5465
}
5466

5467
vcode_reg_t emit_resolved(vcode_reg_t sig)
12,837✔
5468
{
5469
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
12,837✔
5470
}
5471

5472
vcode_reg_t emit_last_value(vcode_reg_t sig)
41✔
5473
{
5474
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
41✔
5475
}
5476

5477
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
42✔
5478
{
5479
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
42✔
5480
   vcode_add_arg(op, signal);
42✔
5481
   if (len != VCODE_INVALID_REG)
42✔
5482
      vcode_add_arg(op, len);
30✔
5483

5484
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
42✔
5485
                "signal argument to last event must have signal type");
5486
   VCODE_ASSERT(len == VCODE_INVALID_REG
42✔
5487
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5488
                "length argument to last event must have offset type");
5489

5490
   return (op->result = vcode_add_reg(vtype_time()));
42✔
5491
}
5492

5493
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
36✔
5494
{
5495
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
36✔
5496
   vcode_add_arg(op, signal);
36✔
5497
   if (len != VCODE_INVALID_REG)
36✔
5498
      vcode_add_arg(op, len);
27✔
5499

5500
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5501
                "signal argument to last active must have signal type");
5502
   VCODE_ASSERT(len == VCODE_INVALID_REG
36✔
5503
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5504
                "length argument to last active must have offset type");
5505

5506
   return (op->result = vcode_add_reg(vtype_time()));
36✔
5507
}
5508

5509
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
6,915✔
5510
{
5511
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
6,915✔
5512
   vcode_add_arg(op, signal);
6,915✔
5513
   vcode_add_arg(op, locus);
6,915✔
5514

5515
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
6,915✔
5516
                "signal argument must have signal type");
5517
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,915✔
5518
                "locus argument must have debug locus type");
5519
}
6,915✔
5520

5521
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
30✔
5522
{
5523
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
30✔
5524
   vcode_add_arg(op, signal);
30✔
5525
   vcode_add_arg(op, len);
30✔
5526

5527
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
30✔
5528
                "signal argument to last active must have signal type");
5529
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
30✔
5530
                "length argument to last active must have offset type");
5531

5532
   return (op->result = vcode_add_reg(vtype_bool()));
30✔
5533
}
5534

5535
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
24✔
5536
{
5537
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
24✔
5538
   vcode_add_arg(op, signal);
24✔
5539
   if (len != VCODE_INVALID_REG)
24✔
5540
      vcode_add_arg(op, len);
3✔
5541

5542
   vcode_type_t signal_type = vcode_reg_type(signal);
24✔
5543

5544
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
24✔
5545
                "signal argument to last active must have signal type");
5546
   VCODE_ASSERT(len == VCODE_INVALID_REG
24✔
5547
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5548
                "length argument to last active must have offset type");
5549

5550
   vcode_type_t base_type = vtype_base(signal_type);
24✔
5551
   op->result = vcode_add_reg(vtype_pointer(base_type));
24✔
5552

5553
   reg_t *rr = vcode_reg_data(op->result);
24✔
5554
   rr->bounds = base_type;
24✔
5555

5556
   return op->result;
24✔
5557
}
5558

5559
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
21,420✔
5560
                       vcode_reg_t dim)
5561
{
5562
   if (rlen == llen)
21,420✔
5563
      return;
5564

5565
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
181,954✔
5566
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
2,810✔
5567
         return;
5568
   }
5569

5570
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
6,707✔
5571
   vcode_add_arg(op, llen);
6,707✔
5572
   vcode_add_arg(op, rlen);
6,707✔
5573
   vcode_add_arg(op, locus);
6,707✔
5574
   if (dim != VCODE_INVALID_REG)
6,707✔
5575
      vcode_add_arg(op, dim);
24✔
5576

5577
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,707✔
5578
                "locus argument to length check must be a debug locus");
5579
}
5580

5581
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
1,572✔
5582
{
5583
   int64_t cval;
1,572✔
5584
   if (vcode_reg_const(exp, &cval) && cval >= 0)
1,572✔
5585
      return;
1,055✔
5586

5587
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
3,290✔
5588
      if (other->args.items[0] == exp)
12✔
5589
         return;
5590
   }
5591

5592
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
517✔
5593
   vcode_add_arg(op, exp);
517✔
5594
   vcode_add_arg(op, locus);
517✔
5595

5596
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
517✔
5597
                "exp argument to exponent check must be a integer");
5598
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
517✔
5599
                "locus argument to exponent check must be a debug locus");
5600
}
5601

5602
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
1,013✔
5603
{
5604
   int64_t cval;
1,013✔
5605
   if (vcode_reg_const(denom, &cval) && cval != 0)
1,013✔
5606
      return;
910✔
5607

5608
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
2,886✔
5609
      if (other->args.items[0] == denom)
56✔
5610
         return;
5611
   }
5612

5613
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
103✔
5614
   vcode_add_arg(op, denom);
103✔
5615
   vcode_add_arg(op, locus);
103✔
5616

5617
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
103✔
5618
                "denom argument to zero check must be a integer");
5619
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
103✔
5620
                "locus argument to zero check must be a debug locus");
5621
}
5622

5623
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
47,055✔
5624
                                   vcode_reg_t right, vcode_reg_t dir)
5625
{
5626
   int64_t dconst;
47,055✔
5627
   if (vcode_reg_const(dir, &dconst)) {
47,055✔
5628
      int64_t lconst, rconst;
38,283✔
5629
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
38,283✔
5630
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
28,889✔
5631
            || (dconst == RANGE_DOWNTO && rconst > lconst);
60,990✔
5632

5633
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
32,102✔
5634

5635
         const bool ok_static =
64,204✔
5636
            (dconst == RANGE_TO
5637
             && bounds->low >= lconst && bounds->high <= rconst)
28,889✔
5638
            || (dconst == RANGE_DOWNTO
7,596✔
5639
                && bounds->low >= rconst && bounds->high <= lconst)
3,213✔
5640
            || (!is_null && (reg == left || reg == right));
36,677✔
5641

5642
         return ok_static;
37,501✔
5643
      }
5644
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
6,181✔
5645
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
5,805✔
5646
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
5,805✔
5647

5648
         assert(lbounds->kind == VCODE_TYPE_REAL);
5,805✔
5649
         assert(rbounds->kind == VCODE_TYPE_REAL);
5,805✔
5650

5651
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
5,805✔
5652
         assert(bounds->kind == VCODE_TYPE_REAL);
5,805✔
5653

5654
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
5,805✔
5655
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
5,399✔
5656
            // Covers the complete double range so can never overflow
5657
            return true;
5658
         }
5659
      }
5660
   }
5661

5662
   return false;
5663
}
5664

5665
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
47,648✔
5666
                              vcode_reg_t left, vcode_reg_t right,
5667
                              vcode_reg_t dir, vcode_reg_t locus,
5668
                              vcode_reg_t hint)
5669
{
5670
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
2,241,352✔
5671
      if (other->args.items[0] == reg && other->args.items[1] == left
13,508✔
5672
          && other->args.items[2] == right && other->args.items[3] == dir)
599✔
5673
         return;
5674
   }
5675

5676
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
47,055✔
5677
      emit_comment("Elided bounds check for r%d", reg);
32,926✔
5678
      return;
32,926✔
5679
   }
5680

5681
   op_t *op = vcode_add_op(kind);
14,129✔
5682
   vcode_add_arg(op, reg);
14,129✔
5683
   vcode_add_arg(op, left);
14,129✔
5684
   vcode_add_arg(op, right);
14,129✔
5685
   vcode_add_arg(op, dir);
14,129✔
5686
   vcode_add_arg(op, locus);
14,129✔
5687
   vcode_add_arg(op, hint);
14,129✔
5688

5689
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
14,129✔
5690
                "locus argument to bounds check must be a debug locus");
5691
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
14,129✔
5692
                "hint argument to bounds check must be a debug locus");
5693
}
5694

5695
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
8,442✔
5696
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5697
{
5698
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
8,442✔
5699
}
8,442✔
5700

5701
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
39,206✔
5702
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5703
{
5704
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
39,206✔
5705
}
39,206✔
5706

5707
void emit_push_scope(vcode_reg_t locus, vcode_type_t type)
1,944✔
5708
{
5709
   op_t *op = vcode_add_op(VCODE_OP_PUSH_SCOPE);
1,944✔
5710
   vcode_add_arg(op, locus);
1,944✔
5711
   op->type = type;
1,944✔
5712

5713
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,944✔
5714
                "locus argument to push scope must be a debug locus");
5715
}
1,944✔
5716

5717
void emit_pop_scope(void)
1,944✔
5718
{
5719
   vcode_add_op(VCODE_OP_POP_SCOPE);
1,944✔
5720
}
1,944✔
5721

5722
vcode_reg_t emit_debug_locus(ident_t unit, ptrdiff_t offset)
116,781✔
5723
{
5724
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
6,272,683✔
5725
      if (other->ident == unit && other->tag == offset)
986,504✔
5726
         return other->result;
7,156✔
5727
   }
5728

5729
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
109,625✔
5730
   op->ident = unit;
109,625✔
5731
   op->value = offset;
109,625✔
5732

5733
   return (op->result = vcode_add_reg(vtype_debug_locus()));
109,625✔
5734
}
5735

5736
void emit_debug_out(vcode_reg_t reg)
×
5737
{
5738
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
5739
   vcode_add_arg(op, reg);
×
5740
}
×
5741

5742
void emit_cover_stmt(uint32_t tag)
838✔
5743
{
5744
   op_t *op = vcode_add_op(VCODE_OP_COVER_STMT);
838✔
5745
   op->tag = tag;
838✔
5746
}
838✔
5747

5748
void emit_cover_branch(uint32_t tag)
483✔
5749
{
5750
   op_t *op = vcode_add_op(VCODE_OP_COVER_BRANCH);
483✔
5751
   op->tag = tag;
483✔
5752
}
483✔
5753

5754
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
308✔
5755
{
5756
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
308✔
5757
   vcode_add_arg(op, signal);
308✔
5758
   op->tag = tag;
308✔
5759
}
308✔
5760

5761
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
12✔
5762
{
5763
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
12✔
5764
   vcode_add_arg(op, signal);
12✔
5765
   vcode_add_arg(op, low);
12✔
5766
   op->tag = tag;
12✔
5767
}
12✔
5768

5769
void emit_cover_expr(vcode_reg_t new_mask, uint32_t tag)
321✔
5770
{
5771
   op_t *op = vcode_add_op(VCODE_OP_COVER_EXPR);
321✔
5772
   vcode_add_arg(op, new_mask);
321✔
5773
   op->tag = tag;
321✔
5774
}
321✔
5775

5776
void emit_unreachable(vcode_reg_t locus)
509✔
5777
{
5778
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
509✔
5779
   if (locus != VCODE_INVALID_REG)
509✔
5780
      vcode_add_arg(op, locus);
153✔
5781
}
509✔
5782

5783
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
1,503✔
5784
{
5785
   active_unit->flags |= UNIT_UNDEFINED;
1,503✔
5786

5787
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
1,503✔
5788
   op->result = vcode_add_reg(type);
1,503✔
5789
   vcode_reg_data(op->result)->bounds = bounds;
1,503✔
5790

5791
   return op->result;
1,503✔
5792
}
5793

5794
void emit_debug_info(const loc_t *loc)
1,336,824✔
5795
{
5796
   if (!loc_invalid_p(loc))
1,336,824✔
5797
      vcode_block_data()->last_loc = *loc;
1,299,975✔
5798
}
1,336,824✔
5799

5800
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
4,127✔
5801
{
5802
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
157,050✔
5803
      if (other->args.items[0] == context && other->ident == name)
8,806✔
5804
         return other->result;
1,553✔
5805
   }
5806

5807
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
2,574✔
5808
   vcode_add_arg(op, context);
2,574✔
5809
   op->ident = name;
2,574✔
5810

5811
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
2,574✔
5812
                "first argument to link var must be context");
5813

5814
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
2,574✔
5815
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
79✔
5816
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
79✔
5817
   }
5818
   else {
5819
      op->result = vcode_add_reg(vtype_pointer(type));
2,495✔
5820
      vcode_reg_data(op->result)->bounds = type;
2,495✔
5821
   }
5822

5823
   return op->result;
2,574✔
5824
}
5825

5826
vcode_reg_t emit_link_package(ident_t name)
22,994✔
5827
{
5828
   VCODE_FOR_EACH_OP(other) {
1,088,322✔
5829
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
1,077,629✔
5830
         return other->result;
7,437✔
5831
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
1,070,192✔
5832
         return other->result;
4,864✔
5833
   }
5834

5835
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
10,693✔
5836
   op->ident = name;
10,693✔
5837

5838
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
10,693✔
5839

5840
   return (op->result = vcode_add_reg(vtype_context(name)));
10,693✔
5841
}
5842

5843
vcode_reg_t emit_link_instance(ident_t name, vcode_reg_t locus)
130✔
5844
{
5845
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_INSTANCE) {
352✔
5846
      if (other->ident == name)
34✔
5847
         return other->result;
25✔
5848
   }
5849

5850
   op_t *op = vcode_add_op(VCODE_OP_LINK_INSTANCE);
105✔
5851
   vcode_add_arg(op, locus);
105✔
5852
   op->ident = name;
105✔
5853

5854
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
105✔
5855
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
105✔
5856
                "locus argument to link instance must be a debug locus");
5857

5858
   return (op->result = vcode_add_reg(vtype_context(name)));
105✔
5859
}
5860

5861
void emit_enter_state(vcode_reg_t state)
219✔
5862
{
5863
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
606✔
5864
      if (other->args.items[0] == state)
6✔
5865
         return;
5866
   }
5867

5868
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
219✔
5869
   vcode_add_arg(op, state);
219✔
5870

5871
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
219✔
5872
                "state must have integer type");
5873
}
5874

5875
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
45✔
5876
                               vcode_reg_t locus, vcode_reg_t bounds)
5877
{
5878
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
45✔
5879
   vcode_add_arg(op, value);
45✔
5880
   vcode_add_arg(op, context);
45✔
5881
   vcode_add_arg(op, locus);
45✔
5882
   if (bounds != VCODE_INVALID_REG)
45✔
5883
      vcode_add_arg(op, bounds);
6✔
5884

5885
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
45✔
5886
                "invalid reflect value context argument");
5887
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5888
                "locus argument to reflect value must be a debug locus");
5889

5890
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
45✔
5891
}
5892

5893
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
42✔
5894
                                 vcode_reg_t bounds)
5895
{
5896
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
42✔
5897
   vcode_add_arg(op, context);
42✔
5898
   vcode_add_arg(op, locus);
42✔
5899
   if (bounds != VCODE_INVALID_REG)
42✔
5900
      vcode_add_arg(op, bounds);
×
5901

5902
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
42✔
5903
                "invalid reflect value context argument");
5904
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
42✔
5905
                "locus argument to reflect value must be a debug locus");
5906

5907
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
42✔
5908
}
5909

5910
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
166✔
5911
                                  int nargs)
5912
{
5913
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
166✔
5914
   op->func = func;
166✔
5915

5916
   for (int i = 0; i < nargs; i++)
471✔
5917
      vcode_add_arg(op, args[i]);
305✔
5918

5919
   return (op->result = vcode_add_reg(vtype_trigger()));
166✔
5920
}
5921

5922
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
31✔
5923
{
5924
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
31✔
5925
   vcode_add_arg(op, left);
31✔
5926
   vcode_add_arg(op, right);
31✔
5927

5928
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
31✔
5929
                "or trigger left argument must be trigger");
5930
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
31✔
5931
                "or trigger right argument must be trigger");
5932

5933
   return (op->result = vcode_add_reg(vtype_trigger()));
31✔
5934
}
5935

5936
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
63✔
5937
{
5938
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
63✔
5939
   vcode_add_arg(op, left);
63✔
5940
   vcode_add_arg(op, right);
63✔
5941

5942
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
63✔
5943
                "cmp trigger left argument must be signal");
5944
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
63✔
5945
                "cmp trigger right argument must be integer");
5946

5947
   return (op->result = vcode_add_reg(vtype_trigger()));
63✔
5948
}
5949

5950
void emit_add_trigger(vcode_reg_t trigger)
260✔
5951
{
5952
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
260✔
5953
   vcode_add_arg(op, trigger);
260✔
5954

5955
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
260✔
5956
                "add trigger argument must be trigger");
5957
}
260✔
5958

5959
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
180✔
5960
{
5961
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
180✔
5962
   vcode_add_arg(op, driving);
180✔
5963
   if (effective != VCODE_INVALID_REG && effective != driving)
180✔
5964
      vcode_add_arg(op, effective);
15✔
5965

5966
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
180✔
5967
                "port conversion argument must be a closure");
5968
   VCODE_ASSERT(effective == VCODE_INVALID_REG
180✔
5969
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
5970
                "port conversion argument must be a closure");
5971

5972
   return (op->result = vcode_add_reg(vtype_conversion()));
180✔
5973
}
5974

5975
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
252✔
5976
{
5977
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
252✔
5978
   vcode_add_arg(op, conv);
252✔
5979
   vcode_add_arg(op, nets);
252✔
5980
   vcode_add_arg(op, count);
252✔
5981

5982
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
252✔
5983
                "conv argument to convert must be a port conversion");
5984
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
252✔
5985
                "nets argument to convert must be a signal");
5986
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
252✔
5987
                "count argument to convert must be offset");
5988
}
252✔
5989

5990
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
294✔
5991
{
5992
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
294✔
5993
   vcode_add_arg(op, conv);
294✔
5994
   vcode_add_arg(op, nets);
294✔
5995
   vcode_add_arg(op, count);
294✔
5996

5997
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
294✔
5998
                "conv argument to convert must be a port conversion");
5999
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
294✔
6000
                "nets argument to convert must be a signal");
6001
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
294✔
6002
                "count argument to convert must be offset");
6003
}
294✔
6004

6005
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
251✔
6006
{
6007
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
251✔
6008
   vcode_add_arg(op, spec);
251✔
6009
   vcode_add_arg(op, length);
251✔
6010
   if (locus != VCODE_INVALID_REG)
251✔
6011
      vcode_add_arg(op, locus);
116✔
6012

6013
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
251✔
6014
                "spec argument to bind foreign must be a pointer");
6015
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
251✔
6016
                "length argument to bind foreign must be offset");
6017
   VCODE_ASSERT(locus == VCODE_INVALID_REG
251✔
6018
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6019
                "locus argument to bind foreign value must be a debug locus");
6020
}
251✔
6021

6022
vcode_reg_t emit_instance_name(vcode_reg_t kind)
777✔
6023
{
6024
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
777✔
6025
   vcode_add_arg(op, kind);
777✔
6026

6027
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
777✔
6028
                "kind argument to instance name must be offset");
6029

6030
   vcode_type_t vchar = vtype_char();
777✔
6031
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
777✔
6032
}
6033

6034
void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count,
87✔
6035
                         vcode_reg_t values)
6036
{
6037
   op_t *op = vcode_add_op(VCODE_OP_DEPOSIT_SIGNAL);
87✔
6038
   vcode_add_arg(op, signal);
87✔
6039
   vcode_add_arg(op, count);
87✔
6040
   vcode_add_arg(op, values);
87✔
6041

6042
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
87✔
6043
                "deposit signal target is not signal");
6044
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
87✔
6045
                "deposit signal count is not offset type");
6046
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
87✔
6047
                "signal cannot be values argument for deposit signal");
6048
}
87✔
6049

6050
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
27,928✔
6051
{
6052
   vcode_state_t state;
27,928✔
6053
   vcode_state_save(&state);
27,928✔
6054

6055
   vcode_select_unit(vu);
27,928✔
6056

6057
   const int nblocks = vcode_count_blocks();
27,928✔
6058
   for (int i = 0; i < nblocks; i++) {
131,972✔
6059
      vcode_select_block(i);
104,044✔
6060

6061
      const int nops = vcode_count_ops();
104,044✔
6062
      for (int op = 0; op < nops; op++) {
1,453,920✔
6063
         switch (vcode_get_op(op)) {
1,349,876✔
6064
         case VCODE_OP_LINK_PACKAGE:
9,149✔
6065
            (*fn)(vcode_get_ident(op), ctx);
9,149✔
6066
            break;
9,149✔
6067
         case VCODE_OP_FCALL:
49,818✔
6068
         case VCODE_OP_PCALL:
6069
         case VCODE_OP_CLOSURE:
6070
         case VCODE_OP_PROTECTED_INIT:
6071
         case VCODE_OP_PACKAGE_INIT:
6072
         case VCODE_OP_FUNCTION_TRIGGER:
6073
            (*fn)(vcode_get_func(op), ctx);
49,818✔
6074
            break;
49,818✔
6075
         default:
6076
            break;
6077
         }
6078
      }
6079
   }
6080

6081
   vcode_state_restore(&state);
27,928✔
6082
}
27,928✔
6083

6084
#ifdef DEBUG
6085
static void shape_mismatch(vcode_unit_t vu, vcode_unit_t shape,
×
6086
                           const char *fmt, ...)
6087
{
6088
   vcode_select_unit(vu);
×
6089
   vcode_dump();
×
6090

6091
   vcode_select_unit(shape);
×
6092
   vcode_dump();
×
6093

6094
   va_list ap;
×
6095
   va_start(ap, fmt);
×
6096

6097
   diag_t *d = diag_new(DIAG_FATAL, NULL);
×
6098
   diag_printf(d, "instance %s does not match shape %s", istr(vu->name),
×
6099
               istr(shape->name));
6100
   diag_stacktrace(d, true);
×
6101
   diag_vhint(d, NULL, fmt, ap);
×
6102
   diag_emit(d);
×
6103

6104
   va_end(ap);
×
6105

6106
   fatal_exit(1);
×
6107
}
6108
#endif
6109

6110
void vcode_check_shape(vcode_unit_t vu, vcode_unit_t shape)
51✔
6111
{
6112
#ifdef DEBUG
6113
   assert(shape->kind == VCODE_UNIT_SHAPE);
51✔
6114
   assert(vu->kind == VCODE_UNIT_INSTANCE);
51✔
6115

6116
   if (shape->vars.count <= vu->vars.count) {
51✔
6117
      for (int i = 0; i < shape->vars.count; i++) {
193✔
6118
         var_t *v = var_array_nth_ptr(&(vu->vars), i);
142✔
6119
         var_t *s = var_array_nth_ptr(&(shape->vars), i);
142✔
6120

6121
         if (v->name != s->name)
142✔
6122
            shape_mismatch(vu, shape, "var %d name %s != %s", i, istr(v->name),
×
6123
                           istr(s->name));
6124
         else if (v->flags != s->flags)
142✔
6125
            shape_mismatch(vu, shape, "var %d flags %x != %x", i, v->flags,
×
6126
                           s->flags);
6127
         // XXX: not possible to compare types at the moment
6128
      }
6129
   }
6130
   else
6131
      shape_mismatch(vu, shape, "shape vars %d > unit vars %d",
×
6132
                     shape->vars.count, vu->vars.count);
6133

6134
   if (shape->context != NULL)
51✔
6135
      vcode_check_shape(vu->context, shape->context);
×
6136
#endif
6137
}
51✔
6138

6139
#if VCODE_CHECK_UNIONS
6140
#define OP_USE_COUNT_U0(x)                                              \
6141
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6142
#define OP_USE_COUNT_U1(x)                                              \
6143
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6144
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6145
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6146

6147
__attribute__((constructor))
6148
static void vcode_check_unions(void)
6149
{
6150
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6151
   for (int i = 0; i < 256; i++) {
6152
      assert(OP_USE_COUNT_U0(i) <= 1);
6153
      assert(OP_USE_COUNT_U1(i) <= 1);
6154
   }
6155
}
6156
#endif  // VCODE_CHECK_UNIONS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc