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