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

nickg / nvc / 9799337310

04 Jul 2024 07:57PM UTC coverage: 91.561% (+0.01%) from 91.55%
9799337310

push

github

nickg
Crash after missing file in coverage report. Fixes #909

36 of 37 new or added lines in 2 files covered. (97.3%)

565 existing lines in 8 files now uncovered.

56897 of 62141 relevant lines covered (91.56%)

670833.56 hits per line

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

96.48
/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,116,570✔
36
DECLARE_AND_DEFINE_ARRAY(vcode_block);
366,798✔
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,261,894✔
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,270✔
157
DECLARE_AND_DEFINE_ARRAY(var);
364,749✔
158
DECLARE_AND_DEFINE_ARRAY(reg);
7,731,368✔
159
DECLARE_AND_DEFINE_ARRAY(block);
129,714✔
160
DECLARE_AND_DEFINE_ARRAY(vtype);
70,723,103✔
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,856✔
216
{
217
   int64_t result;
30,856✔
218
   if (__builtin_add_overflow(a, b, &result))
30,856✔
219
      return b < 0 ? INT64_MIN : INT64_MAX;
11,580✔
220

221
   return result;
222
}
223

224
static inline int64_t ssub64(int64_t a, int64_t b)
44,688✔
225
{
226
   int64_t result;
44,688✔
227
   if (__builtin_sub_overflow(a, b, &result))
44,688✔
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,242,994✔
243
{
244
   assert(active_unit != NULL);
1,242,994✔
245

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

252
   return reg;
1,242,994✔
253
}
254

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

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

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

271
   block_t *block = vcode_block_data();
1,566,410✔
272

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

279
   return op;
1,566,410✔
280
}
281

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

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

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

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

301
static op_t *vcode_find_definition(vcode_reg_t reg)
1,175,668✔
302
{
303
   for (int i = active_block; i >= 0; i--) {
1,224,834✔
304
      block_t *b = &(active_unit->blocks.items[i]);
1,221,866✔
305
      for (int j = b->ops.count - 1; j >= 0; j--) {
15,629,350✔
306
         if (b->ops.items[j].result == reg)
15,580,184✔
307
            return &(b->ops.items[j]);
1,172,700✔
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,865✔
316
{
317
   op_t *defn = vcode_find_definition(reg);
1,146,865✔
318
   VCODE_ASSERT(defn != NULL, "constant %s uses parameter r%d",
1,146,865✔
319
                what, reg);
320
   VCODE_ASSERT(defn->kind == VCODE_OP_CONST
1,146,865✔
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,865✔
329
#endif
330

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

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

344
   int depth = MASK_CONTEXT(type);
68,285,322✔
345
   assert(depth <= unit->depth);
68,285,322✔
346
   while (depth != unit->depth)
69,836,601✔
347
      unit = unit->context;
1,551,279✔
348

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

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

357
   return var_array_nth_ptr(&(active_unit->vars), var);
318,554✔
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,773✔
521
{
522
   state->unit  = active_unit;
84,773✔
523
   state->block = active_block;
84,773✔
524
}
84,773✔
525

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

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

536
   if (unit == active_unit)
41,878✔
537
      vcode_close();
11,646✔
538

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

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

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

556
      for (unsigned j = 0; j < b->ops.count; j++) {
1,623,192✔
557
         op_t *o = &(b->ops.items[j]);
1,493,499✔
558
         if (OP_HAS_COMMENT(o->kind))
1,493,499✔
559
            free(o->comment);
116,414✔
560
         if (OP_HAS_TARGET(o->kind))
1,493,499✔
561
            free(o->targets.items);
78,934✔
562
         free(o->args.items);
1,493,499✔
563
      }
564
      free(b->ops.items);
129,693✔
565
   }
566
   free(unit->blocks.items);
41,878✔
567

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

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

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

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

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

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

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

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

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

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

620
   vtype_t *bounds = vcode_type_data(r->bounds);
664,123✔
621

622
   VCODE_ASSERT(
664,123✔
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) {
664,123✔
627
      if (value) *value = bounds->low;
351,389✔
628
      return true;
351,389✔
629
   }
630
   else
631
      return false;
632
}
633

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

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

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

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

648
         for (int j = b->ops.count - 1; j >= 0; j--) {
2,947,385✔
649
            op_t *o = &(b->ops.items[j]);
2,737,332✔
650

651
            switch (o->kind) {
2,737,332✔
652
            case VCODE_OP_FCALL:
56,512✔
653
               if (o->result == VCODE_INVALID_REG)
56,512✔
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,808,636✔
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,808,636✔
699
                  if (false DEBUG_ONLY(|| o->kind != VCODE_OP_CONST)) {
146,621✔
700
                     o->comment = xasprintf("Dead %s definition of r%d",
74,076✔
701
                                            vcode_op_string(o->kind),
702
                                            o->result);
703
                     o->kind = VCODE_OP_COMMENT;
74,076✔
704
                  }
705
                  else
706
                     o->kind = (vcode_op_t)-1;
72,545✔
707
                  vcode_reg_array_resize(&(o->args), 0, VCODE_INVALID_REG);
146,621✔
708
                  pruned++;
146,621✔
709
               }
710
               uses[o->result] = -1;
1,808,636✔
711
               break;
1,808,636✔
712

713
            default:
714
               break;
715
            }
716

717
            for (int k = 0; k < o->args.count; k++) {
7,455,482✔
718
               if (o->args.items[k] != VCODE_INVALID_REG)
4,718,150✔
719
                  uses[o->args.items[k]]++;
4,675,327✔
720
            }
721
         }
722
      }
723
   } while (pruned > 0);
56,667✔
724

