1 //
2 // Copyright (C) 2011-2019 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 "tree.h"
19 #include "util.h"
20 #include "array.h"
21 #include "object.h"
22 #include "common.h"
23
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28
29 static const imask_t has_map[T_LAST_TREE_KIND] = {
30 // T_ENTITY
31 (I_IDENT | I_PORTS | I_GENERICS | I_CONTEXT | I_DECLS | I_STMTS | I_ATTRS),
32
33 // T_ARCH
34 (I_IDENT | I_IDENT2 | I_DECLS | I_STMTS | I_CONTEXT | I_REF | I_ATTRS),
35
36 // T_PORT_DECL
37 (I_IDENT | I_VALUE | I_TYPE | I_SUBKIND | I_CLASS | I_ATTRS | I_FLAGS),
38
39 // T_FCALL
40 (I_IDENT | I_PARAMS | I_TYPE | I_REF | I_ATTRS | I_FLAGS),
41
42 // T_LITERAL
43 (I_SUBKIND | I_TYPE | I_IVAL | I_DVAL | I_CHARS | I_FLAGS),
44
45 // T_SIGNAL_DECL
46 (I_IDENT | I_VALUE | I_TYPE | I_NETS | I_ATTRS | I_FLAGS),
47
48 // T_VAR_DECL
49 (I_IDENT | I_VALUE | I_TYPE | I_ATTRS | I_FLAGS),
50
51 // T_PROCESS
52 (I_IDENT | I_DECLS | I_STMTS | I_TRIGGERS | I_ATTRS | I_FLAGS),
53
54 // T_REF
55 (I_IDENT | I_TYPE | I_REF | I_ATTRS | I_FLAGS),
56
57 // T_WAIT
58 (I_IDENT | I_VALUE | I_DELAY | I_TRIGGERS | I_ATTRS),
59
60 // T_TYPE_DECL
61 (I_IDENT | I_VALUE | I_TYPE | I_OPS | I_ATTRS),
62
63 // T_VAR_ASSIGN
64 (I_IDENT | I_VALUE | I_TARGET | I_ATTRS),
65
66 // T_PACKAGE
67 (I_IDENT | I_DECLS | I_CONTEXT | I_ATTRS),
68
69 // T_SIGNAL_ASSIGN
70 (I_IDENT | I_TARGET | I_WAVES | I_REJECT | I_ATTRS),
71
72 // T_QUALIFIED
73 (I_IDENT | I_VALUE | I_TYPE),
74
75 // T_ENUM_LIT
76 (I_IDENT | I_TYPE | I_POS | I_ATTRS),
77
78 // T_CONST_DECL
79 (I_IDENT | I_VALUE | I_TYPE | I_ATTRS | I_FLAGS),
80
81 // T_FUNC_DECL
82 (I_IDENT | I_VALUE | I_PORTS | I_TYPE | I_ATTRS | I_FLAGS),
83
84 // T_ELAB
85 (I_IDENT | I_DECLS | I_STMTS | I_CONTEXT | I_ATTRS),
86
87 // T_AGGREGATE
88 (I_TYPE | I_ASSOCS | I_FLAGS),
89
90 // T_ASSERT
91 (I_IDENT | I_VALUE | I_SEVERITY | I_MESSAGE | I_ATTRS),
92
93 // T_ATTR_REF
94 (I_NAME | I_VALUE | I_IDENT | I_PARAMS | I_TYPE | I_ATTRS),
95
96 // T_ARRAY_REF
97 (I_VALUE | I_PARAMS | I_TYPE | I_FLAGS | I_ATTRS),
98
99 // T_ARRAY_SLICE
100 (I_VALUE | I_TYPE | I_RANGES),
101
102 // T_INSTANCE
103 (I_IDENT | I_IDENT2 | I_PARAMS | I_GENMAPS | I_REF | I_CLASS | I_SPEC
104 | I_ATTRS),
105
106 // T_IF
107 (I_IDENT | I_VALUE | I_STMTS | I_ELSES | I_ATTRS),
108
109 // T_NULL
110 (I_IDENT),
111
112 // T_PACK_BODY
113 (I_IDENT | I_DECLS | I_CONTEXT | I_ATTRS),
114
115 // T_FUNC_BODY
116 (I_IDENT | I_DECLS | I_STMTS | I_PORTS | I_TYPE | I_ATTRS | I_FLAGS),
117
118 // T_RETURN
119 (I_IDENT | I_VALUE | I_ATTRS),
120
121 // T_CASSIGN
122 (I_IDENT | I_TARGET | I_CONDS | I_FLAGS),
123
124 // T_WHILE
125 (I_IDENT | I_VALUE | I_STMTS | I_ATTRS),
126
127 // T_WAVEFORM
128 (I_VALUE | I_DELAY),
129
130 // T_ALIAS
131 (I_IDENT | I_VALUE | I_TYPE | I_ATTRS),
132
133 // T_FOR
134 (I_IDENT | I_IDENT2 | I_DECLS | I_STMTS | I_RANGES | I_ATTRS),
135
136 // T_ATTR_DECL
137 (I_IDENT | I_TYPE | I_ATTRS),
138
139 // T_ATTR_SPEC
140 (I_IDENT | I_VALUE | I_IDENT2 | I_CLASS | I_ATTRS),
141
142 // T_PROC_DECL
143 (I_IDENT | I_PORTS | I_TYPE | I_ATTRS),
144
145 // T_PROC_BODY
146 (I_IDENT | I_DECLS | I_STMTS | I_PORTS | I_TYPE | I_ATTRS),
147
148 // T_EXIT
149 (I_IDENT | I_VALUE | I_IDENT2 | I_ATTRS),
150
151 // T_PCALL
152 (I_IDENT | I_IDENT2 | I_PARAMS | I_REF | I_ATTRS),
153
154 // T_CASE
155 (I_IDENT | I_VALUE | I_ASSOCS | I_ATTRS),
156
157 // T_BLOCK
158 (I_IDENT | I_DECLS | I_STMTS | I_ATTRS),
159
160 // T_COND
161 (I_VALUE | I_WAVES | I_REJECT),
162
163 // T_CONCAT
164 (I_PARAMS | I_TYPE),
165
166 // T_TYPE_CONV
167 (I_PARAMS | I_TYPE | I_REF | I_FLAGS),
168
169 // T_SELECT
170 (I_IDENT | I_VALUE | I_ASSOCS | I_FLAGS),
171
172 // T_COMPONENT
173 (I_IDENT | I_PORTS | I_GENERICS | I_ATTRS),
174
175 // T_IF_GENERATE
176 (I_IDENT | I_VALUE | I_DECLS | I_STMTS | I_ATTRS),
177
178 // T_FOR_GENERATE
179 (I_IDENT | I_IDENT2 | I_DECLS | I_STMTS | I_REF | I_RANGES | I_ATTRS),
180
181 // T_FILE_DECL
182 (I_IDENT | I_VALUE | I_TYPE | I_FILE_MODE | I_ATTRS),
183
184 // T_OPEN
185 (I_TYPE),
186
187 // T_FIELD_DECL
188 (I_IDENT | I_TYPE | I_ATTRS),
189
190 // T_RECORD_REF
191 (I_IDENT | I_VALUE | I_TYPE | I_ATTRS),
192
193 // T_ALL
194 (I_VALUE | I_TYPE),
195
196 // T_NEW
197 (I_VALUE | I_TYPE),
198
199 // T_CASSERT
200 (I_IDENT | I_VALUE | I_SEVERITY | I_MESSAGE | I_FLAGS),
201
202 // T_CPCALL
203 (I_IDENT | I_IDENT2 | I_PARAMS | I_REF),
204
205 // T_UNIT_DECL
206 (I_IDENT | I_VALUE | I_TYPE),
207
208 // T_NEXT
209 (I_IDENT | I_VALUE | I_IDENT2 | I_ATTRS),
210
211 // T_GENVAR
212 (I_IDENT | I_TYPE | I_ATTRS),
213
214 // T_PARAM
215 (I_VALUE | I_POS | I_SUBKIND | I_NAME),
216
217 // T_ASSOC
218 (I_VALUE | I_POS | I_NAME | I_RANGES | I_SUBKIND),
219
220 // T_USE
221 (I_IDENT | I_IDENT2),
222
223 // T_HIER
224 (I_IDENT | I_SUBKIND | I_IDENT2 | I_ATTRS),
225
226 // T_SPEC
227 (I_IDENT | I_IDENT2 | I_VALUE),
228
229 // T_BINDING
230 (I_PARAMS | I_GENMAPS | I_IDENT | I_IDENT2 | I_CLASS),
231
232 // T_LIBRARY
233 (I_IDENT),
234
235 // T_DESIGN_UNIT
236 (I_CONTEXT),
237
238 // T_CONFIGURATION
239 (I_IDENT | I_IDENT2 | I_DECLS),
240
241 // T_PROT_BODY
242 (I_IDENT | I_TYPE | I_DECLS | I_ATTRS),
243
244 // T_CONTEXT
245 (I_CONTEXT | I_IDENT),
246
247 // T_CTXREF
248 (I_IDENT | I_REF),
249
250 // T_CONSTRAINT
251 (I_SUBKIND | I_RANGES),
252
253 // T_BLOCK_CONFIG
254 (I_DECLS | I_IDENT | I_VALUE | I_RANGES),
255
256 // T_PRAGMA
257 (I_TEXT),
258 };
259
260 static const char *kind_text_map[T_LAST_TREE_KIND] = {
261 "T_ENTITY", "T_ARCH", "T_PORT_DECL", "T_FCALL",
262 "T_LITERAL", "T_SIGNAL_DECL", "T_VAR_DECL", "T_PROCESS",
263 "T_REF", "T_WAIT", "T_TYPE_DECL", "T_VAR_ASSIGN",
264 "T_PACKAGE", "T_SIGNAL_ASSIGN", "T_QUALIFIED", "T_ENUM_LIT",
265 "T_CONST_DECL", "T_FUNC_DECL", "T_ELAB", "T_AGGREGATE",
266 "T_ASSERT", "T_ATTR_REF", "T_ARRAY_REF", "T_ARRAY_SLICE",
267 "T_INSTANCE", "T_IF", "T_NULL", "T_PACK_BODY",
268 "T_FUNC_BODY", "T_RETURN", "T_CASSIGN", "T_WHILE",
269 "T_WAVEFORM", "T_ALIAS", "T_FOR", "T_ATTR_DECL",
270 "T_ATTR_SPEC", "T_PROC_DECL", "T_PROC_BODY", "T_EXIT",
271 "T_PCALL", "T_CASE", "T_BLOCK", "T_COND",
272 "T_CONCAT", "T_TYPE_CONV", "T_SELECT", "T_COMPONENT",
273 "T_IF_GENERATE", "T_FOR_GENERATE", "T_FILE_DECL", "T_OPEN",
274 "T_FIELD_DECL", "T_RECORD_REF", "T_ALL", "T_NEW",
275 "T_CASSERT", "T_CPCALL", "T_UNIT_DECL", "T_NEXT",
276 "T_GENVAR", "T_PARAM", "T_ASSOC", "T_USE",
277 "T_HIER", "T_SPEC", "T_BINDING", "T_LIBRARY",
278 "T_DESIGN_UNIT", "T_CONFIGURATION", "T_PROT_BODY", "T_CONTEXT",
279 "T_CTXREF", "T_CONSTRAINT", "T_BLOCK_CONFIG", "T_PRAGMA",
280 };
281
282 static const change_allowed_t change_allowed[] = {
283 { T_REF, T_FCALL },
284 { T_REF, T_PCALL },
285 { T_ARRAY_REF, T_FCALL },
286 { T_FCALL, T_ARRAY_REF },
287 { T_FCALL, T_PCALL },
288 { T_FCALL, T_TYPE_CONV },
289 { T_REF, T_RECORD_REF },
290 { T_ARRAY_REF, T_ARRAY_SLICE },
291 { T_ASSERT, T_CASSERT },
292 { T_DESIGN_UNIT, T_ENTITY },
293 { T_DESIGN_UNIT, T_PACKAGE },
294 { T_DESIGN_UNIT, T_PACK_BODY },
295 { T_DESIGN_UNIT, T_ARCH },
296 { T_DESIGN_UNIT, T_CONFIGURATION },
297 { T_DESIGN_UNIT, T_CONTEXT },
298 { T_FUNC_DECL, T_FUNC_BODY },
299 { T_PROC_DECL, T_PROC_BODY },
300 { T_REF, T_ARRAY_SLICE },
301 { T_FCALL, T_CPCALL },
302 { T_REF, T_CPCALL },
303 { T_ATTR_REF, T_ARRAY_REF },
304 { -1, -1 }
305 };
306
307 struct tree {
308 object_t object;
309 };
310
311 static const tree_kind_t stmt_kinds[] = {
312 T_PROCESS, T_WAIT, T_VAR_ASSIGN, T_SIGNAL_ASSIGN,
313 T_ASSERT, T_INSTANCE, T_IF, T_NULL,
314 T_RETURN, T_CASSIGN, T_WHILE, T_FOR,
315 T_EXIT, T_PCALL, T_CASE, T_BLOCK,
316 T_SELECT, T_IF_GENERATE, T_FOR_GENERATE, T_CPCALL,
317 T_CASSERT, T_NEXT, T_PRAGMA,
318 };
319
320 static tree_kind_t expr_kinds[] = {
321 T_FCALL, T_LITERAL, T_REF, T_QUALIFIED,
322 T_AGGREGATE, T_ATTR_REF, T_ARRAY_REF, T_ARRAY_SLICE,
323 T_CONCAT, T_TYPE_CONV, T_OPEN, T_RECORD_REF,
324 T_ALL, T_NEW
325 };
326
327 static tree_kind_t decl_kinds[] = {
328 T_PORT_DECL, T_SIGNAL_DECL, T_VAR_DECL, T_TYPE_DECL,
329 T_CONST_DECL, T_FUNC_DECL, T_FUNC_BODY, T_ALIAS,
330 T_ATTR_DECL, T_ATTR_SPEC, T_PROC_DECL, T_PROC_BODY,
331 T_COMPONENT, T_FILE_DECL, T_FIELD_DECL, T_UNIT_DECL,
332 T_GENVAR, T_HIER, T_SPEC, T_BINDING,
333 T_USE, T_PROT_BODY, T_BLOCK_CONFIG
334 };
335
336 object_class_t tree_object = {
337 .name = "tree",
338 .change_allowed = change_allowed,
339 .has_map = has_map,
340 .kind_text_map = kind_text_map,
341 .tag = OBJECT_TAG_TREE,
342 .last_kind = T_LAST_TREE_KIND,
343 .gc_roots = { T_ARCH, T_ENTITY, T_PACKAGE, T_ELAB, T_PACK_BODY,
344 T_CONTEXT },
345 .gc_num_roots = 5
346 };
347
tree_kind_in(tree_t t,const tree_kind_t * list,size_t len)348 static bool tree_kind_in(tree_t t, const tree_kind_t *list, size_t len)
349 {
350 for (size_t i = 0; i < len; i++) {
351 if (t->object.kind == list[i])
352 return true;
353 }
354
355 return false;
356 }
357
tree_assert_kind(tree_t t,const tree_kind_t * list,size_t len,const char * what)358 static void tree_assert_kind(tree_t t, const tree_kind_t *list, size_t len,
359 const char *what)
360 {
361 LCOV_EXCL_START
362 if (unlikely(!tree_kind_in(t, list, len)))
363 fatal_trace("tree kind %s is not %s",
364 tree_kind_str(t->object.kind), what);
365 LCOV_EXCL_STOP
366 }
367
tree_assert_stmt(tree_t t)368 static void tree_assert_stmt(tree_t t)
369 {
370 tree_assert_kind(t, stmt_kinds, ARRAY_LEN(stmt_kinds), "a statement");
371 }
372
tree_assert_expr(tree_t t)373 static void tree_assert_expr(tree_t t)
374 {
375 tree_assert_kind(t, expr_kinds, ARRAY_LEN(expr_kinds), "an expression");
376 }
377
tree_assert_decl(tree_t t)378 static void tree_assert_decl(tree_t t)
379 {
380 tree_assert_kind(t, decl_kinds, ARRAY_LEN(decl_kinds), "a declaration");
381 }
382
tree_new(tree_kind_t kind)383 tree_t tree_new(tree_kind_t kind)
384 {
385 return (tree_t)object_new(&tree_object, kind);
386 }
387
tree_gc(void)388 void tree_gc(void)
389 {
390 object_gc();
391 }
392
tree_loc(tree_t t)393 const loc_t *tree_loc(tree_t t)
394 {
395 assert(t != NULL);
396
397 return &t->object.loc;
398 }
399
tree_set_loc(tree_t t,const loc_t * loc)400 void tree_set_loc(tree_t t, const loc_t *loc)
401 {
402 assert(t != NULL);
403 assert(loc != NULL);
404
405 t->object.loc = *loc;
406 }
407
tree_ident(tree_t t)408 ident_t tree_ident(tree_t t)
409 {
410 item_t *item = lookup_item(&tree_object, t, I_IDENT);
411 assert(item->ident != NULL);
412 return item->ident;
413 }
414
tree_has_ident(tree_t t)415 bool tree_has_ident(tree_t t)
416 {
417 return lookup_item(&tree_object, t, I_IDENT)->ident != NULL;
418 }
419
tree_set_ident(tree_t t,ident_t i)420 void tree_set_ident(tree_t t, ident_t i)
421 {
422 lookup_item(&tree_object, t, I_IDENT)->ident = i;
423 }
424
tree_ident2(tree_t t)425 ident_t tree_ident2(tree_t t)
426 {
427 item_t *item = lookup_item(&tree_object, t, I_IDENT2);
428 assert(item->ident != NULL);
429 return item->ident;
430 }
431
tree_set_ident2(tree_t t,ident_t i)432 void tree_set_ident2(tree_t t, ident_t i)
433 {
434 lookup_item(&tree_object, t, I_IDENT2)->ident = i;
435 }
436
tree_has_ident2(tree_t t)437 bool tree_has_ident2(tree_t t)
438 {
439 return lookup_item(&tree_object, t, I_IDENT2)->ident != NULL;
440 }
441
tree_kind(tree_t t)442 tree_kind_t tree_kind(tree_t t)
443 {
444 assert(t != NULL);
445 return t->object.kind;
446 }
447
tree_change_kind(tree_t t,tree_kind_t kind)448 void tree_change_kind(tree_t t, tree_kind_t kind)
449 {
450 object_change_kind(&tree_object, &(t->object), kind);
451 }
452
tree_ports(tree_t t)453 unsigned tree_ports(tree_t t)
454 {
455 return lookup_item(&tree_object, t, I_PORTS)->tree_array.count;
456 }
457
tree_port(tree_t t,unsigned n)458 tree_t tree_port(tree_t t, unsigned n)
459 {
460 item_t *item = lookup_item(&tree_object, t, I_PORTS);
461 return tree_array_nth(&(item->tree_array), n);
462 }
463
tree_add_port(tree_t t,tree_t d)464 void tree_add_port(tree_t t, tree_t d)
465 {
466 tree_assert_decl(d);
467 tree_array_add(&(lookup_item(&tree_object, t, I_PORTS)->tree_array), d);
468 }
469
tree_subkind(tree_t t)470 unsigned tree_subkind(tree_t t)
471 {
472 item_t *item = lookup_item(&tree_object, t, I_SUBKIND);
473 return item->ival;
474 }
475
tree_set_subkind(tree_t t,unsigned sub)476 void tree_set_subkind(tree_t t, unsigned sub)
477 {
478 lookup_item(&tree_object, t, I_SUBKIND)->ival = sub;
479 }
480
tree_generics(tree_t t)481 unsigned tree_generics(tree_t t)
482 {
483 return lookup_item(&tree_object, t, I_GENERICS)->tree_array.count;
484 }
485
tree_generic(tree_t t,unsigned n)486 tree_t tree_generic(tree_t t, unsigned n)
487 {
488 item_t *item = lookup_item(&tree_object, t, I_GENERICS);
489 return tree_array_nth(&(item->tree_array), n);
490 }
491
tree_add_generic(tree_t t,tree_t d)492 void tree_add_generic(tree_t t, tree_t d)
493 {
494 tree_assert_decl(d);
495 tree_array_add(&(lookup_item(&tree_object, t, I_GENERICS)->tree_array), d);
496 }
497
tree_type(tree_t t)498 type_t tree_type(tree_t t)
499 {
500 item_t *item = lookup_item(&tree_object, t, I_TYPE);
501 assert(item->type != NULL);
502 return item->type;
503 }
504
tree_set_type(tree_t t,type_t ty)505 void tree_set_type(tree_t t, type_t ty)
506 {
507 lookup_item(&tree_object, t, I_TYPE)->type = ty;
508 }
509
tree_has_type(tree_t t)510 bool tree_has_type(tree_t t)
511 {
512 return lookup_item(&tree_object, t, I_TYPE)->type != NULL;
513 }
514
tree_params(tree_t t)515 unsigned tree_params(tree_t t)
516 {
517 return lookup_item(&tree_object, t, I_PARAMS)->tree_array.count;
518 }
519
tree_param(tree_t t,unsigned n)520 tree_t tree_param(tree_t t, unsigned n)
521 {
522 item_t *item = lookup_item(&tree_object, t, I_PARAMS);
523 return tree_array_nth(&(item->tree_array), n);
524 }
525
tree_add_param(tree_t t,tree_t e)526 void tree_add_param(tree_t t, tree_t e)
527 {
528 assert(tree_kind(e) == T_PARAM);
529 tree_assert_expr(tree_value(e));
530
531 tree_array_t *array = &(lookup_item(&tree_object, t, I_PARAMS)->tree_array);
532
533 if (tree_subkind(e) == P_POS)
534 tree_set_pos(e, array->count);
535
536 tree_array_add(array, e);
537 }
538
tree_genmaps(tree_t t)539 unsigned tree_genmaps(tree_t t)
540 {
541 return lookup_item(&tree_object, t, I_GENMAPS)->tree_array.count;
542 }
543
tree_genmap(tree_t t,unsigned n)544 tree_t tree_genmap(tree_t t, unsigned n)
545 {
546 item_t *item = lookup_item(&tree_object, t, I_GENMAPS);
547 return tree_array_nth(&(item->tree_array), n);
548 }
549
tree_add_genmap(tree_t t,tree_t e)550 void tree_add_genmap(tree_t t, tree_t e)
551 {
552 tree_assert_expr(tree_value(e));
553
554 tree_array_t *array = &(lookup_item(&tree_object, t, I_GENMAPS)->tree_array);
555
556 if (tree_subkind(e) == P_POS)
557 tree_set_pos(e, array->count);
558
559 tree_array_add(&(lookup_item(&tree_object, t, I_GENMAPS)->tree_array), e);
560 }
561
tree_ival(tree_t t)562 int64_t tree_ival(tree_t t)
563 {
564 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_INT));
565 return lookup_item(&tree_object, t, I_IVAL)->ival;
566 }
567
tree_set_ival(tree_t t,int64_t i)568 void tree_set_ival(tree_t t, int64_t i)
569 {
570 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_INT));
571 lookup_item(&tree_object, t, I_IVAL)->ival = i;
572 }
573
tree_dval(tree_t t)574 double tree_dval(tree_t t)
575 {
576 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_REAL));
577 return lookup_item(&tree_object, t, I_DVAL)->dval;
578 }
579
tree_set_dval(tree_t t,double d)580 void tree_set_dval(tree_t t, double d)
581 {
582 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_REAL));
583 lookup_item(&tree_object, t, I_DVAL)->dval = d;
584 }
585
tree_flags(tree_t t)586 tree_flags_t tree_flags(tree_t t)
587 {
588 return lookup_item(&tree_object, t, I_FLAGS)->ival;
589 }
590
tree_set_flag(tree_t t,tree_flags_t mask)591 void tree_set_flag(tree_t t, tree_flags_t mask)
592 {
593 lookup_item(&tree_object, t, I_FLAGS)->ival |= mask;
594 }
595
tree_chars(tree_t t)596 unsigned tree_chars(tree_t t)
597 {
598 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_STRING));
599 return lookup_item(&tree_object, t, I_CHARS)->ident_array.count;
600 }
601
tree_char(tree_t t,unsigned n)602 tree_t tree_char(tree_t t, unsigned n)
603 {
604 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_STRING));
605 item_t *item = lookup_item(&tree_object, t, I_CHARS);
606 return tree_array_nth(&(item->tree_array), n);
607 }
608
tree_add_char(tree_t t,tree_t ref)609 void tree_add_char(tree_t t, tree_t ref)
610 {
611 assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_STRING));
612 tree_array_add(&(lookup_item(&tree_object, t, I_CHARS)->tree_array), ref);
613 }
614
tree_has_value(tree_t t)615 bool tree_has_value(tree_t t)
616 {
617 return lookup_item(&tree_object, t, I_VALUE)->tree != NULL;
618 }
619
tree_value(tree_t t)620 tree_t tree_value(tree_t t)
621 {
622 item_t *item = lookup_item(&tree_object, t, I_VALUE);
623 assert(item->tree != NULL);
624 return item->tree;
625 }
626
tree_set_value(tree_t t,tree_t v)627 void tree_set_value(tree_t t, tree_t v)
628 {
629 if ((v != NULL) && (t->object.kind != T_ASSOC) && (t->object.kind != T_SPEC))
630 tree_assert_expr(v);
631 lookup_item(&tree_object, t, I_VALUE)->tree = v;
632 }
633
tree_decls(tree_t t)634 unsigned tree_decls(tree_t t)
635 {
636 return lookup_item(&tree_object, t, I_DECLS)->tree_array.count;
637 }
638
tree_decl(tree_t t,unsigned n)639 tree_t tree_decl(tree_t t, unsigned n)
640 {
641 item_t *item = lookup_item(&tree_object, t, I_DECLS);
642 return tree_array_nth(&(item->tree_array), n);
643 }
644
tree_add_decl(tree_t t,tree_t d)645 void tree_add_decl(tree_t t, tree_t d)
646 {
647 tree_assert_decl(d);
648 tree_array_add(&(lookup_item(&tree_object, t, I_DECLS)->tree_array), d);
649 }
650
tree_stmts(tree_t t)651 unsigned tree_stmts(tree_t t)
652 {
653 return lookup_item(&tree_object, t, I_STMTS)->tree_array.count;
654 }
655
tree_stmt(tree_t t,unsigned n)656 tree_t tree_stmt(tree_t t, unsigned n)
657 {
658 item_t *item = lookup_item(&tree_object, t, I_STMTS);
659 return tree_array_nth(&(item->tree_array), n);
660 }
661
tree_add_stmt(tree_t t,tree_t s)662 void tree_add_stmt(tree_t t, tree_t s)
663 {
664 tree_assert_stmt(s);
665 tree_array_add(&(lookup_item(&tree_object, t, I_STMTS)->tree_array), s);
666 }
667
tree_waveforms(tree_t t)668 unsigned tree_waveforms(tree_t t)
669 {
670 return lookup_item(&tree_object, t, I_WAVES)->tree_array.count;
671 }
672
tree_waveform(tree_t t,unsigned n)673 tree_t tree_waveform(tree_t t, unsigned n)
674 {
675 item_t *item = lookup_item(&tree_object, t, I_WAVES);
676 return tree_array_nth(&(item->tree_array), n);
677 }
678
tree_add_waveform(tree_t t,tree_t w)679 void tree_add_waveform(tree_t t, tree_t w)
680 {
681 assert(w->object.kind == T_WAVEFORM);
682 tree_array_add(&(lookup_item(&tree_object, t, I_WAVES)->tree_array), w);
683 }
684
tree_else_stmts(tree_t t)685 unsigned tree_else_stmts(tree_t t)
686 {
687 return lookup_item(&tree_object, t, I_ELSES)->tree_array.count;
688 }
689
tree_else_stmt(tree_t t,unsigned n)690 tree_t tree_else_stmt(tree_t t, unsigned n)
691 {
692 item_t *item = lookup_item(&tree_object, t, I_ELSES);
693 return tree_array_nth(&(item->tree_array), n);
694 }
695
tree_add_else_stmt(tree_t t,tree_t s)696 void tree_add_else_stmt(tree_t t, tree_t s)
697 {
698 tree_assert_stmt(s);
699 tree_array_add(&(lookup_item(&tree_object, t, I_ELSES)->tree_array), s);
700 }
701
tree_conds(tree_t t)702 unsigned tree_conds(tree_t t)
703 {
704 return lookup_item(&tree_object, t, I_CONDS)->tree_array.count;
705 }
706
tree_cond(tree_t t,unsigned n)707 tree_t tree_cond(tree_t t, unsigned n)
708 {
709 item_t *item = lookup_item(&tree_object, t, I_CONDS);
710 return tree_array_nth(&(item->tree_array), n);
711 }
712
tree_add_cond(tree_t t,tree_t c)713 void tree_add_cond(tree_t t, tree_t c)
714 {
715 assert(c->object.kind == T_COND);
716 tree_array_add(&(lookup_item(&tree_object, t, I_CONDS)->tree_array), c);
717 }
718
tree_has_delay(tree_t t)719 bool tree_has_delay(tree_t t)
720 {
721 return lookup_item(&tree_object, t, I_DELAY)->tree != NULL;
722 }
723
tree_delay(tree_t t)724 tree_t tree_delay(tree_t t)
725 {
726 item_t *item = lookup_item(&tree_object, t, I_DELAY);
727 assert(item->tree != NULL);
728 return item->tree;
729 }
730
tree_set_delay(tree_t t,tree_t d)731 void tree_set_delay(tree_t t, tree_t d)
732 {
733 tree_assert_expr(d);
734 lookup_item(&tree_object, t, I_DELAY)->tree = d;
735 }
736
tree_triggers(tree_t t)737 unsigned tree_triggers(tree_t t)
738 {
739 return lookup_item(&tree_object, t, I_TRIGGERS)->tree_array.count;
740 }
741
tree_trigger(tree_t t,unsigned n)742 tree_t tree_trigger(tree_t t, unsigned n)
743 {
744 item_t *item = lookup_item(&tree_object, t, I_TRIGGERS);
745 return tree_array_nth(&(item->tree_array), n);
746 }
747
tree_add_trigger(tree_t t,tree_t s)748 void tree_add_trigger(tree_t t, tree_t s)
749 {
750 tree_assert_expr(s);
751 tree_array_add(&(lookup_item(&tree_object, t, I_TRIGGERS)->tree_array), s);
752 }
753
tree_ops(tree_t t)754 unsigned tree_ops(tree_t t)
755 {
756 return lookup_item(&tree_object, t, I_OPS)->tree_array.count;
757 }
758
tree_op(tree_t t,unsigned n)759 tree_t tree_op(tree_t t, unsigned n)
760 {
761 return tree_array_nth(&(lookup_item(&tree_object, t, I_OPS)->tree_array), n);
762 }
763
tree_add_op(tree_t t,tree_t s)764 void tree_add_op(tree_t t, tree_t s)
765 {
766 assert((s->object.kind == T_FUNC_DECL) || (s->object.kind == T_PROC_DECL));
767 tree_array_add(&(lookup_item(&tree_object, t, I_OPS)->tree_array), s);
768 }
769
tree_target(tree_t t)770 tree_t tree_target(tree_t t)
771 {
772 item_t *item = lookup_item(&tree_object, t, I_TARGET);
773 assert(item->tree != NULL);
774 return item->tree;
775 }
776
tree_set_target(tree_t t,tree_t lhs)777 void tree_set_target(tree_t t, tree_t lhs)
778 {
779 lookup_item(&tree_object, t, I_TARGET)->tree = lhs;
780 }
781
tree_ref(tree_t t)782 tree_t tree_ref(tree_t t)
783 {
784 item_t *item = lookup_item(&tree_object, t, I_REF);
785 assert(item->tree != NULL);
786 return item->tree;
787 }
788
tree_has_ref(tree_t t)789 bool tree_has_ref(tree_t t)
790 {
791 return lookup_item(&tree_object, t, I_REF)->tree != NULL;
792 }
793
tree_set_ref(tree_t t,tree_t decl)794 void tree_set_ref(tree_t t, tree_t decl)
795 {
796 lookup_item(&tree_object, t, I_REF)->tree = decl;
797 }
798
tree_spec(tree_t t)799 tree_t tree_spec(tree_t t)
800 {
801 item_t *item = lookup_item(&tree_object, t, I_SPEC);
802 assert(item->tree != NULL);
803 return item->tree;
804 }
805
tree_has_spec(tree_t t)806 bool tree_has_spec(tree_t t)
807 {
808 return lookup_item(&tree_object, t, I_SPEC)->tree != NULL;
809 }
810
tree_set_spec(tree_t t,tree_t s)811 void tree_set_spec(tree_t t, tree_t s)
812 {
813 lookup_item(&tree_object, t, I_SPEC)->tree = s;
814 }
815
tree_contexts(tree_t t)816 unsigned tree_contexts(tree_t t)
817 {
818 return lookup_item(&tree_object, t, I_CONTEXT)->tree_array.count;
819 }
820
tree_context(tree_t t,unsigned n)821 tree_t tree_context(tree_t t, unsigned n)
822 {
823 item_t *item = lookup_item(&tree_object, t, I_CONTEXT);
824 return tree_array_nth(&(item->tree_array), n);
825 }
826
tree_add_context(tree_t t,tree_t ctx)827 void tree_add_context(tree_t t, tree_t ctx)
828 {
829 assert(ctx->object.kind == T_USE || ctx->object.kind == T_LIBRARY
830 || ctx->object.kind == T_CTXREF || ctx->object.kind == T_PRAGMA);
831 tree_array_add(&(lookup_item(&tree_object, t, I_CONTEXT)->tree_array), ctx);
832 }
833
tree_assocs(tree_t t)834 unsigned tree_assocs(tree_t t)
835 {
836 return lookup_item(&tree_object, t, I_ASSOCS)->tree_array.count;
837 }
838
tree_assoc(tree_t t,unsigned n)839 tree_t tree_assoc(tree_t t, unsigned n)
840 {
841 item_t *item = lookup_item(&tree_object, t, I_ASSOCS);
842 return tree_array_nth(&(item->tree_array), n);
843 }
844
tree_add_assoc(tree_t t,tree_t a)845 void tree_add_assoc(tree_t t, tree_t a)
846 {
847 assert(a->object.kind == T_ASSOC);
848
849 tree_array_t *array = &(lookup_item(&tree_object, t, I_ASSOCS)->tree_array);
850
851 if (tree_subkind(a) == A_POS)
852 tree_set_pos(a, array->count);
853
854 tree_array_add(array, a);
855 }
856
tree_nets(tree_t t)857 unsigned tree_nets(tree_t t)
858 {
859 return lookup_item(&tree_object, t, I_NETS)->netid_array.count;
860 }
861
tree_net(tree_t t,unsigned n)862 netid_t tree_net(tree_t t, unsigned n)
863 {
864 item_t *item = lookup_item(&tree_object, t, I_NETS);
865 netid_t nid = netid_array_nth(&(item->netid_array), n);
866 assert(nid != NETID_INVALID);
867 return nid;
868 }
869
tree_add_net(tree_t t,netid_t n)870 void tree_add_net(tree_t t, netid_t n)
871 {
872 netid_array_add(&(lookup_item(&tree_object, t, I_NETS)->netid_array), n);
873 }
874
tree_change_net(tree_t t,unsigned n,netid_t i)875 void tree_change_net(tree_t t, unsigned n, netid_t i)
876 {
877 item_t *item = lookup_item(&tree_object, t, I_NETS);
878
879 if (n >= item->netid_array.count)
880 netid_array_resize(&(item->netid_array), n + 1, 0xff);
881
882 item->netid_array.items[n] = i;
883 }
884
tree_severity(tree_t t)885 tree_t tree_severity(tree_t t)
886 {
887 item_t *item = lookup_item(&tree_object, t, I_SEVERITY);
888 assert(item->tree != NULL);
889 return item->tree;
890 }
891
tree_set_severity(tree_t t,tree_t s)892 void tree_set_severity(tree_t t, tree_t s)
893 {
894 tree_assert_expr(s);
895 lookup_item(&tree_object, t, I_SEVERITY)->tree = s;
896 }
897
tree_message(tree_t t)898 tree_t tree_message(tree_t t)
899 {
900 item_t *item = lookup_item(&tree_object, t, I_MESSAGE);
901 assert(item->tree != NULL);
902 return item->tree;
903 }
904
tree_has_message(tree_t t)905 bool tree_has_message(tree_t t)
906 {
907 return lookup_item(&tree_object, t, I_MESSAGE)->tree != NULL;
908 }
909
tree_set_message(tree_t t,tree_t m)910 void tree_set_message(tree_t t, tree_t m)
911 {
912 tree_assert_expr(m);
913 lookup_item(&tree_object, t, I_MESSAGE)->tree = m;
914 }
915
tree_add_range(tree_t t,range_t r)916 void tree_add_range(tree_t t, range_t r)
917 {
918 range_array_add(&(lookup_item(&tree_object, t, I_RANGES)->range_array), r);
919 }
920
tree_range(tree_t t,unsigned n)921 range_t tree_range(tree_t t, unsigned n)
922 {
923 item_t *item = lookup_item(&tree_object, t, I_RANGES);
924 return range_array_nth(&(item->range_array), n);
925 }
926
tree_ranges(tree_t t)927 unsigned tree_ranges(tree_t t)
928 {
929 return lookup_item(&tree_object, t, I_RANGES)->range_array.count;
930 }
931
tree_change_range(tree_t t,unsigned n,range_t r)932 void tree_change_range(tree_t t, unsigned n, range_t r)
933 {
934 item_t *item = lookup_item(&tree_object, t, I_RANGES);
935 assert(n < item->range_array.count);
936 item->range_array.items[n] = r;
937 }
938
tree_text(tree_t t)939 char *tree_text(tree_t t)
940 {
941 return lookup_item(&tree_object, t, I_TEXT)->text;
942 }
943
tree_set_text(tree_t t,const char * text)944 void tree_set_text(tree_t t, const char *text)
945 {
946 lookup_item(&tree_object, t, I_TEXT)->text = xstrdup(text);
947 }
948
tree_pos(tree_t t)949 unsigned tree_pos(tree_t t)
950 {
951 return lookup_item(&tree_object, t, I_POS)->ival;
952 }
953
tree_set_pos(tree_t t,unsigned pos)954 void tree_set_pos(tree_t t, unsigned pos)
955 {
956 lookup_item(&tree_object, t, I_POS)->ival = pos;
957 }
958
tree_class(tree_t t)959 class_t tree_class(tree_t t)
960 {
961 return lookup_item(&tree_object, t, I_CLASS)->ival;
962 }
963
tree_set_class(tree_t t,class_t c)964 void tree_set_class(tree_t t, class_t c)
965 {
966 lookup_item(&tree_object, t, I_CLASS)->ival = c;
967 }
968
tree_reject(tree_t t)969 tree_t tree_reject(tree_t t)
970 {
971 item_t *item = lookup_item(&tree_object, t, I_REJECT);
972 assert(item->tree != NULL);
973 return item->tree;
974 }
975
tree_set_reject(tree_t t,tree_t r)976 void tree_set_reject(tree_t t, tree_t r)
977 {
978 tree_assert_expr(r);
979 lookup_item(&tree_object, t, I_REJECT)->tree = r;
980 }
981
tree_has_reject(tree_t t)982 bool tree_has_reject(tree_t t)
983 {
984 return lookup_item(&tree_object, t, I_REJECT)->tree != NULL;
985 }
986
tree_name(tree_t t)987 tree_t tree_name(tree_t t)
988 {
989 item_t *item = lookup_item(&tree_object, t, I_NAME);
990 assert(item->tree != NULL);
991 return item->tree;
992 }
993
tree_set_name(tree_t t,tree_t n)994 void tree_set_name(tree_t t, tree_t n)
995 {
996 tree_assert_expr(n);
997 lookup_item(&tree_object, t, I_NAME)->tree = n;
998 }
999
tree_file_mode(tree_t t)1000 tree_t tree_file_mode(tree_t t)
1001 {
1002 return lookup_item(&tree_object, t, I_FILE_MODE)->tree;
1003 }
1004
tree_set_file_mode(tree_t t,tree_t m)1005 void tree_set_file_mode(tree_t t, tree_t m)
1006 {
1007 lookup_item(&tree_object, t, I_FILE_MODE)->tree = m;
1008 }
1009
tree_visit(tree_t t,tree_visit_fn_t fn,void * context)1010 unsigned tree_visit(tree_t t, tree_visit_fn_t fn, void *context)
1011 {
1012 assert(t != NULL);
1013
1014 object_visit_ctx_t ctx = {
1015 .count = 0,
1016 .postorder = fn,
1017 .preorder = NULL,
1018 .context = context,
1019 .kind = T_LAST_TREE_KIND,
1020 .generation = object_next_generation(),
1021 .deep = false
1022 };
1023
1024 object_visit(&(t->object), &ctx);
1025
1026 return ctx.count;
1027 }
1028
tree_visit_only(tree_t t,tree_visit_fn_t fn,void * context,tree_kind_t kind)1029 unsigned tree_visit_only(tree_t t, tree_visit_fn_t fn,
1030 void *context, tree_kind_t kind)
1031 {
1032 assert(t != NULL);
1033
1034 object_visit_ctx_t ctx = {
1035 .count = 0,
1036 .postorder = fn,
1037 .preorder = NULL,
1038 .context = context,
1039 .kind = kind,
1040 .generation = object_next_generation(),
1041 .deep = false
1042 };
1043
1044 object_visit(&(t->object), &ctx);
1045
1046 return ctx.count;
1047 }
1048
tree_write_begin(fbuf_t * f)1049 tree_wr_ctx_t tree_write_begin(fbuf_t *f)
1050 {
1051 return (tree_wr_ctx_t)object_write_begin(f);
1052 }
1053
tree_write_end(tree_wr_ctx_t ctx)1054 void tree_write_end(tree_wr_ctx_t ctx)
1055 {
1056 object_write_end((object_wr_ctx_t *)ctx);
1057 }
1058
tree_write(tree_t t,tree_wr_ctx_t ctx)1059 void tree_write(tree_t t, tree_wr_ctx_t ctx)
1060 {
1061 object_write(&(t->object), (object_wr_ctx_t *)ctx);
1062 }
1063
tree_read(tree_rd_ctx_t ctx)1064 tree_t tree_read(tree_rd_ctx_t ctx)
1065 {
1066 return (tree_t)object_read((object_rd_ctx_t *)ctx, OBJECT_TAG_TREE);
1067 }
1068
tree_read_begin(fbuf_t * f,const char * fname)1069 tree_rd_ctx_t tree_read_begin(fbuf_t *f, const char *fname)
1070 {
1071 return (tree_rd_ctx_t)object_read_begin(f, fname);
1072 }
1073
tree_read_end(tree_rd_ctx_t ctx)1074 void tree_read_end(tree_rd_ctx_t ctx)
1075 {
1076 object_read_end((object_rd_ctx_t *)ctx);
1077 }
1078
tree_find_attr(tree_t t,ident_t name,attr_kind_t kind)1079 static attr_t *tree_find_attr(tree_t t, ident_t name, attr_kind_t kind)
1080 {
1081 assert(t != NULL);
1082 assert(name != NULL);
1083
1084 item_t *item = lookup_item(&tree_object, t, I_ATTRS);
1085 for (unsigned i = 0; i < item->attrs.num; i++) {
1086 if ((item->attrs.table[i].kind == kind)
1087 && (item->attrs.table[i].name == name))
1088 return &(item->attrs.table[i]);
1089 }
1090
1091 return NULL;
1092 }
1093
tree_add_attr(tree_t t,ident_t name,attr_kind_t kind)1094 static attr_t *tree_add_attr(tree_t t, ident_t name, attr_kind_t kind)
1095 {
1096 assert(t != NULL);
1097 assert(name != NULL);
1098
1099 attr_t *a = tree_find_attr(t, name, kind);
1100 if (a != NULL)
1101 return a;
1102
1103 item_t *item = lookup_item(&tree_object, t, I_ATTRS);
1104
1105 if (item->attrs.table == NULL) {
1106 item->attrs.alloc = 8;
1107 item->attrs.table = xmalloc(sizeof(attr_t) * item->attrs.alloc);
1108 }
1109 else if (item->attrs.alloc == item->attrs.num) {
1110 item->attrs.alloc *= 2;
1111 item->attrs.table = xrealloc(item->attrs.table,
1112 sizeof(attr_t) * item->attrs.alloc);
1113 }
1114
1115 unsigned i = item->attrs.num++;
1116 item->attrs.table[i].kind = kind;
1117 item->attrs.table[i].name = name;
1118
1119 return &(item->attrs.table[i]);
1120 }
1121
tree_remove_attr(tree_t t,ident_t name)1122 void tree_remove_attr(tree_t t, ident_t name)
1123 {
1124 assert(t != NULL);
1125 assert(name != NULL);
1126
1127 item_t *item = lookup_item(&tree_object, t, I_ATTRS);
1128
1129 unsigned i;
1130 for (i = 0; (i < item->attrs.num)
1131 && (item->attrs.table[i].name != name); i++)
1132 ;
1133
1134 if (i == item->attrs.num)
1135 return;
1136
1137 for (; i + 1 < item->attrs.num; i++)
1138 item->attrs.table[i] = item->attrs.table[i + 1];
1139
1140 item->attrs.num--;
1141 }
1142
tree_add_attr_str(tree_t t,ident_t name,ident_t str)1143 void tree_add_attr_str(tree_t t, ident_t name, ident_t str)
1144 {
1145 tree_add_attr(t, name, A_STRING)->sval = str;
1146 }
1147
tree_attr_str(tree_t t,ident_t name)1148 ident_t tree_attr_str(tree_t t, ident_t name)
1149 {
1150 attr_t *a = tree_find_attr(t, name, A_STRING);
1151 return a ? a->sval : NULL;
1152 }
1153
tree_add_attr_int(tree_t t,ident_t name,int n)1154 void tree_add_attr_int(tree_t t, ident_t name, int n)
1155 {
1156 tree_add_attr(t, name, A_INT)->ival = n;
1157 }
1158
tree_attr_int(tree_t t,ident_t name,int def)1159 int tree_attr_int(tree_t t, ident_t name, int def)
1160 {
1161 attr_t *a = tree_find_attr(t, name, A_INT);
1162 return a ? a->ival : def;
1163 }
1164
tree_add_attr_ptr(tree_t t,ident_t name,void * ptr)1165 void tree_add_attr_ptr(tree_t t, ident_t name, void *ptr)
1166 {
1167 tree_add_attr(t, name, A_PTR)->pval = ptr;
1168 }
1169
tree_attr_ptr(tree_t t,ident_t name)1170 void *tree_attr_ptr(tree_t t, ident_t name)
1171 {
1172 attr_t *a = tree_find_attr(t, name, A_PTR);
1173 return a ? a->pval : NULL;
1174 }
1175
tree_attr_tree(tree_t t,ident_t name)1176 tree_t tree_attr_tree(tree_t t, ident_t name)
1177 {
1178 attr_t *a = tree_find_attr(t, name, A_TREE);
1179 return a ? a->tval : NULL;
1180 }
1181
tree_add_attr_tree(tree_t t,ident_t name,tree_t val)1182 void tree_add_attr_tree(tree_t t, ident_t name, tree_t val)
1183 {
1184 assert(val != NULL);
1185 tree_add_attr(t, name, A_TREE)->tval = val;
1186 }
1187
tree_rewrite(tree_t t,tree_rewrite_fn_t fn,void * context)1188 tree_t tree_rewrite(tree_t t, tree_rewrite_fn_t fn, void *context)
1189 {
1190 object_rewrite_ctx_t ctx = {
1191 .index = 0,
1192 .generation = object_next_generation(),
1193 .fn = fn,
1194 .context = context
1195 };
1196
1197 tree_t result = (tree_t)object_rewrite(&(t->object), &ctx);
1198 free(ctx.cache);
1199 return result;
1200 }
1201
tree_copy(tree_t t,tree_copy_fn_t fn,void * context)1202 tree_t tree_copy(tree_t t, tree_copy_fn_t fn, void *context)
1203 {
1204 object_copy_ctx_t ctx = {
1205 .generation = object_next_generation(),
1206 .index = 0,
1207 .callback = fn,
1208 .context = context,
1209 .copied = NULL
1210 };
1211
1212 object_copy_mark(&(t->object), &ctx);
1213
1214 if (t->object.index == UINT32_MAX)
1215 return t; // Nothing to copy
1216
1217 ctx.copied = xcalloc(sizeof(void *) * ctx.index);
1218
1219 tree_t copy = (tree_t)object_copy_sweep(&(t->object), &ctx);
1220
1221 free(ctx.copied);
1222 return copy;
1223 }
1224
tree_kind_str(tree_kind_t t)1225 const char *tree_kind_str(tree_kind_t t)
1226 {
1227 return kind_text_map[t];
1228 }
1229