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

nickg / nvc / 6500183523

12 Oct 2023 07:26PM UTC coverage: 91.164% (+0.03%) from 91.136%
6500183523

push

github

nickg
Add layout_of variant for signal types

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

48948 of 53692 relevant lines covered (91.16%)

590265.62 hits per line

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

93.6
/src/type.c
1
//
2
//  Copyright (C) 2011-2022  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 "type.h"
19
#include "tree.h"
20
#include "util.h"
21
#include "common.h"
22
#include "object.h"
23
#include "hash.h"
24

25
#include <assert.h>
26
#include <limits.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <ctype.h>
30
#include <float.h>
31

32
static const imask_t has_map[T_LAST_TYPE_KIND] = {
33
   // T_SUBTYPE
34
   (I_IDENT | I_BASE | I_RESOLUTION | I_CONSTR | I_ELEM),
35

36
   // T_INTEGER
37
   (I_IDENT | I_DIMS),
38

39
   // T_REAL
40
   (I_IDENT | I_DIMS),
41

42
   // T_ENUM
43
   (I_IDENT | I_LITERALS | I_DIMS),
44

45
   // T_PHYSICAL
46
   (I_IDENT | I_UNITS | I_DIMS),
47

48
   // T_ARRAY
49
   (I_IDENT | I_INDEXES | I_ELEM),
50

51
   // T_RECORD
52
   (I_IDENT | I_FIELDS),
53

54
   // T_FILE
55
   (I_IDENT | I_DESIGNATED),
56

57
   // T_ACCESS
58
   (I_IDENT | I_DESIGNATED),
59

60
   // T_FUNC
61
   (I_IDENT | I_PARAMS | I_RESULT),
62

63
   // T_INCOMPLETE
64
   (I_IDENT),
65

66
   // T_PROC
67
   (I_IDENT | I_PARAMS),
68

69
   // T_NONE
70
   (I_IDENT),
71

72
   // T_PROTECTED
73
   (I_IDENT | I_FIELDS),
74

75
   // T_GENERIC
76
   (I_IDENT | I_SUBKIND | I_DESIGNATED | I_INDEXES | I_ELEM),
77

78
   // T_VIEW
79
   (I_IDENT | I_DESIGNATED | I_FIELDS),
80
};
81

82
static const char *kind_text_map[T_LAST_TYPE_KIND] = {
83
   "T_SUBTYPE",    "T_INTEGER",   "T_REAL",       "T_ENUM",
84
   "T_PHYSICAL",   "T_ARRAY",     "T_RECORD",     "T_FILE",
85
   "T_ACCESS",     "T_FUNC",      "T_INCOMPLETE", "T_PROC",
86
   "T_NONE",       "T_PROTECTED", "T_GENERIC",    "T_VIEW",
87
};
88

89
static const change_allowed_t change_allowed[] = {
90
   { -1, -1 }
91
};
92

93
struct _type {
94
   object_t object;
95
};
96

97
struct _tree {
98
   object_t object;
99
};
100

101
object_class_t type_object = {
102
   .name           = "type",
103
   .change_allowed = change_allowed,
104
   .has_map        = has_map,
105
   .kind_text_map  = kind_text_map,
106
   .tag            = OBJECT_TAG_TYPE,
107
   .last_kind      = T_LAST_TYPE_KIND
108
};
109

110
extern object_arena_t *global_arena;
111

112
static inline tree_t tree_array_nth(item_t *item, unsigned n)
113
{
114
   object_t *o = obj_array_nth(item->obj_array, n);
115
   return container_of(o, struct _tree, object);
116
}
117

118
static inline void tree_array_add(item_t *item, tree_t t)
45,634✔
119
{
120
   obj_array_add(&(item->obj_array), &(t->object));
45,634✔
121
}
45,634✔
122

123
static inline type_t type_array_nth(item_t *item, unsigned n)
124
{
125
   object_t *o = obj_array_nth(item->obj_array, n);
126
   return container_of(o, struct _type, object);
127
}
128

129
static inline void type_array_add(item_t *item, type_t t)
91,108✔
130
{
131
   obj_array_add(&(item->obj_array), &(t->object));
91,108✔
132
}
91,108✔
133

134
type_t type_new(type_kind_t kind)
89,236✔
135
{
136
   object_t *o = object_new(NULL, &type_object, kind);
89,236✔
137
   return container_of(o, struct _type, object);
89,236✔
138
}
139

140
type_kind_t type_kind(type_t t)
9,947,370✔
141
{
142
   assert(t != NULL);
9,947,370✔
143
   return t->object.kind;
9,947,370✔
144
}
145

146
static inline type_t type_base_map(type_t t, hash_t *map)
1,412,210✔
147
{
148
   assert(t->object.kind == T_SUBTYPE);
1,412,210✔
149
   type_t base = type_base(t);
1,412,210✔
150
   if (map != NULL)
1,412,210✔
151
      return hash_get(map, base) ?: base;
197✔
152
   else
153
      return base;
154
}
155