725
   for (int i = active_unit->blocks.count - 1; i >= 0; i--) {
171,601✔
726
      block_t *b = &(active_unit->blocks.items[i]);
129,714✔
727
      op_t *dst = &(b->ops.items[0]);
129,714✔
728
      size_t copied = 0;
129,714✔
729
      for (int j = 0; j < b->ops.count; j++) {
1,696,124✔
730
         const op_t *src = &(b->ops.items[j]);
1,566,410✔
731
         if (src->kind != (vcode_op_t)-1) {
1,566,410✔
732
            if (src != dst) {
1,493,865✔
733
               assert(dst < src);
410,514✔
734
               *dst = *src;
410,514✔
735
            }
736
            dst++;
1,493,865✔
737
            copied++;
1,493,865✔
738
         }
739
      }
740

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

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

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

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

765
int vcode_count_vars(void)
79,448✔
766
{
767
   assert(active_unit != NULL);
79,448✔
768
   return active_unit->vars.count;
79,448✔
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,237✔
783
{
784
   return vcode_var_data(var)->name;
36,237✔
785
}
786

787
vcode_type_t vcode_var_type(vcode_var_t var)
138,531✔
788
{
789
   return vcode_var_data(var)->type;
138,531✔
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,845✔
798
{
799
   return vcode_var_data(var)->flags;
35,845✔
800
}
801

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

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

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

821
int64_t vcode_get_value(int op)
364,112✔
822
{
823
   op_t *o = vcode_op_data(op);
364,112✔
824
   assert(OP_HAS_VALUE(o->kind));
364,112✔
825
   return o->value;
364,112✔
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,272✔
836
{
837
   op_t *o = vcode_op_data(op);
140,272✔
838
   assert(OP_HAS_ADDRESS(o->kind));
140,272✔
839
   return o->address;
140,272✔
840
}
841

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

849
int vcode_get_hops(int op)
57,164✔
850
{
851
   op_t *o = vcode_op_data(op);
57,164✔
852
   assert(OP_HAS_HOPS(o->kind));
57,164✔
853
   return o->hops;
57,164✔
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,868✔
871
{
872
   return vcode_op_data(op)->args.count;
181,868✔
873
}
874

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

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

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

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

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

907
vcode_block_t vcode_get_target(int op, int nth)
136,264✔
908
{
909
   op_t *o = vcode_op_data(op);
136,264✔
910
   assert(OP_HAS_TARGET(o->kind));
136,264✔
911
   return vcode_block_array_nth(&(o->targets), nth);
136,264✔
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,667,519✔
923
{
924
   assert(active_unit != NULL);
1,667,519✔
925
   assert(active_block != VCODE_INVALID_BLOCK);
1,667,519✔
926

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

939
const char *vcode_op_string(vcode_op_t op)
74,076✔
940
{
941
   static const char *strs[] = {
74,076✔
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
      "map transaction",
968
   };
969
   if ((unsigned)op >= ARRAY_LEN(strs))
74,076✔
970
      return "???";
971
   else
972
      return strs[op];
74,076✔
973
}
974

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1112
   return col;
1113
}
1114

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2321
         if (j == mark_op && i == old_block)
2322
            color_printf("\t $red$<----$$");
2323

2324
         color_printf("$$\n");
2325

2326
         if (callback != NULL)
2327
            (*callback)(j, arg);
2328
      }
2329

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

2334
   printf("\n");
2335
   fflush(stdout);
2336

2337
   active_block = old_block;
2338
}
2339
LCOV_EXCL_STOP
2340

2341
bool vtype_eq(vcode_type_t a, vcode_type_t b)
31,900,747✔
2342
{
2343
   assert(active_unit != NULL);
32,408,460✔
2344

2345
   if (a == b)
32,408,460✔
2346
      return true;
2347
   else {
2348
      const vtype_t *at = vcode_type_data(a);
29,878,964✔
2349
      const vtype_t *bt = vcode_type_data(b);
29,878,964✔
2350

2351
      if (at->kind != bt->kind)
29,878,964✔
2352
         return false;
2353

2354
      switch (at->kind) {
13,040,006✔
2355
      case VCODE_TYPE_INT:
11,008,242✔
2356
         return (at->low == bt->low) && (at->high == bt->high);
20,686,400✔
2357
      case VCODE_TYPE_REAL:
977,885✔
2358
         return (at->rlow == bt->rlow) && (at->rhigh == bt->rhigh);
1,904,680✔
2359
      case VCODE_TYPE_CARRAY:
71,772✔
2360
         return at->size == bt->size && vtype_eq(at->elem, bt->elem);
78,155✔
2361
      case VCODE_TYPE_UARRAY:
89,189✔
2362
         return at->dims == bt->dims && vtype_eq(at->elem, bt->elem);
111,266✔
2363
      case VCODE_TYPE_POINTER:
427,834✔
2364
      case VCODE_TYPE_ACCESS:
2365
         return vtype_eq(at->pointed, bt->pointed);
427,834✔
2366
      case VCODE_TYPE_OFFSET:
2367
      case VCODE_TYPE_OPAQUE:
2368
      case VCODE_TYPE_DEBUG_LOCUS:
2369
      case VCODE_TYPE_TRIGGER:
2370
      case VCODE_TYPE_CONVERSION:
2371
         return true;
2372
      case VCODE_TYPE_RESOLUTION:
79,879✔
2373
      case VCODE_TYPE_CLOSURE:
2374
      case VCODE_TYPE_SIGNAL:
2375
      case VCODE_TYPE_FILE:
2376
         return vtype_eq(at->base, bt->base);
79,879✔
2377
      case VCODE_TYPE_RECORD:
62,698✔
2378
      case VCODE_TYPE_CONTEXT:
2379
         return at->name == bt->name;
62,698✔
2380
      }
2381

UNCOV
2382
      return false;
×
2383
   }
2384
}
2385

UNCOV
2386
void vcode_dump(void)
×
2387
{
UNCOV
2388
   vcode_dump_with_mark(-1, NULL, NULL);
×
UNCOV
2389
}
×
2390

2391
static vcode_type_t vtype_new(vtype_t *new)
2,437,781✔
2392
{
2393
   int index = active_unit->types.count - 1;
2,437,781✔
2394
   vcode_type_t type = MAKE_HANDLE(active_unit->depth, index);
2,437,781✔
2395

2396
   for (int i = 0; i < index; i++) {
29,601,093✔
2397
      vcode_type_t this = MAKE_HANDLE(active_unit->depth, i);
29,091,706✔
2398
      if (vtype_eq(this, type)) {
29,091,706✔
2399
         active_unit->types.count--;
1,928,394✔
2400
         return this;
1,928,394✔
2401
      }
2402
   }
2403

2404
   return type;
2405
}
2406

2407
vcode_type_t vtype_int(int64_t low, int64_t high)
1,604,622✔
2408
{
2409
   assert(active_unit != NULL);
1,604,622✔
2410

2411
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,604,622✔
2412
   n->kind = VCODE_TYPE_INT;
1,604,622✔
2413
   n->low  = low;
1,604,622✔
2414
   n->high = high;
1,604,622✔
2415

2416
   switch (bits_for_range(low, high)) {
1,604,622✔
2417
   case 64:
122,987✔
2418
      n->repr = low < 0 ? VCODE_REPR_I64 : VCODE_REPR_U64;
122,987✔
2419
      break;
122,987✔
2420
   case 32:
498,883✔
2421
      n->repr = low < 0 ? VCODE_REPR_I32 : VCODE_REPR_U32;
498,883✔
2422
      break;
498,883✔
2423
   case 16:
3,250✔
2424
      n->repr = low < 0 ? VCODE_REPR_I16 : VCODE_REPR_U16;
3,250✔
2425
      break;
3,250✔
2426
   case 8:
423,071✔
2427
      n->repr = low < 0 ? VCODE_REPR_I8 : VCODE_REPR_U8;
423,071✔
2428
      break;
423,071✔
2429
   case 1:
556,430✔
2430
      n->repr = VCODE_REPR_U1;
556,430✔
2431
      break;
556,430✔
2432
   case 0:
1✔
2433
      n->repr = VCODE_REPR_I64;    // Null range
1✔
2434
      break;
1✔
UNCOV
2435
   default:
×
UNCOV
2436
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
×
2437
   }
2438

2439
   return vtype_new(n);
1,604,622✔
2440
}
2441

2442
vcode_type_t vtype_bool(void)
280,643✔
2443
{
2444
   return vtype_int(0, 1);
280,643✔
2445
}
2446

2447
vcode_type_t vtype_carray(int size, vcode_type_t elem, vcode_type_t bounds)
35,645✔
2448
{
2449
   assert(active_unit != NULL);
35,645✔
2450

2451
   const vtype_kind_t ekind = vtype_kind(elem);
35,645✔
2452
   VCODE_ASSERT(ekind != VCODE_TYPE_CARRAY && ekind != VCODE_TYPE_UARRAY,
35,645✔
2453
                "array types may not be nested");
2454

2455
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
35,645✔
2456
   memset(n, '\0', sizeof(vtype_t));
35,645✔
2457
   n->kind   = VCODE_TYPE_CARRAY;
35,645✔
2458
   n->elem   = elem;
35,645✔
2459
   n->bounds = bounds;
35,645✔
2460
   n->size   = MAX(size, 0);
35,645✔
2461

2462
   return vtype_new(n);
35,645✔
2463
}
2464

2465
vcode_type_t vtype_find_named_record(ident_t name)
35,459✔
2466
{
2467
   assert(active_unit != NULL);
35,459✔
2468

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

2475
   return VCODE_INVALID_TYPE;
2476
}
2477

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

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

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

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

2503
   return handle;
10,428✔
2504
}
2505

2506
vcode_type_t vtype_uarray(int ndim, vcode_type_t elem, vcode_type_t bounds)
83,428✔
2507
{
2508
   assert(active_unit != NULL);
83,428✔
2509

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

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

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

2523
   return vtype_new(n);
83,428✔
2524
}
2525

2526
vcode_type_t vtype_pointer(vcode_type_t to)
176,296✔
2527
{
2528
   assert(active_unit != NULL);
176,296✔
2529

2530
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
176,296✔
2531
   n->kind    = VCODE_TYPE_POINTER;
176,296✔
2532
   n->pointed = to;
176,296✔
2533

2534
   VCODE_ASSERT(vtype_kind(to) != VCODE_TYPE_CARRAY,
176,296✔
2535
                "cannot get pointer to carray type");
2536

2537
   return vtype_new(n);
176,296✔
2538
}
2539

2540
vcode_type_t vtype_access(vcode_type_t to)
4,816✔
2541
{
2542
   assert(active_unit != NULL);
4,816✔
2543

2544
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
4,816✔
2545
   n->kind    = VCODE_TYPE_ACCESS;
4,816✔
2546
   n->pointed = to;
4,816✔
2547

2548
   return vtype_new(n);
4,816✔
2549
}
2550

2551
vcode_type_t vtype_signal(vcode_type_t base)
32,362✔
2552
{
2553
   assert(active_unit != NULL);
32,362✔
2554

2555
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
32,362✔
2556
   n->kind = VCODE_TYPE_SIGNAL;
32,362✔
2557
   n->base = base;
32,362✔
2558

2559
   VCODE_ASSERT(vtype_is_scalar(base), "signal base type must be scalar");
32,362✔
2560

2561
   return vtype_new(n);
32,362✔
2562
}
2563

2564
vcode_type_t vtype_resolution(vcode_type_t base)
783✔
2565
{
2566
   assert(active_unit != NULL);
783✔
2567

2568
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
783✔
2569
   n->kind = VCODE_TYPE_RESOLUTION;
783✔
2570
   n->base = base;
783✔
2571

2572
   return vtype_new(n);
783✔
2573
}
2574

2575
vcode_type_t vtype_closure(vcode_type_t result)
965✔
2576
{
2577
   assert(active_unit != NULL);
965✔
2578

2579
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
965✔
2580
   n->kind = VCODE_TYPE_CLOSURE;
965✔
2581
   n->base = result;
965✔
2582

2583
   return vtype_new(n);
965✔
2584
}
2585

2586
vcode_type_t vtype_context(ident_t name)
49,285✔
2587
{
2588
   assert(active_unit != NULL);
49,285✔
2589
   assert(name != NULL);
49,285✔
2590

2591
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
49,285✔
2592
   n->kind = VCODE_TYPE_CONTEXT;
49,285✔
2593
   n->name = name;
49,285✔
2594

2595
   return vtype_new(n);
49,285✔
2596
}
2597

2598
vcode_type_t vtype_file(vcode_type_t base)
582✔
2599
{
2600
   assert(active_unit != NULL);
582✔
2601

2602
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
582✔
2603
   n->kind = VCODE_TYPE_FILE;
582✔
2604
   n->base = base;
582✔
2605

2606
   return vtype_new(n);
582✔
2607
}
2608

2609
vcode_type_t vtype_offset(void)
252,612✔
2610
{
2611
   assert(active_unit != NULL);
252,612✔
2612

2613
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
252,612✔
2614
   n->kind = VCODE_TYPE_OFFSET;
252,612✔
2615
   n->low  = INT64_MIN;
252,612✔
2616
   n->high = INT64_MAX;
252,612✔
2617
   n->repr = VCODE_REPR_I64;
252,612✔
2618

2619
   return vtype_new(n);
252,612✔
2620
}
2621

2622
vcode_type_t vtype_time(void)
15,828✔
2623
{
2624
   return vtype_int(INT64_MIN, INT64_MAX);
15,828✔
2625
}
2626

2627
vcode_type_t vtype_char(void)
9,202✔
2628
{
2629
   return vtype_int(0, 255);
9,202✔
2630
}
2631

2632
vcode_type_t vtype_opaque(void)
1,118✔
2633
{
2634
   assert(active_unit != NULL);
1,118✔
2635

2636
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
1,118✔
2637
   n->kind = VCODE_TYPE_OPAQUE;
1,118✔
2638

2639
   return vtype_new(n);
1,118✔
2640
}
2641

2642
vcode_type_t vtype_debug_locus(void)
109,815✔
2643
{
2644
   assert(active_unit != NULL);
109,815✔
2645

2646
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
109,815✔
2647
   n->kind = VCODE_TYPE_DEBUG_LOCUS;
109,815✔
2648

2649
   return vtype_new(n);
109,815✔
2650
}
2651

2652
vcode_type_t vtype_trigger(void)
287✔
2653
{
2654
   assert(active_unit != NULL);
287✔
2655

2656
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
287✔
2657
   n->kind = VCODE_TYPE_TRIGGER;
287✔
2658

2659
   return vtype_new(n);
287✔
2660
}
2661

2662
vcode_type_t vtype_conversion(void)
180✔
2663
{
2664
   assert(active_unit != NULL);
180✔
2665

2666
   vtype_t *n = vtype_array_alloc(&(active_unit->types));
180✔
2667
   n->kind = VCODE_TYPE_CONVERSION;
180✔
2668

2669
   return vtype_new(n);
180✔
2670
}
2671

2672
vcode_type_t vtype_real(double low, double high)
79,762✔
2673
{
2674
   assert(active_unit != NULL);
79,762✔
2675

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

2681
   return vtype_new(n);
79,762✔
2682
}
2683

2684
vtype_kind_t vtype_kind(vcode_type_t type)
5,500,289✔
2685
{
2686
   vtype_t *vt = vcode_type_data(type);
5,500,289✔
2687
   return vt->kind;
5,500,289✔
2688
}
2689

2690
vtype_repr_t vtype_repr(vcode_type_t type)
449,982✔
2691
{
2692
   vtype_t *vt = vcode_type_data(type);
449,982✔
2693
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
449,982✔
2694
   return vt->repr;
449,982✔
2695
}
2696

2697
vcode_type_t vtype_elem(vcode_type_t type)
347,749✔
2698
{
2699
   vtype_t *vt = vcode_type_data(type);
347,749✔
2700
   assert(vt->kind == VCODE_TYPE_CARRAY || vt->kind == VCODE_TYPE_UARRAY);
347,749✔
2701
   return vt->elem;
347,749✔
2702
}
2703

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

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

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

2727
unsigned vtype_size(vcode_type_t type)
74,589✔
2728
{
2729
   vtype_t *vt = vcode_type_data(type);
74,589✔
2730
   assert(vt->kind == VCODE_TYPE_CARRAY);
74,589✔
2731
   return vt->size;
74,589✔
2732
}
2733

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

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

2748
ident_t vtype_name(vcode_type_t type)
2,716✔
2749
{
2750
   vtype_t *vt = vcode_type_data(type);
2,716✔
2751
   assert(vt->kind == VCODE_TYPE_RECORD || vt->kind == VCODE_TYPE_CONTEXT);
2,716✔
2752
   return vt->name;
2,716✔
2753
}
2754

2755
vcode_type_t vtype_pointed(vcode_type_t type)
365,946✔
2756
{
2757
   vtype_t *vt = vcode_type_data(type);
365,946✔
2758
   assert(vt->kind == VCODE_TYPE_POINTER || vt->kind == VCODE_TYPE_ACCESS);
365,946✔
2759
   return vt->pointed;
365,946✔
2760
}
2761

2762
int64_t vtype_low(vcode_type_t type)
55,620✔
2763
{
2764
   vtype_t *vt = vcode_type_data(type);
55,620✔
2765
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
55,620✔
2766
   return vt->low;
55,620✔
2767
}
2768

2769
int64_t vtype_high(vcode_type_t type)
53,543✔
2770
{
2771
   vtype_t *vt = vcode_type_data(type);
53,543✔
2772
   assert(vt->kind == VCODE_TYPE_INT || vt->kind == VCODE_TYPE_OFFSET);
53,543✔
2773
   return vt->high;
53,543✔
2774
}
2775

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

2782
bool vtype_is_scalar(vcode_type_t type)
373,717✔
2783
{
2784
   const vtype_kind_t kind = vtype_kind(type);
373,717✔
2785
   return kind == VCODE_TYPE_INT || kind == VCODE_TYPE_OFFSET
373,717✔
2786
      || kind == VCODE_TYPE_UARRAY || kind == VCODE_TYPE_POINTER
149,878✔
2787
      || kind == VCODE_TYPE_FILE || kind == VCODE_TYPE_ACCESS
2788
      || kind == VCODE_TYPE_REAL || kind == VCODE_TYPE_SIGNAL
2789
      || kind == VCODE_TYPE_CONTEXT || kind == VCODE_TYPE_TRIGGER;
373,717✔
2790
}
2791

2792
bool vtype_is_composite(vcode_type_t type)
22,564✔
2793
{
2794
   const vtype_kind_t kind = vtype_kind(type);
22,564✔
2795
   return kind == VCODE_TYPE_RECORD || kind == VCODE_TYPE_CARRAY;
22,564✔
2796
}
2797

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

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

2832
bool vtype_repr_signed(vtype_repr_t repr)
44,170✔
2833
{
2834
   return repr == VCODE_REPR_I8 || repr == VCODE_REPR_I16
44,170✔
2835
      || repr == VCODE_REPR_I32 || repr == VCODE_REPR_I64;
44,170✔
2836
}
2837

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

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

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

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

2884
int vcode_count_params(void)
10,758✔
2885
{
2886
   assert(active_unit != NULL);
10,758✔
2887
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
10,758✔
2888
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2889
          || active_unit->kind == VCODE_UNIT_PROPERTY
2890
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2891

2892
   return active_unit->params.count;
10,758✔
2893
}
2894

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

2904
   return active_unit->params.items[param].type;
28,309✔
2905
}
2906

2907
vcode_reg_t vcode_param_reg(int param)
35,997✔
2908
{
2909
   assert(active_unit != NULL);
35,997✔
2910
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
35,997✔
2911
          || active_unit->kind == VCODE_UNIT_PROCEDURE
2912
          || active_unit->kind == VCODE_UNIT_PROPERTY
2913
          || active_unit->kind == VCODE_UNIT_PROTECTED);
2914
   assert(param < active_unit->params.count);
35,997✔
2915

2916
   return active_unit->params.items[param].reg;
35,997✔
2917
}
2918

2919
vcode_block_t emit_block(void)
129,714✔
2920
{
2921
   assert(active_unit != NULL);
129,714✔
2922

2923
   vcode_block_t bnum = active_unit->blocks.count;
129,714✔
2924

2925
   block_t *bptr = block_array_alloc(&(active_unit->blocks));
129,714✔
2926
   memset(bptr, '\0', sizeof(block_t));
129,714✔
2927

2928
   if (active_block != VCODE_INVALID_BLOCK)
129,714✔
2929
      bptr->last_loc = active_unit->blocks.items[active_block].last_loc;
87,827✔
2930
   else
2931
      bptr->last_loc = LOC_INVALID;
41,887✔
2932

2933
   return bnum;
129,714✔
2934
}
2935

2936
void vcode_select_unit(vcode_unit_t unit)
167,380✔
2937
{
2938
   active_unit  = unit;
167,380✔
2939
   active_block = VCODE_INVALID_BLOCK;
167,380✔
2940
}
167,380✔
2941

2942
void vcode_select_block(vcode_block_t block)
540,342✔
2943
{
2944
   assert(active_unit != NULL);
540,342✔
2945
   active_block = block;
540,342✔
2946
}
540,342✔
2947

2948
vcode_block_t vcode_active_block(void)
1,406,362✔
2949
{
2950
   assert(active_unit != NULL);
1,406,362✔
2951
   assert(active_block != -1);
1,406,362✔
2952
   return active_block;
1,406,362✔
2953
}
2954

2955
const loc_t *vcode_last_loc(void)
632,202✔
2956
{
2957
   return &(vcode_block_data()->last_loc);
632,202✔
2958
}
2959

2960
vcode_unit_t vcode_active_unit(void)
812✔
2961
{
2962
   assert(active_unit != NULL);
812✔
2963
   return active_unit;
812✔
2964
}
2965

2966
ident_t vcode_unit_name(vcode_unit_t vu)
150,511✔
2967
{
2968
   assert(vu != NULL);
150,511✔
2969
   return vu->name;
150,511✔
2970
}
2971

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

2978
bool vcode_unit_has_escaping_tlab(vcode_unit_t vu)
4,665✔
2979
{
2980
   return !!(vu->flags & UNIT_ESCAPING_TLAB);
4,665✔
2981
}
2982

UNCOV
2983
int vcode_unit_depth(vcode_unit_t vu)
×
2984
{
UNCOV
2985
   assert(vu != NULL);
×
UNCOV
2986
   return vu->depth;
×
2987
}
2988

2989
void vcode_set_result(vcode_type_t type)
21,086✔
2990
{
2991
   assert(active_unit != NULL);
21,086✔
2992
   assert(active_unit->kind == VCODE_UNIT_FUNCTION
21,086✔
2993
          || active_unit->kind == VCODE_UNIT_THUNK);
2994

2995
   active_unit->result = type;
21,086✔
2996
}
21,086✔
2997

2998
vcode_type_t vcode_unit_result(vcode_unit_t vu)
31,019✔
2999
{
3000
   assert(vu != NULL);
31,019✔
3001
   assert(vu->kind == VCODE_UNIT_FUNCTION || vu->kind == VCODE_UNIT_THUNK);
31,019✔
3002
   return vu->result;
31,019✔
3003
}
3004

3005
vunit_kind_t vcode_unit_kind(vcode_unit_t vu)
345,344✔
3006
{
3007
   assert(vu != NULL);
345,344✔
3008
   return vu->kind;
345,344✔
3009
}
3010

3011
vcode_unit_t vcode_unit_context(vcode_unit_t vu)
128,290✔
3012
{
3013
   assert(vu != NULL);
128,290✔
3014
   return vu->context;
128,290✔
3015
}
3016

3017
void vcode_unit_object(vcode_unit_t vu, ident_t *module, ptrdiff_t *offset)
72,424✔
3018
{
3019
   assert(vu != NULL);
72,424✔
3020
   *module = vu->module;
72,424✔
3021
   *offset = vu->offset;
72,424✔
3022
}
72,424✔
3023

3024
static unsigned vcode_unit_calc_depth(vcode_unit_t unit)
53,741✔
3025
{
3026
   int hops = 0;
53,741✔
3027
   for (; (unit = unit->context); hops++)
131,228✔
3028
      ;
3029
   return hops;
53,741✔
3030
}
3031

3032
static void vcode_add_child(vcode_unit_t context, vcode_unit_t child)
26,109✔
3033
{
3034
   assert(context->kind != VCODE_UNIT_THUNK);
26,109✔
3035

3036
   child->next = NULL;
26,109✔
3037
   if (context->children == NULL)
26,109✔
3038
      context->children = child;
10,537✔
3039
   else {
3040
      vcode_unit_t it;
3041
      for (it = context->children; it->next != NULL; it = it->next)
747,567✔
3042
         ;
3043
      it->next = child;
15,572✔
3044
   }
3045
}
26,109✔
3046

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

3056
   object_locus(obj, &vu->module, &vu->offset);
10,631✔
3057

3058
   vcode_add_child(context, vu);
10,631✔
3059

3060
   vcode_select_unit(vu);
10,631✔
3061
   vcode_select_block(emit_block());
10,631✔
3062
   emit_debug_info(&(obj->loc));
10,631✔
3063

3064
   return vu;
10,631✔
3065
}
3066

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

3076
   object_locus(obj, &vu->module, &vu->offset);
235✔
3077

3078
   vcode_add_child(context, vu);
235✔
3079

