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

nickg / nvc / 6903463504

17 Nov 2023 11:35AM UTC coverage: 91.168% (+0.006%) from 91.162%
6903463504

push

github

nickg
Improve handling of implicit literal conversions

329 of 343 new or added lines in 7 files covered. (95.92%)

759 existing lines in 8 files now uncovered.

50580 of 55480 relevant lines covered (91.17%)

608081.41 hits per line

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

57.69
/src/dump.c
1
//
2
//  Copyright (C) 2011-2023  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 "hash.h"
21
#include "ident.h"
22
#include "phase.h"
23
#include "psl/psl-phase.h"
24
#include "tree.h"
25
#include "type.h"
26
#include "vlog/vlog-phase.h"
27

28
#include <assert.h>
29
#include <string.h>
30
#include <ctype.h>
31
#include <inttypes.h>
32

33
#define DUMP_TYPE_HINT  0
34
#define DUMP_ADDRESS    0
35
#define DUMP_STATICNESS 0
36
#define DUMP_GEN_NAMES  0
37

38
static void dump_expr(tree_t t);
39
static void dump_stmt(tree_t t, int indent);
40
static void dump_port(tree_t t, int indent);
41
static void dump_decl(tree_t t, int indent);
42
static void dump_decls(tree_t t, int indent);
43
static void dump_type(type_t type);
44
static void dump_package(tree_t t, int indent);
45
static void dump_package_body(tree_t t, int indent);
46
static void dump_constraint(tree_t t);
47
static void dump_elem_constraints(type_t type);
48

49
typedef tree_t (*get_fn_t)(tree_t, unsigned);
50

51
static void tab(int indent)
202✔
52
{
53
   print_syntax("%*s", indent, "");
202✔
54
}
202✔
55

56
static void cannot_dump(tree_t t, const char *hint)
×
57
{
58
   print_syntax("\n");
×
59
   fflush(stdout);
×
60
   fatal("cannot dump %s kind %s", hint, tree_kind_str(tree_kind(t)));
×
61
}
62

63
static void dump_param(tree_t p)
23✔
64
{
65
   switch (tree_subkind(p)) {
23✔
66
   case P_POS:
67
      break;
68
   case P_NAMED:
2✔
69
      dump_expr(tree_name(p));
2✔
70
      print_syntax(" => ");
2✔
71
      break;
2✔
72
   }
73
   dump_expr(tree_value(p));
23✔
74
}
23✔
75

76
static void dump_params(tree_t t, get_fn_t get, int n, const char *prefix)
13✔
77
{
78
   if (n > 0) {
13✔
79
      if (prefix != NULL) {
12✔
80
         print_syntax(prefix, "");
2✔
81
         print_syntax(" ");
2✔
82
      }
83
      print_syntax("(");
12✔
84
      for (int i = 0; i < n; i++) {
35✔
85
         if (i > 0)
23✔
86
            print_syntax(", ");
11✔
87
         dump_param((*get)(t, i));
23✔
88
      }
89
      print_syntax(")");
12✔
90
   }
91
}
13✔
92

93
static void dump_range(tree_t r)
7✔
94
{
95
   switch (tree_subkind(r)) {
7✔
96
   case RANGE_TO:
5✔
97
      dump_expr(tree_left(r));
5✔
98
      print_syntax(" #to ");
5✔
99
      dump_expr(tree_right(r));
5✔
100
      break;
5✔
101
   case RANGE_DOWNTO:
2✔
102
      dump_expr(tree_left(r));
2✔
103
      print_syntax(" #downto ");
2✔
104
      dump_expr(tree_right(r));
2✔
105
      break;
2✔
106
   case RANGE_EXPR:
×
107
   case RANGE_ERROR:
108
      if (tree_has_value(r))
×
109
         dump_expr(tree_value(r));
×
110
      return;
111
   }
112
}
7✔
113

114
static void dump_type_hint(tree_t t)
115
{
116
#if DUMP_TYPE_HINT
117
   static int nested = 0;
118
   if (++nested == 1 && tree_has_type(t)) {
119
      color_printf("$red$$<$/*");
120
      dump_type(tree_type(t));
121
      color_printf("$>$$red$*/$$");
122
   }
123
   --nested;
124
#endif
125
}
126

127
static void dump_address(tree_t t)
128
{
129
#if DUMP_ADDRESS
130
   uint32_t a = (uint32_t)((uintptr_t)tree_arena(t) >> 2);
131
   a = (a ^ 61) ^ (a >> 16);
132
   a = a + (a << 3);
133
   a = a ^ (a >> 4);
134
   a = a * UINT32_C(0x27d4eb2d);
135
   a = a ^ (a >> 15);
136

137
   const int r = 1 + a % 5;
138
   const int g = 1 + (a >> 8) % 5;
139
   const int b = 1 + (a >> 16) % 5;
140

141
   const int color = 16 + 36*r + 6*g + b;
142

143
   char *LOCAL fmt = xasprintf("$!#%d${%%p}$$", color);
144
   color_printf(fmt, t);
145
#endif
146
}
147

148
static void dump_waveform(tree_t w)
3✔
149
{
150
   if (tree_has_value(w))
3✔
151
      dump_expr(tree_value(w));
3✔
152
   else
153
      print_syntax("#null");
×
154

155
   if (tree_has_delay(w)) {
3✔
156
      print_syntax(" #after ");
3✔
157
      dump_expr(tree_delay(w));
3✔
158
   }
159
}
3✔
160

161
static void dump_external_name(tree_t t)
1✔
162
{
163
   print_syntax("<< #%s ", class_str(tree_class(t)));
1✔
164
   const int nparts = tree_parts(t);
1✔
165
   for (int i = 0; i < nparts; i++) {
4✔
166
      tree_t part = tree_part(t, i);
3✔
167
      switch (tree_subkind(part)) {
3✔
168
      case PE_ABSOLUTE:
1✔
169
         print_syntax(".");
1✔
170
         break;
1✔
171
      case PE_SIMPLE:
2✔
172
         print_syntax("%s%s", istr(tree_ident(part)),
2✔
173
                      i + 1 < nparts ? "." : "");
2✔
174
         break;
2✔
175
      case PE_CARET:
×
176
         print_syntax("^.");
×
177
         break;
×
178
      }
179
   }
3✔
180
   print_syntax(" : ");
1✔
181
   dump_type(tree_type(t));
1✔
182
   print_syntax(" >>");
1✔
183
}
1✔
184

