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 }