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

nickg / nvc / 28742123901

05 Jul 2026 01:19PM UTC coverage: 92.117% (+0.004%) from 92.113%
28742123901

push

github

nickg
Handle calls between Verilog constant functions

14 of 14 new or added lines in 2 files covered. (100.0%)

205 existing lines in 6 files now uncovered.

79687 of 86506 relevant lines covered (92.12%)

659926.47 hits per line

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

94.47
/src/common.c
1
//
2
//  Copyright (C) 2013-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 "common.h"
20
#include "diag.h"
21
#include "hash.h"
22
#include "ident.h"
23
#include "lib.h"
24
#include "lower.h"
25
#include "option.h"
26
#include "phase.h"
27
#include "printf.h"
28
#include "scan.h"
29
#include "thread.h"
30
#include "type.h"
31
#include "vlog/vlog-phase.h"
32
#include "sdf/sdf-phase.h"
33
#include "sdf/sdf-util.h"
34

35
#include <assert.h>
36
#include <ctype.h>
37
#include <string.h>
38
#include <stdlib.h>
39
#include <inttypes.h>
40

41
static vhdl_standard_t  current_std  = STD_08;
42
static bool             have_set_std = false;
43
static ident_t          id_cache[NUM_WELL_KNOWN];
44
static text_buf_t      *syntax_buf = NULL;
45

46
int64_t assume_int(tree_t t)
1,109,437✔
47
{
48
   int64_t value;
1,109,437✔
49
   if (folded_int(t, &value))
1,109,437✔
50
      return value;
1,109,437✔
51

52
   fatal_at(tree_loc(t), "expression cannot be folded to "
×
53
            "an integer constant");
54
}
55

56
void range_bounds(tree_t r, int64_t *low, int64_t *high)
235,525✔
57
{
58
   assert(tree_kind(r) == T_RANGE);
235,525✔
59

60
   const int64_t left = assume_int(tree_left(r));
235,525✔
61
   const int64_t right = assume_int(tree_right(r));
235,525✔
62

63
   *low  = tree_subkind(r) == RANGE_TO ? left : right;
235,525✔
64
   *high = tree_subkind(r) == RANGE_TO ? right : left;
235,525✔
65
}
235,525✔
66

67
bool folded_int(tree_t t, int64_t *l)
7,506,027✔
68
{
69
   switch (tree_kind(t)) {
7,560,146✔
70
   case T_LITERAL:
4,206,416✔
71
      switch (tree_subkind(t)) {
4,206,416✔
72
      case L_PHYSICAL:
24,415✔
73
         if (tree_has_ref(t))
24,415✔
74
            return false;
75
         // Fall-through
76
      case L_INT:
77
         *l = tree_ival(t);
4,112,170✔
78
         return true;
4,112,170✔
79
      default:
80
         return false;
81
      }
82
   case T_QUALIFIED:
474✔
83
      return folded_int(tree_value(t), l);
474✔
84
   case T_REF:
3,068,323✔
85
      if (tree_has_ref(t)) {
3,068,323✔
86
         tree_t decl = tree_ref(t);
3,068,323✔
87
         switch (tree_kind(decl)) {
3,068,323✔
88
         case T_CONST_DECL:
65,388✔
89
            if (tree_has_value(decl))
65,388✔
90
               return folded_int(tree_value(decl), l);
53,011✔
91
            else
92
               return false;
93
         case T_ENUM_LIT:
2,908,128✔
94
            *l = tree_pos(decl);
2,908,128✔
95
            return true;
2,908,128✔
96
         case T_ALIAS:
634✔
97
            return folded_int(tree_value(decl), l);
634✔
98
         default:
99
            return false;
100
         }
101
      }
102
      // Fall-through
103
   default:
104
      return false;
105
   }
106
}
107

108
bool folded_real(tree_t t, double *l)
318,183✔
109
{
110
   switch (tree_kind(t)) {
318,192✔
111
   case T_LITERAL:
308,522✔
112
      if (tree_subkind(t) == L_REAL) {
308,522✔
113
         *l = tree_dval(t);
308,276✔
114
         return true;
308,276✔
115
      }
116
      else
117
         return false;
118
   case T_QUALIFIED:
9✔
119
      return folded_real(tree_value(t), l);
9✔
120
   default:
121
      return false;
122
   }
123
}
124

125
bool folded_length(tree_t r, int64_t *l)
88,570✔
126
{
127
   int64_t low, high;
88,570✔
128
   if (folded_bounds(r, &low, &high)) {
88,570✔
129
      *l = MAX(high - low + 1, 0);
83,929✔
130
      return true;
83,929✔
131
   }
132
   else
133
      return false;
134
}
135

136
bool folded_bounds(tree_t r, int64_t *low, int64_t *high)
2,990,942✔
137
{
138
   assert(tree_kind(r) == T_RANGE);
2,990,942✔
139

140
   const range_kind_t rkind = tree_subkind(r);
2,990,942✔
141

142
   if (rkind != RANGE_TO && rkind != RANGE_DOWNTO)
2,990,942✔
143
      return false;
144

145
   int64_t left, right;
2,980,713✔
146
   if (!folded_int(tree_left(r), &left))
2,980,713✔
147
      return false;
148
   else if (!folded_int(tree_right(r), &right))
2,821,702✔
149
      return false;
150

151
   switch (rkind) {
2,763,282✔
152
   case RANGE_TO:
2,560,092✔
153
      *low  = left;
2,560,092✔
154
      *high = right;
2,560,092✔
155
      return true;
2,560,092✔
156
   case RANGE_DOWNTO:
203,190✔
157
      *low  = right;
203,190✔
158
      *high = left;
203,190✔
159
      return true;
203,190✔
160
   default:
161
      return false;
162
   }
163
}
164

165
bool folded_bounds_real(tree_t r, double *low, double *high)
116,377✔
166
{
167
   assert(tree_kind(r) == T_RANGE);
116,377✔
168

169
   const range_kind_t rkind = tree_subkind(r);
116,377✔
170

171
   if (rkind != RANGE_TO && rkind != RANGE_DOWNTO)
116,377✔
172
      return false;
173

174
   double left, right;
116,349✔
175
   if (folded_real(tree_left(r), &left) && folded_real(tree_right(r), &right)) {
116,349✔
176
      switch (rkind) {
116,252✔
177
      case RANGE_TO:
116,252✔
178
         *low  = left;
116,252✔
179
         *high = right;
116,252✔
180
         return true;
116,252✔
181
      case RANGE_DOWNTO:
×
182
         *low  = right;
×
183
         *high = left;
×
184
         return true;
×
185
      default:
186
         return false;
187
      }
188
   }
189
   else
190
      return false;
97✔
191
}
192

193
bool folded_bool(tree_t t, bool *b)
49,890✔
194
{
195
   if (tree_kind(t) == T_REF) {
49,890✔
196
      tree_t decl = tree_ref(t);
11,636✔
197
      if (tree_kind(decl) == T_ENUM_LIT
11,636✔
198
          && type_ident(tree_type(decl)) == well_known(W_STD_BOOL)) {
9,130✔
199
         *b = (tree_pos(decl) == 1);
9,130✔
200
         return true;
9,130✔
201
      }
202
   }
203

204
   return false;
205
}
206

207
tree_t get_enum_lit(tree_t t, type_t type, int pos)
9,546✔
208
{
209
   type_t enum_type = type_base_recur(type ?: tree_type(t));
9,546✔
210
   tree_t lit = type_enum_literal(enum_type, pos);
9,546✔
211

212
   tree_t b = tree_new(T_REF);
9,546✔
213
   tree_set_loc(b, tree_loc(t));
9,546✔
214
   tree_set_ref(b, lit);
9,546✔
215
   tree_set_type(b, enum_type);
9,546✔
216
   tree_set_ident(b, tree_ident(lit));
9,546✔
217

218
   return b;
9,546✔
219
}
220

221
tree_t get_int_lit(tree_t t, type_t type, int64_t i)
51,447✔
222
{
223
   tree_t f = tree_new(T_LITERAL);
51,447✔
224
   tree_set_subkind(f, L_INT);
51,447✔
225
   tree_set_ival(f, i);
51,447✔
226
   tree_set_loc(f, tree_loc(t));
51,447✔
227
   tree_set_type(f, type ?: tree_type(t));
51,447✔
228

229
   return f;
51,447✔
230
}
231

232
tree_t get_discrete_lit(tree_t t, type_t type, int64_t i)
5,910✔
233
{
234
   if (type_is_enum(type)) {
5,910✔
235
      type_t base = type_base_recur(type);
90✔
236
      const int maxlit = type_enum_literals(base);
90✔
237
      if (i >= maxlit)
90✔
238
         return NULL;
239
      else
240
         return get_enum_lit(t, type, i);
90✔
241
   }
242
   else
243
      return get_int_lit(t, type, i);
5,820✔
244
}
245

246
tree_t get_real_lit(tree_t t, type_t type, double r)
×
247
{
248
   tree_t f = tree_new(T_LITERAL);
×
249
   tree_set_loc(f, tree_loc(t));
×
250
   tree_set_subkind(f, L_REAL);
×
251
   tree_set_dval(f, r);
×
252
   tree_set_type(f, type ?: tree_type(t));
×
253

254
   return f;
×
255
}
256

257
bool parse_value(type_t type, const char *str, parsed_value_t *value)
127✔
258
{
259
   type_t base = type_base_recur(type);
127✔
260
   const type_kind_t basek = type_kind(base);
127✔
261

262
   if (basek == T_ARRAY && type_is_character_array(base)) {
127✔
263
      value->enums = NULL;
23✔
264

265
      int map[256];
23✔
266
      for (int i = 0; i < ARRAY_LEN(map); i++)
5,911✔
267
         map[i] = INT_MAX;
5,888✔
268

269
      type_t elem = type_elem(base);
23✔
270

271
      const int nlits = type_enum_literals(elem);
23✔
272
      for (int i = 0; i < nlits; i++) {
3,117✔
273
         ident_t id = tree_ident(type_enum_literal(elem, i));
3,094✔
274
         if (ident_char(id, 0) == '\'')
3,094✔
275
            map[(uint8_t)ident_char(id, 1)] = i;
2,314✔
276
      }
277

278
      while (map[(uint8_t)*str] == INT_MAX && isspace_iso88591(*str))
30✔
279
         ++str;
7✔
280

281
      int base = 0, dbits = 1;
23✔
282
      bool quoted = false;
23✔
283
      if (map['\"'] == INT_MAX) {
23✔
284
         if (str[0] == '\"') {
11✔
285
            quoted = true;
2✔
286
            str++;
2✔
287
         }
288
         else if (str[1] == '\"' && toupper_iso88591(str[0]) == 'X') {
9✔
289
            quoted = true;
3✔
290
            base = 16;
3✔
291
            dbits = 4;
3✔
292
            str += 2;
3✔
293
         }
294
      }
295

296
      const size_t max = strlen(str) * dbits;
23✔
297
      enum_array_t *array = xmalloc_flex(sizeof(enum_array_t), max, 1);
23✔
298

299
      int n = 0, m;
23✔
300
      for (; *str != '\0'; str++, n += dbits) {
122✔
301
         if (base > 0) {
84✔
302
            const bool extended = (isdigit_iso88591(*str) && *str < '0' + base)
20✔
303
               || (base > 10 && *str >= 'A' && *str < 'A' + base - 10)
4✔
304
               || (base > 10 && *str >= 'a' && *str < 'a' + base - 10);
15✔
305

306
            if (!extended)
12✔
307
               break;
308

309
            int digit = isdigit_iso88591(*str)
9✔
310
               ? (*str - '0')
8✔
311
               : 10 + (toupper_iso88591(*str) - 'A');
9✔
312

313
            bool valid = true;
9✔
314
            for (int i = dbits - 1; i >= 0; i--) {
45✔
315
               const uint8_t bit = (digit >> i) & 1 ? '1' : '0';
36✔
316
               valid &= (m = map[bit]) != INT_MAX;
36✔
317
               array->values[n + dbits - i - 1] = m;
36✔
318
            }
319

320
            if (!valid)
9✔
321
               break;
322
         }
323
         else if ((m = map[(uint8_t)*str]) == INT_MAX)
72✔
324
            break;
325
         else
326
            array->values[n] = m;
67✔
327
      }
328

329
      assert(n <= max);
23✔
330
      array->count = n;
23✔
331

332
      if (quoted && *str++ != '\"') {
23✔
333
         free(array);
2✔
334
         return false;
2✔
335
      }
336

337
      for (; *str; str++) {
29✔
338
         if (!isspace_iso88591(*str)) {
10✔
339
            free(array);
2✔
340
            return false;
2✔
341
         }
342
      }
343

344
      value->enums = array;
19✔
345
      return true;
19✔
346
   }
347

348
   while (isspace_iso88591(*str))
114✔
349
      ++str;
10✔
350

351
   switch (basek) {
104✔
352
   case T_INTEGER:
77✔
353
      {
354
         const bool is_negative = *str == '-';
77✔
355
         int num_digits = 0;
77✔
356

357
         if (is_negative) ++str;
77✔
358

359
         int64_t sum = 0;
360
         for (; isdigit_iso88591(*str) || (*str == '_'); str++) {
199✔
361
            if (*str != '_') {
122✔
362
               sum *= 10;
120✔
363
               sum += (*str - '0');
120✔
364
               num_digits++;
120✔
365
            }
366
         }
367

368
         value->integer = is_negative ? -sum : sum;
77✔
369

370
         if (num_digits == 0)
77✔
371
            return false;
372
      }
373
      break;
374

375
   case T_ENUM:
16✔
376
      {
377
         bool upcase = true;
16✔
378
         char *copy LOCAL = xstrdup(str), *p;
31✔
379
         for (p = copy; (*p != '\0') && !isspace_iso88591(*p); p++, str++) {
63✔
380
            if (*p == '\'')
47✔
381
               upcase = false;
382
            if (upcase)
25✔
383
               *p = toupper_iso88591(*p);
14✔
384
         }
385
         *p = '\0';
16✔
386

387
         ident_t id = ident_new(copy);
16✔
388

389
         value->integer = -1;
16✔
390

391
         const int nlits = type_enum_literals(base);
16✔
392
         for (int i = 0; i < nlits; i++) {
45✔
393
            if (tree_ident(type_enum_literal(base, i)) == id) {
44✔
394
               value->integer = i;
15✔
395
               break;
15✔
396
            }
397
         }
398

399
         if (value->integer == -1)
16✔
400
            return false;
1✔
401
      }
402
      break;
403

404
   case T_REAL:
6✔
405
      {
406
         char *eptr = NULL;
6✔
407
         value->real = strtod(str, &eptr);
6✔
408
         str = eptr;
6✔
409
      }
410
      break;
6✔
411

412
   case T_PHYSICAL:
5✔
413
      {
414
         char *eptr = NULL;
5✔
415
         double scale = strtod(str, &eptr);
5✔
416
         str = eptr;
5✔
417

418
         while (isspace_iso88591(*str)) ++str;
10✔
419

420
         char *copy LOCAL = xstrdup(str), *p;
10✔
421
         for (p = copy; *p && !isspace_iso88591(*p); p++, str++)
13✔
422
            *p = toupper_iso88591(*p);
8✔
423
         *p = '\0';
5✔
424

425
         if (p == copy)
5✔
426
            return false;
427

428
         ident_t id = ident_new(copy);
4✔
429

430
         value->integer = -1;
4✔
431

432
         const int nunits = type_units(base);
4✔
433
         for (int i = 0; i < nunits; i++) {
11✔
434
            tree_t u = type_unit(base, i);
11✔
435
            if (tree_ident(u) == id) {
11✔
436
               value->integer = scale * assume_int(tree_value(u));
4✔
437
               break;
4✔
438
            }
439
         }
440

441
         if (value->integer == -1)
4✔
442
            return false;
443
      }
444
      break;
445

446
   default:
447
      return false;
448
   }
449

450
   for (; *str; str++) {
113✔
451
      if (!isspace_iso88591(*str))
11✔
452
         return false;
453
   }
454

455
   return true;
456
}
457