185
static void dump_expr(tree_t t)
167✔
186
{
187
   switch (tree_kind(t)) {
167✔
188
   case T_PROT_FCALL:
1✔
189
      dump_expr(tree_name(t));
1✔
190
      print_syntax(".");
1✔
191
      // Fall-through
192
   case T_FCALL:
10✔
193
      if (tree_has_ref(t)) {
10✔
194
         tree_t decl = tree_ref(t);
10✔
195
         dump_address(decl);
10✔
196
         print_syntax("%s", istr(tree_ident(decl)));
10✔
197
      }
198
      else
199
         print_syntax("%s", istr(tree_ident(t)));
×
200
      dump_params(t, tree_param, tree_params(t), NULL);
10✔
201
#if DUMP_STATICNESS
202
      if (tree_flags(t) & TREE_F_LOCALLY_STATIC)
203
         color_printf("$red$/* locally static */$$");
204
      else if (tree_flags(t) & TREE_F_GLOBALLY_STATIC)
205
         color_printf("$red$/* globally static */$$");
206
#endif
207
      break;
10✔
208

209
   case T_CONV_FUNC:
×
210
      if (tree_has_ref(t)) {
×
211
         tree_t decl = tree_ref(t);
×
212
         dump_address(decl);
×
213
         print_syntax("%s", istr(tree_ident(decl)));
×
214
      }
215
      else
216
         print_syntax("%s", istr(tree_ident(t)));
×
217
      print_syntax("(");
×
218
      dump_expr(tree_value(t));
×
219
      print_syntax(")");
×
220
      break;
×
221

222
   case T_LITERAL:
29✔
223
      switch (tree_subkind(t)) {
29✔
224
      case L_INT:
23✔
225
         print_syntax("%"PRIi64, tree_ival(t));
23✔
226
         break;
23✔
227
      case L_PHYSICAL:
4✔
228
         if (tree_has_ident(t))
4✔
229
            print_syntax("%"PRIi64" %s", tree_ival(t), istr(tree_ident(t)));
4✔
230
         else
231
            print_syntax("%"PRIi64, tree_ival(t));
×
232
         break;
233
      case L_REAL:
2✔
234
         print_syntax("%lf", tree_dval(t));
2✔
235
         break;
2✔
236
      case L_NULL:
×
237
         print_syntax("#null");
×
238
         break;
×
239
      default:
240
         assert(false);
×
241
      }
242
      break;
243

244
   case T_STRING:
1✔
245
      {
246
         print_syntax("\"");
1✔
247
         const int nchars = tree_chars(t);
1✔
248
         for (int i = 0; i < nchars; i++) {
7✔
249
            ident_t rune = tree_ident(tree_char(t, i));
6✔
250
            if (ident_char(rune, 0) == '\'')
6✔
251
               print_syntax("%c", ident_char(rune, 1));
6✔
252
            else
253
               print_syntax("\" & %s & \"", istr(rune));
×
254
         }
255
         print_syntax("\"");
1✔
256
      }
257
      break;
1✔
258

259
   case T_NEW:
×
260
      print_syntax("#new ");
×
261
      dump_expr(tree_value(t));
×
262
      break;
×
263

264
   case T_ALL:
×
265
      if (tree_has_value(t)) {
×
266
         dump_expr(tree_value(t));
×
267
         print_syntax(".#all");
×
268
      }
269
      else
270
         print_syntax("#all");
×
271
      break;
272

273
   case T_TYPE_REF:
1✔
274
      dump_type(tree_type(t));
1✔
275
      break;
1✔
276

277
   case T_AGGREGATE:
3✔
278
      print_syntax("(");
3✔
279
      for (unsigned i = 0; i < tree_assocs(t); i++) {
7✔
280
         if (i > 0)
4✔
281
            print_syntax(", ");
1✔
282
         tree_t a = tree_assoc(t, i);
4✔
283
         tree_t value = tree_value(a);
4✔
284
         switch (tree_subkind(a)) {
4✔
285
         case A_POS:
×
286
            dump_expr(value);
×
287
            break;
×
288
         case A_NAMED:
1✔
289
            dump_expr(tree_name(a));
1✔
290
            print_syntax(" => ");
1✔
291
            dump_expr(value);
1✔
292
            break;
1✔
293
         case A_OTHERS:
3✔
294
            print_syntax("#others => ");
3✔
295
            dump_expr(value);
3✔
296
            break;
3✔
297
         case A_RANGE:
×
298
            dump_range(tree_range(a, 0));
×
299
            print_syntax(" => ");
×
300
            dump_expr(value);
×
301
            break;
×
302
         default:
303
            assert(false);
×
304
         }
305
      }
306
      print_syntax(")");
3✔
307
      break;
3✔
308

309
   case T_REF:
37✔
310
      if (tree_has_ref(t)) {
37✔
311
         tree_t decl = tree_ref(t);
37✔
312
         dump_address(decl);
37✔
313
         print_syntax("%s", istr(tree_ident(decl)));
37✔
314
      }
315
      else
316
         print_syntax("%s", istr(tree_ident(t)));
×
317
      break;
318

319
   case T_ATTR_REF:
1✔
320
      dump_expr(tree_name(t));
1✔
321
      print_syntax("'%s", istr(tree_ident(t)));
1✔
322
      if (tree_params(t) > 0)
1✔
323
         dump_params(t, tree_param, tree_params(t), NULL);
×
324
      break;
325

326
   case T_EXTERNAL_NAME:
1✔
327
      dump_external_name(t);
1✔
328
      break;
1✔
329

330
   case T_ARRAY_REF:
1✔
331
      dump_expr(tree_value(t));
1✔
332
      dump_params(t, tree_param, tree_params(t), NULL);
1✔
333
      break;
1✔
334

335
   case T_ARRAY_SLICE:
×
336
      dump_expr(tree_value(t));
×
337
      print_syntax("(");
×
338
      dump_range(tree_range(t, 0));
×
339
      print_syntax(")");
×
340
      break;
×
341

342
   case T_RECORD_REF:
×
343
      dump_expr(tree_value(t));
×
344
      print_syntax(".%s", istr(tree_ident(t)));
×
345
      break;
×
346

347
   case T_TYPE_CONV:
4✔
348
      dump_type(tree_type(t));
4✔
349
      print_syntax("(");
4✔
350
      dump_expr(tree_value(t));
4✔
351
      print_syntax(")");
4✔
352
      break;
4✔
353

UNCOV
354
   case T_QUALIFIED:
×
355
      if (tree_has_value(t)) {
×
356
         print_syntax("%s'(", istr(type_ident(tree_type(t))));
×
357
         dump_expr(tree_value(t));
×
358
         print_syntax(")");
×
359
      }
360
      else
UNCOV
361
         dump_type(tree_type(t));
×
362
      break;
363

364
   case T_OPEN:
1✔
365
      print_syntax("#open");
1✔
366
      break;
1✔
367

368
   case T_BOX:
78✔
369
      print_syntax("<>");
78✔
370
      break;
78✔
371

UNCOV
372
   case T_WAVEFORM:
×
373
      dump_waveform(t);
×
374
      break;
×
375

UNCOV
376
   case T_PACKAGE_MAP:
×
377
      print_syntax("%s ", istr(tree_ident(t)));
×
378
      switch (tree_subkind(t)) {
×
379
      case PACKAGE_MAP_BOX:
×
380
         print_syntax("#generic #map (<>)");
×
381
         break;
×
382
      case PACKAGE_MAP_DEFAULT:
×
383
         print_syntax("#generic map (#default)");
×
384
         break;
×
385
      case PACKAGE_MAP_MATCHING:
×
386
         dump_params(t, tree_genmap, tree_genmaps(t), "#generic #map");
×
387
         break;
×
388
      }
389
      break;
390

391
   case T_COND_VALUE:
UNCOV
392
      for (int i = 0; i < tree_conds(t); i++) {
×
393
         tree_t c = tree_cond(t, i);
×
394
         if (i > 0)
×
395
            print_syntax(" #else ");
×
396
         if (tree_has_result(c))
×
397
            dump_expr(tree_result(c));
×
398
         else
UNCOV
399
            print_syntax("#unaffected");
×
400
         if (tree_has_value(c)) {
×
401
            print_syntax(" #when ");
×
402
            dump_expr(tree_value(c));
×
403
         }
404
      }
405
      break;
406

UNCOV
407
   default:
×
408
      cannot_dump(t, "expr");
×
409
   }
410

411
   dump_type_hint(t);
167✔
412
}
167✔
413

UNCOV
414
static void dump_record_elem_constraint(tree_t t)
×
415
{
UNCOV
416
   print_syntax("%s", istr(tree_ident(t)));
×
417

UNCOV
418
   type_t ftype = tree_type(t);
×
419
   const int ncon = type_constraints(ftype);
×
420
   for (int i = 0; i < ncon; i++)
×
421
      dump_constraint(type_constraint(ftype, i));
×
422

UNCOV
423
   dump_elem_constraints(ftype);
×
424
}
×
425

426
static void dump_constraint(tree_t t)
5✔
427
{
428
   const int nranges = tree_ranges(t);
5✔
429

430
   switch (tree_subkind(t)) {
5✔
431
   case C_RANGE:
1✔
432
      print_syntax(" #range ");
1✔
433
      dump_range(tree_range(t, 0));
1✔
434
      break;
1✔
435
   case C_INDEX:
4✔
436
      print_syntax("(");
4✔
437
      for (int i = 0; i < nranges; i++) {
8✔
438
         if (i > 0) print_syntax(", ");
4✔
439
         dump_range(tree_range(t, i));
4✔
440
      }
441
      print_syntax(")");
4✔
442
      break;
4✔
UNCOV
443
   case C_OPEN:
×
444
      print_syntax("(#open)");
×
445
      break;
×
446
   case C_RECORD:
×
447
      print_syntax("(");
×
448
      for (int i = 0; i < nranges; i++) {
×
449
         if (i > 0) print_syntax(", ");
×
450
         dump_record_elem_constraint(tree_range(t, i));
×
451
      }
UNCOV
452
      print_syntax(")");
×
453
      break;
×
454
   }
455
}
5✔
456

457
static void dump_elem_constraints(type_t type)
5✔
458
{
459
   if (type_is_array(type) && type_has_elem(type)) {
5✔
UNCOV
460
      type_t elem = type_elem(type);
×
461
      if (type_kind(elem) == T_SUBTYPE && !type_has_ident(elem)) {
×
462
         // Anonymous subtype created for element constraints
UNCOV
463
         assert(type_constraints(elem) == 1);
×
464
         dump_constraint(type_constraint(elem, 0));
×
465
         dump_elem_constraints(elem);
×
466
      }
467
   }
468
}
5✔
469

