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

nickg / nvc / 6383422048

02 Oct 2023 05:25PM UTC coverage: 91.231% (+0.008%) from 91.223%
6383422048

push

github

nickg
Handle $MOVE with overlapping regions in x86 backend

9 of 9 new or added lines in 1 file covered. (100.0%)

48709 of 53391 relevant lines covered (91.23%)

623692.98 hits per line

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

98.61
/src/simp.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 "array.h"
20
#include "common.h"
21
#include "diag.h"
22
#include "eval.h"
23
#include "hash.h"
24
#include "phase.h"
25
#include "type.h"
26

27
#include <assert.h>
28
#include <string.h>
29
#include <stdarg.h>
30
#include <inttypes.h>
31
#include <stdlib.h>
32

33
typedef struct {
34
   tree_t           top;
35
   jit_t           *jit;
36
   unit_registry_t *registry;
37
   tree_flags_t     eval_mask;
38
   hash_t          *generics;
39
} simp_ctx_t;
40

41
static tree_t simp_tree(tree_t t, void *context);
42

43
static tree_t simp_call_args(tree_t t)
132,318✔
44
{
45
   tree_t decl = tree_ref(t);
132,318✔
46

47
   const int nparams = tree_params(t);
132,318✔
48
   const int nports  = tree_ports(decl);
132,318✔
49

50
   // Replace named arguments with positional ones
51

52
   int last_pos = -1;
132,318✔
53
   for (int i = 0; i < nparams; i++) {
400,506✔
54
      if (tree_subkind(tree_param(t, i)) == P_POS)
268,188✔
55
         last_pos = i;
264,834✔
56
   }
57

58
   if (last_pos == nports - 1)
132,318✔
59
      return t;
60

61

62
   tree_t new = tree_new(tree_kind(t));
2,780✔
63
   tree_set_loc(new, tree_loc(t));
2,780✔
64
   if (tree_has_ident(t))
2,780✔
65
      tree_set_ident(new, tree_ident(t));
1,673✔
66
   tree_set_ref(new, tree_ref(t));
2,780✔
67

68
   tree_kind_t kind = tree_kind(t);
2,780✔
69
   if (kind == T_FCALL || kind == T_PROT_FCALL) {
2,780✔
70
      tree_set_type(new, tree_type(t));
1,657✔
71
      tree_set_flag(new, tree_flags(t));
1,657✔
72
   }
73

74
   if ((kind == T_PROT_PCALL || kind == T_PROT_FCALL) && tree_has_name(t))
2,780✔
75
      tree_set_name(new, tree_name(t));
76✔
76

77
   for (int i = 0; i <= last_pos; i++) {
7,616✔
78
      tree_t port  = tree_port(decl, i);
4,836✔
79
      tree_t param = tree_param(t, i);
4,836✔
80
      tree_t value = tree_value(param);
4,836✔
81

82
      if (tree_kind(value) == T_OPEN)
4,836✔
83
         value = tree_value(port);
9✔
84

85
      add_param(new, value, P_POS, NULL);
4,836✔
86
   }
87

88
   for (int i = last_pos + 1; i < nports; i++) {
10,000✔
89
      tree_t port = tree_port(decl, i);
7,220✔
90

91
      tree_t agg = NULL;
7,220✔
92
      bool found = false;
7,220✔
93
      for (int j = last_pos + 1; j < nparams; j++) {
16,864✔
94
         tree_t p = tree_param(t, j);
12,950✔
95
         assert(tree_subkind(p) == P_NAMED);
12,950✔
96

97
         tree_t name = tree_name(p);
12,950✔
98
         const tree_kind_t name_kind = tree_kind(name);
12,950✔
99
         if (name_kind == T_REF) {
12,950✔
100
            if (tree_ref(name) == port) {
12,878✔
101
               tree_t value = tree_value(p);
3,306✔
102

103
               if (tree_kind(value) == T_OPEN)
3,306✔
104
                  value = tree_value(port);
9✔
105

106
               add_param(new, value, P_POS, NULL);
3,306✔
107
               found = true;
3,306✔
108
               break;
3,306✔
109
            }
110
         }
111
         else {
112
            // Must be a partial association
113
            tree_t ref = tree_value(name);
72✔
114
            assert(tree_kind(ref) == T_REF);   // Checked by sem
72✔
115
            if (tree_ref(ref) == port) {
72✔
116
               if (agg == NULL) {
48✔
117
                  agg = tree_new(T_AGGREGATE);
24✔
118
                  tree_set_loc(agg, tree_loc(p));
24✔
119
                  tree_set_type(agg, tree_type(port));
24✔
120

121
                  add_param(new, agg, P_POS, NULL);
24✔
122
               }
123

124
               tree_t a = tree_new(T_ASSOC);
48✔
125
               tree_set_loc(a, tree_loc(p));
48✔
126
               tree_set_subkind(a, A_NAMED);
48✔
127
               tree_set_value(a, tree_value(p));
48✔
128

129
               if (name_kind == T_RECORD_REF)
48✔
130
                  tree_set_name(a, make_ref(tree_ref(name)));
36✔
131
               else
132
                  tree_set_name(a, tree_value(tree_param(name, 0)));
12✔
133

134
               tree_add_assoc(agg, a);
48✔
135

136
               found = true;
48✔
137
            }
138
         }
139
      }
140

141
      if (!found) {
7,220✔
142
         assert(tree_has_value(port));  // Checked by sem
3,890✔
143
         add_param(new, tree_value(port), P_POS, NULL);
3,890✔
144
      }
145
   }
146

147
   return new;
148
}
149

150
static tree_t simp_fold(tree_t t, simp_ctx_t *ctx)
151
{
152
   type_t type = tree_type(t);
153
   if (!type_is_scalar(type))
154
      return t;
155
   else if (!eval_possible(t, ctx->registry))
156
      return t;
157

158
   return eval_try_fold(ctx->jit, t, NULL, NULL);
159
}
160

161
static void simp_generic_subprogram(tree_t t, simp_ctx_t *ctx)
162
{
163
   tree_t decl = tree_ref(t);
164
   if (tree_kind(decl) == T_GENERIC_DECL) {
165
      tree_t map = hash_get(ctx->generics, tree_ref(t));
166
      if (map == NULL)
167
         return;
168

169
      if (tree_kind(map) == T_REF)
170
         map = tree_ref(map);
171

172
      assert(is_subprogram(map));
173
      tree_set_ref(t, map);
174
   }
175
}
176

177
static tree_t simp_concat(tree_t t)
3,553✔
178
{
179
   assert(tree_params(t) == 2);
3,553✔
180

181
   tree_t p0 = tree_value(tree_param(t, 0));
3,553✔
182
   tree_t p1 = tree_value(tree_param(t, 1));
3,553✔
183

184
   tree_t p0_enum = NULL, p1_enum = NULL;
3,553✔
185

186
   const tree_kind_t p0_kind = tree_kind(p0);
3,553✔
187
   const tree_kind_t p1_kind = tree_kind(p1);
3,553✔
188

189
   // Only handle concatenations of string literals and enumeration
190
   // literals
191

192
   if (p0_kind == T_REF) {
3,553✔
193
      if (tree_kind((p0_enum = tree_ref(p0))) != T_ENUM_LIT)
230✔
194
         return t;
195
   }
196
   else if (p0_kind != T_STRING)
3,323✔
197
      return t;
198

199
   if (p1_kind == T_REF) {
580✔
200
      if (tree_kind((p1_enum = tree_ref(p1))) != T_ENUM_LIT)
142✔
201
         return t;
202
   }
203
   else if (p1_kind != T_STRING)
438✔
204
      return t;
205

206
   tree_t new = tree_new(T_STRING);
124✔
207
   tree_set_loc(new, tree_loc(t));
124✔
208

209
   if (p0_enum != NULL)
124✔
210
      tree_add_char(new, make_ref(p0_enum));
27✔
211
   else {
212
      const int p0_chars = tree_chars(p0);
97✔
213
      for (int i = 0; i < p0_chars; i++)
2,010✔
214
         tree_add_char(new, tree_char(p0, i));
1,913✔
215
   }
216

217
   if (p1_enum != NULL)
124✔
218
      tree_add_char(new, make_ref(p1_enum));
52✔
219
   else {
220
      const int p1_chars = tree_chars(p1);
72✔
221
      for (int i = 0; i < p1_chars; i++)
2,535✔
222
         tree_add_char(new, tree_char(p1, i));
2,463✔
223
   }
224

225
   tree_set_type(new, subtype_for_string(new, tree_type(t)));
124✔
226
   return new;
124✔
227
}
228

