|
|
1.1 root 1: /* @(#)proc.c 1.4 (Berkeley) 6/1/81 */
2: #include "defs.h"
3: #include "machdefs.h"
4:
5: #ifdef SDB
6: # include <a.out.h>
7: # ifndef N_SO
8: # include <stab.h>
9: # endif
10: #endif
11:
12:
13: typedef
14: struct SizeList
15: {
16: struct SizeList *next;
17: ftnint size;
18: struct VarList *vars;
19: }
20: sizelist;
21:
22:
23: typedef
24: struct VarList
25: {
26: struct VarList *next;
27: Namep np;
28: struct Equivblock *ep;
29: }
30: varlist;
31:
32:
33: LOCAL sizelist *varsizes;
34:
35:
36: /* start a new procedure */
37:
38: newproc()
39: {
40: if(parstate != OUTSIDE)
41: {
42: execerr("missing end statement", CNULL);
43: endproc();
44: }
45:
46: parstate = INSIDE;
47: procclass = CLMAIN; /* default */
48: }
49:
50:
51:
52: /* end of procedure. generate variables, epilogs, and prologs */
53:
54: endproc()
55: {
56: struct Labelblock *lp;
57:
58: if(parstate < INDATA)
59: enddcl();
60: if(ctlstack >= ctls)
61: err("DO loop or BLOCK IF not closed");
62: for(lp = labeltab ; lp < labtabend ; ++lp)
63: if(lp->stateno!=0 && lp->labdefined==NO)
64: errstr("missing statement number %s", convic(lp->stateno) );
65:
66: if (optimflag)
67: optimize();
68:
69: outiodata();
70: epicode();
71: procode();
72: donmlist();
73: dobss();
74:
75: #if FAMILY == PCC
76: putbracket();
77: #endif
78: fixlwm();
79: procinit(); /* clean up for next procedure */
80: }
81:
82:
83:
84: /* End of declaration section of procedure. Allocate storage. */
85:
86: enddcl()
87: {
88: register struct Entrypoint *ep;
89:
90: parstate = INEXEC;
91: docommon();
92: doequiv();
93: docomleng();
94: for(ep = entries ; ep ; ep = ep->entnextp) {
95: doentry(ep);
96: #ifdef SDB
97: if(sdbflag)
98: {
99: entrystab(ep,procclass);
100: }
101: #endif
102: }
103: }
104:
105: /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
106:
107: /* Main program or Block data */
108:
109: startproc(progname, class)
110: struct Extsym * progname;
111: int class;
112: {
113: register struct Entrypoint *p;
114:
115: p = ALLOC(Entrypoint);
116: if(class == CLMAIN)
117: puthead("MAIN_", CLMAIN);
118: else
119: puthead(CNULL, CLBLOCK);
120: if(class == CLMAIN)
121: newentry( mkname(5, "MAIN") );
122: p->entryname = progname;
123: p->entrylabel = newlabel();
124: entries = p;
125:
126: procclass = class;
127: retlabel = newlabel();
128: fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
129: if(progname)
130: fprintf(diagfile, " %s", nounder(XL, procname = progname->extname) );
131: fprintf(diagfile, ":\n");
132: #ifdef SDB
133: if(sdbflag) {
134: entrystab(p,class);
135: }
136: #endif
137: }
138:
139: /* subroutine or function statement */
140:
141: struct Extsym *newentry(v)
142: register Namep v;
143: {
144: register struct Extsym *p;
145:
146: p = mkext( varunder(VL, v->varname) );
147:
148: if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
149: {
150: if(p == 0)
151: dclerr("invalid entry name", v);
152: else dclerr("external name already used", v);
153: return(0);
154: }
155: v->vstg = STGAUTO;
156: v->vprocclass = PTHISPROC;
157: v->vclass = CLPROC;
158: p->extstg = STGEXT;
159: p->extinit = YES;
160: return(p);
161: }
162:
163:
164: entrypt(class, type, length, entry, args)
165: int class, type;
166: ftnint length;
167: struct Extsym *entry;
168: chainp args;
169: {
170: register Namep q;
171: register struct Entrypoint *p, *ep;
172:
173: if(class != CLENTRY)
174: puthead( varstr(XL, procname = entry->extname), class);
175: if(class == CLENTRY)
176: fprintf(diagfile, " entry ");
177: fprintf(diagfile, " %s:\n", nounder(XL, entry->extname));
178: q = mkname(VL, nounder(XL,entry->extname) );
179:
180: if( (type = lengtype(type, (int) length)) != TYCHAR)
181: length = 0;
182: if(class == CLPROC)
183: {
184: procclass = CLPROC;
185: proctype = type;
186: procleng = length;
187:
188: retlabel = newlabel();
189: if(type == TYSUBR)
190: ret0label = newlabel();
191: }
192:
193: p = ALLOC(Entrypoint);
194:
195: if(entries) /* put new block at end of entries list */
196: {
197: for(ep = entries; ep->entnextp; ep = ep->entnextp)
198: ;
199: ep->entnextp = p;
200: }
201: else
202: entries = p;
203:
204: p->entryname = entry;
205: p->arglist = args;
206: p->entrylabel = newlabel();
207: p->enamep = q;
208:
209: if(class == CLENTRY)
210: {
211: class = CLPROC;
212: if(proctype == TYSUBR)
213: type = TYSUBR;
214: }
215:
216: q->vclass = class;
217: q->vprocclass = PTHISPROC;
218: settype(q, type, (int) length);
219: /* hold all initial entry points till end of declarations */
220: if(parstate >= INDATA) {
221: doentry(p);
222: }
223: #ifdef SDB
224: if(sdbflag)
225: { /* may need to preserve CLENTRY here */
226: entrystab(p,class);
227: }
228: #endif
229: }
230:
231: /* generate epilogs */
232:
233: LOCAL epicode()
234: {
235: register int i;
236:
237: if(procclass==CLPROC)
238: {
239: if(proctype==TYSUBR)
240: {
241: putlabel(ret0label);
242: if(substars)
243: putforce(TYINT, ICON(0) );
244: putlabel(retlabel);
245: goret(TYSUBR);
246: }
247: else {
248: putlabel(retlabel);
249: if(multitype)
250: {
251: typeaddr = autovar(1, TYADDR, PNULL);
252: putbranch( cpexpr(typeaddr) );
253: for(i = 0; i < NTYPES ; ++i)
254: if(rtvlabel[i] != 0)
255: {
256: putlabel(rtvlabel[i]);
257: retval(i);
258: }
259: }
260: else
261: retval(proctype);
262: }
263: }
264:
265: else if(procclass != CLBLOCK)
266: {
267: putlabel(retlabel);
268: goret(TYSUBR);
269: }
270: }
271:
272:
273: /* generate code to return value of type t */
274:
275: LOCAL retval(t)
276: register int t;
277: {
278: register Addrp p;
279:
280: switch(t)
281: {
282: case TYCHAR:
283: case TYCOMPLEX:
284: case TYDCOMPLEX:
285: break;
286:
287: case TYLOGICAL:
288: t = tylogical;
289: case TYADDR:
290: case TYSHORT:
291: case TYLONG:
292: p = (Addrp) cpexpr(retslot);
293: p->vtype = t;
294: putforce(t, p);
295: break;
296:
297: case TYREAL:
298: case TYDREAL:
299: p = (Addrp) cpexpr(retslot);
300: p->vtype = t;
301: putforce(t, p);
302: break;
303:
304: default:
305: badtype("retval", t);
306: }
307: goret(t);
308: }
309:
310:
311: /* Allocate extra argument array if needed. Generate prologs. */
312:
313: LOCAL procode()
314: {
315: register struct Entrypoint *p;
316: Addrp argvec;
317:
318: #if TARGET==GCOS
319: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
320: #else
321: if(lastargslot>0 && nentry>1)
322: #if TARGET == VAX
323: argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL);
324: #else
325: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
326: #endif
327: else
328: argvec = NULL;
329: #endif
330:
331:
332: #if TARGET == PDP11
333: /* for the optimizer */
334: if(fudgelabel)
335: putlabel(fudgelabel);
336: #endif
337:
338: for(p = entries ; p ; p = p->entnextp)
339: prolog(p, argvec);
340:
341: #if FAMILY == PCC
342: putrbrack(procno);
343: #endif
344:
345: prendproc();
346: }
347:
348: /*
349: manipulate argument lists (allocate argument slot positions)
350: * keep track of return types and labels
351: */
352:
353: LOCAL doentry(ep)
354: struct Entrypoint *ep;
355: {
356: register int type;
357: register Namep np;
358: chainp p;
359: register Namep q;
360: Addrp mkarg();
361:
362: ++nentry;
363: if(procclass == CLMAIN)
364: {
365: if (optimflag)
366: optbuff (SKLABEL, 0, ep->entrylabel, 0);
367: else
368: putlabel(ep->entrylabel);
369: return;
370: }
371: else if(procclass == CLBLOCK)
372: return;
373:
374: impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) );
375: type = np->vtype;
376: if(proctype == TYUNKNOWN)
377: if( (proctype = type) == TYCHAR)
378: procleng = (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1));
379:
380: if(proctype == TYCHAR)
381: {
382: if(type != TYCHAR)
383: err("noncharacter entry of character function");
384: else if( (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)) != procleng)
385: err("mismatched character entry lengths");
386: }
387: else if(type == TYCHAR)
388: err("character entry of noncharacter function");
389: else if(type != proctype)
390: multitype = YES;
391: if(rtvlabel[type] == 0)
392: rtvlabel[type] = newlabel();
393: ep->typelabel = rtvlabel[type];
394:
395: if(type == TYCHAR)
396: {
397: if(chslot < 0)
398: {
399: chslot = nextarg(TYADDR);
400: chlgslot = nextarg(TYLENG);
401: }
402: np->vstg = STGARG;
403: np->vardesc.varno = chslot;
404: if(procleng < 0)
405: np->vleng = (expptr) mkarg(TYLENG, chlgslot);
406: }
407: else if( ISCOMPLEX(type) )
408: {
409: np->vstg = STGARG;
410: if(cxslot < 0)
411: cxslot = nextarg(TYADDR);
412: np->vardesc.varno = cxslot;
413: }
414: else if(type != TYSUBR)
415: {
416: if(nentry == 1)
417: retslot = autovar(1, TYDREAL, PNULL);
418: np->vstg = STGAUTO;
419: np->voffset = retslot->memoffset->constblock.const.ci;
420: }
421:
422: for(p = ep->arglist ; p ; p = p->nextp)
423: if(! (( q = (Namep) (p->datap) )->vdcldone) )
424: q->vardesc.varno = nextarg(TYADDR);
425:
426: for(p = ep->arglist ; p ; p = p->nextp)
427: if(! (( q = (Namep) (p->datap) )->vdcldone) )
428: {
429: impldcl(q);
430: q->vdcldone = YES;
431: if(q->vtype == TYCHAR)
432: {
433: if(q->vleng == NULL) /* character*(*) */
434: q->vleng = (expptr)
435: mkarg(TYLENG, nextarg(TYLENG) );
436: else if(nentry == 1)
437: nextarg(TYLENG);
438: }
439: else if(q->vclass==CLPROC && nentry==1)
440: nextarg(TYLENG) ;
441: #ifdef SDB
442: if(sdbflag) {
443: namestab(q);
444: }
445: #endif
446: }
447:
448: if (optimflag)
449: optbuff (SKLABEL, 0, ep->entrylabel, 0);
450: else
451: putlabel(ep->entrylabel);
452: }
453:
454:
455:
456: LOCAL nextarg(type)
457: int type;
458: {
459: int k;
460: k = lastargslot;
461: lastargslot += typesize[type];
462: return(k);
463: }
464:
465: /* generate variable references */
466:
467: LOCAL dobss()
468: {
469: register struct Hashentry *p;
470: register Namep q;
471: register int i;
472: int align;
473: ftnint leng, iarrl;
474: char *memname();
475: int qstg, qclass, qtype;
476:
477: pruse(asmfile, USEBSS);
478: varsizes = NULL;
479:
480: for(p = hashtab ; p<lasthash ; ++p)
481: if(q = p->varp)
482: {
483: qstg = q->vstg;
484: qtype = q->vtype;
485: qclass = q->vclass;
486:
487:
488: if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
489: (qclass==CLVAR && qstg==STGUNKNOWN) )
490: warn1("local variable %s never used", varstr(VL,q->varname) );
491: else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG)
492: mkext(varunder(VL, q->varname)) ->extstg = STGEXT;
493:
494: if (qclass == CLVAR && qstg == STGBSS)
495: {
496: if (SMALLVAR(q->varsize))
497: {
498: enlist(q->varsize, q, NULL);
499: q->inlcomm = NO;
500: }
501: else
502: {
503: if (q->init == NO)
504: {
505: preven(ALIDOUBLE);
506: prlocvar(memname(qstg, q->vardesc.varno), q->varsize);
507: q->inlcomm = YES;
508: }
509: else
510: prlocdata(memname(qstg, q->vardesc.varno), q->varsize,
511: q->vtype, q->initoffset, &(q->inlcomm));
512: }
513: }
514: else if(qclass==CLVAR && qstg!=STGARG)
515: {
516: if(q->vdim && !ISICON(q->vdim->nelt) )
517: dclerr("adjustable dimension on non-argument", q);
518: if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng)))
519: dclerr("adjustable leng on nonargument", q);
520: }
521: }
522:
523: for (i = 0 ; i < nequiv ; ++i)
524: if ( (leng = eqvclass[i].eqvleng) != 0 )
525: {
526: if (SMALLVAR(leng))
527: enlist(leng, NULL, eqvclass + i);
528: else if (eqvclass[i].init == NO)
529: {
530: preven(ALIDOUBLE);
531: prlocvar(memname(STGEQUIV, i), leng);
532: eqvclass[i].inlcomm = YES;
533: }
534: else
535: prlocdata(memname(STGEQUIV, i), leng, TYDREAL,
536: eqvclass[i].initoffset, &(eqvclass[i].inlcomm));
537: }
538:
539: outlocvars();
540: #ifdef SDB
541: if(sdbflag) {
542: for(p = hashtab ; p<lasthash ; ++p) if(q = p->varp) {
543: qstg = q->vstg;
544: qclass = q->vclass;
545: if( ONEOF(qclass, M(CLVAR))) {
546: if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) ) namestab(q);
547: }
548: }
549: }
550: #endif
551:
552: close(vdatafile);
553: close(vchkfile);
554: unlink(vdatafname);
555: unlink(vchkfname);
556: vdatahwm = 0;
557: }
558:
559:
560:
561: donmlist()
562: {
563: register struct Hashentry *p;
564: register Namep q;
565:
566: pruse(asmfile, USEINIT);
567:
568: for(p=hashtab; p<lasthash; ++p)
569: if( (q = p->varp) && q->vclass==CLNAMELIST)
570: namelist(q);
571: }
572:
573:
574: doext()
575: {
576: struct Extsym *p;
577:
578: for(p = extsymtab ; p<nextext ; ++p)
579: prext(p);
580: }
581:
582:
583:
584:
585: ftnint iarrlen(q)
586: register Namep q;
587: {
588: ftnint leng;
589:
590: leng = typesize[q->vtype];
591: if(leng <= 0)
592: return(-1);
593: if(q->vdim)
594: if( ISICON(q->vdim->nelt) )
595: leng *= q->vdim->nelt->constblock.const.ci;
596: else return(-1);
597: if(q->vleng)
598: if( ISICON(q->vleng) )
599: leng *= q->vleng->constblock.const.ci;
600: else return(-1);
601: return(leng);
602: }
603:
604: /* This routine creates a static block representing the namelist.
605: An equivalent declaration of the structure produced is:
606: struct namelist
607: {
608: char namelistname[16];
609: struct namelistentry
610: {
611: char varname[16];
612: char *varaddr;
613: int type; # negative means -type= number of chars
614: struct dimensions *dimp; # null means scalar
615: } names[];
616: };
617:
618: struct dimensions
619: {
620: int numberofdimensions;
621: int numberofelements
622: int baseoffset;
623: int span[numberofdimensions];
624: };
625: where the namelistentry list terminates with a null varname
626: If dimp is not null, then the corner element of the array is at
627: varaddr. However, the element with subscripts (i1,...,in) is at
628: varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...)
629: */
630:
631: namelist(np)
632: Namep np;
633: {
634: register chainp q;
635: register Namep v;
636: register struct Dimblock *dp;
637: char *memname();
638: int type, dimno, dimoffset;
639: flag bad;
640:
641:
642: preven(ALILONG);
643: fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno));
644: putstr(asmfile, varstr(VL, np->varname), 16);
645: dimno = ++lastvarno;
646: dimoffset = 0;
647: bad = NO;
648:
649: for(q = np->varxptr.namelist ; q ; q = q->nextp)
650: {
651: vardcl( v = (Namep) (q->datap) );
652: type = v->vtype;
653: if( ONEOF(v->vstg, MSKSTATIC) )
654: {
655: preven(ALILONG);
656: putstr(asmfile, varstr(VL,v->varname), 16);
657: praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset);
658: prconi(asmfile, TYINT,
659: type==TYCHAR ?
660: -(v->vleng->constblock.const.ci) : (ftnint) type);
661: if(v->vdim)
662: {
663: praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset);
664: dimoffset += 3 + v->vdim->ndim;
665: }
666: else
667: praddr(asmfile, STGNULL,0,(ftnint) 0);
668: }
669: else
670: {
671: dclerr("may not appear in namelist", v);
672: bad = YES;
673: }
674: }
675:
676: if(bad)
677: return;
678:
679: putstr(asmfile, "", 16);
680:
681: if(dimoffset > 0)
682: {
683: fprintf(asmfile, LABELFMT, memname(STGINIT,dimno));
684: for(q = np->varxptr.namelist ; q ; q = q->nextp)
685: if(dp = q->datap->nameblock.vdim)
686: {
687: int i;
688: prconi(asmfile, TYINT, (ftnint) (dp->ndim) );
689: prconi(asmfile, TYINT,
690: (ftnint) (dp->nelt->constblock.const.ci) );
691: prconi(asmfile, TYINT,
692: (ftnint) (dp->baseoffset->constblock.const.ci));
693: for(i=0; i<dp->ndim ; ++i)
694: prconi(asmfile, TYINT,
695: dp->dims[i].dimsize->constblock.const.ci);
696: }
697: }
698:
699: }
700:
701: LOCAL docommon()
702: {
703: register struct Extsym *p;
704: register chainp q;
705: struct Dimblock *t;
706: expptr neltp;
707: register Namep v;
708: ftnint size;
709: int type;
710:
711: for(p = extsymtab ; p<nextext ; ++p)
712: if(p->extstg==STGCOMMON)
713: {
714: #ifdef SDB
715: if(sdbflag)
716: prstab(varstr(XL,p->extname), N_BCOMM, 0, 0);
717: #endif
718: for(q = p->extp ; q ; q = q->nextp)
719: {
720: v = (Namep) (q->datap);
721: if(v->vdcldone == NO)
722: vardcl(v);
723: type = v->vtype;
724: if(p->extleng % typealign[type] != 0)
725: {
726: dclerr("common alignment", v);
727: p->extleng = roundup(p->extleng, typealign[type]);
728: }
729: v->voffset = p->extleng;
730: v->vardesc.varno = p - extsymtab;
731: if(type == TYCHAR)
732: size = v->vleng->constblock.const.ci;
733: else size = typesize[type];
734: if(t = v->vdim)
735: if( (neltp = t->nelt) && ISCONST(neltp) )
736: size *= neltp->constblock.const.ci;
737: else
738: dclerr("adjustable array in common", v);
739: p->extleng += size;
740: #ifdef SDB
741: if(sdbflag)
742: {
743: namestab(v);
744: }
745: #endif
746: }
747:
748: frchain( &(p->extp) );
749: #ifdef SDB
750: if(sdbflag)
751: prstab(varstr(XL,p->extname), N_ECOMM, 0, 0);
752: #endif
753: }
754: }
755:
756:
757:
758:
759:
760: LOCAL docomleng()
761: {
762: register struct Extsym *p;
763:
764: for(p = extsymtab ; p < nextext ; ++p)
765: if(p->extstg == STGCOMMON)
766: {
767: if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
768: && !eqn(XL,"_BLNK__ ",p->extname) )
769: warn1("incompatible lengths for common block %s",
770: nounder(XL, p->extname) );
771: if(p->maxleng < p->extleng)
772: p->maxleng = p->extleng;
773: p->extleng = 0;
774: }
775: }
776:
777:
778:
779:
780: /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
781:
782: /* frees a temporary block */
783:
784: frtemp(p)
785: Tempp p;
786: {
787: Addrp t;
788:
789: if (optimflag)
790: {
791: if (p->tag != TTEMP)
792: badtag ("frtemp",p->tag);
793: t = p->memalloc;
794: }
795: else
796: t = (Addrp) p;
797:
798: /* restore clobbered character string lengths */
799: if(t->vtype==TYCHAR && t->varleng!=0)
800: {
801: frexpr(t->vleng);
802: t->vleng = ICON(t->varleng);
803: }
804:
805: /* put block on chain of temps to be reclaimed */
806: holdtemps = mkchain(t, holdtemps);
807: }
808:
809:
810:
811: /* allocate an automatic variable slot */
812:
813: Addrp autovar(nelt, t, lengp)
814: register int nelt, t;
815: expptr lengp;
816: {
817: ftnint leng;
818: register Addrp q;
819:
820: if(t == TYCHAR)
821: if( ISICON(lengp) )
822: leng = lengp->constblock.const.ci;
823: else {
824: fatal("automatic variable of nonconstant length");
825: }
826: else
827: leng = typesize[t];
828: autoleng = roundup( autoleng, typealign[t]);
829:
830: q = ALLOC(Addrblock);
831: q->tag = TADDR;
832: q->vtype = t;
833: if(t == TYCHAR)
834: {
835: q->vleng = ICON(leng);
836: q->varleng = leng;
837: }
838: q->vstg = STGAUTO;
839: q->memno = newlabel();
840: q->ntempelt = nelt;
841: #if TARGET==PDP11 || TARGET==VAX
842: /* stack grows downward */
843: autoleng += nelt*leng;
844: q->memoffset = ICON( - autoleng );
845: #else
846: q->memoffset = ICON( autoleng );
847: autoleng += nelt*leng;
848: #endif
849:
850: return(q);
851: }
852:
853:
854:
855: /*
856: * create a temporary block (TTEMP) when optimizing,
857: * an ordinary TADDR block when not optimizing
858: */
859:
860: Tempp mktmpn(nelt, type, lengp)
861: int nelt;
862: register int type;
863: expptr lengp;
864: {
865: ftnint leng;
866: chainp p, oldp;
867: register Tempp q;
868: Addrp altemp;
869:
870: if (! optimflag)
871: return ( (Tempp) mkaltmpn(nelt,type,lengp) );
872: if(type==TYUNKNOWN || type==TYERROR)
873: badtype("mktmpn", type);
874:
875: if(type==TYCHAR)
876: if( ISICON(lengp) )
877: leng = lengp->constblock.const.ci;
878: else {
879: err("adjustable length");
880: return( (Tempp) errnode() );
881: }
882:
883: if(type == TYCHAR)
884: if( ISICON(lengp) )
885: leng = lengp->constblock.const.ci;
886: else
887: fatal("temporary variable of nonconstant length");
888: else
889: leng = typesize[type];
890:
891: q = ALLOC(Tempblock);
892: q->tag = TTEMP;
893: q->vtype = type;
894: if(type == TYCHAR)
895: {
896: q->vleng = ICON(leng);
897: q->varleng = leng;
898: }
899:
900: altemp = ALLOC(Addrblock);
901: altemp->tag = TADDR;
902: altemp->vstg = STGUNKNOWN;
903: q->memalloc = altemp;
904:
905: q->ntempelt = nelt;
906: q->istemp = YES;
907: return(q);
908: }
909:
910:
911:
912: Addrp mktemp(type, lengp)
913: int type;
914: expptr lengp;
915: {
916: return( (Addrp) mktmpn(1,type,lengp) );
917: }
918:
919:
920:
921: /* allocate a temporary location for the given temporary block;
922: if already allocated, return its location */
923:
924: Addrp altmpn(tp)
925: Tempp tp;
926:
927: {
928: Addrp t, q;
929:
930: if (tp->tag != TTEMP)
931: badtag ("altmpn",tp->tag);
932:
933: t = tp->memalloc;
934: if (t->vstg != STGUNKNOWN)
935: return (t);
936:
937: q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng);
938: cpn (sizeof(struct Addrblock), (char*)q, (char*)t);
939: free ( (charptr) q);
940: return(t);
941: }
942:
943:
944:
945: /* create and allocate space immediately for a temporary */
946:
947: Addrp mkaltemp(type,lengp)
948: int type;
949: expptr lengp;
950: {
951: return (mkaltmpn(1,type,lengp));
952: }
953:
954:
955:
956: Addrp mkaltmpn(nelt,type,lengp)
957: int nelt;
958: register int type;
959: expptr lengp;
960: {
961: ftnint leng;
962: chainp p, oldp;
963: register Addrp q;
964:
965: if(type==TYUNKNOWN || type==TYERROR)
966: badtype("mkaltmpn", type);
967:
968: if(type==TYCHAR)
969: if( ISICON(lengp) )
970: leng = lengp->constblock.const.ci;
971: else {
972: err("adjustable length");
973: return( (Addrp) errnode() );
974: }
975:
976: /*
977: * if a temporary of appropriate shape is on the templist,
978: * remove it from the list and return it
979: */
980:
981: for(oldp=CHNULL, p=templist ; p ; oldp=p, p=p->nextp)
982: {
983: q = (Addrp) (p->datap);
984: if(q->vtype==type && q->ntempelt==nelt &&
985: (type!=TYCHAR || q->vleng->constblock.const.ci==leng) )
986: {
987: if(oldp)
988: oldp->nextp = p->nextp;
989: else
990: templist = p->nextp;
991: free( (charptr) p);
992:
993: if (debugflag[14])
994: fprintf(diagfile,"mkaltmpn reusing offset %d\n",
995: q->memoffset->constblock.const.ci);
996: return(q);
997: }
998: }
999: q = autovar(nelt, type, lengp);
1000: q->istemp = YES;
1001:
1002: if (debugflag[14])
1003: fprintf(diagfile,"mkaltmpn new offset %d\n",
1004: q->memoffset->constblock.const.ci);
1005: return(q);
1006: }
1007:
1008: /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
1009:
1010: struct Extsym *comblock(len, s)
1011: register int len;
1012: register char *s;
1013: {
1014: struct Extsym *p;
1015:
1016: if(len == 0)
1017: {
1018: s = BLANKCOMMON;
1019: len = strlen(s);
1020: }
1021: p = mkext( varunder(len, s) );
1022: if(p->extstg == STGUNKNOWN)
1023: p->extstg = STGCOMMON;
1024: else if(p->extstg != STGCOMMON)
1025: {
1026: errstr("%s cannot be a common block name", s);
1027: return(0);
1028: }
1029:
1030: return( p );
1031: }
1032:
1033:
1034: incomm(c, v)
1035: struct Extsym *c;
1036: Namep v;
1037: {
1038: if(v->vstg != STGUNKNOWN)
1039: dclerr("incompatible common declaration", v);
1040: else
1041: {
1042: v->vstg = STGCOMMON;
1043: c->extp = hookup(c->extp, mkchain(v,CHNULL) );
1044: }
1045: }
1046:
1047:
1048:
1049:
1050: settype(v, type, length)
1051: register Namep v;
1052: register int type;
1053: register int length;
1054: {
1055: if(type == TYUNKNOWN)
1056: return;
1057:
1058: if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
1059: {
1060: v->vtype = TYSUBR;
1061: frexpr(v->vleng);
1062: }
1063: else if(type < 0) /* storage class set */
1064: {
1065: if(v->vstg == STGUNKNOWN)
1066: v->vstg = - type;
1067: else if(v->vstg != -type)
1068: dclerr("incompatible storage declarations", v);
1069: }
1070: else if(v->vtype == TYUNKNOWN)
1071: {
1072: if( (v->vtype = lengtype(type, length))==TYCHAR && length>=0)
1073: v->vleng = ICON(length);
1074: }
1075: else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.const.ci!=length) )
1076: dclerr("incompatible type declarations", v);
1077: }
1078:
1079:
1080:
1081:
1082:
1083: lengtype(type, length)
1084: register int type;
1085: register int length;
1086: {
1087: switch(type)
1088: {
1089: case TYREAL:
1090: if(length == 8)
1091: return(TYDREAL);
1092: if(length == 4)
1093: goto ret;
1094: break;
1095:
1096: case TYCOMPLEX:
1097: if(length == 16)
1098: return(TYDCOMPLEX);
1099: if(length == 8)
1100: goto ret;
1101: break;
1102:
1103: case TYSHORT:
1104: case TYDREAL:
1105: case TYDCOMPLEX:
1106: case TYCHAR:
1107: case TYUNKNOWN:
1108: case TYSUBR:
1109: case TYERROR:
1110: goto ret;
1111:
1112: case TYLOGICAL:
1113: if(length == typesize[TYLOGICAL])
1114: goto ret;
1115: break;
1116:
1117: case TYLONG:
1118: if(length == 0)
1119: return(tyint);
1120: if(length == 2)
1121: return(TYSHORT);
1122: if(length == 4)
1123: goto ret;
1124: break;
1125: default:
1126: badtype("lengtype", type);
1127: }
1128:
1129: if(length != 0)
1130: err("incompatible type-length combination");
1131:
1132: ret:
1133: return(type);
1134: }
1135:
1136:
1137:
1138:
1139:
1140: setintr(v)
1141: register Namep v;
1142: {
1143: register int k;
1144:
1145: if(v->vstg == STGUNKNOWN)
1146: v->vstg = STGINTR;
1147: else if(v->vstg!=STGINTR)
1148: dclerr("incompatible use of intrinsic function", v);
1149: if(v->vclass==CLUNKNOWN)
1150: v->vclass = CLPROC;
1151: if(v->vprocclass == PUNKNOWN)
1152: v->vprocclass = PINTRINSIC;
1153: else if(v->vprocclass != PINTRINSIC)
1154: dclerr("invalid intrinsic declaration", v);
1155: if(k = intrfunct(v->varname))
1156: v->vardesc.varno = k;
1157: else
1158: dclerr("unknown intrinsic function", v);
1159: }
1160:
1161:
1162:
1163: setext(v)
1164: register Namep v;
1165: {
1166: if(v->vclass == CLUNKNOWN)
1167: v->vclass = CLPROC;
1168: else if(v->vclass != CLPROC)
1169: dclerr("invalid external declaration", v);
1170:
1171: if(v->vprocclass == PUNKNOWN)
1172: v->vprocclass = PEXTERNAL;
1173: else if(v->vprocclass != PEXTERNAL)
1174: dclerr("invalid external declaration", v);
1175: }
1176:
1177:
1178:
1179:
1180: /* create dimensions block for array variable */
1181:
1182: setbound(v, nd, dims)
1183: register Namep v;
1184: int nd;
1185: struct { expptr lb, ub; } dims[ ];
1186: {
1187: register expptr q, t;
1188: register struct Dimblock *p;
1189: int i;
1190:
1191: if(v->vclass == CLUNKNOWN)
1192: v->vclass = CLVAR;
1193: else if(v->vclass != CLVAR)
1194: {
1195: dclerr("only variables may be arrays", v);
1196: return;
1197: }
1198:
1199: v->vdim = p = (struct Dimblock *)
1200: ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) );
1201: p->ndim = nd;
1202: p->nelt = ICON(1);
1203:
1204: for(i=0 ; i<nd ; ++i)
1205: {
1206: #ifdef SDB
1207: if(sdbflag) {
1208: /* Save the bounds trees built up by the grammar routines for use in stabs */
1209:
1210: if(dims[i].lb == NULL) p->dims[i].lb=ICON(1);
1211: else p->dims[i].lb= (expptr) cpexpr(dims[i].lb);
1212: if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL;
1213: else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL);
1214:
1215: if(dims[i].ub == NULL) p->dims[i].ub=ICON(1);
1216: else p->dims[i].ub = (expptr) cpexpr(dims[i].ub);
1217: if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL;
1218: else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL);
1219: }
1220: #endif
1221: if( (q = dims[i].ub) == NULL)
1222: {
1223: if(i == nd-1)
1224: {
1225: frexpr(p->nelt);
1226: p->nelt = NULL;
1227: }
1228: else
1229: err("only last bound may be asterisk");
1230: p->dims[i].dimsize = ICON(1);;
1231: p->dims[i].dimexpr = NULL;
1232: }
1233: else
1234: {
1235: if(dims[i].lb)
1236: {
1237: q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
1238: q = mkexpr(OPPLUS, q, ICON(1) );
1239: }
1240: if( ISCONST(q) )
1241: {
1242: p->dims[i].dimsize = q;
1243: p->dims[i].dimexpr = (expptr) PNULL;
1244: }
1245: else {
1246: p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL);
1247: p->dims[i].dimexpr = q;
1248: }
1249: if(p->nelt)
1250: p->nelt = mkexpr(OPSTAR, p->nelt,
1251: cpexpr(p->dims[i].dimsize) );
1252: }
1253: }
1254:
1255: q = dims[nd-1].lb;
1256: if(q == NULL)
1257: q = ICON(1);
1258:
1259: for(i = nd-2 ; i>=0 ; --i)
1260: {
1261: t = dims[i].lb;
1262: if(t == NULL)
1263: t = ICON(1);
1264: if(p->dims[i].dimsize)
1265: q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
1266: }
1267:
1268: if( ISCONST(q) )
1269: {
1270: p->baseoffset = q;
1271: p->basexpr = NULL;
1272: }
1273: else
1274: {
1275: p->baseoffset = (expptr) autovar(1, tyint, PNULL);
1276: p->basexpr = q;
1277: }
1278: }
1279:
1280:
1281:
1282: LOCAL enlist(size, np, ep)
1283: ftnint size;
1284: Namep np;
1285: struct Equivblock *ep;
1286: {
1287: register sizelist *sp;
1288: register sizelist *t;
1289: register varlist *p;
1290:
1291: sp = varsizes;
1292:
1293: if (sp == NULL)
1294: {
1295: sp = ALLOC(SizeList);
1296: sp->size = size;
1297: varsizes = sp;
1298: }
1299: else
1300: {
1301: while (sp->size != size)
1302: {
1303: if (sp->next != NULL && sp->next->size <= size)
1304: sp = sp->next;
1305: else
1306: {
1307: t = sp;
1308: sp = ALLOC(SizeList);
1309: sp->size = size;
1310: sp->next = t->next;
1311: t->next = sp;
1312: }
1313: }
1314: }
1315:
1316: p = ALLOC(VarList);
1317: p->next = sp->vars;
1318: p->np = np;
1319: p->ep = ep;
1320:
1321: sp->vars = p;
1322:
1323: return;
1324: }
1325:
1326:
1327:
1328: outlocvars()
1329: {
1330:
1331: register varlist *first, *last;
1332: register varlist *vp, *t;
1333: register sizelist *sp, *sp1;
1334: register Namep np;
1335: register struct Equivblock *ep;
1336: register int i;
1337: register int alt;
1338: register int type;
1339: char sname[100];
1340: char setbuff[100];
1341:
1342: sp = varsizes;
1343: if (sp == NULL)
1344: return;
1345:
1346: vp = sp->vars;
1347: if (vp->np != NULL)
1348: {
1349: np = vp->np;
1350: sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel,
1351: np->vardesc.varno);
1352: }
1353: else
1354: {
1355: i = vp->ep - eqvclass;
1356: sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart);
1357: }
1358:
1359: first = last = NULL;
1360: alt = NO;
1361:
1362: while (sp != NULL)
1363: {
1364: vp = sp->vars;
1365: while (vp != NULL)
1366: {
1367: t = vp->next;
1368: if (alt == YES)
1369: {
1370: alt = NO;
1371: vp->next = first;
1372: first = vp;
1373: }
1374: else
1375: {
1376: alt = YES;
1377: if (last != NULL)
1378: last->next = vp;
1379: else
1380: first = vp;
1381: vp->next = NULL;
1382: last = vp;
1383: }
1384: vp = t;
1385: }
1386: sp1 = sp;
1387: sp = sp->next;
1388: free((char *) sp1);
1389: }
1390:
1391: vp = first;
1392: while(vp != NULL)
1393: {
1394: if (vp->np != NULL)
1395: {
1396: np = vp->np;
1397: sprintf(sname, "v.%d", np->vardesc.varno);
1398: if (np->init)
1399: prlocdata(sname, np->varsize, np->vtype, np->initoffset,
1400: &(np->inlcomm));
1401: else
1402: {
1403: pralign(typealign[np->vtype]);
1404: fprintf(initfile, "%s:\n\t.space\t%d\n", sname,
1405: np->varsize);
1406: }
1407: np->inlcomm = NO;
1408: }
1409: else
1410: {
1411: ep = vp->ep;
1412: i = ep - eqvclass;
1413: if (ep->eqvleng >= 8)
1414: type = TYDREAL;
1415: else if (ep->eqvleng >= 4)
1416: type = TYLONG;
1417: else if (ep->eqvleng >= 2)
1418: type = TYSHORT;
1419: else
1420: type = TYCHAR;
1421: sprintf(sname, "q.%d", i + eqvstart);
1422: if (ep->init)
1423: prlocdata(sname, ep->eqvleng, type, ep->initoffset,
1424: &(ep->inlcomm));
1425: else
1426: {
1427: pralign(typealign[type]);
1428: fprintf(initfile, "%s:\n\t.space\t%d\n", sname, ep->eqvleng);
1429: }
1430: ep->inlcomm = NO;
1431: }
1432: t = vp;
1433: vp = vp->next;
1434: free((char *) t);
1435: }
1436: fprintf(initfile, "%s\n", setbuff);
1437: return;
1438: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.