3080
   vcode_select_unit(vu);
235✔
3081
   vcode_select_block(emit_block());
235✔
3082
   emit_debug_info(&(obj->loc));
235✔
3083

3084
   return vu;
235✔
3085
}
3086

3087
vcode_unit_t emit_process(ident_t name, object_t *obj, vcode_unit_t context)
8,520✔
3088
{
3089
   assert(context->kind == VCODE_UNIT_INSTANCE
8,520✔
3090
          || context->kind == VCODE_UNIT_SHAPE);
3091

3092
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,520✔
3093
   vu->kind     = VCODE_UNIT_PROCESS;
8,520✔
3094
   vu->name     = name;
8,520✔
3095
   vu->context  = context;
8,520✔
3096
   vu->depth    = vcode_unit_calc_depth(vu);
8,520✔
3097
   vu->result   = VCODE_INVALID_TYPE;
8,520✔
3098

3099
   object_locus(obj, &vu->module, &vu->offset);
8,520✔
3100

3101
   vcode_add_child(context, vu);
8,520✔
3102

3103
   vcode_select_unit(vu);
8,520✔
3104
   vcode_select_block(emit_block());
8,520✔
3105
   emit_debug_info(&(obj->loc));
8,520✔
3106

3107
   return vu;
8,520✔
3108
}
3109

3110
vcode_unit_t emit_instance(ident_t name, object_t *obj, vcode_unit_t context)
8,657✔
3111
{
3112
   assert(context == NULL || context->kind == VCODE_UNIT_INSTANCE);
8,657✔
3113

3114
   vcode_unit_t vu = xcalloc(sizeof(struct _vcode_unit));
8,657✔
3115
   vu->kind     = VCODE_UNIT_INSTANCE;
8,657✔
3116
   vu->name     = name;
8,657✔
3117
   vu->context  = context;
8,657✔
3118
   vu->depth    = vcode_unit_calc_depth(vu);
8,657✔
3119
   vu->result   = VCODE_INVALID_TYPE;
8,657✔
3120

3121
   object_locus(obj, &vu->module, &vu->offset);
8,657✔
3122

3123
   if (context != NULL)
8,657✔
3124
      vcode_add_child(context, vu);
5,379✔
3125

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

3130
   return vu;
8,657✔
3131
}
3132

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

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

3144
   object_locus(obj, &vu->module, &vu->offset);
51✔
3145

3146
   if (context != NULL)
51✔
UNCOV
3147
      vcode_add_child(context, vu);
×
3148

3149
   vcode_select_unit(vu);
51✔
3150
   vcode_select_block(emit_block());
51✔
3151
   emit_debug_info(&(obj->loc));
51✔
3152

3153
   return vu;
51✔
3154
}
3155

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

3165
   object_locus(obj, &vu->module, &vu->offset);
1,668✔
3166

3167
   if (context != NULL)
1,668✔
3168
      vcode_add_child(context, vu);
170✔
3169

3170
   vcode_select_unit(vu);
1,668✔
3171
   vcode_select_block(emit_block());
1,668✔
3172
   emit_debug_info(&(obj->loc));
1,668✔
3173

3174
   return vu;
1,668✔
3175
}
3176

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

3186
   object_locus(obj, &vu->module, &vu->offset);
166✔
3187

3188
   if (context != NULL)
166✔
3189
      vcode_add_child(context, vu);
166✔
3190

3191
   vcode_select_unit(vu);
166✔
3192
   vcode_select_block(emit_block());
166✔
3193
   emit_debug_info(&(obj->loc));
166✔
3194

3195
   return vu;
166✔
3196
}
3197

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

3207
   object_locus(obj, &vu->module, &vu->offset);
105✔
3208

3209
   if (context != NULL)
105✔
3210
      vcode_add_child(context, vu);
105✔
3211

3212
   vcode_select_unit(vu);
105✔
3213
   vcode_select_block(emit_block());
105✔
3214
   emit_debug_info(&(obj->loc));
105✔
3215

3216
   return vu;
105✔
3217
}
3218

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

3229
   object_locus(obj, &vu->module, &vu->offset);
11,854✔
3230

3231
   if (context != NULL)
11,854✔
3232
      vcode_add_child(context, vu);
903✔
3233

3234
   vcode_select_unit(vu);
11,854✔
3235
   vcode_select_block(emit_block());
11,854✔
3236

3237
   return vu;
11,854✔
3238
}
3239

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

3250
   op_t *op = vcode_add_op(VCODE_OP_ASSERT);
13,206✔
3251
   vcode_add_arg(op, value);
13,206✔
3252
   vcode_add_arg(op, severity);
13,206✔
3253
   vcode_add_arg(op, message);
13,206✔
3254
   vcode_add_arg(op, length);
13,206✔
3255
   vcode_add_arg(op, locus);
13,206✔
3256

3257
   if (hint_left != VCODE_INVALID_REG) {
13,206✔
3258
      vcode_add_arg(op, hint_left);
5,473✔
3259
      vcode_add_arg(op, hint_right);
5,473✔
3260

3261
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_left)),
5,473✔
3262
                   "left hint must be scalar");
3263
      VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(hint_right)),
5,473✔
3264
                   "right hint must be scalar");
3265
   }
3266

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

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

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

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

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

3328
   // Reuse any previous operation in this block with the same arguments
3329
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CMP) {
652,790✔
3330
      if (other->args.count == 2 && other->args.items[0] == lhs
27,560✔
3331
          && other->args.items[1] == rhs && other->cmp == cmp)
1,485✔
3332
         return other->result;
356✔
3333
   }
3334

3335
   op_t *op = vcode_add_op(VCODE_OP_CMP);
35,592✔
3336
   vcode_add_arg(op, lhs);
35,592✔
3337
   vcode_add_arg(op, rhs);
35,592✔
3338
   op->cmp    = cmp;
35,592✔
3339
   op->result = vcode_add_reg(vtype_bool());
35,592✔
3340

3341
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vcode_reg_type(rhs)),
35,592✔
3342
                "arguments to cmp are not the same type");
3343

3344
   return op->result;
3345
}
3346

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

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

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

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

3368
      reg_t *rr = vcode_reg_data(o->result);
29,911✔
3369
      rr->bounds = bounds;
29,911✔
3370

3371
      return o->result;
29,911✔
3372
   }
3373
}
3374

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

3383
   vcode_block_array_add(&(o->targets), resume_bb);
777✔
3384

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

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

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

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

3407
   reg_t *r = vcode_reg_data(op->result);
7,406✔
3408
   r->bounds = bounds;
7,406✔
3409

3410
   return op->result;
7,406✔
3411
}
3412

3413
vcode_reg_t emit_const(vcode_type_t type, int64_t value)
927,411✔
3414
{
3415
   // Reuse any previous constant in this block with the same type and value
3416
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST) {
19,995,110✔
3417
      if (other->value == value && vtype_eq(type, other->type))
7,499,541✔
3418
         return other->result;
544,720✔
3419
   }
3420

3421
   op_t *op = vcode_add_op(VCODE_OP_CONST);
382,691✔
3422
   op->value  = value;
382,691✔
3423
   op->type   = type;
382,691✔
3424
   op->result = vcode_add_reg(type);
382,691✔
3425

3426
   vtype_kind_t type_kind = vtype_kind(type);
382,691✔
3427
   VCODE_ASSERT(type_kind == VCODE_TYPE_INT || type_kind == VCODE_TYPE_OFFSET,
382,691✔
3428
                "constant must have integer or offset type");
3429

3430
   reg_t *r = vcode_reg_data(op->result);
382,691✔
3431
   r->bounds = vtype_int(value, value);
382,691✔
3432

3433
   return op->result;
382,691✔
3434
}
3435

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

3443
   op_t *op = vcode_add_op(VCODE_OP_CONST_REAL);
26,324✔
3444
   op->real   = value;
26,324✔
3445
   op->type   = type;
26,324✔
3446
   op->result = vcode_add_reg(op->type);
26,324✔
3447

3448
   reg_t *r = vcode_reg_data(op->result);
26,324✔
3449
   r->bounds = vtype_real(value, value);
26,324✔
3450

3451
   return op->result;
26,324✔
3452
}
3453

3454
vcode_reg_t emit_const_array(vcode_type_t type, vcode_reg_t *values, int num)
26,388✔
3455
{
3456
   vtype_kind_t kind = vtype_kind(type);
26,388✔
3457

3458
   // Reuse any previous operation in this block with the same arguments
3459
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONST_ARRAY) {
1,126,308✔
3460
      if (other->args.count != num)
115,033✔
3461
         continue;
69,022✔
3462
      else if (!vtype_eq(vcode_reg_type(other->result), type))
46,011✔
3463
         continue;
586✔
3464

3465
      bool match = true;
3466
      for (int i = 0; match && i < num; i++) {
287,592✔
3467
         if (other->args.items[i] != values[i])
242,167✔
3468
            match = false;
39,420✔
3469
      }
3470

3471
      if (match) return other->result;
45,425✔
3472
   }
3473

3474
   op_t *op = vcode_add_op(VCODE_OP_CONST_ARRAY);
20,383✔
3475
   op->result = vcode_add_reg(type);
20,383✔
3476

3477
   for (int i = 0; i < num; i++)
1,159,330✔
3478
      vcode_add_arg(op, values[i]);
1,138,947✔
3479

3480
   VCODE_ASSERT(kind == VCODE_TYPE_CARRAY,
20,383✔
3481
                "constant array must have constrained array type");
3482
   VCODE_ASSERT(vtype_size(type) == num, "expected %d elements but have %d",
20,383✔
3483
                vtype_size(type), num);
3484

3485
#ifdef DEBUG
3486
   vcode_type_t elem = vtype_elem(type);
20,383✔
3487
   for (int i = 0; i < num; i++) {
1,159,330✔
3488
      VCODE_ASSERT(vtype_eq(vcode_reg_type(values[i]), elem),
1,138,947✔
3489
                   "wrong element type for item %d", i);
3490
      vcode_assert_const(values[i], "array");
1,138,947✔
3491
   }
3492
#endif
3493

3494
   reg_t *r = vcode_reg_data(op->result);
20,383✔
3495
   r->bounds = vtype_elem(type);
20,383✔
3496

3497
   return op->result;
20,383✔
3498
}
3499

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

3508
   op_t *op = vcode_add_op(VCODE_OP_CONST_REP);
740✔
3509
   op->value = rep;
740✔
3510
   vcode_add_arg(op, value);
740✔
3511

3512
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CARRAY,
740✔
3513
                "constant array must have constrained array type");
3514

3515
   DEBUG_ONLY(vcode_assert_const(value, "repeat"));
740✔
3516

3517
   op->result = vcode_add_reg(type);
740✔
3518

3519
   reg_t *r = vcode_reg_data(op->result);
740✔
3520
   r->bounds = vtype_bounds(type);
740✔
3521

3522
   return op->result;
740✔
3523
}
3524

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

3534
         if (same_regs)
930✔
3535
            return other->result;
217✔
3536
      }
3537
   }
3538

3539
   op_t *op = vcode_add_op(VCODE_OP_CONST_RECORD);
2,499✔
3540
   op->type   = type;
2,499✔
3541
   op->result = vcode_add_reg(type);
2,499✔
3542

3543
   for (int i = 0; i < num; i++)
9,677✔
3544
      vcode_add_arg(op, values[i]);
7,178✔
3545

3546
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_RECORD,
2,499✔
3547
                "constant record must have record type");
3548

3549
   VCODE_ASSERT(vtype_fields(type) == num, "expected %d fields but have %d",
2,499✔
3550
                vtype_fields(type), num);
3551

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

3560
   return op->result;
2,499✔
3561
}
3562

3563
vcode_reg_t emit_address_of(vcode_reg_t value)
28,600✔
3564
{
3565
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ADDRESS_OF) {
1,220,347✔
3566
      if (other->args.items[0] == value)
116,376✔
3567
         return other->result;
6,036✔
3568
   }
3569

3570
   op_t *op = vcode_add_op(VCODE_OP_ADDRESS_OF);
22,564✔
3571
   vcode_add_arg(op, value);
22,564✔
3572

3573
   vcode_type_t type = vcode_reg_type(value);
22,564✔
3574
   VCODE_ASSERT(vtype_is_composite(type),
22,564✔
3575
                "address of argument must be record or array");
3576

3577
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
22,564✔
3578
      vcode_type_t elem = vtype_elem(type);
20,563✔
3579
      op->result = vcode_add_reg(vtype_pointer(elem));
20,563✔
3580

3581
      reg_t *rr = vcode_reg_data(op->result);
20,563✔
3582
      rr->bounds = elem;
20,563✔
3583

3584
      return op->result;
20,563✔
3585
   }
3586
   else
3587
      return (op->result = vcode_add_reg(vtype_pointer(type)));
2,001✔
3588
}
3589

3590
void emit_wait(vcode_block_t target, vcode_reg_t time)
12,419✔
3591
{
3592
   op_t *op = vcode_add_op(VCODE_OP_WAIT);
12,419✔
3593
   vcode_add_target(op, target);
12,419✔
3594
   vcode_add_arg(op, time);
12,419✔
3595

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

3604
void emit_jump(vcode_block_t target)
33,335✔
3605
{
3606
   op_t *op = vcode_add_op(VCODE_OP_JUMP);
33,335✔
3607
   vcode_add_target(op, target);
33,335✔
3608

3609
   VCODE_ASSERT(target != VCODE_INVALID_BLOCK, "invalid jump target");
33,335✔
3610
}
33,335✔
3611

3612
vcode_var_t emit_var(vcode_type_t type, vcode_type_t bounds, ident_t name,
45,911✔
3613
                     vcode_var_flags_t flags)
3614
{
3615
   assert(active_unit != NULL);
45,911✔
3616

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

3625
   return var;
45,911✔
3626
}
3627

3628
vcode_reg_t emit_param(vcode_type_t type, vcode_type_t bounds, ident_t name)
30,270✔
3629
{
3630
   assert(active_unit != NULL);
30,270✔
3631

3632
   param_t *p = param_array_alloc(&(active_unit->params));
30,270✔
3633
   memset(p, '\0', sizeof(param_t));
30,270✔
3634
   p->type   = type;
30,270✔
3635
   p->bounds = bounds;
30,270✔
3636
   p->name   = name;
30,270✔
3637
   p->reg    = vcode_add_reg(type);
30,270✔
3638

3639
   reg_t *rr = vcode_reg_data(p->reg);
30,270✔
3640
   rr->bounds = bounds;
30,270✔
3641

3642
   return p->reg;
30,270✔
3643
}
3644

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

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

3680
      case UNSAFE:
3681
         break;
3682
      }
3683
   }
3684

3685
   if (fold != VCODE_INVALID_REG && state != UNSAFE)
36,111✔
3686
      return fold;
3687

3688
   var_t *v = vcode_var_data(var);
31,793✔
3689

3690
   op_t *op = vcode_add_op(VCODE_OP_LOAD);
31,793✔
3691
   op->address = var;
31,793✔
3692
   op->result  = vcode_add_reg(v->type);
31,793✔
3693

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

3696
   reg_t *r = vcode_reg_data(op->result);
31,793✔
3697
   r->bounds = v->bounds;
31,793✔
3698

3699
   return op->result;
31,793✔
3700
}
3701