458
tree_t make_ref(tree_t to)
8,600✔
459
{
460
   tree_t t = tree_new(T_REF);
8,600✔
461
   tree_set_ident(t, tree_ident(to));
8,600✔
462
   tree_set_ref(t, to);
8,600✔
463
   tree_set_type(t, tree_type(to));
8,600✔
464
   tree_set_loc(t, tree_loc(to));
8,600✔
465
   return t;
8,600✔
466
}
467

468
vhdl_standard_t standard(void)
4,527,516✔
469
{
470
   return current_std;
4,527,516✔
471
}
472

473
void set_standard(vhdl_standard_t s)
8,976✔
474
{
475
   current_std = s;
8,976✔
476
   have_set_std = true;
8,976✔
477
}
8,976✔
478

479
void set_default_standard(vhdl_standard_t s)
1,904✔
480
{
481
   if (!have_set_std)
1,904✔
482
      set_standard(s);
140✔
483
}
1,904✔
484

485
const char *standard_text(vhdl_standard_t s)
7,126✔
486
{
487
   static const char *text[] = {
7,126✔
488
      "1987", "1993", "2000", "2002", "2008", "2019"
489
   };
490

491
   if ((unsigned)s < ARRAY_LEN(text))
7,126✔
492
      return text[s];
7,126✔
493
   else
494
      return "????";
495
}
496

497
tree_t find_element_mode_indication(tree_t view, tree_t field, bool *converse)
787✔
498
{
499
   switch (tree_kind(view)) {
2,404✔
500
   case T_REF:
1,047✔
501
      return find_element_mode_indication(tree_ref(view), field, converse);
1,047✔
502

503
   case T_ALIAS:
260✔
504
      return find_element_mode_indication(tree_value(view), field, converse);
260✔
505

506
   case T_ATTR_REF:
310✔
507
      assert(tree_subkind(view) == ATTR_CONVERSE);
310✔
508
      *converse = !*converse;
310✔
509
      return find_element_mode_indication(tree_name(view), field, converse);
310✔
510

511
   case T_VIEW_DECL:
787✔
512
      {
513
         type_t view_type = tree_type(view);
787✔
514
         assert(type_kind(view_type) == T_VIEW);
787✔
515

516
         const int nelems = type_fields(view_type);
787✔
517
         for (int i = 0; i < nelems; i++) {
1,292✔
518
            tree_t e = type_field(view_type, i);
1,292✔
519
            if (tree_ref(e) == field)
1,292✔
520
               return e;
787✔
521
         }
522

523
         return NULL;
524
      }
525

526
   default:
×
527
      fatal_trace("unhandled tree kind %s in find_element_mode_indication",
528
                  tree_kind_str(tree_kind(view)));
529
   }
530
}
531

532
port_mode_t converse_mode(tree_t port, bool converse)
497✔
533
{
534
   const port_mode_t mode = tree_subkind(port);
497✔
535
   switch (mode) {
497✔
536
   case PORT_IN: return converse ? PORT_OUT : PORT_IN;
230✔
537
   case PORT_OUT: return converse ? PORT_IN : PORT_OUT;
226✔
538
   default: return mode;
539
   }
540
}
541

542
class_t class_of(tree_t t)
482,705✔
543
{
544
   switch (tree_kind(t)) {
543,473✔
545
   case T_VAR_DECL:
546
      return C_VARIABLE;
547
   case T_SIGNAL_DECL:
33,374✔
548
   case T_IMPLICIT_SIGNAL:
549
      return C_SIGNAL;
33,374✔
550
   case T_CONST_DECL:
15,362✔
551
      return C_CONSTANT;
15,362✔
552
   case T_PORT_DECL:
93,779✔
553
   case T_GENERIC_DECL:
554
   case T_PARAM_DECL:
555
   case T_EXTERNAL_NAME:
556
      return tree_class(t);
93,779✔
557
   case T_ENUM_LIT:
287,432✔
558
   case T_LITERAL:
559
   case T_STRING:
560
      return C_LITERAL;
287,432✔
561
   case T_FIELD_DECL:
36✔
562
   case T_ATTR_DECL:
563
      return C_DEFAULT;
36✔
564
   case T_VIEW_DECL:
2✔
565
      return C_VIEW;
2✔
566
   case T_UNIT_DECL:
10,920✔
567
      return C_UNITS;
10,920✔
568
   case T_ARCH:
30✔
569
      return C_ARCHITECTURE;
30✔
570
   case T_FUNC_DECL:
882✔
571
   case T_FUNC_BODY:
572
   case T_FUNC_INST:
573
   case T_FCALL:
574
   case T_PROT_FCALL:
575
      return C_FUNCTION;
882✔
576
   case T_PROC_DECL:
11,025✔
577
   case T_PROC_BODY:
578
   case T_PROC_INST:
579
   case T_PCALL:
580
   case T_PROT_PCALL:
581
      return C_PROCEDURE;
11,025✔
582
   case T_ENTITY:
87✔
583
      return C_ENTITY;
87✔
584
   case T_SUBTYPE_DECL:
891✔
585
      return C_SUBTYPE;
891✔
586
   case T_TYPE_DECL:
697✔
587
   case T_PROT_DECL:
588
   case T_PROT_BODY:
589
      return C_TYPE;
697✔
590
   case T_FILE_DECL:
256✔
591
      return C_FILE;
256✔
592
   case T_PROCESS:
561✔
593
   case T_BLOCK:
594
   case T_FOR:
595
   case T_INSTANCE:
596
   case T_CONCURRENT:
597
   case T_ELAB:
598
   case T_PSL_DECL:
599
   case T_PSL_DIRECT:
600
   case T_FOR_GENERATE:
601
   case T_IF_GENERATE:
602
   case T_CASE_GENERATE:
603
      return C_LABEL;
561✔
604
   case T_COMPONENT:
2✔
605
      return C_COMPONENT;
2✔
606
   case T_REF:
52,055✔
607
   case T_PROT_REF:
608
      return tree_has_ref(t) ? class_of(tree_ref(t)) : C_DEFAULT;
52,055✔
609
   case T_ARRAY_REF:
8,715✔
610
   case T_ARRAY_SLICE:
611
   case T_RECORD_REF:
612
   case T_ALL:
613
   case T_ALIAS:
614
   case T_QUALIFIED:
615
      return class_of(tree_value(t));
8,715✔
616
   case T_PACKAGE:
848✔
617
   case T_PACK_BODY:
618
   case T_PACK_INST:
619
      return C_PACKAGE;
848✔
620
   case T_CONFIGURATION:
1✔
621
      return C_CONFIGURATION;
1✔
622
   case T_LIBRARY:
2✔
623
      return C_LIBRARY;
2✔
624
   case T_ATTR_REF:
52✔
625
      switch (tree_subkind(t)) {
52✔
626
      case ATTR_DELAYED:
627
      case ATTR_STABLE:
628
      case ATTR_QUIET:
629
      case ATTR_TRANSACTION:
630
         return C_SIGNAL;
631
      default:
43✔
632
         return C_DEFAULT;
43✔
633
      }
634
   case T_CONTEXT:
×
635
      return C_CONTEXT;
×
636
   default:
×
637
      fatal_trace("missing class_of for %s", tree_kind_str(tree_kind(t)));
638
   }
639
}
640

641
bool class_has_type(class_t c)
277,312✔
642
{
643
   switch (c) {
277,312✔
644
   case C_LABEL:
645
   case C_ENTITY:
646
   case C_ARCHITECTURE:
647
   case C_COMPONENT:
648
   case C_CONFIGURATION:
649
   case C_PACKAGE:
650
   case C_LIBRARY:
651
      return false;
652
   default:
276,606✔
653
      return true;
276,606✔
654
   }
655
}
656

657
const char *class_str(class_t c)
844✔
658
{
659
   static const char *strs[] = {
844✔
660
      "default", "signal", "variable", "constant", "file", "entity",
661
      "component", "configuration", "architecture", "function", "package",
662
      "type", "subtype", "label", "procedure", "literal", "units", "library",
663
      "context", "view",
664
   };
665
   assert(c < ARRAY_LEN(strs));
844✔
666
   return strs[c];
844✔
667
}
668

669
const char *assoc_kind_str(assoc_kind_t akind)
9✔
670
{
671
   switch (akind) {
9✔
672
   case A_NAMED:  return "named";
673
   case A_CONCAT:
2✔
674
   case A_POS:    return "positional";
2✔
675
   case A_OTHERS: return "others";
3✔
676
   case A_SLICE:
1✔
677
   case A_RANGE:  return "range";
1✔
678
   default:       return "??";
×
679
   }
680
}
681

682
bool is_subprogram(tree_t t)
1,017,707✔
683
{
684
   switch (tree_kind(t)) {
1,017,707✔
685
   case T_FUNC_DECL:
686
   case T_FUNC_BODY:
687
   case T_FUNC_INST:
688
   case T_PROC_DECL:
689
   case T_PROC_BODY:
690
   case T_PROC_INST:
691
      return true;
692
   case T_GENERIC_DECL:
6,418✔
693
      {
694
         const class_t class = tree_class(t);
6,418✔
695
         return class == C_FUNCTION || class == C_PROCEDURE;
6,418✔
696
      }
697
   default:
743,128✔
698
      return false;
743,128✔
699
   }
700
}
701

702
bool is_loop_stmt(tree_t t)
588✔
703
{
704
   const tree_kind_t kind = tree_kind(t);
588✔
705
   return kind == T_WHILE || kind == T_FOR || kind == T_LOOP;
588✔
706
}
707

708
bool is_container(tree_t t)
15,692✔
709
{
710
   switch (tree_kind(t)) {
15,692✔
711
   case T_FUNC_BODY:
712
   case T_PROC_BODY:
713
   case T_ENTITY:
714
   case T_ARCH:
715
   case T_PACKAGE:
716
   case T_PACK_BODY:
717
   case T_CONFIGURATION:
718
   case T_BLOCK:
719
   case T_PROT_BODY:
720
   case T_ELAB:
721
   case T_FOR:
722
   case T_PROCESS:
723
   case T_PACK_INST:
724
      return true;
725
   default:
13,668✔
726
      return false;
13,668✔
727
   }
728
}
729

730
bool is_concurrent_block(tree_t t)
1,104✔
731
{
732
   switch (tree_kind(t)) {
1,104✔
733
   case T_ARCH:
734
   case T_ENTITY:
735
   case T_BLOCK:
736
   case T_IF_GENERATE:
737
   case T_FOR_GENERATE:
738
   case T_CASE_GENERATE:
739
      return true;
740
   default:
174✔
741
      return false;
174✔
742
   }
743
}
744

745
bool is_package(tree_t t)
57,642✔
746
{
747
   switch (tree_kind(t)) {
57,642✔
748
   case T_PACKAGE:
749
   case T_PACK_BODY:
750
   case T_PACK_INST:
751
      return true;
752
   default:
1,371✔
753
      return false;
1,371✔
754
   }
755
}
756

757
bool is_design_unit(tree_t t)
69,404✔
758
{
759
   switch (tree_kind(t)) {
69,404✔
760
   case T_ENTITY:
761
   case T_ARCH:
762
   case T_PACKAGE:
763
   case T_PACK_BODY:
764
   case T_CONFIGURATION:
765
   case T_CONTEXT:
766
   case T_PACK_INST:
767
      return true;
768
   default:
20,326✔
769
      return false;
20,326✔
770
   }
771
}
772

773
bool is_literal(tree_t t)
80,568✔
774
{
775
   switch (tree_kind(t)) {
80,568✔
776
   case T_REF:
29,722✔
777
      return tree_has_ref(t) && tree_kind(tree_ref(t)) == T_ENUM_LIT;
31,945✔
778
   case T_LITERAL:
779
      return true;
780
   case T_STRING:
27,787✔
781
   default:
782
      return false;
27,787✔
783
   }
784
}
785

786
bool is_body(tree_t t)
13,507✔
787
{
788
   switch (tree_kind(t)) {
13,507✔
789
   case T_FUNC_BODY:
790
   case T_PROC_BODY:
791
   case T_PACK_BODY:
792
   case T_PROT_BODY:
793
      return true;
794
   default:
4,881✔
795
      return false;
4,881✔
796
   }
797
}
798

799
bool is_guarded_signal(tree_t decl)
19,915✔
800
{
801
   switch (tree_kind(decl)) {
19,915✔
802
   case T_PORT_DECL:
19,364✔
803
   case T_SIGNAL_DECL:
804
      return !!(tree_flags(decl) & (TREE_F_BUS | TREE_F_REGISTER));
19,364✔
805
   default:
806
      return false;
807
   }
808
}
809

810
bool is_type_decl(tree_t t)
1,205,610✔
811
{
812
   switch (tree_kind(t)) {
1,205,610✔
813
   case T_TYPE_DECL:
814
   case T_SUBTYPE_DECL:
815
   case T_PROT_DECL:
816
   case T_PROT_BODY:
817
      return true;
818
   default:
942,355✔
819
      return false;
942,355✔
820
   }
821
}
822

823
tree_t aliased_type_decl(tree_t decl)
183,242✔
824
{
825
   switch (tree_kind(decl)) {
184,516✔
826
   case T_ALIAS:
1,326✔
827
      {
828
         tree_t value = tree_value(decl);
1,326✔
829
         const tree_kind_t kind = tree_kind(value);
1,326✔
830
         if (kind == T_REF && tree_has_ref(value))
1,326✔
831
            return aliased_type_decl(tree_ref(value));
1,274✔
832
         else if (kind == T_ATTR_REF && is_type_attribute(tree_subkind(value)))
52✔
833
             return value;
834
         else
835
            return NULL;
46✔
836
      }
837
   case T_TYPE_DECL:
838
   case T_SUBTYPE_DECL:
839
   case T_PROT_DECL:
840
   case T_PROT_BODY:
841
      return decl;
842
   case T_GENERIC_DECL:
2,360✔
843
      if (tree_class(decl) == C_TYPE)
2,360✔
844
         return decl;
845
      else
846
         return NULL;
1,226✔
847
   default:
63,544✔
848
      return NULL;
63,544✔
849
   }
850
}
851

852
tree_t add_param(tree_t call, tree_t value, param_kind_t kind, tree_t name)
202,139✔
853
{
854
   tree_t p = tree_new(T_PARAM);
202,139✔
855
   tree_set_loc(p, tree_loc(value));
202,139✔
856
   tree_set_subkind(p, kind);
202,139✔
857
   tree_set_value(p, value);
202,139✔
858

859
   switch (kind) {
202,139✔
860
   case P_NAMED:
204✔
861
      assert(name != NULL);
204✔
862
      tree_set_name(p, name);
204✔
863
      break;
204✔
864
   case P_POS:
201,935✔
865
      tree_set_pos(p, tree_params(call));
201,935✔
866
      break;
201,935✔
867
   }
868

869
   tree_add_param(call, p);
202,139✔
870
   return p;
202,139✔
871
}
872

