1 /*
2  * Copyright (c) 1993-2019, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 /** \file
19  * \brief ILT utility module
20  */
21 
22 #include "iltutil.h"
23 #include "error.h"
24 #include "global.h"
25 #include "symtab.h" /* prerequisite for expand.h and ili.h */
26 #include "ilm.h"
27 #include "fih.h"
28 #include "ili.h"
29 #include "expand.h"
30 #include "ccffinfo.h"
31 
32 #include <stdarg.h>
33 #define MAXILT 67108864
34 
35 static int iltcur;
36 
37 /** \brief Initialize the ILT area
38  */
39 void
ilt_init(void)40 ilt_init(void)
41 {
42   int i;
43 
44   STG_ALLOC(iltb, 128);
45   STG_SET_FREELINK(iltb, ILT, next);
46 }
47 
48 void
ilt_cleanup(void)49 ilt_cleanup(void)
50 {
51   STG_DELETE(iltb);
52 } /* ilt_cleanup */
53 
54 /********************************************************************/
55 
56 /** \brief Add an ilt
57  *
58  * Add an ilt inserting it after the ilt "after"; ilix locates
59  * the ili which represents the root of the ili tree
60  */
61 int
addilt(int after,int ilix)62 addilt(int after, int ilix)
63 {
64   int i;
65   ILT *p;
66   ILTY_KIND type;
67   ILI_OP opc;
68 
69   i = STG_NEXT_FREELIST(iltb);
70   p = iltb.stg_base + i;
71   p->flags.all = 0;
72   p->prev = after;
73   p->next = ILT_NEXT(after);
74   p->lineno = gbl.lineno;
75   p->order = -1;
76   ILT_NEXT(after) = i;
77   ILT_PREV(p->next) = i;
78   p->ilip = ilix;
79   opc = ILI_OPC(ilix);
80   type = IL_TYPE(opc);
81   if (type == ILTY_STORE)
82     p->flags.bits.st = 1;
83   else if (type == ILTY_BRANCH)
84     p->flags.bits.br = 1;
85   p->flags.bits.ex = iltb.callfg;
86   bihb.callfg |= iltb.callfg;
87   bihb.ldvol |= iltb.ldvol;
88   bihb.stvol |= iltb.stvol;
89   bihb.qjsrfg |= iltb.qjsrfg;
90   if (after == 0 && p->next == 0) {
91     /* this is the first ILT for this block */
92     fihb.currfindex = fihb.nextfindex;
93     fihb.currftag = fihb.nextftag;
94   }
95   p->findex = fihb.currfindex;
96   iltb.callfg = 0;
97   iltb.ldvol = 0;
98   iltb.stvol = 0;
99   iltb.qjsrfg = false;
100   return (i);
101 }
102 
103 /** \brief Delete an ilt from a block which is "read" and reuse it
104  */
105 void
delilt(int iltx)106 delilt(int iltx)
107 {
108   int prev, next, ignore, ilip;
109 
110   next = ILT_NEXT(iltx);
111   prev = ILT_PREV(iltx);
112   /* preserve the ILT_ILIP field, ILT_IGNORE flag, set ILT_FREE flag */
113   ignore = ILT_IGNORE(iltx);
114   ilip = ILT_ILIP(iltx);
115   ILT_PREV(next) = prev;
116   ILT_NEXT(prev) = next;
117   STG_ADD_FREELIST(iltb, iltx);
118   ILT_IGNORE(iltx) = ignore;
119   ILT_ILIP(iltx) = ilip;
120   ILT_FREE(iltx) = 1;
121 }
122 
123 /** \brief delete an ilt where the block may not be "read", and possibly reuse
124  * it
125  *
126  * \param iltx    ilt to be deleted
127  * \param bihx    bih of block from which ilt is deleted (0 => read)
128  * \param reuse   true if ilt is to be reused
129  */
130 void
unlnkilt(int iltx,int bihx,bool reuse)131 unlnkilt(int iltx, int bihx, bool reuse)
132 {
133   int i, j;
134 
135   if (bihx) {
136     i = ILT_PREV(iltx);
137     j = ILT_NEXT(iltx);
138     if (j)
139       ILT_PREV(j) = i;
140     else
141       BIH_ILTLAST(bihx) = i;
142     if (i)
143       ILT_NEXT(i) = j;
144     else
145       BIH_ILTFIRST(bihx) = j;
146   } else {
147     j = ILT_NEXT(iltx);
148     i = ILT_PREV(j) = ILT_PREV(iltx);
149     ILT_NEXT(i) = j;
150   }
151   if (reuse) {
152     /* preserve the ILT_ILIP field, ILT_IGNORE flag */
153     int ignore = ILT_IGNORE(iltx);
154     int ilip = ILT_ILIP(iltx);
155     STG_ADD_FREELIST(iltb, iltx);
156     ILT_IGNORE(iltx) = ignore;
157     ILT_ILIP(iltx) = ilip;
158   }
159   ILT_FREE(iltx) = 1;
160   /* else:  hopefully, scans will still work if we start with an ilt which
161    * was removed but not reused
162    */
163 
164 }
165 
166 /*
167  * move an ilt to this BIH after removing it with unlnkilt
168  * iltx = ilt to be added
169  * bihx = bih of block to which ilt is to be added
170  */
171 void
relnkilt(int iltx,int bihx)172 relnkilt(int iltx, int bihx)
173 {
174   int j;
175   j = BIH_ILTLAST(bihx);
176   ILT_PREV(iltx) = j;
177   if (j)
178     ILT_NEXT(j) = iltx;
179   else
180     BIH_ILTFIRST(bihx) = iltx;
181   BIH_ILTLAST(bihx) = iltx;
182   ILT_FREE(iltx) = 0;
183 } /* relnkilt */
184 
185 /********************************************************************/
186 
187 /** \brief Move an ilt before another ilt
188  */
189 void
moveilt(int iltx,int before)190 moveilt(int iltx, int before)
191 {
192   register int i, j;
193 
194   /**  remove iltx from list  **/
195   i = ILT_PREV(iltx);
196   ILT_NEXT(i) = j = ILT_NEXT(iltx);
197   ILT_PREV(j) = i;
198   /**  insert iltx before 'before' **/
199   ILT_PREV(iltx) = i = ILT_PREV(before);
200   ILT_NEXT(i) = iltx;
201   ILT_PREV(before) = iltx;
202   ILT_NEXT(iltx) = before;
203 }
204 
205 /********************************************************************/
206 
207 /**
208   search the ili subtree located by ilix for functions and creating an ilt for
209   each one found.  The static variable iltcur (local to this module indicates
210   where an ilt is added.  iltcur is updated to locate the new ilt
211  */
212 static void
srcfunc(int ilix)213 srcfunc(int ilix)
214 {
215   int noprs; /* number of lnk operands in ilix	 */
216   int i;              /* index variable			 */
217   ILI_OP opc;            /* ili opcode of ilix			 */
218 
219   if (IL_TYPE(opc = ILI_OPC(ilix)) == ILTY_PROC && opc >= IL_JSR) {
220     iltb.callfg = 1;
221     iltcur = addilt(iltcur, ilix); /* create a function ilt */
222   } else if (opc == IL_DFRDP && ILI_OPC(ILI_OPND(ilix, 1)) != IL_QJSR) {
223     iltb.callfg = 1;
224     iltcur = addilt(iltcur, ad1ili(IL_FREEDP, ilix));
225   } else if (opc == IL_DFRSP && ILI_OPC(ILI_OPND(ilix, 1)) != IL_QJSR) {
226     iltb.callfg = 1;
227     iltcur = addilt(iltcur, ad1ili(IL_FREESP, ilix));
228   }
229   else if (opc == IL_DFRCS && ILI_OPC(ILI_OPND(ilix, 1)) != IL_QJSR) {
230     iltb.callfg = 1;
231     iltcur = addilt(iltcur, ad1ili(IL_FREECS, ilix));
232   }
233 #ifdef LONG_DOUBLE_FLOAT128
234   else if (opc == IL_FLOAT128RESULT && ILI_OPC(ILI_OPND(ilix, 1)) != IL_QJSR) {
235     iltb.callfg = 1;
236     iltcur = addilt(iltcur, ad1ili(IL_FLOAT128FREE, ilix));
237   }
238 #endif /* LONG_DOUBLE_FLOAT128 */
239   else {
240     noprs = ilis[opc].oprs;
241     for (i = 1; i <= noprs; i++) {
242       if (IL_ISLINK(opc, i))
243         srcfunc((int)(ILI_OPND(ilix, i)));
244     }
245   }
246 }
247 
248 /********************************************************************/
249 
250 /** \brief Reduce an ilt to a sequence of function ilts
251  *
252  * Reduces the ili tree located by ilix producing ilts which locate function
253  * ilis occuring in ilix.  This routine sets iltucr with iltx which indicates
254  * where ilts are to be added and calls srcfunc.
255  */
256 int
reduce_ilt(int iltx,int ilix)257 reduce_ilt(int iltx, int ilix)
258 {
259   iltcur = iltx; /* avoid passing iltx recursively	 */
260   srcfunc(ilix);
261   return (iltcur);
262 }
263 
264 /********************************************************************/
265 
266 /** \brief Dump ILT to a file
267  *
268  * \param ff - file pointer
269  * \param bihx - BIH number
270  */
271 void
dump_ilt(FILE * ff,int bihx)272 dump_ilt(FILE *ff, int bihx)
273 {
274   int p, q, throw_count;
275 
276   if (ff == NULL)
277     ff = stderr;
278   iltb.privtmp = 0;
279   if (BIH_PAR(bihx) || BIH_TASK(bihx))
280     iltb.privtmp = 2;
281   else
282     iltb.privtmp = 1;
283   fprintf(ff, "\nBlock %5d, line:%6d, label:%6d, assn:%6d, fih:%3d", bihx,
284           BIH_LINENO(bihx), BIH_LABEL(bihx), BIH_ASSN(bihx), BIH_FINDEX(bihx));
285   fprintf(ff, ", flags:");
286   if (BIH_PAR(bihx))
287     fprintf(ff, " PAR");
288   if (BIH_RD(bihx))
289     fprintf(ff, " RD");
290   if (BIH_FT(bihx))
291     fprintf(ff, " FT");
292   if (BIH_EN(bihx))
293     fprintf(ff, " EN");
294   if (BIH_EX(bihx))
295     fprintf(ff, " EX");
296   if (BIH_XT(bihx))
297     fprintf(ff, " XT");
298   if (BIH_LAST(bihx))
299     fprintf(ff, " LAST");
300   if (BIH_PL(bihx))
301     fprintf(ff, " PL");
302   if (BIH_ZTRP(bihx))
303     fprintf(ff, " ZT");
304   if (BIH_NOBLA(bihx))
305     fprintf(ff, " NOBLA");
306   if (BIH_NOMERGE(bihx))
307     fprintf(ff, " NOMERGE");
308 #ifdef BIH_ASM
309   if (BIH_ASM(bihx))
310     fprintf(ff, " ASM");
311 #endif
312   if (BIH_QJSR(bihx))
313     fprintf(ff, " QJSR");
314   if (BIH_HEAD(bihx))
315     fprintf(ff, " HEAD");
316   if (BIH_TAIL(bihx))
317     fprintf(ff, " TAIL");
318   if (BIH_INNERMOST(bihx))
319     fprintf(ff, " INNERMOST");
320 #ifdef BIH_GUARDEE
321   if (BIH_GUARDEE(bihx))
322     fprintf(ff, " GUARDEE");
323 #endif
324 #ifdef BIH_GUARDER
325   if (BIH_GUARDER(bihx))
326     fprintf(ff, " GUARDER");
327 #endif
328   if (BIH_MEXITS(bihx))
329     fprintf(ff, " MEXITS");
330   if (BIH_SMOVE(bihx))
331     fprintf(ff, " SMOVE");
332   if (BIH_CS(bihx))
333     fprintf(ff, " CS");
334   if (BIH_PARSECT(bihx))
335     fprintf(ff, " PARSECT");
336   if (BIH_ENLAB(bihx))
337     fprintf(ff, " ENLAB");
338   if (BIH_PARLOOP(bihx))
339     fprintf(ff, " PARLOOP");
340   if (BIH_UJRES(bihx))
341     fprintf(ff, " UJRES");
342   if (BIH_SIMD(bihx))
343     fprintf(ff, " SIMD");
344   if (BIH_LDVOL(bihx))
345     fprintf(ff, " LDVOL");
346   if (BIH_STVOL(bihx))
347     fprintf(ff, " STVOL");
348 #ifdef BIH_STREG
349   if (BIH_STREG(bihx))
350     fprintf(ff, " STREG");
351 #endif
352   if (BIH_VPAR(bihx))
353     fprintf(ff, " VPAR");
354   if (BIH_PARALN(bihx))
355     fprintf(ff, " PARALN");
356   if (BIH_COMBST(bihx))
357     fprintf(ff, " COMBST");
358   if (BIH_TASK(bihx))
359     fprintf(ff, " TASK");
360   if (BIH_RESID(bihx))
361     fprintf(ff, " RESID");
362   if (BIH_VCAND(bihx))
363     fprintf(ff, " VCAND");
364   if (BIH_MIDIOM(bihx))
365     fprintf(ff, " MIDIOM");
366   if (BIH_DOCONC(bihx))
367     fprintf(ff, " DOCONC");
368 #ifdef BIH_LPCNTFROM
369   if (BIH_LPCNTFROM(bihx))
370     fprintf(ff, " lpcntfrom: %d:", BIH_LPCNTFROM(bihx));
371 #endif
372   fprintf(ff, "\n");
373 
374   q = 0;
375   throw_count = 0;
376   for (p = BIH_ILTFIRST(bihx); p != 0; p = ILT_NEXT(p)) {
377     q = p;
378     if (DBGBIT(10, 128) && DBGBIT(10, 512)) {
379       if (ILT_DELETE(p))
380         fprintf(ff, "[%4d]@\t", p);
381       else if (ILT_IGNORE(p))
382         fprintf(ff, "[%4d]#\t", p);
383       else
384         fprintf(ff, "[%4d]\t", p);
385 #if DEBUG
386       if (ff != stderr)
387         dmpilitree((int)ILT_ILIP(p));
388       else
389         ddilitree((int)ILT_ILIP(p), 1);
390 #endif
391     } else {
392       if (DBGBIT(10, 128)) {
393         fprintf(ff, "[%4d]", p);
394       } else {
395         fprintf(ff, " %5d  %5d^  flags:", p, ILT_ILIP(p));
396       }
397 
398       if (ILT_EX(p))
399         fprintf(ff, " EX");
400       if (ILT_BR(p))
401         fprintf(ff, " BR");
402       if (ILT_CAN_THROW(p)) {
403         int lab;
404         fprintf(ff, " CAN_THROW");
405         ++throw_count;
406         assert(throw_count == 1, "block should have at most one CAN_THROW",
407                bihx, ERR_Severe);
408         lab = ili_throw_label(ILT_ILIP(p));
409         assert(lab, "ILT marked as CAN_THROW but does not", bihx, ERR_Severe);
410       }
411       if (ILT_ST(p))
412         fprintf(ff, " ST");
413       if (ILT_DELETE(p))
414         fprintf(ff, " DELETE");
415       if (ILT_IGNORE(p))
416         fprintf(ff, " IGNORE");
417       if (ILT_DBGLINE(p))
418         fprintf(ff, " DBGL");
419       if (ILT_SPLIT(p))
420         fprintf(ff, " SPLIT");
421       if (ILT_CPLX(p))
422         fprintf(ff, " CPLX");
423       if (ILT_MCACHE(p))
424         fprintf(ff, " MCACHE");
425       if (ILT_DELEBB(p))
426         fprintf(ff, " DELEBB");
427       if (ILT_PREDC(p))
428         fprintf(ff, " PREDC");
429 #if defined(ILT_GUARD)
430       if (ILT_GUARD(p) != -1) {
431         fprintf(ff, "\t iff [%d]", ILT_GUARD(p));
432       }
433 #endif
434       if (ILT_INV(p))
435         fprintf(ff, " INV");
436       fprintf(ff, "\n");
437 #if DEBUG
438       if (DBGBIT(10, 128)) {
439         dmpilitree((int)ILT_ILIP(p));
440       }
441 #endif
442     }
443   }
444   assert(q == BIH_ILTLAST(bihx), "dmpilt: bad end of block", bihx, ERR_Severe);
445   iltb.privtmp = 0;
446 }
447 
448 /** \brief Dump ILT to global debug file
449  *
450  * Synonym to dump_ilt() with gbl.dbgfil as the file argument
451  *
452  * \param bihx - BIH number
453  */
454 void
dmpilt(int bihx)455 dmpilt(int bihx)
456 {
457   dump_ilt(gbl.dbgfil, bihx);
458 }
459 
460 /** \brief Write out an ilt/ili block given its bih
461  *
462  * Write out ilts for the block denoted by bih.  Various flags have already
463  * been set in bih. This routine buffers up the ilt block in the bih area.
464  */
465 void
wrilts(int bihx)466 wrilts(int bihx)
467 {
468   BIH_ILTFIRST(bihx) = ILT_NEXT(0);
469   BIH_ILTLAST(bihx) = ILT_PREV(0);
470   bihb.callfg = 0;
471   bihb.ldvol = 0;
472   bihb.stvol = 0;
473   bihb.qjsrfg = 0;
474   if (bihx != gbl.entbih)
475     BIH_FINDEX(bihx) = fihb.currfindex;
476 #ifdef BIH_FTAG
477   if (bihx != gbl.entbih) {
478     BIH_FINDEX(bihx) = fihb.currfindex;
479     BIH_FTAG(bihx) = fihb.currftag;
480     ++fihb.currftag;
481     if ((fihb.currftag > fihb.nextftag) && (fihb.currfindex == fihb.nextfindex))
482       fihb.nextftag = fihb.currftag;
483   }
484 #endif
485 #if DEBUG
486   if (flg.dbg[8] & 1)
487     dmpilt(bihx);
488 #endif
489 }
490 
491 /** \brief Read in an ilt/ili block
492  *
493  * "Read" in the block specified by bihx.  the 0th entry in the ILT area (next
494  * and prev) are set to the first and last ilts respectively
495  */
496 void
rdilts(int bihx)497 rdilts(int bihx)
498 {
499   if (BIH_RD(bihx) != 0) {
500     ILT_NEXT(0) = BIH_ILTFIRST(bihx);
501     ILT_PREV(0) = BIH_ILTLAST(bihx);
502   }
503   bihb.callfg = BIH_EX(bihx);
504   bihb.ldvol = BIH_LDVOL(bihx);
505   bihb.stvol = BIH_STVOL(bihx);
506   bihb.qjsrfg = BIH_QJSR(bihx);
507 #ifdef BIH_FTAG
508   fihb.nextfindex = fihb.currfindex = BIH_FINDEX(bihx);
509   fihb.nextftag = fihb.currftag = BIH_FTAG(bihx);
510 #endif
511 }
512 
513 /*
514  * save one message
515  *  call ccff_info
516  */
517 void *
ccff_ilt_info(int msgtype,const char * msgid,int iltx,int bihx,const char * message,...)518 ccff_ilt_info(int msgtype, const char *msgid, int iltx, int bihx, const char *message,
519               ...)
520 {
521   va_list argptr;
522   int fihx, lineno;
523   va_start(argptr, message);
524 
525   fihx = -1;
526   lineno = -1;
527   if (iltx > 0) {
528     fihx = ILT_FINDEX(iltx);
529     lineno = ILT_LINENO(iltx);
530   }
531   if (fihx <= 0 || lineno <= 0) {
532     fihx = BIH_FINDEX(bihx);
533     lineno = BIH_LINENO(bihx);
534   }
535   if (fihx == 0)
536     return NULL; /* no info */
537   return _ccff_info(msgtype, msgid, fihx, lineno, NULL, NULL, NULL, message,
538                     argptr);
539 } /* ccff_ilt_info */
540 
541 /*
542  * save one message
543  *  call subccff_info
544  */
545 void *
subccff_ilt_info(void * xparent,int msgtype,const char * msgid,int iltx,int bihx,const char * message,...)546 subccff_ilt_info(void *xparent, int msgtype, const char *msgid, int iltx, int bihx,
547                  const char *message, ...)
548 {
549   va_list argptr;
550   int fihx, lineno;
551   va_start(argptr, message);
552 
553   fihx = -1;
554   lineno = -1;
555   if (iltx > 0) {
556     fihx = ILT_FINDEX(iltx);
557     lineno = ILT_LINENO(iltx);
558   }
559   if (fihx <= 0 || lineno <= 0) {
560     fihx = BIH_FINDEX(bihx);
561     lineno = BIH_LINENO(bihx);
562   }
563   if (fihx == 0)
564     return NULL; /* no info */
565   return _ccff_info(msgtype, msgid, fihx, lineno, NULL, NULL, xparent, message,
566                     argptr);
567 } /* subccff_ilt_info */
568