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: }