229
static bool simp_literal_args(tree_t t, int64_t *p0, int64_t *p1)
80,851✔
230
{
231
   switch (tree_params(t)) {
80,851✔
232
   case 2:
67,911✔
233
      if (!folded_int(tree_value(tree_param(t, 1)), p1))
67,911✔
234
         return false;
235
      // Fall-through
236
   case 1:
237
      return folded_int(tree_value(tree_param(t, 0)), p0);
53,191✔
238
   default:
239
      return false;
240
   }
241
}
242

243
static tree_t simp_fcall(tree_t t, simp_ctx_t *ctx)
119,276✔
244
{
245
   if (standard() >= STD_08 && ctx->generics != NULL)
119,276✔
246
      simp_generic_subprogram(t, ctx);
10,365✔
247

248
   t = simp_call_args(t);
119,276✔
249

250
   const subprogram_kind_t kind = tree_subkind(tree_ref(t));
119,276✔
251
   const tree_flags_t flags = tree_flags(t);
119,276✔
252

253
   if (kind == S_CONCAT)
119,276✔
254
      return simp_concat(t);
3,553✔
255
   else if (kind != S_USER && kind != S_FOREIGN) {
115,723✔
256
      // Simplify basic operations on literals without the overhead of
257
      // generating code
258
      int64_t p0, p1, result;
80,851✔
259
      if (simp_literal_args(t, &p0, &p1)) {
80,851✔
260
         switch (kind) {
15,142✔
261
         case S_NEGATE:
1,644✔
262
            if (p0 == INT64_MIN)
1,644✔
263
               break;
264
            else
265
               return get_int_lit(t, NULL, -p0);
14,655✔
266

267
         case S_IDENTITY:
29✔
268
            return get_int_lit(t, NULL, p0);
29✔
269

270
         case S_SCALAR_NOT:
1,235✔
271
            return get_enum_lit(t, NULL, !p0);
1,235✔
272

273
         case S_SCALAR_EQ:
3,485✔
274
            return get_enum_lit(t, NULL, p0 == p1);
3,485✔
275

276
         case S_SCALAR_NEQ:
42✔
277
            return get_enum_lit(t, NULL, p0 != p1);
42✔
278

279
         case S_SCALAR_GT:
393✔
280
            return get_enum_lit(t, NULL, p0 > p1);
393✔
281

282
         case S_SCALAR_LT:
8✔
283
            return get_enum_lit(t, NULL, p0 < p1);
8✔
284

285
         case S_SCALAR_GE:
3✔
286
            return get_enum_lit(t, NULL, p0 >= p1);
3✔
287

288
         case S_SCALAR_LE:
2✔
289
            return get_enum_lit(t, NULL, p0 <= p1);
2✔
290

291
         case S_SCALAR_XOR:
2✔
292
            return get_enum_lit(t, NULL, p0 ^ p1);
2✔
293

294
         case S_SCALAR_XNOR:
1✔
295
            return get_enum_lit(t, NULL, !(p0 ^ p1));
1✔
296

297
         case S_SCALAR_AND:
1,853✔
298
            return get_enum_lit(t, NULL, p0 & p1);
1,853✔
299

300
         case S_SCALAR_NAND:
1✔
301
            return get_enum_lit(t, NULL, !(p0 & p1));
1✔
302

303
         case S_SCALAR_OR:
32✔
304
            return get_enum_lit(t, NULL, p0 | p1);
32✔
305

306
         case S_SCALAR_NOR:
1✔
307
            return get_enum_lit(t, NULL, !(p0 | p1));
1✔
308

309
         case S_ADD:
1,072✔
310
            if (__builtin_add_overflow(p0, p1, &result))
1,072✔
311
               break;
312
            else
313
               return get_int_lit(t, NULL, result);
1,069✔
314

315
         case S_SUB:
3,231✔
316
            if (__builtin_sub_overflow(p0, p1, &result))
3,231✔
317
               break;
318
            else
319
               return get_int_lit(t, NULL, result);
3,231✔
320

321
         case S_MUL:
661✔
322
            if (__builtin_mul_overflow(p0, p1, &result))
661✔
323
               break;
324
            else
325
               return get_int_lit(t, NULL, result);
661✔
326

327
         case S_DIV:
211✔
328
            if ((p0 == INT64_MIN && p1 == -1) || p1 == 0)
211✔
329
               break;
330
            else
331
               return get_int_lit(t, NULL, p0 / p1);
210✔
332

333
         case S_EXP:
334
            if (p1 >= 0 && ipow_safe(p0, p1, &result))
1,159✔
335
               return get_int_lit(t, NULL, result);
751✔
336
            else
337
               break;
338

339
         case S_ABS:
2✔
340
            if (p0 == INT64_MIN)
2✔
341
               break;
342
            else
343
               return get_int_lit(t, NULL, llabs(p0));
2✔
344

345
         default:
346
            break;
347
         }
348
      }
66,121✔
349
   }
350

351
   if (flags & ctx->eval_mask)
101,068✔
352
      return simp_fold(t, ctx);
15,151✔
353

354
   return t;
355
}
356

357
static tree_t simp_type_conv(tree_t t, simp_ctx_t *ctx)
3,004✔
358
{
359
   return simp_fold(t, ctx);
3,004✔
360
}
361

362
static tree_t simp_pcall(tree_t t, simp_ctx_t *ctx)
13,042✔
363
{
364
   if (standard() >= STD_08 && ctx->generics != NULL)
13,042✔
365
      simp_generic_subprogram(t, ctx);
339✔
366

367
   return simp_call_args(t);
13,042✔
368
}
369

370
static tree_t simp_record_ref(tree_t t, simp_ctx_t *ctx)
371
{
372
   tree_t value = tree_value(t);
373
   if (tree_kind(value) == T_AGGREGATE) {
374
      ident_t field = tree_ident(t);
375
      type_t type = tree_type(value);
376

377
      const int nassocs = tree_assocs(value);
378
      for (int i = 0; i < nassocs; i++) {
379
         tree_t a = tree_assoc(value, i);
380
         switch (tree_subkind(a)) {
381
         case A_POS:
382
            if (tree_ident(type_field(type, tree_pos(a))) == field)
383
               return tree_value(a);
384
            break;
385

386
         case A_NAMED:
387
            if (tree_ident(tree_name(a)) == field)
388
               return tree_value(a);
389
            break;
390
         }
391
      }
392
   }
393

394
   return t;
395
}
396