3702
vcode_reg_t emit_load_indirect(vcode_reg_t reg)
85,629✔
3703
{
3704
   VCODE_FOR_EACH_OP(other) {
1,024,821✔
3705
      if (other->kind == VCODE_OP_LOAD_INDIRECT
964,776✔
3706
          && other->args.items[0] == reg) {
138,552✔
3707
         return other->result;
6,873✔
3708
      }
3709
      else if (other->kind == VCODE_OP_FCALL
957,903✔
3710
               || other->kind == VCODE_OP_PCALL
957,903✔
3711
               || other->kind == VCODE_OP_STORE
3712
               || other->kind == VCODE_OP_STORE_INDIRECT
3713
               || other->kind == VCODE_OP_MEMSET
3714
               || other->kind == VCODE_OP_COPY
3715
               || other->kind == VCODE_OP_FILE_READ)
3716
         break;   // May write to this pointer
3717
   }
3718

3719
   op_t *op = vcode_add_op(VCODE_OP_LOAD_INDIRECT);
78,756✔
3720
   vcode_add_arg(op, reg);
78,756✔
3721

3722
   vcode_type_t rtype = vcode_reg_type(reg);
78,756✔
3723

3724
   VCODE_ASSERT(vtype_kind(rtype) == VCODE_TYPE_POINTER,
78,756✔
3725
                "load indirect with non-pointer argument");
3726

3727
   vcode_type_t deref = vtype_pointed(rtype);
78,756✔
3728
   op->result = vcode_add_reg(deref);
78,756✔
3729

3730
   VCODE_ASSERT(vtype_is_scalar(deref), "cannot load non-scalar type");
78,756✔
3731

3732
   vcode_reg_data(op->result)->bounds = vcode_reg_data(reg)->bounds;
78,756✔
3733

3734
   return op->result;
78,756✔
3735
}
3736

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

3754
   var_t *v = vcode_var_data(var);
56,257✔
3755
   reg_t *r = vcode_reg_data(reg);
56,257✔
3756

3757
   op_t *op = vcode_add_op(VCODE_OP_STORE);
56,257✔
3758
   vcode_add_arg(op, reg);
56,257✔
3759
   op->address = var;
56,257✔
3760

3761
   VCODE_ASSERT(vtype_eq(v->type, r->type),
56,257✔
3762
                "variable and stored value do not have same type");
3763
   VCODE_ASSERT(vtype_is_scalar(v->type), "cannot store non-scalar type");
56,257✔
3764
}
56,257✔
3765

3766
void emit_store_indirect(vcode_reg_t reg, vcode_reg_t ptr)
11,800✔
3767
{
3768
   reg_t *p = vcode_reg_data(ptr);
11,800✔
3769
   reg_t *r = vcode_reg_data(reg);
11,800✔
3770

3771
   op_t *op = vcode_add_op(VCODE_OP_STORE_INDIRECT);
11,800✔
3772
   vcode_add_arg(op, reg);
11,800✔
3773
   vcode_add_arg(op, ptr);
11,800✔
3774

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

3782
static vcode_reg_t emit_arith(vcode_op_t kind, vcode_reg_t lhs, vcode_reg_t rhs,
49,030✔
3783
                              vcode_reg_t locus)
3784
{
3785
   // Reuse any previous operation in this block with the same arguments
3786
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
1,042,545✔
3787
      if (other->args.items[0] == lhs && other->args.items[1] == rhs)
59,028✔
3788
         return other->result;
3,076✔
3789
   }
3790

3791
   op_t *op = vcode_add_op(kind);
45,954✔
3792
   vcode_add_arg(op, lhs);
45,954✔
3793
   vcode_add_arg(op, rhs);
45,954✔
3794
   if (locus != VCODE_INVALID_REG)
45,954✔
3795
      vcode_add_arg(op, locus);
4,896✔
3796

3797
   op->result = vcode_add_reg(vcode_reg_type(lhs));
45,954✔
3798

3799
   vcode_type_t lhs_type = vcode_reg_type(lhs);
45,954✔
3800
   vcode_type_t rhs_type = vcode_reg_type(rhs);
45,954✔
3801

3802
   VCODE_ASSERT(vtype_eq(lhs_type, rhs_type),
45,954✔
3803
                "arguments to %s are not the same type", vcode_op_string(kind));
3804

3805
   return op->result;
3806
}
3807

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

3823
   reg_t *lhs_r = vcode_reg_data(lhs);
2,899✔
3824
   reg_t *rhs_r = vcode_reg_data(rhs);
2,899✔
3825

3826
   vtype_t *bl = vcode_type_data(lhs_r->bounds);
2,899✔
3827
   vtype_t *br = vcode_type_data(rhs_r->bounds);
2,899✔
3828

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

3836
      double min = MIN(MIN(ll, lh), MIN(hl, hh));
1,596✔
3837
      double max = MAX(MAX(ll, lh), MAX(hl, hh));
1,818✔
3838

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

3847
      int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
2,159✔
3848
      int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
2,159✔
3849

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

3856
      vbounds = vtype_int(min, max);
2,159✔
3857
   }
3858

3859
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
2,899✔
3860

3861
   if (vbounds != VCODE_INVALID_TYPE)
2,899✔
3862
      vcode_reg_data(reg)->bounds = vbounds;
2,899✔
3863

3864
   return reg;
3865
}
3866

3867
vcode_reg_t emit_mul(vcode_reg_t lhs, vcode_reg_t rhs)
32,908✔
3868
{
3869
   return emit_mul_op(VCODE_OP_MUL, lhs, rhs, VCODE_INVALID_REG);
32,908✔
3870
}
3871

3872
vcode_reg_t emit_trap_mul(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
846✔
3873
{
3874
   vcode_reg_t result = emit_mul_op(VCODE_OP_TRAP_MUL, lhs, rhs, locus);
846✔
3875

3876
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
846✔
3877
                "trapping add may only be used with integer types");
3878

3879
   return result;
846✔
3880
}
3881

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

3892
   vcode_reg_t reg = emit_arith(VCODE_OP_DIV, lhs, rhs, VCODE_INVALID_REG);
968✔
3893

3894
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
968✔
3895

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

3905
   return reg;
3906
}
3907

3908
vcode_reg_t emit_exp(vcode_reg_t lhs, vcode_reg_t rhs)
79✔
3909
{
3910
   return emit_arith(VCODE_OP_EXP, lhs, rhs, VCODE_INVALID_REG);
79✔
3911
}
3912

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

3923
   vcode_reg_t result = emit_arith(VCODE_OP_TRAP_EXP, lhs, rhs, locus);
580✔
3924

3925
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
580✔
3926
                "trapping exp may only be used with integer types");
3927

3928
   return result;
3929
}
3930

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

3938
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
196✔
3939
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
196✔
3940

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

3946
      reg_t *rr = vcode_reg_data(reg);
28✔
3947
      rr->bounds = vtype_int(0, MAX(0, br->high - 1));
28✔
3948

3949
      return reg;
28✔
3950
   }
3951
   else
3952
      return emit_arith(VCODE_OP_MOD, lhs, rhs, VCODE_INVALID_REG);
168✔
3953
}
3954

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

3962
   vcode_reg_t reg = emit_arith(VCODE_OP_REM, lhs, rhs, VCODE_INVALID_REG);
74✔
3963

3964
   vtype_t *bl = vcode_type_data(vcode_reg_data(lhs)->bounds);
74✔
3965
   vtype_t *br = vcode_type_data(vcode_reg_data(rhs)->bounds);
74✔
3966

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

3972
   return reg;
3973
}
3974

3975
static vcode_reg_t emit_add_op(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs,
42,656✔
3976
                               vcode_reg_t locus)
3977
{
3978
   int64_t lconst, rconst;
42,656✔
3979
   const bool l_is_const = vcode_reg_const(lhs, &lconst);
42,656✔
3980
   const bool r_is_const = vcode_reg_const(rhs, &rconst);
42,656✔
3981
   if (l_is_const && r_is_const)
42,656✔
3982
      return emit_const(vcode_reg_type(lhs), lconst + rconst);
17,265✔
3983
   else if (r_is_const && rconst == 0)
25,391✔
3984
      return lhs;
3985
   else if (l_is_const && lconst == 0)
25,385✔
3986
      return rhs;
3987

3988
   vcode_type_t vbounds = VCODE_INVALID_TYPE;
15,715✔
3989
   if (vcode_reg_kind(lhs) != VCODE_TYPE_REAL) {
15,715✔
3990
      reg_t *lhs_r = vcode_reg_data(lhs);
15,428✔
3991
      reg_t *rhs_r = vcode_reg_data(rhs);
15,428✔
3992

3993
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
15,428✔
3994
      vtype_t *br = vcode_type_data(rhs_r->bounds);
15,428✔
3995

3996
      int64_t rbl = sadd64(bl->low, br->low);
15,428✔
3997
      int64_t rbh = sadd64(bl->high, br->high);
15,428✔
3998

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

4005
      vbounds = vtype_int(rbl, rbh);
15,428✔
4006
   }
4007

4008
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
15,715✔
4009

4010
   if (vbounds != VCODE_INVALID_TYPE)
15,715✔
4011
      vcode_reg_data(reg)->bounds = vbounds;
15,428✔
4012

4013
   return reg;
4014
}
4015

4016
vcode_reg_t emit_add(vcode_reg_t lhs, vcode_reg_t rhs)
39,862✔
4017
{
4018
   return emit_add_op(VCODE_OP_ADD, lhs, rhs, VCODE_INVALID_REG);
39,862✔
4019
}
4020

4021
vcode_reg_t emit_trap_add(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
2,794✔
4022
{
4023
   vcode_reg_t result = emit_add_op(VCODE_OP_TRAP_ADD, lhs, rhs, locus);
2,794✔
4024

4025
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
2,794✔
4026
                "trapping add may only be used with integer types");
4027

4028
   return result;
2,794✔
4029
}
4030

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

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

4049
      vtype_t *bl = vcode_type_data(lhs_r->bounds);
22,344✔
4050
      vtype_t *br = vcode_type_data(rhs_r->bounds);
22,344✔
4051

4052
      int64_t rbl = ssub64(bl->low, br->high);
22,344✔
4053
      int64_t rbh = ssub64(bl->high, br->low);
22,344✔
4054

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

4061
      vbounds = vtype_int(rbl, rbh);
22,344✔
4062
   }
4063

4064
   vcode_reg_t reg = emit_arith(op, lhs, rhs, locus);
22,650✔
4065

4066
   if (vbounds != VCODE_INVALID_TYPE)
22,650✔
4067
      vcode_reg_data(reg)->bounds = vbounds;
22,344✔
4068

4069
   return reg;
4070
}
4071

4072
vcode_reg_t emit_sub(vcode_reg_t lhs, vcode_reg_t rhs)
32,699✔
4073
{
4074
   return emit_sub_op(VCODE_OP_SUB, lhs, rhs, VCODE_INVALID_REG);
32,699✔
4075
}
4076

4077
vcode_reg_t emit_trap_sub(vcode_reg_t lhs, vcode_reg_t rhs, vcode_reg_t locus)
6,617✔
4078
{
4079
   vcode_reg_t result = emit_sub_op(VCODE_OP_TRAP_SUB, lhs, rhs, locus);
6,617✔
4080

4081
   VCODE_ASSERT(vcode_reg_kind(result) == VCODE_TYPE_INT,
6,617✔
4082
                "trapping sub may only be used with integer types");
4083

4084
   return result;
6,617✔
4085
}
4086

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

4096
   case VCODE_TYPE_RECORD:
5,968✔
4097
      op->type = vtype_pointer(var->type);
5,968✔
4098
      op->result = vcode_add_reg(op->type);
5,968✔
4099
      break;
5,968✔
4100

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

4116
   default:
UNCOV
4117
      VCODE_ASSERT(false, "variable %s cannot be indexed",
×
4118
                   istr(var->name));
4119
   }
4120
}
55,892✔
4121

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

4133
   op_t *op = vcode_add_op(VCODE_OP_INDEX);
14,498✔
4134
   op->address = var;
14,498✔
4135

4136
   if (offset != VCODE_INVALID_REG)
14,498✔
4137
      vcode_add_arg(op, offset);
×
4138

4139
   vcode_calculate_var_index_type(op, vcode_var_data(var));
14,498✔
4140

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

4145
   return op->result;
14,498✔
4146
}
4147

4148
vcode_reg_t emit_cast(vcode_type_t type, vcode_type_t bounds, vcode_reg_t reg)
202,600✔
4149
{
4150
   if (vtype_eq(vcode_reg_type(reg), type))
202,600✔
4151
      return reg;
202,600✔
4152

4153
   vtype_kind_t from = vtype_kind(vcode_reg_type(reg));
76,013✔
4154
   vtype_kind_t to   = vtype_kind(type);
76,013✔
4155

4156
   const bool integral =
152,026✔
4157
      (from == VCODE_TYPE_OFFSET || from == VCODE_TYPE_INT)
76,013✔
4158
      && (to == VCODE_TYPE_OFFSET || to == VCODE_TYPE_INT);
76,013✔
4159

4160
   int64_t value;
76,013✔
4161
   if (integral && vcode_reg_const(reg, &value))
76,013✔
4162
      return emit_const(type, value);
14,444✔
4163

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

4170
   op_t *op = vcode_add_op(VCODE_OP_CAST);
47,052✔
4171
   vcode_add_arg(op, reg);
47,052✔
4172
   op->type   = type;
47,052✔
4173
   op->result = vcode_add_reg(type);
47,052✔
4174

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

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

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

UNCOV
4199
   VCODE_ASSERT(false, "invalid type conversion in cast");
×
4200
}
4201

4202
void emit_return(vcode_reg_t reg)
50,259✔
4203
{
4204
   op_t *op = vcode_add_op(VCODE_OP_RETURN);
50,259✔
4205
   if (reg != VCODE_INVALID_REG) {
50,259✔
4206
      vcode_add_arg(op, reg);
27,797✔
4207

4208
      const vtype_kind_t rkind = vcode_reg_kind(reg);
27,797✔
4209
      if (rkind == VCODE_TYPE_POINTER || rkind == VCODE_TYPE_UARRAY) {
27,797✔
4210
         vcode_heap_allocate(reg);
8,169✔
4211
         active_unit->flags |= UNIT_ESCAPING_TLAB;
8,169✔
4212
      }
4213

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

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

4237
   op_t *op = vcode_add_op(VCODE_OP_SCHED_WAVEFORM);
9,846✔
4238
   vcode_add_arg(op, nets);
9,846✔
4239
   vcode_add_arg(op, nnets);
9,846✔
4240
   vcode_add_arg(op, values);
9,846✔
4241
   vcode_add_arg(op, reject);
9,846✔
4242
   vcode_add_arg(op, after);
9,846✔
4243

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

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

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

4265
void emit_release(vcode_reg_t nets, vcode_reg_t nnets)
30✔
4266
{
4267
   op_t *op = vcode_add_op(VCODE_OP_RELEASE);
30✔
4268
   vcode_add_arg(op, nets);
30✔
4269
   vcode_add_arg(op, nnets);
30✔
4270

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

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

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

4292
void emit_cond(vcode_reg_t test, vcode_block_t btrue, vcode_block_t bfalse)
34,602✔
4293
{
4294
   int64_t tconst;
34,602✔
4295
   if (vcode_reg_const(test, &tconst)) {
34,602✔
4296
      emit_jump(!!tconst ? btrue : bfalse);
4,579✔
4297
      return;
2,722✔
4298
   }
4299

4300
   op_t *op = vcode_add_op(VCODE_OP_COND);
31,880✔
4301
   vcode_add_arg(op, test);
31,880✔
4302
   vcode_add_target(op, btrue);
31,880✔
4303
   vcode_add_target(op, bfalse);
31,880✔
4304

4305
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
31,880✔
4306
                "cond test is not a bool");
4307
   VCODE_ASSERT(btrue != VCODE_INVALID_BLOCK && bfalse != VCODE_INVALID_BLOCK,
31,880✔
4308
                "invalid cond targets");
4309
}
4310

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

4317
   op_t *op = vcode_add_op(VCODE_OP_NEG);
7,433✔
4318
   vcode_add_arg(op, lhs);
7,433✔
4319
   op->result = vcode_add_reg(vcode_reg_type(lhs));
7,433✔
4320

4321
   return op->result;
7,433✔
4322
}
4323

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

4332
   op_t *op = vcode_add_op(VCODE_OP_TRAP_NEG);
563✔
4333
   vcode_add_arg(op, lhs);
563✔
4334
   vcode_add_arg(op, locus);
563✔
4335

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

4341
   return (op->result = vcode_add_reg(vcode_reg_type(lhs)));
563✔
4342
}
4343

