|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)proc.c 5.7 (Berkeley) 1/30/86";
9: #endif not lint
10:
11: /*
12: * proc.c
13: *
14: * Routines for handling procedures, f77 compiler, pass 1.
15: *
16: * University of Utah CS Dept modification history:
17: *
18: * $Log: proc.c,v $
19: * Revision 5.9 86/01/28 22:30:28 donn
20: * Let functions of type character have adjustable length.
21: *
22: * Revision 5.8 86/01/10 19:02:19 donn
23: * More dbx hacking -- filter out incomplete declarations (with bogus types).
24: *
25: * Revision 5.7 86/01/10 13:53:02 donn
26: * Since we now postpone determination of the type of an argument, we must
27: * make sure to emit stab information at the end of the routine when we
28: * definitely have the type. Notice some care was taken to make sure that
29: * arguments appear in order in the output file since that's how dbx wants
30: * them. Also a minor change for dummy procedures.
31: *
32: * Revision 5.6 86/01/06 16:28:06 donn
33: * Sigh. We can't commit to defining a symbol as a variable instead of a
34: * function based only on what we have seen through the declaration section;
35: * this was properly handled for normal variables but not for arguments.
36: *
37: * Revision 5.5 86/01/01 21:59:17 donn
38: * Pick up CHARACTER*(*) declarations for variables which aren't dummy
39: * arguments, and complain about them.
40: *
41: * Revision 5.4 85/12/20 19:18:35 donn
42: * Don't assume that dummy procedures of unknown type are functions of type
43: * undefined until the user (mis-)uses them that way -- they may also be
44: * subroutines.
45: *
46: * Revision 5.3 85/09/30 23:21:07 donn
47: * Print space with prspace() in outlocvars() so that alignment is preserved.
48: *
49: * Revision 5.2 85/08/10 05:03:34 donn
50: * Support for NAMELIST i/o from Jerry Berkman.
51: *
52: * Revision 5.1 85/08/10 03:49:14 donn
53: * 4.3 alpha
54: *
55: * Revision 3.11 85/06/04 03:45:29 donn
56: * Changed retval() to recognize that a function declaration might have
57: * bombed out earlier, leaving an error node behind...
58: *
59: * Revision 3.10 85/03/08 23:13:06 donn
60: * Finally figured out why function calls and array elements are not legal
61: * dummy array dimension declarator elements. Hacked safedim() to stop 'em.
62: *
63: * Revision 3.9 85/02/02 00:26:10 donn
64: * Removed the call to entrystab() in enddcl() -- this was redundant (it was
65: * also done in startproc()) and confusing to dbx to boot.
66: *
67: * Revision 3.8 85/01/14 04:21:53 donn
68: * Added changes to implement Jerry's '-q' option.
69: *
70: * Revision 3.7 85/01/11 21:10:35 donn
71: * In conjunction with other changes to implement SAVE statements, function
72: * nameblocks were changed to make it appear that they are 'saved' too --
73: * this arranges things so that function return values are forced out of
74: * register before a return.
75: *
76: * Revision 3.6 84/12/10 19:27:20 donn
77: * comblock() signals an illegal common block name by returning a null pointer,
78: * but incomm() wasn't able to handle it, leading to core dumps. I put the
79: * fix in incomm() to pick up null common blocks.
80: *
81: * Revision 3.5 84/11/21 20:33:31 donn
82: * It seems that I/O elements are treated as character strings so that their
83: * length can be passed to the I/O routines... Unfortunately the compiler
84: * assumes that no temporaries can be of type CHARACTER and casually tosses
85: * length and type info away when removing TEMP blocks. This has been fixed...
86: *
87: * Revision 3.4 84/11/05 22:19:30 donn
88: * Fixed a silly bug in the last fix.
89: *
90: * Revision 3.3 84/10/29 08:15:23 donn
91: * Added code to check the type and shape of subscript declarations,
92: * per Jerry Berkman's suggestion.
93: *
94: * Revision 3.2 84/10/29 05:52:07 donn
95: * Added change suggested by Jerry Berkman to report an error when an array
96: * is redimensioned.
97: *
98: * Revision 3.1 84/10/13 02:12:31 donn
99: * Merged Jerry Berkman's version into mine.
100: *
101: * Revision 2.1 84/07/19 12:04:09 donn
102: * Changed comment headers for UofU.
103: *
104: * Revision 1.6 84/07/19 11:32:15 donn
105: * Incorporated fix to setbound() to detect backward array subscript limits.
106: * The fix is by Bob Corbett, donated by Jerry Berkman.
107: *
108: * Revision 1.5 84/07/18 18:25:50 donn
109: * Fixed problem with doentry() where a placeholder for a return value
110: * was not allocated if the first entry didn't require one but a later
111: * entry did.
112: *
113: * Revision 1.4 84/05/24 20:52:09 donn
114: * Installed firewall #ifdef around the code that recycles stack temporaries,
115: * since it seems to be broken and lacks a good fix for the time being.
116: *
117: * Revision 1.3 84/04/16 09:50:46 donn
118: * Fixed mkargtemp() so that it only passes back a copy of a temporary, keeping
119: * the original for its own use. This fixes a set of bugs that are caused by
120: * elements in the argtemplist getting stomped on.
121: *
122: * Revision 1.2 84/02/28 21:12:58 donn
123: * Added Berkeley changes for subroutine call argument temporaries fix.
124: *
125: */
126:
127: #include "defs.h"
128:
129: #ifdef SDB
130: # include <a.out.h>
131: # ifndef N_SO
132: # include <stab.h>
133: # endif
134: #endif
135:
136: extern flag namesflag;
137:
138: typedef
139: struct SizeList
140: {
141: struct SizeList *next;
142: ftnint size;
143: struct VarList *vars;
144: }
145: sizelist;
146:
147:
148: typedef
149: struct VarList
150: {
151: struct VarList *next;
152: Namep np;
153: struct Equivblock *ep;
154: }
155: varlist;
156:
157:
158: LOCAL sizelist *varsizes;
159:
160:
161: /* start a new procedure */
162:
163: newproc()
164: {
165: if(parstate != OUTSIDE)
166: {
167: execerr("missing end statement", CNULL);
168: endproc();
169: }
170:
171: parstate = INSIDE;
172: procclass = CLMAIN; /* default */
173: }
174:
175:
176:
177: /* end of procedure. generate variables, epilogs, and prologs */
178:
179: endproc()
180: {
181: struct Labelblock *lp;
182:
183: if(parstate < INDATA)
184: enddcl();
185: if(ctlstack >= ctls)
186: err("DO loop or BLOCK IF not closed");
187: for(lp = labeltab ; lp < labtabend ; ++lp)
188: if(lp->stateno!=0 && lp->labdefined==NO)
189: errstr("missing statement number %s", convic(lp->stateno) );
190:
191: if (optimflag)
192: optimize();
193:
194: outiodata();
195: epicode();
196: procode();
197: donmlist();
198: dobss();
199:
200: #if FAMILY == PCC
201: putbracket();
202: #endif
203: fixlwm();
204: procinit(); /* clean up for next procedure */
205: }
206:
207:
208:
209: /* End of declaration section of procedure. Allocate storage. */
210:
211: enddcl()
212: {
213: register struct Entrypoint *ep;
214:
215: parstate = INEXEC;
216: docommon();
217: doequiv();
218: docomleng();
219: for(ep = entries ; ep ; ep = ep->entnextp) {
220: doentry(ep);
221: }
222: }
223:
224: /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
225:
226: /* Main program or Block data */
227:
228: startproc(prgname, class)
229: Namep prgname;
230: int class;
231: {
232: struct Extsym *progname;
233: register struct Entrypoint *p;
234:
235: if(prgname)
236: procname = prgname->varname;
237: if(namesflag == YES) {
238: fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
239: if(prgname)
240: fprintf(diagfile, " %s", varstr(XL, procname) );
241: fprintf(diagfile, ":\n");
242: }
243:
244: if( prgname )
245: progname = newentry( prgname );
246: else
247: progname = NULL;
248:
249: p = ALLOC(Entrypoint);
250: if(class == CLMAIN)
251: puthead("MAIN_", CLMAIN);
252: else
253: puthead(CNULL, CLBLOCK);
254: if(class == CLMAIN)
255: newentry( mkname(5, "MAIN") );
256: p->entryname = progname;
257: p->entrylabel = newlabel();
258: entries = p;
259:
260: procclass = class;
261: retlabel = newlabel();
262: #ifdef SDB
263: if(sdbflag) {
264: entrystab(p,class);
265: }
266: #endif
267: }
268:
269: /* subroutine or function statement */
270:
271: struct Extsym *newentry(v)
272: register Namep v;
273: {
274: register struct Extsym *p;
275:
276: p = mkext( varunder(VL, v->varname) );
277:
278: if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
279: {
280: if(p == 0)
281: dclerr("invalid entry name", v);
282: else dclerr("external name already used", v);
283: return(0);
284: }
285: v->vstg = STGAUTO;
286: v->vprocclass = PTHISPROC;
287: v->vclass = CLPROC;
288: p->extstg = STGEXT;
289: p->extinit = YES;
290: return(p);
291: }
292:
293:
294: entrypt(class, type, length, entname, args)
295: int class, type;
296: ftnint length;
297: Namep entname;
298: chainp args;
299: {
300: struct Extsym *entry;
301: register Namep q;
302: register struct Entrypoint *p, *ep;
303:
304: if(namesflag == YES) {
305: if(class == CLENTRY)
306: fprintf(diagfile, " entry ");
307: if(entname)
308: fprintf(diagfile, " %s", varstr(XL, entname->varname) );
309: fprintf(diagfile, ":\n");
310: }
311:
312: if( entname->vclass == CLPARAM ) {
313: errstr("entry name %s used in 'parameter' statement",
314: varstr(XL, entname->varname) );
315: return;
316: }
317: if( ((type == TYSUBR) || (class == CLENTRY && proctype == TYSUBR))
318: && (entname->vtype != TYUNKNOWN && entname->vtype != TYSUBR) ) {
319: errstr("subroutine entry %s previously declared",
320: varstr(XL, entname->varname) );
321: return;
322: }
323: if( (entname->vstg != STGEXT && entname->vstg != STGUNKNOWN)
324: || (entname->vdim != NULL) ) {
325: errstr("subroutine or function entry %s previously declared",
326: varstr(XL, entname->varname) );
327: return;
328: }
329:
330: if( (class == CLPROC || class == CLENTRY) && type != TYSUBR )
331: /* arrange to save function return values */
332: entname->vsave = YES;
333:
334: entry = newentry( entname );
335:
336: if(class != CLENTRY)
337: puthead( varstr(XL, procname = entry->extname), class);
338: q = mkname(VL, nounder(XL,entry->extname) );
339:
340: if( (type = lengtype(type, (int) length)) != TYCHAR)
341: length = 0;
342: if(class == CLPROC)
343: {
344: procclass = CLPROC;
345: proctype = type;
346: procleng = length;
347:
348: retlabel = newlabel();
349: if(type == TYSUBR)
350: ret0label = newlabel();
351: }
352:
353: p = ALLOC(Entrypoint);
354: if(entries) /* put new block at end of entries list */
355: {
356: for(ep = entries; ep->entnextp; ep = ep->entnextp)
357: ;
358: ep->entnextp = p;
359: }
360: else
361: entries = p;
362:
363: p->entryname = entry;
364: p->arglist = args;
365: p->entrylabel = newlabel();
366: p->enamep = q;
367:
368: if(class == CLENTRY)
369: {
370: class = CLPROC;
371: if(proctype == TYSUBR)
372: type = TYSUBR;
373: }
374:
375: q->vclass = class;
376: q->vprocclass = PTHISPROC;
377: settype(q, type, (int) length);
378: /* hold all initial entry points till end of declarations */
379: if(parstate >= INDATA) {
380: doentry(p);
381: }
382: #ifdef SDB
383: if(sdbflag)
384: { /* may need to preserve CLENTRY here */
385: entrystab(p,class);
386: }
387: #endif
388: }
389:
390: /* generate epilogs */
391:
392: LOCAL epicode()
393: {
394: register int i;
395:
396: if(procclass==CLPROC)
397: {
398: if(proctype==TYSUBR)
399: {
400: putlabel(ret0label);
401: if(substars)
402: putforce(TYINT, ICON(0) );
403: putlabel(retlabel);
404: goret(TYSUBR);
405: }
406: else {
407: putlabel(retlabel);
408: if(multitype)
409: {
410: typeaddr = autovar(1, TYADDR, PNULL);
411: putbranch( cpexpr(typeaddr) );
412: for(i = 0; i < NTYPES ; ++i)
413: if(rtvlabel[i] != 0)
414: {
415: putlabel(rtvlabel[i]);
416: retval(i);
417: }
418: }
419: else
420: retval(proctype);
421: }
422: }
423:
424: else if(procclass != CLBLOCK)
425: {
426: putlabel(retlabel);
427: goret(TYSUBR);
428: }
429: }
430:
431:
432: /* generate code to return value of type t */
433:
434: LOCAL retval(t)
435: register int t;
436: {
437: register Addrp p;
438:
439: switch(t)
440: {
441: case TYCHAR:
442: case TYCOMPLEX:
443: case TYDCOMPLEX:
444: break;
445:
446: case TYLOGICAL:
447: t = tylogical;
448: case TYADDR:
449: case TYSHORT:
450: case TYLONG:
451: p = (Addrp) cpexpr(retslot);
452: p->vtype = t;
453: putforce(t, p);
454: break;
455:
456: case TYREAL:
457: case TYDREAL:
458: p = (Addrp) cpexpr(retslot);
459: p->vtype = t;
460: putforce(t, p);
461: break;
462:
463: case TYERROR:
464: return; /* someone else already complained */
465:
466: default:
467: badtype("retval", t);
468: }
469: goret(t);
470: }
471:
472:
473: /* Allocate extra argument array if needed. Generate prologs. */
474:
475: LOCAL procode()
476: {
477: register struct Entrypoint *p;
478: Addrp argvec;
479:
480: #if TARGET==GCOS
481: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
482: #else
483: if(lastargslot>0 && nentry>1)
484: #if TARGET == VAX
485: argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL);
486: #else
487: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
488: #endif
489: else
490: argvec = NULL;
491: #endif
492:
493:
494: #if TARGET == PDP11
495: /* for the optimizer */
496: if(fudgelabel)
497: putlabel(fudgelabel);
498: #endif
499:
500: for(p = entries ; p ; p = p->entnextp)
501: prolog(p, argvec);
502:
503: #if FAMILY == PCC
504: putrbrack(procno);
505: #endif
506:
507: prendproc();
508: }
509:
510:
511: /*
512: * manipulate argument lists (allocate argument slot positions)
513: * keep track of return types and labels
514: */
515:
516: LOCAL doentry(ep)
517: struct Entrypoint *ep;
518: {
519: register int type;
520: register Namep np;
521: chainp p;
522: register Namep q;
523: Addrp mkarg();
524:
525: ++nentry;
526: if(procclass == CLMAIN)
527: {
528: if (optimflag)
529: optbuff (SKLABEL, 0, ep->entrylabel, 0);
530: else
531: putlabel(ep->entrylabel);
532: return;
533: }
534: else if(procclass == CLBLOCK)
535: return;
536:
537: impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) );
538: type = np->vtype;
539: if(proctype == TYUNKNOWN)
540: if( (proctype = type) == TYCHAR)
541: procleng = (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1));
542:
543: if(proctype == TYCHAR)
544: {
545: if(type != TYCHAR)
546: err("noncharacter entry of character function");
547: else if( (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)) != procleng)
548: err("mismatched character entry lengths");
549: }
550: else if(type == TYCHAR)
551: err("character entry of noncharacter function");
552: else if(type != proctype)
553: multitype = YES;
554: if(rtvlabel[type] == 0)
555: rtvlabel[type] = newlabel();
556: ep->typelabel = rtvlabel[type];
557:
558: if(type == TYCHAR)
559: {
560: if(chslot < 0)
561: {
562: chslot = nextarg(TYADDR);
563: chlgslot = nextarg(TYLENG);
564: }
565: np->vstg = STGARG;
566: np->vardesc.varno = chslot;
567: if(procleng < 0)
568: np->vleng = (expptr) mkarg(TYLENG, chlgslot);
569: }
570: else if( ISCOMPLEX(type) )
571: {
572: np->vstg = STGARG;
573: if(cxslot < 0)
574: cxslot = nextarg(TYADDR);
575: np->vardesc.varno = cxslot;
576: }
577: else if(type != TYSUBR)
578: {
579: if(retslot == NULL)
580: retslot = autovar(1, TYDREAL, PNULL);
581: np->vstg = STGAUTO;
582: np->voffset = retslot->memoffset->constblock.const.ci;
583: }
584:
585: for(p = ep->arglist ; p ; p = p->nextp)
586: if(! (( q = (Namep) (p->datap) )->vdcldone) )
587: q->vardesc.varno = nextarg(TYADDR);
588:
589: for(p = ep->arglist ; p ; p = p->nextp)
590: if(! (( q = (Namep) (p->datap) )->vdcldone) )
591: {
592: if(q->vclass == CLPROC && q->vtype == TYUNKNOWN)
593: continue;
594: impldcl(q);
595: if(q->vtype == TYCHAR)
596: {
597: if(q->vleng == NULL) /* character*(*) */
598: q->vleng = (expptr)
599: mkarg(TYLENG, nextarg(TYLENG) );
600: else if(nentry == 1)
601: nextarg(TYLENG);
602: }
603: else if(q->vclass==CLPROC && nentry==1)
604: nextarg(TYLENG) ;
605: }
606:
607: if (optimflag)
608: optbuff (SKLABEL, 0, ep->entrylabel, 0);
609: else
610: putlabel(ep->entrylabel);
611: }
612:
613:
614:
615: LOCAL nextarg(type)
616: int type;
617: {
618: int k;
619: k = lastargslot;
620: lastargslot += typesize[type];
621: return(k);
622: }
623:
624: /* generate variable references */
625:
626: LOCAL dobss()
627: {
628: register struct Hashentry *p;
629: register Namep q;
630: register int i;
631: int align;
632: ftnint leng, iarrl;
633: char *memname();
634: int qstg, qclass, qtype;
635:
636: pruse(asmfile, USEBSS);
637: varsizes = NULL;
638:
639: for(p = hashtab ; p<lasthash ; ++p)
640: if(q = p->varp)
641: {
642: qstg = q->vstg;
643: qtype = q->vtype;
644: qclass = q->vclass;
645:
646: if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
647: (qclass==CLVAR && qstg==STGUNKNOWN) )
648: warn1("local variable %s never used", varstr(VL,q->varname) );
649: else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG)
650: mkext(varunder(VL, q->varname)) ->extstg = STGEXT;
651:
652: if (qclass == CLVAR && qstg == STGBSS)
653: {
654: if (SMALLVAR(q->varsize))
655: {
656: enlist(q->varsize, q, NULL);
657: q->inlcomm = NO;
658: }
659: else
660: {
661: if (q->init == NO)
662: {
663: preven(ALIDOUBLE);
664: prlocvar(memname(qstg, q->vardesc.varno), q->varsize);
665: q->inlcomm = YES;
666: }
667: else
668: prlocdata(memname(qstg, q->vardesc.varno), q->varsize,
669: q->vtype, q->initoffset, &(q->inlcomm));
670: }
671: }
672: else if(qclass==CLVAR && qstg!=STGARG)
673: {
674: if(q->vdim && !ISICON(q->vdim->nelt) )
675: dclerr("adjustable dimension on non-argument", q);
676: if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng)))
677: dclerr("adjustable leng on nonargument", q);
678: }
679:
680: chkdim(q);
681: }
682:
683: for (i = 0 ; i < nequiv ; ++i)
684: if ( (leng = eqvclass[i].eqvleng) != 0 )
685: {
686: if (SMALLVAR(leng))
687: enlist(leng, NULL, eqvclass + i);
688: else if (eqvclass[i].init == NO)
689: {
690: preven(ALIDOUBLE);
691: prlocvar(memname(STGEQUIV, i), leng);
692: eqvclass[i].inlcomm = YES;
693: }
694: else
695: prlocdata(memname(STGEQUIV, i), leng, TYDREAL,
696: eqvclass[i].initoffset, &(eqvclass[i].inlcomm));
697: }
698:
699: outlocvars();
700: #ifdef SDB
701: if(sdbflag) {
702: register struct Entrypoint *ep;
703: register chainp cp;
704:
705: for (ep = entries; ep; ep = ep->entnextp)
706: for (cp = ep->arglist ; cp ; cp = cp->nextp)
707: if ((q = (Namep) cp->datap) && q->vstg == STGARG) {
708: q->vdcldone = YES;
709: namestab(q);
710: }
711: for (p = hashtab ; p<lasthash ; ++p) if(q = p->varp) {
712: if (q->vtype == TYUNKNOWN || q->vtype == TYERROR)
713: continue;
714: qstg = q->vstg;
715: qclass = q->vclass;
716: q->vdcldone = YES;
717: if ( ONEOF(qclass, M(CLVAR)|M(CLPARAM)|M(CLPROC)) ) {
718: if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) )
719: namestab(q);
720: }
721: }
722: }
723: #endif
724:
725: close(vdatafile);
726: close(vchkfile);
727: unlink(vdatafname);
728: unlink(vchkfname);
729: vdatahwm = 0;
730: }
731:
732:
733:
734: donmlist()
735: {
736: register struct Hashentry *p;
737: register Namep q;
738:
739: pruse(asmfile, USEINIT);
740:
741: for(p=hashtab; p<lasthash; ++p)
742: if( (q = p->varp) && q->vclass==CLNAMELIST)
743: namelist(q);
744: }
745:
746:
747: doext()
748: {
749: struct Extsym *p;
750:
751: for(p = extsymtab ; p<nextext ; ++p)
752: prext(p);
753: }
754:
755:
756:
757:
758: ftnint iarrlen(q)
759: register Namep q;
760: {
761: ftnint leng;
762:
763: leng = typesize[q->vtype];
764: if(leng <= 0)
765: return(-1);
766: if(q->vdim)
767: if( ISICON(q->vdim->nelt) )
768: leng *= q->vdim->nelt->constblock.const.ci;
769: else return(-1);
770: if(q->vleng)
771: if( ISICON(q->vleng) )
772: leng *= q->vleng->constblock.const.ci;
773: else return(-1);
774: return(leng);
775: }
776:
777: /* This routine creates a static block representing the namelist.
778: An equivalent declaration of the structure produced is:
779: struct namelist
780: {
781: char namelistname[16];
782: struct namelistentry
783: {
784: char varname[16]; # 16 plus null padding -> 20
785: char *varaddr;
786: short int type;
787: short int len; # length of type
788: struct dimensions *dimp; # null means scalar
789: } names[];
790: };
791:
792: struct dimensions
793: {
794: int numberofdimensions;
795: int numberofelements
796: int baseoffset;
797: int span[numberofdimensions];
798: };
799: where the namelistentry list terminates with a null varname
800: If dimp is not null, then the corner element of the array is at
801: varaddr. However, the element with subscripts (i1,...,in) is at
802: varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...)
803: */
804:
805: namelist(np)
806: Namep np;
807: {
808: register chainp q;
809: register Namep v;
810: register struct Dimblock *dp;
811: char *memname();
812: int type, dimno, dimoffset;
813: flag bad;
814:
815:
816: preven(ALILONG);
817: fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno));
818: putstr(asmfile, varstr(VL, np->varname), 16);
819: dimno = ++lastvarno;
820: dimoffset = 0;
821: bad = NO;
822:
823: for(q = np->varxptr.namelist ; q ; q = q->nextp)
824: {
825: vardcl( v = (Namep) (q->datap) );
826: type = v->vtype;
827: if( ONEOF(v->vstg, MSKSTATIC) )
828: {
829: preven(ALILONG);
830: putstr(asmfile, varstr(VL,v->varname), 16);
831: praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset);
832: prconi(asmfile, TYSHORT, type );
833: prconi(asmfile, TYSHORT,
834: type==TYCHAR ?
835: (v->vleng->constblock.const.ci) :
836: (ftnint) typesize[type]);
837: if(v->vdim)
838: {
839: praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset);
840: dimoffset += (3 + v->vdim->ndim) * SZINT;
841: }
842: else
843: praddr(asmfile, STGNULL,0,(ftnint) 0);
844: }
845: else
846: {
847: dclerr("may not appear in namelist", v);
848: bad = YES;
849: }
850: }
851:
852: if(bad)
853: return;
854:
855: putstr(asmfile, "", 16);
856:
857: if(dimoffset > 0)
858: {
859: fprintf(asmfile, LABELFMT, memname(STGINIT,dimno));
860: for(q = np->varxptr.namelist ; q ; q = q->nextp)
861: if(dp = q->datap->nameblock.vdim)
862: {
863: int i;
864: prconi(asmfile, TYINT, (ftnint) (dp->ndim) );
865: prconi(asmfile, TYINT,
866: (ftnint) (dp->nelt->constblock.const.ci) );
867: prconi(asmfile, TYINT,
868: (ftnint) (dp->baseoffset->constblock.const.ci));
869: for(i=0; i<dp->ndim ; ++i)
870: prconi(asmfile, TYINT,
871: dp->dims[i].dimsize->constblock.const.ci);
872: }
873: }
874:
875: }
876:
877: LOCAL docommon()
878: {
879: register struct Extsym *p;
880: register chainp q;
881: struct Dimblock *t;
882: expptr neltp;
883: register Namep v;
884: ftnint size;
885: int type;
886:
887: for(p = extsymtab ; p<nextext ; ++p)
888: if(p->extstg==STGCOMMON)
889: {
890: #ifdef SDB
891: if(sdbflag)
892: prstab(varstr(XL,p->extname), N_BCOMM, 0, 0);
893: #endif
894: for(q = p->extp ; q ; q = q->nextp)
895: {
896: v = (Namep) (q->datap);
897: if(v->vdcldone == NO)
898: vardcl(v);
899: type = v->vtype;
900: if(p->extleng % typealign[type] != 0)
901: {
902: dclerr("common alignment", v);
903: p->extleng = roundup(p->extleng, typealign[type]);
904: }
905: v->voffset = p->extleng;
906: v->vardesc.varno = p - extsymtab;
907: if(type == TYCHAR)
908: size = v->vleng->constblock.const.ci;
909: else size = typesize[type];
910: if(t = v->vdim)
911: if( (neltp = t->nelt) && ISCONST(neltp) )
912: size *= neltp->constblock.const.ci;
913: else
914: dclerr("adjustable array in common", v);
915: p->extleng += size;
916: #ifdef SDB
917: if(sdbflag)
918: {
919: namestab(v);
920: }
921: #endif
922: }
923:
924: frchain( &(p->extp) );
925: #ifdef SDB
926: if(sdbflag)
927: prstab(varstr(XL,p->extname), N_ECOMM, 0, 0);
928: #endif
929: }
930: }
931:
932:
933:
934:
935:
936: LOCAL docomleng()
937: {
938: register struct Extsym *p;
939:
940: for(p = extsymtab ; p < nextext ; ++p)
941: if(p->extstg == STGCOMMON)
942: {
943: if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
944: && !eqn(XL,"_BLNK__ ",p->extname) )
945: warn1("incompatible lengths for common block %s",
946: nounder(XL, p->extname) );
947: if(p->maxleng < p->extleng)
948: p->maxleng = p->extleng;
949: p->extleng = 0;
950: }
951: }
952:
953:
954:
955:
956: /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
957:
958: /* frees a temporary block */
959:
960: frtemp(p)
961: Tempp p;
962: {
963: Addrp t;
964:
965: if (optimflag)
966: {
967: if (p->tag != TTEMP)
968: badtag ("frtemp",p->tag);
969: t = p->memalloc;
970: }
971: else
972: t = (Addrp) p;
973:
974: /* restore clobbered character string lengths */
975: if(t->vtype==TYCHAR && t->varleng!=0)
976: {
977: frexpr(t->vleng);
978: t->vleng = ICON(t->varleng);
979: }
980:
981: /* put block on chain of temps to be reclaimed */
982: holdtemps = mkchain(t, holdtemps);
983: }
984:
985:
986:
987: /* allocate an automatic variable slot */
988:
989: Addrp autovar(nelt, t, lengp)
990: register int nelt, t;
991: expptr lengp;
992: {
993: ftnint leng;
994: register Addrp q;
995:
996: if(lengp)
997: if( ISICON(lengp) )
998: leng = lengp->constblock.const.ci;
999: else {
1000: fatal("automatic variable of nonconstant length");
1001: }
1002: else
1003: leng = typesize[t];
1004: autoleng = roundup( autoleng, typealign[t]);
1005:
1006: q = ALLOC(Addrblock);
1007: q->tag = TADDR;
1008: q->vtype = t;
1009: if(lengp)
1010: {
1011: q->vleng = ICON(leng);
1012: q->varleng = leng;
1013: }
1014: q->vstg = STGAUTO;
1015: q->memno = newlabel();
1016: q->ntempelt = nelt;
1017: #if TARGET==PDP11 || TARGET==VAX
1018: /* stack grows downward */
1019: autoleng += nelt*leng;
1020: q->memoffset = ICON( - autoleng );
1021: #else
1022: q->memoffset = ICON( autoleng );
1023: autoleng += nelt*leng;
1024: #endif
1025:
1026: return(q);
1027: }
1028:
1029:
1030:
1031: /*
1032: * create a temporary block (TTEMP) when optimizing,
1033: * an ordinary TADDR block when not optimizing
1034: */
1035:
1036: Tempp mktmpn(nelt, type, lengp)
1037: int nelt;
1038: register int type;
1039: expptr lengp;
1040: {
1041: ftnint leng;
1042: chainp p, oldp;
1043: register Tempp q;
1044: Addrp altemp;
1045:
1046: if (! optimflag)
1047: return ( (Tempp) mkaltmpn(nelt,type,lengp) );
1048: if(type==TYUNKNOWN || type==TYERROR)
1049: badtype("mktmpn", type);
1050:
1051: if(type==TYCHAR)
1052: if( ISICON(lengp) )
1053: leng = lengp->constblock.const.ci;
1054: else {
1055: err("adjustable length");
1056: return( (Tempp) errnode() );
1057: }
1058: else
1059: leng = typesize[type];
1060:
1061: q = ALLOC(Tempblock);
1062: q->tag = TTEMP;
1063: q->vtype = type;
1064: if(type == TYCHAR)
1065: {
1066: q->vleng = ICON(leng);
1067: q->varleng = leng;
1068: }
1069:
1070: altemp = ALLOC(Addrblock);
1071: altemp->tag = TADDR;
1072: altemp->vstg = STGUNKNOWN;
1073: q->memalloc = altemp;
1074:
1075: q->ntempelt = nelt;
1076: q->istemp = YES;
1077: return(q);
1078: }
1079:
1080:
1081:
1082: Addrp mktemp(type, lengp)
1083: int type;
1084: expptr lengp;
1085: {
1086: return( (Addrp) mktmpn(1,type,lengp) );
1087: }
1088:
1089:
1090:
1091: /* allocate a temporary location for the given temporary block;
1092: if already allocated, return its location */
1093:
1094: Addrp altmpn(tp)
1095: Tempp tp;
1096:
1097: {
1098: Addrp t, q;
1099:
1100: if (tp->tag != TTEMP)
1101: badtag ("altmpn",tp->tag);
1102:
1103: t = tp->memalloc;
1104: if (t->vstg != STGUNKNOWN)
1105: {
1106: if (tp->vtype == TYCHAR)
1107: {
1108: /*
1109: * Unformatted I/O parameters are treated like character
1110: * strings (sigh) -- propagate type and length.
1111: */
1112: t = (Addrp) cpexpr(t);
1113: t->vtype = tp->vtype;
1114: t->vleng = tp->vleng;
1115: t->varleng = tp->varleng;
1116: }
1117: return (t);
1118: }
1119:
1120: q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng);
1121: cpn (sizeof(struct Addrblock), (char*)q, (char*)t);
1122: free ( (charptr) q);
1123: return(t);
1124: }
1125:
1126:
1127:
1128: /* create and allocate space immediately for a temporary */
1129:
1130: Addrp mkaltemp(type,lengp)
1131: int type;
1132: expptr lengp;
1133: {
1134: return (mkaltmpn(1,type,lengp));
1135: }
1136:
1137:
1138:
1139: Addrp mkaltmpn(nelt,type,lengp)
1140: int nelt;
1141: register int type;
1142: expptr lengp;
1143: {
1144: ftnint leng;
1145: chainp p, oldp;
1146: register Addrp q;
1147:
1148: if(type==TYUNKNOWN || type==TYERROR)
1149: badtype("mkaltmpn", type);
1150:
1151: if(type==TYCHAR)
1152: if( ISICON(lengp) )
1153: leng = lengp->constblock.const.ci;
1154: else {
1155: err("adjustable length");
1156: return( (Addrp) errnode() );
1157: }
1158:
1159: /*
1160: * if a temporary of appropriate shape is on the templist,
1161: * remove it from the list and return it
1162: */
1163:
1164: #ifdef notdef
1165: /*
1166: * This code is broken until SKFRTEMP slots can be processed in putopt()
1167: * instead of in optimize() -- all kinds of things in putpcc.c can
1168: * bomb because of this. Sigh.
1169: */
1170: for(oldp=CHNULL, p=templist ; p ; oldp=p, p=p->nextp)
1171: {
1172: q = (Addrp) (p->datap);
1173: if(q->vtype==type && q->ntempelt==nelt &&
1174: (type!=TYCHAR || q->vleng->constblock.const.ci==leng) )
1175: {
1176: if(oldp)
1177: oldp->nextp = p->nextp;
1178: else
1179: templist = p->nextp;
1180: free( (charptr) p);
1181:
1182: if (debugflag[14])
1183: fprintf(diagfile,"mkaltmpn reusing offset %d\n",
1184: q->memoffset->constblock.const.ci);
1185: return(q);
1186: }
1187: }
1188: #endif notdef
1189: q = autovar(nelt, type, lengp);
1190: q->istemp = YES;
1191:
1192: if (debugflag[14])
1193: fprintf(diagfile,"mkaltmpn new offset %d\n",
1194: q->memoffset->constblock.const.ci);
1195: return(q);
1196: }
1197:
1198:
1199:
1200: /* The following routine is a patch which is only needed because the */
1201: /* code for processing actual arguments for calls does not allocate */
1202: /* the temps it needs before optimization takes place. A better */
1203: /* solution is possible, but I do not have the time to implement it */
1204: /* now. */
1205: /* */
1206: /* Robert P. Corbett */
1207:
1208: Addrp
1209: mkargtemp(type, lengp)
1210: int type;
1211: expptr lengp;
1212: {
1213: ftnint leng;
1214: chainp oldp, p;
1215: Addrp q;
1216:
1217: if (type == TYUNKNOWN || type == TYERROR)
1218: badtype("mkargtemp", type);
1219:
1220: if (type == TYCHAR)
1221: {
1222: if (ISICON(lengp))
1223: leng = lengp->constblock.const.ci;
1224: else
1225: {
1226: err("adjustable length");
1227: return ((Addrp) errnode());
1228: }
1229: }
1230:
1231: oldp = CHNULL;
1232: p = argtemplist;
1233:
1234: while (p)
1235: {
1236: q = (Addrp) (p->datap);
1237: if (q->vtype == type
1238: && (type != TYCHAR || q->vleng->constblock.const.ci == leng))
1239: {
1240: if (oldp)
1241: oldp->nextp = p->nextp;
1242: else
1243: argtemplist = p->nextp;
1244:
1245: p->nextp = activearglist;
1246: activearglist = p;
1247:
1248: return ((Addrp) cpexpr(q));
1249: }
1250:
1251: oldp = p;
1252: p = p->nextp;
1253: }
1254:
1255: q = autovar(1, type, lengp);
1256: activearglist = mkchain(q, activearglist);
1257: return ((Addrp) cpexpr(q));
1258: }
1259:
1260: /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
1261:
1262: struct Extsym *comblock(len, s)
1263: register int len;
1264: register char *s;
1265: {
1266: struct Extsym *p;
1267:
1268: if(len == 0)
1269: {
1270: s = BLANKCOMMON;
1271: len = strlen(s);
1272: }
1273: p = mkext( varunder(len, s) );
1274: if(p->extstg == STGUNKNOWN)
1275: p->extstg = STGCOMMON;
1276: else if(p->extstg != STGCOMMON)
1277: {
1278: errstr("%s cannot be a common block name", s);
1279: return(0);
1280: }
1281:
1282: return( p );
1283: }
1284:
1285:
1286: incomm(c, v)
1287: struct Extsym *c;
1288: Namep v;
1289: {
1290: if(v->vstg != STGUNKNOWN)
1291: dclerr("incompatible common declaration", v);
1292: else
1293: {
1294: if(c == (struct Extsym *) 0)
1295: return; /* Illegal common block name upstream */
1296: v->vstg = STGCOMMON;
1297: c->extp = hookup(c->extp, mkchain(v,CHNULL) );
1298: }
1299: }
1300:
1301:
1302:
1303:
1304: settype(v, type, length)
1305: register Namep v;
1306: register int type;
1307: register int length;
1308: {
1309: if(type == TYUNKNOWN)
1310: return;
1311:
1312: if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
1313: {
1314: v->vtype = TYSUBR;
1315: frexpr(v->vleng);
1316: }
1317: else if(type < 0) /* storage class set */
1318: {
1319: if(v->vstg == STGUNKNOWN)
1320: v->vstg = - type;
1321: else if(v->vstg != -type)
1322: dclerr("incompatible storage declarations", v);
1323: }
1324: else if(v->vtype == TYUNKNOWN)
1325: {
1326: if( (v->vtype = lengtype(type, length))==TYCHAR )
1327: {
1328: if(length >= 0)
1329: v->vleng = ICON(length);
1330: else if(!(v->vstg == STGARG || v->vclass == CLENTRY ||
1331: (v->vclass == CLPROC && v->vprocclass == PTHISPROC)))
1332: {
1333: dclerr("illegal adjustable length character variable", v);
1334: v->vleng = ICON(0);
1335: }
1336: }
1337: }
1338: else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.const.ci!=length) )
1339: dclerr("incompatible type declarations", v);
1340: }
1341:
1342:
1343:
1344:
1345:
1346: lengtype(type, length)
1347: register int type;
1348: register int length;
1349: {
1350: switch(type)
1351: {
1352: case TYREAL:
1353: if(length == 8)
1354: return(TYDREAL);
1355: if(length == 4)
1356: goto ret;
1357: break;
1358:
1359: case TYCOMPLEX:
1360: if(length == 16)
1361: return(TYDCOMPLEX);
1362: if(length == 8)
1363: goto ret;
1364: break;
1365:
1366: case TYSHORT:
1367: case TYDREAL:
1368: case TYDCOMPLEX:
1369: case TYCHAR:
1370: case TYUNKNOWN:
1371: case TYSUBR:
1372: case TYERROR:
1373: goto ret;
1374:
1375: case TYLOGICAL:
1376: if(length == typesize[TYLOGICAL])
1377: goto ret;
1378: break;
1379:
1380: case TYLONG:
1381: if(length == 0)
1382: return(tyint);
1383: if(length == 2)
1384: return(TYSHORT);
1385: if(length == 4)
1386: goto ret;
1387: break;
1388: default:
1389: badtype("lengtype", type);
1390: }
1391:
1392: if(length != 0)
1393: err("incompatible type-length combination");
1394:
1395: ret:
1396: return(type);
1397: }
1398:
1399:
1400:
1401:
1402:
1403: setintr(v)
1404: register Namep v;
1405: {
1406: register int k;
1407:
1408: if(v->vstg == STGUNKNOWN)
1409: v->vstg = STGINTR;
1410: else if(v->vstg!=STGINTR)
1411: dclerr("incompatible use of intrinsic function", v);
1412: if(v->vclass==CLUNKNOWN)
1413: v->vclass = CLPROC;
1414: if(v->vprocclass == PUNKNOWN)
1415: v->vprocclass = PINTRINSIC;
1416: else if(v->vprocclass != PINTRINSIC)
1417: dclerr("invalid intrinsic declaration", v);
1418: if(k = intrfunct(v->varname))
1419: v->vardesc.varno = k;
1420: else
1421: dclerr("unknown intrinsic function", v);
1422: }
1423:
1424:
1425:
1426: setext(v)
1427: register Namep v;
1428: {
1429: if(v->vclass == CLUNKNOWN)
1430: v->vclass = CLPROC;
1431: else if(v->vclass != CLPROC)
1432: dclerr("conflicting declarations", v);
1433:
1434: if(v->vprocclass == PUNKNOWN)
1435: v->vprocclass = PEXTERNAL;
1436: else if(v->vprocclass != PEXTERNAL)
1437: dclerr("conflicting declarations", v);
1438: }
1439:
1440:
1441:
1442:
1443: /* create dimensions block for array variable */
1444:
1445: setbound(v, nd, dims)
1446: register Namep v;
1447: int nd;
1448: struct { expptr lb, ub; } dims[ ];
1449: {
1450: register expptr q, t;
1451: register struct Dimblock *p;
1452: int i;
1453:
1454: if(v->vclass == CLUNKNOWN)
1455: v->vclass = CLVAR;
1456: else if(v->vclass != CLVAR)
1457: {
1458: dclerr("only variables may be arrays", v);
1459: return;
1460: }
1461: if(v->vdim)
1462: {
1463: dclerr("redimensioned array", v);
1464: return;
1465: }
1466:
1467: v->vdim = p = (struct Dimblock *)
1468: ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) );
1469: p->ndim = nd;
1470: p->nelt = ICON(1);
1471:
1472: for(i=0 ; i<nd ; ++i)
1473: {
1474: #ifdef SDB
1475: if(sdbflag) {
1476: /* Save the bounds trees built up by the grammar routines for use in stabs */
1477:
1478: if(dims[i].lb == NULL) p->dims[i].lb=ICON(1);
1479: else p->dims[i].lb= (expptr) cpexpr(dims[i].lb);
1480: if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL;
1481: else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL);
1482:
1483: if(dims[i].ub == NULL) p->dims[i].ub=ICON(1);
1484: else p->dims[i].ub = (expptr) cpexpr(dims[i].ub);
1485: if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL;
1486: else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL);
1487: }
1488: #endif
1489: if( (q = dims[i].ub) == NULL)
1490: {
1491: if(i == nd-1)
1492: {
1493: frexpr(p->nelt);
1494: p->nelt = NULL;
1495: }
1496: else
1497: err("only last bound may be asterisk");
1498: p->dims[i].dimsize = ICON(1);;
1499: p->dims[i].dimexpr = NULL;
1500: }
1501: else
1502: {
1503: if(dims[i].lb)
1504: {
1505: q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
1506: q = mkexpr(OPPLUS, q, ICON(1) );
1507: }
1508: if( ISCONST(q) )
1509: {
1510: if (!ISINT(q->headblock.vtype)) {
1511: dclerr("dimension bounds must be integer expression", v);
1512: frexpr(q);
1513: q = ICON(0);
1514: }
1515: if ( q->constblock.const.ci <= 0)
1516: {
1517: dclerr("array bounds out of sequence", v);
1518: frexpr(q);
1519: q = ICON(0);
1520: }
1521: p->dims[i].dimsize = q;
1522: p->dims[i].dimexpr = (expptr) PNULL;
1523: }
1524: else {
1525: p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL);
1526: p->dims[i].dimexpr = q;
1527: }
1528: if(p->nelt)
1529: p->nelt = mkexpr(OPSTAR, p->nelt,
1530: cpexpr(p->dims[i].dimsize) );
1531: }
1532: }
1533:
1534: q = dims[nd-1].lb;
1535: if(q == NULL)
1536: q = ICON(1);
1537:
1538: for(i = nd-2 ; i>=0 ; --i)
1539: {
1540: t = dims[i].lb;
1541: if(t == NULL)
1542: t = ICON(1);
1543: if(p->dims[i].dimsize)
1544: q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
1545: }
1546:
1547: if( ISCONST(q) )
1548: {
1549: p->baseoffset = q;
1550: p->basexpr = NULL;
1551: }
1552: else
1553: {
1554: p->baseoffset = (expptr) autovar(1, tyint, PNULL);
1555: p->basexpr = q;
1556: }
1557: }
1558:
1559:
1560:
1561: /*
1562: * Check the dimensions of q to ensure that they are appropriately defined.
1563: */
1564: LOCAL chkdim(q)
1565: register Namep q;
1566: {
1567: register struct Dimblock *p;
1568: register int i;
1569: expptr e;
1570:
1571: if (q == NULL)
1572: return;
1573: if (q->vclass != CLVAR)
1574: return;
1575: if (q->vdim == NULL)
1576: return;
1577: p = q->vdim;
1578: for (i = 0; i < p->ndim; ++i)
1579: {
1580: #ifdef SDB
1581: if (sdbflag)
1582: {
1583: if (e = p->dims[i].lb)
1584: chkdime(e, q);
1585: if (e = p->dims[i].ub)
1586: chkdime(e, q);
1587: }
1588: else
1589: #endif SDB
1590: if (e = p->dims[i].dimexpr)
1591: chkdime(e, q);
1592: }
1593: }
1594:
1595:
1596:
1597: /*
1598: * The actual checking for chkdim() -- examines each expression.
1599: */
1600: LOCAL chkdime(expr, q)
1601: expptr expr;
1602: Namep q;
1603: {
1604: register expptr e;
1605:
1606: e = fixtype(cpexpr(expr));
1607: if (!ISINT(e->exprblock.vtype))
1608: dclerr("non-integer dimension", q);
1609: else if (!safedim(e))
1610: dclerr("undefined dimension", q);
1611: frexpr(e);
1612: return;
1613: }
1614:
1615:
1616:
1617: /*
1618: * A recursive routine to find undefined variables in dimension expressions.
1619: */
1620: LOCAL safedim(e)
1621: expptr e;
1622: {
1623: chainp cp;
1624:
1625: if (e == NULL)
1626: return 1;
1627: switch (e->tag)
1628: {
1629: case TEXPR:
1630: if (e->exprblock.opcode == OPCALL || e->exprblock.opcode == OPCCALL)
1631: return 0;
1632: return safedim(e->exprblock.leftp) && safedim(e->exprblock.rightp);
1633: case TADDR:
1634: switch (e->addrblock.vstg)
1635: {
1636: case STGCOMMON:
1637: case STGARG:
1638: case STGCONST:
1639: case STGEQUIV:
1640: if (e->addrblock.isarray)
1641: return 0;
1642: return safedim(e->addrblock.memoffset);
1643: default:
1644: return 0;
1645: }
1646: case TCONST:
1647: case TTEMP:
1648: return 1;
1649: }
1650: return 0;
1651: }
1652:
1653:
1654:
1655: LOCAL enlist(size, np, ep)
1656: ftnint size;
1657: Namep np;
1658: struct Equivblock *ep;
1659: {
1660: register sizelist *sp;
1661: register sizelist *t;
1662: register varlist *p;
1663:
1664: sp = varsizes;
1665:
1666: if (sp == NULL)
1667: {
1668: sp = ALLOC(SizeList);
1669: sp->size = size;
1670: varsizes = sp;
1671: }
1672: else
1673: {
1674: while (sp->size != size)
1675: {
1676: if (sp->next != NULL && sp->next->size <= size)
1677: sp = sp->next;
1678: else
1679: {
1680: t = sp;
1681: sp = ALLOC(SizeList);
1682: sp->size = size;
1683: sp->next = t->next;
1684: t->next = sp;
1685: }
1686: }
1687: }
1688:
1689: p = ALLOC(VarList);
1690: p->next = sp->vars;
1691: p->np = np;
1692: p->ep = ep;
1693:
1694: sp->vars = p;
1695:
1696: return;
1697: }
1698:
1699:
1700:
1701: outlocvars()
1702: {
1703:
1704: register varlist *first, *last;
1705: register varlist *vp, *t;
1706: register sizelist *sp, *sp1;
1707: register Namep np;
1708: register struct Equivblock *ep;
1709: register int i;
1710: register int alt;
1711: register int type;
1712: char sname[100];
1713: char setbuff[100];
1714:
1715: sp = varsizes;
1716: if (sp == NULL)
1717: return;
1718:
1719: vp = sp->vars;
1720: if (vp->np != NULL)
1721: {
1722: np = vp->np;
1723: sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel,
1724: np->vardesc.varno);
1725: }
1726: else
1727: {
1728: i = vp->ep - eqvclass;
1729: sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart);
1730: }
1731:
1732: first = last = NULL;
1733: alt = NO;
1734:
1735: while (sp != NULL)
1736: {
1737: vp = sp->vars;
1738: while (vp != NULL)
1739: {
1740: t = vp->next;
1741: if (alt == YES)
1742: {
1743: alt = NO;
1744: vp->next = first;
1745: first = vp;
1746: }
1747: else
1748: {
1749: alt = YES;
1750: if (last != NULL)
1751: last->next = vp;
1752: else
1753: first = vp;
1754: vp->next = NULL;
1755: last = vp;
1756: }
1757: vp = t;
1758: }
1759: sp1 = sp;
1760: sp = sp->next;
1761: free((char *) sp1);
1762: }
1763:
1764: vp = first;
1765: while(vp != NULL)
1766: {
1767: if (vp->np != NULL)
1768: {
1769: np = vp->np;
1770: sprintf(sname, "v.%d", np->vardesc.varno);
1771: if (np->init)
1772: prlocdata(sname, np->varsize, np->vtype, np->initoffset,
1773: &(np->inlcomm));
1774: else
1775: {
1776: pralign(typealign[np->vtype]);
1777: fprintf(initfile, "%s:\n", sname);
1778: prspace(np->varsize);
1779: }
1780: np->inlcomm = NO;
1781: }
1782: else
1783: {
1784: ep = vp->ep;
1785: i = ep - eqvclass;
1786: if (ep->eqvleng >= 8)
1787: type = TYDREAL;
1788: else if (ep->eqvleng >= 4)
1789: type = TYLONG;
1790: else if (ep->eqvleng >= 2)
1791: type = TYSHORT;
1792: else
1793: type = TYCHAR;
1794: sprintf(sname, "q.%d", i + eqvstart);
1795: if (ep->init)
1796: prlocdata(sname, ep->eqvleng, type, ep->initoffset,
1797: &(ep->inlcomm));
1798: else
1799: {
1800: pralign(typealign[type]);
1801: fprintf(initfile, "%s:\n", sname);
1802: prspace(ep->eqvleng);
1803: }
1804: ep->inlcomm = NO;
1805: }
1806: t = vp;
1807: vp = vp->next;
1808: free((char *) t);
1809: }
1810: fprintf(initfile, "%s\n", setbuff);
1811: return;
1812: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.