1: /* 2: * Copyright (c) 1983 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[] = "@(#)symbols.c 5.2 (Berkeley) 9/5/85"; 9: #endif not lint 10: 11: static char rcsid[] = "$Header: symbols.c,v 1.6 84/12/26 10:42:31 linton Exp $"; 12: 13: /* 14: * Symbol management. 15: */ 16: 17: #include "defs.h" 18: #include "symbols.h" 19: #include "languages.h" 20: #include "printsym.h" 21: #include "tree.h" 22: #include "operators.h" 23: #include "eval.h" 24: #include "mappings.h" 25: #include "events.h" 26: #include "process.h" 27: #include "runtime.h" 28: #include "machine.h" 29: #include "names.h" 30: 31: #ifndef public 32: typedef struct Symbol *Symbol; 33: 34: #include "machine.h" 35: #include "names.h" 36: #include "languages.h" 37: #include "tree.h" 38: 39: /* 40: * Symbol classes 41: */ 42: 43: typedef enum { 44: BADUSE, CONST, TYPE, VAR, ARRAY, DYNARRAY, SUBARRAY, PTRFILE, RECORD, FIELD, 45: PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 46: LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 47: FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF 48: } Symclass; 49: 50: typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; 51: 52: struct Symbol { 53: Name name; 54: Language language; 55: Symclass class : 8; 56: Integer level : 8; 57: Symbol type; 58: Symbol chain; 59: union { 60: Node constval; /* value of constant symbol */ 61: int offset; /* variable address */ 62: long iconval; /* integer constant value */ 63: double fconval; /* floating constant value */ 64: int ndims; /* no. of dimensions for dynamic/sub-arrays */ 65: struct { /* field offset and size (both in bits) */ 66: int offset; 67: int length; 68: } field; 69: struct { /* common offset and chain; used to relocate */ 70: int offset; /* vars in global BSS */ 71: Symbol chain; 72: } common; 73: struct { /* range bounds */ 74: Rangetype lowertype : 16; 75: Rangetype uppertype : 16; 76: long lower; 77: long upper; 78: } rangev; 79: struct { 80: int offset : 16; /* offset for of function value */ 81: Boolean src : 1; /* true if there is source line info */ 82: Boolean inline : 1; /* true if no separate act. rec. */ 83: Boolean intern : 1; /* internal calling sequence */ 84: int unused : 13; 85: Address beginaddr; /* address of function code */ 86: } funcv; 87: struct { /* variant record info */ 88: int size; 89: Symbol vtorec; 90: Symbol vtag; 91: } varnt; 92: String typeref; /* type defined by "<module>:<type>" */ 93: Symbol extref; /* indirect symbol for external reference */ 94: } symvalue; 95: Symbol block; /* symbol containing this symbol */ 96: Symbol next_sym; /* hash chain */ 97: }; 98: 99: /* 100: * Basic types. 101: */ 102: 103: Symbol t_boolean; 104: Symbol t_char; 105: Symbol t_int; 106: Symbol t_real; 107: Symbol t_nil; 108: Symbol t_addr; 109: 110: Symbol program; 111: Symbol curfunc; 112: 113: boolean showaggrs; 114: 115: #define symname(s) ident(s->name) 116: #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 117: #define isblock(s) (Boolean) ( \ 118: s->class == FUNC or s->class == PROC or \ 119: s->class == MODULE or s->class == PROG \ 120: ) 121: #define isroutine(s) (Boolean) ( \ 122: s->class == FUNC or s->class == PROC \ 123: ) 124: 125: #define nosource(f) (not (f)->symvalue.funcv.src) 126: #define isinline(f) ((f)->symvalue.funcv.inline) 127: 128: #define isreg(s) (s->level < 0) 129: 130: #include "tree.h" 131: 132: /* 133: * Some macros to make finding a symbol with certain attributes. 134: */ 135: 136: #define find(s, withname) \ 137: { \ 138: s = lookup(withname); \ 139: while (s != nil and not (s->name == (withname) and 140: 141: #define where /* qualification */ 142: 143: #define endfind(s) )) { \ 144: s = s->next_sym; \ 145: } \ 146: } 147: 148: #endif 149: 150: /* 151: * Symbol table structure currently does not support deletions. 152: */ 153: 154: #define HASHTABLESIZE 2003 155: 156: private Symbol hashtab[HASHTABLESIZE]; 157: 158: #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 159: 160: /* 161: * Allocate a new symbol. 162: */ 163: 164: #define SYMBLOCKSIZE 100 165: 166: typedef struct Sympool { 167: struct Symbol sym[SYMBLOCKSIZE]; 168: struct Sympool *prevpool; 169: } *Sympool; 170: 171: private Sympool sympool = nil; 172: private Integer nleft = 0; 173: 174: public Symbol symbol_alloc() 175: { 176: register Sympool newpool; 177: 178: if (nleft <= 0) { 179: newpool = new(Sympool); 180: bzero(newpool, sizeof(newpool)); 181: newpool->prevpool = sympool; 182: sympool = newpool; 183: nleft = SYMBLOCKSIZE; 184: } 185: --nleft; 186: return &(sympool->sym[nleft]); 187: } 188: 189: public symbol_dump (func) 190: Symbol func; 191: { 192: register Symbol s; 193: register integer i; 194: 195: printf(" symbols in %s \n",symname(func)); 196: for (i = 0; i < HASHTABLESIZE; i++) { 197: for (s = hashtab[i]; s != nil; s = s->next_sym) { 198: if (s->block == func) { 199: psym(s); 200: } 201: } 202: } 203: } 204: 205: /* 206: * Free all the symbols currently allocated. 207: */ 208: 209: public symbol_free() 210: { 211: Sympool s, t; 212: register Integer i; 213: 214: s = sympool; 215: while (s != nil) { 216: t = s->prevpool; 217: dispose(s); 218: s = t; 219: } 220: for (i = 0; i < HASHTABLESIZE; i++) { 221: hashtab[i] = nil; 222: } 223: sympool = nil; 224: nleft = 0; 225: } 226: 227: /* 228: * Create a new symbol with the given attributes. 229: */ 230: 231: public Symbol newSymbol(name, blevel, class, type, chain) 232: Name name; 233: Integer blevel; 234: Symclass class; 235: Symbol type; 236: Symbol chain; 237: { 238: register Symbol s; 239: 240: s = symbol_alloc(); 241: s->name = name; 242: s->language = primlang; 243: s->level = blevel; 244: s->class = class; 245: s->type = type; 246: s->chain = chain; 247: return s; 248: } 249: 250: /* 251: * Insert a symbol into the hash table. 252: */ 253: 254: public Symbol insert(name) 255: Name name; 256: { 257: register Symbol s; 258: register unsigned int h; 259: 260: h = hash(name); 261: s = symbol_alloc(); 262: s->name = name; 263: s->next_sym = hashtab[h]; 264: hashtab[h] = s; 265: return s; 266: } 267: 268: /* 269: * Symbol lookup. 270: */ 271: 272: public Symbol lookup(name) 273: Name name; 274: { 275: register Symbol s; 276: register unsigned int h; 277: 278: h = hash(name); 279: s = hashtab[h]; 280: while (s != nil and s->name != name) { 281: s = s->next_sym; 282: } 283: return s; 284: } 285: 286: /* 287: * Delete a symbol from the symbol table. 288: */ 289: 290: public delete (s) 291: Symbol s; 292: { 293: register Symbol t; 294: register unsigned int h; 295: 296: h = hash(s->name); 297: t = hashtab[h]; 298: if (t == nil) { 299: panic("delete of non-symbol '%s'", symname(s)); 300: } else if (t == s) { 301: hashtab[h] = s->next_sym; 302: } else { 303: while (t->next_sym != s) { 304: t = t->next_sym; 305: if (t == nil) { 306: panic("delete of non-symbol '%s'", symname(s)); 307: } 308: } 309: t->next_sym = s->next_sym; 310: } 311: } 312: 313: /* 314: * Dump out all the variables associated with the given 315: * procedure, function, or program associated with the given stack frame. 316: * 317: * This is quite inefficient. We traverse the entire symbol table 318: * each time we're called. The assumption is that this routine 319: * won't be called frequently enough to merit improved performance. 320: */ 321: 322: public dumpvars(f, frame) 323: Symbol f; 324: Frame frame; 325: { 326: register Integer i; 327: register Symbol s; 328: 329: for (i = 0; i < HASHTABLESIZE; i++) { 330: for (s = hashtab[i]; s != nil; s = s->next_sym) { 331: if (container(s) == f) { 332: if (should_print(s)) { 333: printv(s, frame); 334: putchar('\n'); 335: } else if (s->class == MODULE) { 336: dumpvars(s, frame); 337: } 338: } 339: } 340: } 341: } 342: 343: /* 344: * Create a builtin type. 345: * Builtin types are circular in that btype->type->type = btype. 346: */ 347: 348: private Symbol maketype(name, lower, upper) 349: String name; 350: long lower; 351: long upper; 352: { 353: register Symbol s; 354: Name n; 355: 356: if (name == nil) { 357: n = nil; 358: } else { 359: n = identname(name, true); 360: } 361: s = insert(n); 362: s->language = primlang; 363: s->level = 0; 364: s->class = TYPE; 365: s->type = nil; 366: s->chain = nil; 367: s->type = newSymbol(nil, 0, RANGE, s, nil); 368: s->type->symvalue.rangev.lower = lower; 369: s->type->symvalue.rangev.upper = upper; 370: return s; 371: } 372: 373: /* 374: * Create the builtin symbols. 375: */ 376: 377: public symbols_init () 378: { 379: Symbol s; 380: 381: t_boolean = maketype("$boolean", 0L, 1L); 382: t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); 383: t_char = maketype("$char", 0L, 255L); 384: t_real = maketype("$real", 8L, 0L); 385: t_nil = maketype("$nil", 0L, 0L); 386: t_addr = insert(identname("$address", true)); 387: t_addr->language = primlang; 388: t_addr->level = 0; 389: t_addr->class = TYPE; 390: t_addr->type = newSymbol(nil, 1, PTR, t_int, nil); 391: s = insert(identname("true", true)); 392: s->class = CONST; 393: s->type = t_boolean; 394: s->symvalue.constval = build(O_LCON, 1L); 395: s->symvalue.constval->nodetype = t_boolean; 396: s = insert(identname("false", true)); 397: s->class = CONST; 398: s->type = t_boolean; 399: s->symvalue.constval = build(O_LCON, 0L); 400: s->symvalue.constval->nodetype = t_boolean; 401: } 402: 403: /* 404: * Reduce type to avoid worrying about type names. 405: */ 406: 407: public Symbol rtype(type) 408: Symbol type; 409: { 410: register Symbol t; 411: 412: t = type; 413: if (t != nil) { 414: if (t->class == VAR or t->class == CONST or 415: t->class == FIELD or t->class == REF 416: ) { 417: t = t->type; 418: } 419: if (t->class == TYPEREF) { 420: resolveRef(t); 421: } 422: while (t->class == TYPE or t->class == TAG) { 423: t = t->type; 424: if (t->class == TYPEREF) { 425: resolveRef(t); 426: } 427: } 428: } 429: return t; 430: } 431: 432: /* 433: * Find the end of a module name. Return nil if there is none 434: * in the given string. 435: */ 436: 437: private String findModuleMark (s) 438: String s; 439: { 440: register char *p, *r; 441: register boolean done; 442: 443: p = s; 444: done = false; 445: do { 446: if (*p == ':') { 447: done = true; 448: r = p; 449: } else if (*p == '\0') { 450: done = true; 451: r = nil; 452: } else { 453: ++p; 454: } 455: } while (not done); 456: return r; 457: } 458: 459: /* 460: * Resolve a type reference by modifying to be the appropriate type. 461: * 462: * If the reference has a name, then it refers to an opaque type and 463: * the actual type is directly accessible. Otherwise, we must use 464: * the type reference string, which is of the form "module:{module:}name". 465: */ 466: 467: public resolveRef (t) 468: Symbol t; 469: { 470: register char *p; 471: char *start; 472: Symbol s, m, outer; 473: Name n; 474: 475: if (t->name != nil) { 476: s = t; 477: } else { 478: start = t->symvalue.typeref; 479: outer = program; 480: p = findModuleMark(start); 481: while (p != nil) { 482: *p = '\0'; 483: n = identname(start, true); 484: find(m, n) where m->block == outer endfind(m); 485: if (m == nil) { 486: p = nil; 487: outer = nil; 488: s = nil; 489: } else { 490: outer = m; 491: start = p + 1; 492: p = findModuleMark(start); 493: } 494: } 495: if (outer != nil) { 496: n = identname(start, true); 497: find(s, n) where s->block == outer endfind(s); 498: } 499: } 500: if (s != nil and s->type != nil) { 501: t->name = s->type->name; 502: t->class = s->type->class; 503: t->type = s->type->type; 504: t->chain = s->type->chain; 505: t->symvalue = s->type->symvalue; 506: t->block = s->type->block; 507: } 508: } 509: 510: public integer regnum (s) 511: Symbol s; 512: { 513: integer r; 514: 515: checkref(s); 516: if (s->level < 0) { 517: r = s->symvalue.offset; 518: } else { 519: r = -1; 520: } 521: return r; 522: } 523: 524: public Symbol container(s) 525: Symbol s; 526: { 527: checkref(s); 528: return s->block; 529: } 530: 531: public Node constval(s) 532: Symbol s; 533: { 534: checkref(s); 535: if (s->class != CONST) { 536: error("[internal error: constval(non-CONST)]"); 537: } 538: return s->symvalue.constval; 539: } 540: 541: /* 542: * Return the object address of the given symbol. 543: * 544: * There are the following possibilities: 545: * 546: * globals - just take offset 547: * locals - take offset from locals base 548: * arguments - take offset from argument base 549: * register - offset is register number 550: */ 551: 552: #define isglobal(s) (s->level == 1) 553: #define islocaloff(s) (s->level >= 2 and s->symvalue.offset < 0) 554: #define isparamoff(s) (s->level >= 2 and s->symvalue.offset >= 0) 555: 556: public Address address (s, frame) 557: Symbol s; 558: Frame frame; 559: { 560: register Frame frp; 561: register Address addr; 562: register Symbol cur; 563: 564: checkref(s); 565: if (not isactive(s->block)) { 566: error("\"%s\" is not currently defined", symname(s)); 567: } else if (isglobal(s)) { 568: addr = s->symvalue.offset; 569: } else { 570: frp = frame; 571: if (frp == nil) { 572: cur = s->block; 573: while (cur != nil and cur->class == MODULE) { 574: cur = cur->block; 575: } 576: if (cur == nil) { 577: frp = nil; 578: } else { 579: frp = findframe(cur); 580: if (frp == nil) { 581: error("[internal error: unexpected nil frame for \"%s\"]", 582: symname(s) 583: ); 584: } 585: } 586: } 587: if (islocaloff(s)) { 588: addr = locals_base(frp) + s->symvalue.offset; 589: } else if (isparamoff(s)) { 590: addr = args_base(frp) + s->symvalue.offset; 591: } else if (isreg(s)) { 592: addr = savereg(s->symvalue.offset, frp); 593: } else { 594: panic("address: bad symbol \"%s\"", symname(s)); 595: } 596: } 597: return addr; 598: } 599: 600: /* 601: * Define a symbol used to access register values. 602: */ 603: 604: public defregname (n, r) 605: Name n; 606: integer r; 607: { 608: Symbol s; 609: 610: s = insert(n); 611: s->language = t_addr->language; 612: s->class = VAR; 613: s->level = -3; 614: s->type = t_addr; 615: s->symvalue.offset = r; 616: } 617: 618: /* 619: * Resolve an "abstract" type reference. 620: * 621: * It is possible in C to define a pointer to a type, but never define 622: * the type in a particular source file. Here we try to resolve 623: * the type definition. This is problematic, it is possible to 624: * have multiple, different definitions for the same name type. 625: */ 626: 627: public findtype(s) 628: Symbol s; 629: { 630: register Symbol t, u, prev; 631: 632: u = s; 633: prev = nil; 634: while (u != nil and u->class != BADUSE) { 635: if (u->name != nil) { 636: prev = u; 637: } 638: u = u->type; 639: } 640: if (prev == nil) { 641: error("couldn't find link to type reference"); 642: } 643: t = lookup(prev->name); 644: while (t != nil and 645: not ( 646: t != prev and t->name == prev->name and 647: t->block->class == MODULE and t->class == prev->class and 648: t->type != nil and t->type->type != nil and 649: t->type->type->class != BADUSE 650: ) 651: ) { 652: t = t->next_sym; 653: } 654: if (t == nil) { 655: error("couldn't resolve reference"); 656: } else { 657: prev->type = t->type; 658: } 659: } 660: 661: /* 662: * Find the size in bytes of the given type. 663: * 664: * This is probably the WRONG thing to do. The size should be kept 665: * as an attribute in the symbol information as is done for structures 666: * and fields. I haven't gotten around to cleaning this up yet. 667: */ 668: 669: #define MAXUCHAR 255 670: #define MAXUSHORT 65535L 671: #define MINCHAR -128 672: #define MAXCHAR 127 673: #define MINSHORT -32768 674: #define MAXSHORT 32767 675: 676: public findbounds (u, lower, upper) 677: Symbol u; 678: long *lower, *upper; 679: { 680: Rangetype lbt, ubt; 681: long lb, ub; 682: 683: if (u->class == RANGE) { 684: lbt = u->symvalue.rangev.lowertype; 685: ubt = u->symvalue.rangev.uppertype; 686: lb = u->symvalue.rangev.lower; 687: ub = u->symvalue.rangev.upper; 688: if (lbt == R_ARG or lbt == R_TEMP) { 689: if (not getbound(u, lb, lbt, lower)) { 690: error("dynamic bounds not currently available"); 691: } 692: } else { 693: *lower = lb; 694: } 695: if (ubt == R_ARG or ubt == R_TEMP) { 696: if (not getbound(u, ub, ubt, upper)) { 697: error("dynamic bounds not currently available"); 698: } 699: } else { 700: *upper = ub; 701: } 702: } else if (u->class == SCAL) { 703: *lower = 0; 704: *upper = u->symvalue.iconval - 1; 705: } else { 706: error("[internal error: unexpected array bound type]"); 707: } 708: } 709: 710: public integer size(sym) 711: Symbol sym; 712: { 713: register Symbol s, t, u; 714: register integer nel, elsize; 715: long lower, upper; 716: integer r, off, len; 717: 718: t = sym; 719: checkref(t); 720: if (t->class == TYPEREF) { 721: resolveRef(t); 722: } 723: switch (t->class) { 724: case RANGE: 725: lower = t->symvalue.rangev.lower; 726: upper = t->symvalue.rangev.upper; 727: if (upper == 0 and lower > 0) { 728: /* real */ 729: r = lower; 730: } else if (lower > upper) { 731: /* unsigned long */ 732: r = sizeof(long); 733: } else if ( 734: (lower >= MINCHAR and upper <= MAXCHAR) or 735: (lower >= 0 and upper <= MAXUCHAR) 736: ) { 737: r = sizeof(char); 738: } else if ( 739: (lower >= MINSHORT and upper <= MAXSHORT) or 740: (lower >= 0 and upper <= MAXUSHORT) 741: ) { 742: r = sizeof(short); 743: } else { 744: r = sizeof(long); 745: } 746: break; 747: 748: case ARRAY: 749: elsize = size(t->type); 750: nel = 1; 751: for (t = t->chain; t != nil; t = t->chain) { 752: u = rtype(t); 753: findbounds(u, &lower, &upper); 754: nel *= (upper-lower+1); 755: } 756: r = nel*elsize; 757: break; 758: 759: case DYNARRAY: 760: r = (t->symvalue.ndims + 1) * sizeof(Word); 761: break; 762: 763: case SUBARRAY: 764: r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 765: break; 766: 767: case REF: 768: case VAR: 769: r = size(t->type); 770: /* 771: * 772: if (r < sizeof(Word) and isparam(t)) { 773: r = sizeof(Word); 774: } 775: */ 776: break; 777: 778: case FVAR: 779: case CONST: 780: case TAG: 781: r = size(t->type); 782: break; 783: 784: case TYPE: 785: if (t->type->class == PTR and t->type->type->class == BADUSE) { 786: findtype(t); 787: } 788: r = size(t->type); 789: break; 790: 791: case FIELD: 792: off = t->symvalue.field.offset; 793: len = t->symvalue.field.length; 794: r = (off + len + 7) div 8 - (off div 8); 795: break; 796: 797: case RECORD: 798: case VARNT: 799: r = t->symvalue.offset; 800: if (r == 0 and t->chain != nil) { 801: panic("missing size information for record"); 802: } 803: break; 804: 805: case PTR: 806: case TYPEREF: 807: case FILET: 808: r = sizeof(Word); 809: break; 810: 811: case SCAL: 812: r = sizeof(Word); 813: /* 814: * 815: if (t->symvalue.iconval > 255) { 816: r = sizeof(short); 817: } else { 818: r = sizeof(char); 819: } 820: * 821: */ 822: break; 823: 824: case FPROC: 825: case FFUNC: 826: r = sizeof(Word); 827: break; 828: 829: case PROC: 830: case FUNC: 831: case MODULE: 832: case PROG: 833: r = sizeof(Symbol); 834: break; 835: 836: case SET: 837: u = rtype(t->type); 838: switch (u->class) { 839: case RANGE: 840: r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1; 841: break; 842: 843: case SCAL: 844: r = u->symvalue.iconval; 845: break; 846: 847: default: 848: error("expected range for set base type"); 849: break; 850: } 851: r = (r + BITSPERBYTE - 1) div BITSPERBYTE; 852: break; 853: 854: /* 855: * These can happen in C (unfortunately) for unresolved type references 856: * Assume they are pointers. 857: */ 858: case BADUSE: 859: r = sizeof(Address); 860: break; 861: 862: default: 863: if (ord(t->class) > ord(TYPEREF)) { 864: panic("size: bad class (%d)", ord(t->class)); 865: } else { 866: fprintf(stderr, "can't compute size of a %s\n", classname(t)); 867: } 868: r = 0; 869: break; 870: } 871: return r; 872: } 873: 874: /* 875: * Return the size associated with a symbol that takes into account 876: * reference parameters. This might be better as the normal size function, but 877: * too many places already depend on it working the way it does. 878: */ 879: 880: public integer psize (s) 881: Symbol s; 882: { 883: integer r; 884: Symbol t; 885: 886: if (s->class == REF) { 887: t = rtype(s->type); 888: if (t->class == DYNARRAY) { 889: r = (t->symvalue.ndims + 1) * sizeof(Word); 890: } else if (t->class == SUBARRAY) { 891: r = (2 * t->symvalue.ndims + 1) * sizeof(Word); 892: } else { 893: r = sizeof(Word); 894: } 895: } else { 896: r = size(s); 897: } 898: return r; 899: } 900: 901: /* 902: * Test if a symbol is a parameter. This is true if there 903: * is a cycle from s->block to s via chain pointers. 904: */ 905: 906: public Boolean isparam(s) 907: Symbol s; 908: { 909: register Symbol t; 910: 911: t = s->block; 912: while (t != nil and t != s) { 913: t = t->chain; 914: } 915: return (Boolean) (t != nil); 916: } 917: 918: /* 919: * Test if a type is an open array parameter type. 920: */ 921: 922: public boolean isopenarray (type) 923: Symbol type; 924: { 925: Symbol t; 926: 927: t = rtype(type); 928: return (boolean) (t->class == DYNARRAY); 929: } 930: 931: /* 932: * Test if a symbol is a var parameter, i.e. has class REF. 933: */ 934: 935: public Boolean isvarparam(s) 936: Symbol s; 937: { 938: return (Boolean) (s->class == REF); 939: } 940: 941: /* 942: * Test if a symbol is a variable (actually any addressible quantity 943: * with do). 944: */ 945: 946: public Boolean isvariable(s) 947: Symbol s; 948: { 949: return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 950: } 951: 952: /* 953: * Test if a symbol is a constant. 954: */ 955: 956: public Boolean isconst(s) 957: Symbol s; 958: { 959: return (Boolean) (s->class == CONST); 960: } 961: 962: /* 963: * Test if a symbol is a module. 964: */ 965: 966: public Boolean ismodule(s) 967: register Symbol s; 968: { 969: return (Boolean) (s->class == MODULE); 970: } 971: 972: /* 973: * Mark a procedure or function as internal, meaning that it is called 974: * with a different calling sequence. 975: */ 976: 977: public markInternal (s) 978: Symbol s; 979: { 980: s->symvalue.funcv.intern = true; 981: } 982: 983: public boolean isinternal (s) 984: Symbol s; 985: { 986: return s->symvalue.funcv.intern; 987: } 988: 989: /* 990: * Decide if a field begins or ends on a bit rather than byte boundary. 991: */ 992: 993: public Boolean isbitfield(s) 994: register Symbol s; 995: { 996: boolean b; 997: register integer off, len; 998: register Symbol t; 999: 1000: off = s->symvalue.field.offset; 1001: len = s->symvalue.field.length; 1002: if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) { 1003: b = true; 1004: } else { 1005: t = rtype(s->type); 1006: b = (Boolean) ( 1007: (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or 1008: len != (size(t)*BITSPERBYTE) 1009: ); 1010: } 1011: return b; 1012: } 1013: 1014: private boolean primlang_typematch (t1, t2) 1015: Symbol t1, t2; 1016: { 1017: return (boolean) ( 1018: (t1 == t2) or 1019: ( 1020: t1->class == RANGE and t2->class == RANGE and 1021: t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and 1022: t1->symvalue.rangev.upper == t2->symvalue.rangev.upper 1023: ) or ( 1024: t1->class == PTR and t2->class == RANGE and 1025: t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower 1026: ) or ( 1027: t2->class == PTR and t1->class == RANGE and 1028: t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower 1029: ) 1030: ); 1031: } 1032: 1033: /* 1034: * Test if two types match. 1035: * Equivalent names implies a match in any language. 1036: * 1037: * Special symbols must be handled with care. 1038: */ 1039: 1040: public Boolean compatible(t1, t2) 1041: register Symbol t1, t2; 1042: { 1043: Boolean b; 1044: Symbol rt1, rt2; 1045: 1046: if (t1 == t2) { 1047: b = true; 1048: } else if (t1 == nil or t2 == nil) { 1049: b = false; 1050: } else if (t1 == procsym) { 1051: b = isblock(t2); 1052: } else if (t2 == procsym) { 1053: b = isblock(t1); 1054: } else if (t1->language == primlang) { 1055: if (t2->language == primlang) { 1056: b = primlang_typematch(rtype(t1), rtype(t2)); 1057: } else { 1058: b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 1059: } 1060: } else if (t2->language == primlang) { 1061: b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 1062: } else if (t1->language == nil) { 1063: if (t2->language == nil) { 1064: b = false; 1065: } else { 1066: b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 1067: } 1068: } else { 1069: b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 1070: } 1071: return b; 1072: } 1073: 1074: /* 1075: * Check for a type of the given name. 1076: */ 1077: 1078: public Boolean istypename(type, name) 1079: Symbol type; 1080: String name; 1081: { 1082: register Symbol t; 1083: Boolean b; 1084: 1085: t = type; 1086: if (t == nil) { 1087: b = false; 1088: } else { 1089: b = (Boolean) ( 1090: t->class == TYPE and streq(ident(t->name), name) 1091: ); 1092: } 1093: return b; 1094: } 1095: 1096: /* 1097: * Determine if a (value) parameter should actually be passed by address. 1098: */ 1099: 1100: public boolean passaddr (p, exprtype) 1101: Symbol p, exprtype; 1102: { 1103: boolean b; 1104: Language def; 1105: 1106: if (p == nil) { 1107: def = findlanguage(".c"); 1108: b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype); 1109: } else if (p->language == nil or p->language == primlang) { 1110: b = false; 1111: } else if (isopenarray(p->type)) { 1112: b = true; 1113: } else { 1114: b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype); 1115: } 1116: return b; 1117: } 1118: 1119: /* 1120: * Test if the name of a symbol is uniquely defined or not. 1121: */ 1122: 1123: public Boolean isambiguous(s) 1124: register Symbol s; 1125: { 1126: register Symbol t; 1127: 1128: find(t, s->name) where t != s endfind(t); 1129: return (Boolean) (t != nil); 1130: } 1131: 1132: typedef char *Arglist; 1133: 1134: #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 1135: 1136: private Symbol mkstring(); 1137: 1138: /* 1139: * Determine the type of a parse tree. 1140: * 1141: * Also make some symbol-dependent changes to the tree such as 1142: * removing indirection for constant or register symbols. 1143: */ 1144: 1145: public assigntypes (p) 1146: register Node p; 1147: { 1148: register Node p1; 1149: register Symbol s; 1150: 1151: switch (p->op) { 1152: case O_SYM: 1153: p->nodetype = p->value.sym; 1154: break; 1155: 1156: case O_LCON: 1157: p->nodetype = t_int; 1158: break; 1159: 1160: case O_CCON: 1161: p->nodetype = t_char; 1162: break; 1163: 1164: case O_FCON: 1165: p->nodetype = t_real; 1166: break; 1167: 1168: case O_SCON: 1169: p->nodetype = mkstring(p->value.scon); 1170: break; 1171: 1172: case O_INDIR: 1173: p1 = p->value.arg[0]; 1174: s = rtype(p1->nodetype); 1175: if (s->class != PTR) { 1176: beginerrmsg(); 1177: fprintf(stderr, "\""); 1178: prtree(stderr, p1); 1179: fprintf(stderr, "\" is not a pointer"); 1180: enderrmsg(); 1181: } 1182: p->nodetype = rtype(p1->nodetype)->type; 1183: break; 1184: 1185: case O_DOT: 1186: p->nodetype = p->value.arg[1]->value.sym; 1187: break; 1188: 1189: case O_RVAL: 1190: p1 = p->value.arg[0]; 1191: p->nodetype = p1->nodetype; 1192: if (p1->op == O_SYM) { 1193: if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) { 1194: p->op = p1->op; 1195: p->value.sym = p1->value.sym; 1196: p->nodetype = p1->nodetype; 1197: dispose(p1); 1198: } else if (p1->value.sym->class == CONST) { 1199: p->op = p1->op; 1200: p->value = p1->value; 1201: p->nodetype = p1->nodetype; 1202: dispose(p1); 1203: } else if (isreg(p1->value.sym)) { 1204: p->op = O_SYM; 1205: p->value.sym = p1->value.sym; 1206: dispose(p1); 1207: } 1208: } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 1209: s = p1->value.arg[0]->value.sym; 1210: if (isreg(s)) { 1211: p1->op = O_SYM; 1212: dispose(p1->value.arg[0]); 1213: p1->value.sym = s; 1214: p1->nodetype = s; 1215: } 1216: } 1217: break; 1218: 1219: case O_COMMA: 1220: p->nodetype = p->value.arg[0]->nodetype; 1221: break; 1222: 1223: case O_CALLPROC: 1224: case O_CALL: 1225: p1 = p->value.arg[0]; 1226: p->nodetype = rtype(p1->nodetype)->type; 1227: break; 1228: 1229: case O_TYPERENAME: 1230: p->nodetype = p->value.arg[1]->nodetype; 1231: break; 1232: 1233: case O_ITOF: 1234: p->nodetype = t_real; 1235: break; 1236: 1237: case O_NEG: 1238: s = p->value.arg[0]->nodetype; 1239: if (not compatible(s, t_int)) { 1240: if (not compatible(s, t_real)) { 1241: beginerrmsg(); 1242: fprintf(stderr, "\""); 1243: prtree(stderr, p->value.arg[0]); 1244: fprintf(stderr, "\" is improper type"); 1245: enderrmsg(); 1246: } else { 1247: p->op = O_NEGF; 1248: } 1249: } 1250: p->nodetype = s; 1251: break; 1252: 1253: case O_ADD: 1254: case O_SUB: 1255: case O_MUL: 1256: binaryop(p, nil); 1257: break; 1258: 1259: case O_LT: 1260: case O_LE: 1261: case O_GT: 1262: case O_GE: 1263: case O_EQ: 1264: case O_NE: 1265: binaryop(p, t_boolean); 1266: break; 1267: 1268: case O_DIVF: 1269: convert(&(p->value.arg[0]), t_real, O_ITOF); 1270: convert(&(p->value.arg[1]), t_real, O_ITOF); 1271: p->nodetype = t_real; 1272: break; 1273: 1274: case O_DIV: 1275: case O_MOD: 1276: convert(&(p->value.arg[0]), t_int, O_NOP); 1277: convert(&(p->value.arg[1]), t_int, O_NOP); 1278: p->nodetype = t_int; 1279: break; 1280: 1281: case O_AND: 1282: case O_OR: 1283: chkboolean(p->value.arg[0]); 1284: chkboolean(p->value.arg[1]); 1285: p->nodetype = t_boolean; 1286: break; 1287: 1288: case O_QLINE: 1289: p->nodetype = t_int; 1290: break; 1291: 1292: default: 1293: p->nodetype = nil; 1294: break; 1295: } 1296: } 1297: 1298: /* 1299: * Process a binary arithmetic or relational operator. 1300: * Convert from integer to real if necessary. 1301: */ 1302: 1303: private binaryop (p, t) 1304: Node p; 1305: Symbol t; 1306: { 1307: Node p1, p2; 1308: Boolean t1real, t2real; 1309: Symbol t1, t2; 1310: 1311: p1 = p->value.arg[0]; 1312: p2 = p->value.arg[1]; 1313: t1 = rtype(p1->nodetype); 1314: t2 = rtype(p2->nodetype); 1315: t1real = compatible(t1, t_real); 1316: t2real = compatible(t2, t_real); 1317: if (t1real or t2real) { 1318: p->op = (Operator) (ord(p->op) + 1); 1319: if (not t1real) { 1320: p->value.arg[0] = build(O_ITOF, p1); 1321: } else if (not t2real) { 1322: p->value.arg[1] = build(O_ITOF, p2); 1323: } 1324: p->nodetype = t_real; 1325: } else { 1326: if (size(p1->nodetype) > sizeof(integer)) { 1327: beginerrmsg(); 1328: fprintf(stderr, "operation not defined on \""); 1329: prtree(stderr, p1); 1330: fprintf(stderr, "\""); 1331: enderrmsg(); 1332: } else if (size(p2->nodetype) > sizeof(integer)) { 1333: beginerrmsg(); 1334: fprintf(stderr, "operation not defined on \""); 1335: prtree(stderr, p2); 1336: fprintf(stderr, "\""); 1337: enderrmsg(); 1338: } 1339: p->nodetype = t_int; 1340: } 1341: if (t != nil) { 1342: p->nodetype = t; 1343: } 1344: } 1345: 1346: /* 1347: * Convert a tree to a type via a conversion operator; 1348: * if this isn't possible generate an error. 1349: * 1350: * Note the tree is call by address, hence the #define below. 1351: */ 1352: 1353: private convert(tp, typeto, op) 1354: Node *tp; 1355: Symbol typeto; 1356: Operator op; 1357: { 1358: Node tree; 1359: Symbol s, t; 1360: 1361: tree = *tp; 1362: s = rtype(tree->nodetype); 1363: t = rtype(typeto); 1364: if (compatible(t, t_real) and compatible(s, t_int)) { 1365: tree = build(op, tree); 1366: } else if (not compatible(s, t)) { 1367: beginerrmsg(); 1368: fprintf(stderr, "expected integer or real, found \""); 1369: prtree(stderr, tree); 1370: fprintf(stderr, "\""); 1371: enderrmsg(); 1372: } else if (op != O_NOP and s != t) { 1373: tree = build(op, tree); 1374: } 1375: *tp = tree; 1376: } 1377: 1378: /* 1379: * Construct a node for the dot operator. 1380: * 1381: * If the left operand is not a record, but rather a procedure 1382: * or function, then we interpret the "." as referencing an 1383: * "invisible" variable; i.e. a variable within a dynamically 1384: * active block but not within the static scope of the current procedure. 1385: */ 1386: 1387: public Node dot(record, fieldname) 1388: Node record; 1389: Name fieldname; 1390: { 1391: register Node rec, p; 1392: register Symbol s, t; 1393: 1394: rec = record; 1395: if (isblock(rec->nodetype)) { 1396: find(s, fieldname) where 1397: s->block == rec->nodetype and 1398: s->class != FIELD 1399: endfind(s); 1400: if (s == nil) { 1401: beginerrmsg(); 1402: fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 1403: printname(stderr, rec->nodetype); 1404: enderrmsg(); 1405: } 1406: p = new(Node); 1407: p->op = O_SYM; 1408: p->value.sym = s; 1409: p->nodetype = s; 1410: } else { 1411: p = rec; 1412: t = rtype(p->nodetype); 1413: if (t->class == PTR) { 1414: s = findfield(fieldname, t->type); 1415: } else { 1416: s = findfield(fieldname, t); 1417: } 1418: if (s == nil) { 1419: beginerrmsg(); 1420: fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 1421: prtree(stderr, rec); 1422: enderrmsg(); 1423: } 1424: if (t->class != PTR or isreg(rec->nodetype)) { 1425: p = unrval(p); 1426: } 1427: p->nodetype = t_addr; 1428: p = build(O_DOT, p, build(O_SYM, s)); 1429: } 1430: return build(O_RVAL, p); 1431: } 1432: 1433: /* 1434: * Return a tree corresponding to an array reference and do the 1435: * error checking. 1436: */ 1437: 1438: public Node subscript(a, slist) 1439: Node a, slist; 1440: { 1441: Symbol t; 1442: Node p; 1443: 1444: t = rtype(a->nodetype); 1445: if (t->language == nil or t->language == primlang) { 1446: p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist); 1447: } else { 1448: p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); 1449: } 1450: return build(O_RVAL, p); 1451: } 1452: 1453: /* 1454: * Evaluate a subscript index. 1455: */ 1456: 1457: public int evalindex(s, base, i) 1458: Symbol s; 1459: Address base; 1460: long i; 1461: { 1462: Symbol t; 1463: int r; 1464: 1465: t = rtype(s); 1466: if (t->language == nil or t->language == primlang) { 1467: r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i)); 1468: } else { 1469: r = ((*language_op(t->language, L_EVALAREF)) (s, base, i)); 1470: } 1471: return r; 1472: } 1473: 1474: /* 1475: * Check to see if a tree is boolean-valued, if not it's an error. 1476: */ 1477: 1478: public chkboolean(p) 1479: register Node p; 1480: { 1481: if (p->nodetype != t_boolean) { 1482: beginerrmsg(); 1483: fprintf(stderr, "found "); 1484: prtree(stderr, p); 1485: fprintf(stderr, ", expected boolean expression"); 1486: enderrmsg(); 1487: } 1488: } 1489: 1490: /* 1491: * Construct a node for the type of a string. 1492: */ 1493: 1494: private Symbol mkstring(str) 1495: String str; 1496: { 1497: register Symbol s; 1498: 1499: s = newSymbol(nil, 0, ARRAY, t_char, nil); 1500: s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1501: s->chain->language = s->language; 1502: s->chain->symvalue.rangev.lower = 1; 1503: s->chain->symvalue.rangev.upper = strlen(str) + 1; 1504: return s; 1505: } 1506: 1507: /* 1508: * Free up the space allocated for a string type. 1509: */ 1510: 1511: public unmkstring(s) 1512: Symbol s; 1513: { 1514: dispose(s->chain); 1515: } 1516: 1517: /* 1518: * Figure out the "current" variable or function being referred to 1519: * by the name n. 1520: */ 1521: 1522: private boolean stwhich(), dynwhich(); 1523: 1524: public Symbol which (n) 1525: Name n; 1526: { 1527: Symbol s; 1528: 1529: s = lookup(n); 1530: if (s == nil) { 1531: error("\"%s\" is not defined", ident(n)); 1532: } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) { 1533: printf("[using "); 1534: printname(stdout, s); 1535: printf("]\n"); 1536: } 1537: return s; 1538: } 1539: 1540: /* 1541: * Static search. 1542: */ 1543: 1544: private boolean stwhich (var_s) 1545: Symbol *var_s; 1546: { 1547: Name n; /* name of desired symbol */ 1548: Symbol s; /* iteration variable for symbols with name n */ 1549: Symbol f; /* iteration variable for blocks containing s */ 1550: integer count; /* number of levels from s->block to curfunc */ 1551: Symbol t; /* current best answer for stwhich(n) */ 1552: integer mincount; /* relative level for current best answer (t) */ 1553: boolean b; /* return value, true if symbol found */ 1554: 1555: s = *var_s; 1556: n = s->name; 1557: t = s; 1558: mincount = 10000; /* force first match to set mincount */ 1559: do { 1560: if (s->name == n and s->class != FIELD and s->class != TAG) { 1561: f = curfunc; 1562: count = 0; 1563: while (f != nil and f != s->block) { 1564: ++count; 1565: f = f->block; 1566: } 1567: if (f != nil and count < mincount) { 1568: t = s; 1569: mincount = count; 1570: b = true; 1571: } 1572: } 1573: s = s->next_sym; 1574: } while (s != nil); 1575: if (mincount != 10000) { 1576: *var_s = t; 1577: b = true; 1578: } else { 1579: b = false; 1580: } 1581: return b; 1582: } 1583: 1584: /* 1585: * Dynamic search. 1586: */ 1587: 1588: private boolean dynwhich (var_s) 1589: Symbol *var_s; 1590: { 1591: Name n; /* name of desired symbol */ 1592: Symbol s; /* iteration variable for possible symbols */ 1593: Symbol f; /* iteration variable for active functions */ 1594: Frame frp; /* frame associated with stack walk */ 1595: boolean b; /* return value */ 1596: 1597: f = curfunc; 1598: frp = curfuncframe(); 1599: n = (*var_s)->name; 1600: b = false; 1601: if (frp != nil) { 1602: frp = nextfunc(frp, &f); 1603: while (frp != nil) { 1604: s = *var_s; 1605: while (s != nil and 1606: ( 1607: s->name != n or s->block != f or 1608: s->class == FIELD or s->class == TAG 1609: ) 1610: ) { 1611: s = s->next_sym; 1612: } 1613: if (s != nil) { 1614: *var_s = s; 1615: b = true; 1616: break; 1617: } 1618: if (f == program) { 1619: break; 1620: } 1621: frp = nextfunc(frp, &f); 1622: } 1623: } 1624: return b; 1625: } 1626: 1627: /* 1628: * Find the symbol that has the same name and scope as the 1629: * given symbol but is of the given field. Return nil if there is none. 1630: */ 1631: 1632: public Symbol findfield (fieldname, record) 1633: Name fieldname; 1634: Symbol record; 1635: { 1636: register Symbol t; 1637: 1638: t = rtype(record)->chain; 1639: while (t != nil and t->name != fieldname) { 1640: t = t->chain; 1641: } 1642: return t; 1643: } 1644: 1645: public Boolean getbound(s,off,type,valp) 1646: Symbol s; 1647: int off; 1648: Rangetype type; 1649: int *valp; 1650: { 1651: Frame frp; 1652: Address addr; 1653: Symbol cur; 1654: 1655: if (not isactive(s->block)) { 1656: return(false); 1657: } 1658: cur = s->block; 1659: while (cur != nil and cur->class == MODULE) { /* WHY*/ 1660: cur = cur->block; 1661: } 1662: if(cur == nil) { 1663: cur = whatblock(pc); 1664: } 1665: frp = findframe(cur); 1666: if (frp == nil) { 1667: return(false); 1668: } 1669: if(type == R_TEMP) addr = locals_base(frp) + off; 1670: else if (type == R_ARG) addr = args_base(frp) + off; 1671: else return(false); 1672: dread(valp,addr,sizeof(long)); 1673: return(true); 1674: }