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

nickg / nvc / 16629796914

30 Jul 2025 05:38PM UTC coverage: 92.406% (+0.007%) from 92.399%
16629796914

push

github

nickg
Adjust scheduling for Verilog blocking assignment

Fixes #1227

123 of 124 new or added lines in 4 files covered. (99.19%)

299 existing lines in 11 files now uncovered.

72172 of 78103 relevant lines covered (92.41%)

551595.6 hits per line

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

98.19
/src/vlog/vlog-node.c
1
//
2
//  Copyright (C) 2022-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 "vlog/vlog-node.h"
20
#include "vlog/vlog-number.h"
21
#include "object.h"
22

23
#include <string.h>
24
#include <inttypes.h>
25
#include <stdlib.h>
26

27
static const imask_t has_map[V_LAST_NODE_KIND] = {
28
   // V_MODULE
29
   (I_IDENT | I_PORTS | I_STMTS | I_DECLS | I_IDENT2),
30

31
   // V_PORT_DECL
32
   (I_IDENT | I_SUBKIND | I_IDENT2 | I_REF | I_RANGES | I_TYPE | I_VALUE),
33

34
   // V_REF
35
   (I_IDENT | I_REF),
36

37
   // V_ALWAYS
38
   (I_IDENT | I_SUBKIND | I_STMTS),
39

40
   // V_TIMING
41
   (I_VALUE | I_STMTS),
42

43
   // V_NBASSIGN
44
   (I_TARGET | I_VALUE | I_DELAY),
45

46
   // V_EVENT
47
   (I_SUBKIND | I_VALUE),
48

49
   // V_INITIAL
50
   (I_IDENT | I_STMTS),
51

52
   // V_BLOCK
53
   (I_IDENT | I_DECLS | I_STMTS),
54

55
   // V_SYS_TCALL
56
   (I_IDENT | I_PARAMS),
57

58
   // V_STRING
59
   (I_NUMBER),
60

61
   // V_NUMBER
62
   (I_NUMBER),
63

64
   // V_NET_DECL
65
   (I_IDENT | I_SUBKIND | I_TYPE | I_RANGES | I_VALUE),
66

67
   // V_ASSIGN
68
   (I_TARGET | I_VALUE | I_IDENT | I_DELAY),
69

70
   // V_DIMENSION
71
   (I_SUBKIND | I_LEFT | I_RIGHT),
72

73
   // V_IF
74
   (I_CONDS),
75

76
   // V_COND
77
   (I_VALUE | I_STMTS),
78

79
   // V_VAR_DECL
80
   (I_IDENT | I_TYPE | I_RANGES | I_VALUE),
81

82
   // V_DELAY_CONTROL
83
   (I_VALUE),
84

85
   // V_BINARY
86
   (I_LEFT | I_RIGHT | I_SUBKIND),
87

88
   // V_BASSIGN
89
   (I_TARGET | I_VALUE | I_SUBKIND | I_DELAY),
90

91
   // V_UNARY
92
   (I_VALUE | I_SUBKIND),
93

94
   // V_GATE_INST
95
   (I_SUBKIND | I_PARAMS | I_IDENT | I_REF | I_TARGET),
96

97
   // V_STRENGTH
98
   (I_SUBKIND),
99

100
   // V_MOD_INST
101
   (I_IDENT | I_PARAMS),
102

103
   // V_BIT_SELECT
104
   (I_VALUE | I_PARAMS),
105

106
   // V_SYS_FCALL
107
   (I_IDENT | I_PARAMS),
108

109
   // V_FOREVER
110
   (I_STMTS),
111

112
   // V_SPECIFY
113
   (I_DECLS),
114

115
   // V_PRIMITIVE
116
   (I_IDENT | I_IDENT2 | I_PORTS | I_DECLS | I_STMTS),
117

118
   // V_UDP_TABLE
119
   (I_IDENT | I_PARAMS | I_SUBKIND | I_STMTS),
120

121
   // V_UDP_ENTRY
122
   (I_PARAMS),
123

124
   // V_DATA_TYPE
125
   (I_SUBKIND | I_RANGES),
126

127
   // V_TYPE_DECL
128
   (I_IDENT | I_TYPE),
129

130
   // V_ENUM_DECL
131
   (I_IDENT | I_TYPE | I_RANGES | I_DECLS),
132

133
   // V_ENUM_NAME
134
   (I_IDENT | I_TYPE),
135

136
   // V_UNION_DECL
137
   (I_IDENT | I_DECLS),
138

139
   // V_STRUCT_DECL
140
   (I_IDENT | I_DECLS),
141

142
   // V_EVENT_CONTROL
143
   (I_PARAMS),
144

145
   // V_EMPTY
146
   (0),
147

148
   // V_REPEAT
149
   (I_VALUE | I_STMTS),
150

151
   // V_WHILE
152
   (I_VALUE | I_STMTS),
153

154
   // V_DO_WHILE
155
   (I_VALUE | I_STMTS),
156

157
   // V_TASK_DECL
158
   (I_IDENT | I_STMTS | I_DECLS | I_PORTS),
159

160
   // V_FUNC_DECL
161
   (I_IDENT | I_STMTS | I_DECLS | I_TYPE | I_PORTS),
162

163
   // V_WAIT
164
   (I_VALUE | I_STMTS),
165

166
   // V_PARAM_DECL
167
   (I_IDENT | I_VALUE | I_TYPE),
168

169
   // V_COND_EXPR
170
   (I_VALUE | I_LEFT | I_RIGHT),
171

172
   // V_REAL
173
   (I_DVAL),
174

175
   // V_CONCAT
176
   (I_PARAMS | I_VALUE),
177

178
   // V_FOR_LOOP
179
   (I_LEFT | I_VALUE | I_RIGHT | I_STMTS),
180

181
   // V_FOR_INIT
182
   (I_DECLS | I_STMTS),
183

184
   // V_FOR_STEP
185
   (I_STMTS),
186

187
   // V_PREFIX
188
   (I_TARGET | I_SUBKIND),
189

190
   // V_POSTFIX
191
   (I_TARGET | I_SUBKIND),
192

193
   // V_LOCALPARAM
194
   (I_IDENT | I_VALUE | I_TYPE),
195

196
   // V_CASE
197
   (I_SUBKIND | I_VALUE | I_STMTS),
198

199
   // V_CASE_ITEM
200
   (I_PARAMS | I_STMTS),
201

202
   // V_INST_LIST
203
   (I_PARAMS | I_STMTS | I_IDENT),
204

205
   // V_PARAM_ASSIGN
206
   (I_IDENT | I_VALUE),
207

208
   // V_INST_BODY
209
   (I_IDENT | I_IDENT2 | I_PORTS | I_STMTS | I_DECLS),
210

211
   // V_PORT_CONN
212
   (I_IDENT | I_VALUE),
213

214
   // V_PART_SELECT
215
   (I_SUBKIND | I_VALUE | I_LEFT | I_RIGHT),
216

217
   // V_IF_GENERATE
218
   (I_CONDS),
219

220
   // V_EVENT_TRIGGER
221
   (I_IDENT),
222

223
   // V_USER_FCALL
224
   (I_IDENT | I_REF | I_PARAMS),
225

226
   // V_UDP_LEVEL
227
   (I_SUBKIND | I_IVAL),
228

229
   // V_UDP_EDGE
230
   (I_SUBKIND | I_LEFT | I_RIGHT),
231

232
   // V_SPECPARAM
233
   (I_IDENT | I_VALUE),
234

235
   // V_FORK
236
   (I_IDENT | I_DECLS | I_STMTS),
237

238
   // V_ATTR_INST
239
   (0),
240

241
   // V_USER_TCALL
242
   (I_IDENT | I_REF | I_PARAMS),
243

244
   // V_VOID_CALL
245
   (I_VALUE),
246

247
   // V_GENVAR_DECL
248
   (I_IDENT),
249

250
   // V_FOR_GENERATE
251
   (I_LEFT | I_VALUE | I_RIGHT | I_STMTS),
252

253
   // V_DEASSIGN
254
   (I_TARGET),
255

256
   // V_FORCE
257
   (I_TARGET | I_VALUE),
258

259
   // V_RELEASE
260
   (I_TARGET | I_VALUE),
261

262
   // V_DISABLE
263
   (I_IDENT),
264

265
   // V_HIER_REF
266
   (I_IDENT | I_IDENT2 | I_REF),
267
};
268