4344
vcode_reg_t emit_abs(vcode_reg_t lhs)
245✔
4345
{
4346
   int64_t lconst;
245✔
4347
   if (vcode_reg_const(lhs, &lconst))
245✔
4348
      return emit_const(vcode_reg_type(lhs), llabs(lconst));
1✔
4349

4350
   op_t *op = vcode_add_op(VCODE_OP_ABS);
244✔
4351
   vcode_add_arg(op, lhs);
244✔
4352
   op->result = vcode_add_reg(vcode_reg_type(lhs));
244✔
4353

4354
   return op->result;
244✔
4355
}
4356

4357
void emit_comment(const char *fmt, ...)
42,098✔
4358
{
4359
#ifndef NDEBUG
4360
   va_list ap;
42,098✔
4361
   va_start(ap, fmt);
42,098✔
4362

4363
   char *buf = xvasprintf(fmt, ap);
42,098✔
4364
   for (char *p = buf + strlen(buf) - 1;
42,098✔
4365
        p >= buf && isspace_iso88591(*p); p--)
42,098✔
UNCOV
4366
      *p = '\0';
×
4367

4368
   vcode_add_op(VCODE_OP_COMMENT)->comment = buf;
42,098✔
4369
   va_end(ap);
42,098✔
4370
#endif
4371
}
42,098✔
4372

4373
vcode_reg_t emit_select(vcode_reg_t test, vcode_reg_t rtrue,
18,671✔
4374
                        vcode_reg_t rfalse)
4375
{
4376
   int64_t tconst;
18,671✔
4377
   if (vcode_reg_const(test, &tconst))
18,671✔
4378
      return !!tconst ? rtrue : rfalse;
4,255✔
4379
   else if (rtrue == rfalse)
14,416✔
4380
      return rtrue;
4381

4382
   // Find a previous identical select
4383
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_SELECT) {
312,311✔
4384
      if (other->args.items[0] == test && other->args.items[1] == rtrue
13,024✔
4385
          && other->args.items[2] == rfalse)
714✔
4386
         return other->result;
659✔
4387
   }
4388

4389
   op_t *op = vcode_add_op(VCODE_OP_SELECT);
13,518✔
4390
   vcode_add_arg(op, test);
13,518✔
4391
   vcode_add_arg(op, rtrue);
13,518✔
4392
   vcode_add_arg(op, rfalse);
13,518✔
4393
   op->result = vcode_add_reg(vcode_reg_type(rtrue));
13,518✔
4394

4395
   VCODE_ASSERT(vtype_eq(vcode_reg_type(test), vtype_bool()),
13,518✔
4396
                "select test must have bool type");
4397
   VCODE_ASSERT(vtype_eq(vcode_reg_type(rtrue), vcode_reg_type(rfalse)),
13,518✔
4398
                "select arguments are not the same type");
4399

4400
   return op->result;
13,518✔
4401
}
4402

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

4417
static vcode_reg_t emit_logical(vcode_op_t op, vcode_reg_t lhs, vcode_reg_t rhs)
5,981✔
4418
{
4419
   vcode_type_t vtbool = vtype_bool();
5,981✔
4420

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

4457
   vcode_reg_t result = emit_arith(op, lhs, rhs, VCODE_INVALID_REG);
5,869✔
4458

4459
   VCODE_ASSERT(vtype_eq(vcode_reg_type(lhs), vtbool)
5,869✔
4460
                && vtype_eq(vcode_reg_type(rhs), vtbool),
4461
                "arguments to %s are not boolean", vcode_op_string(op));
4462

4463
   return result;
4464
}
4465

4466
vcode_reg_t emit_or(vcode_reg_t lhs, vcode_reg_t rhs)
1,525✔
4467
{
4468
   return emit_logical(VCODE_OP_OR, lhs, rhs);
1,525✔
4469
}
4470

4471
vcode_reg_t emit_and(vcode_reg_t lhs, vcode_reg_t rhs)
4,088✔
4472
{
4473
   return emit_logical(VCODE_OP_AND, lhs, rhs);
4,088✔
4474
}
4475

4476
vcode_reg_t emit_nand(vcode_reg_t lhs, vcode_reg_t rhs)
80✔
4477
{
4478
   return emit_logical(VCODE_OP_NAND, lhs, rhs);
80✔
4479
}
4480

4481
vcode_reg_t emit_nor(vcode_reg_t lhs, vcode_reg_t rhs)
81✔
4482
{
4483
   return emit_logical(VCODE_OP_NOR, lhs, rhs);
81✔
4484
}
4485

4486
vcode_reg_t emit_xor(vcode_reg_t lhs, vcode_reg_t rhs)
122✔
4487
{
4488
   return emit_logical(VCODE_OP_XOR, lhs, rhs);
122✔
4489
}
4490

4491
vcode_reg_t emit_xnor(vcode_reg_t lhs, vcode_reg_t rhs)
85✔
4492
{
4493
   return emit_logical(VCODE_OP_XNOR, lhs, rhs);
85✔
4494
}
4495

4496
vcode_reg_t emit_not(vcode_reg_t arg)
2,049✔
4497
{
4498
   int64_t cval;
2,049✔
4499
   if (vcode_reg_const(arg, &cval))
2,049✔
4500
      return emit_const(vtype_bool(), !cval);
27✔
4501

4502
   op_t *op = vcode_add_op(VCODE_OP_NOT);
2,022✔
4503
   vcode_add_arg(op, arg);
2,022✔
4504

4505
   vcode_type_t vtbool = vtype_bool();
2,022✔
4506
   VCODE_ASSERT(vtype_eq(vcode_reg_type(arg), vtbool),
2,022✔
4507
                "argument to not is not boolean");
4508

4509
   return (op->result = vcode_add_reg(vtbool));
2,022✔
4510
}
4511

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

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

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

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

4551
   vcode_type_t elem = (ptrkind == VCODE_TYPE_POINTER)
74,022✔
4552
      ? vtype_pointed(ptr_type) : ptr_type;
37,011✔
4553

4554
   op->result = vcode_add_reg(
37,011✔
4555
      vtype_uarray(ndims, elem, vcode_reg_bounds(data)));
4556

4557
   return op->result;
37,011✔
4558
}
4559

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

4574
   op_t *op = vcode_add_op(o);
49,497✔
4575
   vcode_add_arg(op, array);
49,497✔
4576
   op->dim = dim;
49,497✔
4577

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

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

4585
   if (rtype == VCODE_INVALID_TYPE)
49,497✔
4586
      rtype = vtype_offset();
32,232✔
4587

4588
   return (op->result = vcode_add_reg(rtype));
49,497✔
4589
}
4590

4591
vcode_reg_t emit_uarray_left(vcode_reg_t array, unsigned dim)
38,933✔
4592
{
4593
   return emit_uarray_op(VCODE_OP_UARRAY_LEFT, VCODE_INVALID_TYPE,
38,933✔
4594
                         array, dim, 0);
4595
}
4596

4597
vcode_reg_t emit_uarray_right(vcode_reg_t array, unsigned dim)
29,992✔
4598
{
4599
   return emit_uarray_op(VCODE_OP_UARRAY_RIGHT, VCODE_INVALID_TYPE,
29,992✔
4600
                         array, dim, 1);
4601
}
4602

4603
vcode_reg_t emit_uarray_dir(vcode_reg_t array, unsigned dim)
38,614✔
4604
{
4605
   return emit_uarray_op(VCODE_OP_UARRAY_DIR, vtype_bool(),
38,614✔
4606
                         array, dim, 2);
4607
}
4608

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

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

4627
   op_t *op = vcode_add_op(VCODE_OP_UARRAY_LEN);
23,851✔
4628
   vcode_add_arg(op, array);
23,851✔
4629
   op->dim = dim;
23,851✔
4630

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

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

4638
   return (op->result = vcode_add_reg(vtype_offset()));
23,851✔
4639
}
4640

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

4650
   op_t *op = vcode_add_op(VCODE_OP_UNWRAP);
26,478✔
4651
   vcode_add_arg(op, array);
26,478✔
4652

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

4657
   vcode_type_t elem = vt->elem;
26,478✔
4658

4659
   vcode_type_t rtype = (vtype_kind(elem) == VCODE_TYPE_SIGNAL)
26,478✔
4660
      ? elem : vtype_pointer(elem);
26,478✔
4661

4662
   op->result = vcode_add_reg(rtype);
26,478✔
4663

4664
   reg_t *rr = vcode_reg_data(op->result);
26,478✔
4665
   rr->bounds = elem;
26,478✔
4666

4667
   return op->result;
26,478✔
4668
}
4669

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

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

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

4699
   op_t *op = vcode_add_op(VCODE_OP_RANGE_NULL);
4,700✔
4700
   vcode_add_arg(op, left);
4,700✔
4701
   vcode_add_arg(op, right);
4,700✔
4702
   vcode_add_arg(op, dir);
4,700✔
4703

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

4709
   return (op->result = vcode_add_reg(vtype_bool()));
4,700✔
4710
}
4711

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

4722
   int64_t lconst, rconst, dconst;
9,996✔
4723
   if (vcode_reg_const(dir, &dconst) && vcode_reg_const(left, &lconst)
9,996✔
4724
       && vcode_reg_const(right, &rconst)) {
5,652✔
4725

4726
      int64_t diff;
3,705✔
4727
      if (dconst == RANGE_TO)
3,705✔
4728
         diff = rconst - lconst;
3,459✔
4729
      else
4730
         diff = lconst - rconst;
246✔
4731

4732
      return emit_const(vtype_offset(), diff < 0 ? 0 : diff + 1);
3,705✔
4733
   }
4734

4735
   op_t *op = vcode_add_op(VCODE_OP_RANGE_LENGTH);
6,291✔
4736
   vcode_add_arg(op, left);
6,291✔
4737
   vcode_add_arg(op, right);
6,291✔
4738
   vcode_add_arg(op, dir);
6,291✔
4739

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

4745
   return (op->result = vcode_add_reg(vtype_offset()));
6,291✔
4746
}
4747

4748
vcode_reg_t emit_var_upref(int hops, vcode_var_t var)
48,636✔
4749
{
4750
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_VAR_UPREF) {
436,729✔
4751
      if (other->hops == hops && other->address == var)
59,074✔
4752
         return other->result;
7,242✔
4753
   }
4754

4755
   op_t *op = vcode_add_op(VCODE_OP_VAR_UPREF);
41,394✔
4756
   op->hops    = hops;
41,394✔
4757
   op->address = var;
41,394✔
4758

4759
   VCODE_ASSERT(hops > 0, "invalid hop count");
41,394✔
4760

4761
   vcode_unit_t vu = active_unit;
41,394✔
4762
   for (int i = 0; i < hops; i++) {
93,256✔
4763
      vu = vu->context;
51,862✔
4764
      VCODE_ASSERT(vu, "hop count is greater than depth");
51,862✔
4765
   }
4766

4767
   VCODE_ASSERT(var < vu->vars.count, "upref %d is not a variable", var);
41,394✔
4768

4769
   vcode_calculate_var_index_type(op, &(vu->vars.items[var]));
41,394✔
4770

4771
   return op->result;
41,394✔
4772
}
4773

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

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

4799
   return (op->result = vcode_add_reg(vtype_signal(type)));
10,961✔
4800
}
4801

4802
void emit_resolve_signal(vcode_reg_t signal, vcode_reg_t resolution)
2,869✔
4803
{
4804
   op_t *op = vcode_add_op(VCODE_OP_RESOLVE_SIGNAL);
2,869✔
4805
   vcode_add_arg(op, signal);
2,869✔
4806
   vcode_add_arg(op, resolution);
2,869✔
4807

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

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

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

4834
   return (op->result = vcode_add_reg(vtype_signal(type)));
21✔
4835
}
4836

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

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

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

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

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

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

4880
void emit_drive_signal(vcode_reg_t target, vcode_reg_t count)
8,741✔
4881
{
4882
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DRIVE_SIGNAL) {
110,481✔
4883
      if (other->args.items[0] == target && other->args.items[1] == count)
13,622✔
4884
         return;
4885
   }
4886

4887
   op_t *op = vcode_add_op(VCODE_OP_DRIVE_SIGNAL);
8,726✔
4888
   vcode_add_arg(op, target);
8,726✔
4889
   vcode_add_arg(op, count);
8,726✔
4890

4891
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
8,726✔
4892
                "target argument to drive signal is not a signal");
4893
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
8,726✔
4894
                "count argument type to drive signal is not offset");
4895
}
4896

4897
void emit_transfer_signal(vcode_reg_t target, vcode_reg_t source,
1,185✔
4898
                          vcode_reg_t count, vcode_reg_t reject,
4899
                          vcode_reg_t after)
4900
{
4901
   op_t *op = vcode_add_op(VCODE_OP_TRANSFER_SIGNAL);
1,185✔
4902
   vcode_add_arg(op, target);
1,185✔
4903
   vcode_add_arg(op, source);
1,185✔
4904
   vcode_add_arg(op, count);
1,185✔
4905
   vcode_add_arg(op, reject);
1,185✔
4906
   vcode_add_arg(op, after);
1,185✔
4907

4908
   VCODE_ASSERT(vcode_reg_kind(target) == VCODE_TYPE_SIGNAL,
1,185✔
4909
                "target argument to transfer signal is not a signal");
4910
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
1,185✔
4911
                "count argument type to transfer signal is not offset");
4912
   VCODE_ASSERT(vcode_reg_kind(source) == VCODE_TYPE_SIGNAL,
1,185✔
4913
                "source argument to transfer signal is not a signal");
4914
}
1,185✔
4915

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

4926
   VCODE_ASSERT(vcode_reg_kind(closure) == VCODE_TYPE_CLOSURE,
783✔
4927
                "first argument to resolution wrapper must be closure");
4928

4929
   op_t *op = vcode_add_op(VCODE_OP_RESOLUTION_WRAPPER);
783✔
4930
   vcode_add_arg(op, closure);
783✔
4931
   vcode_add_arg(op, ileft);
783✔
4932
   vcode_add_arg(op, nlits);
783✔
4933

4934
   return (op->result = vcode_add_reg(vtype_resolution(type)));
783✔
4935
}
4936

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

4945
   op_t *op = vcode_add_op(VCODE_OP_CLOSURE);
965✔
4946
   vcode_add_arg(op, context);
965✔
4947
   op->func = func;
965✔
4948
   op->type = atype;
965✔
4949

4950
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
965✔
4951
                "invalid closure context argument");
4952

4953
   return (op->result = vcode_add_reg(vtype_closure(rtype)));
965✔
4954
}
4955