873
type_t array_aggregate_type(type_t array, int from_dim)
398✔
874
{
875
   if (type_is_none(array))
398✔
876
      return type_new(T_NONE);
2✔
877

878
   if (type_is_unconstrained(array)) {
396✔
879
      const int nindex = type_indexes(array);
57✔
880
      assert(from_dim < nindex);
57✔
881

882
      type_t type = type_new(T_ARRAY);
57✔
883
      type_set_ident(type, type_ident(array));
57✔
884
      type_set_elem(type, type_elem(array));
57✔
885

886
      for (int i = from_dim; i < nindex; i++)
114✔
887
         type_add_index(type, type_index(array, i));
57✔
888

889
      return type;
890
   }
891
   else {
892
      const int ndims = dimension_of(array);
339✔
893
      assert(from_dim < ndims);
339✔
894

895
      type_t base = type_new(T_ARRAY);
339✔
896
      type_set_ident(base, type_ident(array));
339✔
897
      type_set_elem(base, type_elem(array));
339✔
898

899
      tree_t constraint = tree_new(T_CONSTRAINT);
339✔
900
      tree_set_subkind(constraint, C_INDEX);
339✔
901

902
      type_t sub = type_new(T_SUBTYPE);
339✔
903
      type_set_base(sub, base);
339✔
904
      type_set_constraint(sub, constraint);
339✔
905

906
      for (int i = from_dim; i < ndims; i++) {
710✔
907
         tree_t r = range_of(array, i);
371✔
908
         if (r == NULL) {
371✔
909
            // Not enough constraints were provided for the type
910
            r = tree_new(T_RANGE);
1✔
911
            tree_set_subkind(r, RANGE_ERROR);
1✔
912
            tree_set_type(r, type_new(T_NONE));
1✔
913
         }
914

915
         type_add_index(base, tree_type(r));
371✔
916
         tree_add_range(constraint, r);
371✔
917
      }
918

919
      return sub;
920
   }
921
}
922

923
unsigned bits_for_range(int64_t low, int64_t high)
2,837,429✔
924
{
925
   if (low > high)
2,837,429✔
926
      return 0;   // Null range
927
   else if (low < 0) {
2,837,429✔
928
      // Signed integers
929
      if (low >= INT8_MIN && high <= INT8_MAX)
662,417✔
930
         return 8;
931
      else if (low >= INT16_MIN && high <= INT16_MAX)
662,332✔
932
         return 16;
933
      else if (low >= INT32_MIN && high <= INT32_MAX)
662,211✔
934
         return 32;
935
      else
936
         return 64;
97,958✔
937
   }
938
   else {
939
      // Unsigned integers
940
      if (high <= 1)
2,175,012✔
941
         return 1;
942
      else if (high <= UINT8_MAX)
1,443,462✔
943
         return 8;
944
      else if (high <= UINT16_MAX)
3,678✔
945
         return 16;
946
      else if (high <= UINT32_MAX)
3,473✔
947
         return 32;
948
      else
949
         return 64;
164✔
950
   }
951
}
952

953
unsigned dimension_of(type_t type)
2,315,050✔
954
{
955
   switch (type_kind(type)) {
4,373,693✔
956
   case T_SUBTYPE:
2,058,641✔
957
      return dimension_of(type_base(type));
2,058,641✔
958
   case T_GENERIC:
428✔
959
      switch (type_subkind(type)) {
428✔
960
      case GTYPE_ARRAY:
378✔
961
         return type_indexes(type);
378✔
962
      case GTYPE_ACCESS:
×
963
         return dimension_of(type_designated(type));
×
964
      case GTYPE_FILE:
965
      case GTYPE_PRIVATE:
966
         return 0;
967
      default:
50✔
968
         return 1;
50✔
969
      }
970
   case T_ARRAY:
2,305,401✔
971
      return type_indexes(type);
2,305,401✔
972
   case T_NONE:
973
   case T_RECORD:
974
   case T_INCOMPLETE:
975
   case T_FILE:
976
   case T_SIGNATURE:
977
   case T_VIEW:
978
      return 0;
979
   case T_INTEGER:
9,130✔
980
   case T_REAL:
981
   case T_PHYSICAL:
982
   case T_ENUM:
983
      return type_dims(type);
9,130✔
984
   case T_ACCESS:
2✔
985
      return dimension_of(type_designated(type));
2✔
986
   default:
×
987
      fatal_trace("invalid type kind %s in dimension_of",
988
                  type_kind_str(type_kind(type)));
989
   }
990
}
991

992
tree_t range_of(type_t type, unsigned dim)
3,537,856✔
993
{
994
   switch (type_kind(type)) {
3,582,750✔
995
   case T_SUBTYPE:
2,884,333✔
996
      if (type_has_constraint(type)) {
2,884,333✔
997
         tree_t c = type_constraint(type);
2,839,439✔
998
         switch (tree_subkind(c)) {
2,839,439✔
999
         case C_INDEX:
2,839,439✔
1000
         case C_RANGE:
1001
            if (dim < tree_ranges(c))
2,839,439✔
1002
               return tree_range(c, dim);
2,839,438✔
1003
            else
1004
               return NULL;   // Must be an error
1005
         default:
×
1006
            should_not_reach_here();
1007
         }
1008
      }
1009
      else
1010
         return range_of(type_base(type), dim);
44,894✔
1011
   case T_INTEGER:
698,417✔
1012
   case T_REAL:
1013
   case T_PHYSICAL:
1014
   case T_ENUM:
1015
      return type_dim(type, dim);
698,417✔
1016
   default:
×
1017
      fatal_trace("invalid type kind %s for %s in range_of",
1018
                  type_kind_str(type_kind(type)), type_pp(type));
1019
   }
1020
}
1021

1022
range_kind_t direction_of(type_t type, unsigned dim)
31,932✔
1023
{
1024
   switch (type_kind(type)) {
32,036✔
1025
   case T_ENUM:
1026
      return RANGE_TO;
1027
   case T_NONE:
×
1028
      return RANGE_ERROR;
×
1029
   case T_INTEGER:
31,903✔
1030
   case T_REAL:
1031
   case T_PHYSICAL:
1032
   case T_SUBTYPE:
1033
      {
1034
         tree_t r = range_of(type, dim);
31,903✔
1035
         const range_kind_t rkind = tree_subkind(r);
31,903✔
1036
         if (rkind == RANGE_EXPR) {
31,903✔
1037
            // Return a fixed direction if possible
1038
            tree_t value = tree_value(r);
196✔
1039
            assert(tree_kind(value) == T_ATTR_REF);
196✔
1040

1041
            DEBUG_ONLY({
196✔
1042
                  const attr_kind_t attr = tree_subkind(value);
1043
                  assert(attr == ATTR_RANGE || attr == ATTR_REVERSE_RANGE);
1044
               });
196✔
1045

1046
            tree_t name = tree_name(value);
196✔
1047
            if (tree_kind(name) == T_REF && tree_has_ref(name)) {
196✔
1048
               tree_t decl = tree_ref(name);
195✔
1049
               if (is_type_decl(decl))
195✔
1050
                  return direction_of(tree_type(decl), 0);
104✔
1051
            }
1052
         }
1053

1054
         return rkind;
1055
      }
1056
   default:
×
1057
      fatal_trace("invalid type kind %s in direction_of",
1058
                  type_kind_str(type_kind(type)));
1059
   }
1060
}
1061

1062
type_t index_type_of(type_t type, unsigned dim)
319,604✔
1063
{
1064
   if (dim >= dimension_of(type))
319,606✔
1065
      return NULL;
1066

1067
   type_t base = type_base_recur(type);
319,561✔
1068
   type_kind_t base_kind = type_kind(base);
319,561✔
1069
   if (base_kind == T_ARRAY)
319,561✔
1070
      return type_index(base, dim);
315,097✔
1071
   else if (base_kind == T_ENUM || base_kind == T_NONE)
4,464✔
1072
      return type;
1073
   else if (base_kind == T_GENERIC && type_subkind(base) == GTYPE_ARRAY)
4,265✔
1074
      return type_index(base, dim);
228✔
1075
   else if (base_kind == T_RECORD || base_kind == T_GENERIC)
4,037✔
1076
      return NULL;
1077
   else if (base_kind == T_ACCESS)
4,012✔
1078
      return index_type_of(type_designated(type), dim);
2✔
1079
   else
1080
      return tree_type(range_of(base, dim));
4,010✔
1081
}
1082

1083
int64_t rebase_index(type_t array_type, int dim, int64_t value)
320✔
1084
{
1085
   // Convert value which is in the range of array_type to a zero-based index
1086
   tree_t r = range_of(array_type, dim);
320✔
1087
   const int64_t left = assume_int(tree_left(r));
320✔
1088
   return (tree_subkind(r) == RANGE_TO) ? value - left : left - value;
320✔
1089
}
1090

1091
ident_t well_known(well_known_t id)
568,050✔
1092
{
1093
   assert(id < NUM_WELL_KNOWN);
568,050✔
1094
   return id_cache[id];
568,050✔
1095
}
1096

1097
well_known_t is_well_known(ident_t ident)
343,357✔
1098
{
1099
   return ident_key(ident);
343,357✔
1100
}
1101

1102
void intern_strings(void)
9,285✔
1103
{
1104
   static const char *tab[] = {
9,285✔
1105
      [W_STD_STANDARD]   = "STD.STANDARD",
1106
      [W_ALL]            = "all",
1107
      [W_STD_BIT]        = "STD.STANDARD.BIT",
1108
      [W_STD_BOOL]       = "STD.STANDARD.BOOLEAN",
1109
      [W_STD_CHAR]       = "STD.STANDARD.CHARACTER",
1110
      [W_STD_NATURAL]    = "STD.STANDARD.NATURAL",
1111
      [W_STD_POSITIVE]   = "STD.STANDARD.POSITIVE",
1112
      [W_STD_INTEGER]    = "STD.STANDARD.INTEGER",
1113
      [W_STD_STRING]     = "STD.STANDARD.STRING",
1114
      [W_STD_REAL]       = "STD.STANDARD.REAL",
1115
      [W_STD_TIME]       = "STD.STANDARD.TIME",
1116
      [W_STD_BIT_VECTOR] = "STD.STANDARD.BIT_VECTOR",
1117

1118
      [W_IEEE_SIGNED]   = "IEEE.NUMERIC_STD.SIGNED",
1119
      [W_IEEE_UNSIGNED] = "IEEE.NUMERIC_STD.UNSIGNED",
1120
      [W_IEEE_LOGIC]    = "IEEE.STD_LOGIC_1164.STD_LOGIC",
1121
      [W_IEEE_ULOGIC]   = "IEEE.STD_LOGIC_1164.STD_ULOGIC",
1122

1123
      [W_IEEE_1164_AND]  = "IEEE.STD_LOGIC_1164.\"and\"",
1124
      [W_IEEE_1164_NAND] = "IEEE.STD_LOGIC_1164.\"nand\"",
1125
      [W_IEEE_1164_OR]   = "IEEE.STD_LOGIC_1164.\"or\"",
1126
      [W_IEEE_1164_NOR]  = "IEEE.STD_LOGIC_1164.\"nor\"",
1127
      [W_IEEE_1164_XOR]  = "IEEE.STD_LOGIC_1164.\"xor\"",
1128
      [W_IEEE_1164_XNOR] = "IEEE.STD_LOGIC_1164.\"xnor\"",
1129

1130
      [W_FOREIGN]         = "FOREIGN",
1131
      [W_WORK]            = "WORK",
1132
      [W_STD]             = "STD",
1133
      [W_THUNK]           = "thunk",
1134
      [W_BODY]            = "body",
1135
      [W_CARET]           = "^",
1136
      [W_IEEE]            = "IEEE",
1137
      [W_IEEE_1164]       = "IEEE.STD_LOGIC_1164",
1138
      [W_ERROR]           = "$error",
1139
      [W_ELAB]            = "elab",
1140
      [W_NUMERIC_STD]     = "IEEE.NUMERIC_STD",
1141
      [W_NUMERIC_BIT]     = "IEEE.NUMERIC_BIT",
1142
      [W_NVC]             = "NVC",
1143
      [W_DEFAULT_CLOCK]   = "default clock",
1144
      [W_STD_REFLECTION]  = "STD.REFLECTION",
1145
      [W_NEVER_WAITS]     = "NEVER_WAITS",
1146
      [W_NVC_VERILOG]     = "NVC.VERILOG",
1147
      [W_NVC_PSL_SUPPORT] = "NVC.PSL_SUPPORT",
1148
      [W_INSTANCE_NAME]   = "instance_name",
1149
      [W_PATH_NAME]       = "path_name",
1150
      [W_VITAL]           = "VITAL",
1151
      [W_RESOLUTION]      = "resolution",
1152
      [W_TEXT_UTIL]       = "NVC.TEXT_UTIL",
1153
      [W_VERILOG_LOGIC]   = "NVC.VERILOG.T_LOGIC",
1154
      [W_DLR_SIGNED]      = "$signed",
1155
      [W_DLR_UNSIGNED]    = "$unsigned",
1156
      [W_DLR_CLOG2]       = "$clog2",
1157
      [W_DLR_SQRT]        = "$sqrt",
1158
      [W_DLR_BITS]        = "$bits",
1159
      [W_DLR_RTOI]        = "$rtoi",
1160
      [W_DLR_CEIL]        = "$ceil",
1161
      [W_DLR_FLOOR]        = "$floor",
1162
      [W_COUNTERS]        = "#counters",
1163

1164
      [W_IEEE_LOGIC_VECTOR]      = "IEEE.STD_LOGIC_1164.STD_LOGIC_VECTOR",
1165
      [W_IEEE_ULOGIC_VECTOR]     = "IEEE.STD_LOGIC_1164.STD_ULOGIC_VECTOR",
1166
      [W_IEEE_1164_RISING_EDGE]  = "IEEE.STD_LOGIC_1164.RISING_EDGE(sU)B",
1167
      [W_IEEE_1164_FALLING_EDGE] = "IEEE.STD_LOGIC_1164.FALLING_EDGE(sU)B",
1168

1169
      [W_NUMERIC_STD_UNSIGNED] = "IEEE.NUMERIC_STD_UNSIGNED",
1170
      [W_NUMERIC_BIT_UNSIGNED] = "IEEE.NUMERIC_BIT_UNSIGNED",
1171
      [W_VERILOG_NET_VALUE]    = "NVC.VERILOG.T_NET_VALUE",
1172
      [W_VERILOG_WIRE_ARRAY]   = "NVC.VERILOG.T_WIRE_ARRAY",
1173

1174
      [W_OP_CCONV]               = "\"??\"",
1175
      [W_OP_AND]                 = "\"and\"",
1176
      [W_OP_OR]                  = "\"or\"",
1177
      [W_OP_NAND]                = "\"nand\"",
1178
      [W_OP_NOR]                 = "\"nor\"",
1179
      [W_OP_XOR]                 = "\"xor\"",
1180
      [W_OP_XNOR]                = "\"xnor\"",
1181
      [W_OP_EQUAL]               = "\"=\"",
1182
      [W_OP_NOT_EQUAL]           = "\"/=\"",
1183
      [W_OP_LESS_THAN]           = "\"<\"",
1184
      [W_OP_LESS_EQUAL]          = "\"<=\"",
1185
      [W_OP_GREATER_THAN]        = "\">\"",
1186
      [W_OP_GREATER_EQUAL]       = "\">=\"",
1187
      [W_OP_MATCH_EQUAL]         = "\"?=\"",
1188
      [W_OP_MATCH_NOT_EQUAL]     = "\"?/=\"",
1189
      [W_OP_MATCH_LESS_THAN]     = "\"?<\"",
1190
      [W_OP_MATCH_LESS_EQUAL]    = "\"?<=\"",
1191
      [W_OP_MATCH_GREATER_THAN]  = "\"?>\"",
1192
      [W_OP_MATCH_GREATER_EQUAL] = "\"?>=\"",
1193
      [W_OP_SLL]                 = "\"sll\"",
1194
      [W_OP_SRL]                 = "\"srl\"",
1195
      [W_OP_SLA]                 = "\"sla\"",
1196
      [W_OP_SRA]                 = "\"sra\"",
1197
      [W_OP_ROL]                 = "\"rol\"",
1198
      [W_OP_ROR]                 = "\"ror\"",
1199
      [W_OP_ADD]                 = "\"+\"",
1200
      [W_OP_MINUS]               = "\"-\"",
1201
      [W_OP_CONCAT]              = "\"&\"",
1202
      [W_OP_TIMES]               = "\"*\"",
1203
      [W_OP_DIVIDE]              = "\"/\"",
1204
      [W_OP_MOD]                 = "\"mod\"",
1205
      [W_OP_REM]                 = "\"rem\"",
1206
      [W_OP_EXPONENT]            = "\"**\"",
1207
      [W_OP_ABS]                 = "\"abs\"",
1208
      [W_OP_NOT]                 = "\"not\"",
1209
   };
1210

1211
   for (int i = 0; i < ARRAY_LEN(tab); i++)
919,215✔
1212
      id_cache[i] = ident_intern(i, tab[i]);
909,930✔
1213
}
9,285✔
1214

