1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1985-1998 by Symantec 6 * Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/debug.c, backend/debugprint.d) 10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/debug.c 11 */ 12 13 module dmd.backend.debugprint; 14 15 version (SCPP) 16 version = COMPILE; 17 version (MARS) 18 version = COMPILE; 19 version (HTOD) 20 version = COMPILE; 21 22 version (COMPILE) 23 { 24 25 import core.stdc.stdio; 26 import core.stdc.stdlib; 27 import core.stdc.string; 28 29 import dmd.backend.cdef; 30 import dmd.backend.cc; 31 import dmd.backend.el; 32 import dmd.backend.global; 33 import dmd.backend.code; 34 import dmd.backend.code_x86; 35 import dmd.backend.goh; 36 import dmd.backend.oper; 37 import dmd.backend.symtab; 38 import dmd.backend.ty; 39 import dmd.backend.type; 40 41 import dmd.backend.dlist; 42 import dmd.backend.dvec; 43 44 extern (C++): 45 46 nothrow: 47 48 void ferr(const(char)* p) { printf("%s", p); } 49 50 /******************************* 51 * Write out storage class. 52 */ 53 54 const(char)* str_class(SC c) 55 { 56 __gshared const char[10][SCMAX] sc = 57 [ 58 "unde", 59 "auto", 60 "static", 61 "thread", 62 "extern", 63 "register", 64 "pseudo", 65 "global", 66 "comdat", 67 "parameter", 68 "regpar", 69 "fastpar", 70 "shadowreg", 71 "typedef", 72 "explicit", 73 "mutable", 74 "label", 75 "struct", 76 "enum", 77 "field", 78 "const", 79 "member", 80 "anon", 81 "inline", 82 "sinline", 83 "einline", 84 "overload", 85 "friend", 86 "virtual", 87 "locstat", 88 "template", 89 "functempl", 90 "ftexpspec", 91 "linkage", 92 "public", 93 "comdef", 94 "bprel", 95 "namespace", 96 "alias", 97 "funcalias", 98 "memalias", 99 "stack", 100 "adl", 101 ]; 102 __gshared char[9 + 3] buffer; 103 104 static assert(sc.length == SCMAX); 105 if (cast(uint) c < SCMAX) 106 sprintf(buffer.ptr,"SC%s",sc[c].ptr); 107 else 108 sprintf(buffer.ptr,"SC%u",cast(uint)c); 109 return buffer.ptr; 110 } 111 112 void WRclass(SC c) 113 { 114 printf("%11s ",str_class(c)); 115 } 116 117 /*************************** 118 * Write out oper numbers. 119 */ 120 121 void WROP(uint oper) 122 { 123 if (oper >= OPMAX) 124 { printf("op = x%x, OPMAX = %d\n",oper,OPMAX); 125 assert(0); 126 } 127 ferr(debtab[oper]); 128 ferr(" "); 129 } 130 131 /******************************* 132 * Write TYxxxx 133 */ 134 135 void WRTYxx(tym_t t) 136 { 137 if (t & mTYnear) 138 printf("mTYnear|"); 139 if (t & mTYfar) 140 printf("mTYfar|"); 141 if (t & mTYcs) 142 printf("mTYcs|"); 143 if (t & mTYconst) 144 printf("mTYconst|"); 145 if (t & mTYvolatile) 146 printf("mTYvolatile|"); 147 if (t & mTYshared) 148 printf("mTYshared|"); 149 //#if !MARS && (__linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun) 150 // if (t & mTYtransu) 151 // printf("mTYtransu|"); 152 //#endif 153 t = tybasic(t); 154 if (t >= TYMAX) 155 { printf("TY %x\n",cast(int)t); 156 assert(0); 157 } 158 printf("TY%s ",tystring[tybasic(t)]); 159 } 160 161 void WRBC(uint bc) 162 { 163 __gshared const char[7][BCMAX] bcs = 164 ["unde ","goto ","true ","ret ","retexp", 165 "exit ","asm ","switch","ifthen","jmptab", 166 "try ","catch ","jump ", 167 "_try ","_filte","_final","_ret ","_excep", 168 "jcatch","_lpad ", 169 ]; 170 171 assert(bc < BCMAX); 172 printf("BC%s",bcs[bc].ptr); 173 } 174 175 /************************ 176 * Write arglst 177 */ 178 179 void WRarglst(list_t a) 180 { int n = 1; 181 182 if (!a) printf("0 args\n"); 183 while (a) 184 { const(char)* c = cast(const(char)*)list_ptr(a); 185 printf("arg %d: '%s'\n", n, c ? c : "NULL"); 186 a = a.next; 187 n++; 188 } 189 } 190 191 /*************************** 192 * Write out equation elem. 193 */ 194 195 void WReqn(elem *e) 196 { __gshared int nest; 197 198 if (!e) 199 return; 200 if (OTunary(e.Eoper)) 201 { 202 WROP(e.Eoper); 203 if (OTbinary(e.EV.E1.Eoper)) 204 { nest++; 205 ferr("("); 206 WReqn(e.EV.E1); 207 ferr(")"); 208 nest--; 209 } 210 else 211 WReqn(e.EV.E1); 212 } 213 else if (e.Eoper == OPcomma && !nest) 214 { WReqn(e.EV.E1); 215 printf(";\n\t"); 216 WReqn(e.EV.E2); 217 } 218 else if (OTbinary(e.Eoper)) 219 { 220 if (OTbinary(e.EV.E1.Eoper)) 221 { nest++; 222 ferr("("); 223 WReqn(e.EV.E1); 224 ferr(")"); 225 nest--; 226 } 227 else 228 WReqn(e.EV.E1); 229 ferr(" "); 230 WROP(e.Eoper); 231 if (e.Eoper == OPstreq) 232 printf("%d", cast(int)type_size(e.ET)); 233 ferr(" "); 234 if (OTbinary(e.EV.E2.Eoper)) 235 { nest++; 236 ferr("("); 237 WReqn(e.EV.E2); 238 ferr(")"); 239 nest--; 240 } 241 else 242 WReqn(e.EV.E2); 243 } 244 else 245 { 246 switch (e.Eoper) 247 { case OPconst: 248 elem_print_const(e); 249 break; 250 case OPrelconst: 251 ferr("#"); 252 goto case OPvar; 253 254 case OPvar: 255 printf("%s",e.EV.Vsym.Sident.ptr); 256 if (e.EV.Vsym.Ssymnum != SYMIDX.max) 257 printf("(%d)", cast(int) e.EV.Vsym.Ssymnum); 258 if (e.EV.Voffset != 0) 259 { 260 if (e.EV.Voffset.sizeof == 8) 261 printf(".x%llx", cast(ulong)e.EV.Voffset); 262 else 263 printf(".%d",cast(int)e.EV.Voffset); 264 } 265 break; 266 case OPasm: 267 case OPstring: 268 printf("\"%s\"",e.EV.Vstring); 269 if (e.EV.Voffset) 270 printf("+%lld",cast(long)e.EV.Voffset); 271 break; 272 case OPmark: 273 case OPgot: 274 case OPframeptr: 275 case OPhalt: 276 case OPdctor: 277 case OPddtor: 278 WROP(e.Eoper); 279 break; 280 case OPstrthis: 281 break; 282 default: 283 WROP(e.Eoper); 284 assert(0); 285 } 286 } 287 } 288 289 void WRblocklist(list_t bl) 290 { 291 foreach (bl2; ListRange(bl)) 292 { 293 block *b = list_block(bl2); 294 295 if (b && b.Bweight) 296 printf("B%d (%p) ",b.Bdfoidx,b); 297 else 298 printf("%p ",b); 299 } 300 ferr("\n"); 301 } 302 303 void WRdefnod() 304 { int i; 305 306 for (i = 0; i < go.defnod.length; i++) 307 { printf("defnod[%d] in B%d = (", go.defnod[i].DNblock.Bdfoidx, i); 308 WReqn(go.defnod[i].DNelem); 309 printf(");\n"); 310 } 311 } 312 313 void WRFL(FL fl) 314 { 315 __gshared const(char)[7][FLMAX] fls = 316 [ "unde ","const ","oper ","func ","data ", 317 "reg ", 318 "pseudo", 319 "auto ","fast ","para ","extrn ", 320 "code ","block ","udata ","cs ","swit ", 321 "fltrg ","offst ","datsg ", 322 "ctor ","dtor ","regsav","asm ", 323 "ndp ", 324 "farda ","csdat ", 325 "local ","tlsdat", 326 "bprel ","frameh","blocko","alloca", 327 "stack ","dsym ", 328 "got ","gotoff", 329 "funcar", 330 ]; 331 332 if (cast(uint)fl >= FLMAX) 333 printf("FL%d",fl); 334 else 335 printf("FL%s",fls[fl].ptr); 336 } 337 338 /*********************** 339 * Write out block. 340 */ 341 342 void WRblock(block *b) 343 { 344 if (OPTIMIZER) 345 { 346 if (b && b.Bweight) 347 printf("B%d: (%p), weight=%d",b.Bdfoidx,b,b.Bweight); 348 else 349 printf("block %p",b); 350 if (!b) 351 { ferr("\n"); 352 return; 353 } 354 printf(" flags=x%x weight=%d",b.Bflags,b.Bweight); 355 //printf("\tfile %p, line %d",b.Bfilptr,b.Blinnum); 356 printf(" "); 357 WRBC(b.BC); 358 printf(" Btry=%p Bindex=%d",b.Btry,b.Bindex); 359 if (b.BC == BCtry) 360 printf(" catchvar = %p",b.catchvar); 361 printf("\n"); 362 printf("\tBpred: "); WRblocklist(b.Bpred); 363 printf("\tBsucc: "); WRblocklist(b.Bsucc); 364 if (b.Belem) 365 { if (debugf) /* if full output */ 366 elem_print(b.Belem); 367 else 368 { ferr("\t"); 369 WReqn(b.Belem); 370 printf(";\n"); 371 } 372 } 373 version (MARS) 374 { 375 if (b.Bcode) 376 b.Bcode.print(); 377 } 378 version (SCPP) 379 { 380 if (b.Bcode) 381 b.Bcode.print(); 382 } 383 ferr("\n"); 384 } 385 else 386 { 387 targ_llong *pu; 388 int ncases; 389 390 assert(b); 391 printf("%2d: ", b.Bnumber); WRBC(b.BC); 392 if (b.Btry) 393 printf(" Btry=B%d",b.Btry ? b.Btry.Bnumber : 0); 394 if (b.Bindex) 395 printf(" Bindex=%d",b.Bindex); 396 if (b.BC == BC_finally) 397 printf(" b_ret=B%d", b.b_ret ? b.b_ret.Bnumber : 0); 398 version (MARS) 399 { 400 if (b.Bsrcpos.Sfilename) 401 printf(" %s(%u)", b.Bsrcpos.Sfilename, b.Bsrcpos.Slinnum); 402 } 403 printf("\n"); 404 if (b.Belem) 405 { 406 if (debugf) 407 elem_print(b.Belem); 408 else 409 { 410 ferr("\t"); 411 WReqn(b.Belem); 412 printf(";\n"); 413 } 414 } 415 if (b.Bpred) 416 { 417 printf("\tBpred:"); 418 foreach (bl; ListRange(b.Bpred)) 419 printf(" B%d",list_block(bl).Bnumber); 420 printf("\n"); 421 } 422 list_t bl = b.Bsucc; 423 switch (b.BC) 424 { 425 case BCswitch: 426 pu = b.Bswitch; 427 assert(pu); 428 ncases = cast(int)*pu; 429 printf("\tncases = %d\n",ncases); 430 printf("\tdefault: B%d\n",list_block(bl) ? list_block(bl).Bnumber : 0); 431 while (ncases--) 432 { bl = list_next(bl); 433 printf("\tcase %lld: B%d\n", cast(long)*++pu,list_block(bl).Bnumber); 434 } 435 break; 436 case BCiftrue: 437 case BCgoto: 438 case BCasm: 439 case BCtry: 440 case BCcatch: 441 case BCjcatch: 442 case BC_try: 443 case BC_filter: 444 case BC_finally: 445 case BC_lpad: 446 case BC_ret: 447 case BC_except: 448 449 if (bl) 450 { 451 printf("\tBsucc:"); 452 for ( ; bl; bl = list_next(bl)) 453 printf(" B%d",list_block(bl).Bnumber); 454 printf("\n"); 455 } 456 break; 457 case BCret: 458 case BCretexp: 459 case BCexit: 460 break; 461 default: 462 printf("bc = %d\n", b.BC); 463 assert(0); 464 } 465 } 466 } 467 468 /***************************** 469 * Number the blocks starting at 1. 470 * So much more convenient than pointer values. 471 */ 472 void numberBlocks(block *startblock) 473 { 474 uint number = 0; 475 for (block *b = startblock; b; b = b.Bnext) 476 b.Bnumber = ++number; 477 } 478 479 void WRfunc() 480 { 481 printf("func: '%s'\n",funcsym_p.Sident.ptr); 482 483 numberBlocks(startblock); 484 485 for (block *b = startblock; b; b = b.Bnext) 486 WRblock(b); 487 } 488 489 }