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

nickg / nvc / 16099227452

06 Jul 2025 12:45PM UTC coverage: 92.335% (+0.05%) from 92.284%
16099227452

push

github

nickg
Handle underscores in Verilog decimal literals

Fixes #1230

18 of 20 new or added lines in 1 file covered. (90.0%)

598 existing lines in 16 files now uncovered.

71069 of 76969 relevant lines covered (92.33%)

564781.41 hits per line

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

89.95
/src/mir/mir-unit.c
1
//
2
//  Copyright (C) 2024-2025  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 "hash.h"
20
#include "ident.h"
21
#include "lib.h"
22
#include "mir/mir-node.h"
23
#include "mir/mir-priv.h"
24
#include "mir/mir-structs.h"
25
#include "mir/mir-unit.h"
26
#include "object.h"
27
#include "option.h"
28
#include "thread.h"
29

30
#include <assert.h>
31
#include <stdlib.h>
32

33
#define TYPE_TAB_SIZE 256
34

35
mir_context_t *mir_context_new(void)
10,326✔
36
{
37
   mir_context_t *mc = xcalloc(sizeof(mir_context_t));
10,326✔
38
   mc->map  = chash_new(32);
10,326✔
39
   mc->pool = pool_new();
10,326✔
40

41
   type_tab_t *tab =
10,326✔
42
      xcalloc_flex(sizeof(type_tab_t), TYPE_TAB_SIZE, sizeof(type_data_t));
10,326✔
43
   tab->max_types = TYPE_TAB_SIZE;
10,326✔
44
   tab->hashtab = xcalloc_array(TYPE_TAB_SIZE, sizeof(uint32_t));
10,326✔
45

46
   store_release(&mc->resizing, tab);
10,326✔
47
   store_release(&mc->typetab, tab);
10,326✔
48

49
   return mc;
10,326✔
50
}
51

52
static void mir_unit_free_memory(mir_unit_t *mu)
72,234✔
53
{
54
#ifdef DEBUG
55
   if (mu->comments != NULL)
72,234✔
56
      tb_free(mu->comments);
155✔
57
#endif
58

59
   for (int i = 0; i < mu->blocks.count; i++)
279,119✔
60
      free(mu->blocks.items[i].nodes);
206,885✔
61

62
   ACLEAR(mu->blocks);
72,234✔
63
   ACLEAR(mu->params);
72,234✔
64
   ACLEAR(mu->vars);
72,234✔
65
   ACLEAR(mu->stamps);
72,234✔
66
   ACLEAR(mu->linkage);
72,234✔
67
   ACLEAR(mu->extvars);
72,234✔
68

69
   pool_free(mu->pool);
72,234✔
70

71
   hash_free(mu->objmap);
72,234✔
72
   hash_free(mu->privmap);
72,234✔
73
   free(mu->nodes);
72,234✔
74
   free(mu->argspill);
72,234✔
75
   free(mu);
72,234✔
76
}
72,234✔
77

78
static void mir_free_unit_cb(const void *key, void *value)
244,208✔
79
{
80
   switch (pointer_tag(value)) {
244,208✔
81
   case UNIT_GENERATED:
57,176✔
82
      mir_unit_free_memory(untag_pointer(value, mir_unit_t));
57,176✔
83
      break;
57,176✔
84
   case UNIT_FREED:
1✔
85
      {
86
         mir_shape_t *s = untag_pointer(value, mir_shape_t);
1✔
87
         hash_free(s->objmap);
1✔
88
      }
89
      break;
1✔
90
   }
91
}
244,208✔
92

93
void mir_context_free(mir_context_t *mc)
10,302✔
94
{
95
   chash_iter(mc->map, mir_free_unit_cb);
10,302✔
96
   mir_free_types(mc->typetab);
10,302✔
97
   pool_free(mc->pool);
10,302✔
98
   chash_free(mc->map);
10,302✔
99
   free(mc);
10,302✔
100
}
10,302✔
101

102
mir_unit_t *mir_unit_new(mir_context_t *mc, ident_t name, object_t *object,
72,256✔
103
                         mir_unit_kind_t kind, mir_shape_t *parent)
