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