debug.c revision 1.38 1 1.38 rillig /* $NetBSD: debug.c,v 1.38 2023/06/30 14:39:23 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.38 rillig __RCSID("$NetBSD: debug.c,v 1.38 2023/06/30 14:39:23 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.32 rillig static FILE *
53 1.32 rillig debug_file(void)
54 1.32 rillig {
55 1.32 rillig /*
56 1.32 rillig * Using stdout preserves the order between the debug messages and
57 1.32 rillig * lint's diagnostics.
58 1.32 rillig *
59 1.32 rillig * Using stderr preserves the order between lint's debug messages and
60 1.32 rillig * yacc's debug messages (see the -y option).
61 1.32 rillig */
62 1.32 rillig return stdout;
63 1.32 rillig }
64 1.32 rillig
65 1.34 rillig void
66 1.1 rillig debug_printf(const char *fmt, ...)
67 1.1 rillig {
68 1.1 rillig va_list va;
69 1.1 rillig
70 1.1 rillig va_start(va, fmt);
71 1.32 rillig (void)vfprintf(debug_file(), fmt, va);
72 1.1 rillig va_end(va);
73 1.1 rillig }
74 1.1 rillig
75 1.1 rillig void
76 1.7 rillig debug_print_indent(void)
77 1.1 rillig {
78 1.1 rillig
79 1.1 rillig debug_printf("%*s", 2 * debug_indentation, "");
80 1.1 rillig }
81 1.1 rillig
82 1.1 rillig void
83 1.1 rillig debug_indent_inc(void)
84 1.1 rillig {
85 1.1 rillig
86 1.1 rillig debug_indentation++;
87 1.1 rillig }
88 1.1 rillig
89 1.1 rillig void
90 1.1 rillig debug_indent_dec(void)
91 1.1 rillig {
92 1.1 rillig
93 1.1 rillig debug_indentation--;
94 1.1 rillig }
95 1.1 rillig
96 1.1 rillig void
97 1.28 rillig debug_enter_func(const char *func)
98 1.1 rillig {
99 1.1 rillig
100 1.32 rillig fprintf(debug_file(), "%*s+ %s\n", 2 * debug_indentation++, "", func);
101 1.1 rillig }
102 1.1 rillig
103 1.34 rillig void
104 1.1 rillig debug_step(const char *fmt, ...)
105 1.1 rillig {
106 1.1 rillig va_list va;
107 1.1 rillig
108 1.7 rillig debug_print_indent();
109 1.1 rillig va_start(va, fmt);
110 1.32 rillig (void)vfprintf(debug_file(), fmt, va);
111 1.1 rillig va_end(va);
112 1.32 rillig fprintf(debug_file(), "\n");
113 1.1 rillig }
114 1.1 rillig
115 1.1 rillig void
116 1.28 rillig debug_leave_func(const char *func)
117 1.1 rillig {
118 1.1 rillig
119 1.32 rillig fprintf(debug_file(), "%*s- %s\n", 2 * --debug_indentation, "", func);
120 1.1 rillig }
121 1.1 rillig
122 1.22 rillig static void
123 1.22 rillig debug_type_details(const type_t *tp)
124 1.22 rillig {
125 1.22 rillig
126 1.22 rillig if (is_struct_or_union(tp->t_tspec)) {
127 1.22 rillig debug_indent_inc();
128 1.38 rillig debug_step("size %u bits, align %u bits, %s",
129 1.38 rillig tp->t_sou->sou_size_in_bits,
130 1.38 rillig (unsigned int)tp->t_sou->sou_align_in_bits,
131 1.38 rillig tp->t_sou->sou_incomplete ? "incomplete" : "complete");
132 1.38 rillig
133 1.29 rillig for (const sym_t *mem = tp->t_sou->sou_first_member;
134 1.22 rillig mem != NULL; mem = mem->s_next) {
135 1.22 rillig debug_sym("", mem, "\n");
136 1.22 rillig debug_type_details(mem->s_type);
137 1.22 rillig }
138 1.22 rillig debug_indent_dec();
139 1.22 rillig }
140 1.22 rillig if (tp->t_is_enum) {
141 1.22 rillig debug_indent_inc();
142 1.22 rillig for (const sym_t *en = tp->t_enum->en_first_enumerator;
143 1.22 rillig en != NULL; en = en->s_next) {
144 1.22 rillig debug_sym("", en, "\n");
145 1.22 rillig }
146 1.22 rillig debug_indent_dec();
147 1.22 rillig }
148 1.22 rillig }
149 1.22 rillig
150 1.22 rillig void
151 1.22 rillig debug_type(const type_t *tp)
152 1.22 rillig {
153 1.22 rillig
154 1.22 rillig debug_step("type details for '%s':", type_name(tp));
155 1.22 rillig debug_type_details(tp);
156 1.22 rillig }
157 1.22 rillig
158 1.1 rillig void
159 1.10 rillig debug_node(const tnode_t *tn) // NOLINT(misc-no-recursion)
160 1.1 rillig {
161 1.1 rillig op_t op;
162 1.1 rillig
163 1.1 rillig if (tn == NULL) {
164 1.2 rillig debug_step("null");
165 1.1 rillig return;
166 1.1 rillig }
167 1.1 rillig
168 1.1 rillig op = tn->tn_op;
169 1.7 rillig debug_print_indent();
170 1.20 rillig debug_printf("'%s'",
171 1.20 rillig op == CVT && !tn->tn_cast ? "convert" : modtab[op].m_name);
172 1.20 rillig if (op == NAME)
173 1.20 rillig debug_printf(" '%s' with %s",
174 1.20 rillig tn->tn_sym->s_name,
175 1.20 rillig storage_class_name(tn->tn_sym->s_scl));
176 1.20 rillig else
177 1.20 rillig debug_printf(" type");
178 1.20 rillig debug_printf(" '%s'", type_name(tn->tn_type));
179 1.20 rillig if (tn->tn_lvalue)
180 1.20 rillig debug_printf(", lvalue");
181 1.20 rillig if (tn->tn_parenthesized)
182 1.20 rillig debug_printf(", parenthesized");
183 1.20 rillig if (tn->tn_sys)
184 1.20 rillig debug_printf(", sys");
185 1.1 rillig
186 1.24 rillig switch (op) {
187 1.24 rillig case NAME:
188 1.20 rillig debug_printf("\n");
189 1.24 rillig break;
190 1.24 rillig case CON:
191 1.24 rillig if (is_floating(tn->tn_type->t_tspec))
192 1.36 rillig debug_printf(", value %Lg", tn->tn_val.v_ldbl);
193 1.24 rillig else if (is_uinteger(tn->tn_type->t_tspec))
194 1.27 rillig debug_printf(", value %llu",
195 1.36 rillig (unsigned long long)tn->tn_val.v_quad);
196 1.24 rillig else if (is_integer(tn->tn_type->t_tspec))
197 1.27 rillig debug_printf(", value %lld",
198 1.36 rillig (long long)tn->tn_val.v_quad);
199 1.27 rillig else {
200 1.27 rillig lint_assert(tn->tn_type->t_tspec == BOOL);
201 1.27 rillig debug_printf(", value %s",
202 1.36 rillig tn->tn_val.v_quad != 0 ? "true" : "false");
203 1.27 rillig }
204 1.36 rillig if (tn->tn_val.v_unsigned_since_c90)
205 1.27 rillig debug_printf(", unsigned_since_c90");
206 1.36 rillig if (tn->tn_val.v_char_constant)
207 1.35 rillig debug_printf(", char_constant");
208 1.27 rillig debug_printf("\n");
209 1.24 rillig break;
210 1.24 rillig case STRING:
211 1.24 rillig if (tn->tn_string->st_char)
212 1.24 rillig debug_printf(", length %zu, \"%s\"\n",
213 1.24 rillig tn->tn_string->st_len,
214 1.24 rillig (const char *)tn->tn_string->st_mem);
215 1.24 rillig else {
216 1.24 rillig size_t n = MB_CUR_MAX * (tn->tn_string->st_len + 1);
217 1.24 rillig char *s = xmalloc(n);
218 1.24 rillig (void)wcstombs(s, tn->tn_string->st_mem, n);
219 1.24 rillig debug_printf(", length %zu, L\"%s\"\n",
220 1.24 rillig tn->tn_string->st_len, s);
221 1.24 rillig free(s);
222 1.24 rillig }
223 1.24 rillig break;
224 1.24 rillig default:
225 1.2 rillig debug_printf("\n");
226 1.1 rillig
227 1.2 rillig debug_indent_inc();
228 1.30 rillig lint_assert(tn->tn_left != NULL);
229 1.2 rillig debug_node(tn->tn_left);
230 1.33 rillig if (op != INCBEF && op != INCAFT
231 1.33 rillig && op != DECBEF && op != DECAFT)
232 1.33 rillig lint_assert(is_binary(tn) == (tn->tn_right != NULL));
233 1.30 rillig if (tn->tn_right != NULL)
234 1.2 rillig debug_node(tn->tn_right);
235 1.2 rillig debug_indent_dec();
236 1.1 rillig }
237 1.1 rillig }
238 1.1 rillig
239 1.9 rillig static const char *
240 1.9 rillig def_name(def_t def)
241 1.9 rillig {
242 1.9 rillig static const char *const name[] = {
243 1.9 rillig "not-declared",
244 1.9 rillig "declared",
245 1.9 rillig "tentative-defined",
246 1.9 rillig "defined",
247 1.9 rillig };
248 1.9 rillig
249 1.9 rillig return name[def];
250 1.9 rillig }
251 1.9 rillig
252 1.9 rillig const char *
253 1.17 rillig declaration_kind_name(declaration_kind dk)
254 1.17 rillig {
255 1.17 rillig static const char *const name[] = {
256 1.17 rillig "extern",
257 1.17 rillig "member-of-struct",
258 1.17 rillig "member-of-union",
259 1.17 rillig "enum-constant",
260 1.17 rillig "old-style-function-argument",
261 1.17 rillig "prototype-argument",
262 1.17 rillig "auto",
263 1.17 rillig "abstract",
264 1.17 rillig };
265 1.17 rillig
266 1.17 rillig return name[dk];
267 1.17 rillig }
268 1.17 rillig
269 1.17 rillig const char *
270 1.9 rillig scl_name(scl_t scl)
271 1.9 rillig {
272 1.9 rillig static const char *const name[] = {
273 1.9 rillig "none",
274 1.9 rillig "extern",
275 1.9 rillig "static",
276 1.9 rillig "auto",
277 1.9 rillig "register",
278 1.9 rillig "typedef",
279 1.9 rillig "struct",
280 1.9 rillig "union",
281 1.9 rillig "enum",
282 1.9 rillig "member-of-struct",
283 1.9 rillig "member-of-union",
284 1.9 rillig "abstract",
285 1.9 rillig "old-style-function-argument",
286 1.9 rillig "prototype-argument",
287 1.9 rillig "inline",
288 1.9 rillig };
289 1.9 rillig
290 1.9 rillig return name[scl];
291 1.9 rillig }
292 1.9 rillig
293 1.9 rillig const char *
294 1.9 rillig symt_name(symt_t kind)
295 1.9 rillig {
296 1.9 rillig static const char *const name[] = {
297 1.9 rillig "var-func-type",
298 1.9 rillig "member",
299 1.9 rillig "tag",
300 1.9 rillig "label",
301 1.9 rillig };
302 1.9 rillig
303 1.9 rillig return name[kind];
304 1.9 rillig }
305 1.9 rillig
306 1.9 rillig const char *
307 1.9 rillig tqual_name(tqual_t qual)
308 1.9 rillig {
309 1.9 rillig static const char *const name[] = {
310 1.9 rillig "const",
311 1.9 rillig "volatile",
312 1.9 rillig "restrict",
313 1.9 rillig "_Thread_local",
314 1.25 rillig "_Atomic",
315 1.9 rillig };
316 1.9 rillig
317 1.9 rillig return name[qual];
318 1.9 rillig }
319 1.9 rillig
320 1.9 rillig static void
321 1.9 rillig debug_word(bool flag, const char *name)
322 1.9 rillig {
323 1.9 rillig
324 1.9 rillig if (flag)
325 1.9 rillig debug_printf(" %s", name);
326 1.9 rillig }
327 1.9 rillig
328 1.9 rillig void
329 1.10 rillig debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
330 1.9 rillig {
331 1.9 rillig
332 1.21 rillig if (suffix[0] == '\n')
333 1.21 rillig debug_print_indent();
334 1.10 rillig debug_printf("%s%s", prefix, sym->s_name);
335 1.9 rillig if (sym->s_type != NULL)
336 1.9 rillig debug_printf(" type='%s'", type_name(sym->s_type));
337 1.9 rillig if (sym->s_rename != NULL)
338 1.9 rillig debug_printf(" rename=%s", sym->s_rename);
339 1.9 rillig debug_printf(" %s", symt_name(sym->s_kind));
340 1.9 rillig debug_word(sym->s_keyword != NULL, "keyword");
341 1.9 rillig debug_word(sym->s_bitfield, "bit-field");
342 1.9 rillig debug_word(sym->s_set, "set");
343 1.9 rillig debug_word(sym->s_used, "used");
344 1.9 rillig debug_word(sym->s_arg, "argument");
345 1.9 rillig debug_word(sym->s_register, "register");
346 1.9 rillig debug_word(sym->s_defarg, "old-style-undefined");
347 1.9 rillig debug_word(sym->s_return_type_implicit_int, "return-int");
348 1.9 rillig debug_word(sym->s_osdef, "old-style");
349 1.9 rillig debug_word(sym->s_inline, "inline");
350 1.9 rillig debug_word(sym->s_ext_sym != NULL, "has-external");
351 1.9 rillig debug_word(sym->s_scl != NOSCL, scl_name(sym->s_scl));
352 1.9 rillig debug_word(sym->s_keyword == NULL, def_name(sym->s_def));
353 1.9 rillig
354 1.9 rillig if (sym->s_def_pos.p_file != NULL)
355 1.9 rillig debug_printf(" defined-at=%s:%d",
356 1.9 rillig sym->s_def_pos.p_file, sym->s_def_pos.p_line);
357 1.9 rillig if (sym->s_set_pos.p_file != NULL)
358 1.9 rillig debug_printf(" set-at=%s:%d",
359 1.9 rillig sym->s_set_pos.p_file, sym->s_set_pos.p_line);
360 1.9 rillig if (sym->s_use_pos.p_file != NULL)
361 1.9 rillig debug_printf(" used-at=%s:%d",
362 1.9 rillig sym->s_use_pos.p_file, sym->s_use_pos.p_line);
363 1.9 rillig
364 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_is_enum)
365 1.14 rillig debug_printf(" value=%d", sym->u.s_enum_constant);
366 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_tspec == BOOL)
367 1.14 rillig debug_printf(" value=%s",
368 1.14 rillig sym->u.s_bool_constant ? "true" : "false");
369 1.9 rillig
370 1.15 rillig if (is_member(sym) && sym->u.s_member.sm_sou_type != NULL) {
371 1.14 rillig struct_or_union *sou_type = sym->u.s_member.sm_sou_type;
372 1.14 rillig const char *tag = sou_type->sou_tag->s_name;
373 1.14 rillig const sym_t *def = sou_type->sou_first_typedef;
374 1.9 rillig if (tag == unnamed && def != NULL)
375 1.9 rillig debug_printf(" sou='typedef %s'", def->s_name);
376 1.9 rillig else
377 1.9 rillig debug_printf(" sou=%s", tag);
378 1.9 rillig }
379 1.9 rillig
380 1.9 rillig if (sym->s_keyword != NULL) {
381 1.14 rillig int t = sym->u.s_keyword.sk_token;
382 1.9 rillig if (t == T_TYPE || t == T_STRUCT_OR_UNION)
383 1.14 rillig debug_printf(" %s",
384 1.14 rillig tspec_name(sym->u.s_keyword.sk_tspec));
385 1.9 rillig else if (t == T_QUAL)
386 1.14 rillig debug_printf(" %s",
387 1.14 rillig tqual_name(sym->u.s_keyword.sk_qualifier));
388 1.9 rillig }
389 1.9 rillig
390 1.12 rillig debug_word(sym->s_osdef && sym->u.s_old_style_args != NULL,
391 1.12 rillig "old-style-args");
392 1.9 rillig
393 1.10 rillig debug_printf("%s", suffix);
394 1.10 rillig }
395 1.10 rillig
396 1.10 rillig void
397 1.10 rillig debug_dinfo(const dinfo_t *d) // NOLINT(misc-no-recursion)
398 1.10 rillig {
399 1.10 rillig
400 1.10 rillig debug_print_indent();
401 1.17 rillig debug_printf("dinfo: %s", declaration_kind_name(d->d_kind));
402 1.10 rillig if (d->d_scl != NOSCL)
403 1.10 rillig debug_printf(" %s", scl_name(d->d_scl));
404 1.10 rillig if (d->d_type != NULL) {
405 1.10 rillig debug_printf(" '%s'", type_name(d->d_type));
406 1.10 rillig } else {
407 1.31 rillig if (d->d_abstract_type != NO_TSPEC)
408 1.10 rillig debug_printf(" %s", tspec_name(d->d_abstract_type));
409 1.31 rillig if (d->d_complex_mod != NO_TSPEC)
410 1.10 rillig debug_printf(" %s", tspec_name(d->d_complex_mod));
411 1.31 rillig if (d->d_sign_mod != NO_TSPEC)
412 1.10 rillig debug_printf(" %s", tspec_name(d->d_sign_mod));
413 1.31 rillig if (d->d_rank_mod != NO_TSPEC)
414 1.10 rillig debug_printf(" %s", tspec_name(d->d_rank_mod));
415 1.10 rillig }
416 1.10 rillig if (d->d_redeclared_symbol != NULL)
417 1.10 rillig debug_sym(" redeclared=(", d->d_redeclared_symbol, ")");
418 1.16 rillig if (d->d_offset_in_bits != 0)
419 1.16 rillig debug_printf(" offset=%u", d->d_offset_in_bits);
420 1.10 rillig if (d->d_sou_align_in_bits != 0)
421 1.10 rillig debug_printf(" align=%u", (unsigned)d->d_sou_align_in_bits);
422 1.10 rillig
423 1.26 rillig debug_word(d->d_const, "const");
424 1.26 rillig debug_word(d->d_volatile, "volatile");
425 1.26 rillig debug_word(d->d_inline, "inline");
426 1.26 rillig debug_word(d->d_multiple_storage_classes, "multiple_storage_classes");
427 1.26 rillig debug_word(d->d_invalid_type_combination, "invalid_type_combination");
428 1.26 rillig debug_word(d->d_nonempty_decl, "nonempty_decl");
429 1.26 rillig debug_word(d->d_vararg, "vararg");
430 1.37 rillig debug_word(d->d_prototype, "prototype");
431 1.37 rillig debug_word(d->d_no_type_specifier, "no_type_specifier");
432 1.26 rillig debug_word(d->d_asm, "asm");
433 1.26 rillig debug_word(d->d_packed, "packed");
434 1.26 rillig debug_word(d->d_used, "used");
435 1.10 rillig
436 1.37 rillig if (d->d_tag_type != NULL)
437 1.37 rillig debug_printf(" tag_type='%s'", type_name(d->d_tag_type));
438 1.10 rillig for (const sym_t *arg = d->d_func_args;
439 1.10 rillig arg != NULL; arg = arg->s_next)
440 1.10 rillig debug_sym(" arg(", arg, ")");
441 1.10 rillig if (d->d_func_def_pos.p_file != NULL)
442 1.10 rillig debug_printf(" func_def_pos=%s:%d:%d",
443 1.10 rillig d->d_func_def_pos.p_file, d->d_func_def_pos.p_line,
444 1.10 rillig d->d_func_def_pos.p_uniq);
445 1.10 rillig for (const sym_t *sym = d->d_func_proto_syms;
446 1.10 rillig sym != NULL; sym = sym->s_next)
447 1.23 rillig debug_sym(" func_proto_sym(", sym, ")");
448 1.9 rillig debug_printf("\n");
449 1.10 rillig
450 1.11 rillig if (d->d_enclosing != NULL) {
451 1.10 rillig debug_indent_inc();
452 1.11 rillig debug_dinfo(d->d_enclosing);
453 1.10 rillig debug_indent_dec();
454 1.10 rillig }
455 1.9 rillig }
456 1.1 rillig #endif
457