|
|
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.