104
{
105
   mir_unit_t *mu = xcalloc(sizeof(mir_unit_t));
72,256✔
106
   mu->context = mc;
72,256✔
107
   mu->name    = name;
72,256✔
108
   mu->object  = object;
72,256✔
109
   mu->kind    = kind;
72,256✔
110
   mu->parent  = parent;
72,256✔
111
   mu->result  = MIR_NULL_TYPE;
72,256✔
112

113
   mir_block_t entry = mir_add_block(mu);
72,256✔
114
   mir_set_cursor(mu, entry, MIR_APPEND);
72,256✔
115

116
   if (object != NULL)
72,256✔
117
      mir_set_loc(mu, &(object->loc));
72,236✔
118

119
   return mu;
72,256✔
120
}
121

122
mir_unit_kind_t mir_get_kind(mir_unit_t *mu)
415,823✔
123
{
124
   return mu->kind;
415,823✔
125
}
126

127
object_t *mir_get_object(mir_unit_t *mu)
71,490✔
128
{
129
   return mu->object;
71,490✔
130
}
131

132
ident_t mir_get_parent(mir_unit_t *mu)
980✔
133
{
134
   if (mu->parent != NULL)
980✔
135
      return mu->parent->name;
980✔
136
   else
137
      return NULL;
138
}
139

140
mir_context_t *mir_get_context(mir_unit_t *mu)
116✔
141
{
142
   return mu->context;
116✔
143
}
144

145
int mir_find_slot(mir_shape_t *shape, ident_t name)
261✔
146
{
147
   for (int i = 0; i < shape->num_slots; i++) {
588✔
148
      if (shape->slots[i].name == name)
588✔
149
         return i;
261✔
150
   }
151

152
   return -1;
153
}
154

155
ident_t mir_get_shape_parent(mir_shape_t *shape)
116✔
156
{
157
   return shape->parent ? shape->parent->name : NULL;
116✔
158
}
159

160
mir_value_t mir_search_object(mir_unit_t *mu, const void *obj, int *hops)
2,033✔
161
{
162
   *hops = 0;
2,033✔
163

164
   if (mu->objmap != NULL) {
2,033✔
165
      void *ptr = hash_get(mu->objmap, obj);
145✔
166
      if (ptr != NULL)
145✔
167
         return (mir_value_t){ .bits = (uintptr_t)ptr };
145✔
168
   }
169

170
   for (mir_shape_t *s = mu->parent; s != NULL; s = s->parent) {
1,888✔
171
      (*hops)++;
1,888✔
172
      if (s->objmap != NULL) {
1,888✔
173
         void *ptr = hash_get(s->objmap, obj);
1,888✔
174
         if (ptr != NULL) {
1,888✔
175
            mir_value_t value = { .bits = (uintptr_t)ptr };
1,888✔
176
            assert(value.tag == MIR_TAG_VAR);
1,888✔
177
            return value;
1,888✔
178
         }
179
      }
180
   }
181

UNCOV
182
   return MIR_NULL_VALUE;
×
183
}
184

185
void mir_put_object(mir_unit_t *mu, const void *obj, mir_value_t value)
747✔
186
{
187
   if (mu->objmap == NULL)
747✔
188
      mu->objmap = hash_new(16);
171✔
189

190
   hash_put(mu->objmap, obj, (void *)(uintptr_t)value.bits);
747✔
191
}
747✔
192

193
void *mir_get_priv(mir_unit_t *mu, const void *obj)
4,285✔
194
{
195
   if (mu->privmap == NULL)
4,285✔
196
      return NULL;
197
   else
198
      return hash_get(mu->privmap, obj);
1,021✔
199
}
200

201
void mir_put_priv(mir_unit_t *mu, const void *obj, void *value)
1,378✔
202
{
203
   if (mu->privmap == NULL)
1,378✔
204
      mu->privmap = hash_new(16);
1,067✔
205

206
   hash_put(mu->privmap, obj, value);
1,378✔
207
}
1,378✔
208

209
void *mir_malloc(mir_unit_t *mu, size_t size)
3,334✔
210
{
211
   if (mu->pool == NULL)
3,334✔
212
      mu->pool = pool_new();
1,511✔
213

214
   return pool_malloc(mu->pool, size);
3,334✔
215
}
216

217
void *mir_global_malloc(mir_context_t *mc, size_t fixed, size_t nelems,
209,602✔
218
                        size_t size)