1215
bool is_uninstantiated_package(tree_t pack)
60,444✔
1216
{
1217
   return tree_kind(pack) == T_PACKAGE
60,444✔
1218
      && tree_generics(pack) > 0
58,522✔
1219
      && tree_genmaps(pack) == 0;
63,208✔
1220
}
1221

1222
bool is_uninstantiated_subprogram(tree_t decl)
128,583✔
1223
{
1224
   switch (tree_kind(decl)) {
128,583✔
1225
   case T_FUNC_DECL:
127,785✔
1226
   case T_FUNC_BODY:
1227
   case T_PROC_DECL:
1228
   case T_PROC_BODY:
1229
      return tree_generics(decl) > 0;
127,785✔
1230
   default:
1231
      return false;
1232
   }
1233
}
1234

1235
bool is_anonymous_subtype(type_t type)
375,323✔
1236
{
1237
   return type_kind(type) == T_SUBTYPE && !type_has_ident(type);
375,323✔
1238
}
1239

1240
bool unit_needs_cgen(tree_t unit)
351✔
1241
{
1242
   switch (tree_kind(unit)) {
351✔
1243
   case T_PACK_INST:
1244
      return true;
UNCOV
1245
   case T_PACK_BODY:
×
1246
      {
1247
         tree_t pack = tree_primary(unit);
×
UNCOV
1248
         return package_needs_body(pack) && !is_uninstantiated_package(pack);
×
1249
      }
1250
   case T_PACKAGE:
20✔
1251
      return !package_needs_body(unit) && !is_uninstantiated_package(unit);
40✔
1252
   default:
×
UNCOV
1253
      return false;
×
1254
   }
1255
}
1256

1257
bool package_needs_body(tree_t pack)
20,450✔
1258
{
1259
   assert(tree_kind(pack) == T_PACKAGE);
20,450✔
1260

1261
   const int ndecls = tree_decls(pack);
20,450✔
1262
   for (int i = 0; i < ndecls; i++) {
1,348,351✔
1263
      tree_t d = tree_decl(pack, i);
1,346,522✔
1264
      const tree_kind_t dkind = tree_kind(d);
1,346,522✔
1265
      if ((dkind == T_FUNC_DECL || dkind == T_PROC_DECL)
1,346,522✔
1266
          && !(tree_flags(d) & TREE_F_PREDEFINED))
1,209,218✔
1267
         return true;
1268
      else if (dkind == T_CONST_DECL && !tree_has_value(d))
1,328,708✔
1269
         return true;
1270
      else if (dkind == T_PROT_DECL)
1,328,071✔
1271
         return true;
1272
   }
1273

1274
   return false;
1275
}
1276

1277
static tree_t cached_unit(tree_t hint, tree_t *cache, well_known_t lib_name,
20,666✔
1278
                          well_known_t unit_name)
1279
{
1280
   const vhdl_standard_t curr = standard();
20,666✔
1281

1282
   if (cache[curr] == NULL) {
20,666✔
1283
      if (hint != NULL)
6,424✔
1284
         cache[curr] = hint;
1,941✔
1285
      else {
1286
         lib_t std = lib_require(well_known(lib_name));
4,483✔
1287
         cache[curr] = lib_get(std, well_known(unit_name));
4,483✔
1288
         assert(cache[curr] != NULL);
4,483✔
1289
      }
1290
   }
1291

1292
   assert(hint == NULL || hint == cache[curr]);
20,666✔
1293
   return cache[curr];
20,666✔
1294
}
1295

1296
static tree_t cached_std(tree_t hint)
18,925✔
1297
{
1298
   static tree_t standard_cache[STD_19 + 1] = {};
18,925✔
1299
   return cached_unit(hint, standard_cache, W_STD, W_STD_STANDARD);
18,925✔
1300
}
1301

1302
static tree_t search_type_decls(tree_t container, ident_t name)
19,962✔
1303
{
1304
   const int ndecls = tree_decls(container);
19,962✔
1305

1306
   for (int i = 0; i < ndecls; i++) {
1,046,437✔
1307
      tree_t d = tree_decl(container, i);
1,046,437✔
1308
      if (is_type_decl(d) && tree_ident(d) == name)
1,046,437✔
1309
         return d;
19,962✔
1310
   }
1311

1312
   return NULL;
1313
}
1314

1315
type_t std_type(tree_t std, std_type_t which)
1,236,357✔
1316
{
1317
   static type_t cache[STD_RANGE_DIRECTION + 1] = {};
1,236,357✔
1318
   assert(which < ARRAY_LEN(cache));
1,236,357✔
1319

1320
   if (cache[which] == NULL) {
1,236,357✔
1321
      const char *names[] = {
18,925✔
1322
         "universal_integer",
1323
         "universal_real",
1324
         "INTEGER",
1325
         "REAL",
1326
         "BOOLEAN",
1327
         "STRING",
1328
         "TIME",
1329
         "BIT",
1330
         "FILE_OPEN_KIND",
1331
         "FILE_OPEN_STATUS",
1332
         "NATURAL",
1333
         "BIT_VECTOR",
1334
         "SEVERITY_LEVEL",
1335
         "FILE_ORIGIN_KIND",
1336
         "FILE_OPEN_STATE",
1337
         "RANGE_DIRECTION",
1338
      };
1339

1340
      tree_t d = search_type_decls(cached_std(std), ident_new(names[which]));
18,925✔
1341
      if (d == NULL)
18,925✔
1342
         fatal_trace("cannot find standard type %s", names[which]);
1343

1344
      // Do not cache standard types while bootstrapping as the GC will
1345
      // move the objects after parsing
1346
      static int can_cache = -1;
18,925✔
1347
      if (can_cache == -1) can_cache = !opt_get_int(OPT_BOOTSTRAP);
18,925✔
1348

1349
      if (can_cache)
18,925✔
1350
         return (cache[which] = tree_type(d));
18,775✔
1351
      else
1352
         return tree_type(d);
150✔
1353
   }
1354
   else
1355
      return cache[which];
1356
}
1357

1358
type_t ieee_type(ieee_type_t which)
2,746✔
1359
{
1360
   static type_t cache[IEEE_STD_LOGIC_VECTOR + 1] = {};
2,746✔
1361
   assert(which < ARRAY_LEN(cache));
2,746✔
1362

1363
   if (cache[which] == NULL) {
2,746✔
1364
      static const char *const names[] = {
433✔
1365
         [IEEE_STD_ULOGIC] = "STD_ULOGIC",
1366
         [IEEE_STD_LOGIC] = "STD_LOGIC",
1367
         [IEEE_STD_ULOGIC_VECTOR] = "STD_ULOGIC_VECTOR",
1368
         [IEEE_STD_LOGIC_VECTOR] = "STD_LOGIC_VECTOR",
1369
      };
1370

1371
      static tree_t ieee_cache[STD_19 + 1] = {};
433✔
1372
      tree_t unit = cached_unit(NULL, ieee_cache, W_IEEE, W_IEEE_1164);
433✔
1373

1374
      tree_t d = search_type_decls(unit, ident_new(names[which]));
433✔
1375
      if (d == NULL)
433✔
1376
         fatal_trace("cannot find IEEE type %s", names[which]);
1377

1378
      // STD.STANDARD cannot depend on IEEE
1379
      assert(!opt_get_int(OPT_BOOTSTRAP));
433✔
1380

1381
      return (cache[which] = tree_type(d));
433✔
1382
   }
1383
   else
1384
      return cache[which];
1385
}
1386

1387
static tree_t cached_verilog(void)
1,253✔
1388
{
1389
   static tree_t verilog_cache[STD_19 + 1] = {};
1,253✔
1390
   return cached_unit(NULL, verilog_cache, W_NVC, W_NVC_VERILOG);
1,253✔
1391
}
1392

1393
type_t verilog_type(verilog_type_t which)
1,732✔
1394
{
1395
   static type_t cache[VERILOG_WIRE_ARRAY + 1] = {};
1,732✔
1396
   assert(which < ARRAY_LEN(cache));
1,732✔
1397

1398
   if (cache[which] == NULL) {
1,732✔
1399
      static const char *const names[] = {
549✔
1400
         [VERILOG_LOGIC] = "T_LOGIC",
1401
         [VERILOG_LOGIC_ARRAY] = "T_LOGIC_ARRAY",
1402
         [VERILOG_INT64] = "T_INT64",
1403
         [VERILOG_NET_VALUE] = "T_NET_VALUE",
1404
         [VERILOG_NET_ARRAY] = "T_NET_ARRAY",
1405
         [VERILOG_WIRE] = "T_WIRE",
1406
         [VERILOG_WIRE_ARRAY] = "T_WIRE_ARRAY",
1407
      };
1408

1409
      tree_t d = search_type_decls(cached_verilog(), ident_new(names[which]));
549✔
1410
      if (d == NULL)
549✔
1411
         fatal_trace("cannot find NVC.VERILOG type %s", names[which]);
1412

1413
      // STD.STANDARD cannot depend on NVC.VERILOG
1414
      assert(!opt_get_int(OPT_BOOTSTRAP));
549✔
1415

1416
      return (cache[which] = tree_type(d));
549✔
1417
   }
1418
   else
1419
      return cache[which];
1420
}
1421

1422
type_t reflection_type(reflect_type_t which)
281✔
1423
{
1424
   static type_t cache[REFLECT_SUBTYPE_MIRROR + 1] = {};
281✔
1425
   assert(which < ARRAY_LEN(cache));
281✔
1426

1427
   if (cache[which] == NULL) {
281✔
1428
      static const char *const names[] = {
55✔
1429
         [REFLECT_VALUE_MIRROR] = "VALUE_MIRROR",
1430
         [REFLECT_SUBTYPE_MIRROR] = "SUBTYPE_MIRROR",
1431
      };
1432

1433
      static tree_t reflect_cache[STD_19 + 1] = {};
55✔
1434
      tree_t unit = cached_unit(NULL, reflect_cache, W_STD, W_STD_REFLECTION);
55✔
1435

1436
      tree_t d = search_type_decls(unit, ident_new(names[which]));
55✔
1437
      if (d == NULL)
55✔
1438
         fatal_trace("cannot find REFLECTION type %s", names[which]);
1439

1440
      // STD.STANDARD cannot depend on REFLECTION
1441
      assert(!opt_get_int(OPT_BOOTSTRAP));
55✔
1442

1443
      return (cache[which] = tree_type(d));
55✔
1444
   }
1445
   else
1446
      return cache[which];
1447
}
1448

1449
bool is_open_coded_builtin(subprogram_kind_t kind)
2,463,697✔
1450
{
1451
   switch (kind) {
2,463,697✔
1452
   case S_ADD:
1453
   case S_SUB:
1454
   case S_DIV:
1455
   case S_MUL:
1456
   case S_MUL_PR:
1457
   case S_MUL_RP:
1458
   case S_MUL_PI:
1459
   case S_MUL_IP:
1460
   case S_DIV_PR:
1461
   case S_DIV_PP:
1462
   case S_DIV_PI:
1463
   case S_IDENTITY:
1464
   case S_NEGATE:
1465
   case S_SCALAR_LT:
1466
   case S_SCALAR_LE:
1467
   case S_SCALAR_GT:
1468
   case S_SCALAR_GE:
1469
   case S_SCALAR_EQ:
1470
   case S_SCALAR_NEQ:
1471
   case S_ABS:
1472
   case S_MOD:
1473
   case S_REM:
1474
   case S_EXP:
1475
   case S_MUL_RI:
1476
   case S_MUL_IR:
1477
   case S_DIV_RI:
1478
   case S_CONCAT:
1479
   case S_SCALAR_AND:
1480
   case S_SCALAR_OR:
1481
   case S_SCALAR_NOT:
1482
   case S_SCALAR_NAND:
1483
   case S_SCALAR_NOR:
1484
   case S_SCALAR_XOR:
1485
   case S_SCALAR_XNOR:
1486
   case S_FILE_OPEN1:
1487
   case S_FILE_OPEN2:
1488
   case S_FILE_READ:
1489
   case S_FILE_WRITE:
1490
   case S_DEALLOCATE:
1491
   case S_IEEE_AND:
1492
   case S_IEEE_OR:
1493
   case S_IEEE_XOR:
1494
   case S_IEEE_NAND:
1495
   case S_IEEE_NOR:
1496
   case S_IEEE_XNOR:
1497
   case S_IEEE_NOT:
1498
      return true;
1499
   default:
986,991✔
1500
      return false;
986,991✔
1501
   }
1502
}
1503

UNCOV
1504
tree_t std_func(ident_t mangled)
×
1505
{
UNCOV
1506
   tree_t std = cached_std(NULL);
×
1507

1508
   const int ndecls = tree_decls(std);
×
1509
   for (int i = 0; i < ndecls; i++) {
×
1510
      tree_t d = tree_decl(std, i);
×
1511
      if (is_subprogram(d) && tree_has_ident2(d) && tree_ident2(d) == mangled)
×
UNCOV
1512
         return d;
×
1513
   }
1514

1515
   return NULL;
1516
}
1517

1518
tree_t verilog_func(ident_t mangled)
704✔
1519
{
1520
   tree_t pack = cached_verilog();
704✔
1521

1522
   const int ndecls = tree_decls(pack);
704✔
1523
   for (int i = 0; i < ndecls; i++) {
75,542✔
1524
      tree_t d = tree_decl(pack, i);
75,542✔
1525
      if (is_subprogram(d) && tree_ident2(d) == mangled)
75,542✔
1526
         return d;
704✔
1527
   }
1528

1529
   fatal_trace("missing Verilog helper function %s", istr(mangled));
1530
}
1531

1532
tree_t name_to_ref(tree_t name)
107,360✔
1533
{
1534
   tree_kind_t kind;
107,360✔
1535
   while ((kind = tree_kind(name)) != T_REF) {
120,810✔
1536
      switch (kind) {
14,981✔
1537
      case T_ARRAY_REF:
13,450✔
1538
      case T_ARRAY_SLICE:
1539
      case T_RECORD_REF:
1540
      case T_ALL:
1541
         name = tree_value(name);
13,450✔
1542
         break;
13,450✔
1543
      default:
1544
         return NULL;
1545
      }
1546
   }
1547

1548
   return name;
1549
}
1550