269
static const char *kind_text_map[V_LAST_NODE_KIND] = {
270
   "V_MODULE",        "V_PORT_DECL",   "V_REF",           "V_ALWAYS",
271
   "V_TIMING",        "V_NBASSIGN",    "V_EVENT",         "V_INITIAL",
272
   "V_BLOCK",         "V_SYS_TCALL",   "V_STRING",        "V_NUMBER",
273
   "V_NET_DECL",      "V_ASSIGN",      "V_DIMENSION",     "V_IF",
274
   "V_COND",          "V_VAR_DECL",    "V_DELAY_CONTROL", "V_BINARY",
275
   "V_BASSIGN",       "V_UNARY",       "V_GATE_INST",     "V_STRENGTH",
276
   "V_MOD_INST",      "V_BIT_SELECT",  "V_SYS_FCALL",     "V_FOREVER",
277
   "V_SPECIFY",       "V_PRIMITIVE",   "V_UDP_TABLE",     "V_UDP_ENTRY",
278
   "V_DATA_TYPE",     "V_TYPE_DECL",   "V_ENUM_DECL",     "V_ENUM_NAME",
279
   "V_UNION_DECL",    "V_STRUCT_DECL", "V_EVENT_CONTROL", "V_EMPTY",
280
   "V_REPEAT",        "V_WHILE",       "V_DO_WHILE",      "V_TASK_DECL",
281
   "V_FUNC_DECL",     "V_WAIT",        "V_PARAM_DECL",    "V_COND_EXPR",
282
   "V_REAL",          "V_CONCAT",      "V_FOR_LOOP",      "V_FOR_INIT",
283
   "V_FOR_STEP",      "V_PREFIX",      "V_POSTFIX",       "V_LOCALPARAM",
284
   "V_CASE",          "V_CASE_ITEM",   "V_INST_LIST",     "V_PARAM_ASSIGN",
285
   "V_INST_BODY",     "V_PORT_CONN",   "V_PART_SELECT",   "V_IF_GENERATE",
286
   "V_EVENT_TRIGGER", "V_USER_FCALL",  "V_UDP_LEVEL",     "V_UDP_EDGE",
287
   "V_SPECPARAM",     "V_FORK",        "V_ATTR_INST",     "V_USER_TCALL",
288
   "V_VOID_CALL",     "V_GENVAR_DECL", "V_FOR_GENERATE",  "V_DEASSIGN",
289
   "V_FORCE",         "V_RELEASE",     "V_DISABLE",       "V_HIER_REF",
290
};
291