219
{
220
   SCOPED_LOCK(mc->pool_mtx);
419,204✔
221
   return pool_malloc_flex(mc->pool, fixed, nelems, size);
209,602✔
222
}
223

224
static mir_shape_t *mir_build_shape(mir_unit_t *mu)
18,165✔
225
{
226
   mir_shape_t *sh = mir_global_malloc(mu->context, sizeof(mir_shape_t),
36,330✔
227
                                       mu->vars.count, sizeof(shape_slot_t));
18,165✔
228
   sh->name      = mu->name;
18,165✔
229
   sh->kind      = mu->kind;
18,165✔
230
   sh->type      = mir_self_type(mu);
18,165✔
231
   sh->num_slots = mu->vars.count;
18,165✔
232
   sh->parent    = mu->parent;
18,165✔
233
   sh->objmap    = mu->objmap;
18,165✔
234

235
   mu->objmap = NULL;   // Takes ownership
18,165✔
236

237
   for (int i = 0; i < mu->vars.count; i++) {
69,938✔
238
      const var_data_t *vd = &(mu->vars.items[i]);
51,773✔
239
      sh->slots[i].name    = vd->name;
51,773✔
240
      sh->slots[i].type    = vd->type;
51,773✔
241
      sh->slots[i].pointer = vd->pointer;
51,773✔
242
   }
243

244
   return sh;
18,165✔
245
}
246

247
void mir_unit_free(mir_unit_t *mu)
15,058✔
248
{
249
   if (mu->name != NULL) {
15,058✔
250
      void *ptr = chash_get(mu->context->map, mu->name);
21✔
251
      switch (pointer_tag(ptr)) {
21✔
252
      case UNIT_GENERATED:
1✔
253
         {
254
            mir_shape_t *sh = mu->shape ?: mir_build_shape(mu);
1✔
255
            chash_put(mu->context->map, mu->name, tag_pointer(sh, UNIT_FREED));
1✔
256
         }
257
         break;
1✔
UNCOV
258
      case UNIT_FREED:
×
259
      case UNIT_DEFERRED:
260
         should_not_reach_here();
261
      default:
262
         break;
263
      }
264
   }
265

266
   mir_unit_free_memory(mu);
15,058✔
267
}
15,058✔
268

269
void mir_put_unit(mir_context_t *mc, mir_unit_t *mu)
55,647✔
270
{
271
   assert(mu->context == mc);
55,647✔
272

273
#ifdef DEBUG
274
   void *ptr = chash_get(mc->map, mu->name);
55,647✔
275
   if (ptr != NULL)
55,647✔
276
      fatal_trace("%s already registered", istr(mu->name));
277
#endif
278

279
   if (opt_get_verbose(OPT_LOWER_VERBOSE, istr(mu->name))) {
55,647✔
UNCOV
280
      mir_set_cursor(mu, MIR_NULL_BLOCK, MIR_APPEND);
×
UNCOV
281
      mir_dump(mu);
×
282
   }
283

284
   chash_put(mc->map, mu->name, tag_pointer(mu, UNIT_GENERATED));
55,647✔
285
}
55,647✔
286

287
static mir_unit_t *mir_lazy_build(mir_context_t *mc, deferred_unit_t *du)
1,552✔
288
{
289
   mir_shape_t *parent = NULL;
1,552✔
290
   if (du->parent != NULL && (parent = mir_get_shape(mc, du->parent)) == NULL)
1,552✔
291
      fatal_trace("cannot get parent %s of unit %s", istr(du->parent),
292
                  istr(du->name));
293

294
   mir_unit_t *mu = mir_unit_new(mc, du->name, du->object, du->kind, parent);
1,552✔
295
   (*du->fn)(mu, du->object);
1,552✔
296

297
   if (opt_get_verbose(OPT_LOWER_VERBOSE, istr(du->name))) {
1,552✔
UNCOV
298
      mir_set_cursor(mu, MIR_NULL_BLOCK, MIR_APPEND);
×
UNCOV
299
      mir_dump(mu);
×
300
   }
301

302
   chash_put(mc->map, du->name, tag_pointer(mu, UNIT_GENERATED));
1,552✔
303
   return mu;
1,552✔
304
}
305

