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