397
static tree_t simp_ref(tree_t t, simp_ctx_t *ctx)
398
{
399
   tree_t decl = tree_ref(t);
400

401
   switch (tree_kind(decl)) {
402
   case T_CONST_DECL:
403
      if (tree_flags(t) & TREE_F_FORMAL_NAME)
404
         return t;
405
      else if (!type_is_scalar(tree_type(decl)))
406
         return t;
407
      else if (tree_has_value(decl)) {
408
         tree_t value = tree_value(decl);
409
         switch (tree_kind(value)) {
410
         case T_LITERAL:
411
            return value;
412
         case T_REF:
413
            if (tree_kind(tree_ref(value)) == T_ENUM_LIT)
414
               return value;
415
            // Fall-through
416
         default:
417
            return t;
418
         }
419
      }
420
      else
421
         return t;
422

423
   case T_UNIT_DECL:
424
      return tree_value(decl);
425

426
   case T_PORT_DECL:
427
   case T_GENERIC_DECL:
428
      if (ctx->generics != NULL) {
429
         tree_t map = hash_get(ctx->generics, decl);
430
         if (map != NULL) {
431
            switch (tree_kind(map)) {
432
            case T_LITERAL:
433
            case T_STRING:
434
            case T_AGGREGATE:
435
            case T_ARRAY_SLICE:
436
            case T_ARRAY_REF:
437
            case T_FCALL:
438
            case T_RECORD_REF:
439
            case T_OPEN:
440
            case T_QUALIFIED:
441
            case T_TYPE_CONV:
442
            case T_ATTR_REF:
443
            case T_REF:
444
            case T_TYPE_REF:
445
               // Do not rewrite references to non-references if they appear
446
               // as formal names
447
               if (tree_flags(t) & TREE_F_FORMAL_NAME)
448
                  break;
449
               return map;
450
            case T_PORT_DECL:
451
               tree_set_ref(t, map);
452
               tree_set_type(t, tree_type(map));
453
               return t;
454
            default:
455
               fatal_trace("cannot rewrite generic %s to tree kind %s",
456
                           istr(tree_ident(t)), tree_kind_str(tree_kind(map)));
457
            }
458
         }
459
      }
460
      return t;
461

462
   default:
463
      return t;
464
   }
465
}
466

467
static tree_t simp_convert_range_bound(tree_t expr, tree_t where)
4,359✔
468
{
469
   type_t type = tree_type(where);
4,359✔
470
   if (type_eq(tree_type(expr), type))
4,359✔
471
      return expr;
472

473
   tree_t conv = tree_new(T_TYPE_CONV);
6✔
474
   tree_set_loc(conv, tree_loc(where));
6✔
475
   tree_set_value(conv, expr);
6✔
476
   tree_set_type(conv, type);
6✔
477

478
   return conv;
6✔
479
}
480

481
static tree_t simp_attr_ref(tree_t t, simp_ctx_t *ctx)
482
{
483
   if (tree_has_value(t))
484
      return tree_value(t);
485

486
   const attr_kind_t predef = tree_subkind(t);
487
   switch (predef) {
488
   case ATTR_POS:
489
      {
490
         tree_t value = tree_value(tree_param(t, 0));
491

492
         int64_t ipos;
493
         if (folded_int(value, &ipos))
494
            return get_int_lit(t, NULL, ipos);
495

496
         return t;
497
      }
498

499
   case ATTR_LENGTH:
500
   case ATTR_LEFT:
501
   case ATTR_LOW:
502
   case ATTR_HIGH:
503
   case ATTR_RIGHT:
504
   case ATTR_ASCENDING:
505
      {
506
         tree_t name = tree_name(t);
507
         tree_kind_t name_kind = tree_kind(name);
508

509
         if (name_kind == T_ATTR_REF) {
510
            // Try to rewrite expressions like X'RANGE(1)'LEFT to X'LEFT(1)
511
            attr_kind_t prefix_predef = tree_subkind(name);
512
            if (prefix_predef == ATTR_RANGE || prefix_predef == ATTR_BASE
513
                || prefix_predef == ATTR_REVERSE_RANGE) {
514
               tree_t new = tree_new(T_ATTR_REF);
515
               tree_set_loc(new, tree_loc(t));
516
               tree_set_name(new, tree_name(name));
517
               tree_set_ident(new, tree_ident(t));
518
               tree_set_subkind(new, predef);
519
               tree_set_type(new, tree_type(t));
520

521
               const int nparams = tree_params(name);
522
               for (int i = 0; i < nparams; i++)
523
                  tree_add_param(new, tree_param(name, i));
524

525
               t = new;
526
               name = tree_name(new);
527
               name_kind = tree_kind(name);
528
            }
529
         }
530

531
         type_t type = tree_type(name);
532
         int64_t dim_i = 1;
533

534
         if (type_kind(type) == T_ENUM) {
535
            // Enumeration subtypes are handled below
536
            const int nlits = type_enum_literals(type);
537

538
            switch (predef) {
539
            case ATTR_LEFT:
540
            case ATTR_LOW:
541
               return make_ref(type_enum_literal(type, 0));
542
            case ATTR_RIGHT:
543
            case ATTR_HIGH:
544
               return make_ref(type_enum_literal(type, nlits - 1));
545
            case ATTR_ASCENDING:
546
               return get_enum_lit(t, NULL, true);
547
            case ATTR_LENGTH:
548
               return get_int_lit(t, NULL, nlits);
549
            default:
550
               fatal_trace("invalid enumeration attribute %d", predef);
551
            }
552
         }
553
         else if (type_is_array(type)) {
554
            if (tree_params(t) > 0) {
555
               tree_t value = tree_value(tree_param(t, 0));
556
               if (!folded_int(value, &dim_i))
557
                  fatal_at(tree_loc(value), "locally static dimension "
558
                           "expression was not folded");
559
            }
560

561
            if (name_kind == T_REF
562
                && tree_kind(tree_ref(name)) == T_TYPE_DECL
563
                && type_kind(type) == T_ARRAY) {
564

565
               // Get index type of unconstrained array
566

567
               if (dim_i < 1 || dim_i > type_indexes(type))
568
                  return t;
569

570
               type  = type_index(type, dim_i - 1);
571
               dim_i = 1;
572
            }
573
            else if (type_is_unconstrained(type))
574
               return t;
575
            else if (dim_i < 1 || dim_i > dimension_of(type))
576
               return t;
577
         }
578

579
         tree_t r = range_of(type, dim_i - 1);
580

581
         const range_kind_t rkind = tree_subkind(r);
582
         if (rkind != RANGE_TO && rkind != RANGE_DOWNTO)
583
            return t;
584

585
         switch (predef) {
586
         case ATTR_LENGTH:
587
            {
588
               int64_t low, high, length = 0;
589
               if (folded_bounds(r, &low, &high)) {
590
                  if (high < low)
591
                     return get_int_lit(t, NULL, 0);
592
                  else {
593
                     bool overflow = false;
594
                     overflow |= __builtin_sub_overflow(high, low, &length);
595
                     overflow |= __builtin_add_overflow(length, 1, &length);
596

597
                     if (overflow)
598
                        error_at(tree_loc(t), "value of LENGTH attribute "
599
                                 "exceeds universal integer range");
600
                     else
601
                        return get_int_lit(t, NULL, length);
602
                  }
603
               }
604

605
               return t;
606
            }
607

608
         case ATTR_LOW:
609
            if (tree_subkind(r) == RANGE_TO)
610
               return simp_convert_range_bound(tree_left(r), t);
611
            else
612
               return simp_convert_range_bound(tree_right(r), t);
613
         case ATTR_HIGH:
614
            if (tree_subkind(r) == RANGE_TO)
615
               return simp_convert_range_bound(tree_right(r), t);
616
            else
617
               return simp_convert_range_bound(tree_left(r), t);
618
         case ATTR_LEFT:
619
            return simp_convert_range_bound(tree_left(r), t);
620
         case ATTR_RIGHT:
621
            return simp_convert_range_bound(tree_right(r), t);
622
         case ATTR_ASCENDING:
623
            return get_enum_lit(t, NULL, (rkind == RANGE_TO));
624
         default:
625
            return t;
626
         }
627
      }
628

629
   default:
630
      return t;
631
   }
632
}
633