156
static bool _type_eq(type_t a, type_t b, bool strict, hash_t *map)
29,128,600✔
157
{
158
   assert(a != NULL);
29,128,600✔
159
   assert(b != NULL);
29,128,600✔
160

161
   if (a == b)
29,128,600✔
162
      return true;
163

164
   type_kind_t kind_a = a->object.kind;
26,187,600✔
165
   type_kind_t kind_b = b->object.kind;
26,187,600✔
166

167
   if (map != NULL) {
26,187,600✔
168
      if (kind_a == T_GENERIC) {
14,362✔
169
         a = hash_get(map, a) ?: a;
7,231✔
170
         kind_a = a->object.kind;
7,231✔
171
      }
172

173
      if (kind_b == T_GENERIC) {
14,362✔
174
         b = hash_get(map, b) ?: b;
1,653✔
175
         kind_b = b->object.kind;
1,653✔
176
      }
177

178
      if (a == b)
14,362✔
179
         return true;
180
   }
181

182
   if (!strict) {
26,186,700✔
183
      // Subtypes are convertible to the base type
184
      while ((kind_a = a->object.kind) == T_SUBTYPE)
26,578,100✔
185
         a = type_base_map(a, map);
391,493✔
186
      while ((kind_b = b->object.kind) == T_SUBTYPE)
27,207,300✔
187
         b = type_base_map(b, map);
1,020,720✔
188

189
      if (a == b)
26,186,600✔
190
         return true;
191
   }
192

193
   const imask_t has = has_map[a->object.kind];
25,965,700✔
194

195
   if (!(has & I_PARAMS)) {
25,965,700✔
196
      ident_t ai = lookup_item(&type_object, a, I_IDENT)->ident;
21,718,600✔
197
      ident_t bi = lookup_item(&type_object, b, I_IDENT)->ident;
21,718,600✔
198

199
      if (ai != bi)
21,718,600✔
200
         return false;
201
   }
202

203
   if (kind_a == T_INCOMPLETE || kind_b == T_INCOMPLETE)
4,247,730✔
204
      return true;
205

206
   if (kind_a != kind_b)
4,247,330✔
207
      return false;
208

209
   if (kind_a == T_ARRAY)
4,025,950✔
210
      return _type_eq(type_elem(a), type_elem(b), strict, map);
×
211

212
   if (kind_a == T_ACCESS)
4,025,950✔
213
      return _type_eq(type_designated(a), type_designated(b), strict, map);
×
214

215
   if ((has & I_DIMS) && (type_dims(a) != type_dims(b)))
4,025,950✔
216
      return false;
217

218
   if (kind_a == T_FUNC) {
4,025,950✔
219
      if (!_type_eq(type_result(a), type_result(b), strict, map))
3,944,670✔
220
         return false;
221
   }
222

223
   if (has & I_PARAMS) {
1,546,670✔
224
      item_t *ap = lookup_item(&type_object, a, I_PARAMS);
1,546,460✔
225
      item_t *bp = lookup_item(&type_object, b, I_PARAMS);
1,546,460✔
226

227
      const int acount = obj_array_count(ap->obj_array);
1,546,460✔
228
      const int bcount = obj_array_count(bp->obj_array);
1,546,460✔
229

230
      if (acount != bcount)
1,546,460✔
231
         return false;
232

233
      for (int i = 0; i < acount; i++) {
1,600,130✔
234
         type_t ai = type_array_nth(ap, i);
1,573,590✔
235
         type_t bi = type_array_nth(bp, i);
1,573,590✔
236
         if (ai != bi && !_type_eq(ai, bi, strict, map))
1,573,590✔
237
            return false;
238
      }
239
   }
240

241
   return true;
242
}
243

244
bool type_strict_eq(type_t a, type_t b)
12,555✔
245
{
246
   return _type_eq(a, b, true, NULL);
12,555✔
247
}
248

249
bool type_eq(type_t a, type_t b)
23,387,800✔
250
{
251
   return _type_eq(a, b, false, NULL);
23,387,800✔
252
}
253

254
bool type_eq_map(type_t a, type_t b, hash_t *map)
367,614✔
255
{
256
   return _type_eq(a, b, false, map);
367,614✔
257
}
258

259
ident_t type_ident(type_t t)
228,032✔
260
{
261
   assert(t != NULL);
229,536✔
262

263
   item_t *item = lookup_item(&type_object, t, I_IDENT);
229,536✔
264
   if (item->ident == NULL) {
229,536✔
265
      switch (t->object.kind) {
1,531✔
266
      case T_SUBTYPE:
1,504✔
267
         return type_ident(type_base(t));
1,504✔
268
      case T_NONE:
27✔
269
         return ident_new("none");
27✔
270
      case T_GENERIC:
×
271
         return ident_new("anonymous");
×
272
      default:
×
273
         fatal_trace("type kind %s has no ident",
×
274
                     type_kind_str(t->object.kind));
275
      }
276
   }
277
   else
278
      return item->ident;
279
}
280

281
bool type_has_ident(type_t t)
47,661✔
282
{
283
   assert(t != NULL);
47,661✔
284
   return (lookup_item(&type_object, t, I_IDENT)->ident != NULL);
47,661✔
285
}
286

287
void type_set_ident(type_t t, ident_t id)
59,756✔
288
{
289
   assert(t != NULL);
59,756✔
290
   lookup_item(&type_object, t, I_IDENT)->ident = id;
59,756✔
291
}
59,756✔
292