1551
const char *port_mode_str(port_mode_t mode)
47✔
1552
{
1553
   const char *mode_str[] = {
47✔
1554
      "INVALID", "IN", "OUT", "INOUT", "BUFFER", "LINKAGE", "VIEW", "VIEW"
1555
   };
1556
   assert(mode < ARRAY_LEN(mode_str));
47✔
1557
   return mode_str[mode];
47✔
1558
}
1559

1560
void mangle_one_type(text_buf_t *buf, type_t type)
221,665✔
1561
{
1562
   ident_t ident = type_ident(type);
221,665✔
1563

1564
   char code = 0;
221,665✔
1565
   switch (is_well_known(ident)) {
221,665✔
1566
   case W_STD_INTEGER:        code = 'I'; break;
1567
   case W_STD_STRING:         code = 'S'; break;
4,590✔
1568
   case W_STD_REAL:           code = 'R'; break;
4,105✔
1569
   case W_STD_BOOL:           code = 'B'; break;
30,189✔
1570
   case W_STD_CHAR:           code = 'C'; break;
732✔
1571
   case W_STD_TIME:           code = 'T'; break;
1,218✔
1572
   case W_STD_NATURAL:        code = 'N'; break;
4,865✔
1573
   case W_STD_POSITIVE:       code = 'P'; break;
469✔
1574
   case W_STD_BIT:            code = 'J'; break;
3,563✔
1575
   case W_STD_BIT_VECTOR:     code = 'Q'; break;
3,662✔
1576
   case W_IEEE_LOGIC:         code = 'L'; break;
421✔
1577
   case W_IEEE_ULOGIC:        code = 'U'; break;
5,518✔
1578
   case W_IEEE_LOGIC_VECTOR:  code = 'V'; break;
2,383✔
1579
   case W_IEEE_ULOGIC_VECTOR: code = 'Y'; break;
1,497✔
1580
   default: break;
1581
   }
1582

1583
   if (code)
63,212✔
1584
      tb_append(buf, code);
79,215✔
1585
   else {
1586
      tb_printf(buf, "%zu", ident_len(ident));
142,450✔
1587
      tb_istr(buf, ident);
142,450✔
1588
   }
1589
}
221,665✔
1590

1591
ident_t get_call_context(ident_t mangled)
4,591✔
1592
{
1593
   const char *str = istr(mangled), *p = str, *end = NULL;
4,591✔
1594
   for (; *p; p++) {
169,302✔
1595
      if (*p == '(') break;
161,449✔
1596
      if (*p == '.') end = p;
160,120✔
1597
   }
1598
   assert(end != NULL);
4,591✔
1599

1600
   return ident_new_n(str, end - str);
4,591✔
1601
}
1602

1603
tree_t primary_unit_of(tree_t unit)
39,184✔
1604
{
1605
   switch (tree_kind(unit)) {
39,184✔
1606
   case T_ENTITY:
1607
   case T_COMPONENT:
1608
   case T_PACKAGE:
1609
   case T_BLOCK:
1610
   case T_ELAB:
1611
   case T_PACK_INST:
1612
      return unit;
1613
   case T_ARCH:
26,250✔
1614
   case T_CONFIGURATION:
1615
   case T_PACK_BODY:
1616
      return tree_primary(unit);
26,250✔
UNCOV
1617
   default:
×
1618
      fatal_trace("invalid kind %s in primary_unit_of",
1619
                  tree_kind_str(tree_kind(unit)));
1620
   }
1621
}
1622

1623
unsigned get_case_choice_char(tree_t value, int depth)
15,249✔
1624
{
1625
   switch (tree_kind(value)) {
16,069✔
1626
   case T_STRING:
15,227✔
1627
      if (depth < tree_chars(value))
15,227✔
1628
         return assume_int(tree_char(value, depth));
14,666✔
1629
      else
1630
         return ~0;   // Out of bounds
1631

1632
   case T_AGGREGATE:
22✔
1633
      {
1634
         const int nassocs = tree_assocs(value);
22✔
1635
         type_t type = tree_type(value);
22✔
1636

1637
         for (int i = 0, pos = 0; i < nassocs; i++) {
36✔
1638
            tree_t a = tree_assoc(value, i);
35✔
1639
            switch (tree_subkind(a)) {
35✔
1640
            case A_NAMED:
×
1641
               if (rebase_index(type, 0, assume_int(tree_name(a))) == depth)
×
UNCOV
1642
                  return assume_int(tree_value(a));
×
1643
               break;
1644

1645
            case A_POS:
11✔
1646
               if (pos++ == (unsigned)depth)
11✔
1647
                  return assume_int(tree_value(a));
5✔
1648
               break;
1649

1650
            case A_CONCAT:
24✔
1651
               {
1652
                  tree_t left = tree_value(a);
24✔
1653

1654
                  type_t left_type = tree_type(left);
24✔
1655
                  if (type_is_unconstrained(left_type))
24✔
UNCOV
1656
                     fatal_at(tree_loc(left), "sorry, this expression is not "
×
1657
                              "currently supported in a case choice");
1658

1659
                  tree_t lr = range_of(tree_type(left), 0);
24✔
1660
                  int64_t left_len;
24✔
1661
                  if (!folded_length(lr, &left_len))
24✔
UNCOV
1662
                     fatal_at(tree_loc(left), "cannot determine length of "
×
1663
                              "aggregate element");
1664

1665
                  if (depth < pos + left_len)
24✔
1666
                     return get_case_choice_char(left, depth - pos);
16✔
1667

1668
                  pos += left_len;
8✔
1669
               }
1670
               break;
8✔
1671

1672
            case A_OTHERS:
×
UNCOV
1673
               return assume_int(tree_value(a));
×
1674

UNCOV
1675
            case A_SLICE:
×
1676
               {
1677
                  tree_t base = tree_value(a);
×
UNCOV
1678
                  tree_t r = tree_range(a, 0);
×
1679

1680
                  const int64_t rleft = assume_int(tree_left(r));
×
UNCOV
1681
                  const int64_t rright = assume_int(tree_right(r));
×
1682

1683
                  const int64_t loffset = rebase_index(type, 0, rleft);
×
UNCOV
1684
                  const int64_t roffset = rebase_index(type, 0, rright);
×
1685

1686
                  if (depth >= loffset && depth <= roffset)
×
UNCOV
1687
                     return get_case_choice_char(base, depth - loffset);
×
1688
               }
1689
            }
1690
         }
1691

1692
         // This will produce an error during bounds checking
1693
         return ~0;
1694
      }
1695

1696
   case T_REF:
500✔
1697
      {
1698
         tree_t decl = tree_ref(value);
500✔
1699
         assert(tree_kind(decl) == T_CONST_DECL || tree_kind(decl) == T_ALIAS);
500✔
1700
         assert(tree_has_value(decl));
500✔
1701
         return get_case_choice_char(tree_value(decl), depth);
500✔
1702
      }
1703

1704
   case T_ARRAY_SLICE:
320✔
1705
      {
1706
         tree_t base = tree_value(value);
320✔
1707
         tree_t r = tree_range(value, 0);
320✔
1708
         const int64_t rleft = assume_int(tree_left(r));
320✔
1709
         const int64_t offset = rebase_index(tree_type(base), 0, rleft);
320✔
1710
         return get_case_choice_char(base, depth + offset);
320✔
1711
      }
1712

1713
   default:
×
UNCOV
1714
      fatal_at(tree_loc(value), "unsupported tree type %s in case choice",
×
1715
               tree_kind_str(tree_kind(value)));
1716
   }
1717
}
1718

1719
int64_t encode_case_choice(tree_t value, int length, int bits)
2,009✔
1720
{
1721
   uint64_t enc = 0;
2,009✔
1722
   for (int i = 0; i < length; i++) {
17,220✔
1723
      if (bits > 0) {
15,211✔
1724
         enc <<= bits;
5,412✔
1725
         enc |= get_case_choice_char(value, i);
5,412✔
1726
      }
1727
      else {
1728
         enc *= 0x27d4eb2d;
9,799✔
1729
         enc += get_case_choice_char(value, i);
9,799✔
1730
      }
1731
   }
1732

1733
   return enc;
2,009✔
1734
}
1735

1736
void to_string(text_buf_t *tb, type_t type, int64_t value)
723✔
1737
{
1738
   if (type_is_integer(type))
723✔
1739
      tb_printf(tb, "%"PRIi64, value);
556✔
1740
   else if (type_is_enum(type)) {
167✔
1741
      type_t base = type_base_recur(type);
70✔
1742
      if (value < 0 || value >= type_enum_literals(base))
70✔
1743
         tb_printf(tb, "%"PRIi64, value);
4✔
1744
      else
1745
         tb_cat(tb, istr(tree_ident(type_enum_literal(base, value))));
66✔
1746
   }
1747
   else if (type_is_physical(type)) {
97✔
1748
      type_t base = type_base_recur(type);
27✔
1749
      const unsigned nunits = type_units(base);
27✔
1750
      tree_t max_unit = NULL;
27✔
1751
      int64_t max_unit_value = 0;
27✔
1752

1753
      // Find the largest unit that evenly divides the given value
1754
      for (unsigned u = 0; u < nunits; u++) {
243✔
1755
         tree_t unit = type_unit(base, u);
216✔
1756
         const int64_t unit_value = assume_int(tree_value(unit));
216✔
1757
         if ((unit_value > max_unit_value) && (value % unit_value == 0)) {
216✔
1758
            max_unit = unit;
100✔
1759
            max_unit_value = unit_value;
100✔
1760
         }
1761
      }
1762
      assert(max_unit);
27✔
1763

1764
      tb_printf(tb, "%"PRIi64" %s", value / max_unit_value,
27✔
1765
                istr(tree_ident(max_unit)));
1766
   }
1767
   else if (type_is_real(type)) {
70✔
1768
      union { int64_t i; double r; } u = { .i = value };
62✔
1769
      tb_printf(tb, "%.17g", u.r);
62✔
1770
   }
1771
   else if (type_is_access(type)) {
8✔
1772
      if (value == 0)
8✔
1773
         tb_cat(tb, "NULL");
4✔
1774
      else
1775
         tb_printf(tb, "%p", (void *)value);
4✔
1776
   }
1777
}
723✔
1778

1779
static bool is_static(tree_t expr)
3,560✔
1780
{
1781
   switch (tree_kind(expr)) {
3,623✔
1782
   case T_REF:
902✔
1783
      {
1784
         tree_t decl = tree_ref(expr);
902✔
1785
         switch (tree_kind(decl)) {
902✔
1786
         case T_CONST_DECL:
186✔
1787
            return !!(tree_flags(decl) & TREE_F_GLOBALLY_STATIC);
186✔
1788
         case T_UNIT_DECL:
1789
         case T_ENUM_LIT:
1790
         case T_GENERIC_DECL:
1791
            return true;
1792
         case T_ALIAS:
×
UNCOV
1793
            return is_static(tree_value(decl));
×
1794
         default:
257✔
1795
            return false;
257✔
1796
         }
1797
      }
1798

1799
   case T_LITERAL:
1800
   case T_STRING:
1801
      return true;
1802

1803
   case T_FCALL:
228✔
1804
      return !!(tree_flags(expr) & (TREE_F_LOCALLY_STATIC
228✔
1805
                                    | TREE_F_GLOBALLY_STATIC));
1806

1807
   case T_RECORD_REF:
59✔
1808
      return is_static(tree_value(expr));
59✔
1809

1810
   case T_ARRAY_REF:
64✔
1811
      {
1812
         if (!is_static(tree_value(expr)))
64✔
1813
            return false;
1814

1815
         const int nparams = tree_params(expr);
64✔
1816
         for (int i = 0; i < nparams; i++) {
128✔
1817
            if (!is_static(tree_value(tree_param(expr, i))))
64✔
1818
               return false;
1819
         }
1820

1821
         return true;
1822
      }
1823

1824
   case T_ARRAY_SLICE:
32✔
1825
      {
1826
         if (!is_static(tree_value(expr)))
32✔
1827
            return false;
1828

1829
         assert(tree_ranges(expr) == 1);
32✔
1830

1831
         tree_t r = tree_range(expr, 0);
32✔
1832
         if (!is_static(tree_left(r)) || !is_static(tree_right(r)))
32✔
UNCOV
1833
            return false;
×
1834

1835
         return true;
1836
      }
1837

1838
   case T_ATTR_REF:
43✔
1839
      {
1840
         switch (tree_subkind(expr)) {
43✔
1841
         case ATTR_EVENT:
1842
         case ATTR_ACTIVE:
1843
         case ATTR_LAST_EVENT:
1844
         case ATTR_LAST_ACTIVE:
1845
         case ATTR_LAST_VALUE:
1846
         case ATTR_DRIVING:
1847
         case ATTR_DRIVING_VALUE:
1848
         case ATTR_STABLE:
1849
         case ATTR_QUIET:
1850
            return false;
1851
         case ATTR_POS:
4✔
1852
         case ATTR_VAL:
1853
         case ATTR_LEFTOF:
1854
         case ATTR_RIGHTOF:
1855
         case ATTR_SUCC:
1856
         case ATTR_PRED:
1857
         case ATTR_VALUE:
1858
         case ATTR_IMAGE:
1859
            assert(tree_params(expr) == 1);
4✔
1860
            return is_static(tree_value(tree_param(expr, 0)));
4✔
1861
         case ATTR_LENGTH:
39✔
1862
         case ATTR_LEFT:
1863
         case ATTR_RIGHT:
1864
         case ATTR_LOW:
1865
         case ATTR_HIGH:
1866
         case ATTR_RANGE:
1867
         case ATTR_REVERSE_RANGE:
1868
            {
1869
               tree_t ref = name_to_ref(tree_name(expr));
39✔
1870
               if (ref == NULL)
39✔
1871
                  return false;
1872

1873
               switch (tree_kind(tree_ref(ref))) {
39✔
1874
               case T_GENERIC_DECL:
1875
               case T_PORT_DECL:
1876
               case T_SIGNAL_DECL:
1877
               case T_SUBTYPE_DECL:
1878
               case T_TYPE_DECL:
1879
                  return true;
1880
               default:
9✔
1881
                  return false;
9✔
1882
               }
1883
            }
1884
         default:
×
UNCOV
1885
            return true;
×
1886
         }
1887
      }
1888

1889
   default:
×
UNCOV
1890
      return false;
×
1891
   }
1892
}
1893

1894
tree_t longest_static_prefix(tree_t expr)
16,618✔
1895
{
1896
   switch (tree_kind(expr)) {
16,618✔
1897
   case T_ARRAY_REF:
2,429✔
1898
      {
1899
         tree_t value = tree_value(expr);
2,429✔
1900
         tree_t prefix = longest_static_prefix(value);
2,429✔
1901

1902
         if (prefix != value)
2,429✔
1903
            return prefix;
1904

1905
         const int nparams = tree_params(expr);
2,392✔
1906
         for (int i = 0; i < nparams; i++) {
4,734✔
1907
            if (!is_static(tree_value(tree_param(expr, i))))
2,668✔
1908
               return prefix;
1909
         }
1910

1911
         return expr;
1912
      }
1913

1914
   case T_ARRAY_SLICE:
361✔
1915
      {
1916
         tree_t value = tree_value(expr);
361✔
1917
         tree_t prefix = longest_static_prefix(value);
361✔
1918

1919
         if (prefix != value)
361✔
1920
            return prefix;
1921

1922
         assert(tree_ranges(expr) == 1);
352✔
1923

1924
         tree_t r = tree_range(expr, 0);
352✔
1925
         if (tree_subkind(r) == RANGE_EXPR) {
352✔
1926
            if (!is_static(tree_value(r)))
19✔
1927
               return prefix;
6✔
1928
         }
1929
         else if (!is_static(tree_left(r)) || !is_static(tree_right(r)))
333✔
1930
            return prefix;
20✔
1931

1932
         return expr;
1933
      }
1934

1935
   case T_RECORD_REF:
1,069✔
1936
      {
1937
         tree_t value = tree_value(expr);
1,069✔
1938
         tree_t prefix = longest_static_prefix(value);
1,069✔
1939

1940
         if (prefix != value)
1,069✔
1941
            return prefix;
28✔
1942

1943
         return expr;
1944
      }
1945

1946
   default:
1947
      return expr;
1948
   }
1949
}
1950