292
static const change_allowed_t change_allowed[] = {
293
   { -1, -1 }
294
};
295

296
object_class_t vlog_object = {
297
   .name           = "vlog",
298
   .change_allowed = change_allowed,
299
   .has_map        = has_map,
300
   .kind_text_map  = kind_text_map,
301
   .tag            = OBJECT_TAG_VLOG,
302
   .last_kind      = V_LAST_NODE_KIND,
303
   .has_loc        = true,
304
   .gc_roots       = { V_MODULE, V_PRIMITIVE },
305
   .gc_num_roots   = 2
306
};
307

308
struct _vlog_node {
309
   object_t object;
310
};
311

312
static inline vlog_node_t vlog_array_nth(item_t *item, unsigned n)
16,382✔
313
{
314
   object_t *o = obj_array_nth(item->obj_array, n);
16,382✔
315
   return container_of(o, struct _vlog_node, object);
16,382✔
316
}
317

318
static inline void vlog_array_add(item_t *item, vlog_node_t v)
9,654✔
319
{
320
   obj_array_add(&(item->obj_array), &(v->object));
9,654✔
321
}
9,654✔
322

323
vlog_node_t vlog_new(vlog_kind_t kind)
15,649✔
324
{
325
   object_t *o = object_new(NULL, &vlog_object, kind);
15,649✔
326
   return container_of(o, struct _vlog_node, object);
15,649✔
327
}
328

