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 Expander utility routines
20 */
21
22 #include "exputil.h"
23 #include "expreg.h"
24 #include "dinit.h"
25 #include "dinitutl.h"
26 #include "dtypeutl.h"
27 #include "llassem.h"
28 #include "ilm.h"
29 #include "ilmtp.h"
30 #include "fih.h"
31 #include "ili.h"
32 #include "iliutil.h"
33 #define EXPANDER_DECLARE_INTERNAL
34 #include "expand.h"
35 #include "machar.h"
36 #include "regutil.h"
37 #include "machreg.h"
38 #include "symfun.h"
39
40 static void propagate_bihflags(void);
41 static void flsh_saveili(void);
42
43 #define DO_PFO (XBIT(148, 0x1000) && !XBIT(148, 0x4000))
44
45 #ifdef __cplusplus
getSptr_bnd_con(ISZ_T i)46 inline SPTR getSptr_bnd_con(ISZ_T i) {
47 return static_cast<SPTR>(get_bnd_con(i));
48 }
49 #else
50 #define getSptr_bnd_con get_bnd_con
51 #endif
52
53 /** \brief Make an argument list
54 *
55 * Create a compiler generated array temporary for an argument list.
56 * its size is cnt and its dtype is dt. NOTE that the caller may modify
57 * the size of this array (a target may require alignment other than int).
58 * mkarglist guarantees reuse as long as expb.arglcnt.next is reset
59 * to expb.arglcnt.start.
60 */
61 void
mkarglist(int cnt,DTYPE dt)62 mkarglist(int cnt, DTYPE dt)
63 {
64
65 DTYPE dtype;
66 ADSC *ad;
67 static INT ival[2];
68
69 ival[1] = cnt;
70 expb.arglist = getccsym('a', expb.arglcnt.next++, ST_ARRAY);
71 dtype = DTYPEG(expb.arglist);
72 if (dtype) {
73 ad = AD_DPTR(dtype);
74 if (ival[1] > ad_val_of(AD_NUMELM(ad)))
75 AD_NUMELM(ad) = AD_UPBD(ad, 0) = getSptr_bnd_con(ival[1]);
76 } else {
77 SCP(expb.arglist, SC_AUTO);
78 STYPEP(expb.arglist, ST_ARRAY);
79 dtype = get_array_dtype(1, dt);
80 DTYPEP(expb.arglist, dtype);
81
82 ad = AD_DPTR(dtype);
83 AD_MLPYR(ad, 0) = stb.i1;
84 AD_LWBD(ad, 0) = stb.i1;
85 AD_UPBD(ad, 0) = getSptr_bnd_con(ival[1]);
86 AD_NUMDIM(ad) = 1;
87 AD_SCHECK(ad) = 0;
88 AD_ZBASE(ad) = stb.i1;
89 AD_NUMELM(ad) = AD_UPBD(ad, 0); /* numelm must be set ater numdim */
90 }
91
92 if (expb.arglcnt.max < expb.arglcnt.next)
93 expb.arglcnt.max = expb.arglcnt.next;
94 }
95
96 /** \brief Create a block during expand
97 */
98 void
cr_block(void)99 cr_block(void)
100 {
101 expb.curbih = exp_addbih(expb.curbih);
102 BIH_LINENO(expb.curbih) = expb.curlin ? expb.curlin : gbl.lineno;
103 BIH_GUARDEE(expb.curbih) = expb.isguarded >= 1 ? 1 : 0;
104 expb.flags.bits.noblock = 0;
105 ILT_NEXT(0) = 0;
106 ILT_PREV(0) = 0;
107 if (expb.curlin && expb.flags.bits.dbgline) {
108 expb.curilt =
109 addilt(0, ad2ili(IL_QJSR, mkfunc("dbg_i_line"), ad1ili(IL_NULL, 0)));
110 ILT_DBGLINE(expb.curilt) = 1;
111 } else
112 expb.curilt = 0;
113 expb.curlin = 0;
114 if (EXPDBG(8, 32))
115 fprintf(gbl.dbgfil, "---cr_block: bih %d, ILM line %d\n", expb.curbih,
116 gbl.lineno);
117 }
118
119 /** \brief Write a block during expand
120 */
121 void
wr_block(void)122 wr_block(void)
123 {
124 int iltx, opc = 0;
125
126 if (EXPDBG(8, 64))
127 fprintf(gbl.dbgfil, "%6d ilm words in block %6d\n", expb.ilm_words,
128 expb.curbih);
129 expb.ilm_words = 0;
130 iltx = ILT_PREV(0);
131 if (iltx != 0)
132 opc = ILI_OPC(ILT_ILIP(iltx));
133 if (iltx == 0 || !ILT_BR(iltx) || (opc != IL_JMP && opc != IL_QSWITCH &&
134 opc != IL_JMPMK &&
135 opc != IL_JMPM))
136 BIH_FT(expb.curbih) = 1;
137
138 propagate_bihflags();
139
140 expb.flags.bits.callfg |= bihb.callfg;
141 wrilts(expb.curbih); /* wrilts zeros bihb.callfg & qjsrfg */
142 #ifdef BIH_ASM
143 bihb.gasm = 0;
144 #endif
145 if (EXPDBG(8, 32))
146 fprintf(gbl.dbgfil, "---wr_block: bih %d, ILM line %d\n", expb.curbih,
147 gbl.lineno);
148 expb.flags.bits.noblock = 1;
149 }
150
151 static void
propagate_bihflags(void)152 propagate_bihflags(void)
153 {
154 /* Set of flags for which it's necessary to propagate from iltb
155 * to bihb to BIH because the write of an ilt may be deferred.
156 */
157 BIH_EX(expb.curbih) = bihb.callfg;
158 BIH_LDVOL(expb.curbih) = bihb.ldvol;
159 BIH_STVOL(expb.curbih) = bihb.stvol;
160 BIH_QJSR(expb.curbih) = bihb.qjsrfg;
161 #ifdef BIH_ASM
162 BIH_ASM(expb.curbih) = bihb.gasm;
163 #endif
164
165 /*
166 * Set of flags where it's known that a block has been created
167 * because of the context implied by the flags.
168 */
169 BIH_PAR(expb.curbih) |= bihb.parfg;
170 BIH_CS(expb.curbih) |= bihb.csfg;
171 BIH_PARSECT(expb.curbih) |= bihb.parsectfg;
172 BIH_TASK(expb.curbih) |= bihb.taskfg;
173 }
174
175 /** \brief Close current block and write out.
176 */
177 void
flsh_block(void)178 flsh_block(void)
179 {
180 flsh_saveili();
181 wr_block();
182 }
183
184 /** \brief Put out expb.saveili if necesssary.
185 *
186 * May be an unadded ili if expb.flags.bits.waitlbl is set
187 */
188 static void
flsh_saveili(void)189 flsh_saveili(void)
190 {
191 int savefg; /* save for the ilt call flag */
192 char ldvol; /* save for the ilt ldvol flag */
193 char stvol; /* save for the ilt stvol flag */
194 bool qjsrfg; /* save for the ilt qjsrfg flag */
195
196 if (expb.flags.bits.waitlbl) {
197
198 /*
199 * waiting for a label ilm; curilt will become the end of the current
200 * block if the opt level is not 1 -- i.e., the current block is
201 * written out and a new block is created. And, the ilt for saveili
202 * becomes the first ilt of this block. For opt level 1, an ilt for
203 * saveili is added to the current block
204 *
205 * NOTE: this does not happen at opt=0 -- this flag is not set (see the
206 * end of this routine)
207 */
208
209 expb.flags.bits.waitlbl = 0;
210 if (flg.opt != 1) {
211 if (EXPDBG(8, 32))
212 fprintf(gbl.dbgfil, "---flsh_saveili: wait end, curilt %d\n",
213 expb.curilt);
214
215 /* write out the block with curilt as its last ilt */
216
217 wr_block();
218
219 /*
220 * create a new block - saveili will be the first ilt of the new
221 * block
222 */
223 cr_block();
224 }
225 /* append the ilt to the current block */
226
227 if (EXPDBG(8, 32))
228 fprintf(gbl.dbgfil, "---flsh_saveili: wait add, curilt %d, saveili %d\n",
229 expb.curilt, expb.saveili);
230 savefg = iltb.callfg;
231 ldvol = iltb.ldvol;
232 stvol = iltb.stvol;
233 qjsrfg = iltb.qjsrfg;
234 iltb.callfg = 0;
235 iltb.ldvol = 0;
236 iltb.stvol = 0;
237 iltb.qjsrfg = false;
238 expb.curilt = addilt(expb.curilt, expb.saveili);
239 iltb.callfg = savefg;
240 iltb.ldvol = ldvol;
241 iltb.stvol = stvol;
242 iltb.qjsrfg = qjsrfg;
243 }
244 }
245
246 /** \brief Check for end of ILT block
247 *
248 * Check if the current block is at its end. newili locates an
249 * ili tree which represents an ili statement.
250 */
251 void
chk_block(int newili)252 chk_block(int newili)
253 {
254 int ili; /* ili of the current ilt */
255 ILI_OP opc; /* ili opcode of the current ilt */
256 int c_noprs; /* # of operands for conditional branch */
257 int c_lb; /* label of conditional branch */
258 int u_lb; /* label of unconditional branch */
259 int old_lastilt;
260
261 if (newili == 0)
262 /* seems odd that newili is 0, but this can happen if one is adding
263 * a branch ili -- iliutil could change the branch into a nop.
264 * The caller could check the ili first -- there are many cases
265 * where we do -- but it's something that can be easily overlooked.
266 */
267 return;
268
269 flsh_saveili(); /* write out saveili if waitlbl is set. (see
270 * below) */
271
272 if (!ILT_BR(expb.curilt) && (flg.opt < 2 || !ILT_CAN_THROW(expb.curilt))) {
273
274 /* The current end of the block is not a branch and [at -O2] cannot throw.
275 * Just create a new ilt and add it to the block. Note that if the block
276 * is null (expb.curilt is zero), the flags of ilt 0 are zero.
277 */
278 if (EXPDBG(8, 32))
279 fprintf(gbl.dbgfil, "---chk_block: curilt %d not br, add newili %d\n",
280 expb.curilt, newili);
281 old_lastilt = expb.curilt;
282 expb.curilt = addilt(expb.curilt, newili);
283 /* addilt does not update BIH_ILTLAST(). We need to do it here: */
284 if (expb.curbih && BIH_ILTLAST(expb.curbih) == old_lastilt) {
285 BIH_ILTLAST(expb.curbih) = expb.curilt;
286 }
287 return;
288 }
289 /* the current end of the block is some sort of branch,
290 call that can throw, or store of result of a call
291 that can throw. */
292
293 ili = ILT_ILIP(expb.curilt);
294 opc = ILI_OPC(ili);
295 if (opc == IL_JMP) {
296
297 /*
298 * the current end of the block is an unconditional branch. newili is
299 * unreachable, don't add it
300 */
301 opc = ILI_OPC(newili);
302 if (IL_TYPE(opc) == ILTY_BRANCH &&
303 IL_OPRFLAG(opc, ilis[opc].oprs) == ILIO_SYM)
304 RFCNTD(ILI_OPND(newili, ilis[opc].oprs));
305 iltb.callfg = 0;
306 if (EXPDBG(8, 32))
307 fprintf(gbl.dbgfil, "---chk_block: newili %d not reached\n", newili);
308 return;
309 }
310 /* the current end of the block is a conditional branch,
311 or something that can throw. */
312
313 if (ILI_OPC(newili) != IL_JMP || ILT_CAN_THROW(expb.curilt)) {
314
315 /* the new ili is not an unconditional branch, or the new ili is
316 an IL_JMP just past a potential throw point. */
317
318 if (flg.opt == 1 && !XBIT(137, 1) && !XBIT(163, 1))
319 /* create an extended basic block -- add a new ilt */
320
321 expb.curilt = addilt(expb.curilt, newili);
322 else {
323
324 /*
325 * the current block is at its end; write it out, create a new
326 * block with its first ilt locating newili
327 */
328 wr_block();
329 cr_block();
330 expb.curilt = addilt(expb.curilt, newili);
331 }
332 if (EXPDBG(8, 32))
333 fprintf(gbl.dbgfil, "---chk_block: add newili %d\n", newili);
334 return;
335 }
336 /*
337 * the current end of the block is a conditional branch and the new ili
338 * is an unconditional branch
339 */
340 c_noprs = ilis[opc].oprs;
341 c_lb = ILI_OPND(ili, c_noprs);
342 u_lb = ILI_OPND(newili, 1);
343 if (opc != IL_JMPM &&
344 opc != IL_JMPA &&
345 opc != IL_JMPMK &&
346 u_lb == c_lb) {
347
348 /*
349 * the labels are the same; search the current ilt and create new
350 * ilts for any procedures found. These ilts are added before the
351 * current ilt
352 */
353 (void)reduce_ilt((int)ILT_PREV(expb.curilt), ili);
354
355 /*
356 * the current ilt is changed to be the unconditional branch; the
357 * label's reference count is also decremented
358 */
359 if (EXPDBG(8, 32))
360 fprintf(gbl.dbgfil,
361 "---chk_block: uncond/cond, newili %d, to same label\n", newili);
362 ILT_ILIP(expb.curilt) = newili;
363 RFCNTD(ILI_OPND(newili, 1));
364 return;
365 }
366 /*
367 * the current end of the block is a conditional branch and the new ili
368 * is an unconditional branch whose labels are different. the checking of
369 * this block is delayed just in case a label ilm is processed before any
370 * other ilt producing ilms. This is done to catch cases of the form:
371 * if <cond> goto x;
372 * goto y;
373 * x: --- NOTE: this does not happen at opt 0;
374 * the current block is written out (with previlt as the last ilt) and
375 * previlt becomes the first ilt of the new block.
376 */
377 if (flg.opt != 0) {
378 if (EXPDBG(8, 32))
379 fprintf(gbl.dbgfil,
380 "---chk_block: uncond/cond, newili %d, to diff label\n", newili);
381 if (opc != IL_JMPM &&
382 opc != IL_JMPA &&
383 opc != IL_JMPMK &&
384 ILIBLKG(c_lb) == 0 && ILIBLKG(u_lb)) {
385 /* conditional branch is a forward branch; unconditional branch
386 * is a backward branch
387 */
388 ILT_ILIP(expb.curilt) = compl_br(ili, u_lb);
389 newili = ad1ili(IL_JMP, c_lb);
390 if (EXPDBG(8, 32))
391 fprintf(gbl.dbgfil, "---chk_block: swap lbls %d %d, c_br %d, u_br %d\n",
392 c_lb, u_lb, (int)ILT_ILIP(expb.curilt), newili);
393 }
394 expb.flags.bits.waitlbl = 1;
395 expb.saveili = newili;
396
397 } else {
398 wr_block(); /* the current block */
399 cr_block();
400 expb.curilt = addilt(expb.curilt, newili);
401 }
402 }
403
404 /** \brief Like chk_block, but suppress CAN_THROW flag.
405 *
406 * When a call can throw and defines two result registers, we have an ad-hoc
407 * rule that only the second store is marked as "can throw". This utility
408 * is useful for ensuring that the first store is not marked "can throw".
409 */
410 void
chk_block_suppress_throw(int newili)411 chk_block_suppress_throw(int newili)
412 {
413 chk_block(newili);
414 ILT_SET_CAN_THROW(expb.curilt, 0);
415 }
416
417 /** \brief Check an ILM which has been evaluated
418 *
419 * This routine checks an ILM which has already been evaluated
420 * (i.e., the ILM is referenced again). Depending on the type
421 * of the ili which defines this ILM, certain actions may occur
422 * to "redefine" the ILM (i.e., create a new ILI for the ILM).
423 *
424 * \param ilmx -- ILM index of the ILM evaluated
425 * \param ilix -- ILI index of the ILI for the ILM
426 */
427 int
check_ilm(int ilmx,int ilix)428 check_ilm(int ilmx, int ilix)
429 {
430 int cse; /* cse ILI */
431 SPTR sym; /* symbol table index */
432 int base, /* address ILI */
433 nme, /* names entry */
434 blk, /* bih index */
435 iltx; /* ilt index */
436 ILI_OP opc; /* opcode of ilix */
437
438 int saveilix = ilix;
439 switch (IL_TYPE(opc = ILI_OPC(ilix))) {
440
441 case ILTY_CONS:
442 /* a constant ILI is okay to re-use */
443 if (EXPDBG(8, 2))
444 fprintf(gbl.dbgfil, "check_ilm, ILM const: ilm %d, result ili %d\n", ilmx,
445 ilix);
446 return ilix;
447
448 case ILTY_ARTH:
449 case ILTY_LOAD:
450 case ILTY_DEFINE:
451 case ILTY_MOVE:
452 /*
453 * these results represent an expression which may contain
454 * side-effect operations. The new result is a CSE ILI of ilix
455 */
456 /* assertion: for fortran the only side-effects which may occur are
457 * those due to function calls; however, there are cases where
458 * it's necessary that several ili statements "belong" to the
459 * statement. To represent this, the sequence will begin with
460 * a pseudo store, followed by statements which have cse uses.
461 * For this case, the assertion (fortran-only) is that this
462 * will only occur for pseudo stores and stores.
463 */
464 cse = ilix;
465 if (EXPDBG(8, 2))
466 fprintf(gbl.dbgfil,
467 "check_ilm, ILM expr: ilm %d, old ili %d, cse ili %d\n", ilmx,
468 ilix, cse);
469 /*
470 * no longer have:
471 * !BIH_QJSR(expb.curbih) &&
472 * leader block may not yet be created
473 */
474 if (!iltb.qjsrfg && qjsr_in(ilix)) {
475 iltb.qjsrfg = true;
476 if (EXPDBG(8, 2))
477 fprintf(gbl.dbgfil, "check_ilm - qjsr_in(%d)\n", ilix);
478 }
479 return cse;
480
481 case ILTY_OTHER:
482 #ifdef ILTY_PSTORE
483 case ILTY_PSTORE:
484 #endif
485 #ifdef ILTY_PLOAD
486 case ILTY_PLOAD:
487 #endif
488 /* handle FREEIR... ili with ILTY_STORE */
489 if (!is_freeili_opcode(opc)) {
490 /* not a FREE ili */
491 return ilix;
492 }
493 goto like_store;
494
495 case ILTY_STORE:
496 /*
497 * assertion: for fortran the only side-effects which may occur are
498 * those due to function calls; however, there are cases where
499 * it's necessary that several ili statements "belong" to the
500 * statement. To represent this, the sequence will begin with
501 * a pseudo store, followed by statements which have cse uses.
502 * For this case, the assertion (fortran-only) is that this
503 * will only occur for pseudo stores and stores.
504 */
505
506 like_store:
507 /*** __OLDCSE ***/
508
509 cse = ad_cse((int)ILI_OPND(ilix, 1));
510
511 if ((blk = ILM_BLOCK(ilmx)) == expb.curbih) {
512 if (ILM_OPC((ILM *)(ilmb.ilm_base + ilmx)) == IM_PSEUDOST) {
513 /* We generate a pseudo store for postfix expressions.
514 * If the value prior to incrementing/decrementing is needed
515 * later by an arithmetic op, then we cannot safely CSE it.
516 * For example (from PH lang test): i++ != 2 ? 0 : i; In
517 * this case, a comparison followed by a branch needs the
518 * old value.
519 */
520 int len, opc2, i, found_use, found_arth;
521 int use = ILM_OPND((ILM *)(ilmb.ilm_base + ilmx), 2);
522 int ilmx2 = ilmx + ilms[IM_PSEUDOST].oprs + 1;
523 for (found_use = 0, found_arth = 0; ilmx2 < expb.nilms; ilmx2 += len) {
524 opc2 = ILM_OPC((ILM *)(ilmb.ilm_base + ilmx2));
525 len = ilms[opc2].oprs + 1;
526 if (IM_VAR(opc2))
527 len += ILM_OPND((ILM *)(ilmb.ilm_base + ilmx2), 1);
528 for (i = 1; i < len; ++i) {
529 if (IM_OPRFLAG(opc2, i) == OPR_LNK &&
530 ILM_OPND((ILM *)(ilmb.ilm_base + ilmx2), i) == use) {
531 found_use = 1;
532 } else if (found_use && IM_OPRFLAG(opc2, i) == OPR_LNK &&
533 ILM_OPND((ILM *)(ilmb.ilm_base + ilmx2), i) == ilmx) {
534 /* Convert the pseudo store to a real
535 * store on comparisons and other artimetics only.
536 */
537 if (IM_TYPE(opc2) != IMTY_ARTH) {
538 found_arth = 0;
539 goto break_out;
540 }
541 found_arth = 1;
542 }
543 }
544 }
545 break_out:
546 if (found_arth)
547 goto conv_pseudo_st;
548
549 } /* end if (ILM_OPC(...) == IM_PSEUDOST) */
550
551 /* reference is in the current block */
552
553 if (EXPDBG(8, 2))
554 fprintf(gbl.dbgfil,
555 "check_ilm, store re-used: ilm %d, old ili %d, cse ili %d\n",
556 ilmx, ilix, cse);
557 return cse;
558 } else {
559 /* The reference is in the current block if we jumped here
560 * from above (see the lines after "break_out:"), otherwise
561 * it's across block boundaries.
562 */
563 int save_iltb_callfg, save_iltb_ldvol, save_iltb_stvol;
564 bool save_iltb_qjsrfg;
565
566 conv_pseudo_st:
567 /* JHM (8 Dec 2011) bug-fix:
568 * This is quite complicated so I'll explain the logic in
569 * full detail. We're about to read in the ILTs of a
570 * block 'blk' (which may be 'expb.curbih' itself or a
571 * different block), then possibly add a new store ILT to
572 * it, then read in the ILTs of 'expb.curbih' again.
573 * Before doing this we must do the following:
574 *
575 * (1) Save the values of 'iltb.{x}', where {x} = {callfg,
576 * ldvol, stvol, qjsrfg}, to be restored later.
577 *
578 * (2) Set bihb.{x} |= iltb.{x}
579 *
580 * (3) Call 'propagate_bihflags()' to copy each bihb.{x}
581 * value to the corresponding BIH_{X}( expb.curbih ) field.
582 *
583 * Then at the end, after reading in 'expb.curbih's ILTs again:
584 *
585 * (4) Copy the saved values back to 'iltb.{x}'.
586 *
587 * Normally (2) would be performed by the next call to
588 * 'addilt()' and (3) by the next call to 'wr_block()'.
589 * However, because we call 'rdilts( blk )' and possibly
590 * add an ILT to 'blk', the above fields may be over-written
591 * before these actions can take place, as follows:
592 *
593 * -- 'rdilts( blk )' sets:
594 * bihb.{x} = BIH_{X}( blk )
595 * thus (potentially) over-writing the current values of bihb.{x}.
596 *
597 * -- Then 'addilt()' (if it's called) sets:
598 * bihb.{x} |= iltb.{x}
599 * iltb.{x} = 0
600 * thus over-writing the current values of iltb.{x}.
601 *
602 * -- Finally 'rdilts( expb.curbih )' sets:
603 * bihb.{x} = BIH_{X}( expb.curbih )
604 * which is only correct if BIH_{X}( expb.curbih ) contains
605 * the correct values, i.e. if actions (2) and (3) above
606 * have already been performed.
607 *
608 * By performing actions (2) and (3) we ensure that
609 * bihb.{x} and BIH_{X}( expb.curbih ) are correct at the
610 * end of this code, and (1) and (4) ensure that the
611 * current values are restored to 'iltb.{x}'.
612 */
613 bihb.callfg |= (save_iltb_callfg = iltb.callfg);
614 bihb.ldvol |= (save_iltb_ldvol = iltb.ldvol);
615 bihb.stvol |= (save_iltb_stvol = iltb.stvol);
616 bihb.qjsrfg |= (save_iltb_qjsrfg = iltb.qjsrfg);
617
618 iltb.callfg = 0; /* ...it's used by 'addilt()' to set ILT_EX() */
619 propagate_bihflags();
620 fihb.currfindex = BIH_FINDEX(expb.curbih);
621 fihb.currftag = BIH_FTAG(expb.curbih);
622 wrilts(expb.curbih); /* write out the current block and */
623 rdilts(blk); /* read in the block of the store */
624
625 sym = mkrtemp_sc(cse, expb.sc);
626 base = ad_acon(sym, (INT)0);
627 nme = addnme(NT_VAR, sym, 0, (INT)0);
628
629 for (iltx = ILT_PREV(0); iltx != 0; iltx = ILT_PREV(iltx)) {
630 if (ILT_ILIP(iltx) == ilix) {
631 switch (opc) {
632 case IL_ST:
633 ilix = ad4ili(IL_ST, cse, base, nme, ILI_OPND(ilix, 4));
634 break;
635 case IL_FREEIR:
636 ilix = ad4ili(IL_ST, cse, base, nme, MSZ_WORD);
637 break;
638 case IL_STKR:
639 ilix = ad4ili(IL_STKR, cse, base, nme, ILI_OPND(ilix, 4));
640 break;
641 case IL_FREEKR:
642 ilix = ad4ili(IL_STKR, cse, base, nme, MSZ_I8);
643 break;
644 case IL_STA:
645 case IL_FREEAR:
646 ilix = ad3ili(IL_STA, cse, base, nme);
647 ILM_NME(ilmx) = addnme(NT_IND, SPTR_NULL, nme, (INT)0);
648 break;
649 case IL_STSP:
650 case IL_FREESP:
651 ilix = ad4ili(IL_STSP, cse, base, nme, MSZ_F4);
652 break;
653 case IL_STDP:
654 case IL_FREEDP:
655 ilix = ad4ili(IL_STDP, cse, base, nme, MSZ_F8);
656 break;
657 case IL_STSCMPLX:
658 case IL_FREECS:
659 ilix = ad4ili(IL_STSCMPLX, cse, base, nme, MSZ_F8);
660 break;
661 case IL_STDCMPLX:
662 case IL_FREECD:
663 ilix = ad4ili(IL_STDCMPLX, cse, base, nme, MSZ_F16);
664 break;
665 #ifdef LONG_DOUBLE_FLOAT128
666 case IL_FLOAT128ST:
667 case IL_FLOAT128FREE:
668 ilix = ad4ili(IL_FLOAT128ST, cse, base, nme, MSZ_F16);
669 break;
670 #endif /* LONG_DOUBLE_FLOAT128 */
671 default:
672 interr("check_ilm: illegal store", ilix, ERR_Severe);
673 goto wr_out;
674 }
675 ADDRCAND(ilix, nme);
676 iltx = addilt(iltx, ilix);
677 ilix = ad_load(ilix);
678 if (ilix) {
679 if (EXPDBG(8, 2))
680 fprintf(gbl.dbgfil,
681 "check_ilm: store across block, ilm %d, ilt %d, ili %d\n",
682 ilmx, iltx, ilix);
683 ADDRCAND(ilix, nme);
684 } else {
685 ilix = ILT_ILIP(iltx);
686 interr("check_ilm: illegal store1", ilix, ERR_Severe);
687 }
688 goto wr_out;
689 }
690 }
691
692 /* no store found; just use cse as the result */
693
694 ilix = cse;
695 if (EXPDBG(8, 2))
696 fprintf(gbl.dbgfil,
697 "check_ilm: store not found, ilm %d, ilt %d, ili %d\n", ilmx,
698 iltx, ilix);
699
700 wr_out:
701 wrilts(blk); /* write out the modified block */
702 rdilts(expb.curbih); /* read back in the current block */
703
704 iltb.callfg = save_iltb_callfg;
705 iltb.ldvol = save_iltb_ldvol;
706 iltb.stvol = save_iltb_stvol;
707 iltb.qjsrfg = save_iltb_qjsrfg;
708 }
709 return ilix;
710
711 default:
712 if (EXPDBG(8, 2))
713 fprintf(gbl.dbgfil,
714 "check_ilm: bad reference, ilm %d(%s), ili %d, iliopc %d\n", ilmx,
715 ilms[ILM_OPC((ILM *)(ilmb.ilm_base + ilmx))].name, ilix, opc);
716 interr("check_ilm: bad reference", ilmx, ERR_Severe);
717 }
718
719 return saveilix;
720 }
721
722 /***************************************************************/
723
724 #if defined(DINIT_FUNCCOUNT)
725 void
put_funccount(void)726 put_funccount(void)
727 {
728 dinit_put(DINIT_FUNCCOUNT, gbl.func_count);
729 } /* put_funccount */
730 #endif
731
732 /** \brief Make a switch list for the intrinsic
733 *
734 * The switch list consists of the number of cases which occurred, the
735 * default label, and followed by the pairs (in sorted order based on
736 * case values) of case values and their respective case labels.
737 */
738 int
mk_swlist(INT n,SWEL * swhdr,int doinit)739 mk_swlist(INT n, SWEL *swhdr, int doinit)
740 {
741 SPTR sym;
742 int i;
743 SWEL *swel;
744 DTYPE dtype;
745
746 sym = getccsym('J', expb.swtcnt++, ST_ARRAY); /* get switch array */
747 SCP(sym, SC_STATIC);
748 i = dtype = get_type(3, TY_ARRAY, DT_INT);
749 DTYPEP(sym, dtype);
750 DTySetArrayDesc(dtype, get_bnd_con(2 * (n + 1)));
751
752 if (doinit) {
753 /* initialized this array with the switch list */
754 DINITP(sym, 1);
755
756 #if defined(DINIT_FUNCCOUNT)
757 put_funccount();
758 #endif
759 dinit_put(DINIT_LOC, sym);
760
761 dinit_put(DT_INT, n); /* number of cases */
762 dinit_put(DINIT_LABEL, (INT)swhdr->clabel); /* default label */
763 i = swhdr->next;
764 do {
765 swel = switch_base + i;
766 dinit_put(DT_INT, swel->val); /* case value */
767 dinit_put(DINIT_LABEL, (INT)swel->clabel); /* case label */
768 i = swel->next;
769 } while (i != 0);
770 }
771
772 return ad_acon(sym, 0);
773 }
774
775 int
access_swtab_base_label(int base_label,int sptr,int flag)776 access_swtab_base_label(int base_label, int sptr, int flag)
777 {
778
779 /* Store a list of jump table sptr's and their branch label. Used
780 * on the ST100 for the enhanced method 3 scheme.
781 * if flag == -2 then we are just access the routine's mode (GP16/GP32).
782 * if flag == -1 then we are just accessing the routine sptr
783 * If flag == 1 then we are just accessing the value.
784 * If flag == 0 then we are adding a new value.
785 * If flag == 2 then we are also removing the record from the list.
786 * Returns 0 if not found, else branch_label_sptr.
787 */
788
789 typedef struct swtab_branch_label {
790 int branch_label;
791 int sptr_swtab;
792 int sptr_routine;
793 int mode;
794 struct swtab_branch_label *next;
795 } swtab_branch_label;
796
797 int branch_label_sptr = 0, mode = 0, routine_sptr = 0;
798
799 static swtab_branch_label swtab_info = {0, 0, 0, 0, 0};
800
801 swtab_branch_label *curr, *prev;
802
803 if (flag != 0) {
804
805 prev = &swtab_info;
806 for (curr = swtab_info.next; curr; curr = curr->next) {
807
808 if (curr->sptr_swtab == sptr) {
809
810 branch_label_sptr = curr->branch_label;
811 mode = curr->mode;
812 routine_sptr = curr->sptr_routine;
813 if (flag == 2) {
814 /* Remove record from list */
815 prev->next = curr->next;
816 FREE(curr);
817 }
818
819 if (flag == -1) {
820 return routine_sptr;
821 } else if (flag == -2) {
822 return mode;
823 } else {
824 return branch_label_sptr;
825 }
826 }
827 prev = curr;
828 }
829
830 } else {
831 NEW(curr, swtab_branch_label, sizeof(swtab_branch_label));
832 curr->branch_label = base_label;
833 curr->sptr_swtab = sptr;
834 curr->sptr_routine = gbl.currsub;
835 curr->mode = 0;
836 curr->next = swtab_info.next;
837 swtab_info.next = curr;
838 branch_label_sptr = base_label;
839 }
840
841 return branch_label_sptr;
842 }
843
844 int
access_swtab_case_label(int case_label,int * case_val,int sptr,int flag)845 access_swtab_case_label(int case_label, int *case_val, int sptr, int flag)
846 {
847 /* Store a list of jump table sptr's and their case labels. Used
848 * on the ST100 for the constant time method (an inline jump table).
849 * If flag == 1 then we are just accessing the value.
850 * If flag == 0 then we are adding a new value.
851 * If flag == 2 then we are also removing the record from the list.
852 * Returns 0 if not found, else case_label_sptr.
853 */
854
855 typedef struct swtab_case_label {
856 int case_label;
857 int case_val;
858 int sptr_swtab;
859 struct swtab_case_label *next;
860 } swtab_case_label;
861
862 int case_label_sptr = 0;
863
864 static swtab_case_label swtab_info = {0, 0, 0, 0};
865
866 swtab_case_label *curr, *prev;
867
868 if (flag) {
869
870 prev = &swtab_info;
871 for (curr = swtab_info.next; curr; curr = curr->next) {
872
873 if (curr->sptr_swtab == sptr) {
874
875 case_label_sptr = curr->case_label;
876 *case_val = curr->case_val;
877 if (flag == 2) {
878 /* Remove record from list */
879 prev->next = curr->next;
880 FREE(curr);
881 }
882 return case_label_sptr;
883 }
884 prev = curr;
885 }
886
887 } else {
888 NEW(curr, swtab_case_label, sizeof(swtab_case_label));
889 curr->case_label = case_label;
890 curr->sptr_swtab = sptr;
891 curr->next = swtab_info.next;
892 curr->case_val = *case_val;
893 swtab_info.next = curr;
894 case_label_sptr = case_label;
895 }
896
897 return case_label_sptr;
898 }
899
900
901 #define DINITSWTAB_put(c, s)
902 #define DINITSWTAB_put2(c, s, t)
903
904 /** \brief Make a switch address table
905 */
906 int
mk_swtab(INT n,SWEL * swhdr,int deflab,int doinit)907 mk_swtab(INT n, SWEL *swhdr, int deflab, int doinit)
908 {
909 int sym;
910 int i;
911 INT case_val;
912 SWEL *swel;
913 DTYPE tabdtype = DT_CPTR;
914
915 sym = getccsym('J', expb.swtcnt++, ST_PLIST); /* get switch array */
916 DTYPEP(sym, tabdtype);
917 SCP(sym, SC_STATIC);
918 PLLENP(sym, n);
919
920 /* initialize this array with the switch table */
921
922 SWELP(sym, swhdr - switch_base);
923 DEFLABP(sym, deflab);
924 if (doinit) {
925 /*
926 * generate the entry for the default label.
927 */
928 DINITSWTAB_put(DINIT_LOC, sym);
929
930 if (deflab) {
931 /*
932 * If the default label is passed, then it will not appear in the
933 * switch list. Just make sure that swel locates the first case.
934 */
935 swel = swhdr;
936 } else {
937 /*
938 * Since the default label is not passed, then the switch list
939 * contains the default label. Extract it and make sure that it
940 * gets added to the initialization of the switch array.
941 */
942 deflab = swhdr->clabel;
943 DINITSWTAB_put(DINIT_LABEL, (INT)deflab);
944 swel = switch_base + swhdr->next;
945 }
946
947 case_val = swel->val; /* start with first case value */
948 do {
949 /*
950 * generate the remainder of the label table -- if there are
951 * holes, the default label is generated. case_val denotes
952 * the expected case value.
953 */
954 for (case_val = swel->val - case_val; case_val; case_val--) {
955 DINITSWTAB_put(DINIT_LABEL, deflab); /* default */
956 RFCNTI((int)swhdr->clabel);
957 #if DEBUG
958 interr("mk_swtab: CGOTO has holes, swidx", swhdr - switch_base, ERR_Warning);
959 #endif
960 }
961 DINITSWTAB_put(DINIT_LABEL, (INT)swel->clabel); /* case label */
962 case_val = swel->val + 1;
963 i = swel->next;
964 swel = switch_base + i;
965 } while (i != 0);
966 }
967
968 return sym;
969 }
970
971 int
mk_swtab_ll(INT n,SWEL * swhdr,int deflab,int doinit)972 mk_swtab_ll(INT n, SWEL *swhdr, int deflab, int doinit)
973 {
974 int sym;
975 int i;
976 INT case_val[2];
977 SWEL *swel;
978 static INT one[2] = {0, 1};
979 static INT zero[2] = {0, 0};
980 INT vv[2];
981
982 sym = getccsym('J', expb.swtcnt++, ST_PLIST); /* get switch array */
983 DTYPEP(sym, DT_INT8);
984 SCP(sym, SC_STATIC);
985 PLLENP(sym, n);
986
987 /* initialize this array with the switch table */
988
989 SWELP(sym, swhdr - switch_base);
990 DEFLABP(sym, deflab);
991 if (doinit) {
992 DINITP(sym, 1);
993 /*
994 * generate the entry for the default label.
995 */
996 dinit_put(DINIT_LOC, sym);
997 if (deflab)
998 /*
999 * If the default label is passed, then it will not appear in the
1000 * switch list. Just make sure that swel locates the first case.
1001 */
1002 swel = swhdr;
1003 else {
1004 /*
1005 * Since the default label is not passed, then the switch list
1006 * contains the default label. Extract it and make sure that it
1007 * gets added to the initialization of the switch array.
1008 */
1009 deflab = swhdr->clabel;
1010 dinit_put(DINIT_LABEL, (INT)deflab);
1011 swel = switch_base + swhdr->next;
1012 }
1013 case_val[0] = CONVAL1G(swel->val); /* start with first case value */
1014 case_val[1] = CONVAL2G(swel->val);
1015 do {
1016 /*
1017 * generate the remainder of the label table -- if there are
1018 * holes, the default label is generated. case_val denotes
1019 * the expected case value.
1020 */
1021 vv[0] = CONVAL1G(swel->val);
1022 vv[1] = CONVAL2G(swel->val);
1023 sub64(vv, case_val, case_val);
1024 /*for (case_val = swel->val - case_val; case_val; case_val--)*/
1025 while (true) {
1026 if (cmp64(case_val, zero) == 0)
1027 break;
1028 dinit_put(DINIT_LABEL, deflab); /* default */
1029 RFCNTI((int)swhdr->clabel);
1030 #if DEBUG
1031 interr("mk_swtab: CGOTO has holes, swidx", swhdr - switch_base, ERR_Warning);
1032 #endif
1033 sub64(case_val, one, case_val);
1034 }
1035 dinit_put(DINIT_LABEL, (INT)swel->clabel); /* case label */
1036 /*case_val = swel->val + 1;*/
1037 vv[0] = CONVAL1G(swel->val);
1038 vv[1] = CONVAL2G(swel->val);
1039 add64(vv, one, case_val);
1040 i = swel->next;
1041 swel = switch_base + i;
1042 } while (i != 0);
1043 }
1044
1045 return sym;
1046 }
1047
1048 /** \brief Make a sym for an arg's address
1049 */
1050 SPTR
mk_argasym(int sptr)1051 mk_argasym(int sptr)
1052 {
1053 SPTR asym;
1054 asym = getccsym('c', sptr, ST_VAR);
1055 IS_PROC_DESCRP(asym, IS_PROC_DESCRG(sptr));
1056 DESCARRAYP(asym, DESCARRAYG(sptr));
1057 CLASSP(asym, CLASSG(sptr));
1058 SDSCP(asym, SDSCG(sptr));
1059 if (gbl.internal == 1 && CLASSG(asym) && DESCARRAYG(asym)) {
1060 /* Do not set lscope on class arguments within host subroutines */
1061 LSCOPEP(asym, 0);
1062 }
1063 SCP(asym, SCG(sptr));
1064 DTYPEP(asym, DT_CPTR);
1065 REDUCP(asym, 1); /* mark sym --> no further indirection */
1066 MIDNUMP(asym, sptr); /* link indirection temp to formal */
1067 QALNP(asym, QALNG(sptr));
1068 NOCONFLICTP(asym, 1);
1069 GSCOPEP(asym, GSCOPEG(sptr));
1070 if (INTERNREFG(sptr)) {
1071 INTERNREFP(asym, 1);
1072 ADDRESSP(asym, ADDRESSG(sptr));
1073 MEMARGP(asym, MEMARGG(sptr));
1074 }
1075 if (UPLEVELG(sptr)) {
1076 /* Currently in an internal procedure and the argument is from
1077 * the host; need to propagate a few flags to the indirection
1078 * temp.
1079 */
1080 UPLEVELP(asym, 1);
1081 ADDRESSP(asym, ADDRESSG(sptr));
1082 MEMARGP(asym, MEMARGG(sptr));
1083 }
1084 return asym;
1085 }
1086
1087 /*
1088 * is there an indirection symbol for this dummy?
1089 */
1090 SPTR
find_argasym(int sptr)1091 find_argasym(int sptr)
1092 {
1093 char name[16];
1094 SPTR asym;
1095 sprintf(name, ".%c%04d", 'c', sptr);
1096 asym = lookupsym(name, strlen(name));
1097 if (asym && DTYPEG(asym) == DT_CPTR && MIDNUMG(asym) == sptr)
1098 return asym;
1099 return SPTR_NULL;
1100 } /* find_argasym */
1101
1102 /***************************************************************/
1103
1104 int
mk_impsym(SPTR sptr)1105 mk_impsym(SPTR sptr)
1106 {
1107 char bf[3 * MAXIDLEN + 10]; /* accommodate "__imp_" and possibly mod name
1108 * as prefixes
1109 */
1110 int impsym;
1111
1112 switch (STYPEG(sptr)) {
1113 case ST_ENTRY:
1114 case ST_PROC:
1115 if (INMODULEG(sptr)) {
1116 sprintf(bf, "__imp_%s_%s", SYMNAME(INMODULEG(sptr)), SYMNAME(sptr));
1117 break;
1118 }
1119 /***** else FALLTHRU *****/
1120 default:
1121 #if defined(PGFTN) && defined(TARGET_WIN_X8664)
1122 sprintf(bf, "__imp_%s", getsname2(sptr));
1123 #else
1124 sprintf(bf, "__imp_%s", getsname(sptr));
1125 #endif
1126 }
1127
1128 impsym = getsymbol(bf);
1129
1130 if (SCG(impsym) == SC_NONE) {
1131 STYPEP(impsym, ST_VAR);
1132 SCP(impsym, SC_EXTERN);
1133 DTYPEP(impsym, __POINT_T);
1134 }
1135 return impsym;
1136 }
1137
1138 /***************************************************************/
1139
1140 SPTR
mkfunc_cncall(const char * nmptr)1141 mkfunc_cncall(const char *nmptr)
1142 {
1143 SPTR sptr;
1144 sptr = mkfunc(nmptr);
1145 CNCALLP(sptr, 1);
1146 return sptr;
1147 }
1148
1149 /***************************************************************/
1150
1151 static const char *
skipws(const char * q)1152 skipws(const char *q)
1153 {
1154 while (*q <= ' ' && *q != '\0')
1155 ++q;
1156 return q;
1157 }
1158
1159 SPTR
mkfunc_sflags(const char * nmptr,const char * flags)1160 mkfunc_sflags(const char *nmptr, const char *flags)
1161 {
1162 SPTR sptr;
1163 const char *p;
1164 sptr = mkfunc(nmptr);
1165 p = flags;
1166 while (true) {
1167 p = skipws(p);
1168 if (*p == '\0')
1169 break;
1170 if (strncmp(p, "cncall", 6) == 0) {
1171 CNCALLP(sptr, 1);
1172 p += 6;
1173 } else if (strncmp(p, "xmmsafe", 7) == 0) {
1174 if (!XBIT(7, 0x4000))
1175 XMMSAFEP(sptr, 1);
1176 p += 7;
1177 }
1178 #if DEBUG
1179 else {
1180 interr("mkfunc_sflags(): urecognized flag", sptr, ERR_Severe);
1181 break;
1182 }
1183 #endif
1184 }
1185 return sptr;
1186 }
1187
1188 void
exp_add_copy(SPTR lhssptr,SPTR rhssptr)1189 exp_add_copy(SPTR lhssptr, SPTR rhssptr)
1190 {
1191 int rhsacon, lhsacon, rhsnme, lhsnme, rhsld, lhsst, sz;
1192 ILI_OP rhsopc, lhsopc;
1193 MSZ msz;
1194 if (lhssptr == rhssptr)
1195 return;
1196 rhsacon = ad_acon(rhssptr, 0);
1197 sz = size_of(DTYPEG(rhssptr));
1198 if (sz == 8) {
1199 rhsopc = IL_LDKR;
1200 lhsopc = IL_STKR;
1201 msz = MSZ_I8;
1202 } else if (sz == 4) {
1203 rhsopc = IL_LD;
1204 lhsopc = IL_ST;
1205 msz = MSZ_WORD;
1206 } else if (sz == 2) {
1207 rhsopc = IL_LD;
1208 lhsopc = IL_ST;
1209 msz = MSZ_SHWORD;
1210 } else if (sz == 1) {
1211 rhsopc = IL_LD;
1212 lhsopc = IL_ST;
1213 msz = MSZ_BYTE;
1214 }
1215 rhsnme = addnme(NT_VAR, rhssptr, 0, 0);
1216 rhsld = ad3ili(rhsopc, rhsacon, rhsnme, msz);
1217 lhsacon = ad_acon(lhssptr, 0);
1218 lhsnme = addnme(NT_VAR, lhssptr, 0, 0);
1219 lhsst = ad4ili(lhsopc, rhsld, lhsacon, lhsnme, msz);
1220 chk_block(lhsst);
1221 }
1222
1223 SPTR
get_byval_local(int argsptr)1224 get_byval_local(int argsptr)
1225 {
1226 char *new_name;
1227 SPTR newsptr;
1228 int new_length;
1229
1230 newsptr = MIDNUMG(argsptr);
1231 if (newsptr > SPTR_NULL)
1232 return newsptr;
1233 new_name = SYMNAME(argsptr);
1234 new_name += 3; /* move past appended _V_ */
1235 new_length = strlen(new_name);
1236 newsptr = getsymbol(new_name);
1237 for (; newsptr; newsptr = HASHLKG(newsptr)) {
1238 if (strncmp(new_name, SYMNAME(newsptr), new_length) != 0 ||
1239 *(SYMNAME(newsptr) + new_length) != '\0')
1240 continue;
1241 if (STYPEG(newsptr) == STYPEG(argsptr)) {
1242 if (SCG(newsptr) == SC_LOCAL)
1243 return newsptr;
1244 }
1245 }
1246 newsptr = getsymbol(new_name); /* OH OH -- ICE */
1247 return newsptr;
1248 }
1249
1250 /** \brief Add a register argument
1251 *
1252 * Add argument expression argili to existing argument list, arglist,
1253 * using registers. If arglist = 0, begin a new list.
1254 */
1255 int
add_reg_arg_ili(int arglist,int argili,int nmex,DTYPE dtype)1256 add_reg_arg_ili(int arglist, int argili, int nmex, DTYPE dtype)
1257 {
1258 int rg, ilix;
1259 ILI_OP opc;
1260 static int avail_ireg; /* next available integer register for jsr */
1261 static int avail_freg; /* next available floating point register for jsr */
1262
1263 if (arglist == 0) {
1264 arglist = ad1ili(IL_NULL, 0);
1265 avail_ireg = 0;
1266 avail_freg = 0;
1267 }
1268 if (DTY(dtype) == TY_PTR) {
1269 rg = IR(avail_ireg++);
1270 opc = IL_DAAR;
1271 } else if (DT_ISINT(dtype)) {
1272 rg = IR(avail_ireg++);
1273 opc = IL_RES(ILI_OPC(argili)) != ILIA_KR ? IL_DAIR : IL_DAKR;
1274 } else {
1275 if (DTY(dtype) == TY_DBLE && (avail_freg & 1))
1276 avail_freg++;
1277 rg = SP(avail_freg);
1278 avail_freg++;
1279 if (DTY(dtype) == TY_DBLE) {
1280 opc = IL_DADP;
1281 avail_freg++;
1282 } else {
1283 opc = IL_DASP;
1284 }
1285 }
1286
1287 ilix = ad3ili(opc, argili, rg, arglist);
1288 return ilix;
1289 } /* add_reg_arg_ili */
1290
1291 #if DEBUG
1292 void
expdumpilms()1293 expdumpilms()
1294 {
1295 int i, bsize;
1296 ilmb.ilm_base[BOS_SIZE - 1] = ilmb.ilmavl;
1297 if (gbl.dbgfil == NULL)
1298 gbl.dbgfil = stderr;
1299
1300 if (ilmb.ilm_base[0] != IM_BOS) {
1301 fprintf(gbl.dbgfil, "expdumpilms: no IM_BOS (ilm_base[0]==%d)\n", ilmb.ilm_base[0]);
1302 }
1303
1304 fprintf(gbl.dbgfil, "\n----- lineno: %d"
1305 " ----- global ILM index %d:%d"
1306 "\n",
1307 ilmb.ilm_base[1] , ilmb.globalilmstart, ilmb.globalilmcount
1308 );
1309 bsize = ilmb.ilm_base[BOS_SIZE - 1]; /* number of words in this ILM block */
1310
1311 i = 0;
1312 do { /* loop once for each ILM opcode: */
1313 int _dumponeilm(ILM_T *, int, int check);
1314 int j = i;
1315 i = _dumponeilm(ilmb.ilm_base, i, 0);
1316 if (ILM_RESULT(j))
1317 fprintf(gbl.dbgfil, " result:%d", ILM_RESULT(j));
1318 if (ILM_IRESULT(j))
1319 fprintf(gbl.dbgfil, " iresult/clen:%d", ILM_IRESULT(j));
1320 if (ILM_RESTYPE(j))
1321 fprintf(gbl.dbgfil, " restype:%d", ILM_RESTYPE(j));
1322 if (ILM_NME(j))
1323 fprintf(gbl.dbgfil, " nme:%d", ILM_NME(j));
1324 if (ILM_BLOCK(j))
1325 fprintf(gbl.dbgfil, " block:%d", ILM_BLOCK(j));
1326 if (ILM_SCALE(j))
1327 fprintf(gbl.dbgfil, " scale:%d", ILM_SCALE(j));
1328 if (ILM_MXLEN(j))
1329 fprintf(gbl.dbgfil, " mxlen/clen:%d", ILM_MXLEN(j));
1330 if (ILM_EXPANDED_FOR(j))
1331 fprintf(gbl.dbgfil, " expanded_for:%d", ILM_EXPANDED_FOR(j));
1332
1333 fprintf(gbl.dbgfil, "\n");
1334 if (i > bsize) {
1335 fprintf(gbl.dbgfil, "BAD BLOCK LENGTH: %d\n", bsize);
1336 }
1337 } while (i < bsize);
1338 } /* expdumpilms */
1339 #endif
1340