4956
vcode_reg_t emit_package_init(ident_t name, vcode_reg_t context)
28,713✔
4957
{
4958
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_PACKAGE_INIT) {
43,749✔
4959
      if (other->func == name)
21,685✔
4960
         return other->result;
12,022✔
4961
   }
4962

4963
   op_t *op = vcode_add_op(VCODE_OP_PACKAGE_INIT);
16,691✔
4964
   op->func = name;
16,691✔
4965
   if (context != VCODE_INVALID_REG)
16,691✔
4966
      vcode_add_arg(op, context);
170✔
4967

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

4977
   return (op->result = vcode_add_reg(vtype_context(name)));
16,691✔
4978
}
4979

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

4987
   if (path_name != VCODE_INVALID_REG && inst_name != VCODE_INVALID_REG) {
154✔
4988
      vcode_add_arg(op, path_name);
32✔
4989
      vcode_add_arg(op, inst_name);
32✔
4990

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

4997
   VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_CONTEXT,
154✔
4998
                "protected init type must be context");
4999
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
154✔
5000
                "invalid protected init context argument");
5001

5002
   return (op->result = vcode_add_reg(type));
154✔
5003
}
5004

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

5011
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
70✔
5012
                "locus argument to process init must be a debug locus");
5013
}
70✔
5014

5015
void emit_protected_free(vcode_reg_t obj)
7✔
5016
{
5017
   op_t *op = vcode_add_op(VCODE_OP_PROTECTED_FREE);
7✔
5018
   vcode_add_arg(op, obj);
7✔
5019

5020
   VCODE_ASSERT(vcode_reg_kind(obj) == VCODE_TYPE_CONTEXT,
7✔
5021
                "protected object type must be context");
5022
}
7✔
5023

5024
vcode_reg_t emit_context_upref(int hops)
15,047✔
5025
{
5026
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONTEXT_UPREF) {
98,937✔
5027
      if (other->hops == hops)
6,800✔
5028
         return other->result;
6,741✔
5029
   }
5030

5031
   op_t *op = vcode_add_op(VCODE_OP_CONTEXT_UPREF);
8,306✔
5032
   op->hops = hops;
8,306✔
5033

5034
   VCODE_ASSERT(hops >= 0, "invalid hop count");
8,306✔
5035

5036
   vcode_unit_t vu = active_unit;
8,306✔
5037
   for (int i = 0; i < hops; i++) {
15,965✔
5038
      vu = vu->context;
7,659✔
5039
      VCODE_ASSERT(vu, "hop count is greater than depth");
7,659✔
5040
   }
5041

5042
   return (op->result = vcode_add_reg(vtype_context(vu->name)));
8,306✔
5043
}
5044

5045
static vcode_reg_t emit_signal_flag(vcode_op_t opkind, vcode_reg_t nets,
494✔
5046
                                    vcode_reg_t len)
5047
{
5048
   op_t *op = vcode_add_op(opkind);
494✔
5049
   vcode_add_arg(op, nets);
494✔
5050
   vcode_add_arg(op, len);
494✔
5051

5052
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
494✔
5053
                "argument to %s is not a signal", vcode_op_string(opkind));
5054

5055
   return (op->result = vcode_add_reg(vtype_bool()));
494✔
5056
}
5057

5058
vcode_reg_t emit_event_flag(vcode_reg_t nets, vcode_reg_t len)
304✔
5059
{
5060
   return emit_signal_flag(VCODE_OP_EVENT, nets, len);
304✔
5061
}
5062

5063
vcode_reg_t emit_active_flag(vcode_reg_t nets, vcode_reg_t len)
190✔
5064
{
5065
   return emit_signal_flag(VCODE_OP_ACTIVE, nets, len);
190✔
5066
}
5067

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

5076
   op_t *op = vcode_add_op(VCODE_OP_RECORD_REF);
34,624✔
5077
   op->field = field;
34,624✔
5078
   vcode_add_arg(op, record);
34,624✔
5079

5080
   vtype_t *rptype = vcode_type_data(vcode_reg_type(record));
34,624✔
5081

5082
   VCODE_ASSERT(rptype->kind == VCODE_TYPE_POINTER,
34,624✔
5083
                "argument to record ref must be a pointer");
5084

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

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

5091
   vcode_type_t field_type  = rtype->fields.items[field];
34,624✔
5092
   vcode_type_t bounds_type = field_type;
34,624✔
5093
   vcode_type_t result_type = field_type;
34,624✔
5094

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

5103
   op->result = vcode_add_reg(vtype_pointer(result_type));
34,624✔
5104

5105
   reg_t *rr = vcode_reg_data(op->result);
34,624✔
5106
   rr->bounds = bounds_type;
34,624✔
5107

5108
   return op->result;
34,624✔
5109
}
5110

5111
vcode_reg_t emit_array_ref(vcode_reg_t array, vcode_reg_t offset)
34,661✔
5112
{
5113
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ARRAY_REF) {
1,649,697✔
5114
      if (other->args.items[0] == array && other->args.items[1] == offset)
97,797✔
5115
         return other->result;
1,174✔
5116
   }
5117

5118
   op_t *op = vcode_add_op(VCODE_OP_ARRAY_REF);
33,487✔
5119
   vcode_add_arg(op, array);
33,487✔
5120
   vcode_add_arg(op, offset);
33,487✔
5121

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

5130
   op->result = vcode_add_reg(rtype);
33,487✔
5131

5132
   reg_t *rr = vcode_reg_data(op->result);
33,487✔
5133
   rr->bounds = vcode_reg_bounds(array);
33,487✔
5134

5135
   return op->result;
33,487✔
5136
}
5137

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

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

5153
   vcode_type_t dtype = vcode_reg_type(dest);
15,511✔
5154
   vcode_type_t stype = vcode_reg_type(src);
15,511✔
5155

5156
   vtype_kind_t dkind = vtype_kind(dtype);
15,511✔
5157
   vtype_kind_t skind = vtype_kind(stype);
15,511✔
5158

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

5169
   op->type = vtype_pointed(dtype);
15,511✔
5170
}
5171

5172
void emit_sched_event(vcode_reg_t nets, vcode_reg_t n_elems)
5,399✔
5173
{
5174
   VCODE_FOR_EACH_OP(other) {
95,019✔
5175
      if (other->kind == VCODE_OP_CLEAR_EVENT)
89,653✔
5176
         break;
5177
      else if (other->kind == VCODE_OP_SCHED_EVENT
89,623✔
5178
               && other->args.items[0] == nets
4,687✔
5179
               && other->args.items[1] == n_elems)
6✔
5180
         return;
5181
   }
5182

5183
   op_t *op = vcode_add_op(VCODE_OP_SCHED_EVENT);
5,396✔
5184
   vcode_add_arg(op, nets);
5,396✔
5185
   vcode_add_arg(op, n_elems);
5,396✔
5186

5187
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
5,396✔
5188
                "nets argument to sched event must be signal");
5189
}
5190

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

5199
   op_t *op = vcode_add_op(VCODE_OP_IMPLICIT_EVENT);
18✔
5200
   vcode_add_arg(op, nets);
18✔
5201
   vcode_add_arg(op, count);
18✔
5202
   vcode_add_arg(op, wake);
18✔
5203

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

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

5221
   op_t *op = vcode_add_op(VCODE_OP_CLEAR_EVENT);
468✔
5222
   vcode_add_arg(op, nets);
468✔
5223
   vcode_add_arg(op, n_elems);
468✔
5224

5225
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
468✔
5226
                "nets argument to clear event must be signal");
5227
}
5228

5229
void emit_resume(ident_t func)
777✔
5230
{
5231
   op_t *op = vcode_add_op(VCODE_OP_RESUME);
777✔
5232
   op->func = func;
777✔
5233

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

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

5244
   op_t *op = vcode_add_op(VCODE_OP_MEMSET);
5,648✔
5245
   vcode_add_arg(op, ptr);
5,648✔
5246
   vcode_add_arg(op, value);
5,648✔
5247
   vcode_add_arg(op, len);
5,648✔
5248

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

5257
void emit_case(vcode_reg_t value, vcode_block_t def, const vcode_reg_t *cases,
539✔
5258
               const vcode_block_t *blocks, int ncases)
5259
{
5260
   int64_t cval1, cval2;
539✔
5261
   bool is_const = vcode_reg_const(value, &cval1);
539✔
5262

5263
   for (int i = 0; i < ncases; i++) {
4,980✔
5264
      bool can_fold = false;
4,445✔
5265
      if (cases[i] == value)
4,445✔
5266
         can_fold = true;
5267
      else if (is_const && vcode_reg_const(cases[i], &cval2))
4,445✔
5268
         can_fold = (cval1 == cval2);
4✔
5269

5270
      if (can_fold) {
4✔
5271
         emit_jump(blocks[i]);
4✔
5272
         return;
8✔
5273
      }
5274
   }
5275

5276
   if (is_const) {
535✔
UNCOV
5277
      emit_jump(def);
×
UNCOV
5278
      return;
×
5279
   }
5280

5281
   op_t *op = vcode_add_op(VCODE_OP_CASE);
535✔
5282
   vcode_add_arg(op, value);
535✔
5283
   vcode_add_target(op, def);
535✔
5284

5285
   for (int i = 0; i < ncases; i++) {
4,976✔
5286
      vcode_add_arg(op, cases[i]);
4,441✔
5287
      vcode_add_target(op, blocks[i]);
4,441✔
5288

5289
#ifdef DEBUG
5290
      for (int j = 0; j < i; j++)
245,341✔
5291
         VCODE_ASSERT(cases[i] != cases[j], "duplicate case choice");
240,900✔
5292
#endif
5293
   }
5294
}
5295

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

5307
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
241✔
5308
                "file open first argument must have file pointer type");
5309
}
241✔
5310

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

5319
   VCODE_ASSERT(vtype_is_pointer(vcode_reg_type(file), VCODE_TYPE_FILE),
125✔
5320
                "file write first argument must have file pointer type");
5321
}
125✔
5322

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

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

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

5351
   op_t *op = vcode_add_op(VCODE_OP_NULL);
6,663✔
5352
   op->result = vcode_add_reg(type);
6,663✔
5353

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

5359
   return op->result;
5360
}
5361

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

5368
   op->result = vcode_add_reg(vtype_access(type));
422✔
5369

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

5379
   return op->result;
422✔
5380
}
5381

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

5391
   op_t *op = vcode_add_op(VCODE_OP_NULL_CHECK);
1,123✔
5392
   vcode_add_arg(op, ptr);
1,123✔
5393
   vcode_add_arg(op, locus);
1,123✔
5394

5395
   VCODE_ASSERT(vtype_kind(vcode_reg_type(ptr)) == VCODE_TYPE_ACCESS,
1,123✔
5396
                "null check argument must be an access");
5397
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,123✔
5398
                "locus argument to null check must be a debug locus");
5399
}
5400

5401
void emit_deallocate(vcode_reg_t ptr)
207✔
5402
{
5403
   op_t *op = vcode_add_op(VCODE_OP_DEALLOCATE);
207✔
5404
   vcode_add_arg(op, ptr);
207✔
5405

5406
   vcode_type_t ptype = vcode_reg_type(ptr);
207✔
5407
   VCODE_ASSERT(vtype_kind(ptype) == VCODE_TYPE_POINTER
207✔
5408
                && vtype_kind(vtype_pointed(ptype)) == VCODE_TYPE_ACCESS,
5409
                "deallocate argument must be pointer to access");
5410
}
207✔
5411

5412
vcode_reg_t emit_all(vcode_reg_t reg)
2,177✔
5413
{
5414
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ALL) {
146,040✔
5415
      if (other->args.items[0] == reg)
9,251✔
5416
         return other->result;
632✔
5417
   }
5418

5419
   op_t *op = vcode_add_op(VCODE_OP_ALL);
1,545✔
5420
   vcode_add_arg(op, reg);
1,545✔
5421

5422
   vcode_type_t vtype = vcode_reg_type(reg);
1,545✔
5423

5424
   VCODE_ASSERT(vtype_kind(vtype) == VCODE_TYPE_ACCESS,
1,545✔
5425
                "all argument must be an access");
5426

5427
   vcode_type_t pointed = vtype_pointed(vtype);
1,545✔
5428
   op->result = vcode_add_reg(vtype_pointer(pointed));
1,545✔
5429

5430
   reg_t *rr = vcode_reg_data(op->result);
1,545✔
5431
   rr->bounds = pointed;
1,545✔
5432

5433
   VCODE_ASSERT(vtype_kind(pointed) != VCODE_TYPE_OPAQUE,
1,545✔
5434
                "cannot dereference opaque type");
5435

5436
   return op->result;
5437
}
5438

5439
static vcode_reg_t emit_signal_data_op(vcode_op_t kind, vcode_reg_t sig)
12,896✔
5440
{
5441
   block_t *b = &(active_unit->blocks.items[active_block]);
12,896✔
5442
   for (int i = b->ops.count - 1; i >= 0; i--) {
350,580✔
5443
      const op_t *other = &(b->ops.items[i]);
338,221✔
5444
      if (other->kind == kind && other->args.items[0] == sig)
338,221✔
5445
         return other->result;
537✔
5446
   }
5447

5448
   op_t *op = vcode_add_op(kind);
12,359✔
5449
   vcode_add_arg(op, sig);
12,359✔
5450

5451
   vcode_type_t stype = vcode_reg_type(sig);
12,359✔
5452
   op->type = stype;
12,359✔
5453

5454
   VCODE_ASSERT(vtype_kind(stype) == VCODE_TYPE_SIGNAL,
12,359✔
5455
                "argument r%d to resolved is not a signal", sig);
5456

5457
   vcode_type_t rtype = vtype_base(stype);
12,359✔
5458

5459
   const vtype_kind_t rkind = vtype_kind(rtype);
12,359✔
5460
   if (rkind == VCODE_TYPE_CARRAY || rkind == VCODE_TYPE_UARRAY)
12,359✔
UNCOV
5461
      rtype = vtype_elem(rtype);
×
5462

5463
   VCODE_ASSERT(vtype_is_scalar(rtype),
12,359✔
5464
                "resolved signal base type must be scalar");
5465

5466
   op->result = vcode_add_reg(vtype_pointer(rtype));
12,359✔
5467

5468
   reg_t *rr = vcode_reg_data(op->result);
12,359✔
5469
   rr->bounds = rtype;
12,359✔
5470

5471
   return op->result;
12,359✔
5472
}
5473

5474
vcode_reg_t emit_resolved(vcode_reg_t sig)
12,855✔
5475
{
5476
   return emit_signal_data_op(VCODE_OP_RESOLVED, sig);
12,855✔
5477
}
5478

5479
vcode_reg_t emit_last_value(vcode_reg_t sig)
41✔
5480
{
5481
   return emit_signal_data_op(VCODE_OP_LAST_VALUE, sig);
41✔
5482
}
5483

5484
vcode_reg_t emit_last_event(vcode_reg_t signal, vcode_reg_t len)
42✔
5485
{
5486
   op_t *op = vcode_add_op(VCODE_OP_LAST_EVENT);
42✔
5487
   vcode_add_arg(op, signal);
42✔
5488
   if (len != VCODE_INVALID_REG)
42✔
5489
      vcode_add_arg(op, len);
30✔
5490

5491
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
42✔
5492
                "signal argument to last event must have signal type");
5493
   VCODE_ASSERT(len == VCODE_INVALID_REG
42✔
5494
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5495
                "length argument to last event must have offset type");
5496

5497
   return (op->result = vcode_add_reg(vtype_time()));
42✔
5498
}
5499