1951
tree_t body_of(tree_t pack)
19,000✔
1952
{
1953
   const tree_kind_t kind = tree_kind(pack);
19,000✔
1954
   if (kind == T_PACK_INST)
19,000✔
1955
      return NULL;
1956

1957
   assert(tree_kind(pack) == T_PACKAGE);
19,000✔
1958

1959
   ident_t body_i = well_known(W_BODY);
19,000✔
1960
   ident_t body_name = ident_prefix(tree_ident(pack), body_i, '-');
19,000✔
1961
   return lib_get_qualified(body_name);
19,000✔
1962
}
1963

1964
tree_t find_generic_map(tree_t unit, int pos, tree_t g)
976✔
1965
{
1966
   const int ngenmaps = tree_genmaps(unit);
976✔
1967

1968
   if (pos < ngenmaps) {
976✔
1969
      tree_t m = tree_genmap(unit, pos);
778✔
1970
      if (tree_subkind(m) == P_POS && tree_pos(m) == pos)
778✔
1971
         return tree_value(m);
579✔
1972
   }
1973

1974
   for (int j = 0; j < ngenmaps; j++) {
1,365✔
1975
      tree_t m = tree_genmap(unit, j);
1,167✔
1976
      switch (tree_subkind(m)) {
1,167✔
1977
      case P_NAMED:
605✔
1978
         {
1979
            tree_t name = tree_name(m);
605✔
1980
            assert(tree_kind(name) == T_REF);
605✔
1981

1982
            if (tree_has_ref(name) && tree_ref(name) == g)
605✔
1983
               return tree_value(m);
23✔
1984
         }
1985
         break;
1986

1987
      case P_POS:
562✔
1988
         if (tree_pos(m) == pos)
562✔
1989
            return tree_value(m);
176✔
1990
         break;
1991

1992
      default:
1993
         break;
1994
      }
1995
   }
1996

1997
   return NULL;
1998
}
1999

2000
bool relaxed_rules(void)
713,340✔
2001
{
2002
   return opt_get_int(OPT_RELAXED);
713,340✔
2003
}
2004

2005
bool is_type_attribute(attr_kind_t kind)
57,381✔
2006
{
2007
   switch (kind) {
57,381✔
2008
   case ATTR_SUBTYPE:
2009
   case ATTR_BASE:
2010
   case ATTR_ELEMENT:
2011
   case ATTR_DESIGNATED_SUBTYPE:
2012
   case ATTR_INDEX:
2013
   case ATTR_RECORD:
2014
      return true;
2015
   default:
56,445✔
2016
      return false;
56,445✔
2017
   }
2018
}
2019

2020
bool attribute_has_param(attr_kind_t attr)
28,538✔
2021
{
2022
   switch (attr) {
28,538✔
2023
   case ATTR_IMAGE:
2024
   case ATTR_SUCC:
2025
   case ATTR_PRED:
2026
   case ATTR_DELAYED:
2027
   case ATTR_LEFTOF:
2028
   case ATTR_RIGHTOF:
2029
   case ATTR_VALUE:
2030
   case ATTR_POS:
2031
   case ATTR_LOW:
2032
   case ATTR_HIGH:
2033
   case ATTR_LEFT:
2034
   case ATTR_RIGHT:
2035
   case ATTR_LENGTH:
2036
   case ATTR_RANGE:
2037
   case ATTR_REVERSE_RANGE:
2038
   case ATTR_VAL:
2039
   case ATTR_QUIET:
2040
   case ATTR_STABLE:
2041
   case ATTR_INDEX:
2042
   case ATTR_ASCENDING:
2043
      return true;
2044
   default:
3,113✔
2045
      return false;
3,113✔
2046
   }
2047
}
2048

2049
type_t get_type_or_null(tree_t t)
4,734,999✔
2050
{
2051
   switch (tree_kind(t)) {
4,734,999✔
2052
   case T_LIBRARY:
2053
   case T_ATTR_SPEC:
2054
   case T_PACKAGE:
2055
   case T_PACK_INST:
2056
   case T_PACK_BODY:
2057
   case T_ENTITY:
2058
   case T_ARCH:
2059
   case T_PROCESS:
2060
   case T_COMPONENT:
2061
   case T_INSTANCE:
2062
   case T_CONCURRENT:
2063
   case T_BLOCK:
2064
   case T_WHILE:
2065
   case T_FOR:
2066
   case T_LOOP:
2067
   case T_GROUP_TEMPLATE:
2068
   case T_CONFIGURATION:
2069
   case T_GROUP:
2070
   case T_FOR_GENERATE:
2071
   case T_IF_GENERATE:
2072
   case T_CASE_GENERATE:
2073
   case T_USE:
2074
   case T_CONTEXT:
2075
   case T_PSL_DECL:
2076
   case T_PSL_DIRECT:
2077
   case T_WAVEFORM:
2078
      return NULL;
2079
   default:
4,609,486✔
2080
      if (tree_has_type(t))
4,609,486✔
2081
         return tree_type(t);
4,600,775✔
2082
      else
2083
         return NULL;
2084
   }
2085
}
2086

2087
type_t subtype_for_string(tree_t str, type_t base)
33,579✔
2088
{
2089
   if (type_const_bounds(base))
33,579✔
2090
      return base;    // Can be checked statically
2091
   else if (!type_is_unconstrained(base))
29,289✔
2092
      base = type_base_recur(base);
371✔
2093

2094
   // Construct a new constrained array subtype: the direction and
2095
   // bounds are the same as those for a positional array aggregate
2096
   type_t sub = type_new(T_SUBTYPE);
29,289✔
2097
   type_set_base(sub, base);
29,289✔
2098

2099
   type_t index_type = index_type_of(base, 0);
29,289✔
2100
   const bool is_enum = type_is_enum(index_type);
29,289✔
2101

2102
   // The direction is determined by the index type
2103
   range_kind_t dir = direction_of(index_type, 0);
29,289✔
2104
   tree_t index_r = range_of(index_type, 0);
29,289✔
2105

2106
   // The left bound is the left of the index type and the right bound
2107
   // is determined by the number of elements
2108

2109
   tree_t left = NULL, right = NULL;
29,289✔
2110
   const int nchars = tree_chars(str);
29,289✔
2111

2112
   if (is_enum) {
29,289✔
2113
      const int nlits = type_enum_literals(type_base_recur(index_type));
16✔
2114
      int64_t index_left = assume_int(tree_left(index_r));
16✔
2115

2116
      int64_t iright, ileft;
16✔
2117
      if (nchars == 0) {
16✔
2118
         iright = index_left;
1✔
2119
         ileft = assume_int(tree_right(index_r));
1✔
2120
      }
2121
      else if (dir == RANGE_DOWNTO) {
15✔
2122
         ileft = index_left;
×
UNCOV
2123
         iright = MIN(nlits - 1, MAX(0, index_left - nchars + 1));
×
2124
      }
2125
      else {
2126
         ileft = index_left;
15✔
2127
         iright = MIN(nlits - 1, MAX(0, index_left + nchars - 1));
15✔
2128
      }
2129

2130
      left = get_enum_lit(str, index_type, ileft);
16✔
2131
      right = get_enum_lit(str, index_type, iright);
16✔
2132
   }
2133
   else {
2134
      left = tree_left(index_r);
29,273✔
2135

2136
      int64_t iright;
29,273✔
2137
      if (dir == RANGE_DOWNTO)
29,273✔
UNCOV
2138
         iright = assume_int(left) - nchars + 1;
×
2139
      else
2140
         iright = assume_int(left) + nchars - 1;
29,273✔
2141

2142
      right = get_int_lit(str, index_type, iright);
29,273✔
2143
   }
2144

2145
   tree_t r = tree_new(T_RANGE);
29,289✔
2146
   tree_set_subkind(r, dir);
29,289✔
2147
   tree_set_left(r, left);
29,289✔
2148
   tree_set_right(r, right);
29,289✔
2149
   tree_set_loc(r, tree_loc(str));
29,289✔
2150
   tree_set_type(r, index_type);
29,289✔
2151

2152
   tree_t c = tree_new(T_CONSTRAINT);
29,289✔
2153
   tree_set_subkind(c, C_INDEX);
29,289✔
2154
   tree_add_range(c, r);
29,289✔
2155
   tree_set_loc(c, tree_loc(str));
29,289✔
2156

2157
   type_set_constraint(sub, c);
29,289✔
2158

2159
   return sub;
29,289✔
2160
}
2161

2162
tree_t change_ref(tree_t name, tree_t new)
2,875✔
2163
{
2164
   switch (tree_kind(name)) {
2,875✔
2165
   case T_REF:
1,896✔
2166
      {
2167
         tree_t ref = make_ref(new);
1,896✔
2168
         tree_set_loc(ref, tree_loc(name));
1,896✔
2169
         return ref;
1,896✔
2170
      }
2171

2172
   case T_ARRAY_REF:
146✔
2173
      {
2174
         tree_t value = change_ref(tree_value(name), new);
146✔
2175

2176
         tree_t t = tree_new(T_ARRAY_REF);
146✔
2177
         tree_set_loc(t, tree_loc(name));
146✔
2178
         tree_set_value(t, value);
146✔
2179
         tree_set_type(t, type_elem(tree_type(value)));
146✔
2180

2181
         const int nparams = tree_params(name);
146✔
2182
         for (int i = 0; i < nparams; i++)
292✔
2183
            tree_add_param(t, tree_param(name, i));
146✔
2184

2185
         return t;
2186
      }
2187

2188
   case T_ARRAY_SLICE:
69✔
2189
      {
2190
         tree_t value = change_ref(tree_value(name), new);
69✔
2191
         tree_t r = tree_range(name, 0);
69✔
2192

2193
         tree_t constraint = tree_new(T_CONSTRAINT);
69✔
2194
         tree_set_subkind(constraint, C_INDEX);
69✔
2195
         tree_add_range(constraint, r);
69✔
2196

2197
         type_t slice_type = type_new(T_SUBTYPE);
69✔
2198
         type_set_constraint(slice_type, constraint);
69✔
2199
         type_set_base(slice_type, tree_type(value));
69✔
2200

2201
         tree_t t = tree_new(T_ARRAY_SLICE);
69✔
2202
         tree_set_loc(t, tree_loc(name));
69✔
2203
         tree_set_value(t, value);
69✔
2204
         tree_set_type(t, slice_type);
69✔
2205
         tree_add_range(t, r);
69✔
2206

2207
         return t;
69✔
2208
      }
2209

2210
   case T_RECORD_REF:
534✔
2211
      {
2212
         tree_t t = tree_new(T_RECORD_REF);
534✔
2213
         tree_set_loc(t, tree_loc(name));
534✔
2214
         tree_set_value(t, change_ref(tree_value(name), new));
534✔
2215
         tree_set_type(t, tree_type(name));
534✔
2216
         tree_set_ident(t, tree_ident(name));
534✔
2217
         tree_set_ref(t, tree_ref(name));
534✔
2218

2219
         return t;
534✔
2220
      }
2221

2222
   case T_CONV_FUNC:
218✔
2223
      {
2224
         tree_t t = tree_new(T_CONV_FUNC);
218✔
2225
         tree_set_loc(t, tree_loc(name));
218✔
2226
         tree_set_value(t, change_ref(tree_value(name), new));
218✔
2227
         tree_set_ident(t, tree_ident(name));
218✔
2228
         tree_set_type(t, tree_type(name));
218✔
2229
         tree_set_ref(t, tree_ref(name));
218✔
2230

2231
         return t;
218✔
2232
      }
2233

2234
   case T_TYPE_CONV:
12✔
2235
      {
2236
         tree_t t = tree_new(T_TYPE_CONV);
12✔
2237
         tree_set_loc(t, tree_loc(name));
12✔
2238
         tree_set_type(t, tree_type(name));
12✔
2239
         tree_set_value(t, change_ref(tree_value(name), new));
12✔
2240

2241
         return t;
12✔
2242
      }
2243

UNCOV
2244
   default:
×
2245
      fatal_trace("cannot handle tree kind %s in elab_change_ref",
2246
                  tree_kind_str(tree_kind(name)));
2247
   }
2248
}
2249

2250
static void build_wait_for_target(tree_t expr, build_wait_fn_t fn, void *ctx)
4,125✔
2251
{
2252
   switch (tree_kind(expr)) {
4,125✔
2253
   case T_ARRAY_SLICE:
108✔
2254
      build_wait(tree_range(expr, 0), fn, ctx);
108✔
2255
      break;
108✔
2256

2257
   case T_ARRAY_REF:
780✔
2258
      {
2259
         const int nparams = tree_params(expr);
780✔
2260
         for (int i = 0; i < nparams; i++)
1,560✔
2261
            build_wait(tree_value(tree_param(expr, i)), fn, ctx);
780✔
2262
      }
2263
      break;
2264

2265
   default:
2266
      break;
2267
   }
2268
}
4,125✔
2269

