debug.c revision 1.23 1 1.23 rillig /* $NetBSD: debug.c,v 1.23 2022/07/16 22:23:38 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.23 rillig __RCSID("$NetBSD: debug.c,v 1.23 2022/07/16 22:23:38 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.1 rillig (debug_enter)(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.1 rillig (debug_leave)(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.1 rillig if (op == NAME)
169 1.20 rillig debug_printf("\n");
170 1.1 rillig else if (op == CON && is_floating(tn->tn_type->t_tspec))
171 1.19 rillig debug_printf(", value %Lg\n", tn->tn_val->v_ldbl);
172 1.1 rillig else if (op == CON && is_uinteger(tn->tn_type->t_tspec))
173 1.9 rillig debug_printf(", value %llu\n",
174 1.9 rillig (unsigned long long)tn->tn_val->v_quad);
175 1.1 rillig else if (op == CON && is_integer(tn->tn_type->t_tspec))
176 1.9 rillig debug_printf(", value %lld\n",
177 1.9 rillig (long long)tn->tn_val->v_quad);
178 1.6 rillig else if (op == CON && tn->tn_type->t_tspec == BOOL)
179 1.6 rillig debug_printf(", value %s\n",
180 1.6 rillig tn->tn_val->v_quad != 0 ? "true" : "false");
181 1.1 rillig else if (op == CON)
182 1.2 rillig debug_printf(", unknown value\n");
183 1.8 rillig else if (op == STRING && tn->tn_string->st_char)
184 1.2 rillig debug_printf(", length %zu, \"%s\"\n",
185 1.8 rillig tn->tn_string->st_len,
186 1.8 rillig (const char *)tn->tn_string->st_mem);
187 1.8 rillig else if (op == STRING) {
188 1.8 rillig size_t n = MB_CUR_MAX * (tn->tn_string->st_len + 1);
189 1.8 rillig char *s = xmalloc(n);
190 1.8 rillig (void)wcstombs(s, tn->tn_string->st_mem, n);
191 1.19 rillig debug_printf(", length %zu, L\"%s\"\n",
192 1.2 rillig tn->tn_string->st_len, s);
193 1.2 rillig free(s);
194 1.2 rillig
195 1.2 rillig } else {
196 1.2 rillig debug_printf("\n");
197 1.1 rillig
198 1.2 rillig debug_indent_inc();
199 1.2 rillig debug_node(tn->tn_left);
200 1.3 rillig if (is_binary(tn) || tn->tn_right != NULL)
201 1.2 rillig debug_node(tn->tn_right);
202 1.2 rillig debug_indent_dec();
203 1.1 rillig }
204 1.1 rillig }
205 1.1 rillig
206 1.9 rillig static const char *
207 1.9 rillig def_name(def_t def)
208 1.9 rillig {
209 1.9 rillig static const char *const name[] = {
210 1.9 rillig "not-declared",
211 1.9 rillig "declared",
212 1.9 rillig "tentative-defined",
213 1.9 rillig "defined",
214 1.9 rillig };
215 1.9 rillig
216 1.9 rillig return name[def];
217 1.9 rillig }
218 1.9 rillig
219 1.9 rillig const char *
220 1.17 rillig declaration_kind_name(declaration_kind dk)
221 1.17 rillig {
222 1.17 rillig static const char *const name[] = {
223 1.17 rillig "extern",
224 1.17 rillig "member-of-struct",
225 1.17 rillig "member-of-union",
226 1.17 rillig "enum-constant",
227 1.17 rillig "old-style-function-argument",
228 1.17 rillig "prototype-argument",
229 1.17 rillig "auto",
230 1.17 rillig "abstract",
231 1.17 rillig };
232 1.17 rillig
233 1.17 rillig return name[dk];
234 1.17 rillig }
235 1.17 rillig
236 1.17 rillig const char *
237 1.9 rillig scl_name(scl_t scl)
238 1.9 rillig {
239 1.9 rillig static const char *const name[] = {
240 1.9 rillig "none",
241 1.9 rillig "extern",
242 1.9 rillig "static",
243 1.9 rillig "auto",
244 1.9 rillig "register",
245 1.9 rillig "typedef",
246 1.9 rillig "struct",
247 1.9 rillig "union",
248 1.9 rillig "enum",
249 1.9 rillig "member-of-struct",
250 1.9 rillig "member-of-union",
251 1.9 rillig "abstract",
252 1.9 rillig "old-style-function-argument",
253 1.9 rillig "prototype-argument",
254 1.9 rillig "inline",
255 1.9 rillig };
256 1.9 rillig
257 1.9 rillig return name[scl];
258 1.9 rillig }
259 1.9 rillig
260 1.9 rillig const char *
261 1.9 rillig symt_name(symt_t kind)
262 1.9 rillig {
263 1.9 rillig static const char *const name[] = {
264 1.9 rillig "var-func-type",
265 1.9 rillig "member",
266 1.9 rillig "tag",
267 1.9 rillig "label",
268 1.9 rillig };
269 1.9 rillig
270 1.9 rillig return name[kind];
271 1.9 rillig }
272 1.9 rillig
273 1.9 rillig const char *
274 1.9 rillig tqual_name(tqual_t qual)
275 1.9 rillig {
276 1.9 rillig static const char *const name[] = {
277 1.9 rillig "const",
278 1.9 rillig "volatile",
279 1.9 rillig "restrict",
280 1.9 rillig "_Thread_local",
281 1.9 rillig };
282 1.9 rillig
283 1.9 rillig return name[qual];
284 1.9 rillig }
285 1.9 rillig
286 1.9 rillig static void
287 1.9 rillig debug_word(bool flag, const char *name)
288 1.9 rillig {
289 1.9 rillig
290 1.9 rillig if (flag)
291 1.9 rillig debug_printf(" %s", name);
292 1.9 rillig }
293 1.9 rillig
294 1.9 rillig void
295 1.10 rillig debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
296 1.9 rillig {
297 1.9 rillig
298 1.21 rillig if (suffix[0] == '\n')
299 1.21 rillig debug_print_indent();
300 1.10 rillig debug_printf("%s%s", prefix, sym->s_name);
301 1.9 rillig if (sym->s_type != NULL)
302 1.9 rillig debug_printf(" type='%s'", type_name(sym->s_type));
303 1.9 rillig if (sym->s_rename != NULL)
304 1.9 rillig debug_printf(" rename=%s", sym->s_rename);
305 1.9 rillig debug_printf(" %s", symt_name(sym->s_kind));
306 1.9 rillig debug_word(sym->s_keyword != NULL, "keyword");
307 1.9 rillig debug_word(sym->s_bitfield, "bit-field");
308 1.9 rillig debug_word(sym->s_set, "set");
309 1.9 rillig debug_word(sym->s_used, "used");
310 1.9 rillig debug_word(sym->s_arg, "argument");
311 1.9 rillig debug_word(sym->s_register, "register");
312 1.9 rillig debug_word(sym->s_defarg, "old-style-undefined");
313 1.9 rillig debug_word(sym->s_return_type_implicit_int, "return-int");
314 1.9 rillig debug_word(sym->s_osdef, "old-style");
315 1.9 rillig debug_word(sym->s_inline, "inline");
316 1.9 rillig debug_word(sym->s_ext_sym != NULL, "has-external");
317 1.9 rillig debug_word(sym->s_scl != NOSCL, scl_name(sym->s_scl));
318 1.9 rillig debug_word(sym->s_keyword == NULL, def_name(sym->s_def));
319 1.9 rillig
320 1.9 rillig if (sym->s_def_pos.p_file != NULL)
321 1.9 rillig debug_printf(" defined-at=%s:%d",
322 1.9 rillig sym->s_def_pos.p_file, sym->s_def_pos.p_line);
323 1.9 rillig if (sym->s_set_pos.p_file != NULL)
324 1.9 rillig debug_printf(" set-at=%s:%d",
325 1.9 rillig sym->s_set_pos.p_file, sym->s_set_pos.p_line);
326 1.9 rillig if (sym->s_use_pos.p_file != NULL)
327 1.9 rillig debug_printf(" used-at=%s:%d",
328 1.9 rillig sym->s_use_pos.p_file, sym->s_use_pos.p_line);
329 1.9 rillig
330 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_is_enum)
331 1.14 rillig debug_printf(" value=%d", sym->u.s_enum_constant);
332 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_tspec == BOOL)
333 1.14 rillig debug_printf(" value=%s",
334 1.14 rillig sym->u.s_bool_constant ? "true" : "false");
335 1.9 rillig
336 1.15 rillig if (is_member(sym) && sym->u.s_member.sm_sou_type != NULL) {
337 1.14 rillig struct_or_union *sou_type = sym->u.s_member.sm_sou_type;
338 1.14 rillig const char *tag = sou_type->sou_tag->s_name;
339 1.14 rillig const sym_t *def = sou_type->sou_first_typedef;
340 1.9 rillig if (tag == unnamed && def != NULL)
341 1.9 rillig debug_printf(" sou='typedef %s'", def->s_name);
342 1.9 rillig else
343 1.9 rillig debug_printf(" sou=%s", tag);
344 1.9 rillig }
345 1.9 rillig
346 1.9 rillig if (sym->s_keyword != NULL) {
347 1.14 rillig int t = sym->u.s_keyword.sk_token;
348 1.9 rillig if (t == T_TYPE || t == T_STRUCT_OR_UNION)
349 1.14 rillig debug_printf(" %s",
350 1.14 rillig tspec_name(sym->u.s_keyword.sk_tspec));
351 1.9 rillig else if (t == T_QUAL)
352 1.14 rillig debug_printf(" %s",
353 1.14 rillig tqual_name(sym->u.s_keyword.sk_qualifier));
354 1.9 rillig }
355 1.9 rillig
356 1.12 rillig debug_word(sym->s_osdef && sym->u.s_old_style_args != NULL,
357 1.12 rillig "old-style-args");
358 1.9 rillig
359 1.10 rillig debug_printf("%s", suffix);
360 1.10 rillig }
361 1.10 rillig
362 1.10 rillig void
363 1.10 rillig debug_dinfo(const dinfo_t *d) // NOLINT(misc-no-recursion)
364 1.10 rillig {
365 1.10 rillig
366 1.10 rillig debug_print_indent();
367 1.17 rillig debug_printf("dinfo: %s", declaration_kind_name(d->d_kind));
368 1.10 rillig if (d->d_scl != NOSCL)
369 1.10 rillig debug_printf(" %s", scl_name(d->d_scl));
370 1.10 rillig if (d->d_type != NULL) {
371 1.10 rillig debug_printf(" '%s'", type_name(d->d_type));
372 1.10 rillig } else {
373 1.10 rillig if (d->d_abstract_type != NOTSPEC)
374 1.10 rillig debug_printf(" %s", tspec_name(d->d_abstract_type));
375 1.10 rillig if (d->d_complex_mod != NOTSPEC)
376 1.10 rillig debug_printf(" %s", tspec_name(d->d_complex_mod));
377 1.10 rillig if (d->d_sign_mod != NOTSPEC)
378 1.10 rillig debug_printf(" %s", tspec_name(d->d_sign_mod));
379 1.10 rillig if (d->d_rank_mod != NOTSPEC)
380 1.10 rillig debug_printf(" %s", tspec_name(d->d_rank_mod));
381 1.10 rillig }
382 1.10 rillig if (d->d_redeclared_symbol != NULL)
383 1.10 rillig debug_sym(" redeclared=(", d->d_redeclared_symbol, ")");
384 1.16 rillig if (d->d_offset_in_bits != 0)
385 1.16 rillig debug_printf(" offset=%u", d->d_offset_in_bits);
386 1.10 rillig if (d->d_sou_align_in_bits != 0)
387 1.10 rillig debug_printf(" align=%u", (unsigned)d->d_sou_align_in_bits);
388 1.10 rillig
389 1.10 rillig if (d->d_const)
390 1.10 rillig debug_printf(" const");
391 1.10 rillig if (d->d_volatile)
392 1.10 rillig debug_printf(" volatile");
393 1.10 rillig if (d->d_inline)
394 1.10 rillig debug_printf(" inline");
395 1.10 rillig if (d->d_multiple_storage_classes)
396 1.10 rillig debug_printf(" multiple_storage_classes");
397 1.10 rillig if (d->d_invalid_type_combination)
398 1.10 rillig debug_printf(" invalid_type_combination");
399 1.10 rillig if (d->d_nonempty_decl)
400 1.10 rillig debug_printf(" nonempty_decl");
401 1.10 rillig if (d->d_vararg)
402 1.10 rillig debug_printf(" vararg");
403 1.10 rillig if (d->d_proto)
404 1.10 rillig debug_printf(" prototype");
405 1.10 rillig if (d->d_notyp)
406 1.10 rillig debug_printf(" no_type_specifier");
407 1.10 rillig if (d->d_asm)
408 1.10 rillig debug_printf(" asm");
409 1.10 rillig if (d->d_packed)
410 1.10 rillig debug_printf(" packed");
411 1.10 rillig if (d->d_used)
412 1.10 rillig debug_printf(" used");
413 1.10 rillig
414 1.10 rillig if (d->d_tagtyp != NULL)
415 1.10 rillig debug_printf(" tagtyp='%s'", type_name(d->d_tagtyp));
416 1.10 rillig for (const sym_t *arg = d->d_func_args;
417 1.10 rillig arg != NULL; arg = arg->s_next)
418 1.10 rillig debug_sym(" arg(", arg, ")");
419 1.10 rillig if (d->d_func_def_pos.p_file != NULL)
420 1.10 rillig debug_printf(" func_def_pos=%s:%d:%d",
421 1.10 rillig d->d_func_def_pos.p_file, d->d_func_def_pos.p_line,
422 1.10 rillig d->d_func_def_pos.p_uniq);
423 1.10 rillig for (const sym_t *sym = d->d_func_proto_syms;
424 1.10 rillig sym != NULL; sym = sym->s_next)
425 1.23 rillig debug_sym(" func_proto_sym(", sym, ")");
426 1.9 rillig debug_printf("\n");
427 1.10 rillig
428 1.11 rillig if (d->d_enclosing != NULL) {
429 1.10 rillig debug_indent_inc();
430 1.11 rillig debug_dinfo(d->d_enclosing);
431 1.10 rillig debug_indent_dec();
432 1.10 rillig }
433 1.9 rillig }
434 1.1 rillig #endif
435