debug.c revision 1.18 1 1.18 rillig /* $NetBSD: debug.c,v 1.18 2022/05/20 21:18:55 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.18 rillig __RCSID("$NetBSD: debug.c,v 1.18 2022/05/20 21:18:55 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.1 rillig void
110 1.10 rillig debug_node(const tnode_t *tn) // NOLINT(misc-no-recursion)
111 1.1 rillig {
112 1.1 rillig op_t op;
113 1.1 rillig
114 1.1 rillig if (tn == NULL) {
115 1.2 rillig debug_step("null");
116 1.1 rillig return;
117 1.1 rillig }
118 1.1 rillig
119 1.1 rillig op = tn->tn_op;
120 1.7 rillig debug_print_indent();
121 1.4 rillig debug_printf("'%s' with type '%s'%s%s%s",
122 1.1 rillig op == CVT && !tn->tn_cast ? "convert" : modtab[op].m_name,
123 1.1 rillig type_name(tn->tn_type), tn->tn_lvalue ? ", lvalue" : "",
124 1.4 rillig tn->tn_parenthesized ? ", parenthesized" : "",
125 1.5 rillig tn->tn_sys ? ", sys" : "");
126 1.1 rillig
127 1.1 rillig if (op == NAME)
128 1.2 rillig debug_printf(" %s %s\n", tn->tn_sym->s_name,
129 1.2 rillig storage_class_name(tn->tn_sym->s_scl));
130 1.1 rillig else if (op == CON && is_floating(tn->tn_type->t_tspec))
131 1.2 rillig debug_printf(", value %Lg", tn->tn_val->v_ldbl);
132 1.1 rillig else if (op == CON && is_uinteger(tn->tn_type->t_tspec))
133 1.9 rillig debug_printf(", value %llu\n",
134 1.9 rillig (unsigned long long)tn->tn_val->v_quad);
135 1.1 rillig else if (op == CON && is_integer(tn->tn_type->t_tspec))
136 1.9 rillig debug_printf(", value %lld\n",
137 1.9 rillig (long long)tn->tn_val->v_quad);
138 1.6 rillig else if (op == CON && tn->tn_type->t_tspec == BOOL)
139 1.6 rillig debug_printf(", value %s\n",
140 1.6 rillig tn->tn_val->v_quad != 0 ? "true" : "false");
141 1.1 rillig else if (op == CON)
142 1.2 rillig debug_printf(", unknown value\n");
143 1.8 rillig else if (op == STRING && tn->tn_string->st_char)
144 1.2 rillig debug_printf(", length %zu, \"%s\"\n",
145 1.8 rillig tn->tn_string->st_len,
146 1.8 rillig (const char *)tn->tn_string->st_mem);
147 1.8 rillig else if (op == STRING) {
148 1.8 rillig size_t n = MB_CUR_MAX * (tn->tn_string->st_len + 1);
149 1.8 rillig char *s = xmalloc(n);
150 1.8 rillig (void)wcstombs(s, tn->tn_string->st_mem, n);
151 1.2 rillig debug_printf(", length %zu, L\"%s\"",
152 1.2 rillig tn->tn_string->st_len, s);
153 1.2 rillig free(s);
154 1.2 rillig
155 1.2 rillig } else {
156 1.2 rillig debug_printf("\n");
157 1.1 rillig
158 1.2 rillig debug_indent_inc();
159 1.2 rillig debug_node(tn->tn_left);
160 1.3 rillig if (is_binary(tn) || tn->tn_right != NULL)
161 1.2 rillig debug_node(tn->tn_right);
162 1.2 rillig debug_indent_dec();
163 1.1 rillig }
164 1.1 rillig }
165 1.1 rillig
166 1.9 rillig static const char *
167 1.9 rillig def_name(def_t def)
168 1.9 rillig {
169 1.9 rillig static const char *const name[] = {
170 1.9 rillig "not-declared",
171 1.9 rillig "declared",
172 1.9 rillig "tentative-defined",
173 1.9 rillig "defined",
174 1.9 rillig };
175 1.9 rillig
176 1.9 rillig return name[def];
177 1.9 rillig }
178 1.9 rillig
179 1.9 rillig const char *
180 1.17 rillig declaration_kind_name(declaration_kind dk)
181 1.17 rillig {
182 1.17 rillig static const char *const name[] = {
183 1.17 rillig "extern",
184 1.17 rillig "member-of-struct",
185 1.17 rillig "member-of-union",
186 1.17 rillig "enum-constant",
187 1.17 rillig "old-style-function-argument",
188 1.17 rillig "prototype-argument",
189 1.17 rillig "auto",
190 1.17 rillig "abstract",
191 1.17 rillig };
192 1.17 rillig
193 1.17 rillig return name[dk];
194 1.17 rillig }
195 1.17 rillig
196 1.17 rillig const char *
197 1.9 rillig scl_name(scl_t scl)
198 1.9 rillig {
199 1.9 rillig static const char *const name[] = {
200 1.9 rillig "none",
201 1.9 rillig "extern",
202 1.9 rillig "static",
203 1.9 rillig "auto",
204 1.9 rillig "register",
205 1.9 rillig "typedef",
206 1.9 rillig "struct",
207 1.9 rillig "union",
208 1.9 rillig "enum",
209 1.9 rillig "member-of-struct",
210 1.9 rillig "member-of-union",
211 1.9 rillig "abstract",
212 1.9 rillig "old-style-function-argument",
213 1.9 rillig "prototype-argument",
214 1.9 rillig "inline",
215 1.9 rillig };
216 1.9 rillig
217 1.9 rillig return name[scl];
218 1.9 rillig }
219 1.9 rillig
220 1.9 rillig const char *
221 1.9 rillig symt_name(symt_t kind)
222 1.9 rillig {
223 1.9 rillig static const char *const name[] = {
224 1.9 rillig "var-func-type",
225 1.9 rillig "member",
226 1.9 rillig "tag",
227 1.9 rillig "label",
228 1.9 rillig };
229 1.9 rillig
230 1.9 rillig return name[kind];
231 1.9 rillig }
232 1.9 rillig
233 1.9 rillig const char *
234 1.9 rillig tqual_name(tqual_t qual)
235 1.9 rillig {
236 1.9 rillig static const char *const name[] = {
237 1.9 rillig "const",
238 1.9 rillig "volatile",
239 1.9 rillig "restrict",
240 1.9 rillig "_Thread_local",
241 1.9 rillig };
242 1.9 rillig
243 1.9 rillig return name[qual];
244 1.9 rillig }
245 1.9 rillig
246 1.9 rillig static void
247 1.9 rillig debug_word(bool flag, const char *name)
248 1.9 rillig {
249 1.9 rillig
250 1.9 rillig if (flag)
251 1.9 rillig debug_printf(" %s", name);
252 1.9 rillig }
253 1.9 rillig
254 1.9 rillig void
255 1.10 rillig debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
256 1.9 rillig {
257 1.9 rillig
258 1.9 rillig debug_print_indent();
259 1.10 rillig debug_printf("%s%s", prefix, sym->s_name);
260 1.9 rillig if (sym->s_type != NULL)
261 1.9 rillig debug_printf(" type='%s'", type_name(sym->s_type));
262 1.9 rillig if (sym->s_rename != NULL)
263 1.9 rillig debug_printf(" rename=%s", sym->s_rename);
264 1.9 rillig debug_printf(" %s", symt_name(sym->s_kind));
265 1.9 rillig debug_word(sym->s_keyword != NULL, "keyword");
266 1.9 rillig debug_word(sym->s_bitfield, "bit-field");
267 1.9 rillig debug_word(sym->s_set, "set");
268 1.9 rillig debug_word(sym->s_used, "used");
269 1.9 rillig debug_word(sym->s_arg, "argument");
270 1.9 rillig debug_word(sym->s_register, "register");
271 1.9 rillig debug_word(sym->s_defarg, "old-style-undefined");
272 1.9 rillig debug_word(sym->s_return_type_implicit_int, "return-int");
273 1.9 rillig debug_word(sym->s_osdef, "old-style");
274 1.9 rillig debug_word(sym->s_inline, "inline");
275 1.9 rillig debug_word(sym->s_ext_sym != NULL, "has-external");
276 1.9 rillig debug_word(sym->s_scl != NOSCL, scl_name(sym->s_scl));
277 1.9 rillig debug_word(sym->s_keyword == NULL, def_name(sym->s_def));
278 1.9 rillig
279 1.9 rillig if (sym->s_def_pos.p_file != NULL)
280 1.9 rillig debug_printf(" defined-at=%s:%d",
281 1.9 rillig sym->s_def_pos.p_file, sym->s_def_pos.p_line);
282 1.9 rillig if (sym->s_set_pos.p_file != NULL)
283 1.9 rillig debug_printf(" set-at=%s:%d",
284 1.9 rillig sym->s_set_pos.p_file, sym->s_set_pos.p_line);
285 1.9 rillig if (sym->s_use_pos.p_file != NULL)
286 1.9 rillig debug_printf(" used-at=%s:%d",
287 1.9 rillig sym->s_use_pos.p_file, sym->s_use_pos.p_line);
288 1.9 rillig
289 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_is_enum)
290 1.14 rillig debug_printf(" value=%d", sym->u.s_enum_constant);
291 1.14 rillig if (sym->s_type != NULL && sym->s_type->t_tspec == BOOL)
292 1.14 rillig debug_printf(" value=%s",
293 1.14 rillig sym->u.s_bool_constant ? "true" : "false");
294 1.9 rillig
295 1.15 rillig if (is_member(sym) && sym->u.s_member.sm_sou_type != NULL) {
296 1.14 rillig struct_or_union *sou_type = sym->u.s_member.sm_sou_type;
297 1.14 rillig const char *tag = sou_type->sou_tag->s_name;
298 1.14 rillig const sym_t *def = sou_type->sou_first_typedef;
299 1.9 rillig if (tag == unnamed && def != NULL)
300 1.9 rillig debug_printf(" sou='typedef %s'", def->s_name);
301 1.9 rillig else
302 1.9 rillig debug_printf(" sou=%s", tag);
303 1.9 rillig }
304 1.9 rillig
305 1.9 rillig if (sym->s_keyword != NULL) {
306 1.14 rillig int t = sym->u.s_keyword.sk_token;
307 1.9 rillig if (t == T_TYPE || t == T_STRUCT_OR_UNION)
308 1.14 rillig debug_printf(" %s",
309 1.14 rillig tspec_name(sym->u.s_keyword.sk_tspec));
310 1.9 rillig else if (t == T_QUAL)
311 1.14 rillig debug_printf(" %s",
312 1.14 rillig tqual_name(sym->u.s_keyword.sk_qualifier));
313 1.9 rillig }
314 1.9 rillig
315 1.12 rillig debug_word(sym->s_osdef && sym->u.s_old_style_args != NULL,
316 1.12 rillig "old-style-args");
317 1.9 rillig
318 1.10 rillig debug_printf("%s", suffix);
319 1.10 rillig }
320 1.10 rillig
321 1.10 rillig void
322 1.10 rillig debug_dinfo(const dinfo_t *d) // NOLINT(misc-no-recursion)
323 1.10 rillig {
324 1.10 rillig
325 1.10 rillig debug_print_indent();
326 1.17 rillig debug_printf("dinfo: %s", declaration_kind_name(d->d_kind));
327 1.10 rillig if (d->d_scl != NOSCL)
328 1.10 rillig debug_printf(" %s", scl_name(d->d_scl));
329 1.10 rillig if (d->d_type != NULL) {
330 1.10 rillig debug_printf(" '%s'", type_name(d->d_type));
331 1.10 rillig } else {
332 1.10 rillig if (d->d_abstract_type != NOTSPEC)
333 1.10 rillig debug_printf(" %s", tspec_name(d->d_abstract_type));
334 1.10 rillig if (d->d_complex_mod != NOTSPEC)
335 1.10 rillig debug_printf(" %s", tspec_name(d->d_complex_mod));
336 1.10 rillig if (d->d_sign_mod != NOTSPEC)
337 1.10 rillig debug_printf(" %s", tspec_name(d->d_sign_mod));
338 1.10 rillig if (d->d_rank_mod != NOTSPEC)
339 1.10 rillig debug_printf(" %s", tspec_name(d->d_rank_mod));
340 1.10 rillig }
341 1.10 rillig if (d->d_redeclared_symbol != NULL)
342 1.10 rillig debug_sym(" redeclared=(", d->d_redeclared_symbol, ")");
343 1.16 rillig if (d->d_offset_in_bits != 0)
344 1.16 rillig debug_printf(" offset=%u", d->d_offset_in_bits);
345 1.10 rillig if (d->d_sou_align_in_bits != 0)
346 1.10 rillig debug_printf(" align=%u", (unsigned)d->d_sou_align_in_bits);
347 1.10 rillig
348 1.10 rillig if (d->d_const)
349 1.10 rillig debug_printf(" const");
350 1.10 rillig if (d->d_volatile)
351 1.10 rillig debug_printf(" volatile");
352 1.10 rillig if (d->d_inline)
353 1.10 rillig debug_printf(" inline");
354 1.10 rillig if (d->d_multiple_storage_classes)
355 1.10 rillig debug_printf(" multiple_storage_classes");
356 1.10 rillig if (d->d_invalid_type_combination)
357 1.10 rillig debug_printf(" invalid_type_combination");
358 1.10 rillig if (d->d_nonempty_decl)
359 1.10 rillig debug_printf(" nonempty_decl");
360 1.10 rillig if (d->d_vararg)
361 1.10 rillig debug_printf(" vararg");
362 1.10 rillig if (d->d_proto)
363 1.10 rillig debug_printf(" prototype");
364 1.10 rillig if (d->d_notyp)
365 1.10 rillig debug_printf(" no_type_specifier");
366 1.10 rillig if (d->d_asm)
367 1.10 rillig debug_printf(" asm");
368 1.10 rillig if (d->d_packed)
369 1.10 rillig debug_printf(" packed");
370 1.10 rillig if (d->d_used)
371 1.10 rillig debug_printf(" used");
372 1.10 rillig
373 1.10 rillig if (d->d_tagtyp != NULL)
374 1.10 rillig debug_printf(" tagtyp='%s'", type_name(d->d_tagtyp));
375 1.10 rillig for (const sym_t *arg = d->d_func_args;
376 1.10 rillig arg != NULL; arg = arg->s_next)
377 1.10 rillig debug_sym(" arg(", arg, ")");
378 1.10 rillig if (d->d_func_def_pos.p_file != NULL)
379 1.10 rillig debug_printf(" func_def_pos=%s:%d:%d",
380 1.10 rillig d->d_func_def_pos.p_file, d->d_func_def_pos.p_line,
381 1.10 rillig d->d_func_def_pos.p_uniq);
382 1.10 rillig for (const sym_t *sym = d->d_func_proto_syms;
383 1.10 rillig sym != NULL; sym = sym->s_next)
384 1.10 rillig debug_sym("func_proto_sym(", sym, ")");
385 1.9 rillig debug_printf("\n");
386 1.10 rillig
387 1.11 rillig if (d->d_enclosing != NULL) {
388 1.10 rillig debug_indent_inc();
389 1.11 rillig debug_dinfo(d->d_enclosing);
390 1.10 rillig debug_indent_dec();
391 1.10 rillig }
392 1.9 rillig }
393 1.1 rillig #endif
394