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 }