329
vlog_kind_t vlog_kind(vlog_node_t v)
110,888✔
330
{
331
   return v->object.kind;
110,888✔
332
}
333

UNCOV
334
const char *vlog_kind_str(vlog_kind_t kind)
×
335
{
UNCOV
336
   return kind_text_map[kind];
×
337
}
338

339
ident_t vlog_ident(vlog_node_t v)
10,678✔
340
{
341
   item_t *item = lookup_item(&vlog_object, v, I_IDENT);
10,678✔
342
   assert(item->ident != NULL);
10,678✔
343
   return item->ident;
10,678✔
344
}
345

346
void vlog_set_ident(vlog_node_t v, ident_t i)
6,644✔
347
{
348
   lookup_item(&vlog_object, v, I_IDENT)->ident = i;
6,644✔
349
}
6,644✔
350

351
bool vlog_has_ident(vlog_node_t v)
80✔
352
{
353
   return lookup_item(&vlog_object, v, I_IDENT)->ident != NULL;
80✔
354
}
355

356
ident_t vlog_ident2(vlog_node_t v)
867✔
357
{
358
   item_t *item = lookup_item(&vlog_object, v, I_IDENT2);
867✔
359
   assert(item->ident != NULL);
867✔
360
   return item->ident;
867✔
361
}
362

363
void vlog_set_ident2(vlog_node_t v, ident_t i)
824✔
364
{
365
   lookup_item(&vlog_object, v, I_IDENT2)->ident = i;
824✔
366
}
824✔
367

368
const loc_t *vlog_loc(vlog_node_t v)
14,470✔
369
{
370
   assert(v != NULL);
14,470✔
371
   return &(v->object.loc);
14,470✔
372
}
373

374
void vlog_set_loc(vlog_node_t v, const loc_t *loc)
16,589✔
375
{
376
   assert(v != NULL);
16,589✔
377
   assert(loc != NULL);
16,589✔
378
   v->object.loc = *loc;
16,589✔
379
}
16,589✔
380

381
vlog_node_t vlog_ref(vlog_node_t v)
12,161✔
382
{
383
   item_t *item = lookup_item(&vlog_object, v, I_REF);
12,161✔
384
   assert(item->object != NULL);
12,161✔
385
   return container_of(item->object, struct _vlog_node, object);
12,161✔
386
}
387

388
bool vlog_has_ref(vlog_node_t v)
6,719✔
389
{
390
   return lookup_item(&vlog_object, v, I_REF)->object != NULL;
6,719✔
391
}
392

393
void vlog_set_ref(vlog_node_t v, vlog_node_t d)
3,024✔
394
{
395
   lookup_item(&vlog_object, v, I_REF)->object = &(d->object);
3,024✔
396
   object_write_barrier(&(v->object), &(d->object));
3,024✔
397
}
3,024✔
398

399
unsigned vlog_stmts(vlog_node_t v)
2,148✔
400
{
401
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
2,148✔
402
   return obj_array_count(item->obj_array);
2,148✔
403
}
404

405
vlog_node_t vlog_stmt(vlog_node_t v, unsigned n)
4,256✔
406
{
407
   item_t *item = lookup_item(&vlog_object, v, I_STMTS);
4,256✔
408
   return vlog_array_nth(item, n);
4,256✔
409
}
410

411
void vlog_add_stmt(vlog_node_t v, vlog_node_t s)
4,224✔
412
{
413
   assert(s != NULL);
4,224✔
414
   vlog_array_add(lookup_item(&vlog_object, v, I_STMTS), s);
4,224✔
415
   object_write_barrier(&(v->object), &(s->object));
4,224✔
416
}
4,224✔
417

418
unsigned vlog_ports(vlog_node_t v)
925✔
419
{
420
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
925✔
421
   return obj_array_count(item->obj_array);
925✔
422
}
423

424
vlog_node_t vlog_port(vlog_node_t v, unsigned n)
1,478✔
425
{
426
   item_t *item = lookup_item(&vlog_object, v, I_PORTS);
1,478✔
427
   return vlog_array_nth(item, n);
1,478✔
428
}
429

