debug.c revision 1.28 1 1.28 rillig /* $NetBSD: debug.c,v 1.28 2023/04/11 17:52:11 rillig Exp $ */
2 1.1 rillig
3 1.1 rillig /*-
4 1.1 rillig * Copyright (c) 2021 The NetBSD Foundation, Inc.
5 1.1 rillig * All rights reserved.
6 1.1 rillig *
7 1.1 rillig * This code is derived from software contributed to The NetBSD Foundation
8 1.1 rillig * by Roland Illig <rillig (at) NetBSD.org>.
9 1.1 rillig *
10 1.1 rillig * Redistribution and use in source and binary forms, with or without
11 1.1 rillig * modification, are permitted provided that the following conditions
12 1.1 rillig * are met:
13 1.1 rillig * 1. Redistributions of source code must retain the above copyright
14 1.1 rillig * notice, this list of conditions and the following disclaimer.
15 1.1 rillig * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 rillig * notice, this list of conditions and the following disclaimer in the
17 1.1 rillig * documentation and/or other materials provided with the distribution.
18 1.1 rillig *
19 1.1 rillig * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 rillig * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 rillig * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 rillig * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 rillig * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 rillig * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 rillig * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 rillig * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 rillig * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 rillig * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 rillig * POSSIBILITY OF SUCH DAMAGE.
30 1.1 rillig */
31 1.1 rillig
32 1.1 rillig #if HAVE_NBTOOL_CONFIG_H
33 1.1 rillig #include "nbtool_config.h"
34 1.1 rillig #endif
35 1.1 rillig
36 1.1 rillig #include <sys/cdefs.h>
37 1.18 rillig #if defined(__RCSID)
38 1.28 rillig __RCSID("$NetBSD: debug.c,v 1.28 2023/04/11 17:52:11 rillig Exp $");
39 1.1 rillig #endif
40 1.1 rillig
41 1.2 rillig #include <stdlib.h>
42 1.2 rillig
43 1.1 rillig #include "lint1.h"
44 1.9 rillig #include "cgram.h"
45 1.1 rillig
46 1.1 rillig
47 1.1 rillig #ifdef DEBUG
48 1.1 rillig
49 1.1 rillig static int debug_indentation = 0;
50 1.1 rillig
51 1.1 rillig
52 1.1 rillig void __printflike(1, 2)
53 1.1 rillig debug_printf(const char *fmt, ...)
54 1.1 rillig {
55 1.1 rillig va_list va;
56 1.1 rillig
57 1.1 rillig va_start(va, fmt);
58 1.10 rillig (void)vfprintf(stdout, fmt, va);
59 1.1 rillig va_end(va);
60 1.1 rillig }
61 1.1 rillig
62 1.1 rillig void
63 1.7 rillig debug_print_indent(void)
64 1.1 rillig {
65 1.1 rillig
66 1.1 rillig debug_printf("%*s", 2 * debug_indentation, "");
67 1.1 rillig }
68 1.1 rillig
69 1.1 rillig void
70 1.1 rillig debug_indent_inc(void)
71 1.1 rillig {
72 1.1 rillig
73 1.1 rillig debug_indentation++;
74 1.1 rillig }
75 1.1 rillig
76 1.1 rillig void
77 1.1 rillig debug_indent_dec(void)
78 1.1 rillig {
79 1.1 rillig
80 1.1 rillig debug_indentation--;
81 1.1 rillig }
82 1.1 rillig
83 1.1 rillig void
84 1.28 rillig debug_enter_func(const char *func)
85 1.1 rillig {
86 1.1 rillig
87 1.1 rillig printf("%*s+ %s\n", 2 * debug_indentation++, "", func);
88 1.1 rillig }
89 1.1 rillig
90 1.1 rillig void __printflike(1, 2)
91 1.1 rillig debug_step(const char *fmt, ...)
92 1.1 rillig {
93 1.1 rillig va_list va;
94 1.1 rillig
95 1.7 rillig debug_print_indent();
96 1.1 rillig va_start(va, fmt);
97 1.10 rillig (void)vfprintf(stdout, fmt, va);
98 1.1 rillig va_end(va);
99 1.1 rillig printf("\n");
100 1.1 rillig }
101 1.1 rillig
102 1.1 rillig void
103 1.28 rillig debug_leave_func(const char *func)
104 1.1 rillig {
105 1.1 rillig
106 1.1 rillig printf("%*s- %s\n", 2 * --debug_indentation, "", func);
107 1.1 rillig }
108 1.1 rillig
109 1.22 rillig static void
110 1.22 rillig debug_type_details(const type_t *tp)
111 1.22 rillig {
112 1.22 rillig
113 1.22 rillig if (is_struct_or_union(tp->t_tspec)) {
114 1.22 rillig debug_indent_inc();
115 1.22 rillig for (const sym_t *mem = tp->t_str->sou_first_member;
116 1.22 rillig mem != NULL; mem = mem->s_next) {
117 1.22 rillig debug_sym("", mem, "\n");
118 1.22 rillig debug_type_details(mem->s_type);
119 1.22 rillig }
120 1.22 rillig debug_indent_dec();
121 1.22 rillig }
122 1.22 rillig if (tp->t_is_enum) {
123 1.22 rillig debug_indent_inc();
124 1.22 rillig for (const sym_t *en = tp->t_enum->en_first_enumerator;
125 1.22 rillig en != NULL; en = en->s_next) {
126 1.22 rillig debug_sym("", en, "\n");
127 1.22 rillig }
128 1.22 rillig debug_indent_dec();
129 1.22 rillig }
130 1.22 rillig }
131 1.22 rillig
132 1.22 rillig void
133 1.22 rillig debug_type(const type_t *tp)
134 1.22 rillig {
135 1.22 rillig
136 1.22 rillig debug_step("type details for '%s':", type_name(tp));
137 1.22 rillig debug_type_details(tp);
138 1.22 rillig }
139 1.22 rillig
140 1.1 rillig void
141 1.10 rillig debug_node(const tnode_t *tn) // NOLINT(misc-no-recursion)
142 1.1 rillig {
143 1.1 rillig op_t op;
144 1.1 rillig
145 1.1 rillig if (tn == NULL) {
146 1.2 rillig debug_step("null");
147 1.1 rillig return;
148 1.1 rillig }
149 1.1 rillig
150 1.1 rillig op = tn->tn_op;
151 1.7 rillig debug_print_indent();
152 1.20 rillig debug_printf("'%s'",
153 1.20 rillig op == CVT && !tn->tn_cast ? "convert" : modtab[op].m_name);
154 1.20 rillig if (op == NAME)
155 1.20 rillig debug_printf(" '%s' with %s",
156 1.20 rillig tn->tn_sym->s_name,
157 1.20 rillig storage_class_name(tn->tn_sym->s_scl));
158 1.20 rillig else
159 1.20 rillig debug_printf(" type");
160 1.20 rillig debug_printf(" '%s'", type_name(tn->tn_type));
161 1.20 rillig if (tn->tn_lvalue)
162 1.20 rillig debug_printf(", lvalue");
163 1.20 rillig if (tn->tn_parenthesized)
164 1.20 rillig debug_printf(", parenthesized");
165 1.20 rillig if (tn->tn_sys)
166 1.20 rillig debug_printf(", sys");
167 1.1 rillig
168 1.24 rillig switch (op) {
169 1.24 rillig case NAME:
170 1.20 rillig debug_printf("\n");
171 1.24 rillig break;
172 1.24 rillig case CON:
173 1.24 rillig if (is_floating(tn->tn_type->t_tspec))
174 1.27 rillig debug_printf(", value %Lg", tn->tn_val->v_ldbl);
175 1.24 rillig else if (is_uinteger(tn->tn_type->t_tspec))
176 1.27 rillig debug_printf(", value %llu",
177 1.24 rillig (unsigned long long)tn->tn_val->v_quad);
178 1.24 rillig else if (is_integer(tn->tn_type->t_tspec))
179 1.27 rillig debug_printf(", value %lld",
180 1.24 rillig (long long)tn->tn_val->v_quad);
181 1.27 rillig else {
182 1.27 rillig lint_assert(tn->tn_type->t_tspec == BOOL);
183 1.27 rillig debug_printf(", value %s",
184 1.24 rillig tn->tn_val->v_quad != 0 ? "true" : "false");
185 1.27 rillig }
186 1.27 rillig if (tn->tn_val->v_unsigned_since_c90)
187 1.27 rillig debug_printf(", unsigned_since_c90");
188 1.27 rillig debug_printf("\n");
189 1.24 rillig break;
190 1.24 rillig case STRING:
191 1.24 rillig if (tn->tn_string->st_char)
192 1.24 rillig debug_printf(", length %zu, \"%s\"\n",
193 1.24 rillig tn->tn_string->st_len,
194 1.24 rillig (const char *)tn->tn_string->st_mem);
195 1.24 rillig else {
196 1.24 rillig size_t n = MB_CUR_MAX * (tn->tn_string->st_len + 1);
197 1.24 rillig char *s = xmalloc(n);
198 1.24 rillig (void)wcstombs(s, tn->tn_string->st_mem, n);
199 1.24 rillig debug_printf(", length %zu, L\"%s\"\n",
200 1.24 rillig tn->tn_string->st_len, s);
201 1.24 rillig free(s);
202 1.24 rillig }
203 1.24 rillig break;
204 1.24 rillig default:
205 1.2 rillig debug_printf("\n");
206 1.1 rillig
207 1.2 rillig debug_indent_inc();
208 1.2 rillig debug_node(tn->tn_left);
209 1.3 rillig if (is_binary(tn) || tn->tn_right != NULL)
210 1.2 rillig debug_node(tn->tn_right);
211 1.2 rillig debug_indent_dec();
212 1.1 rillig }
213 1.1 rillig }
214 1.1 rillig
215 1.9 rillig static const char *
216 1.9 rillig def_name(def_t def)
217 1.9 rillig {
218 1.9 rillig static const char *const name[] = {
219 1.9 rillig "not-declared",
220 1.9 rillig "declared",
221 1.9 rillig "tentative-defined",
222 1.9 rillig "defined",
223 1.9 rillig };
224 1.9 rillig
225 1.9 rillig return name[def];
226 1.9 rillig }
227 1.9 rillig
228 1.9 rillig const char *
229 1.17 rillig declaration_kind_name(declaration_kind dk)
230 1.17 rillig {
231 1.17 rillig static const char *const name[] = {
232 1.17 rillig "extern",
233 1.17 rillig "member-of-struct",
234 1.17 rillig "member-of-union",
235 1.17 rillig "enum-constant",
236 1.17 rillig "old-style-function-argument",
237 1.17 rillig "prototype-argument",
238 1.17 rillig "auto",
239 1.17 rillig "abstract",
240 1.17 rillig };
241 1.17 rillig
242 1.17 rillig return name[dk];
243 1.17 rillig }
244 1.17 rillig
245 1.17 rillig const char *
246 1.9 rillig scl_name(scl_t scl)
247 1.9 rillig {
248 1.9 rillig static const char *const name[] = {
249 1.9 rillig "none",
250 1.9 rillig "extern",
251 1.9 rillig "static",
252 1.9 rillig "auto",
253 1.9 rillig "register",
254 1.9 rillig "typedef",
255 1.9 rillig "struct",
256 1.9 rillig "union",
257 1.9 rillig "enum",
258 1.9 rillig "member-of-struct",
259 1.9 rillig "member-of-union",
260 1.9 rillig "abstract",
261 1.9 rillig "old-style-function-argument",
262 1.9 rillig "prototype-argument",
263 1.9 rillig "inline",
264 1.9 rillig };
265 1.9 rillig
266 1.9 rillig return name[scl];
267 1.9 rillig }
268 1.9 rillig
269 1.9 rillig const char *
270 1.9 rillig symt_name(symt_t kind)
271 1.9 rillig {
272 1.9 rillig static const char *const name[] = {
273 1.9 rillig "var-func-type",
274 1.9 rillig "member",
275 1.9 rillig "tag",
276 1.9 rillig "label",
277 1.9 rillig };
278 1.9 rillig
279 1.9 rillig return name[kind];
280 1.9 rillig }
281 1.9 rillig
282 1.9 rillig const char *
283 1.9 rillig tqual_name(tqual_t qual)
284 1.9 rillig {
285 1.9 rillig static const char *const name[] = {
286 1.9 rillig "const",
287 1.9 rillig "volatile",
288 1.9 rillig "restrict",
289 1.9 rillig "_Thread_local",
290 1.25 rillig "_Atomic",
291 1.9 rillig };
292 1.9 rillig
293 1.9 rillig return name[qual];
294 1.9 rillig }
295 1.9 rillig
296 1.9 rillig static void
297 1.9 rillig debug_word(bool flag, const char *name)
298 1.9 rillig {
299 1.9 rillig
300 1.9 rillig if (flag)
301 1.9 rillig debug_printf(" %s", name);
302 1.9 rillig }
303 1.9 rillig
304 1.9 rillig void
305 1.10 rillig debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
306 1.9 rillig {
307 1.9 rillig
308 1.21 rillig if (suffix[0] == '\n')
309 1.21 rillig debug_print_indent();
310 1.10 rillig debug_printf("%s%s", prefix, sym->s_name);
311 1.9 rillig if (sym->s_type != NULL)
312 1.9 rillig debug_printf(" type='%s'", type_name(sym->s_type));
313 1.9 rillig if (sym->s_rename != NULL)
314 1.9 rillig debug_printf(" rename=%s", sym->s_rename);
315 1.9 rillig debug_printf(" %s", symt_name(sym->s_kind));
316 1.9 rillig debug_word(sym->s_keyword != NULL, "keyword");
317 1.9 rillig debug_word(sym->s_bitfield, "bit-field");
318 1.9 rillig debug_word(sym->s_set, "set");
319 1.9 rillig debug_word(sym->s_used, "used");
320 1.9 rillig debug_word(sym->s_arg, "argument");
321 1.9 rillig debug_word(sym->s_register, "register");
322 1.9 rillig debug_word(sym->s_defarg, "old-style-undefined");
323 1.9 rillig debug_word(sym->s_return_type_implicit_int, "return-int");
324 1.9 rillig debug_word(sym->s_osdef, "old-style");
325 1.9 rillig debug_word(sym->s_inline, "inline");
326 1.9 rillig debug_word(sym->s_ext_sym != NULL, "has-external");
327 1.9 rillig debug_word(sym->s_scl != NOSCL, scl_name(sym->s_scl));
328 1.9 rillig debug_word(sym->s_keyword == NULL, def_name(sym->s_def));
329 1.9 rillig
330 1.9 rillig if (sym->s_def_pos.p_file != NULL)
331 1.9 rillig debug_printf(" defined-at=%s:%d",
332 1.9 rillig sym->s_def_pos.p_file, sym->s_def_pos.p_line);
333 1.9 rillig if (sym->s_set_pos.p_file != NULL)
334 1.9 rillig debug_printf(" set-at=%s:%d",
335 1.9 rillig sym->s_set_pos.p_file, sym->s_set_pos.p_line);
336 1.9 rillig if (sym->s_use_pos.p_file != NULL)
337 1.9 rillig debug_printf(" used-at=%s:%d",
338 1.9 rillig sym->s_use_pos.p_file, sym->s_use_pos.p_line);
339 1.9 rillig
340 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_is_enum)
341 1.14 rillig debug_printf(" value=%d", sym->u.s_enum_constant);
342 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_tspec == BOOL)
343 1.14 rillig debug_printf(" value=%s",
344 1.14 rillig sym->u.s_bool_constant ? "true" : "false");
345 1.9 rillig
346 1.15 rillig if (is_member(sym) && sym->u.s_member.sm_sou_type != NULL) {
347 1.14 rillig struct_or_union *sou_type = sym->u.s_member.sm_sou_type;
348 1.14 rillig const char *tag = sou_type->sou_tag->s_name;
349 1.14 rillig const sym_t *def = sou_type->sou_first_typedef;
350 1.9 rillig if (tag == unnamed && def != NULL)
351 1.9 rillig debug_printf(" sou='typedef %s'", def->s_name);
352 1.9 rillig else
353 1.9 rillig debug_printf(" sou=%s", tag);
354 1.9 rillig }
355 1.9 rillig
356 1.9 rillig if (sym->s_keyword != NULL) {
357 1.14 rillig int t = sym->u.s_keyword.sk_token;
358 1.9 rillig if (t == T_TYPE || t == T_STRUCT_OR_UNION)
359 1.14 rillig debug_printf(" %s",
360 1.14 rillig tspec_name(sym->u.s_keyword.sk_tspec));
361 1.9 rillig else if (t == T_QUAL)
362 1.14 rillig debug_printf(" %s",
363 1.14 rillig tqual_name(sym->u.s_keyword.sk_qualifier));
364 1.9 rillig }
365 1.9 rillig
366 1.12 rillig debug_word(sym->s_osdef && sym->u.s_old_style_args != NULL,
367 1.12 rillig "old-style-args");
368 1.9 rillig
369 1.10 rillig debug_printf("%s", suffix);
370 1.10 rillig }
371 1.10 rillig
372 1.10 rillig void
373 1.10 rillig debug_dinfo(const dinfo_t *d) // NOLINT(misc-no-recursion)
374 1.10 rillig {
375 1.10 rillig
376 1.10 rillig debug_print_indent();
377 1.17 rillig debug_printf("dinfo: %s", declaration_kind_name(d->d_kind));
378 1.10 rillig if (d->d_scl != NOSCL)
379 1.10 rillig debug_printf(" %s", scl_name(d->d_scl));
380 1.10 rillig if (d->d_type != NULL) {
381 1.10 rillig debug_printf(" '%s'", type_name(d->d_type));
382 1.10 rillig } else {
383 1.10 rillig if (d->d_abstract_type != NOTSPEC)
384 1.10 rillig debug_printf(" %s", tspec_name(d->d_abstract_type));
385 1.10 rillig if (d->d_complex_mod != NOTSPEC)
386 1.10 rillig debug_printf(" %s", tspec_name(d->d_complex_mod));
387 1.10 rillig if (d->d_sign_mod != NOTSPEC)
388 1.10 rillig debug_printf(" %s", tspec_name(d->d_sign_mod));
389 1.10 rillig if (d->d_rank_mod != NOTSPEC)
390 1.10 rillig debug_printf(" %s", tspec_name(d->d_rank_mod));
391 1.10 rillig }
392 1.10 rillig if (d->d_redeclared_symbol != NULL)
393 1.10 rillig debug_sym(" redeclared=(", d->d_redeclared_symbol, ")");
394 1.16 rillig if (d->d_offset_in_bits != 0)
395 1.16 rillig debug_printf(" offset=%u", d->d_offset_in_bits);
396 1.10 rillig if (d->d_sou_align_in_bits != 0)
397 1.10 rillig debug_printf(" align=%u", (unsigned)d->d_sou_align_in_bits);
398 1.10 rillig
399 1.26 rillig debug_word(d->d_const, "const");
400 1.26 rillig debug_word(d->d_volatile, "volatile");
401 1.26 rillig debug_word(d->d_inline, "inline");
402 1.26 rillig debug_word(d->d_multiple_storage_classes, "multiple_storage_classes");
403 1.26 rillig debug_word(d->d_invalid_type_combination, "invalid_type_combination");
404 1.26 rillig debug_word(d->d_nonempty_decl, "nonempty_decl");
405 1.26 rillig debug_word(d->d_vararg, "vararg");
406 1.26 rillig debug_word(d->d_proto, "prototype");
407 1.26 rillig debug_word(d->d_notyp, "no_type_specifier");
408 1.26 rillig debug_word(d->d_asm, "asm");
409 1.26 rillig debug_word(d->d_packed, "packed");
410 1.26 rillig debug_word(d->d_used, "used");
411 1.10 rillig
412 1.10 rillig if (d->d_tagtyp != NULL)
413 1.10 rillig debug_printf(" tagtyp='%s'", type_name(d->d_tagtyp));
414 1.10 rillig for (const sym_t *arg = d->d_func_args;
415 1.10 rillig arg != NULL; arg = arg->s_next)
416 1.10 rillig debug_sym(" arg(", arg, ")");
417 1.10 rillig if (d->d_func_def_pos.p_file != NULL)
418 1.10 rillig debug_printf(" func_def_pos=%s:%d:%d",
419 1.10 rillig d->d_func_def_pos.p_file, d->d_func_def_pos.p_line,
420 1.10 rillig d->d_func_def_pos.p_uniq);
421 1.10 rillig for (const sym_t *sym = d->d_func_proto_syms;
422 1.10 rillig sym != NULL; sym = sym->s_next)
423 1.23 rillig debug_sym(" func_proto_sym(", sym, ")");
424 1.9 rillig debug_printf("\n");
425 1.10 rillig
426 1.11 rillig if (d->d_enclosing != NULL) {
427 1.10 rillig debug_indent_inc();
428 1.11 rillig debug_dinfo(d->d_enclosing);
429 1.10 rillig debug_indent_dec();
430 1.10 rillig }
431 1.9 rillig }
432 1.1 rillig #endif
433