306
mir_unit_t *mir_get_unit(mir_context_t *mc, ident_t name)
103,862✔
307
{
308
   void *ptr = chash_get(mc->map, name);
103,862✔
309
   if (ptr == NULL)
103,862✔
310
      return NULL;
311

312
   switch (pointer_tag(ptr)) {
77,068✔
313
   case UNIT_DEFERRED:
1,552✔
314
      {
315
         deferred_unit_t *du = untag_pointer(ptr, deferred_unit_t);
1,552✔
316
         return mir_lazy_build(mc, du);
1,552✔
317
      }
318
   case UNIT_GENERATED:
75,516✔
319
      return untag_pointer(ptr, mir_unit_t);
75,516✔
UNCOV
320
   case UNIT_FREED:
×
321
      fatal_trace("unit %s has already been freed", istr(name));
UNCOV
322
   default:
×
323
      should_not_reach_here();
324
   }
325
}
326

327
mir_shape_t *mir_get_shape(mir_context_t *mc, ident_t name)
43,140✔
328
{
329
   void *ptr = chash_get(mc->map, name);
43,140✔
330
   if (ptr == NULL)
43,140✔
331
      return NULL;
332

333
   switch (pointer_tag(ptr)) {
43,023✔
UNCOV
334
   case UNIT_DEFERRED:
×
335
      {
UNCOV
336
         deferred_unit_t *du = untag_pointer(ptr, deferred_unit_t);
×
337
         mir_unit_t *mu = mir_lazy_build(mc, du);
×
UNCOV
338
         return (mu->shape = mir_build_shape(mu));
×
339
      }
340
   case UNIT_GENERATED:
43,022✔
341
      {
342
         mir_unit_t *mu = untag_pointer(ptr, mir_unit_t);
43,022✔
343
         if (mu->shape != NULL)
43,022✔
344
            return mu->shape;
345

346
         return (mu->shape = mir_build_shape(mu));
18,165✔
347
      }
348
   case UNIT_FREED:
1✔
349
      return untag_pointer(ptr, mir_shape_t);
1✔
UNCOV
350
   default:
×
351
      should_not_reach_here();
352
   }
353
}
354

355
void mir_defer(mir_context_t *mc, ident_t name, ident_t parent,
189,059✔
356
               mir_unit_kind_t kind, mir_lower_fn_t fn, object_t *object)
357
{
358
#ifdef DEBUG
359
   void *ptr = chash_get(mc->map, name);
189,059✔
360
   if (ptr != NULL) {
189,059✔
361
      switch (pointer_tag(ptr)) {
1✔
362
      case UNIT_DEFERRED:
1✔
363
         {
364
            deferred_unit_t *du = untag_pointer(ptr, deferred_unit_t);
1✔
365
            assert(du->fn == fn);
1✔
366
            assert(du->kind == kind);
1✔
367
            assert(du->object == object);
1✔
368
         }
369
         return;
370
      case UNIT_GENERATED:
×
371
         {
UNCOV
372
            mir_unit_t *mu = untag_pointer(ptr, mir_unit_t);
×
UNCOV
373
            assert(mu->kind == kind);
×
UNCOV
374
            assert(mu->object == object);
×
375
         }
376
         return;
UNCOV
377
      case UNIT_FREED:
×
378
         {
UNCOV
379
            mir_shape_t *s = untag_pointer(ptr, mir_shape_t);
×
UNCOV
380
            assert(s->kind == kind);
×
381
         }
382
         return;
UNCOV
383
      default:
×
384
         should_not_reach_here();
385
      }
386
   }
387
#endif
388

389
   deferred_unit_t *du = mir_global_malloc(mc, sizeof(deferred_unit_t), 0, 0);
189,058✔
390
   du->name   = name;
189,058✔
391
   du->fn     = fn;
189,058✔
392
   du->parent = parent;
189,058✔
393
   du->kind   = kind;
189,058✔
394
   du->object = object;
189,058✔
395

396
   chash_put(mc->map, name, tag_pointer(du, UNIT_DEFERRED));
189,058✔
397
}
398

399
unsigned mir_count_linkage(mir_unit_t *mu)
20,154✔
400
{
401
   return mu->linkage.count;
20,154✔
402
}
403

404
ident_t mir_get_linkage(mir_unit_t *mu, unsigned nth)
30,694✔
405
{
406
   return AGET(mu->linkage, nth);
30,694✔
407
}
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