470
static void dump_type(type_t type)
117✔
471
{
472
   if (type_kind(type) == T_SUBTYPE && !type_has_ident(type)) {
117✔
473
      // Anonymous subtype
474
      print_syntax("%s", type_pp(type));
4✔
475
      if (type_ident(type) == type_ident(type_base(type))) {
4✔
476
         const int ncon = type_constraints(type);
4✔
477
         for (int i = 0; i < ncon; i++)
8✔
478
            dump_constraint(type_constraint(type, i));
4✔
479
      }
480
      dump_elem_constraints(type);
4✔
481
   }
482
   else if (type_is_none(type))
113✔
UNCOV
483
      print_syntax("/* error */");
×
484
   else
485
      print_syntax("%s", type_pp(type));
113✔
486
}
117✔
487

488
static void dump_arguments(tree_t t, int indent, const char *trailer)
6✔
489
{
490
   const int nports = tree_ports(t);
6✔
491
   if (nports > 0) {
6✔
492
      print_syntax(" (");
3✔
493
      if (nports > 1) {
3✔
494
         print_syntax("\n");
1✔
495
         for (int i = 0; i < nports; i++) {
3✔
496
            if (i > 0) print_syntax(";\n");
2✔
497
            dump_port(tree_port(t, i), indent + 4);
2✔
498
         }
499
      }
500
      else
501
         dump_port(tree_port(t, 0), 1);
2✔
502
      print_syntax(" )%s", trailer);
3✔
503
   }
504
}
6✔
505

506
static void dump_ports(tree_t t, int indent)
4✔
507
{
508
   const int nports = tree_ports(t);
4✔
509
   if (nports > 0) {
4✔
510
      tab(indent);
2✔
511
      print_syntax("#port (");
2✔
512
      if (nports > 1) {
2✔
513
         print_syntax("\n");
2✔
514
         for (unsigned i = 0; i < nports; i++) {
6✔
515
            if (i > 0) print_syntax(";\n");
4✔
516
            dump_port(tree_port(t, i), indent + 2);
4✔
517
         }
518
      }
519
      else
UNCOV
520
         dump_port(tree_port(t, 0), 1);
×
521
      print_syntax(" );\n");
2✔
522
   }
523
}
4✔
524

525
static void dump_generics(tree_t t, int indent, const char *trailer)
11✔
526
{
527
   const int ngenerics = tree_generics(t);
11✔
528
   if (ngenerics > 0) {
11✔
529
      tab(indent);
3✔
530
      print_syntax("#generic (");
3✔
531
      if (ngenerics > 1) {
3✔
532
         print_syntax("\n");
2✔
533
         for (int i = 0; i < ngenerics; i++) {
93✔
534
            tree_t g = tree_generic(t, i);
91✔
535
            dump_port(g, indent + 2);
91✔
536
            if (i + 1 == ngenerics && (tree_flags(g) & TREE_F_PREDEFINED)) {
91✔
537
               print_syntax(";\n");
2✔
538
               tab(indent - 1);
2✔
539
            }
540
            else if (i + 1 < ngenerics)
89✔
541
               print_syntax(";\n");
89✔
542
         }
543
      }
544
      else
545
         dump_port(tree_generic(t, 0), 1);
1✔
546
      print_syntax(" )%s", trailer);
3✔
547
   }
548
}
11✔
549

550
static void dump_port_map(tree_t t, int indent, const char *trailer)
2✔
551
{
552
   const int nparams = tree_params(t);
2✔
553
   if (nparams > 0) {
2✔
554
      tab(indent);
1✔
555
      dump_params(t, tree_param, nparams, "#port #map");
1✔
556
      print_syntax("%s", trailer);
1✔
557
   }
558
}
2✔
559

560
static void dump_generic_map(tree_t t, int indent, const char *trailer)
3✔
561
{
562
   const int ngenmaps = tree_genmaps(t);
3✔
563
   if (ngenmaps > 0) {
3✔
564
      tab(indent);
1✔
565
      dump_params(t, tree_genmap, ngenmaps, "#generic #map");
1✔
566
      print_syntax("%s", trailer);
1✔
567
   }
568
}
3✔
569

UNCOV
570
static void dump_binding(tree_t t, int indent)
×
571
{
UNCOV
572
   print_syntax("#use %s", istr(tree_ident(t)));
×
573
   if (tree_has_ident2(t))
×
574
      print_syntax("(%s)", istr(tree_ident2(t)));
×
575
   if (tree_genmaps(t) > 0 || tree_params(t) > 0)
×
576
      print_syntax("\n");
×
577
   dump_generic_map(t, indent + 2, tree_params(t) > 0 ? "\n" : "");
×
578
   dump_port_map(t, indent + 2, "");
×
579
   print_syntax(";\n");
×
580
}
×
581

582
static void dump_stmts(tree_t t, int indent)
10✔
583
{
584
   const int nstmts = tree_stmts(t);
10✔
585
   for (int i = 0; i < nstmts; i++) {
19✔
586
      tree_t s = tree_stmt(t, i);
9✔
587
      const tree_kind_t kind = tree_kind(s);
9✔
588
      const bool needs_newline =
18✔
589
         kind == T_BLOCK || kind == T_PROCESS || kind == T_INSTANCE;
9✔
590
      if (needs_newline && i > 0)
9✔
UNCOV
591
         print_syntax("\n");
×
592
      dump_stmt(s, indent);
9✔
593
   }
594
}
10✔
595

596
static void dump_block(tree_t t, int indent)
5✔
597
{
598
   dump_decls(t, indent + 2);
5✔
599
   tab(indent);
5✔
600
   print_syntax("#begin\n");
5✔
601
   dump_stmts(t, indent + 2);
5✔
602
}
5✔
603

604
static void dump_wait_level(tree_t t)
2✔
605
{
606
   const tree_flags_t flags = tree_flags(t);
2✔
607
   if (flags & TREE_F_NEVER_WAITS)
2✔
608
      print_syntax("   -- Never waits");
2✔
UNCOV
609
   else if (flags & TREE_F_HAS_WAIT)
×
610
      print_syntax("   -- Contains wait statement");
×
611
}
2✔
612

613
static void dump_type_decl(tree_t t, int indent)
2✔
614
{
615
   type_t type = tree_type(t);
2✔
616
   const type_kind_t kind = type_kind(type);
2✔
617

618
   print_syntax("#type %s", istr(tree_ident(t)));
2✔
619

620
   if (kind == T_INCOMPLETE) {
2✔
UNCOV
621
      print_syntax(";\n");
×
622
      return;
×
623
   }
624

625
   print_syntax(" #is ");
2✔
626

627
   if (type_is_integer(type) || type_is_real(type)) {
2✔
UNCOV
628
      print_syntax("#range ");
×
629
      dump_range(type_dim(type, 0));
×
630
   }
631
   else if (type_is_physical(type)) {
2✔
UNCOV
632
      print_syntax("#range ");
×
633
      dump_range(type_dim(type, 0));
×
634
      print_syntax("\n");
×
635
      tab(indent + 2);
×
636
      print_syntax("#units\n");
×
637
      {
UNCOV
638
         const int nunits = type_units(type);
×
639
         for (int i = 0; i < nunits; i++) {
×
640
            tree_t u = type_unit(type, i);
×
641
            tab(indent + 4);
×
642
            print_syntax("%s = ", istr(tree_ident(u)));
×
643
            dump_expr(tree_value(u));
×
644
            print_syntax(";\n");
×
645
         }
646
      }
UNCOV
647
      tab(indent + 2);
×
648
      print_syntax("#end #units");
×
649
   }
650
   else if (type_is_array(type)) {
2✔
651
      print_syntax("#array ");
1✔
652
      if (kind == T_ARRAY) {
1✔
653
         print_syntax("(");
1✔
654
         const int nindex = type_indexes(type);
1✔
655
         for (int i = 0; i < nindex; i++) {
2✔
656
            if (i > 0) print_syntax(", ");
1✔
657
            dump_type(type_index(type, i));
1✔
658
            print_syntax(" #range <>");
1✔
659
         }
660
         print_syntax(")");
1✔
661
      }
UNCOV
662
      else if (kind == T_SUBTYPE) {
×
663
         const int ncon = type_constraints(type);
×
664
         for (int i = 0; i < ncon; i++)
×
665
            dump_constraint(type_constraint(type, i));
×
666
      }
667
      else {
UNCOV
668
         print_syntax("(");
×
669
         const int ndims = type_dims(type);
×
670
         for (int i = 0; i < ndims; i++) {
×
671
            if (i > 0) print_syntax(", ");
×
672
            dump_range(type_dim(type, i));
×
673
         }
UNCOV
674
         print_syntax(")");
×
675
      }
676
      print_syntax(" #of ");
1✔
677
      dump_type(type_elem(type));
1✔
678
   }
679
   else if (type_is_record(type)) {
1✔
680
      print_syntax("#record\n");
1✔
681
      const int nfields = type_fields(type);
1✔
682
      for (int i = 0; i < nfields; i++)
3✔
683
         dump_decl(type_field(type, i), indent + 2);
2✔
684
      tab(indent);
1✔
685
      print_syntax("#end #record");
1✔
686
   }
UNCOV
687
   else if (kind == T_ENUM) {
×
688
      print_syntax("(");
×
689
      for (unsigned i = 0; i < type_enum_literals(type); i++) {
×
690
         if (i > 0) print_syntax(", ");
×
691
         print_syntax("%s", istr(tree_ident(type_enum_literal(type, i))));
×
692
      }
UNCOV
693
      print_syntax(")");
×
694
   }
UNCOV
695
   else if (kind == T_INCOMPLETE)
×
696
      ;
697
   else
UNCOV
698
      dump_type(type);
×
699

700
   print_syntax(";\n");
2✔
701
}
702