634
static void simp_build_wait_cb(tree_t expr, void *ctx)
1,873✔
635
{
636
   tree_t wait = ctx;
1,873✔
637

638
   if (tree_kind(expr) == T_REF) {
1,873✔
639
      // Check for duplicates
640
      tree_t decl = tree_ref(expr);
1,518✔
641
      const int ntriggers = tree_triggers(wait);
1,518✔
642
      for (int i = 0; i < ntriggers; i++) {
1,913✔
643
         tree_t t = tree_trigger(wait, i);
477✔
644
         if (tree_kind(t) == T_REF && tree_ref(t) == decl)
477✔
645
            return;
646
      }
647
   }
648

649
   tree_add_trigger(wait, expr);
1,791✔
650
}
651

652
static tree_t simp_process(tree_t t)
11,648✔
653
{
654
   // Replace sensitivity list with a "wait on" statement
655
   const int ntriggers = tree_triggers(t);
11,648✔
656
   if (ntriggers > 0) {
11,648✔
657
      const int nstmts = tree_stmts(t);
328✔
658
      if (nstmts == 0)
328✔
659
         return NULL;   // Body was optimised away
660

661
      tree_t p = tree_new(T_PROCESS);
328✔
662
      tree_set_ident(p, tree_ident(t));
328✔
663
      tree_set_loc(p, tree_loc(t));
328✔
664
      tree_set_flag(p, tree_flags(t));
328✔
665

666
      const int ndecls = tree_decls(t);
328✔
667
      for (int i = 0; i < ndecls; i++)
461✔
668
         tree_add_decl(p, tree_decl(t, i));
133✔
669

670
      for (int i = 0; i < nstmts; i++)
760✔
671
         tree_add_stmt(p, tree_stmt(t, i));
432✔
672

673
      tree_t w = tree_new(T_WAIT);
328✔
674
      tree_set_ident(w, tree_ident(p));
328✔
675
      tree_set_flag(w, TREE_F_STATIC_WAIT);
328✔
676

677
      if (ntriggers == 1 && tree_kind(tree_trigger(t, 0)) == T_ALL)
328✔
678
         build_wait(t, simp_build_wait_cb, w);
17✔
679
      else {
680
         for (int i = 0; i < ntriggers; i++)
729✔
681
            tree_add_trigger(w, tree_trigger(t, i));
418✔
682
      }
683

684
      tree_add_stmt(p, w);
328✔
685

686
      return p;
328✔
687
   }
688

689
   // Delete processes that contain just a single wait statement
690
   if (tree_stmts(t) == 1 && tree_kind(tree_stmt(t, 0)) == T_WAIT)
11,320✔
691
      return NULL;
692
   else
693
      return t;
11,097✔
694
}
695

696
static tree_t simp_wait(tree_t t)
10,085✔
697
{
698
   // LRM 93 section 8.1
699
   // If there is no sensitivity list supplied generate one from the
700
   // condition clause
701

702
   if (tree_has_value(t) && tree_triggers(t) == 0)
10,085✔
703
      build_wait(tree_value(t), simp_build_wait_cb, t);
220✔
704

705
   return t;
10,085✔
706
}
707

708
static tree_t simp_case(tree_t t)
595✔
709
{
710
   const int nstmts = tree_stmts(t);
595✔
711
   if (nstmts == 0)
595✔
712
      return NULL;    // All choices are unreachable
713

714
   int64_t ival;
595✔
715
   if (!folded_int(tree_value(t), &ival))
595✔
716
      return t;
717

718
   for (int i = 0; i < nstmts; i++) {
60✔
719
      tree_t alt = tree_stmt(t, i);
60✔
720

721
      const int nassocs = tree_assocs(alt);
60✔
722
      for (int j = 0; j < nassocs; j++) {
98✔
723
         tree_t a = tree_assoc(alt, j);
60✔
724
         switch (tree_subkind(a)) {
60✔
725
         case A_NAMED:
56✔
726
            {
727
               int64_t aval;
56✔
728
               if (!folded_int(tree_name(a), &aval))
56✔
729
                  continue;
38✔
730
               else if (ival != aval)
56✔
731
                  continue;
38✔
732
            }
733
            break;
18✔
734

735
         case A_RANGE:
1✔
736
            {
737
               int64_t low, high;
1✔
738
               if (!folded_bounds(tree_range(a, 0), &low, &high))
1✔
739
                  continue;
×
740
               else if (ival < low || ival > high)
1✔
741
                  continue;
×
742
            }
743

744
         case A_OTHERS:
745
            break;
746
         }
747

748
         // This choice is always executed
749
         if (tree_stmts(alt) > 0) {
22✔
750
            const tree_kind_t kind =
38✔
751
               tree_kind(t) == T_CASE_GENERATE ? T_BLOCK : T_SEQUENCE;
19✔
752
            tree_t seq = tree_new(kind);
19✔
753
            tree_set_loc(seq, tree_loc(alt));
19✔
754
            if (tree_has_ident(alt))
19✔
755
               tree_set_ident(seq, tree_ident(alt));
1✔
756
            else if (tree_has_ident(t))
18✔
757
               tree_set_ident(seq, tree_ident(t));
×
758

759
            const int nstmts = tree_stmts(alt);
19✔
760
            for (int i = 0; i < nstmts; i++)
162✔
761
               tree_add_stmt(seq, tree_stmt(alt, i));
143✔
762

763
            return seq;
764
         }
765
         else
766
            return NULL;
767
      }
768
   }
769

770
   return NULL;  // No choices can be executed
771
}
772

773
static bool simp_has_drivers(tree_t t)
1,582✔
774
{
775
   switch (tree_kind(t)) {
1,582✔
776
   case T_SIGNAL_ASSIGN:
777
      return true;
778
   case T_VAR_ASSIGN:
35✔
779
   case T_WAIT:
780
   case T_NEXT:
781
   case T_EXIT:
782
   case T_FORCE:
783
   case T_RELEASE:
784
   case T_RETURN:
785
      return false;
35✔
786
   case T_IF:
5✔
787
      {
788
         const int nconds = tree_conds(t);
5✔
789
         for (int i = 0; i < nconds; i++) {
13✔
790
            if (simp_has_drivers(tree_cond(t, i)))
9✔
791
               return true;
792
         }
793
         return false;
794
      }
795
   case T_CASE:
814✔
796
   case T_MATCH_CASE:
797
   case T_WHILE:
798
   case T_COND_STMT:
799
   case T_SEQUENCE:
800
      {
801
         const int nstmts = tree_stmts(t);
814✔
802
         for (int i = 0; i < nstmts; i++) {
864✔
803
            if (simp_has_drivers(tree_stmt(t, i)))
779✔
804
               return true;
805
         }
806
         return false;
807
      }
808
   default:
809
      return true;   // Conservative
810
   }
811
}
812