293
unsigned type_dims(type_t t)
3,218✔
294
{
295
   item_t *item = lookup_item(&type_object, t, I_DIMS);
3,218✔
296
   return obj_array_count(item->obj_array);
3,218✔
297
}
298

299
tree_t type_dim(type_t t, unsigned n)
623,740✔
300
{
301
   item_t *item = lookup_item(&type_object, t, I_DIMS);
623,740✔
302
   return tree_array_nth(item, n);
623,740✔
303
}
304

305
void type_add_dim(type_t t, tree_t r)
563✔
306
{
307
   tree_array_add(lookup_item(&type_object, t, I_DIMS), r);
563✔
308
   object_write_barrier(&(t->object), &(r->object));
563✔
309
}
563✔
310

311
type_t type_base(type_t t)
10,142,200✔
312
{
313
   item_t *item = lookup_item(&type_object, t, I_BASE);
10,142,200✔
314
   assert(item->object != NULL);
10,142,200✔
315
   return container_of(item->object, struct _type, object);
10,142,200✔
316
}
317

318
void type_set_base(type_t t, type_t b)
37,980✔
319
{
320
   lookup_item(&type_object, t, I_BASE)->object = &(b->object);
37,980✔
321
   object_write_barrier(&(t->object), &(b->object));
37,980✔
322
}
37,980✔
323

324
type_t type_elem(type_t t)
1,150,010✔
325
{
326
   assert(t != NULL);
2,047,520✔
327

328
   if (t->object.kind == T_NONE)
2,047,520✔
329
      return t;
330
   else {
331
      item_t *item = lookup_item(&type_object, t, I_ELEM);
2,047,520✔
332
      if (t->object.kind == T_SUBTYPE && item->object == NULL)
2,047,520✔
333
         return type_elem(type_base(t));
897,505✔
334
      else {
335
         assert(item->object != NULL);
1,150,010✔
336
         return container_of(item->object, struct _type, object);
1,150,010✔
337
      }
338
   }
339
}
340

341
void type_set_elem(type_t t, type_t e)
2,568✔
342
{
343
   lookup_item(&type_object, t, I_ELEM)->object = &(e->object);
2,568✔
344
   object_write_barrier(&(t->object), &(e->object));
2,568✔
345
}
2,568✔
346

347
bool type_has_elem(type_t t)
10,660✔
348
{
349
   return lookup_item(&type_object, t, I_ELEM)->object != NULL;
10,660✔
350
}
351

352
unsigned type_subkind(type_t t)
2,616✔
353
{
354
   item_t *item = lookup_item(&type_object, t, I_SUBKIND);
2,616✔
355
   return item->ival;
2,616✔
356
}
357

358
void type_set_subkind(type_t t, unsigned sub)
134✔
359
{
360
   lookup_item(&type_object, t, I_SUBKIND)->ival = sub;
134✔
361
}
134✔
362

363
bool type_is_universal(type_t t)
3,137,400✔
364
{
365
   assert(t != NULL);
3,137,400✔
366

367
   switch (t->object.kind) {
3,137,400✔
368
   case T_INTEGER:
767,562✔
369
      return t == std_type(NULL, STD_UNIVERSAL_INTEGER);
767,562✔
370
   case T_REAL:
287,232✔
371
      return t == std_type(NULL, STD_UNIVERSAL_REAL);
287,232✔
372
   default:
373
      return false;
374
   }
375
}
376

377
unsigned type_units(type_t t)
3,647✔
378
{
379
   item_t *item = lookup_item(&type_object, t, I_UNITS);
3,647✔
380
   return obj_array_count(item->obj_array);
3,647✔
381
}
382

383
tree_t type_unit(type_t t, unsigned n)
28,562✔
384
{
385
   item_t *item = lookup_item(&type_object, t, I_UNITS);
28,562✔
386
   return tree_array_nth(item, n);
28,562✔
387
}
388

389
void type_add_unit(type_t t, tree_t u)
138✔
390
{
391
   tree_array_add(lookup_item(&type_object, t, I_UNITS), u);
138✔
392
   object_write_barrier(&(t->object), &(u->object));
138✔
393
}
138✔
394

395
unsigned type_enum_literals(type_t t)
491,301✔
396
{
397
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
491,301✔
398
   return obj_array_count(item->obj_array);
491,301✔
399
}
400

401
tree_t type_enum_literal(type_t t, unsigned n)
32,434,100✔
402
{
403
   item_t *item = lookup_item(&type_object, t, I_LITERALS);
32,434,100✔
404
   return tree_array_nth(item, n);
32,434,100✔
405
}
406

407
void type_enum_add_literal(type_t t, tree_t lit)
3,566✔
408
{
409
   assert(tree_kind(lit) == T_ENUM_LIT);
3,566✔
410
   tree_array_add(lookup_item(&type_object, t, I_LITERALS), lit);
3,566✔
411
   object_write_barrier(&(t->object), &(lit->object));
3,566✔
412
}
3,566✔
413

414
unsigned type_params(type_t t)
1,940✔
415
{
416
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
1,940✔
417
   return obj_array_count(item->obj_array);
1,940✔
418
}
419

