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