5500
vcode_reg_t emit_last_active(vcode_reg_t signal, vcode_reg_t len)
36✔
5501
{
5502
   op_t *op = vcode_add_op(VCODE_OP_LAST_ACTIVE);
36✔
5503
   vcode_add_arg(op, signal);
36✔
5504
   if (len != VCODE_INVALID_REG)
36✔
5505
      vcode_add_arg(op, len);
27✔
5506

5507
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
36✔
5508
                "signal argument to last active must have signal type");
5509
   VCODE_ASSERT(len == VCODE_INVALID_REG
36✔
5510
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5511
                "length argument to last active must have offset type");
5512

5513
   return (op->result = vcode_add_reg(vtype_time()));
36✔
5514
}
5515

5516
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus)
6,919✔
5517
{
5518
   op_t *op = vcode_add_op(VCODE_OP_ALIAS_SIGNAL);
6,919✔
5519
   vcode_add_arg(op, signal);
6,919✔
5520
   vcode_add_arg(op, locus);
6,919✔
5521

5522
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
6,919✔
5523
                "signal argument must have signal type");
5524
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,919✔
5525
                "locus argument must have debug locus type");
5526
}
6,919✔
5527

5528
vcode_reg_t emit_driving_flag(vcode_reg_t signal, vcode_reg_t len)
30✔
5529
{
5530
   op_t *op = vcode_add_op(VCODE_OP_DRIVING);
30✔
5531
   vcode_add_arg(op, signal);
30✔
5532
   vcode_add_arg(op, len);
30✔
5533

5534
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
30✔
5535
                "signal argument to last active must have signal type");
5536
   VCODE_ASSERT(vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
30✔
5537
                "length argument to last active must have offset type");
5538

5539
   return (op->result = vcode_add_reg(vtype_bool()));
30✔
5540
}
5541

5542
vcode_reg_t emit_driving_value(vcode_reg_t signal, vcode_reg_t len)
24✔
5543
{
5544
   op_t *op = vcode_add_op(VCODE_OP_DRIVING_VALUE);
24✔
5545
   vcode_add_arg(op, signal);
24✔
5546
   if (len != VCODE_INVALID_REG)
24✔
5547
      vcode_add_arg(op, len);
3✔
5548

5549
   vcode_type_t signal_type = vcode_reg_type(signal);
24✔
5550

5551
   VCODE_ASSERT(vtype_kind(signal_type) == VCODE_TYPE_SIGNAL,
24✔
5552
                "signal argument to last active must have signal type");
5553
   VCODE_ASSERT(len == VCODE_INVALID_REG
24✔
5554
                || vcode_reg_kind(len) == VCODE_TYPE_OFFSET,
5555
                "length argument to last active must have offset type");
5556

5557
   vcode_type_t base_type = vtype_base(signal_type);
24✔
5558
   op->result = vcode_add_reg(vtype_pointer(base_type));
24✔
5559

5560
   reg_t *rr = vcode_reg_data(op->result);
24✔
5561
   rr->bounds = base_type;
24✔
5562

5563
   return op->result;
24✔
5564
}
5565

5566
void emit_length_check(vcode_reg_t llen, vcode_reg_t rlen, vcode_reg_t locus,
21,438✔
5567
                       vcode_reg_t dim)
5568
{
5569
   if (rlen == llen)
21,438✔
5570
      return;
5571

5572
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LENGTH_CHECK) {
181,954✔
5573
      if (other->args.items[0] == llen && other->args.items[1] == rlen)
2,810✔
5574
         return;
5575
   }
5576

5577
   op_t *op = vcode_add_op(VCODE_OP_LENGTH_CHECK);
6,707✔
5578
   vcode_add_arg(op, llen);
6,707✔
5579
   vcode_add_arg(op, rlen);
6,707✔
5580
   vcode_add_arg(op, locus);
6,707✔
5581
   if (dim != VCODE_INVALID_REG)
6,707✔
5582
      vcode_add_arg(op, dim);
24✔
5583

5584
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6,707✔
5585
                "locus argument to length check must be a debug locus");
5586
}
5587

5588
void emit_exponent_check(vcode_reg_t exp, vcode_reg_t locus)
1,572✔
5589
{
5590
   int64_t cval;
1,572✔
5591
   if (vcode_reg_const(exp, &cval) && cval >= 0)
1,572✔
5592
      return;
1,055✔
5593

5594
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_EXPONENT_CHECK) {
3,290✔
5595
      if (other->args.items[0] == exp)
12✔
5596
         return;
5597
   }
5598

5599
   op_t *op = vcode_add_op(VCODE_OP_EXPONENT_CHECK);
517✔
5600
   vcode_add_arg(op, exp);
517✔
5601
   vcode_add_arg(op, locus);
517✔
5602

5603
   VCODE_ASSERT(vcode_reg_kind(exp) == VCODE_TYPE_INT,
517✔
5604
                "exp argument to exponent check must be a integer");
5605
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
517✔
5606
                "locus argument to exponent check must be a debug locus");
5607
}
5608

5609
void emit_zero_check(vcode_reg_t denom, vcode_reg_t locus)
1,013✔
5610
{
5611
   int64_t cval;
1,013✔
5612
   if (vcode_reg_const(denom, &cval) && cval != 0)
1,013✔
5613
      return;
910✔
5614

5615
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ZERO_CHECK) {
2,886✔
5616
      if (other->args.items[0] == denom)
56✔
5617
         return;
5618
   }
5619

5620
   op_t *op = vcode_add_op(VCODE_OP_ZERO_CHECK);
103✔
5621
   vcode_add_arg(op, denom);
103✔
5622
   vcode_add_arg(op, locus);
103✔
5623

5624
   VCODE_ASSERT(vcode_reg_kind(denom) == VCODE_TYPE_INT,
103✔
5625
                "denom argument to zero check must be a integer");
5626
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
103✔
5627
                "locus argument to zero check must be a debug locus");
5628
}
5629

5630
static bool vcode_can_elide_bounds(vcode_reg_t reg, vcode_reg_t left,
47,106✔
5631
                                   vcode_reg_t right, vcode_reg_t dir)
5632
{
5633
   int64_t dconst;
47,106✔
5634
   if (vcode_reg_const(dir, &dconst)) {
47,106✔
5635
      int64_t lconst, rconst;
38,334✔
5636
      if (vcode_reg_const(left, &lconst) && vcode_reg_const(right, &rconst)) {
38,334✔
5637
         const bool is_null = (dconst == RANGE_TO && lconst > rconst)
28,940✔
5638
            || (dconst == RANGE_DOWNTO && rconst > lconst);
61,092✔
5639

5640
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
32,153✔
5641

5642
         const bool ok_static =
64,306✔
5643
            (dconst == RANGE_TO
5644
             && bounds->low >= lconst && bounds->high <= rconst)
28,940✔
5645
            || (dconst == RANGE_DOWNTO
7,608✔
5646
                && bounds->low >= rconst && bounds->high <= lconst)
3,213✔
5647
            || (!is_null && (reg == left || reg == right));
36,740✔
5648

5649
         return ok_static;
37,552✔
5650
      }
5651
      else if (vcode_reg_kind(reg) == VCODE_TYPE_REAL) {
6,181✔
5652
         vtype_t *lbounds = vcode_type_data(vcode_reg_bounds(left));
5,805✔
5653
         vtype_t *rbounds = vcode_type_data(vcode_reg_bounds(right));
5,805✔
5654

5655
         assert(lbounds->kind == VCODE_TYPE_REAL);
5,805✔
5656
         assert(rbounds->kind == VCODE_TYPE_REAL);
5,805✔
5657

5658
         vtype_t *bounds = vcode_type_data(vcode_reg_bounds(reg));
5,805✔
5659
         assert(bounds->kind == VCODE_TYPE_REAL);
5,805✔
5660

5661
         if (isfinite(bounds->rlow) && lbounds->rlow == -DBL_MAX
5,805✔
5662
             && isfinite(bounds->rhigh) && rbounds->rhigh == DBL_MAX) {
5,399✔
5663
            // Covers the complete double range so can never overflow
5664
            return true;
5665
         }
5666
      }
5667
   }
5668

5669
   return false;
5670
}
5671

5672
static void emit_bounds_check(vcode_op_t kind, vcode_reg_t reg,
47,699✔
5673
                              vcode_reg_t left, vcode_reg_t right,
5674
                              vcode_reg_t dir, vcode_reg_t locus,
5675
                              vcode_reg_t hint)
5676
{
5677
   VCODE_FOR_EACH_MATCHING_OP(other, kind) {
2,242,129✔
5678
      if (other->args.items[0] == reg && other->args.items[1] == left
13,508✔
5679
          && other->args.items[2] == right && other->args.items[3] == dir)
599✔
5680
         return;
5681
   }
5682

5683
   if (vcode_can_elide_bounds(reg, left, right, dir)) {
47,106✔
5684
      emit_comment("Elided bounds check for r%d", reg);
32,965✔
5685
      return;
32,965✔
5686
   }
5687

5688
   op_t *op = vcode_add_op(kind);
14,141✔
5689
   vcode_add_arg(op, reg);
14,141✔
5690
   vcode_add_arg(op, left);
14,141✔
5691
   vcode_add_arg(op, right);
14,141✔
5692
   vcode_add_arg(op, dir);
14,141✔
5693
   vcode_add_arg(op, locus);
14,141✔
5694
   vcode_add_arg(op, hint);
14,141✔
5695

5696
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
14,141✔
5697
                "locus argument to bounds check must be a debug locus");
5698
   VCODE_ASSERT(vcode_reg_kind(hint) == VCODE_TYPE_DEBUG_LOCUS,
14,141✔
5699
                "hint argument to bounds check must be a debug locus");
5700
}
5701

5702
void emit_range_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
8,454✔
5703
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5704
{
5705
   emit_bounds_check(VCODE_OP_RANGE_CHECK, reg, left, right, dir, locus, hint);
8,454✔
5706
}
8,454✔
5707

5708
void emit_index_check(vcode_reg_t reg, vcode_reg_t left, vcode_reg_t right,
39,245✔
5709
                      vcode_reg_t dir, vcode_reg_t locus, vcode_reg_t hint)
5710
{
5711
   emit_bounds_check(VCODE_OP_INDEX_CHECK, reg, left, right, dir, locus, hint);
39,245✔
5712
}
39,245✔
5713

5714
void emit_push_scope(vcode_reg_t locus, vcode_type_t type)
1,944✔
5715
{
5716
   op_t *op = vcode_add_op(VCODE_OP_PUSH_SCOPE);
1,944✔
5717
   vcode_add_arg(op, locus);
1,944✔
5718
   op->type = type;
1,944✔
5719

5720
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
1,944✔
5721
                "locus argument to push scope must be a debug locus");
5722
}
1,944✔
5723

5724
void emit_pop_scope(void)
1,944✔
5725
{
5726
   vcode_add_op(VCODE_OP_POP_SCOPE);
1,944✔
5727
}
1,944✔
5728

5729
vcode_reg_t emit_debug_locus(ident_t unit, ptrdiff_t offset)
116,931✔
5730
{
5731
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_DEBUG_LOCUS) {
6,274,850✔
5732
      if (other->ident == unit && other->tag == offset)
986,652✔
5733
         return other->result;
7,162✔
5734
   }
5735

5736
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_LOCUS);
109,769✔
5737
   op->ident = unit;
109,769✔
5738
   op->value = offset;
109,769✔
5739

5740
   return (op->result = vcode_add_reg(vtype_debug_locus()));
109,769✔
5741
}
5742

UNCOV
5743
void emit_debug_out(vcode_reg_t reg)
×
5744
{
UNCOV
5745
   op_t *op = vcode_add_op(VCODE_OP_DEBUG_OUT);
×
UNCOV
5746
   vcode_add_arg(op, reg);
×
UNCOV
5747
}
×
5748

5749
void emit_cover_stmt(uint32_t tag)
844✔
5750
{
5751
   op_t *op = vcode_add_op(VCODE_OP_COVER_STMT);
844✔
5752
   op->tag = tag;
844✔
5753
}
844✔
5754

5755
void emit_cover_branch(uint32_t tag)
483✔
5756
{
5757
   op_t *op = vcode_add_op(VCODE_OP_COVER_BRANCH);
483✔
5758
   op->tag = tag;
483✔
5759
}
483✔
5760

5761
void emit_cover_toggle(vcode_reg_t signal, uint32_t tag)
314✔
5762
{
5763
   op_t *op = vcode_add_op(VCODE_OP_COVER_TOGGLE);
314✔
5764
   vcode_add_arg(op, signal);
314✔
5765
   op->tag = tag;
314✔
5766
}
314✔
5767

5768
void emit_cover_state(vcode_reg_t signal, vcode_reg_t low, uint32_t tag)
12✔
5769
{
5770
   op_t *op = vcode_add_op(VCODE_OP_COVER_STATE);
12✔
5771
   vcode_add_arg(op, signal);
12✔
5772
   vcode_add_arg(op, low);
12✔
5773
   op->tag = tag;
12✔
5774
}
12✔
5775

5776
void emit_cover_expr(vcode_reg_t new_mask, uint32_t tag)
324✔
5777
{
5778
   op_t *op = vcode_add_op(VCODE_OP_COVER_EXPR);
324✔
5779
   vcode_add_arg(op, new_mask);
324✔
5780
   op->tag = tag;
324✔
5781
}
324✔
5782

5783
void emit_unreachable(vcode_reg_t locus)
509✔
5784
{
5785
   op_t *op = vcode_add_op(VCODE_OP_UNREACHABLE);
509✔
5786
   if (locus != VCODE_INVALID_REG)
509✔
5787
      vcode_add_arg(op, locus);
153✔
5788
}
509✔
5789

5790
vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
1,504✔
5791
{
5792
   active_unit->flags |= UNIT_UNDEFINED;
1,504✔
5793

5794
   op_t *op = vcode_add_op(VCODE_OP_UNDEFINED);
1,504✔
5795
   op->result = vcode_add_reg(type);
1,504✔
5796
   vcode_reg_data(op->result)->bounds = bounds;
1,504✔
5797

5798
   return op->result;
1,504✔
5799
}
5800

5801
void emit_debug_info(const loc_t *loc)
1,316,015✔
5802
{
5803
   if (!loc_invalid_p(loc))
1,316,015✔
5804
      vcode_block_data()->last_loc = *loc;
1,290,400✔
5805
}
1,316,015✔
5806

5807
vcode_reg_t emit_link_var(vcode_reg_t context, ident_t name, vcode_type_t type)
4,127✔
5808
{
5809
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_VAR) {
157,050✔
5810
      if (other->args.items[0] == context && other->ident == name)
8,806✔
5811
         return other->result;
1,553✔
5812
   }
5813

5814
   op_t *op = vcode_add_op(VCODE_OP_LINK_VAR);
2,574✔
5815
   vcode_add_arg(op, context);
2,574✔
5816
   op->ident = name;
2,574✔
5817

5818
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
2,574✔
5819
                "first argument to link var must be context");
5820

5821
   if (vtype_kind(type) == VCODE_TYPE_CARRAY) {
2,574✔
5822
      op->result = vcode_add_reg(vtype_pointer(vtype_elem(type)));
79✔
5823
      vcode_reg_data(op->result)->bounds = vtype_bounds(type);
79✔
5824
   }
5825
   else {
5826
      op->result = vcode_add_reg(vtype_pointer(type));
2,495✔
5827
      vcode_reg_data(op->result)->bounds = type;
2,495✔
5828
   }
5829

5830
   return op->result;
2,574✔
5831
}
5832