430
void vlog_add_port(vlog_node_t v, vlog_node_t p)
452✔
431
{
432
   assert(p != NULL);
452✔
433
   assert(p->object.kind == V_REF || p->object.kind == V_PORT_DECL);
452✔
434
   vlog_array_add(lookup_item(&vlog_object, v, I_PORTS), p);
452✔
435
   object_write_barrier(&(v->object), &(p->object));
452✔
436
}
452✔
437

438
unsigned vlog_params(vlog_node_t v)
2,707✔
439
{
440
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
2,707✔
441
   return obj_array_count(item->obj_array);
2,707✔
442
}
443

444
vlog_node_t vlog_param(vlog_node_t v, unsigned n)
3,518✔
445
{
446
   item_t *item = lookup_item(&vlog_object, v, I_PARAMS);
3,518✔
447
   return vlog_array_nth(item, n);
3,518✔
448
}
449

450
void vlog_add_param(vlog_node_t v, vlog_node_t p)
2,407✔
451
{
452
   assert(p != NULL);
2,407✔
453
   vlog_array_add(lookup_item(&vlog_object, v, I_PARAMS), p);
2,407✔
454
   object_write_barrier(&(v->object), &(p->object));
2,407✔
455
}
2,407✔
456

457
unsigned vlog_ranges(vlog_node_t v)
4,983✔
458
{
459
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
4,983✔
460
   return obj_array_count(item->obj_array);
4,983✔
461
}
462

463
vlog_node_t vlog_range(vlog_node_t v, unsigned n)
1,965✔
464
{
465
   item_t *item = lookup_item(&vlog_object, v, I_RANGES);
1,965✔
466
   return vlog_array_nth(item, n);
1,965✔
467
}
468

469
void vlog_add_range(vlog_node_t v, vlog_node_t r)
234✔
470
{
471
   assert(r != NULL);
234✔
472
   assert(r->object.kind == V_DIMENSION);
234✔
473
   vlog_array_add(lookup_item(&vlog_object, v, I_RANGES), r);
234✔
474
   object_write_barrier(&(v->object), &(r->object));
234✔
475
}
234✔
476

477
unsigned vlog_decls(vlog_node_t v)
902✔
478
{
479
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
902✔
480
   return obj_array_count(item->obj_array);
902✔
481
}
482

483
vlog_node_t vlog_decl(vlog_node_t v, unsigned n)
4,675✔
484
{
485
   item_t *item = lookup_item(&vlog_object, v, I_DECLS);
4,675✔
486
   return vlog_array_nth(item, n);
4,675✔
487
}
488

489
void vlog_add_decl(vlog_node_t v, vlog_node_t d)
1,930✔
490
{
491
   assert(d != NULL);
1,930✔
492
   vlog_array_add(lookup_item(&vlog_object, v, I_DECLS), d);
1,930✔
493
   object_write_barrier(&(v->object), &(d->object));
1,930✔
494
}
1,930✔
495

496
unsigned vlog_conds(vlog_node_t v)
384✔
497
{
498
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
384✔
499
   return obj_array_count(item->obj_array);
384✔
500
}
501

502
vlog_node_t vlog_cond(vlog_node_t v, unsigned n)
490✔
503
{
504
   item_t *item = lookup_item(&vlog_object, v, I_CONDS);
490✔
505
   return vlog_array_nth(item, n);
490✔
506
}
507

508
void vlog_add_cond(vlog_node_t v, vlog_node_t c)
407✔
509
{
510
   assert(c != NULL && c->object.kind == V_COND);
407✔
511
   vlog_array_add(lookup_item(&vlog_object, v, I_CONDS), c);
407✔
512
   object_write_barrier(&(v->object), &(c->object));
407✔
513
}
407✔
514

515
unsigned vlog_subkind(vlog_node_t v)
2,649✔
516
{
517
   return lookup_item(&vlog_object, v, I_SUBKIND)->ival;
2,649✔
518
}
519

520
void vlog_set_subkind(vlog_node_t v, unsigned sub)
3,308✔
521
{
522
   lookup_item(&vlog_object, v, I_SUBKIND)->ival = sub;
3,308✔
523
}
3,308✔
524