703
static void dump_subtype_decl(tree_t t, int indent)
704
{
705
   type_t type = tree_type(t);
706

707
   print_syntax("#subtype %s #is ", istr(tree_ident(t)));
708
   if (type_has_resolution(type)) {
709
      dump_expr(type_resolution(type));
710
      print_syntax(" ");
711
   }
712
   print_syntax("%s", type_pp(type_base(type)));
713

714
   const int ncon = type_constraints(type);
715
   for (int i = 0; i < ncon; i++)
716
      dump_constraint(type_constraint(type, i));
717

718
   dump_elem_constraints(type);
719

720
   print_syntax(";\n");
721
}
722

723
static void dump_component(tree_t t, int indent)
1✔
724
{
725
   print_syntax("#component %s #is\n", istr(tree_ident(t)));
1✔
726
   dump_generics(t, indent + 2, ";\n");
1✔
727
   dump_ports(t, indent + 2);
1✔
728
   print_syntax("#end #component;\n");
1✔
729
}
1✔
730

731
static void dump_use(tree_t t)
6✔
732
{
733
   print_syntax("#use %s", istr(tree_ident(t)));
6✔
734
   if (tree_has_ident2(t))
6✔
735
      print_syntax(".%s", istr(tree_ident2(t)));
6✔
736
   print_syntax(";\n");
6✔
737
}
6✔
738

