debug.c revision 1.46 1 1.46 rillig /* $NetBSD: debug.c,v 1.46 2023/07/02 18:28:15 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.46 rillig __RCSID("$NetBSD: debug.c,v 1.46 2023/07/02 18:28:15 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.44 rillig tp->t_sou->sou_size_in_bits, tp->t_sou->sou_align_in_bits,
130 1.38 rillig tp->t_sou->sou_incomplete ? "incomplete" : "complete");
131 1.38 rillig
132 1.29 rillig for (const sym_t *mem = tp->t_sou->sou_first_member;
133 1.22 rillig mem != NULL; mem = mem->s_next) {
134 1.22 rillig debug_sym("", mem, "\n");
135 1.22 rillig debug_type_details(mem->s_type);
136 1.22 rillig }
137 1.22 rillig debug_indent_dec();
138 1.22 rillig }
139 1.22 rillig if (tp->t_is_enum) {
140 1.22 rillig debug_indent_inc();
141 1.22 rillig for (const sym_t *en = tp->t_enum->en_first_enumerator;
142 1.22 rillig en != NULL; en = en->s_next) {
143 1.22 rillig debug_sym("", en, "\n");
144 1.22 rillig }
145 1.22 rillig debug_indent_dec();
146 1.22 rillig }
147 1.22 rillig }
148 1.22 rillig
149 1.22 rillig void
150 1.22 rillig debug_type(const type_t *tp)
151 1.22 rillig {
152 1.22 rillig
153 1.22 rillig debug_step("type details for '%s':", type_name(tp));
154 1.22 rillig debug_type_details(tp);
155 1.22 rillig }
156 1.22 rillig
157 1.1 rillig void
158 1.10 rillig debug_node(const tnode_t *tn) // NOLINT(misc-no-recursion)
159 1.1 rillig {
160 1.1 rillig op_t op;
161 1.1 rillig
162 1.1 rillig if (tn == NULL) {
163 1.2 rillig debug_step("null");
164 1.1 rillig return;
165 1.1 rillig }
166 1.1 rillig
167 1.1 rillig op = tn->tn_op;
168 1.7 rillig debug_print_indent();
169 1.20 rillig debug_printf("'%s'",
170 1.20 rillig op == CVT && !tn->tn_cast ? "convert" : modtab[op].m_name);
171 1.20 rillig if (op == NAME)
172 1.20 rillig debug_printf(" '%s' with %s",
173 1.20 rillig tn->tn_sym->s_name,
174 1.20 rillig storage_class_name(tn->tn_sym->s_scl));
175 1.20 rillig else
176 1.20 rillig debug_printf(" type");
177 1.20 rillig debug_printf(" '%s'", type_name(tn->tn_type));
178 1.20 rillig if (tn->tn_lvalue)
179 1.20 rillig debug_printf(", lvalue");
180 1.20 rillig if (tn->tn_parenthesized)
181 1.20 rillig debug_printf(", parenthesized");
182 1.20 rillig if (tn->tn_sys)
183 1.20 rillig debug_printf(", sys");
184 1.1 rillig
185 1.24 rillig switch (op) {
186 1.24 rillig case NAME:
187 1.20 rillig debug_printf("\n");
188 1.24 rillig break;
189 1.24 rillig case CON:
190 1.24 rillig if (is_floating(tn->tn_type->t_tspec))
191 1.45 rillig debug_printf(", value %Lg", tn->tn_val.u.floating);
192 1.24 rillig else if (is_uinteger(tn->tn_type->t_tspec))
193 1.27 rillig debug_printf(", value %llu",
194 1.45 rillig (unsigned long long)tn->tn_val.u.integer);
195 1.24 rillig else if (is_integer(tn->tn_type->t_tspec))
196 1.27 rillig debug_printf(", value %lld",
197 1.45 rillig (long long)tn->tn_val.u.integer);
198 1.27 rillig else {
199 1.27 rillig lint_assert(tn->tn_type->t_tspec == BOOL);
200 1.27 rillig debug_printf(", value %s",
201 1.45 rillig tn->tn_val.u.integer != 0 ? "true" : "false");
202 1.27 rillig }
203 1.36 rillig if (tn->tn_val.v_unsigned_since_c90)
204 1.27 rillig debug_printf(", unsigned_since_c90");
205 1.36 rillig if (tn->tn_val.v_char_constant)
206 1.35 rillig debug_printf(", char_constant");
207 1.27 rillig debug_printf("\n");
208 1.24 rillig break;
209 1.24 rillig case STRING:
210 1.24 rillig if (tn->tn_string->st_char)
211 1.24 rillig debug_printf(", length %zu, \"%s\"\n",
212 1.24 rillig tn->tn_string->st_len,
213 1.24 rillig (const char *)tn->tn_string->st_mem);
214 1.24 rillig else {
215 1.24 rillig size_t n = MB_CUR_MAX * (tn->tn_string->st_len + 1);
216 1.24 rillig char *s = xmalloc(n);
217 1.24 rillig (void)wcstombs(s, tn->tn_string->st_mem, n);
218 1.24 rillig debug_printf(", length %zu, L\"%s\"\n",
219 1.24 rillig tn->tn_string->st_len, s);
220 1.24 rillig free(s);
221 1.24 rillig }
222 1.24 rillig break;
223 1.24 rillig default:
224 1.2 rillig debug_printf("\n");
225 1.1 rillig
226 1.2 rillig debug_indent_inc();
227 1.30 rillig lint_assert(tn->tn_left != NULL);
228 1.2 rillig debug_node(tn->tn_left);
229 1.33 rillig if (op != INCBEF && op != INCAFT
230 1.33 rillig && op != DECBEF && op != DECAFT)
231 1.33 rillig lint_assert(is_binary(tn) == (tn->tn_right != NULL));
232 1.30 rillig if (tn->tn_right != NULL)
233 1.2 rillig debug_node(tn->tn_right);
234 1.2 rillig debug_indent_dec();
235 1.1 rillig }
236 1.1 rillig }
237 1.1 rillig
238 1.9 rillig static const char *
239 1.9 rillig def_name(def_t def)
240 1.9 rillig {
241 1.9 rillig static const char *const name[] = {
242 1.9 rillig "not-declared",
243 1.9 rillig "declared",
244 1.9 rillig "tentative-defined",
245 1.9 rillig "defined",
246 1.9 rillig };
247 1.9 rillig
248 1.9 rillig return name[def];
249 1.9 rillig }
250 1.9 rillig
251 1.9 rillig const char *
252 1.40 rillig decl_level_kind_name(decl_level_kind kind)
253 1.17 rillig {
254 1.17 rillig static const char *const name[] = {
255 1.17 rillig "extern",
256 1.40 rillig "struct",
257 1.40 rillig "union",
258 1.40 rillig "enum",
259 1.40 rillig "old-style-function-arguments",
260 1.40 rillig "prototype-parameters",
261 1.17 rillig "auto",
262 1.17 rillig "abstract",
263 1.17 rillig };
264 1.17 rillig
265 1.40 rillig return name[kind];
266 1.17 rillig }
267 1.17 rillig
268 1.17 rillig const char *
269 1.9 rillig scl_name(scl_t scl)
270 1.9 rillig {
271 1.9 rillig static const char *const name[] = {
272 1.9 rillig "none",
273 1.9 rillig "extern",
274 1.9 rillig "static",
275 1.9 rillig "auto",
276 1.9 rillig "register",
277 1.9 rillig "typedef",
278 1.9 rillig "struct",
279 1.9 rillig "union",
280 1.9 rillig "enum",
281 1.9 rillig "member-of-struct",
282 1.9 rillig "member-of-union",
283 1.9 rillig "abstract",
284 1.9 rillig "old-style-function-argument",
285 1.9 rillig "prototype-argument",
286 1.9 rillig "inline",
287 1.9 rillig };
288 1.9 rillig
289 1.9 rillig return name[scl];
290 1.9 rillig }
291 1.9 rillig
292 1.9 rillig const char *
293 1.9 rillig symt_name(symt_t kind)
294 1.9 rillig {
295 1.9 rillig static const char *const name[] = {
296 1.9 rillig "var-func-type",
297 1.9 rillig "member",
298 1.9 rillig "tag",
299 1.9 rillig "label",
300 1.9 rillig };
301 1.9 rillig
302 1.9 rillig return name[kind];
303 1.9 rillig }
304 1.9 rillig
305 1.9 rillig const char *
306 1.9 rillig tqual_name(tqual_t qual)
307 1.9 rillig {
308 1.9 rillig static const char *const name[] = {
309 1.9 rillig "const",
310 1.9 rillig "volatile",
311 1.9 rillig "restrict",
312 1.9 rillig "_Thread_local",
313 1.25 rillig "_Atomic",
314 1.9 rillig };
315 1.9 rillig
316 1.9 rillig return name[qual];
317 1.9 rillig }
318 1.9 rillig
319 1.9 rillig static void
320 1.9 rillig debug_word(bool flag, const char *name)
321 1.9 rillig {
322 1.9 rillig
323 1.9 rillig if (flag)
324 1.9 rillig debug_printf(" %s", name);
325 1.9 rillig }
326 1.9 rillig
327 1.9 rillig void
328 1.10 rillig debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
329 1.9 rillig {
330 1.9 rillig
331 1.21 rillig if (suffix[0] == '\n')
332 1.21 rillig debug_print_indent();
333 1.10 rillig debug_printf("%s%s", prefix, sym->s_name);
334 1.9 rillig if (sym->s_type != NULL)
335 1.9 rillig debug_printf(" type='%s'", type_name(sym->s_type));
336 1.9 rillig if (sym->s_rename != NULL)
337 1.9 rillig debug_printf(" rename=%s", sym->s_rename);
338 1.9 rillig debug_printf(" %s", symt_name(sym->s_kind));
339 1.9 rillig debug_word(sym->s_keyword != NULL, "keyword");
340 1.9 rillig debug_word(sym->s_bitfield, "bit-field");
341 1.9 rillig debug_word(sym->s_set, "set");
342 1.9 rillig debug_word(sym->s_used, "used");
343 1.9 rillig debug_word(sym->s_arg, "argument");
344 1.9 rillig debug_word(sym->s_register, "register");
345 1.9 rillig debug_word(sym->s_defarg, "old-style-undefined");
346 1.9 rillig debug_word(sym->s_return_type_implicit_int, "return-int");
347 1.9 rillig debug_word(sym->s_osdef, "old-style");
348 1.9 rillig debug_word(sym->s_inline, "inline");
349 1.9 rillig debug_word(sym->s_ext_sym != NULL, "has-external");
350 1.9 rillig debug_word(sym->s_scl != NOSCL, scl_name(sym->s_scl));
351 1.9 rillig debug_word(sym->s_keyword == NULL, def_name(sym->s_def));
352 1.9 rillig
353 1.9 rillig if (sym->s_def_pos.p_file != NULL)
354 1.9 rillig debug_printf(" defined-at=%s:%d",
355 1.9 rillig sym->s_def_pos.p_file, sym->s_def_pos.p_line);
356 1.9 rillig if (sym->s_set_pos.p_file != NULL)
357 1.9 rillig debug_printf(" set-at=%s:%d",
358 1.9 rillig sym->s_set_pos.p_file, sym->s_set_pos.p_line);
359 1.9 rillig if (sym->s_use_pos.p_file != NULL)
360 1.9 rillig debug_printf(" used-at=%s:%d",
361 1.9 rillig sym->s_use_pos.p_file, sym->s_use_pos.p_line);
362 1.9 rillig
363 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_is_enum)
364 1.14 rillig debug_printf(" value=%d", sym->u.s_enum_constant);
365 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_tspec == BOOL)
366 1.14 rillig debug_printf(" value=%s",
367 1.14 rillig sym->u.s_bool_constant ? "true" : "false");
368 1.9 rillig
369 1.39 rillig if (is_member(sym)) {
370 1.42 rillig struct_or_union *sou = sym->u.s_member.sm_containing_type;
371 1.42 rillig const char *tag = sou->sou_tag->s_name;
372 1.42 rillig const sym_t *def = sou->sou_first_typedef;
373 1.9 rillig if (tag == unnamed && def != NULL)
374 1.9 rillig debug_printf(" sou='typedef %s'", def->s_name);
375 1.9 rillig else
376 1.42 rillig debug_printf(" sou='%s'", tag);
377 1.9 rillig }
378 1.9 rillig
379 1.9 rillig if (sym->s_keyword != NULL) {
380 1.14 rillig int t = sym->u.s_keyword.sk_token;
381 1.9 rillig if (t == T_TYPE || t == T_STRUCT_OR_UNION)
382 1.14 rillig debug_printf(" %s",
383 1.14 rillig tspec_name(sym->u.s_keyword.sk_tspec));
384 1.42 rillig if (t == T_QUAL)
385 1.14 rillig debug_printf(" %s",
386 1.14 rillig tqual_name(sym->u.s_keyword.sk_qualifier));
387 1.9 rillig }
388 1.9 rillig
389 1.12 rillig debug_word(sym->s_osdef && sym->u.s_old_style_args != NULL,
390 1.12 rillig "old-style-args");
391 1.9 rillig
392 1.10 rillig debug_printf("%s", suffix);
393 1.10 rillig }
394 1.10 rillig
395 1.43 rillig static void
396 1.43 rillig debug_decl_level(const decl_level *dl)
397 1.10 rillig {
398 1.10 rillig
399 1.10 rillig debug_print_indent();
400 1.40 rillig debug_printf("decl_level: %s", decl_level_kind_name(dl->d_kind));
401 1.40 rillig if (dl->d_scl != NOSCL)
402 1.40 rillig debug_printf(" %s", scl_name(dl->d_scl));
403 1.40 rillig if (dl->d_type != NULL)
404 1.40 rillig debug_printf(" '%s'", type_name(dl->d_type));
405 1.40 rillig else {
406 1.40 rillig if (dl->d_abstract_type != NO_TSPEC)
407 1.40 rillig debug_printf(" %s", tspec_name(dl->d_abstract_type));
408 1.40 rillig if (dl->d_complex_mod != NO_TSPEC)
409 1.40 rillig debug_printf(" %s", tspec_name(dl->d_complex_mod));
410 1.40 rillig if (dl->d_sign_mod != NO_TSPEC)
411 1.40 rillig debug_printf(" %s", tspec_name(dl->d_sign_mod));
412 1.40 rillig if (dl->d_rank_mod != NO_TSPEC)
413 1.40 rillig debug_printf(" %s", tspec_name(dl->d_rank_mod));
414 1.10 rillig }
415 1.40 rillig if (dl->d_redeclared_symbol != NULL)
416 1.40 rillig debug_sym(" redeclared=(", dl->d_redeclared_symbol, ")");
417 1.46 rillig if (dl->d_sou_size_in_bits != 0)
418 1.46 rillig debug_printf(" size=%u", dl->d_sou_size_in_bits);
419 1.40 rillig if (dl->d_sou_align_in_bits != 0)
420 1.44 rillig debug_printf(" align=%u", dl->d_sou_align_in_bits);
421 1.40 rillig
422 1.40 rillig debug_word(dl->d_const, "const");
423 1.40 rillig debug_word(dl->d_volatile, "volatile");
424 1.40 rillig debug_word(dl->d_inline, "inline");
425 1.40 rillig debug_word(dl->d_multiple_storage_classes, "multiple_storage_classes");
426 1.40 rillig debug_word(dl->d_invalid_type_combination, "invalid_type_combination");
427 1.40 rillig debug_word(dl->d_nonempty_decl, "nonempty_decl");
428 1.40 rillig debug_word(dl->d_vararg, "vararg");
429 1.40 rillig debug_word(dl->d_prototype, "prototype");
430 1.40 rillig debug_word(dl->d_no_type_specifier, "no_type_specifier");
431 1.40 rillig debug_word(dl->d_asm, "asm");
432 1.40 rillig debug_word(dl->d_packed, "packed");
433 1.40 rillig debug_word(dl->d_used, "used");
434 1.40 rillig
435 1.40 rillig if (dl->d_tag_type != NULL)
436 1.40 rillig debug_printf(" tag_type='%s'", type_name(dl->d_tag_type));
437 1.40 rillig for (const sym_t *arg = dl->d_func_args;
438 1.10 rillig arg != NULL; arg = arg->s_next)
439 1.10 rillig debug_sym(" arg(", arg, ")");
440 1.40 rillig if (dl->d_func_def_pos.p_file != NULL)
441 1.41 rillig debug_printf(" func_def_pos=%s:%d:%d",
442 1.40 rillig dl->d_func_def_pos.p_file, dl->d_func_def_pos.p_line,
443 1.40 rillig dl->d_func_def_pos.p_uniq);
444 1.40 rillig for (const sym_t *sym = dl->d_func_proto_syms;
445 1.10 rillig sym != NULL; sym = sym->s_next)
446 1.23 rillig debug_sym(" func_proto_sym(", sym, ")");
447 1.9 rillig debug_printf("\n");
448 1.43 rillig }
449 1.10 rillig
450 1.43 rillig void
451 1.43 rillig debug_dcs(bool all)
452 1.43 rillig {
453 1.43 rillig int prev_indentation = debug_indentation;
454 1.43 rillig for (const decl_level *dl = dcs; dl != NULL; dl = dl->d_enclosing) {
455 1.43 rillig debug_decl_level(dl);
456 1.43 rillig if (!all)
457 1.43 rillig return;
458 1.43 rillig debug_indentation++;
459 1.10 rillig }
460 1.43 rillig debug_indentation = prev_indentation;
461 1.9 rillig }
462 1.1 rillig #endif
463