525
vlog_node_t vlog_value(vlog_node_t v)
3,644✔
526
{
527
   item_t *item = lookup_item(&vlog_object, v, I_VALUE);
3,644✔
528
   assert(item->object != NULL);
3,644✔
529
   return container_of(item->object, struct _vlog_node, object);
3,644✔
530
}
531

532
bool vlog_has_value(vlog_node_t v)
1,540✔
533
{
534
   return lookup_item(&vlog_object, v, I_VALUE)->object != NULL;
1,540✔
535
}
536

537
void vlog_set_value(vlog_node_t v, vlog_node_t e)
2,760✔
538
{
539
   lookup_item(&vlog_object, v, I_VALUE)->object = &(e->object);
2,760✔
540
   object_write_barrier(&(v->object), &(e->object));
2,760✔
541
}
2,760✔
542

543
vlog_node_t vlog_target(vlog_node_t v)
1,979✔
544
{
545
   item_t *item = lookup_item(&vlog_object, v, I_TARGET);
1,979✔
546
   assert(item->object != NULL);
1,979✔
547
   return container_of(item->object, struct _vlog_node, object);
1,979✔
548
}
549

550
void vlog_set_target(vlog_node_t v, vlog_node_t e)
980✔
551
{
552
   lookup_item(&vlog_object, v, I_TARGET)->object = &(e->object);
980✔
553
   object_write_barrier(&(v->object), &(e->object));
980✔
554
}
980✔
555

556
vlog_node_t vlog_delay(vlog_node_t v)
50✔
557
{
558
   item_t *item = lookup_item(&vlog_object, v, I_DELAY);
50✔
559
   assert(item->object != NULL);
50✔
560
   return container_of(item->object, struct _vlog_node, object);
50✔
561
}
562

563
bool vlog_has_delay(vlog_node_t v)
798✔
564
{
565
   return lookup_item(&vlog_object, v, I_DELAY)->object != NULL;
798✔
566
}
567

568
void vlog_set_delay(vlog_node_t v, vlog_node_t d)
50✔
569
{
570
   lookup_item(&vlog_object, v, I_DELAY)->object = &(d->object);
50✔
571
   object_write_barrier(&(v->object), &(d->object));
50✔
572
}
50✔
573

574
vlog_node_t vlog_type(vlog_node_t v)
4,510✔
575
{
576
   item_t *item = lookup_item(&vlog_object, v, I_TYPE);
4,510✔
577
   assert(item->object != NULL);
4,510✔
578
   return container_of(item->object, struct _vlog_node, object);
4,510✔
579
}
580

UNCOV
581
bool vlog_has_type(vlog_node_t v)
×
582
{
UNCOV
583
   return lookup_item(&vlog_object, v, I_TYPE)->object != NULL;
×
584
}
585

586
void vlog_set_type(vlog_node_t v, vlog_node_t t)
1,121✔
587
{
588
   lookup_item(&vlog_object, v, I_TYPE)->object = &(t->object);
1,121✔
589
   object_write_barrier(&(v->object), &(t->object));
1,121✔
590
}
1,121✔
591

592
number_t vlog_number(vlog_node_t v)
7,161✔
593
{
594
   return lookup_item(&vlog_object, v, I_NUMBER)->number;
7,161✔
595
}
596

597
void vlog_set_number(vlog_node_t v, number_t n)
3,046✔
598
{
599
   lookup_item(&vlog_object, v, I_NUMBER)->number = n;
3,046✔
600
}
3,046✔
601

602
vlog_node_t vlog_left(vlog_node_t v)
3,784✔
603
{
604
   item_t *item = lookup_item(&vlog_object, v, I_LEFT);
3,784✔
605
   assert(item->object != NULL);
3,784✔
606
   return container_of(item->object, struct _vlog_node, object);
3,784✔
607
}
608

609
void vlog_set_left(vlog_node_t v, vlog_node_t e)
961✔
610
{
611
   lookup_item(&vlog_object, v, I_LEFT)->object = &(e->object);
961✔
612
   object_write_barrier(&(v->object), &(e->object));
961✔
613
}
961✔
614

615
vlog_node_t vlog_right(vlog_node_t v)
3,732✔
616
{
617
   item_t *item = lookup_item(&vlog_object, v, I_RIGHT);
3,732✔
618
   assert(item->object != NULL);
3,732✔
619
   return container_of(item->object, struct _vlog_node, object);
3,732✔
620
}
621