739
static void dump_decl(tree_t t, int indent)
26✔
740
{
741
   tab(indent);
26✔
742
   if (tree_kind(t) != T_HIER) dump_address(t);
26✔
743

744
   switch (tree_kind(t)) {
26✔
UNCOV
745
   case T_IMPLICIT_SIGNAL:
×
746
      print_syntax("/* implicit */ ");
×
747
      // Fall-through
748
   case T_SIGNAL_DECL:
3✔
749
      print_syntax("#signal %s : ", istr(tree_ident(t)));
3✔
750
      break;
3✔
751

752
   case T_VAR_DECL:
3✔
753
      print_syntax("#variable %s : ", istr(tree_ident(t)));
3✔
754
      break;
3✔
755

756
   case T_CONST_DECL:
3✔
757
      print_syntax("#constant %s : ", istr(tree_ident(t)));
3✔
758
      break;
3✔
759

760
   case T_GENERIC_DECL:
1✔
761
      // Loop variable in for-generate statement
762
      print_syntax("/* loop variable */ %s : ", istr(tree_ident(t)));
1✔
763
      break;
1✔
764

765
   case T_FIELD_DECL:
2✔
766
      print_syntax("%s : ", istr(tree_ident(t)));
2✔
767
      break;
2✔
768

769
   case T_TYPE_DECL:
2✔
770
      dump_type_decl(t, indent);
2✔
771
      return;
2✔
772

773
   case T_SUBTYPE_DECL:
1✔
774
      dump_subtype_decl(t, indent);
1✔
775
      return;
1✔
776

UNCOV
777
   case T_SPEC:
×
778
      print_syntax("#for %s", istr(tree_ident(t)));
×
779
      if (tree_has_ref(t))
×
780
         print_syntax(" : %s", istr(tree_ident(tree_ref(t))));
×
781
      print_syntax("\n");
×
782
      tab(indent + 2);
×
783
      dump_binding(tree_value(t), indent + 2);
×
784
      dump_decls(t, indent + 2);
×
785
      tab(indent);
×
786
      print_syntax("#end #for;\n");
×
787
      return;
×
788

UNCOV
789
   case T_BLOCK_CONFIG:
×
790
      print_syntax("#for %s\n", istr(tree_ident(t)));
×
791
      dump_decls(t, indent + 2);
×
792
      tab(indent);
×
793
      print_syntax("#end #for;\n");
×
794
      return;
×
795

UNCOV
796
   case T_ENUM_LIT:
×
797
      print_syntax("%s", istr(tree_ident(t)));
×
798
      return;
×
799

UNCOV
800
   case T_ALIAS:
×
801
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
802
         print_syntax("-- predefined ");
×
803
      print_syntax("#alias %s", istr(tree_ident(t)));
×
804
      if (tree_has_type(t)) {
×
805
         print_syntax(" : ");
×
806
         dump_type(tree_type(t));
×
807
      }
UNCOV
808
      print_syntax(" #is ");
×
809
      dump_expr(tree_value(t));
×
810
      print_syntax(";\n");
×
811
      return;
×
812

813
   case T_ATTR_SPEC:
1✔
814
      print_syntax("#attribute %s #of %s : #%s #is ", istr(tree_ident(t)),
1✔
815
             istr(tree_ident2(t)), class_str(tree_class(t)));
816
      dump_expr(tree_value(t));
1✔
817
      print_syntax(";\n");
1✔
818
      return;
1✔
819

820
   case T_ATTR_DECL:
1✔
821
      print_syntax("#attribute %s : ", istr(tree_ident(t)));
1✔
822
      dump_type(tree_type(t));
1✔
823
      print_syntax(";\n");
1✔
824
      return;
1✔
825

826
   case T_FUNC_DECL:
2✔
827
      if (tree_flags(t) & TREE_F_PREDEFINED)
2✔
UNCOV
828
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
829
      else {
830
         print_syntax("#function %s", istr(tree_ident(t)));
2✔
831
         dump_generics(t, indent + 2, "");
2✔
832
         dump_arguments(t, indent, "");
2✔
833
         print_syntax(" #return ");
2✔
834
         dump_type(type_result(tree_type(t)));
2✔
835
         print_syntax(";\n");
2✔
836
         if (tree_has_ident2(t)) {
2✔
837
            tab(indent + 2);
2✔
838
            print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
839
         }
840
      }
841
      return;
842

843
   case T_FUNC_INST:
2✔
844
   case T_FUNC_BODY:
845
      print_syntax("#function %s", istr(tree_ident(t)));
2✔
846
      dump_type_hint(t);
2✔
847
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
848
      if (tree_kind(t) == T_FUNC_INST)
2✔
UNCOV
849
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
850
      dump_arguments(t, indent, "");
2✔
851
      print_syntax(" #return ");
2✔
852
      dump_type(type_result(tree_type(t)));
2✔
853
      print_syntax(" #is\n");
2✔
854
      if (tree_has_ident2(t)) {
2✔
855
         tab(indent + 2);
2✔
856
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
857
      }
858
      dump_block(t, indent);
2✔
859
      tab(indent);
2✔
860
      print_syntax("#end #function;\n");
2✔
861
      return;
2✔
862

UNCOV
863
   case T_PROC_DECL:
×
864
      if (tree_flags(t) & TREE_F_PREDEFINED)
×
865
         print_syntax("-- predefined %s\n", type_pp(tree_type(t)));
×
866
      else {
UNCOV
867
         print_syntax("#procedure %s", istr(tree_ident(t)));
×
868
         dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
869
         dump_arguments(t, indent, "");
×
870
         print_syntax(";");
×
871
         dump_wait_level(t);
×
872
         print_syntax("\n");
×
873
         if (tree_has_ident2(t)) {
×
874
            tab(indent + 2);
×
875
            print_syntax("-- %s\n", istr(tree_ident2(t)));
×
876
         }
877
      }
878
      return;
879

880
   case T_PROC_INST:
2✔
881
   case T_PROC_BODY:
882
      print_syntax("#procedure %s", istr(tree_ident(t)));
2✔
883
      dump_type_hint(t);
2✔
884
      dump_generics(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
3✔
885
      if (tree_kind(t) == T_PROC_INST)
2✔
UNCOV
886
         dump_generic_map(t, indent + 2, tree_ports(t) > 0 ? "\n" : "");
×
887
      dump_arguments(t, indent, "");
2✔
888
      print_syntax(" #is");
2✔
889
      dump_wait_level(t);
2✔
890
      print_syntax("\n");
2✔
891
      if (tree_has_ident2(t)) {
2✔
892
         tab(indent + 2);
2✔
893
         print_syntax("-- %s\n", istr(tree_ident2(t)));
2✔
894
      }
895
      dump_block(t, indent);
2✔
896
      tab(indent);
2✔
897
      print_syntax("#end #procedure;\n");
2✔
898
      return;
2✔
899

UNCOV
900
   case T_HIER:
×
901
      {
UNCOV
902
         const char *kind = "Scope";
×
903
         switch (tree_subkind(t)) {
×
904
         case T_ARCH: kind = "Instance"; break;
×
905
         case T_IF_GENERATE: kind = "If generate"; break;
×
906
         case T_FOR_GENERATE: kind = "For generate"; break;
×
907
         case T_BLOCK: kind = "Block"; break;
×
908
         }
UNCOV
909
         print_syntax("-- %s %s\n", kind, istr(tree_ident2(t)));
×
910
      }
UNCOV
911
      return;
×
912

913
   case T_COMPONENT:
1✔
914
      dump_component(t, indent);
1✔
915
      return;
1✔
916

917
   case T_PROT_DECL:
1✔
918
      print_syntax("#type %s #is #protected\n", istr(tree_ident(t)));
1✔
919
      dump_decls(t, indent + 2);
1✔
920
      tab(indent);
1✔
921
      print_syntax("#end #protected;\n");
1✔
922
      return;
1✔
923

924
   case T_PROT_BODY:
1✔
925
      print_syntax("#type %s #is #protected #body\n", istr(tree_ident(t)));
1✔
926
      dump_decls(t, indent + 2);
1✔
927
      tab(indent);
1✔
928
      print_syntax("#end #protected #body;\n");
1✔
929
      return;
1✔
930

UNCOV
931
   case T_FILE_DECL:
×
932
      print_syntax("#file %s : ", istr(tree_ident(t)));
×
933
      dump_type(tree_type(t));
×
934
      if (tree_has_value(t)) {
×
935
         print_syntax(" #open ");
×
936
         dump_expr(tree_file_mode(t));
×
937
         print_syntax(" #is ");
×
938
         dump_expr(tree_value(t));
×
939
      }
UNCOV
940
      print_syntax(";\n");
×
941
      return;
×
942

UNCOV
943
   case T_USE:
×
944
      dump_use(t);
×
945
      return;
×
946

UNCOV
947
   case T_PACKAGE:
×
948
   case T_PACK_INST:
UNCOV
949
      dump_package(t, indent);
×
950
      return;
×
951

UNCOV
952
   case T_PACK_BODY:
×
953
      dump_package_body(t, indent);
×
954
      return;
×
955

UNCOV
956
   default:
×
957
      cannot_dump(t, "decl");
×
958
   }
959

960
   dump_type(tree_type(t));
12✔
961

962
   if (tree_kind(t) != T_FIELD_DECL && tree_has_value(t)) {
12✔
963
      print_syntax(" := ");
6✔
964
      dump_expr(tree_value(t));
6✔
965
   }
966
   print_syntax(";\n");
12✔
967
}
968

969
static void dump_waveforms(tree_t t)
2✔
970
{
971
   const int nwaves = tree_waveforms(t);
2✔
972
   for (int i = 0; i < nwaves; i++) {
5✔
973
      if (i > 0) print_syntax(", ");
3✔
974
      dump_waveform(tree_waveform(t, i));
3✔
975
   }
976
}
2✔
977

UNCOV
978
static void dump_alternative(tree_t t, int indent)
×
979
{
UNCOV
980
   tab(indent);
×
981
   print_syntax("#when ");
×
982
   if (tree_has_ident(t))
×
983
      print_syntax("%s: ", istr(tree_ident(t)));
×
984
   for (unsigned i = 0; i < tree_assocs(t); i++) {
×
985
      if (i > 0) print_syntax("| ");
×
986
      tree_t a = tree_assoc(t, i);
×
987
      switch (tree_subkind(a)) {
×
988
      case A_NAMED:
×
989
         dump_expr(tree_name(a));
×
990
         break;
×
991
      case A_OTHERS:
×
992
         print_syntax("#others");
×
993
         break;
×
994
      case A_RANGE:
×
995
         dump_range(tree_range(a, 0));
×
996
         break;
×
997
      }
UNCOV
998
   }
×
999
   print_syntax(" =>\n");
×
1000
   if (tree_decls(t) > 0) {
×
1001
      dump_decls(t, indent + 4);
×
1002
      tab(indent + 2);
×
1003
      print_syntax("#begin\n");
×
1004
      dump_stmts(t, indent + 4);
×
1005
      tab(indent + 2);
×
1006
      print_syntax("#end;\n");
×
1007
   }
1008
   else
UNCOV
1009
      dump_stmts(t, indent + 2);
×
1010
}
×
1011

1012
static void dump_psl(tree_t t, int indent)
1013
{
1014
   if (standard() < STD_08)
1015
      print_syntax("-- psl ");
1016
   psl_dump(tree_psl(t));
1017
}
1018

1019
static void dump_instance(tree_t t, int indent)
1✔
1020
{
1021
   switch (tree_class(t)) {
1✔
UNCOV
1022
   case C_ENTITY:        print_syntax("#entity "); break;
×
1023
   case C_COMPONENT:     print_syntax("#component "); break;
1✔
UNCOV
1024
   case C_CONFIGURATION: print_syntax("#configuration "); break;
×
1025
   default: break;
1026
   }
1027

1028
   print_syntax("%s", istr(tree_ident2(t)));
1✔
1029

1030
   const int nparams = tree_params(t);
1✔
1031
   const int ngenmaps = tree_genmaps(t);
1✔
1032

1033
   if (tree_has_spec(t)) {
1✔
UNCOV
1034
      tree_t spec = tree_spec(t);
×
1035
      if (tree_has_value(spec)) {
×
1036
         tree_t bind = tree_value(spec);
×
1037
         LOCAL_TEXT_BUF tb = tb_new();
×
1038
         tb_cat(tb, istr(tree_ident(bind)));
×
1039
         if (tree_has_ident2(bind))
×
1040
            tb_printf(tb, "(%s)", istr(tree_ident2(bind)));
×
1041
         print_syntax("  -- bound to %s\n", tb_get(tb));
×
1042
      }
1043
   }
1044
   else if (nparams > 0 || ngenmaps > 0)
1✔
1045
      print_syntax("\n");
1✔
1046

1047
   dump_generic_map(t, indent + 2, nparams > 0 ? "\n" : "");
1✔
1048
   dump_port_map(t, indent + 2, "");
1✔
1049
   print_syntax(";\n");
1✔
1050
}
1✔
1051

1052
static void dump_stmt(tree_t t, int indent)
13✔
1053
{
1054
   tab(indent);
15✔
1055

1056
   if (tree_has_ident(t)) {
15✔
1057
      const char *label = istr(tree_ident(t));
6✔
1058
#if !DUMP_GEN_NAMES
1059
      if (label[0] != '_')   // Skip generated labels
6✔
1060
#endif
1061
         print_syntax("%s: ", label);
4✔
1062
   }
1063

1064
   switch (tree_kind(t)) {
15✔
1065
   case T_PROCESS:
1✔
1066
      dump_address(t);
1✔
1067
      if (tree_flags(t) & TREE_F_POSTPONED)
1✔
UNCOV
1068
         print_syntax("#postponed ");
×
1069
      print_syntax("#process ");
1✔
1070
      if (tree_triggers(t) > 0) {
1✔
1071
         print_syntax("(");
1✔
1072
         for (unsigned i = 0; i < tree_triggers(t); i++) {
2✔
1073
            if (i > 0)
1✔
UNCOV
1074
               print_syntax(", ");
×
1075
            dump_expr(tree_trigger(t, i));
1✔
1076
         }
1077
         print_syntax(") ");
1✔
1078
      }
1079
      print_syntax("#is\n");
1✔
1080
      dump_decls(t, indent + 2);
1✔
1081
      tab(indent);
1✔
1082
      print_syntax("#begin\n");
1✔
1083
      dump_stmts(t, indent + 2);
1✔
1084
      tab(indent);
1✔
1085
      print_syntax("#end #process;\n");
1✔
1086
      return;
1✔
1087

1088
   case T_SIGNAL_ASSIGN:
1✔
1089
      dump_expr(tree_target(t));
1✔
1090
      print_syntax(" <= #reject ");
1✔
1091
      if (tree_has_reject(t))
1✔
1092
         dump_expr(tree_reject(t));
1✔
1093
      else
UNCOV
1094
         print_syntax("0 ps");
×
1095
      print_syntax(" #inertial ");
1✔
1096
      dump_waveforms(t);
1✔
1097
      break;
1✔
1098

UNCOV
1099
   case T_FORCE:
×
1100
      dump_expr(tree_target(t));
×
1101
      print_syntax(" <= #force ");
×
1102
      dump_expr(tree_value(t));
×
1103
      break;
×
1104

UNCOV
1105
   case T_RELEASE:
×
1106
      dump_expr(tree_target(t));
×
1107
      print_syntax(" <= #release");
×
1108
      break;
×
1109

1110
   case T_VAR_ASSIGN:
2✔
1111
      dump_expr(tree_target(t));
2✔
1112
      print_syntax(" := ");
2✔
1113
      dump_expr(tree_value(t));
2✔
1114
      break;
2✔
1115

UNCOV
1116
   case T_WAIT:
×
1117
      print_syntax("#wait");
×
1118
      if (tree_triggers(t) > 0) {
×
1119
         print_syntax(" #on ");
×
1120
         for (unsigned i = 0; i < tree_triggers(t); i++) {
×
1121
            if (i > 0)
×
1122
               print_syntax(", ");
×
1123
            dump_expr(tree_trigger(t, i));
×
1124
         }
1125
      }
UNCOV
1126
      if (tree_has_value(t)) {
×
1127
         print_syntax(" #until ");
×
1128
         dump_expr(tree_value(t));
×
1129
      }
UNCOV
1130
      if (tree_has_delay(t)) {
×
1131
         print_syntax(" #for ");
×
1132
         dump_expr(tree_delay(t));
×
1133
      }
UNCOV
1134
      print_syntax(";");
×
1135
      if (tree_flags(t) & TREE_F_STATIC_WAIT)
×
1136
         print_syntax("   -- static");
×
1137
      print_syntax("\n");
×
1138
      return;
×
1139

1140
   case T_BLOCK:
1✔
1141
      dump_address(t);
1✔
1142
      print_syntax("#block #is\n");
1✔
1143
      dump_generics(t, indent + 2, ";\n");
1✔
1144
      dump_generic_map(t, indent + 2, ";\n");
1✔
1145
      dump_ports(t, indent + 2);
1✔
1146
      dump_port_map(t, indent + 2, ";\n");
1✔
1147
      dump_block(t, indent);
1✔
1148
      tab(indent);
1✔
1149
      print_syntax("#end #block;\n");
1✔
1150
      return;
1✔
1151

UNCOV
1152
   case T_SEQUENCE:
×
1153
      print_syntax("#block #is\n");
×
1154
      dump_block(t, indent);
×
1155
      tab(indent);
×
1156
      print_syntax("#end #block;\n");
×
1157
      return;
×
1158

1159
   case T_ASSERT:
1✔
1160
      if (tree_has_value(t)) {
1✔
1161
         print_syntax("#assert ");
1✔
1162
         dump_expr(tree_value(t));
1✔
1163
         print_syntax(" ");
1✔
1164
      }
1165
      if (tree_has_message(t)) {
1✔
UNCOV
1166
         print_syntax("#report ");
×
1167
         dump_expr(tree_message(t));
×
1168
         print_syntax(" ");
×
1169
      }
1170
      print_syntax("#severity ");
1✔
1171
      dump_expr(tree_severity(t));
1✔
1172
      break;
1✔
1173

UNCOV
1174
   case T_WHILE:
×
1175
      if (tree_has_value(t)) {
×
1176
         print_syntax("#while ");
×
1177
         dump_expr(tree_value(t));
×
1178
         print_syntax(" ");
×
1179
      }
UNCOV
1180
      print_syntax("#loop\n");
×
1181
      dump_stmts(t, indent + 2);
×
1182
      tab(indent);
×
1183
      print_syntax("#end #loop");
×
1184
      break;
×
1185

1186
   case T_IF:
1187
      for (unsigned i = 0; i < tree_conds(t); i++) {
3✔
1188
         tree_t c = tree_cond(t, i);
2✔
1189
         if (tree_has_value(c)) {
2✔
1190
            if (i > 0)
1✔
UNCOV
1191
               tab(indent);
×
1192
            print_syntax(i > 0 ? "#elsif " : "#if ");
2✔
1193
            dump_expr(tree_value(c));
1✔
1194
            print_syntax(" #then\n");
1✔
1195
         }
1196
         else {
1197
            tab(indent);
1✔
1198
            print_syntax("#else\n");
1✔
1199
         }
1200
         dump_stmts(c, indent + 2);
2✔
1201
      }
1202
      tab(indent);
1✔
1203
      print_syntax("#end #if");
1✔
1204
      break;
1✔
1205

UNCOV
1206
   case T_EXIT:
×
1207
      print_syntax("#exit %s", istr(tree_ident2(t)));
×
1208
      if (tree_has_value(t)) {
×
1209
         print_syntax(" #when ");
×
1210
         dump_expr(tree_value(t));
×
1211
      }
1212
      break;
1213

UNCOV
1214
   case T_CASE:
×
1215
   case T_MATCH_CASE:
1216
      {
UNCOV
1217
         const char *suffix = tree_kind(t) == T_MATCH_CASE ? "?" : "";
×
1218
         print_syntax("#case%s ", suffix);
×
1219
         dump_expr(tree_value(t));
×
1220
         print_syntax(" #is\n");
×
1221
         const int nstmts = tree_stmts(t);
×
1222
         for (int i = 0; i < nstmts; i++)
×
1223
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1224
         tab(indent);
×
1225
         print_syntax("#end #case%s", suffix);
×
1226
      }
UNCOV
1227
      break;
×
1228

1229
   case T_RETURN:
3✔
1230
      print_syntax("#return");
3✔
1231
      if (tree_has_value(t)) {
3✔
1232
         print_syntax(" ");
3✔
1233
         dump_expr(tree_value(t));
3✔
1234
      }
1235
      break;
1236

UNCOV
1237
   case T_COND_RETURN:
×
1238
      print_syntax("#return #when ");
×
1239
      dump_expr(tree_value(t));
×
1240
      break;
×
1241

UNCOV
1242
   case T_FOR:
×
1243
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
×
1244
      dump_range(tree_range(t, 0));
×
1245
      print_syntax(" #loop\n");
×
1246
      dump_stmts(t, indent + 2);
×
1247
      tab(indent);
×
1248
      print_syntax("#end #for");
×
1249
      break;
×
1250

UNCOV
1251
   case T_PROT_PCALL:
×
1252
      dump_expr(tree_name(t));
×
1253
      print_syntax(".");
×
1254
      // Fall-through
UNCOV
1255
   case T_PCALL:
×
1256
      if (tree_has_ref(t)) {
×
1257
         tree_t decl = tree_ref(t);
×
1258
         dump_address(decl);
×
1259
         print_syntax("%s", istr(tree_ident(decl)));
×
1260
      }
1261
      else
UNCOV
1262
         print_syntax("%s", istr(tree_ident(t)));
×
1263
      dump_params(t, tree_param, tree_params(t), NULL);
×
1264
      break;
×
1265

1266
   case T_FOR_GENERATE:
1✔
1267
      print_syntax("#for %s #in ", istr(tree_ident(tree_decl(t, 0))));
1✔
1268
      dump_range(tree_range(t, 0));
1✔
1269
      print_syntax(" #generate\n");
1✔
1270
      dump_decls(t, indent + 2);
1✔
1271
      tab(indent);
1✔
1272
      print_syntax("#begin\n");
1✔
1273
      dump_stmts(t, indent + 2);
1✔
1274
      tab(indent);
1✔
1275
      print_syntax("#end #generate");
1✔
1276
      break;
1✔
1277

UNCOV
1278
   case T_CASE_GENERATE:
×
1279
      {
UNCOV
1280
         print_syntax("#case ");
×
1281
         dump_expr(tree_value(t));
×
1282
         print_syntax(" #generate\n");
×
1283

UNCOV
1284
         const int nstmts = tree_stmts(t);
×
1285
         for (int i = 0; i < nstmts; i++)
×
1286
            dump_alternative(tree_stmt(t, i), indent + 2);
×
1287

UNCOV
1288
         print_syntax("#end #generate");
×
1289
         tab(indent);
×
1290
      }
UNCOV
1291
      break;
×
1292

1293
   case T_IF_GENERATE:
UNCOV
1294
      for (unsigned i = 0; i < tree_conds(t); i++) {
×
1295
         tree_t c = tree_cond(t, i);
×
1296
         if (tree_has_value(c)) {
×
1297
            if (i > 0)
×
1298
               tab(indent);
×
1299
            print_syntax(i > 0 ? "#elsif " : "#if ");
×
1300
            dump_expr(tree_value(c));
×
1301
            print_syntax(" #generate\n");
×
1302
         }
1303
         else {
UNCOV
1304
            tab(indent);
×
1305
            print_syntax("#else\n");
×
1306
         }
UNCOV
1307
         for (unsigned i = 0; i < tree_stmts(c); i++)
×
1308
            dump_stmt(tree_stmt(c, i), indent + 2);
×
1309
      }
UNCOV
1310
      tab(indent);
×
1311
      print_syntax("#end #generate");
×
1312
      break;
×
1313

1314
   case T_INSTANCE:
1✔
1315
      dump_instance(t, indent);
1✔
1316
      return;
1✔
1317

UNCOV
1318
   case T_NEXT:
×
1319
      print_syntax("#next");
×
1320
      if (tree_has_value(t)) {
×
1321
         print_syntax(" #when ");
×
1322
         dump_expr(tree_value(t));
×
1323
      }
1324
      break;
1325

UNCOV
1326
   case T_NULL:
×
1327
      print_syntax("#null");
×
1328
      break;
×
1329

1330
   case T_COND_ASSIGN:
1✔
1331
      dump_expr(tree_target(t));
1✔
1332
      print_syntax(" <= ");
1✔
1333
      for (int i = 0; i < tree_conds(t); i++) {
2✔
1334
         tree_t c = tree_cond(t, i);
1✔
1335
         dump_waveforms(tree_stmt(c, 0));
1✔
1336
         if (tree_has_value(c)) {
1✔
UNCOV
1337
            print_syntax(" #when ");
×
1338
            dump_expr(tree_value(c));
×
1339
         }
1340
      }
1341
      break;
1342

UNCOV
1343
   case T_SELECT:
×
1344
      print_syntax(" <= ");
×
1345
      if (tree_has_guard(t)) print_syntax("#guarded ");
×
1346
      color_printf("$red$/* TODO: T_SELECT */$$");
×
1347
      break;
×
1348

1349
   case T_CONCURRENT:
2✔
1350
      if (tree_flags(t) & TREE_F_POSTPONED)
2✔
UNCOV
1351
         print_syntax("#postponed ");
×
1352
      if (tree_has_guard(t))
2✔
UNCOV
1353
         print_syntax("#guarded ");
×
1354
      dump_stmt(tree_stmt(t, 0), 0);
2✔
1355
      return;
2✔
1356

UNCOV
1357
   case T_PSL:
×
1358
      dump_psl(t, 0);
×
1359
      break;
×
1360

UNCOV
1361
   case T_VERILOG:
×
1362
      print_syntax("#block #is\n");
×
1363
      dump_generic_map(t, indent + 2, ";\n");
×
1364
      dump_port_map(t, indent + 2, ";\n");
×
1365
      tab(indent);
×
1366
      print_syntax("#begin\n");
×
1367
      vlog_dump(tree_vlog(t), indent + 2);
×
1368
      tab(indent);
×
1369
      print_syntax("#end #block");
×
1370
      break;
×
1371

UNCOV
1372
   default:
×
1373
      cannot_dump(t, "stmt");
×
1374
   }
1375

1376
   print_syntax(";\n");
10✔
1377
}
1378

1379
static void dump_port(tree_t t, int indent)
100✔
1380
{
1381
   tab(indent);
100✔
1382
   dump_address(t);
100✔
1383

1384
   if (tree_flags(t) & TREE_F_PREDEFINED)
100✔
1385
      print_syntax("-- predefined ");
80✔
1386

1387
   const class_t class = tree_class(t);
100✔
1388
   print_syntax("#%s %s", class_str(class), istr(tree_ident(t)));
100✔
1389

1390
   type_t type = get_type_or_null(t);
100✔
1391
   if (class == C_PACKAGE) {
100✔
UNCOV
1392
      print_syntax(" #is #new ");
×
1393
      dump_expr(tree_value(t));
×
1394
   }
1395
   else if (class == C_TYPE && type_kind(type) == T_GENERIC) {
100✔
1396
      print_syntax(" #is ");
10✔
1397

1398
      switch (type_subkind(type)) {
10✔
1399
      case GTYPE_PRIVATE:
2✔
1400
         print_syntax("#private");
2✔
1401
         break;
2✔
1402
      case GTYPE_SCALAR:
1✔
1403
         print_syntax("<>");
1✔
1404
         break;
1✔
1405
      case GTYPE_DISCRETE:
1✔
1406
         print_syntax("(<>)");
1✔
1407
         break;
1✔
1408
      case GTYPE_INTEGER:
1✔
1409
         print_syntax("#range <>");
1✔
1410
         break;
1✔
1411
      case GTYPE_PHYSICAL:
1✔
1412
         print_syntax("#units <>");
1✔
1413
         break;
1✔
1414
      case GTYPE_FLOATING:
1✔
1415
         print_syntax("#range <> . <>");
1✔
1416
         break;
1✔
1417
      case GTYPE_ARRAY:
1✔
1418
         {
1419
            print_syntax("#array (");
1✔
1420
            const int nindex = type_indexes(type);
1✔
1421
            for (int i = 0; i < nindex; i++) {
2✔
1422
               if (i > 0) print_syntax(", ");
1✔
1423
               dump_type(type_index(type, i));
1✔
1424
               print_syntax(" #range <>");
1✔
1425
            }
1426
            print_syntax(") #of ");
1✔
1427
            dump_type(type_elem(type));
1✔
1428
         }
1429
         break;
1✔
1430
      case GTYPE_ACCESS:
1✔
1431
         print_syntax("#access ..");
1✔
1432
         break;
1✔
1433
      case GTYPE_FILE:
1✔
1434
         print_syntax("#file #of ..");
1✔
1435
         break;
1✔
1436
      }
1437
   }
1438
   else {
1439
      const char *dir = NULL;
90✔
1440
      switch (tree_subkind(t)) {
90✔
1441
      case PORT_IN:      dir = "in";     break;
86✔
1442
      case PORT_OUT:     dir = "out";    break;
4✔
UNCOV
1443
      case PORT_INOUT:   dir = "inout";  break;
×
1444
      case PORT_BUFFER:  dir = "buffer"; break;
×
1445
      case PORT_INVALID: dir = "??";     break;
×
1446
      }
1447
      print_syntax(" : #%s ", dir);
90✔
1448
      dump_type(type);
90✔
1449

1450
      if (tree_has_value(t)) {
90✔
1451
         print_syntax(" := ");
79✔
1452
         dump_expr(tree_value(t));
79✔
1453
      }
1454
   }
1455
}
100✔
1456

1457
static void dump_context(tree_t t, int indent)
6✔
1458
{
1459
   const int nctx = tree_contexts(t);
6✔
1460
   for (int i = 0; i < nctx; i++) {
24✔
1461
      tree_t c = tree_context(t, i);
18✔
1462
      switch (tree_kind(c)) {
18✔
1463
      case T_LIBRARY:
12✔
1464
         switch (is_well_known(tree_ident(c))) {
12✔
1465
         case W_STD:
1466
         case W_WORK:
1467
            break;
UNCOV
1468
         default:
×
1469
            print_syntax("#library %s;\n", istr(tree_ident(c)));
×
1470
         }
1471
         break;
1472

1473
      case T_USE:
6✔
1474
         dump_use(c);
6✔
1475
         break;
6✔
1476

UNCOV
1477
      case T_CONTEXT_REF:
×
1478
         print_syntax("#context %s;\n", istr(tree_ident(t)));
×
1479
         break;
×
1480

1481
      default:
1482
         break;
1483
      }
1484

1485
      tab(indent);
18✔
1486
   }
1487

1488
   if (nctx > 0) {
6✔
1489
      print_syntax("\n");
6✔
1490
      tab(indent);
6✔
1491
   }
1492
}
6✔
1493

UNCOV
1494
static void dump_elab(tree_t t)
×
1495
{
UNCOV
1496
   dump_context(t, 0);
×
1497
   dump_address(t);
×
1498
   print_syntax("#entity %s #is\n#end #entity;\n\n", istr(tree_ident(t)));
×
1499
   print_syntax("#architecture #elab #of %s #is\n", istr(tree_ident(t)));
×
1500
   dump_decls(t, 2);
×
1501
   print_syntax("#begin\n");
×
1502
   for (unsigned i = 0; i < tree_stmts(t); i++)
×
1503
      dump_stmt(tree_stmt(t, i), 2);
×
1504
   print_syntax("#end #architecture;\n\n");
×
1505
}
×
1506

1507
static void dump_entity(tree_t t)
2✔
1508
{
1509
   dump_context(t, 0);
2✔
1510
   dump_address(t);
2✔
1511
   print_syntax("#entity %s #is\n", istr(tree_ident(t)));
2✔
1512
   dump_generics(t, 2, ";\n");
2✔
1513
   dump_ports(t, 2);
2✔
1514
   dump_decls(t, 2);
2✔
1515
   if (tree_stmts(t) > 0) {
2✔
UNCOV
1516
      print_syntax("#begin\n");
×
1517
      for (unsigned i = 0; i < tree_stmts(t); i++) {
×
1518
         dump_stmt(tree_stmt(t, i), 2);
×
1519
      }
1520
   }
1521
   print_syntax("#end #entity;\n\n");
2✔
1522
}
2✔
1523

1524
static void dump_decls(tree_t t, int indent)
15✔
1525
{
1526
   const int ndecls = tree_decls(t);
15✔
1527
   bool was_body = false;
15✔
1528
   for (unsigned i = 0; i < ndecls; i++) {
31✔
1529
      tree_t d = tree_decl(t, i);
16✔
1530
      tree_kind_t dkind = tree_kind(d);
16✔
1531
      const bool is_body = dkind == T_FUNC_BODY || dkind == T_PROT_BODY
32✔
1532
         || dkind == T_PROC_BODY;
16✔
1533
      if ((was_body && !is_body) || (is_body && i > 0))
16✔
1534
         print_syntax("\n");
4✔
1535
      was_body = is_body;
16✔
1536
      dump_decl(d, indent);
16✔
1537
   }
1538
}
15✔
1539

1540
static void dump_arch(tree_t t)
1✔
1541
{
1542
   dump_context(t, 0);
1✔
1543
   dump_address(t);
1✔
1544
   print_syntax("#architecture %s #of %s #is\n",
1✔
1545
                istr(tree_ident(t)), istr(tree_ident2(t)));
1546
   dump_decls(t, 2);
1✔
1547
   print_syntax("#begin\n");
1✔
1548
   dump_stmts(t, 2);
1✔
1549
   print_syntax("#end #architecture;\n\n");
1✔
1550
}
1✔
1551

1552
static void dump_package(tree_t t, int indent)
1✔
1553
{
1554
   dump_context(t, indent);
1✔
1555
   dump_address(t);
1✔
1556
   print_syntax("#package %s #is\n", istr(tree_ident(t)));
1✔
1557
   if (tree_kind(t) == T_PACK_INST && tree_has_ref(t)) {
1✔
UNCOV
1558
      tab(indent);
×
1559
      print_syntax("  -- Instantiated from %s\n", istr(tree_ident(tree_ref(t))));
×
1560
   }
1561
   dump_generics(t, indent + 2, ";\n");
1✔
1562
   dump_generic_map(t, indent + 2, ";\n");
1✔
1563
   dump_decls(t, indent + 2);
1✔
1564
   tab(indent);
1✔
1565
   print_syntax("#end #package;\n\n");
1✔
1566
}
1✔
1567

1568
static void dump_package_body(tree_t t, int indent)
2✔
1569
{
1570
   dump_context(t, indent);
2✔
1571
   dump_address(t);
2✔
1572
   print_syntax("#package #body %s #is\n", istr(tree_ident(t)));
2✔
1573
   dump_decls(t, indent + 2);
2✔
1574
   tab(indent);
2✔
1575
   print_syntax("#end #package #body;\n\n");
2✔
1576
}
2✔
1577

UNCOV
1578
static void dump_configuration(tree_t t)
×
1579
{
UNCOV
1580
   dump_address(t);
×
1581
   print_syntax("#configuration %s #of %s #is\n",
×
1582
          istr(tree_ident(t)), istr(tree_ident2(t)));
UNCOV
1583
   dump_decls(t, 2);
×
1584
   print_syntax("#end #configuration\n");
×
1585
}
×
1586

1587
void vhdl_dump(tree_t t, int indent)
29✔
1588
{
1589
   switch (tree_kind(t)) {
29✔
UNCOV
1590
   case T_ELAB:
×
1591
      dump_elab(t);
×
1592
      break;
×
1593
   case T_ENTITY:
2✔
1594
      dump_entity(t);
2✔
1595
      break;
2✔
1596
   case T_ARCH:
1✔
1597
      dump_arch(t);
1✔
1598
      break;
1✔
1599
   case T_PACKAGE:
1✔
1600
   case T_PACK_INST:
1601
      dump_package(t, indent);
1✔
1602
      break;
1✔
1603
   case T_PACK_BODY:
2✔
1604
      dump_package_body(t, indent);
2✔
1605
      break;
2✔
UNCOV
1606
   case T_CONFIGURATION:
×
1607
      dump_configuration(t);
×
1608
      break;
×
1609
   case T_REF:
10✔
1610
   case T_FCALL:
1611
   case T_PROT_FCALL:
1612
   case T_LITERAL:
1613
   case T_AGGREGATE:
1614
   case T_ARRAY_REF:
1615
   case T_ARRAY_SLICE:
1616
   case T_TYPE_CONV:
1617
   case T_RECORD_REF:
1618
   case T_ATTR_REF:
1619
   case T_CONV_FUNC:
1620
   case T_QUALIFIED:
1621
   case T_EXTERNAL_NAME:
1622
   case T_STRING:
1623
   case T_PACKAGE_MAP:
1624
      dump_expr(t);
10✔
1625
      break;
10✔
1626
   case T_INSTANCE:
4✔
1627
   case T_FOR_GENERATE:
1628
   case T_CASE_GENERATE:
1629
   case T_BLOCK:
1630
   case T_PROCESS:
1631
   case T_CASE:
1632
   case T_FOR:
1633
   case T_SIGNAL_ASSIGN:
1634
   case T_IF:
1635
   case T_WAIT:
1636
   case T_PSL:
1637
   case T_VAR_ASSIGN:
1638
   case T_RETURN:
1639
   case T_ASSERT:
1640
      dump_stmt(t, indent);
4✔
1641
      break;
4✔
1642
   case T_CONST_DECL:
8✔
1643
   case T_VAR_DECL:
1644
   case T_SIGNAL_DECL:
1645
   case T_TYPE_DECL:
1646
   case T_FIELD_DECL:
1647
   case T_FUNC_DECL:
1648
   case T_PROC_BODY:
1649
   case T_FUNC_BODY:
1650
   case T_PROC_DECL:
1651
   case T_ATTR_DECL:
1652
   case T_ATTR_SPEC:
1653
   case T_ENUM_LIT:
1654
   case T_COMPONENT:
1655
   case T_BLOCK_CONFIG:
1656
   case T_SPEC:
1657
   case T_ALIAS:
1658
   case T_FUNC_INST:
1659
   case T_PROC_INST:
1660
   case T_SUBTYPE_DECL:
1661
      dump_decl(t, indent);
8✔
1662
      break;
8✔
UNCOV
1663
   case T_PORT_DECL:
×
1664
   case T_GENERIC_DECL:
1665
      dump_port(t, indent);
×
UNCOV
1666
      break;
×
1667
   case T_RANGE:
1✔
1668
      dump_range(t);
1✔
1669
      break;
1✔
UNCOV
1670
   case T_BINDING:
×
UNCOV
1671
      dump_binding(t, indent);
×
1672
      break;
×
1673
   case T_PARAM:
×
1674
      dump_param(t);
×
1675
      break;
×
1676
   case T_CONSTRAINT:
×
1677
      dump_constraint(t);
×
1678
      break;
×
1679
   case T_ELEM_CONSTRAINT:
×
1680
      dump_record_elem_constraint(t);
×
1681
      break;
×
1682
   case T_ALTERNATIVE:
×
1683
      dump_alternative(t, indent);
×
1684
      break;
×
1685
   default:
×
1686
      cannot_dump(t, "tree");
×
1687
   }
1688
}
29✔
1689

1690
void dump(tree_t t)
18✔
1691
{
1692
   vhdl_dump(t, 0);
18✔
1693
   print_syntax("\r");
18✔
1694
}
18✔
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