2270
void build_wait(tree_t expr, build_wait_fn_t fn, void *ctx)
19,750✔
2271
{
2272
   // LRM 08 section 10.2 has rules for building a wait statement from a
2273
   // sensitivity list. LRM 08 section 11.3 extends these rules to
2274
   // all-sensitised processes.
2275

2276
   switch (tree_kind(expr)) {
24,420✔
2277
   case T_REF:
6,200✔
2278
      if (class_of(tree_ref(expr)) == C_SIGNAL)
6,200✔
2279
         (*fn)(expr, ctx);
3,593✔
2280
      break;
2281

2282
   case T_EXTERNAL_NAME:
10✔
2283
      if (tree_class(expr) == C_SIGNAL)
10✔
2284
         (*fn)(expr, ctx);
10✔
2285
      break;
2286

2287
   case T_WAVEFORM:
3,995✔
2288
   case T_QUALIFIED:
2289
   case T_TYPE_CONV:
2290
   case T_INERTIAL:
2291
      if (tree_has_value(expr))
3,995✔
2292
         build_wait(tree_value(expr), fn, ctx);
3,983✔
2293
      break;
2294

2295
   case T_ASSERT:
634✔
2296
      build_wait(tree_value(expr), fn, ctx);
634✔
2297
      // Fall-through
2298
   case T_REPORT:
639✔
2299
      if (tree_has_message(expr))
639✔
2300
         build_wait(tree_message(expr), fn, ctx);
403✔
2301
      break;
2302

2303
   case T_ARRAY_REF:
1,157✔
2304
   case T_ARRAY_SLICE:
2305
   case T_RECORD_REF:
2306
      {
2307
         tree_t ref = name_to_ref(expr);
1,157✔
2308
         if (ref != NULL && class_of(ref) == C_SIGNAL
1,157✔
2309
             && longest_static_prefix(expr) == expr)
761✔
2310
            (*fn)(expr, ctx);
663✔
2311
         else {
2312
            build_wait(tree_value(expr), fn, ctx);
494✔
2313
            build_wait_for_target(expr, fn, ctx);
494✔
2314
         }
2315
      }
2316
      break;
2317

2318
   case T_FCALL:
2,949✔
2319
   case T_PCALL:
2320
   case T_PROT_FCALL:
2321
   case T_PROT_PCALL:
2322
      {
2323
         tree_t decl = tree_ref(expr);
2,949✔
2324
         const int nparams = tree_params(expr);
2,949✔
2325
         for (int i = 0; i < nparams; i++) {
8,014✔
2326
            tree_t p = tree_param(expr, i), port;
5,065✔
2327
            switch (tree_subkind(p)) {
5,065✔
2328
            case P_POS:
5,065✔
2329
               port = tree_port(decl, tree_pos(p));
5,065✔
2330
               break;
5,065✔
2331
            case P_NAMED:
×
2332
               port = tree_ref(name_to_ref(tree_name(p)));
×
2333
               break;
×
UNCOV
2334
            default:
×
2335
               should_not_reach_here();
2336
            }
2337
            assert(tree_kind(port) == T_PARAM_DECL);
5,065✔
2338

2339
            switch (tree_subkind(port)) {
5,065✔
2340
            case PORT_IN:
5,056✔
2341
            case PORT_INOUT:
2342
            case PORT_ARRAY_VIEW:
2343
            case PORT_RECORD_VIEW:
2344
               build_wait(tree_value(p), fn, ctx);
5,056✔
2345
               break;
5,056✔
2346
            default:
2347
               break;
2348
            }
2349
         }
2350
      }
2351
      break;
2352

2353
   case T_AGGREGATE:
540✔
2354
      {
2355
         const int nassocs = tree_assocs(expr);
540✔
2356
         for (int i = 0; i < nassocs; i++) {
1,948✔
2357
            tree_t a = tree_assoc(expr, i);
1,408✔
2358
            build_wait(tree_value(a), fn, ctx);
1,408✔
2359

2360
            switch (tree_subkind(a)) {
1,408✔
2361
            case A_RANGE:
70✔
2362
            case A_SLICE:
2363
               build_wait(tree_range(a, 0), fn, ctx);
70✔
2364
               break;
70✔
2365
            case A_NAMED:
124✔
2366
               build_wait(tree_name(a), fn, ctx);
124✔
2367
               break;
124✔
2368
            }
2369
         }
2370
      }
2371
      break;
2372

2373
   case T_ATTR_REF:
574✔
2374
      {
2375
         const attr_kind_t predef = tree_subkind(expr);
574✔
2376
         if (predef == ATTR_EVENT || predef == ATTR_ACTIVE)
574✔
2377
            build_wait(tree_name(expr), fn, ctx);
234✔
2378

2379
         const int nparams = tree_params(expr);
574✔
2380
         for (int i = 0; i < nparams; i++)
598✔
2381
            build_wait(tree_value(tree_param(expr, i)), fn, ctx);
24✔
2382
      }
2383
      break;
2384

2385
   case T_LITERAL:
2386
   case T_STRING:
2387
   case T_DUMMY_DRIVER:
2388
      break;
2389

2390
   case T_IF:
330✔
2391
      {
2392
         const int nconds = tree_conds(expr);
330✔
2393
         for (int i = 0; i < nconds; i++)
894✔
2394
            build_wait(tree_cond(expr, i), fn, ctx);
564✔
2395
      }
2396
      break;
2397

2398
   case T_COND_STMT:
568✔
2399
      {
2400
         if (tree_has_value(expr))
568✔
2401
            build_wait(tree_value(expr), fn, ctx);
382✔
2402

2403
         const int nstmts = tree_stmts(expr);
568✔
2404
         for (int i = 0; i < nstmts; i++)
1,154✔
2405
            build_wait(tree_stmt(expr, i), fn, ctx);
586✔
2406
      }
2407
      break;
2408

2409
   case T_COND_VALUE:
4✔
2410
      {
2411
         const int nconds = tree_conds(expr);
4✔
2412
         for (int i = 0; i < nconds; i++)
16✔
2413
            build_wait(tree_cond(expr, i), fn, ctx);
12✔
2414
         break;
2415
      }
2416

2417
   case T_COND_EXPR:
12✔
2418
      {
2419
         if (tree_has_value(expr))
12✔
2420
            build_wait(tree_value(expr), fn, ctx);
8✔
2421

2422
         build_wait(tree_result(expr), fn, ctx);
12✔
2423
         break;
12✔
2424
      }
2425

2426
   case T_PROCESS:
74✔
2427
   case T_SEQUENCE:
2428
   case T_PROC_BODY:
2429
      {
2430
         const int ndecls = tree_decls(expr);
74✔
2431
         for (int i = 0; i < ndecls; i++) {
105✔
2432
            tree_t d = tree_decl(expr, i);
31✔
2433
            if (tree_kind(d) == T_PROC_BODY)
31✔
2434
               build_wait(d, fn, ctx);
2✔
2435
         }
2436

2437
         const int nstmts = tree_stmts(expr);
74✔
2438
         for (int i = 0; i < nstmts; i++)
187✔
2439
            build_wait(tree_stmt(expr, i), fn, ctx);
113✔
2440
      }
2441
      break;
2442

2443
   case T_SIGNAL_ASSIGN:
3,562✔
2444
      {
2445
         build_wait_for_target(tree_target(expr), fn, ctx);
3,562✔
2446

2447
         const int nwaves = tree_waveforms(expr);
3,562✔
2448
         for (int i = 0; i < nwaves; i++)
7,354✔
2449
            build_wait(tree_waveform(expr, i), fn, ctx);
3,792✔
2450
      }
2451
      break;
2452

2453
   case T_VAR_ASSIGN:
65✔
2454
   case T_FORCE:
2455
      build_wait_for_target(tree_target(expr), fn, ctx);
65✔
2456
      build_wait(tree_value(expr), fn, ctx);
65✔
2457
      break;
65✔
2458

2459
   case T_RELEASE:
4✔
2460
      build_wait_for_target(tree_target(expr), fn, ctx);
4✔
2461
      break;
4✔
2462

2463
   case T_CASE:
61✔
2464
   case T_MATCH_CASE:
2465
      {
2466
         build_wait(tree_value(expr), fn, ctx);
61✔
2467

2468
         const int nstmts = tree_stmts(expr);
61✔
2469
         for (int i = 0; i < nstmts; i++) {
374✔
2470
            tree_t alt = tree_stmt(expr, i);
313✔
2471

2472
            const int nstmts = tree_stmts(alt);
313✔
2473
            for (int j = 0; j < nstmts; j++)
626✔
2474
               build_wait(tree_stmt(alt, j), fn, ctx);
313✔
2475
         }
2476
      }
2477
      break;
2478

2479
   case T_FOR:
21✔
2480
      {
2481
         build_wait(tree_range(expr, 0), fn, ctx);
21✔
2482

2483
         const int nstmts = tree_stmts(expr);
21✔
2484
         for (int i = 0; i < nstmts; i++)
46✔
2485
            build_wait(tree_stmt(expr, i), fn, ctx);
25✔
2486
      }
2487
      break;
2488

2489
   case T_WHILE:
1✔
2490
      build_wait(tree_value(expr), fn, ctx);
1✔
2491
      // Fall-through
2492
   case T_LOOP:
5✔
2493
      {
2494
         const int nstmts = tree_stmts(expr);
5✔
2495
         for (int i = 0; i < nstmts; i++)
26✔
2496
            build_wait(tree_stmt(expr, i), fn, ctx);
21✔
2497
      }
2498
      break;
2499

2500
   case T_NEXT:
12✔
2501
   case T_EXIT:
2502
      if (tree_has_value(expr))
12✔
2503
         build_wait(tree_value(expr), fn, ctx);
8✔
2504
      break;
2505

2506
   case T_RANGE:
199✔
2507
      if (tree_subkind(expr) == RANGE_EXPR)
199✔
2508
         build_wait(tree_value(expr), fn, ctx);
21✔
2509
      else {
2510
         build_wait(tree_left(expr), fn, ctx);
178✔
2511
         build_wait(tree_right(expr), fn, ctx);
178✔
2512
      }
2513
      break;
2514

2515
   case T_OPEN:
2516
      break;
2517

UNCOV
2518
   default:
×
2519
      fatal_trace("Cannot handle tree kind %s in wait expression",
2520
                  tree_kind_str(tree_kind(expr)));
2521
   }
2522
}
19,750✔
2523

2524
void print_syntax(const char *fmt, ...)
2,193✔
2525
{
2526
   LOCAL_TEXT_BUF tb = tb_new();
2,193✔
2527
   bool highlighting = false;
2,193✔
2528
   static bool comment = false, last_was_newline = false;
2,193✔
2529
   for (const char *p = fmt; *p != '\0'; p++) {
11,404✔
2530
      if (comment) {
9,211✔
2531
         if (*p == '\n' || *p == '\r') {
3,278✔
2532
            comment = false;
95✔
2533
            last_was_newline = true;
95✔
2534
            tb_cat(tb, "$$\n");
95✔
2535
         }
2536
         else if (*p != '~' && *p != '#') {
3,183✔
2537
            tb_append(tb, *p);
3,023✔
2538
            last_was_newline = false;
3,023✔
2539
         }
2540
         if (p > fmt && *p == '/' && *(p - 1) == '*') {
3,278✔
2541
            tb_cat(tb, "$$");
18✔
2542
            comment = false;
18✔
2543
            last_was_newline = false;
18✔
2544
         }
2545
      }
2546
      else if (*p == '\r') {
5,933✔
2547
         if (!last_was_newline) {
22✔
2548
            tb_append(tb, '\n');
×
UNCOV
2549
            last_was_newline = true;
×
2550
         }
2551
      }
2552
      else if (*p == '#' && *(p + 1) != '#') {
5,911✔
2553
         tb_cat(tb, "$bold$$cyan$");
390✔
2554
         last_was_newline = false;
390✔
2555
         highlighting = true;
390✔
2556
      }
2557
      else if (*p == '~' && *(p + 1) != '~') {
5,521✔
2558
         tb_cat(tb, "$yellow$");
1✔
2559
         last_was_newline = false;
1✔
2560
         highlighting = true;
1✔
2561
      }
2562
      else if ((*p == '-' && *(p + 1) == '-')
5,520✔
2563
               || (*p == '/' && *(p + 1) == '/')
5,429✔
2564
               || (*p == '/' && *(p + 1) == '*')) {
5,425✔
2565
         tb_cat(tb, "$red$");
113✔
2566
         tb_append(tb, *p);
113✔
2567
         last_was_newline = false;
113✔
2568
         comment = true;
113✔
2569
      }
2570
      else if (!isalnum_iso88591(*p) && *p != '_'
5,407✔
2571
               && *p != '%' && highlighting) {
2,791✔
2572
         tb_cat(tb, "$$");
330✔
2573
         tb_append(tb, *p);
330✔
2574
         last_was_newline = false;
330✔
2575
         highlighting = false;
330✔
2576
      }
2577
      else {
2578
         tb_append(tb, *p);
5,077✔
2579
         last_was_newline = (*p == '\n');
5,077✔
2580
      }
2581
   }
2582

2583
   if (highlighting)
2,193✔
2584
      tb_cat(tb, "$$");
61✔
2585

2586
   va_list ap;
2,193✔
2587
   va_start(ap, fmt);
2,193✔
2588

2589
   if (syntax_buf != NULL) {
2,193✔
2590
      ostream_t os = { tb_ostream_write, syntax_buf, CHARSET_ISO88591 };
2,193✔
2591
      nvc_vfprintf(&os, tb_get(tb), ap);
2,193✔
2592
   }
2593
   else
UNCOV
2594
      nvc_vprintf(tb_get(tb), ap);
×
2595

2596
   va_end(ap);
2,193✔
2597
}
2,193✔
2598

2599
void capture_syntax(text_buf_t *tb)
9✔
2600
{
2601
   assert(tb == NULL || syntax_buf == NULL);
9✔
2602
   syntax_buf = tb;
9✔
2603
}
9✔
2604

2605
bool all_character_literals(type_t type)
35,611✔
2606
{
2607
   assert(type_is_enum(type));
35,611✔
2608

2609
   type_t base = type_base_recur(type);
35,611✔
2610
   const int nlits = type_enum_literals(base);
35,611✔
2611
   for (int i = 0; i < nlits; i++) {
198,281✔
2612
      if (ident_char(tree_ident(type_enum_literal(base, i)), 0) != '\'')
174,028✔
2613
         return false;
2614
   }
2615

2616
   return true;
2617
}
2618

2619
bool is_operator_symbol(ident_t ident)
31,966✔
2620
{
2621
   const well_known_t wk = is_well_known(ident);
31,966✔
2622
   if (wk >= NUM_WELL_KNOWN)
31,966✔
2623
      return false;
2624
   else if (standard() < STD_08)
17,259✔
2625
      return wk >= W_OP_AND && wk <= W_OP_NOT;
3,305✔
2626
   else
2627
      return wk >= W_OP_AND && wk <= W_OP_MATCH_GREATER_EQUAL;
13,954✔
2628
}
2629

2630
bool same_tree(tree_t a, tree_t b)
8,472✔
2631
{
2632
   const tree_kind_t akind = tree_kind(a);
8,472✔
2633
   if (akind != tree_kind(b))
8,472✔
2634
      return false;
2635

2636
   switch (akind) {
8,209✔
2637
   case T_REF:
3,717✔
2638
      return tree_has_ref(a) && tree_has_ref(b) && tree_ref(a) == tree_ref(b);
4,873✔
2639
   case T_ARRAY_REF:
1,302✔
2640
      {
2641
         if (!same_tree(tree_value(a), tree_value(b)))
1,302✔
2642
            return false;
2643

2644
         const int nparams = tree_params(a);
1,273✔
2645
         assert(nparams == tree_params(b));
1,273✔
2646

2647
         for (int i = 0; i < nparams; i++) {
2,403✔
2648
            tree_t pa = tree_value(tree_param(a, i));
2,173✔
2649
            tree_t pb = tree_value(tree_param(b, i));
2,173✔
2650
            if (!same_tree(pa, pb))
2,173✔
2651
               return false;
2652
         }
2653

2654
         return true;
2655
      }
2656
   case T_ARRAY_SLICE:
46✔
2657
      {
2658
         if (!same_tree(tree_value(a), tree_value(b)))
46✔
2659
            return false;
2660

2661
         tree_t ra = tree_range(a, 0);
46✔
2662
         tree_t rb = tree_range(b, 0);
46✔
2663

2664
         const range_kind_t rakind = tree_subkind(ra);
46✔
2665
         if (rakind != tree_subkind(rb) || rakind == RANGE_EXPR)
46✔
2666
            return false;
2667

2668
         return same_tree(tree_left(ra), tree_left(rb))
46✔
2669
            && same_tree(tree_right(ra), tree_right(rb));
50✔
2670
      }
2671
   case T_RECORD_REF:
346✔
2672
      return ident_casecmp(tree_ident(a), tree_ident(b))
346✔
2673
         && same_tree(tree_value(a), tree_value(b));
354✔
2674
   case T_LITERAL:
2,512✔
2675
      {
2676
         const literal_kind_t lkind = tree_subkind(a);
2,512✔
2677
         if (lkind != tree_subkind(b))
2,512✔
2678
            return false;
2679

2680
         switch (lkind) {
2,512✔
2681
         case L_PHYSICAL:
36✔
2682
            {
2683
               ident_t aid = tree_has_ident(a) ? tree_ident(a) : NULL;
36✔
2684
               ident_t bid = tree_has_ident(b) ? tree_ident(b) : NULL;
36✔
2685
               if (aid == bid)
36✔
2686
                  return tree_ival(a) == tree_ival(b);
36✔
2687
               else
2688
                  return false;
2689
            }
2690
         case L_INT:
2,445✔
2691
            return tree_ival(a) == tree_ival(b);
2,445✔
2692
         case L_REAL:
31✔
2693
            return tree_dval(a) == tree_dval(b);
31✔
2694
         case L_NULL:
2695
            return true;
2696
         default:
×
UNCOV
2697
            return false;
×
2698
         }
2699
      }
2700
   case T_STRING:
254✔
2701
      {
2702
         const int nchars = tree_chars(a);
254✔
2703
         if (tree_chars(b) != nchars)
254✔
2704
            return false;
2705

2706
         for (int i = 0; i < nchars; i++) {
309✔
2707
            if (!same_tree(tree_char(a, i), tree_char(b, i)))
56✔
2708
               return false;
2709
         }
2710

2711
         return true;
2712
      }
2713
   case T_OPEN:
2714
      return true;
2715
   default:
32✔
2716
      return false;
32✔
2717
   }
2718
}
2719