813
static tree_t simp_cond(tree_t t)
19,160✔
814
{
815
   if (tree_has_value(t)) {
19,160✔
816
      bool value_b;
14,082✔
817
      if (folded_bool(tree_value(t), &value_b)) {
14,082✔
818
         if (!tree_has_ident(t) && simp_has_drivers(t)) {
1,722✔
819
            // The statement part contains drivers that we cannot remove
820
            // without changing the behaviour
821
            return t;
1,722✔
822
         }
823
         else if (value_b) {
995✔
824
            // Always true, remove the test
825
            tree_set_value(t, NULL);
507✔
826
            return t;
507✔
827
         }
828
         else {
829
            // Always false, delete the condition
830
            return NULL;
831
         }
832
      }
833
   }
834

835
   return t;
836
}
837

838
static tree_t simp_if(tree_t t)
11,782✔
839
{
840
   if (tree_conds(t) == 0)
11,782✔
841
      return NULL;   // All conditions were false
842

843
   tree_t c0 = tree_cond(t, 0);
11,780✔
844
   if (!tree_has_value(c0)) {
11,780✔
845
      // If statement always executes so replace with then part
846
      if (tree_stmts(c0) == 1)
63✔
847
         return tree_stmt(c0, 0);
17✔
848
      else {
849
         tree_t b = tree_new(T_SEQUENCE);
46✔
850
         tree_set_loc(b, tree_loc(t));
46✔
851
         if (tree_has_ident(t))
46✔
852
            tree_set_ident(b, tree_ident(t));
×
853

854
         const int nstmts = tree_stmts(c0);
46✔
855
         for (int i = 0; i < nstmts; i++)
50✔
856
            tree_add_stmt(b, tree_stmt(c0, i));
4✔
857
         return b;
858
      }
859
   }
860

861
   return t;
862
}
863

864
static tree_t simp_while(tree_t t)
511✔
865
{
866
   bool value_b;
511✔
867
   if (!tree_has_value(t))
511✔
868
      return t;
869
   else if (folded_bool(tree_value(t), &value_b) && !value_b
511✔
870
            && !simp_has_drivers(t)) {
2✔
871
      // Condition is false so loop never executes
872
      return NULL;
873
   }
874
   else
875
      return t;
510✔
876
}
877

878
static tree_t simp_guard(tree_t container, tree_t t, tree_t wait, tree_t s0)
8✔
879
{
880
   // See LRM 93 section 9.3
881

882
   tree_t g_if = tree_new(T_IF);
8✔
883
   tree_set_ident(g_if, ident_new("guard_if"));
8✔
884
   tree_set_loc(g_if, tree_loc(t));
8✔
885

886
   tree_t c0 = tree_new(T_COND_STMT);
8✔
887
   tree_add_cond(g_if, c0);
8✔
888

889
   tree_t guard_ref = tree_guard(t);
8✔
890
   tree_set_value(c0, guard_ref);
8✔
891
   tree_add_trigger(wait, guard_ref);
8✔
892

893
   // TODO: handle disconnection specifications here
894
   //
895
   // For now just use the default "disconnect S : T after 0 ns;"
896

897
   if (tree_kind(s0) == T_SIGNAL_ASSIGN) {
8✔
898
      tree_t target = tree_target(s0);
7✔
899
      tree_t ref = name_to_ref(target);
7✔
900
      if (ref != NULL && is_guarded_signal(tree_ref(ref))) {
7✔
901
         tree_t d = tree_new(T_SIGNAL_ASSIGN);
3✔
902
         tree_set_loc(d, tree_loc(t));
3✔
903
         tree_set_target(d, tree_target(s0));
3✔
904

905
         tree_t w0 = tree_new(T_WAVEFORM);
3✔
906
         tree_set_loc(w0, tree_loc(t));
3✔
907

908
         tree_add_waveform(d, w0);
3✔
909

910
         tree_t c1 = tree_new(T_COND_STMT);
3✔
911
         tree_add_cond(g_if, c1);
3✔
912

913
         tree_add_stmt(c1, d);
3✔
914
      }
915
   }
916

917
   tree_add_stmt(container, g_if);
8✔
918
   return c0;
8✔
919
}
920

921
static tree_t simp_concurrent(tree_t t)
2,535✔
922
{
923
   if (tree_stmts(t) == 0)
2,535✔
924
      return NULL;   // Body was optimised out
925

926
   // Replace concurrent statements with a process
927

928
   tree_t p = tree_new(T_PROCESS);
1,926✔
929
   tree_set_ident(p, tree_ident(t));
1,926✔
930
   tree_set_loc(p, tree_loc(t));
1,926✔
931
   tree_set_flag(p, tree_flags(t));
1,926✔
932

933
   tree_t s0 = tree_stmt(t, 0);
1,926✔
934

935
   tree_t w = tree_new(T_WAIT);
1,926✔
936

937
   if (tree_kind(s0) == T_PCALL) {
1,926✔
938
      // Concurrent procedure calls may have internal waits
939
      tree_t decl = tree_ref(s0);
42✔
940
      if (tree_flags(decl) & TREE_F_NEVER_WAITS)
42✔
941
         tree_set_flag(w, TREE_F_STATIC_WAIT);
11✔
942
   }
943
   else
944
      tree_set_flag(w, TREE_F_STATIC_WAIT);
1,884✔
945

946
   tree_t container = p;  // Where to add new statements
1,926✔
947

948
   if (tree_has_guard(t))
1,926✔
949
      container = simp_guard(container, t, w, s0);
8✔
950

951
   tree_add_stmt(container, s0);
1,926✔
952

953
   build_wait(s0, simp_build_wait_cb, w);
1,926✔
954

955
   tree_add_stmt(p, w);
1,926✔
956
   return p;
1,926✔
957
}
958

959
static tree_t simp_cond_assign(tree_t t)
1,505✔
960
{
961
   const int nconds = tree_conds(t);
1,505✔
962
   tree_t c0 = tree_cond(t, 0);
1,505✔
963

964
   if (nconds == 1 && !tree_has_value(c0))
1,505✔
965
      return tree_stmt(c0, 0);
1,365✔
966
   else {
967
      tree_t s = tree_new(T_IF);
140✔
968
      tree_set_loc(s, tree_loc(t));
140✔
969

970
      for (int i = 0; i < nconds; i++)
414✔
971
         tree_add_cond(s, tree_cond(t, i));
274✔
972

973
      return s;
974
   }
975
}
976

977
static tree_t simp_select(tree_t t)
38✔
978
{
979
   // Replace a select statement with a case statement
980

981
   const tree_kind_t kind =
76✔
982
      tree_kind(t) == T_MATCH_SELECT ? T_MATCH_CASE : T_CASE;
38✔
983

984
   tree_t c = tree_new(kind);
38✔
985
   tree_set_loc(c, tree_loc(t));
38✔
986
   tree_set_value(c, tree_value(t));
38✔
987

988
   const int nstmts = tree_stmts(t);
38✔
989
   for (int i = 0; i < nstmts; i++)
252✔
990
      tree_add_stmt(c, tree_stmt(t, i));
214✔
991

992
   return c;
38✔
993
}
994

995
static tree_t simp_context_ref(tree_t t, simp_ctx_t *ctx)
996
{
997
   tree_t decl = tree_ref(t);
998

999
   const int nctx = tree_contexts(decl);
1000
   for (int i = 2; i < nctx; i++)
1001
      tree_add_context(ctx->top, tree_context(decl, i));
1002

1003
   return NULL;
1004
}
1005

1006
static tree_t simp_assert(tree_t t)
23,020✔
1007
{
1008
   bool value_b;
23,020✔
1009
   if (!tree_has_value(t))
23,020✔
1010
      return t;
1011
   else if (folded_bool(tree_value(t), &value_b) && value_b) {
20,803✔
1012
      // Assertion always passes
1013
      return NULL;
1014
   }
1015
   else
1016
      return t;
17,827✔
1017
}
1018

1019
static tree_t simp_if_generate(tree_t t)
1,072✔
1020
{
1021
   if (tree_conds(t) == 0)
1,072✔
1022
      return NULL;   // All conditions were false
1023

1024
   tree_t c0 = tree_cond(t, 0);
608✔
1025
   if (!tree_has_value(c0)) {
608✔
1026
      // First condition is always true
1027
      tree_t b = tree_new(T_BLOCK);
466✔
1028
      tree_set_loc(b, tree_loc(c0));
466✔
1029
      tree_set_ident(b, tree_ident(c0));
466✔
1030

1031
      const int ndecls = tree_decls(c0);
466✔
1032
      for (int i = 0; i < ndecls; i++)
514✔
1033
         tree_add_decl(b, tree_decl(c0, i));
48✔
1034

1035
      const int nstmts = tree_stmts(c0);
466✔
1036
      for (int i = 0; i < nstmts; i++)
984✔
1037
         tree_add_stmt(b, tree_stmt(c0, i));
518✔
1038

1039
      return b;
1040
   }
1041

1042
   return t;
1043
}
1044

1045
static tree_t simp_signal_assign(tree_t t)
8,872✔
1046
{
1047
   tree_t target = tree_target(t);
8,872✔
1048

1049
   if (tree_kind(target) == T_OPEN)
8,872✔
1050
      return NULL;    // Delete it
×
1051

1052
   return t;
1053
}
1054

1055
static tree_t simp_var_assign(tree_t t)
20,197✔
1056
{
1057
   tree_t value = tree_value(t);
20,197✔
1058
   if (tree_kind(value) == T_COND_VALUE) {
20,197✔
1059
      // Replace with an if statement
1060
      tree_t new = tree_new(T_IF);
11✔
1061
      tree_set_loc(new, tree_loc(t));
11✔
1062

1063
      const int nconds = tree_conds(value);
11✔
1064
      for (int i = 0; i < nconds; i++) {
32✔
1065
         tree_t e = tree_cond(value, i);
21✔
1066

1067
         tree_t c = tree_new(T_COND_STMT);
21✔
1068
         tree_set_loc(c, tree_loc(e));
21✔
1069

1070
         if (tree_has_value(e))
21✔
1071
            tree_set_value(c, tree_value(e));
14✔
1072
         else
1073
            assert(i == nconds - 1);
7✔
1074

1075
         tree_t s = tree_new(T_VAR_ASSIGN);
21✔
1076
         tree_set_loc(s, tree_loc(t));
21✔
1077
         tree_set_target(s, tree_target(t));
21✔
1078
         tree_set_value(s, tree_result(e));
21✔
1079

1080
         tree_add_stmt(c, s);
21✔
1081
         tree_add_cond(new, c);
21✔
1082
      }
1083

1084
      return new;
1085
   }
1086

1087
   return t;
1088
}
1089

1090
static tree_t simp_return(tree_t t)
15,854✔
1091
{
1092
   if (!tree_has_value(t))
15,854✔
1093
      return t;
1094

1095
   tree_t value = tree_value(t);
15,510✔
1096
   if (tree_kind(value) == T_COND_VALUE) {
15,510✔
1097
      // Replace with an if statement
1098
      tree_t new = tree_new(T_IF);
11✔
1099
      tree_set_loc(new, tree_loc(t));
11✔
1100

1101
      const int nconds = tree_conds(value);
11✔
1102
      for (int i = 0; i < nconds; i++) {
37✔
1103
         tree_t e = tree_cond(value, i);
26✔
1104

1105
         tree_t c = tree_new(T_COND_STMT);
26✔
1106
         tree_set_loc(c, tree_loc(e));
26✔
1107

1108
         if (tree_has_value(e))
26✔
1109
            tree_set_value(c, tree_value(e));
20✔
1110
         else
1111
            assert(i == nconds - 1);
6✔
1112

1113
         tree_t s = tree_new(T_RETURN);
26✔
1114
         tree_set_loc(s, tree_loc(tree_result(e)));
26✔
1115
         tree_set_value(s, tree_result(e));
26✔
1116

1117
         tree_add_stmt(c, s);
26✔
1118
         tree_add_cond(new, c);
26✔
1119
      }
1120

1121
      return new;
1122
   }
1123

1124
   return t;
1125
}
1126

1127
static tree_t simp_cond_return(tree_t t)
3✔
1128
{
1129
   tree_t value = tree_value(t);
3✔
1130

1131
   bool folded;
3✔
1132
   if (folded_bool(tree_value(t), &folded)) {
3✔
1133
      if (folded) {
2✔
1134
         tree_t new = tree_new(T_RETURN);
1✔
1135
         tree_set_loc(new, tree_loc(t));
1✔
1136
         return new;
1✔
1137
      }
1138
      else
1139
         return NULL;
1140
   }
1141

1142
   // Replace with an if statement
1143
   tree_t new = tree_new(T_IF);
1✔
1144
   tree_set_loc(new, tree_loc(t));
1✔
1145

1146
   tree_t c = tree_new(T_COND_STMT);
1✔
1147
   tree_set_loc(c, tree_loc(t));
1✔
1148
   tree_set_value(c, value);
1✔
1149

1150
   tree_t s = tree_new(T_RETURN);
1✔
1151
   tree_set_loc(s, tree_loc(t));
1✔
1152

1153
   tree_add_stmt(c, s);
1✔
1154
   tree_add_cond(new, c);
1✔
1155

1156
   return new;
1✔
1157
}
1158

1159
static tree_t simp_literal(tree_t t)
149,201✔
1160
{
1161
   switch (tree_subkind(t)) {
149,201✔
1162
   case L_PHYSICAL:
6,265✔
1163
      // Rewrite in terms of the base unit
1164
      if (tree_has_ref(t)) {
6,265✔
1165
         tree_t decl = tree_ref(t);
5,748✔
1166
         int64_t base = assume_int(tree_value(decl));
5,748✔
1167

1168
         // TODO: check for overflow here
1169
         if (tree_ival(t) == 0)
5,748✔
1170
            tree_set_ival(t, tree_dval(t) * base);
968✔
1171
         else
1172
            tree_set_ival(t, tree_ival(t) * base);
4,780✔
1173

1174
         tree_set_ref(t, NULL);
5,748✔
1175
         tree_set_ident(t, tree_ident(decl));
5,748✔
1176
      }
1177
      return t;
1178

1179
   default:
1180
      return t;
1181
   }
1182
}
1183

1184
static tree_t simp_range(tree_t t)
46,017✔
1185
{
1186
   if (tree_subkind(t) != RANGE_EXPR)
46,017✔
1187
      return t;
1188

1189
   tree_t value = tree_value(t);
3,654✔
1190
   assert(tree_kind(value) == T_ATTR_REF);
3,654✔
1191

1192
   const attr_kind_t attr = tree_subkind(value);
3,654✔
1193
   assert(attr == ATTR_RANGE || attr == ATTR_REVERSE_RANGE);
3,654✔
1194

1195
   tree_t name = tree_name(value);
3,654✔
1196

1197
   type_t type = tree_type(name);
3,654✔
1198
   if (type_is_unconstrained(type))
3,654✔
1199
      return t;
1200

1201
   int dim = 0;
1,618✔
1202
   if (tree_params(value) > 0) {
1,618✔
1203
      int64_t ival;
172✔
1204
      if (!folded_int(tree_value(tree_param(value, 0)), &ival))
172✔
1205
         return t;
×
1206
      dim = ival - 1;
172✔
1207
   }
1208

1209
   if (attr == ATTR_REVERSE_RANGE) {
1,618✔
1210
      tree_t base_r = range_of(type, dim);
9✔
1211
      const range_kind_t base_kind = tree_subkind(base_r);
9✔
1212
      if (base_kind == RANGE_EXPR)
9✔
1213
         return t;
1214
      else {
1215
         tree_t rev = tree_new(T_RANGE);
3✔
1216
         tree_set_subkind(rev, base_kind ^ 1);
3✔
1217
         tree_set_loc(rev, tree_loc(t));
3✔
1218
         tree_set_type(rev, tree_type(t));
3✔
1219
         tree_set_left(rev, tree_right(base_r));
3✔
1220
         tree_set_right(rev, tree_left(base_r));
3✔
1221

1222
         return rev;
3✔
1223
      }
1224
   }
1225
   else
1226
      return range_of(type, dim);
1,609✔
1227
}
1228