420
type_t type_param(type_t t, unsigned n)
4,044✔
421
{
422
   item_t *item = lookup_item(&type_object, t, I_PARAMS);
4,044✔
423
   return type_array_nth(item, n);
4,044✔
424
}
425

426
void type_add_param(type_t t, type_t p)
88,360✔
427
{
428
   type_array_add(lookup_item(&type_object, t, I_PARAMS), p);
88,360✔
429
   object_write_barrier(&(t->object), &(p->object));
88,360✔
430
}
88,360✔
431

432
unsigned type_fields(type_t t)
62,667✔
433
{
434
   if (t->object.kind == T_SUBTYPE)
69,654✔
435
      return type_fields(type_base(t));
6,987✔
436
   else {
437
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
62,667✔
438
      return obj_array_count(item->obj_array);
62,667✔
439
   }
440
}
441

442
tree_t type_field(type_t t, unsigned n)
205,420✔
443
{
444
   if (t->object.kind == T_SUBTYPE)
221,840✔
445
      return type_field(type_base(t), n);
16,420✔
446
   else {
447
      item_t *item = lookup_item(&type_object, t, I_FIELDS);
205,420✔
448
      return tree_array_nth(item, n);
205,420✔
449
   }
450
}
451

452
void type_add_field(type_t t, tree_t p)
3,817✔
453
{
454
   tree_array_add(lookup_item(&type_object, t, I_FIELDS), p);
3,817✔
455
   object_write_barrier(&(t->object), &(p->object));
3,817✔
456
}
3,817✔
457

458
type_t type_result(type_t t)
9,665,650✔
459
{
460
   item_t *item = lookup_item(&type_object, t, I_RESULT);
9,665,650✔
461
   assert(item->object != NULL);
9,665,650✔
462
   return container_of(item->object, struct _type, object);
9,665,650✔
463
}
464

465
void type_set_result(type_t t, type_t r)
42,011✔
466
{
467
   lookup_item(&type_object, t, I_RESULT)->object = &(r->object);
42,011✔
468
   object_write_barrier(&(t->object), &(r->object));
42,011✔
469
}
42,011✔
470

471
unsigned type_indexes(type_t t)
1,095,100✔
472
{
473
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
1,095,100✔
474
   return obj_array_count(item->obj_array);
1,095,100✔
475
}
476

477
void type_add_index(type_t t, type_t sub)
2,748✔
478
{
479
   type_array_add(lookup_item(&type_object, t, I_INDEXES), sub);
2,748✔
480
   object_write_barrier(&(t->object), &(sub->object));
2,748✔
481
}
2,748✔
482

483
type_t type_index(type_t t, unsigned n)
190,937✔
484
{
485
   item_t *item = lookup_item(&type_object, t, I_INDEXES);
190,937✔
486
   return type_array_nth(item, n);
190,937✔
487
}
488

489
unsigned type_constraints(type_t t)
1,898,690✔
490
{
491
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
1,898,690✔
492
   return obj_array_count(item->obj_array);
1,898,690✔
493
}
494

495
void type_add_constraint(type_t t, tree_t c)
37,550✔
496
{
497
   assert(c->object.kind == T_CONSTRAINT);
37,550✔
498
   tree_array_add(lookup_item(&type_object, t, I_CONSTR), c);
37,550✔
499
   object_write_barrier(&(t->object), &(c->object));
37,550✔
500
}
37,550✔
501

502
tree_t type_constraint(type_t t, unsigned n)
2,856,790✔
503
{
504
   assert(n == 0);    // TODO: this list is largely redundant now
2,856,790✔
505
   item_t *item = lookup_item(&type_object, t, I_CONSTR);
2,856,790✔
506
   return tree_array_nth(item, n);
2,856,790✔
507
}
508

509
void type_set_resolution(type_t t, tree_t r)
329✔
510
{
511
   lookup_item(&type_object, t, I_RESOLUTION)->object = &(r->object);
329✔
512
   object_write_barrier(&(t->object), &(r->object));
329✔
513
}
329✔
514

515
bool type_has_resolution(type_t t)
23,233✔
516
{
517
   return lookup_item(&type_object, t, I_RESOLUTION)->object != NULL;
23,233✔
518
}
519

520
tree_t type_resolution(type_t t)
2,304✔
521
{
522
   item_t *item = lookup_item(&type_object, t, I_RESOLUTION);
2,304✔
523
   assert(item->object != NULL);
2,304✔
524
   return container_of(item->object, struct _tree, object);
2,304✔
525
}
526

527
type_t type_designated(type_t t)
9,883✔
528
{
529
   if (t->object.kind == T_SUBTYPE)
9,884✔
530
      return type_designated(type_base(t));
1✔
531
   else {
532
      item_t *item = lookup_item(&type_object, t, I_DESIGNATED);
9,883✔
533
      assert(item->object != NULL);
9,883✔
534
      return container_of(item->object, struct _type, object);
9,883✔
535
   }
536
}
537

538
void type_set_designated(type_t t, type_t d)
440✔
539
{
540
   lookup_item(&type_object, t, I_DESIGNATED)->object = &(d->object);
440✔
541
   object_write_barrier(&(t->object), &(d->object));
440✔
542
}
440✔
543

544
void type_signature(type_t t, text_buf_t *tb)
989✔
545
{
546
   assert(t->object.kind == T_FUNC || t->object.kind == T_PROC);
989✔
547

548
   tb_printf(tb, "[");
989✔
549
   const int nparams = type_params(t);
989✔
550
   for (int i = 0; i < nparams; i++)
2,383✔
551
      tb_printf(tb, "%s%s", (i == 0 ? "" : ", "),
1,922✔
552
                type_pp(type_param(t, i)));
553
   if (t->object.kind == T_FUNC)
989✔
554
      tb_printf(tb, "%sreturn %s", nparams > 0 ? " " : "",
612✔
555
                type_pp(type_result(t)));
556
   tb_printf(tb, "]");
989✔
557
}
989✔
558

559
const char *type_pp2(type_t t, type_t other)
6,069✔
560
{
561
   assert(t != NULL);
6,069✔
562

563
   switch (type_kind(t)) {
6,069✔
564
   case T_FUNC:
2,708✔
565
   case T_PROC:
566
      {
567
         static hash_t *cache = NULL;
2,708✔
568
         if (cache == NULL)
2,708✔
569
            cache = hash_new(64);
356✔
570

571
         text_buf_t *tb = hash_get(cache, t);
2,708✔
572
         if (tb == NULL) {
2,708✔
573
            tb = tb_new();
938✔
574
            hash_put(cache, t, tb);
938✔
575

576
            if (type_has_ident(t)) {
938✔
577
               tb_istr(tb, type_ident(t));
938✔
578
               tb_append(tb, ' ');
938✔
579
            }
580
            type_signature(t, tb);
938✔
581
         }
582

583
         return tb_get(tb);
2,708✔
584
      }
585

586
   case T_GENERIC:
204✔
587
      if (!type_has_ident(t))
204✔
588
         return "(an anonymous type)";
589
      // Fall-through
590

591
   default:
592
      {
593
         const char *full1 = istr(type_ident(t));
3,359✔
594
         const char *dot1  = strrchr(full1, '.');
3,359✔
595
         const char *tail1 = dot1 ? dot1 + 1 : full1;
3,359✔
596

597
         if (other != NULL) {
3,359✔
598
            const char *full2 = istr(type_ident(other));
82✔
599
            const char *dot2  = strrchr(full2, '.');
82✔
600
            const char *tail2 = dot2 ? dot2 + 1 : full2;
82✔
601

602
            return strcmp(tail1, tail2) ? tail1 : full1;
82✔
603
         }
604
         else
605
            return tail1;
606
      }
607
   }
608
}
609

610
const char *type_pp(type_t t)
5,987✔
611
{
612
   return type_pp2(t, NULL);
5,987✔
613
}
614

615
type_kind_t type_base_kind(type_t t)
28,422,300✔
616
{
617
   assert(t != NULL);
34,901,100✔
618
   if (t->object.kind == T_SUBTYPE)
34,901,100✔
619
      return type_base_kind(type_base(t));
6,478,800✔
620
   else
621
      return t->object.kind;
28,422,300✔
622
}
623

624
bool type_is_array(type_t t)
4,097,460✔
625
{
626
   const type_kind_t base = type_base_kind(t);
4,097,460✔
627
   if (base == T_GENERIC)
4,097,460✔
628
      return type_subkind(type_base_recur(t)) == GTYPE_ARRAY;
1,093✔
629
   else
630
      return base == T_ARRAY;
4,096,370✔
631
}
632

633
bool type_is_record(type_t t)
2,068,900✔
634
{
635
   return type_base_kind(t) == T_RECORD;
2,068,900✔
636
}
637

638
bool type_is_protected(type_t t)
117,845✔
639
{
640
   return type_base_kind(t) == T_PROTECTED;
117,845✔
641
}
642

643
bool type_is_file(type_t t)
102,666✔
644
{
645
   const type_kind_t base = type_base_kind(t);
102,666✔
646
   if (base == T_GENERIC)
102,666✔
647
      return type_subkind(type_base_recur(t)) == GTYPE_FILE;
188✔
648
   else
649
      return base == T_FILE;
102,478✔
650
}
651

652
bool type_is_access(type_t t)
196,796✔
653
{
654
   const type_kind_t base = type_base_kind(t);
196,796✔
655
   if (base == T_GENERIC)
196,796✔
656
      return type_subkind(type_base_recur(t)) == GTYPE_ACCESS;
386✔
657
   else
658
      return base == T_ACCESS;
196,410✔
659
}
660

661
bool type_is_incomplete(type_t t)
25,759✔
662
{
663
   return type_base_kind(t) == T_INCOMPLETE;
25,759✔
664
}
665

666
bool type_is_none(type_t t)
16,595,500✔
667
{
668
   return type_base_kind(t) == T_NONE;
16,595,500✔
669
}
670

671
bool type_is_valid(type_t t)
112✔
672
{
673
   return type_base_kind(t) != T_NONE;
112✔
674
}
675

676
tree_t type_constraint_for_field(type_t t, tree_t f)
6,255✔
677
{
678
   if (t->object.kind == T_SUBTYPE) {
6,277✔
679
      const int ncon = type_constraints(t);
5,351✔
680
      if (ncon > 0) {
5,351✔
681
         tree_t c = type_constraint(t, ncon - 1);
5,349✔
682

683
         if (tree_subkind(c) != C_RECORD)
5,349✔
684
            return NULL;
685

686
         const int nelem = tree_ranges(c);
5,349✔
687
         for (int i = 0; i < nelem; i++) {
7,514✔
688
            tree_t ei = tree_range(c, i);
7,494✔
689
            assert(tree_kind(ei) == T_ELEM_CONSTRAINT);
7,494✔
690

691
            if (tree_has_ref(ei) && tree_ref(ei) == f)
7,494✔
692
               return ei;
5,329✔
693
         }
694
      }
695

696
      return type_constraint_for_field(type_base(t), f);
22✔
697
   }
698
   else
699
      return NULL;
700
}
701

702
bool type_is_unconstrained(type_t t)
1,800,490✔
703
{
704
   assert(t != NULL);
1,800,490✔
705

706
   if (t->object.kind == T_SUBTYPE) {
1,800,490✔
707
      if (type_is_record(t)) {
936,573✔
708
         if (standard() >= STD_08) {
4,391✔
709
            const int nfields = type_fields(t);
3,328✔
710
            for (int i = 0; i < nfields; i++) {
9,103✔
711
               tree_t f = type_field(t, i);
5,780✔
712
               if (type_is_unconstrained(tree_type(f))
5,780✔
713
                   && type_constraint_for_field(t, f) == NULL)
3,930✔
714
                  return true;
715
            }
716
         }
717

718
         return false;
4,386✔
719
      }
720
      else if (type_is_array(t)) {
932,182✔
721
         if (standard() >= STD_08) {
843,772✔
722
            if (type_is_array(t)) {
240,587✔
723
               type_t elem = type_elem(t);
240,587✔
724
               if (type_is_unconstrained(elem))
240,587✔
725
                  return true;
726
            }
727
         }
728

729
         for (; t->object.kind == T_SUBTYPE; t = type_base(t)) {
857,822✔
730
            if (type_constraints(t) > 0) {
843,623✔
731
               tree_t c = type_constraint(t, 0);
829,769✔
732
               if (tree_subkind(c) == C_INDEX)
829,769✔
733
                  return false;
734
            }
735
         }
736

737
         assert(t->object.kind == T_ARRAY);
14,199✔
738
         return true;
739
      }
740
      else
741
         return false;
742
   }
743
   else if (t->object.kind == T_ARRAY)
863,913✔
744
      return true;
745
   else if (t->object.kind == T_GENERIC && type_subkind(t) == GTYPE_ARRAY)
461,776✔
746
      return true;
747
   else if (t->object.kind == T_RECORD && standard() >= STD_08) {
461,775✔
748
      const int nfields = type_fields(t);
6,273✔
749
      for (int i = 0; i < nfields; i++) {
20,829✔
750
         if (type_is_unconstrained(tree_type(type_field(t, i))))
15,923✔
751
            return true;
752
      }
753
      return false;
754
   }
755
   else
756
      return false;
455,502✔
757
}
758

759
bool type_is_enum(type_t t)
104,627✔
760
{
761
   return type_base_kind(t) == T_ENUM;
104,627✔
762
}
763

764
bool type_is_discrete(type_t t)
25,167✔
765
{
766
   const type_kind_t base = type_base_kind(t);
25,167✔
767
   if (base == T_GENERIC) {
25,167✔
768
      const gtype_class_t class = type_subkind(type_base_recur(t));
15✔
769
      return class == GTYPE_INTEGER || class == GTYPE_DISCRETE;
15✔
770
   }
771
   else
772
      return base == T_INTEGER || base == T_ENUM;
25,152✔
773
}
774

775
bool type_is_subprogram(type_t t)
1,008,370✔
776
{
777
   return t->object.kind == T_FUNC || t->object.kind == T_PROC;
1,008,370✔
778
}
779

780
bool type_is_physical(type_t t)
176✔
781
{
782
   const type_kind_t base = type_base_kind(t);
176✔
783
   if (base == T_GENERIC)
176✔
784
      return type_subkind(type_base_recur(t)) == GTYPE_PHYSICAL;
1✔
785
   else
786
      return base == T_PHYSICAL;
175✔
787
}
788

789
bool type_is_integer(type_t t)
97,844✔
790
{
791
   const type_kind_t base = type_base_kind(t);
97,844✔
792
   if (base == T_GENERIC)
97,844✔
793
      return type_subkind(type_base_recur(t)) == GTYPE_INTEGER;
2✔
794
   else
795
      return base == T_INTEGER;
97,842✔
796
}
797

798
bool type_is_real(type_t t)
19,199✔
799
{
800
   const type_kind_t base = type_base_kind(t);
19,199✔
801
   if (base == T_GENERIC)
19,199✔
802
      return type_subkind(type_base_recur(t)) == GTYPE_FLOATING;
2✔
803
   else
804
      return base == T_REAL;
19,197✔
805
}
806

807
bool type_is_generic(type_t t)
9,400✔
808
{
809
   return type_base_kind(t) == T_GENERIC;
9,400✔
810
}
811

812
bool type_is_scalar(type_t t)
821,114✔
813
{
814
   const type_kind_t base = type_base_kind(t);
821,114✔
815
   if (base == T_GENERIC) {
821,114✔
816
      const gtype_class_t class = type_subkind(type_base_recur(t));
133✔
817
      return class == GTYPE_SCALAR || class == GTYPE_DISCRETE
133✔
818
         || class == GTYPE_FLOATING || class == GTYPE_INTEGER;
262✔
819
   }
820
   else
821
      return base == T_INTEGER || base == T_REAL
820,981✔
822
         || base == T_ENUM || base == T_PHYSICAL || base == T_NONE;
820,981✔
823
}
824

825
bool type_is_representable(type_t t)
12,232✔
826
{
827
   if (type_is_scalar(t))
12,835✔
828
      return true;
829
   else if (standard() < STD_19)
5,639✔
830
      return false;
831
   else if (type_is_record(t)) {
1,058✔
832
      const int nfields = type_fields(t);
311✔
833
      for (int i = 0; i < nfields; i++) {
1,004✔
834
         if (!type_is_representable(tree_type(type_field(t, i))))
716✔
835
            return false;
836
      }
837

838
      return true;
839
   }
840
   else if (type_is_array(t))
747✔
841
      return type_is_representable(type_elem(t));
603✔
842
   else
843
      return false;
844
}
845

846
bool type_const_bounds(type_t t)
731,481✔
847
{
848
   if (type_is_unconstrained(t))
731,481✔
849
      return false;
850
   else if (type_is_record(t)) {
590,954✔
851
      const int nfields = type_fields(t);
18,730✔
852
      for (int i = 0; i < nfields; i++) {
79,725✔
853
         type_t ftype = tree_type(type_field(t, i));
62,221✔
854
         if (!type_const_bounds(ftype))
62,221✔
855
            return false;
856
      }
857

858
      return true;
859
   }
860
   else if (type_is_array(t)) {
572,224✔
861
      const int ndims = dimension_of(t);
324,900✔
862
      for (int i = 0; i < ndims; i++) {
585,818✔
863
         int64_t low, high;
347,840✔
864
         if (!folded_bounds(range_of(t, i), &low, &high))
347,840✔
865
            return false;
86,922✔
866
      }
867

868
      return type_const_bounds(type_elem(t));
237,978✔
869
   }
870
   else
871
      return true;
872
}
873

874
type_t type_base_recur(type_t t)
405,966✔
875
{
876
   assert(t != NULL);
405,966✔
877
   while (t->object.kind == T_SUBTYPE)
595,877✔
878
      t = type_base(t);
189,911✔
879
   return t;
405,966✔
880
}
881

882
const char *type_kind_str(type_kind_t t)
×
883
{
884
   assert(t < T_LAST_TYPE_KIND);
×
885
   return kind_text_map[t];
×
886
}
887

888
unsigned type_width(type_t type)
11,888✔
889
{
890
   if (type_is_array(type)) {
11,888✔
891
      const unsigned elem_w = type_width(type_elem(type));
×
892
      unsigned w = 1;
×
893
      const int ndims = dimension_of(type);
×
894
      for (int i = 0; i < ndims; i++) {
×
895
         int64_t low, high;
×
896
         range_bounds(range_of(type, i), &low, &high);
×
897
         w *= MAX(high - low + 1, 0);
×
898
      }
899
      return w * elem_w;
×
900
   }
901
   else if (type_is_record(type)) {
11,888✔
902
      type_t base = type_base_recur(type);
×
903
      unsigned w = 0;
×
904
      const int nfields = type_fields(base);
×
905
      for (int i = 0; i < nfields; i++)
×
906
         w += type_width(tree_type(type_field(base, i)));
×
907
      return w;
×
908
   }
909
   else
910
      return 1;
911
}
912

913
bool type_is_convertible_map(type_t from, type_t to, hash_t *map)
2,021,180✔
914
{
915
   // LRM 08 section 9.3.6 final paragraph lists rules for implicit
916
   // conversion from universal operands to other integer/real types.
917

918
   type_kind_t fromk = type_base_kind(from);
2,021,180✔
919
   type_kind_t tok   = type_base_kind(to);
2,021,180✔
920

921
   if (fromk == T_NONE)
2,021,180✔
922
      return true;  // Suppress cascading errors
923
   else if (!type_is_universal(from))
2,020,920✔
924
      return false;
925
   else if (type_is_universal(to))
311,388✔
926
      return false;
927
   else if (fromk == T_INTEGER && tok == T_INTEGER)
291,764✔
928
      return true;
929
   else if (fromk == T_REAL && tok == T_REAL)
186,778✔
930
      return true;
931
   else if (tok == T_GENERIC && map != NULL) {
147,819✔
932
      type_t to_map = hash_get(map, to);
54✔
933
      return to_map ? type_is_convertible_map(from, to_map, map) : false;
54✔
934
   }
935
   else if (tok == T_GENERIC) {
147,765✔
936
      // Handle VHDL-2019 anonymous type classes
937
      return (fromk == T_INTEGER && type_subkind(to) == GTYPE_INTEGER)
121✔
938
         || (fromk == T_REAL && type_subkind(to) == GTYPE_FLOATING);
351✔
939
   }
940
   else
941
      return false;
942
}
943

944
bool type_is_convertible(type_t from, type_t to)
1,954,300✔
945
{
946
   return type_is_convertible_map(from, to, NULL);
1,954,300✔
947
}
948

949
bool type_is_composite(type_t t)
67,288✔
950
{
951
   const type_kind_t base = type_base_kind(t);
67,288✔
952
   return base == T_ARRAY || base == T_RECORD;
67,288✔
953
}
954

955
bool type_is_homogeneous(type_t t)
109,309✔
956
{
957
   if (type_is_scalar(t))
153,413✔
958
      return true;
959
   else if (type_is_array(t))
54,284✔
960
      return type_is_homogeneous(type_elem(t));
44,104✔
961
   else
962
      return false;
963
}
964

965
bool type_is_resolved(type_t t)
53✔
966
{
967
   if (t->object.kind == T_SUBTYPE)
53✔
968
      return type_has_resolution(t) || type_is_resolved(type_base(t));
17✔
969
   else
970
      return false;
971
}
972

973
bool type_frozen(type_t t)
97✔
974
{
975
   return arena_frozen(object_arena(&(t->object)));
97✔
976
}
977

978
tree_t type_container(type_t t)
180✔
979
{
980
   object_t *o = arena_root(object_arena(&(t->object)));
180✔
981
   assert(o->tag == OBJECT_TAG_TREE);
180✔
982
   return container_of(o, struct _tree, object);
180✔
983
}
984

985
object_t *type_to_object(type_t t)
×
986
{
987
   return t ? &(t->object) : NULL;
×
988
}
989

990
type_t type_from_object(object_t *obj)
×
991
{
992
   assert(obj->tag == OBJECT_TAG_TYPE);
×
993
   return container_of(obj, struct _type, object);
×
994
}
995

996
int type_bit_width(type_t type)
8,663✔
997
{
998
   switch (type_kind(type)) {
20,394✔
999
   case T_INTEGER:
2,998✔
1000
   case T_PHYSICAL:
1001
      {
1002
         tree_t r = range_of(type, 0);
2,998✔
1003
         return bits_for_range(assume_int(tree_left(r)),
2,998✔
1004
                               assume_int(tree_right(r)));
1005
      }
1006

1007
   case T_REAL:
1008
       // All real types are doubles at the moment
1009
       return 64;
1010

1011
   case T_SUBTYPE:
7,353✔
1012
      return type_bit_width(type_base(type));
7,353✔
1013

1014
   case T_ENUM:
5,359✔
1015
      return bits_for_range(0, type_enum_literals(type) - 1);
5,359✔
1016

1017
   case T_ARRAY:
4,378✔
1018
      return type_bit_width(type_elem(type));
4,378✔
1019

1020
   default:
×
1021
      fatal_trace("unhandled type %s in type_bit_width", type_pp(type));
×
1022
   }
1023
}
1024

1025
int type_byte_width(type_t type)
8,663✔
1026
{
1027
   return (type_bit_width(type) + 7) / 8;
8,663✔
1028
}
1029

1030
bool type_is_character_array(type_t t)
41,828✔
1031
{
1032
   // LRM 93 section 3.1.1 an enumeration type is a character type if at
1033
   // least one of its enumeration literals is a character literal
1034

1035
   if (!type_is_array(t))
41,828✔
1036
      return false;
1037

1038
   if (dimension_of(t) != 1)
34,755✔
1039
      return false;
1040

1041
   type_t elem = type_base_recur(type_elem(t));
34,754✔
1042

1043
   if (!type_is_enum(elem))
34,754✔
1044
      return false;
1045

1046
   const int nlits = type_enum_literals(elem);
34,403✔
1047
   for (int i = 0; i < nlits; i++) {
485,885✔
1048
      tree_t lit = type_enum_literal(elem, i);
485,776✔
1049
      if (ident_char(tree_ident(lit), 0) == '\'')
485,776✔
1050
         return true;
1051
   }
1052

1053
   return false;
1054
}
1055

1056
bool type_matches_class(type_t t, gtype_class_t class)
151✔
1057
{
1058
   switch (class) {
151✔
1059
   case GTYPE_PRIVATE:
1060
      return true;
1061
   case GTYPE_SCALAR:
7✔
1062
      return type_is_scalar(t);
7✔
1063
   case GTYPE_DISCRETE:
5✔
1064
      return type_is_discrete(t);
5✔
1065
   case GTYPE_INTEGER:
5✔
1066
      return type_is_integer(t);
5✔
1067
   case GTYPE_FLOATING:
3✔
1068
      return type_is_real(t);
3✔
1069
   case GTYPE_PHYSICAL:
3✔
1070
      return type_is_physical(t);
3✔
1071
   case GTYPE_ACCESS:
5✔
1072
      return type_is_access(t);
5✔
1073
   case GTYPE_ARRAY:
7✔
1074
      return type_is_array(t);
7✔
1075
   case GTYPE_FILE:
5✔
1076
      return type_is_file(t);
5✔
1077
   default:
×
1078
      return false;
×
1079
   }
1080
}
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