622
void vlog_set_right(vlog_node_t v, vlog_node_t e)
961✔
623
{
624
   lookup_item(&vlog_object, v, I_RIGHT)->object = &(e->object);
961✔
625
   object_write_barrier(&(v->object), &(e->object));
961✔
626
}
961✔
627

628
double vlog_dval(vlog_node_t v)
1✔
629
{
630
   return lookup_item(&vlog_object, v, I_DVAL)->dval;
1✔
631
}
632

633
void vlog_set_dval(vlog_node_t v, double d)
23✔
634
{
635
   lookup_item(&vlog_object, v, I_DVAL)->dval = d;
23✔
636
}
23✔
637

638
int64_t vlog_ival(vlog_node_t v)
616✔
639
{
640
   return lookup_item(&vlog_object, v, I_IVAL)->ival;
616✔
641
}
642

643
void vlog_set_ival(vlog_node_t v, int64_t i)
529✔
644
{
645
   lookup_item(&vlog_object, v, I_IVAL)->ival = i;
529✔
646
}
529✔
647

648
void vlog_visit(vlog_node_t v, vlog_visit_fn_t fn, void *context)
464✔
649
{
650
   vlog_visit_only(v, fn, context, V_LAST_NODE_KIND);
464✔
651
}
464✔
652

653
void vlog_visit_only(vlog_node_t v, vlog_visit_fn_t fn, void *context,
464✔
654
                     vlog_kind_t kind)
655
{
656
   assert(v != NULL);
464✔
657

658
   object_visit_ctx_t ctx = {
464✔
659
      .count      = 0,
660
      .postorder  = (object_visit_fn_t)fn,
661
      .preorder   = NULL,
662
      .context    = context,
663
      .kind       = kind,
664
      .tag        = OBJECT_TAG_VLOG,
665
      .generation = object_next_generation(),
464✔
666
      .deep       = false
667
   };
668

669
   object_visit(&(v->object), &ctx);
464✔
670
}
464✔
671

672
vlog_node_t vlog_rewrite(vlog_node_t v, vlog_rewrite_fn_t fn, void *context)
963✔
673
{
674
   object_arena_t *arena = object_arena(&(v->object));
963✔
675
   if (arena_frozen(arena))
963✔
676
      return v;
677

678
   object_rewrite_ctx_t ctx = {
963✔
679
      .generation = object_next_generation(),
963✔
680
      .context    = context,
681
      .arena      = arena,
682
   };
683

684
   ctx.post_fn[OBJECT_TAG_VLOG] = (object_rewrite_post_fn_t)fn;
963✔
685

686
   object_t *result = object_rewrite(&(v->object), &ctx);
963✔
687
   free(ctx.cache);
963✔
688
   return container_of(result, struct _vlog_node, object);
963✔
689
}
690

691
vlog_node_t vlog_copy(vlog_node_t v, vlog_copy_pred_t pred, void *ctx)
242✔
692
{
693
   object_copy_ctx_t *copy LOCAL = xcalloc_flex(sizeof(object_copy_ctx_t),
242✔
694
                                                1, sizeof(object_t *));
695
   copy->generation   = object_next_generation();
242✔
696
   copy->pred_context = ctx;
242✔
697
   copy->nroots       = 1;
242✔
698
   copy->roots[0]     = &(v->object);
242✔
699

700
   copy->should_copy[OBJECT_TAG_VLOG] = (object_copy_pred_t)pred;
242✔
701

702
   object_copy(copy);
242✔
703

704
   return container_of(copy->roots[0], struct _vlog_node, object);
242✔
705
}
706

707
object_t *vlog_to_object(vlog_node_t v)
1,655✔
708
{
709
   return &(v->object);
1,655✔
710
}
711

712
vlog_node_t vlog_from_object(object_t *obj)
6,699✔
713
{
714
   if (obj != NULL && obj->tag == OBJECT_TAG_VLOG)
6,699✔
715
      return container_of(obj, struct _vlog_node, object);
716
   else
717
      return NULL;
5,560✔
718
}
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