1229
static tree_t simp_cond_expr(tree_t t)
90✔
1230
{
1231
   if (!tree_has_result(t))
90✔
1232
      return NULL;   // "unaffected" expression is redundant
1233
   else if (tree_has_value(t)) {
82✔
1234
      bool value_b;
59✔
1235
      if (folded_bool(tree_value(t), &value_b)) {
59✔
1236
         if (value_b) {
1✔
1237
            // Always true, remove the test
1238
            tree_set_value(t, NULL);
×
1239
            return t;
1✔
1240
         }
1241
         else {
1242
            // Always false, delete the condition
1243
            return NULL;
1244
         }
1245
      }
1246
   }
1247

1248
   return t;
1249
}
1250

1251
static tree_t simp_cond_value(tree_t t)
41✔
1252
{
1253
   tree_t c0 = tree_cond(t, 0);
41✔
1254
   if (!tree_has_value(c0)) {
41✔
1255
      // Always evaluates to "else" condition
1256
      return tree_result(c0);
1✔
1257
   }
1258

1259
   return t;
1260
}
1261

1262
static tree_t simp_hidden_decl(tree_t decl, simp_ctx_t *ctx)
1263
{
1264
   // Remove predefined operators which are hidden by explicitly defined
1265
   // operators in the same region
1266

1267
   const tree_flags_t flags = tree_flags(decl);
1268
   if ((flags & TREE_F_PREDEFINED) && (flags & TREE_F_HIDDEN))
1269
      return NULL;
1270

1271
   return decl;
1272
}
1273

1274
static void simp_generic_map(tree_t t, tree_t unit)
6,302✔
1275
{
1276
   switch (tree_kind(unit)) {
6,302✔
1277
   case T_CONFIGURATION:
245✔
1278
   case T_ARCH:
1279
      unit = tree_primary(unit);
245✔
1280
      break;
245✔
1281
   default:
1282
      break;
1283
   }
1284

1285
   const int ngenmaps = tree_genmaps(t);
6,302✔
1286
   const int ngenerics = tree_generics(unit);
6,302✔
1287

1288
   int last_pos = 0;
6,302✔
1289
   for (; last_pos < ngenmaps; last_pos++) {
9,643✔
1290
      if (tree_subkind(tree_genmap(t, last_pos)) != P_POS)
3,708✔
1291
         break;
1292
   }
1293

1294
   if (last_pos == ngenmaps && ngenmaps == ngenerics)
6,302✔
1295
      return;
5,863✔
1296

1297
   const tree_kind_t kind = tree_kind(t);
439✔
1298

1299
   SCOPED_A(tree_t) values = AINIT;
878✔
1300

1301
   for (int i = last_pos; i < ngenerics; i++) {
1,530✔
1302
      tree_t g = tree_generic(unit, i), value = NULL;
1,091✔
1303
      ident_t ident = tree_ident(g);
1,091✔
1304

1305
      for (int j = last_pos; j < ngenmaps; j++) {
4,508✔
1306
         tree_t mj = tree_genmap(t, j);
3,417✔
1307

1308
         if (tree_subkind(mj) == P_POS) {
3,417✔
1309
            // This was added by the parser or checker
1310
            if (tree_pos(mj) == i)
968✔
1311
               value = tree_value(mj);
189✔
1312
            continue;
968✔
1313
         }
1314

1315
         tree_t name = tree_name(mj);
2,449✔
1316
         tree_t ref = name_to_ref(name);
2,449✔
1317
         if (ref == NULL || tree_ident(ref) != ident)
2,449✔
1318
            continue;
1,750✔
1319

1320
         switch (tree_kind(name)) {
699✔
1321
         case T_REF:
688✔
1322
            assert(value == NULL);
688✔
1323
            value = tree_value(mj);
688✔
1324
            break;
688✔
1325

1326
         case T_ARRAY_REF:
11✔
1327
         case T_RECORD_REF:
1328
            {
1329
               tree_t a = tree_new(T_ASSOC);
11✔
1330
               tree_set_loc(a, tree_loc(mj));
11✔
1331
               tree_set_subkind(a, A_NAMED);
11✔
1332
               tree_set_value(a, tree_value(mj));
11✔
1333

1334
               if (tree_kind(name) == T_ARRAY_REF)
11✔
1335
                  tree_set_name(a, tree_value(tree_param(name, 0)));
9✔
1336
               else
1337
                  tree_set_name(a, make_ref(find_record_field(name)));
2✔
1338

1339
               if (value == NULL) {
11✔
1340
                  value = tree_new(T_AGGREGATE);
5✔
1341
                  tree_set_loc(value, tree_loc(mj));
5✔
1342
                  tree_set_type(value, tree_type(g));
5✔
1343
               }
1344
               else
1345
                  assert(tree_kind(value) == T_AGGREGATE);
6✔
1346

1347
               tree_add_assoc(value, a);
11✔
1348
            }
1349
            break;
11✔
1350

1351
         default:
×
1352
            fatal_at(tree_loc(name), "sorry, this form of generic map is not "
×
1353
                     "yet supported");
1354
            break;
3,417✔
1355
         }
1356
      }
1357

1358
      if (value == NULL) {
1,091✔
1359
         if (kind == T_BINDING || !tree_has_value(g)) {
209✔
1360
            value = tree_new(T_OPEN);
95✔
1361
            tree_set_loc(value, tree_loc(t));
95✔
1362
            tree_set_type(value, tree_type(g));
95✔
1363
         }
1364
         else
1365
            value = tree_value(g);
114✔
1366
      }
1367

1368
      APUSH(values, value);
1,091✔
1369
   }
1370

1371
   for (int i = 0; i < values.count; i++) {
1,530✔
1372
      tree_t m;
1,091✔
1373
      if (last_pos + i < ngenmaps)
1,091✔
1374
         m = tree_genmap(t, last_pos + i);
882✔
1375
      else {
1376
         m = tree_new(T_PARAM);
209✔
1377
         tree_add_genmap(t, m);
209✔
1378
      }
1379

1380
      tree_set_subkind(m, P_POS);
1,091✔
1381
      tree_set_pos(m, last_pos + i);
1,091✔
1382
      tree_set_value(m, values.items[i]);
1,091✔
1383
      tree_set_loc(m, tree_loc(values.items[i]));
1,091✔
1384
   }
1385

1386
   if (last_pos + values.count < ngenmaps)
439✔
1387
      tree_trim_genmaps(t, last_pos + values.count);
5✔
1388
}
1389

1390
static tree_t simp_tree(tree_t t, void *_ctx)
1,731,450✔
1391
{
1392
   simp_ctx_t *ctx = _ctx;
1,731,450✔
1393

1394
   switch (tree_kind(t)) {
1,731,450✔
1395
   case T_PROCESS:
11,648✔
1396
      return simp_process(t);
11,648✔
1397
   case T_ATTR_REF:
31,408✔
1398
      return simp_attr_ref(t, ctx);
31,408✔
1399
   case T_FCALL:
119,276✔
1400
   case T_PROT_FCALL:
1401
      return simp_fcall(t, ctx);
119,276✔
1402
   case T_PCALL:
13,042✔
1403
   case T_PROT_PCALL:
1404
      return simp_pcall(t, ctx);
13,042✔
1405
   case T_REF:
582,157✔
1406
      return simp_ref(t, ctx);
582,157✔
1407
   case T_IF:
11,782✔
1408
      return simp_if(t);
11,782✔
1409
   case T_CASE:
595✔
1410
   case T_CASE_GENERATE:
1411
      return simp_case(t);
595✔
1412
   case T_WHILE:
511✔
1413
      return simp_while(t);
511✔
1414
   case T_CONCURRENT:
2,535✔
1415
      return simp_concurrent(t);
2,535✔
1416
   case T_COND_ASSIGN:
1,505✔
1417
      return simp_cond_assign(t);
1,505✔
1418
   case T_SELECT:
38✔
1419
   case T_MATCH_SELECT:
1420
      return simp_select(t);
38✔
1421
   case T_WAIT:
10,085✔
1422
      return simp_wait(t);
10,085✔
1423
   case T_NULL:
1424
      return NULL;   // Delete it
1425
   case T_RECORD_REF:
9,412✔
1426
      return simp_record_ref(t, ctx);
9,412✔
1427
   case T_CONTEXT_REF:
9✔
1428
      return simp_context_ref(t, ctx);
9✔
1429
   case T_ASSERT:
23,020✔
1430
      return simp_assert(t);
23,020✔
1431
   case T_IF_GENERATE:
1,072✔
1432
      return simp_if_generate(t);
1,072✔
1433
   case T_SIGNAL_ASSIGN:
8,872✔
1434
      return simp_signal_assign(t);
8,872✔
1435
   case T_VAR_ASSIGN:
20,197✔
1436
      return simp_var_assign(t);
20,197✔
1437
   case T_RETURN:
15,854✔
1438
      return simp_return(t);
15,854✔
1439
   case T_COND_RETURN:
3✔
1440
      return simp_cond_return(t);
3✔
1441
   case T_TYPE_CONV:
3,004✔
1442
      return simp_type_conv(t, ctx);
3,004✔
1443
   case T_LITERAL:
149,201✔
1444
      return simp_literal(t);
149,201✔
1445
   case T_RANGE:
46,017✔
1446
      return simp_range(t);
46,017✔
1447
   case T_FUNC_DECL:
39,283✔
1448
   case T_PROC_DECL:
1449
   case T_GENERIC_DECL:
1450
      return simp_hidden_decl(t, ctx);
39,283✔
1451
   case T_INSTANCE:
4,015✔
1452
   case T_BINDING:
1453
   case T_PACKAGE_MAP:
1454
      simp_generic_map(t, tree_ref(t));
4,015✔
1455
      return t;
4,015✔
1456
   case T_BLOCK:
1,139✔
1457
      simp_generic_map(t, t);
1,139✔
1458
      return t;
1,139✔
1459
   case T_COND_STMT:
19,160✔
1460
      return simp_cond(t);
19,160✔
1461
   case T_COND_EXPR:
90✔
1462
      return simp_cond_expr(t);
90✔
1463
   case T_COND_VALUE:
41✔
1464
      return simp_cond_value(t);
41✔
1465
   case T_PACK_INST:
348✔
1466
   case T_FUNC_INST:
1467
   case T_PROC_INST:
1468
      simp_generic_map(t, t);
348✔
1469
      return t;
348✔
1470
   case T_PACKAGE:
919✔
1471
      if (!is_uninstantiated_package(t))
919✔
1472
         simp_generic_map(t, t);
800✔
1473
      return t;
1474
   default:
605,075✔
1475
      return t;
605,075✔
1476
   }
1477
}
1478

1479
static type_t simp_type(type_t type, void *__ctx)
675✔
1480
{
1481
   simp_ctx_t *ctx = __ctx;
675✔
1482

1483
   // Replace generic types with the concrete type from the generic map
1484

1485
   if (type_kind(type) != T_GENERIC)
675✔
1486
      return type;
1487

1488
   type_t map = NULL;
27✔
1489
   if (ctx->generics != NULL)
27✔
1490
      map = hash_get(ctx->generics, type);
18✔
1491

1492
   return map ?: type;
18✔
1493
}
1494

1495
static void simp_generics(tree_t t, simp_ctx_t *ctx)
1496
{
1497
   const int ngenerics = tree_generics(t);
1498
   for (int i = 0; i < ngenerics; i++) {
1499
      tree_t g = tree_generic(t, i);
1500

1501
      tree_t map = find_generic_map(t, i, g);
1502
      if (map == NULL)
1503
         continue;
1504

1505
      if (tree_kind(map) == T_OPEN)
1506
         map = tree_value(g);
1507

1508
      if (ctx->generics == NULL)
1509
         ctx->generics = hash_new(128);
1510

1511
      hash_put(ctx->generics, g, map);
1512
   }
1513
}
1514

1515
static void simp_pre_cb(tree_t t, void *__ctx)
1,676,940✔
1516
{
1517
   simp_ctx_t *ctx = __ctx;
1,676,940✔
1518

1519
   switch (tree_kind(t)) {
1,676,940✔
1520
   case T_BLOCK:
1,939✔
1521
   case T_PACKAGE:
1522
   case T_PACK_INST:
1523
   case T_FUNC_INST:
1524
   case T_PROC_INST:
1525
      if (tree_genmaps(t) > 0)
1,939✔
1526
         simp_generics(t, ctx);
359✔
1527
      break;
1528
   default:
1529
      break;
1530
   }
1531
}
1,676,940✔
1532

1533
void simplify_local(tree_t top, jit_t *jit, unit_registry_t *ur)
9,004✔
1534
{
1535
   simp_ctx_t ctx = {
9,004✔
1536
      .top       = top,
1537
      .jit       = jit,
1538
      .registry  = ur,
1539
      .eval_mask = TREE_F_LOCALLY_STATIC,
1540
   };
1541

1542
   tree_rewrite(top, simp_pre_cb, simp_tree, NULL, &ctx);
9,004✔
1543

1544
   if (ctx.generics)
9,004✔
1545
      hash_free(ctx.generics);
129✔
1546
}
9,004✔
1547

1548
void simplify_global(tree_t top, hash_t *generics, jit_t *jit,
8,131✔
1549
                     unit_registry_t *ur)
1550
{
1551
   simp_ctx_t ctx = {
8,131✔
1552
      .top       = top,
1553
      .jit       = jit,
1554
      .registry  = ur,
1555
      .eval_mask = TREE_F_LOCALLY_STATIC | TREE_F_GLOBALLY_STATIC,
1556
      .generics  = generics,
1557
   };
1558

1559
   type_rewrite_post_fn_t type_cb = NULL;
8,131✔
1560
   if (standard() >= STD_08)
8,131✔
1561
      type_cb = simp_type;
1,176✔
1562

1563
   tree_rewrite(top, simp_pre_cb, simp_tree, type_cb, &ctx);
8,131✔
1564

1565
   if (generics == NULL && ctx.generics != NULL)
8,128✔
1566
      hash_free(ctx.generics);
76✔
1567
}
8,128✔
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