5833
vcode_reg_t emit_link_package(ident_t name)
23,006✔
5834
{
5835
   VCODE_FOR_EACH_OP(other) {
1,088,371✔
5836
      if (other->kind == VCODE_OP_LINK_PACKAGE && other->ident == name)
1,077,675✔
5837
         return other->result;
7,440✔
5838
      else if (other->kind == VCODE_OP_PACKAGE_INIT && other->func == name)
1,070,235✔
5839
         return other->result;
4,870✔
5840
   }
5841

5842
   op_t *op = vcode_add_op(VCODE_OP_LINK_PACKAGE);
10,696✔
5843
   op->ident = name;
10,696✔
5844

5845
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
10,696✔
5846

5847
   return (op->result = vcode_add_reg(vtype_context(name)));
10,696✔
5848
}
5849

5850
vcode_reg_t emit_link_instance(ident_t name, vcode_reg_t locus)
130✔
5851
{
5852
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_LINK_INSTANCE) {
352✔
5853
      if (other->ident == name)
34✔
5854
         return other->result;
25✔
5855
   }
5856

5857
   op_t *op = vcode_add_op(VCODE_OP_LINK_INSTANCE);
105✔
5858
   vcode_add_arg(op, locus);
105✔
5859
   op->ident = name;
105✔
5860

5861
   VCODE_ASSERT(name != active_unit->name, "cannot link the current unit");
105✔
5862
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
105✔
5863
                "locus argument to link instance must be a debug locus");
5864

5865
   return (op->result = vcode_add_reg(vtype_context(name)));
105✔
5866
}
5867

5868
void emit_enter_state(vcode_reg_t state)
219✔
5869
{
5870
   VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_ENTER_STATE) {
606✔
5871
      if (other->args.items[0] == state)
6✔
5872
         return;
5873
   }
5874

5875
   op_t *op = vcode_add_op(VCODE_OP_ENTER_STATE);
219✔
5876
   vcode_add_arg(op, state);
219✔
5877

5878
   VCODE_ASSERT(vcode_reg_kind(state) == VCODE_TYPE_INT,
219✔
5879
                "state must have integer type");
5880
}
5881

5882
vcode_reg_t emit_reflect_value(vcode_reg_t value, vcode_reg_t context,
45✔
5883
                               vcode_reg_t locus, vcode_reg_t bounds)
5884
{
5885
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_VALUE);
45✔
5886
   vcode_add_arg(op, value);
45✔
5887
   vcode_add_arg(op, context);
45✔
5888
   vcode_add_arg(op, locus);
45✔
5889
   if (bounds != VCODE_INVALID_REG)
45✔
5890
      vcode_add_arg(op, bounds);
6✔
5891

5892
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
45✔
5893
                "invalid reflect value context argument");
5894
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
45✔
5895
                "locus argument to reflect value must be a debug locus");
5896

5897
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
45✔
5898
}
5899

5900
vcode_reg_t emit_reflect_subtype(vcode_reg_t context, vcode_reg_t locus,
42✔
5901
                                 vcode_reg_t bounds)
5902
{
5903
   op_t *op = vcode_add_op(VCODE_OP_REFLECT_SUBTYPE);
42✔
5904
   vcode_add_arg(op, context);
42✔
5905
   vcode_add_arg(op, locus);
42✔
5906
   if (bounds != VCODE_INVALID_REG)
42✔
UNCOV
5907
      vcode_add_arg(op, bounds);
×
5908

5909
   VCODE_ASSERT(vcode_reg_kind(context) == VCODE_TYPE_CONTEXT,
42✔
5910
                "invalid reflect value context argument");
5911
   VCODE_ASSERT(vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
42✔
5912
                "locus argument to reflect value must be a debug locus");
5913

5914
   return (op->result = vcode_add_reg(vtype_access(vtype_opaque())));
42✔
5915
}
5916

5917
vcode_reg_t emit_function_trigger(ident_t func, const vcode_reg_t *args,
166✔
5918
                                  int nargs)
5919
{
5920
   op_t *op = vcode_add_op(VCODE_OP_FUNCTION_TRIGGER);
166✔
5921
   op->func = func;
166✔
5922

5923
   for (int i = 0; i < nargs; i++)
471✔
5924
      vcode_add_arg(op, args[i]);
305✔
5925

5926
   return (op->result = vcode_add_reg(vtype_trigger()));
166✔
5927
}
5928

5929
vcode_reg_t emit_or_trigger(vcode_reg_t left, vcode_reg_t right)
31✔
5930
{
5931
   op_t *op = vcode_add_op(VCODE_OP_OR_TRIGGER);
31✔
5932
   vcode_add_arg(op, left);
31✔
5933
   vcode_add_arg(op, right);
31✔
5934

5935
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_TRIGGER,
31✔
5936
                "or trigger left argument must be trigger");
5937
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_TRIGGER,
31✔
5938
                "or trigger right argument must be trigger");
5939

5940
   return (op->result = vcode_add_reg(vtype_trigger()));
31✔
5941
}
5942

5943
vcode_reg_t emit_cmp_trigger(vcode_reg_t left, vcode_reg_t right)
63✔
5944
{
5945
   op_t *op = vcode_add_op(VCODE_OP_CMP_TRIGGER);
63✔
5946
   vcode_add_arg(op, left);
63✔
5947
   vcode_add_arg(op, right);
63✔
5948

5949
   VCODE_ASSERT(vcode_reg_kind(left) == VCODE_TYPE_SIGNAL,
63✔
5950
                "cmp trigger left argument must be signal");
5951
   VCODE_ASSERT(vcode_reg_kind(right) == VCODE_TYPE_INT,
63✔
5952
                "cmp trigger right argument must be integer");
5953

5954
   return (op->result = vcode_add_reg(vtype_trigger()));
63✔
5955
}
5956

5957
void emit_add_trigger(vcode_reg_t trigger)
260✔
5958
{
5959
   op_t *op = vcode_add_op(VCODE_OP_ADD_TRIGGER);
260✔
5960
   vcode_add_arg(op, trigger);
260✔
5961

5962
   VCODE_ASSERT(vcode_reg_kind(trigger) == VCODE_TYPE_TRIGGER,
260✔
5963
                "add trigger argument must be trigger");
5964
}
260✔
5965

5966
vcode_reg_t emit_port_conversion(vcode_reg_t driving, vcode_reg_t effective)
180✔
5967
{
5968
   op_t *op = vcode_add_op(VCODE_OP_PORT_CONVERSION);
180✔
5969
   vcode_add_arg(op, driving);
180✔
5970
   if (effective != VCODE_INVALID_REG && effective != driving)
180✔
5971
      vcode_add_arg(op, effective);
15✔
5972

5973
   VCODE_ASSERT(vcode_reg_kind(driving) == VCODE_TYPE_CLOSURE,
180✔
5974
                "port conversion argument must be a closure");
5975
   VCODE_ASSERT(effective == VCODE_INVALID_REG
180✔
5976
                || vcode_reg_kind(effective) == VCODE_TYPE_CLOSURE,
5977
                "port conversion argument must be a closure");
5978

5979
   return (op->result = vcode_add_reg(vtype_conversion()));
180✔
5980
}
5981

5982
void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
252✔
5983
{
5984
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_IN);
252✔
5985
   vcode_add_arg(op, conv);
252✔
5986
   vcode_add_arg(op, nets);
252✔
5987
   vcode_add_arg(op, count);
252✔
5988

5989
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
252✔
5990
                "conv argument to convert must be a port conversion");
5991
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
252✔
5992
                "nets argument to convert must be a signal");
5993
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
252✔
5994
                "count argument to convert must be offset");
5995
}
252✔
5996

5997
void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count)
294✔
5998
{
5999
   op_t *op = vcode_add_op(VCODE_OP_CONVERT_OUT);
294✔
6000
   vcode_add_arg(op, conv);
294✔
6001
   vcode_add_arg(op, nets);
294✔
6002
   vcode_add_arg(op, count);
294✔
6003

6004
   VCODE_ASSERT(vcode_reg_kind(conv) == VCODE_TYPE_CONVERSION,
294✔
6005
                "conv argument to convert must be a port conversion");
6006
   VCODE_ASSERT(vcode_reg_kind(nets) == VCODE_TYPE_SIGNAL,
294✔
6007
                "nets argument to convert must be a signal");
6008
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
294✔
6009
                "count argument to convert must be offset");
6010
}
294✔
6011

6012
void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus)
251✔
6013
{
6014
   op_t *op = vcode_add_op(VCODE_OP_BIND_FOREIGN);
251✔
6015
   vcode_add_arg(op, spec);
251✔
6016
   vcode_add_arg(op, length);
251✔
6017
   if (locus != VCODE_INVALID_REG)
251✔
6018
      vcode_add_arg(op, locus);
116✔
6019

6020
   VCODE_ASSERT(vcode_reg_kind(spec) == VCODE_TYPE_POINTER,
251✔
6021
                "spec argument to bind foreign must be a pointer");
6022
   VCODE_ASSERT(vcode_reg_kind(length) == VCODE_TYPE_OFFSET,
251✔
6023
                "length argument to bind foreign must be offset");
6024
   VCODE_ASSERT(locus == VCODE_INVALID_REG
251✔
6025
                || vcode_reg_kind(locus) == VCODE_TYPE_DEBUG_LOCUS,
6026
                "locus argument to bind foreign value must be a debug locus");
6027
}
251✔
6028

6029
vcode_reg_t emit_instance_name(vcode_reg_t kind)
777✔
6030
{
6031
   op_t *op = vcode_add_op(VCODE_OP_INSTANCE_NAME);
777✔
6032
   vcode_add_arg(op, kind);
777✔
6033

6034
   VCODE_ASSERT(vcode_reg_kind(kind) == VCODE_TYPE_OFFSET,
777✔
6035
                "kind argument to instance name must be offset");
6036

6037
   vcode_type_t vchar = vtype_char();
777✔
6038
   return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
777✔
6039
}
6040

6041
void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count,
87✔
6042
                         vcode_reg_t values)
6043
{
6044
   op_t *op = vcode_add_op(VCODE_OP_DEPOSIT_SIGNAL);
87✔
6045
   vcode_add_arg(op, signal);
87✔
6046
   vcode_add_arg(op, count);
87✔
6047
   vcode_add_arg(op, values);
87✔
6048

6049
   VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL,
87✔
6050
                "deposit signal target is not signal");
6051
   VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET,
87✔
6052
                "deposit signal count is not offset type");
6053
   VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL,
87✔
6054
                "signal cannot be values argument for deposit signal");
6055
}
87✔
6056

6057
void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx)
27,991✔
6058
{
6059
   vcode_state_t state;
27,991✔
6060
   vcode_state_save(&state);
27,991✔
6061

6062
   vcode_select_unit(vu);
27,991✔
6063

6064
   const int nblocks = vcode_count_blocks();
27,991✔
6065
   for (int i = 0; i < nblocks; i++) {
132,188✔
6066
      vcode_select_block(i);
104,197✔
6067

6068
      const int nops = vcode_count_ops();
104,197✔
6069
      for (int op = 0; op < nops; op++) {
1,455,607✔
6070
         switch (vcode_get_op(op)) {
1,351,410✔
6071
         case VCODE_OP_LINK_PACKAGE:
9,153✔
6072
            (*fn)(vcode_get_ident(op), ctx);
9,153✔
6073
            break;
9,153✔
6074
         case VCODE_OP_FCALL:
49,860✔
6075
         case VCODE_OP_PCALL:
6076
         case VCODE_OP_CLOSURE:
6077
         case VCODE_OP_PROTECTED_INIT:
6078
         case VCODE_OP_PACKAGE_INIT:
6079
         case VCODE_OP_FUNCTION_TRIGGER:
6080
            (*fn)(vcode_get_func(op), ctx);
49,860✔
6081
            break;
49,860✔
6082
         default:
6083
            break;
6084
         }
6085
      }
6086
   }
6087

6088
   vcode_state_restore(&state);
27,991✔
6089
}
27,991✔
6090

6091
#ifdef DEBUG
6092
static void shape_mismatch(vcode_unit_t vu, vcode_unit_t shape,
×
6093
                           const char *fmt, ...)
6094
{
6095
   vcode_select_unit(vu);
×
UNCOV
6096
   vcode_dump();
×
6097

6098
   vcode_select_unit(shape);
×
UNCOV
6099
   vcode_dump();
×
6100

6101
   va_list ap;
×
6102
   va_start(ap, fmt);
×
6103

6104
   diag_t *d = diag_new(DIAG_FATAL, NULL);
×
UNCOV
6105
   diag_printf(d, "instance %s does not match shape %s", istr(vu->name),
×
6106
               istr(shape->name));
UNCOV
6107
   diag_stacktrace(d, true);
×
UNCOV
6108
   diag_vhint(d, NULL, fmt, ap);
×
UNCOV
6109
   diag_emit(d);
×
6110

UNCOV
6111
   va_end(ap);
×
6112

UNCOV
6113
   fatal_exit(1);
×
6114
}
6115
#endif
6116

6117
void vcode_check_shape(vcode_unit_t vu, vcode_unit_t shape)
51✔
6118
{
6119
#ifdef DEBUG
6120
   assert(shape->kind == VCODE_UNIT_SHAPE);
51✔
6121
   assert(vu->kind == VCODE_UNIT_INSTANCE);
51✔
6122

6123
   if (shape->vars.count <= vu->vars.count) {
51✔
6124
      for (int i = 0; i < shape->vars.count; i++) {
193✔
6125
         var_t *v = var_array_nth_ptr(&(vu->vars), i);
142✔
6126
         var_t *s = var_array_nth_ptr(&(shape->vars), i);
142✔
6127

6128
         if (v->name != s->name)
142✔
UNCOV
6129
            shape_mismatch(vu, shape, "var %d name %s != %s", i, istr(v->name),
×
6130
                           istr(s->name));
6131
         else if (v->flags != s->flags)
142✔
UNCOV
6132
            shape_mismatch(vu, shape, "var %d flags %x != %x", i, v->flags,
×
6133
                           s->flags);
6134
         // XXX: not possible to compare types at the moment
6135
      }
6136
   }
6137
   else
UNCOV
6138
      shape_mismatch(vu, shape, "shape vars %d > unit vars %d",
×
6139
                     shape->vars.count, vu->vars.count);
6140

6141
   if (shape->context != NULL)
51✔
UNCOV
6142
      vcode_check_shape(vu->context, shape->context);
×
6143
#endif
6144
}
51✔
6145

6146
#if VCODE_CHECK_UNIONS
6147
#define OP_USE_COUNT_U0(x)                                              \
6148
   (OP_HAS_IDENT(x) + OP_HAS_FUNC(x) + OP_HAS_ADDRESS(x))
6149
#define OP_USE_COUNT_U1(x)                                              \
6150
   (OP_HAS_CMP(x) + OP_HAS_VALUE(x) + OP_HAS_REAL(x) +                  \
6151
    OP_HAS_COMMENT(x) + OP_HAS_DIM(x) + OP_HAS_TARGET(x) +              \
6152
    OP_HAS_HOPS(x) + OP_HAS_FIELD(x) + OP_HAS_TAG(x))
6153

6154
__attribute__((constructor))
6155
static void vcode_check_unions(void)
6156
{
6157
   printf("sizeof(op_t) = %ld\n", sizeof(op_t));
6158
   for (int i = 0; i < 256; i++) {
6159
      assert(OP_USE_COUNT_U0(i) <= 1);
6160
      assert(OP_USE_COUNT_U1(i) <= 1);
6161
   }
6162
}
6163
#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