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