2720
static range_kind_t get_range_direction(tree_t r)
410✔
2721
{
2722
   assert(tree_kind(r) == T_RANGE);
410✔
2723

2724
   const range_kind_t dir = tree_subkind(r);
410✔
2725
   if (dir != RANGE_EXPR)
410✔
2726
      return dir;
2727

2728
   // Handle ranges like X'RANGE where X has known direction
2729

2730
   tree_t aref = tree_value(r);
59✔
2731
   assert(tree_kind(aref) == T_ATTR_REF);
59✔
2732

2733
   const attr_kind_t kind = tree_subkind(aref);
59✔
2734
   assert(kind == ATTR_RANGE || kind == ATTR_REVERSE_RANGE);
59✔
2735

2736
   type_t prefix_type = tree_type(tree_name(aref));
59✔
2737
   if (type_is_none(prefix_type))
59✔
2738
      return RANGE_ERROR;
2739
   if (type_is_unconstrained(prefix_type))
58✔
2740
      return RANGE_EXPR;
2741

2742
   tree_t prefix_r = range_of(prefix_type, 0);
54✔
2743

2744
   const range_kind_t prefix_dir = get_range_direction(prefix_r);
54✔
2745
   if (prefix_dir != RANGE_TO && prefix_dir != RANGE_DOWNTO)
54✔
2746
      return prefix_dir;
2747
   else if (kind == ATTR_REVERSE_RANGE)
54✔
2748
      return prefix_dir == RANGE_TO ? RANGE_DOWNTO : RANGE_TO;
4✔
2749
   else
2750
      return prefix_dir;
2751
}
2752

2753
bool calculate_aggregate_bounds(tree_t expr, range_kind_t *kind,
9,106✔
2754
                                int64_t *left, int64_t *right)
2755
{
2756
   // Calculate the direction and bounds of an array aggregate using the
2757
   // rules in LRM 93 7.3.2.2
2758

2759
   type_t type = tree_type(expr);
9,106✔
2760
   if (type_is_none(type))
9,106✔
2761
      return false;
2762

2763
   type_t index_type = index_type_of(type, 0);
9,106✔
2764
   if (index_type == NULL)
9,106✔
2765
      return false;
2766
   else if (type_is_none(index_type) || type_is_generic(index_type))
9,106✔
2767
      return false;
3✔
2768

2769
   tree_t index_r = range_of(index_type, 0), base_r = index_r;
9,103✔
2770

2771
   int64_t low, high;
9,103✔
2772
   if (!folded_bounds(index_r, &low, &high))
9,103✔
2773
      return false;
2774

2775
   int64_t clow = INT64_MAX, chigh = INT64_MIN;  // Actual bounds computed below
9,083✔
2776

2777
   range_kind_t dir;
9,083✔
2778
   if (type_is_unconstrained(type))
9,083✔
2779
      dir = tree_subkind(index_r);
8,727✔
2780
   else {
2781
      base_r = range_of(type, 0);
356✔
2782
      dir = get_range_direction(base_r);
356✔
2783
   }
2784

2785
   const int nassocs = tree_assocs(expr);
9,083✔
2786

2787
   if (standard() >= STD_08) {
9,083✔
2788
      // VHDL-2008 range association determines index direction for
2789
      // unconstrained aggregate when the expression type matches the
2790
      // array type
2791
      for (int i = 0; i < nassocs; i++) {
19,083✔
2792
         tree_t a = tree_assoc(expr, i);
13,802✔
2793
         if (tree_subkind(a) == A_SLICE)
13,802✔
2794
            dir = tree_subkind(tree_range(a, 0));
71✔
2795
      }
2796
   }
2797

2798
   if (dir != RANGE_TO && dir != RANGE_DOWNTO)
9,083✔
2799
      return false;
2800

2801
   int64_t pos = 0;
2802
   for (int i = 0; i < nassocs; i++) {
25,590✔
2803
      tree_t a = tree_assoc(expr, i);
22,608✔
2804
      int64_t ilow = 0, ihigh = 0;
22,608✔
2805
      const assoc_kind_t akind = tree_subkind(a);
22,608✔
2806

2807
      switch (akind) {
22,608✔
2808
      case A_NAMED:
861✔
2809
         {
2810
            tree_t name = tree_name(a);
861✔
2811
            if (folded_int(name, &ilow))
861✔
2812
               ihigh = ilow;
848✔
2813
            else
2814
               return false;
6,084✔
2815
         }
2816
         break;
848✔
2817

2818
      case A_RANGE:
1,481✔
2819
      case A_SLICE:
2820
         {
2821
            tree_t r = tree_range(a, 0);
1,481✔
2822
            const range_kind_t rkind = tree_subkind(r);
1,481✔
2823
            if (rkind == RANGE_TO || rkind == RANGE_DOWNTO) {
1,481✔
2824
               tree_t left = tree_left(r), right = tree_right(r);
1,112✔
2825

2826
               int64_t ileft, iright;
1,112✔
2827
               if (folded_int(left, &ileft) && folded_int(right, &iright)) {
1,112✔
2828
                  ilow = (rkind == RANGE_TO ? ileft : iright);
581✔
2829
                  ihigh = (rkind == RANGE_TO ? iright : ileft);
581✔
2830
               }
2831
               else
2832
                  return false;
531✔
2833
            }
2834
            else
2835
               return false;
2836
         }
2837
         break;
2838

2839
      case A_OTHERS:
2840
         return false;
2841

2842
      case A_POS:
12,616✔
2843
         if (i == 0) {
12,616✔
2844
            int64_t ileft;
2,043✔
2845
            if (folded_int(tree_left(base_r), &ileft))
2,043✔
2846
               ilow = ihigh = ileft;
2,043✔
2847
            else
UNCOV
2848
               return false;
×
2849
         }
2850
         else if (dir == RANGE_TO)
10,573✔
2851
            ilow = ihigh = clow + pos;
10,571✔
2852
         else
2853
            ilow = ihigh = chigh - pos;
2✔
2854
         pos++;
12,616✔
2855
         break;
12,616✔
2856

2857
      case A_CONCAT:
7,636✔
2858
         {
2859
            type_t value_type = tree_type(tree_value(a));
7,636✔
2860

2861
            int64_t length;
7,636✔
2862
            if (type_is_unconstrained(value_type))
7,636✔
2863
               return false;
5,157✔
2864
            else if (folded_length(range_of(value_type, 0), &length)) {
2,874✔
2865
               if (i == 0) {
2,479✔
2866
                  int64_t ileft;
2,083✔
2867
                  if (folded_int(tree_left(base_r), &ileft))
2,083✔
2868
                     ilow = ihigh = ileft;
2,083✔
2869
                  else
UNCOV
2870
                     return false;
×
2871
               }
2872
               else if (dir == RANGE_TO) {
396✔
2873
                  ilow = clow + pos;
372✔
2874
                  ihigh = ilow + length - 1;
372✔
2875
               }
2876
               else {
2877
                  ihigh = chigh - pos;
24✔
2878
                  ilow = ihigh - length + 1;
24✔
2879
               }
2880
               pos += length;
2,479✔
2881
            }
2882
            else
2883
               return false;
2884
         }
2885
         break;
2886
      }
2887

2888
      clow = MIN(clow, ilow);
16,524✔
2889
      chigh = MAX(chigh, ihigh);
16,524✔
2890
   }
2891

2892
   if (clow < low || chigh > high)
2,982✔
2893
      return false;   // Will raise a bounds check error later
2894

2895
   *kind = dir;
2,976✔
2896
   *left = dir == RANGE_TO ? clow : chigh;
2,976✔
2897
   *right = dir == RANGE_TO ? chigh : clow;
2,976✔
2898

2899
   return true;
2,976✔
2900
}
2901

2902
type_t calculate_aggregate_subtype(tree_t expr)
7,526✔
2903
{
2904
   range_kind_t dir;
7,526✔
2905
   int64_t ileft, iright;
7,526✔
2906
   if (!calculate_aggregate_bounds(expr, &dir, &ileft, &iright))
7,526✔
2907
      return NULL;
2908

2909
   type_t type = tree_type(expr);
2,955✔
2910

2911
   const int ndims = dimension_of(type);
2,955✔
2912
   type_t a0_type = NULL;
2,955✔
2913
   if (ndims > 1) {
2,955✔
2914
      a0_type = tree_type(tree_value(tree_assoc(expr, 0)));
87✔
2915
      if (type_is_unconstrained(a0_type))
87✔
2916
         return NULL;
2917

2918
      assert(dimension_of(a0_type) == ndims - 1);
87✔
2919
   }
2920

2921
   type_t index_type = index_type_of(type, 0);
2,955✔
2922

2923
   tree_t left = get_discrete_lit(expr, index_type, ileft);
2,955✔
2924
   tree_t right = get_discrete_lit(expr, index_type, iright);
2,955✔
2925
   assert(left != NULL && right != NULL);
2,955✔
2926

2927
   type_t sub = type_new(T_SUBTYPE);
2,955✔
2928
   type_set_base(sub, type_base_recur(type));
2,955✔
2929

2930
   type_t elem = type_elem(type);
2,955✔
2931
   if (type_is_unconstrained(elem)) {
2,955✔
2932
      tree_t a0 = tree_assoc(expr, 0);
149✔
2933
      switch (tree_subkind(a0)) {
149✔
2934
      case A_CONCAT:
15✔
2935
      case A_SLICE:
2936
         a0_type = type_elem(tree_type(tree_value(a0)));
15✔
2937
         break;
15✔
2938
      default:
134✔
2939
         a0_type = tree_type(tree_value(a0));
134✔
2940
         break;
134✔
2941
      }
2942

2943
      if (!type_is_unconstrained(a0_type))
149✔
2944
         elem = a0_type;
93✔
2945
   }
2946

2947
   type_set_elem(sub, elem);
2,955✔
2948

2949
   tree_t cons = tree_new(T_CONSTRAINT);
2,955✔
2950
   tree_set_subkind(cons, C_INDEX);
2,955✔
2951

2952
   tree_t r = tree_new(T_RANGE);
2,955✔
2953
   tree_set_subkind(r, dir);
2,955✔
2954
   tree_set_type(r, index_type);
2,955✔
2955
   tree_set_left(r, left);
2,955✔
2956
   tree_set_right(r, right);
2,955✔
2957

2958
   tree_add_range(cons, r);
2,955✔
2959

2960
   for (int i = 1; i < ndims; i++)
3,042✔
2961
      tree_add_range(cons, range_of(a0_type, i - 1));
87✔
2962

2963
   type_set_constraint(sub, cons);
2,955✔
2964

2965
   return sub;
2,955✔
2966
}
2967

2968
bool can_be_signal(type_t type)
55,505✔
2969
{
2970
   switch (type_kind(type)) {
76,296✔
2971
   case T_RECORD:
12,654✔
2972
      {
2973
         const int nfields = type_fields(type);
12,654✔
2974
         for (int i = 0; i < nfields; i++) {
50,104✔
2975
            if (!can_be_signal(tree_type(type_field(type, i))))
38,816✔
2976
               return false;
2977
         }
2978

2979
         return true;
2980
      }
2981
   case T_ARRAY:
8,034✔
2982
      return can_be_signal(type_elem(type));
8,034✔
2983
   case T_SUBTYPE:
12,757✔
2984
      return can_be_signal(type_base(type));
12,757✔
2985
   case T_ACCESS:
2986
   case T_FILE:
2987
   case T_PROTECTED:
2988
   case T_INCOMPLETE:
2989
      return false;
2990
   default:
36,612✔
2991
      return true;
36,612✔
2992
   }
2993
}
2994

2995
type_t merge_constraints(type_t to, type_t from)
1,318✔
2996
{
2997
   assert(type_is_unconstrained(to));
1,318✔
2998
   assert(type_eq(to, from));
1,318✔
2999

3000
   tree_t cto = NULL;
1,318✔
3001
   if (type_kind(to) == T_SUBTYPE && type_has_constraint(to))
1,318✔
3002
      cto = type_constraint(to);
30✔
3003

3004
   tree_t cfrom = NULL;
1,318✔
3005
   if (type_kind(from) == T_SUBTYPE && type_has_constraint(from))
1,318✔
3006
      cfrom = type_constraint(from);
1,036✔
3007

3008
   if (cfrom == NULL)
1,036✔
3009
      return to;
282✔
3010

3011
   type_t sub = type_new(T_SUBTYPE);
1,036✔
3012
   type_set_base(sub, type_base_recur(to));
1,036✔
3013

3014
   if (type_is_array(to)) {
1,036✔
3015
      type_set_constraint(sub, cto ?: cfrom);
2,047✔
3016

3017
      type_t elem = type_elem(to);
1,030✔
3018
      if (type_is_unconstrained(elem))
1,030✔
3019
         type_set_elem(sub, merge_constraints(elem, type_elem(from)));
18✔
3020
      else
3021
         type_set_elem(sub, elem);
1,012✔
3022
   }
3023
   else {
3024
      tree_t cnew = tree_new(T_CONSTRAINT);
6✔
3025
      tree_set_subkind(cnew, C_RECORD);
6✔
3026
      tree_set_loc(cnew, tree_loc(cto ?: cfrom));
7✔
3027

3028
      type_set_constraint(sub, cnew);
6✔
3029

3030
      if (cto != NULL) {
6✔
3031
         const int nto = tree_ranges(cto);
5✔
3032
         for (int i = 0; i < nto; i++)
10✔
3033
            tree_add_range(cnew, tree_range(cto, i));
5✔
3034
      }
3035

3036
      const int nfrom = tree_ranges(cfrom), base = tree_ranges(cnew);
6✔
3037
      for (int i = 0; i < nfrom; i++) {
16✔
3038
         tree_t ec = tree_range(cfrom, i);
10✔
3039
         assert(tree_kind(ec) == T_ELEM_CONSTRAINT);
10✔
3040

3041
         ident_t id = tree_ident(ec);
10✔
3042
         bool found = false;
10✔
3043
         for (int j = 0; j < base && !found; j++)
19✔
3044
            found |= tree_ident(tree_range(cnew, j)) == id;
9✔
3045

3046
         if (!found)
10✔
3047
            tree_add_range(cnew, ec);
5✔
3048
      }
3049
   }
3050

3051
   return sub;
3052
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc