|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)symbols.c 1.11 8/16/83"; ! 4: ! 5: /* ! 6: * Symbol management. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "symbols.h" ! 11: #include "languages.h" ! 12: #include "printsym.h" ! 13: #include "tree.h" ! 14: #include "operators.h" ! 15: #include "eval.h" ! 16: #include "mappings.h" ! 17: #include "events.h" ! 18: #include "process.h" ! 19: #include "runtime.h" ! 20: #include "machine.h" ! 21: #include "names.h" ! 22: ! 23: #ifndef public ! 24: typedef struct Symbol *Symbol; ! 25: ! 26: #include "machine.h" ! 27: #include "names.h" ! 28: #include "languages.h" ! 29: ! 30: /* ! 31: * Symbol classes ! 32: */ ! 33: ! 34: typedef enum { ! 35: BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, ! 36: PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, ! 37: LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, ! 38: FPROC, FFUNC, MODULE, TAG, COMMON, TYPEREF ! 39: } Symclass; ! 40: ! 41: typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype; ! 42: ! 43: struct Symbol { ! 44: Name name; ! 45: Language language; ! 46: Symclass class : 8; ! 47: Integer level : 8; ! 48: Symbol type; ! 49: Symbol chain; ! 50: union { ! 51: int offset; /* variable address */ ! 52: long iconval; /* integer constant value */ ! 53: double fconval; /* floating constant value */ ! 54: struct { /* field offset and size (both in bits) */ ! 55: int offset; ! 56: int length; ! 57: } field; ! 58: struct { /* common offset and chain; used to relocate */ ! 59: int offset; /* vars in global BSS */ ! 60: Symbol chain; ! 61: } common; ! 62: struct { /* range bounds */ ! 63: Rangetype lowertype : 16; ! 64: Rangetype uppertype : 16; ! 65: long lower; ! 66: long upper; ! 67: } rangev; ! 68: struct { ! 69: int offset : 16; /* offset for of function value */ ! 70: Boolean src : 8; /* true if there is source line info */ ! 71: Boolean inline : 8; /* true if no separate act. rec. */ ! 72: Address beginaddr; /* address of function code */ ! 73: } funcv; ! 74: struct { /* variant record info */ ! 75: int size; ! 76: Symbol vtorec; ! 77: Symbol vtag; ! 78: } varnt; ! 79: } symvalue; ! 80: Symbol block; /* symbol containing this symbol */ ! 81: Symbol next_sym; /* hash chain */ ! 82: }; ! 83: ! 84: /* ! 85: * Basic types. ! 86: */ ! 87: ! 88: Symbol t_boolean; ! 89: Symbol t_char; ! 90: Symbol t_int; ! 91: Symbol t_real; ! 92: Symbol t_nil; ! 93: ! 94: Symbol program; ! 95: Symbol curfunc; ! 96: ! 97: #define symname(s) ident(s->name) ! 98: #define codeloc(f) ((f)->symvalue.funcv.beginaddr) ! 99: #define isblock(s) (Boolean) ( \ ! 100: s->class == FUNC or s->class == PROC or \ ! 101: s->class == MODULE or s->class == PROG \ ! 102: ) ! 103: ! 104: #define nosource(f) (not (f)->symvalue.funcv.src) ! 105: #define isinline(f) ((f)->symvalue.funcv.inline) ! 106: ! 107: #include "tree.h" ! 108: ! 109: /* ! 110: * Some macros to make finding a symbol with certain attributes. ! 111: */ ! 112: ! 113: #define find(s, withname) \ ! 114: { \ ! 115: s = lookup(withname); \ ! 116: while (s != nil and not (s->name == (withname) and ! 117: ! 118: #define where /* qualification */ ! 119: ! 120: #define endfind(s) )) { \ ! 121: s = s->next_sym; \ ! 122: } \ ! 123: } ! 124: ! 125: #endif ! 126: ! 127: /* ! 128: * Symbol table structure currently does not support deletions. ! 129: */ ! 130: ! 131: #define HASHTABLESIZE 2003 ! 132: ! 133: private Symbol hashtab[HASHTABLESIZE]; ! 134: ! 135: #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) ! 136: ! 137: /* ! 138: * Allocate a new symbol. ! 139: */ ! 140: ! 141: #define SYMBLOCKSIZE 100 ! 142: ! 143: typedef struct Sympool { ! 144: struct Symbol sym[SYMBLOCKSIZE]; ! 145: struct Sympool *prevpool; ! 146: } *Sympool; ! 147: ! 148: private Sympool sympool = nil; ! 149: private Integer nleft = 0; ! 150: ! 151: public Symbol symbol_alloc() ! 152: { ! 153: register Sympool newpool; ! 154: ! 155: if (nleft <= 0) { ! 156: newpool = new(Sympool); ! 157: bzero(newpool, sizeof(newpool)); ! 158: newpool->prevpool = sympool; ! 159: sympool = newpool; ! 160: nleft = SYMBLOCKSIZE; ! 161: } ! 162: --nleft; ! 163: return &(sympool->sym[nleft]); ! 164: } ! 165: ! 166: ! 167: public symbol_dump(func) ! 168: Symbol func; ! 169: { ! 170: register Symbol s; ! 171: register Integer i; ! 172: ! 173: printf(" symbols in %s \n",symname(func)); ! 174: for (i = 0; i< HASHTABLESIZE; i++) { ! 175: for (s = hashtab[i]; s != nil; s = s->next_sym) { ! 176: if (s->block == func) { ! 177: psym(s); ! 178: } ! 179: } ! 180: } ! 181: } ! 182: ! 183: /* ! 184: * Free all the symbols currently allocated. ! 185: */ ! 186: ! 187: public symbol_free() ! 188: { ! 189: Sympool s, t; ! 190: register Integer i; ! 191: ! 192: s = sympool; ! 193: while (s != nil) { ! 194: t = s->prevpool; ! 195: dispose(s); ! 196: s = t; ! 197: } ! 198: for (i = 0; i < HASHTABLESIZE; i++) { ! 199: hashtab[i] = nil; ! 200: } ! 201: sympool = nil; ! 202: nleft = 0; ! 203: } ! 204: ! 205: /* ! 206: * Create a new symbol with the given attributes. ! 207: */ ! 208: ! 209: public Symbol newSymbol(name, blevel, class, type, chain) ! 210: Name name; ! 211: Integer blevel; ! 212: Symclass class; ! 213: Symbol type; ! 214: Symbol chain; ! 215: { ! 216: register Symbol s; ! 217: ! 218: s = symbol_alloc(); ! 219: s->name = name; ! 220: s->level = blevel; ! 221: s->class = class; ! 222: s->type = type; ! 223: s->chain = chain; ! 224: return s; ! 225: } ! 226: ! 227: /* ! 228: * Insert a symbol into the hash table. ! 229: */ ! 230: ! 231: public Symbol insert(name) ! 232: Name name; ! 233: { ! 234: register Symbol s; ! 235: register unsigned int h; ! 236: ! 237: h = hash(name); ! 238: s = symbol_alloc(); ! 239: s->name = name; ! 240: s->next_sym = hashtab[h]; ! 241: hashtab[h] = s; ! 242: return s; ! 243: } ! 244: ! 245: /* ! 246: * Symbol lookup. ! 247: */ ! 248: ! 249: public Symbol lookup(name) ! 250: Name name; ! 251: { ! 252: register Symbol s; ! 253: register unsigned int h; ! 254: ! 255: h = hash(name); ! 256: s = hashtab[h]; ! 257: while (s != nil and s->name != name) { ! 258: s = s->next_sym; ! 259: } ! 260: return s; ! 261: } ! 262: ! 263: /* ! 264: * Dump out all the variables associated with the given ! 265: * procedure, function, or program at the given recursive level. ! 266: * ! 267: * This is quite inefficient. We traverse the entire symbol table ! 268: * each time we're called. The assumption is that this routine ! 269: * won't be called frequently enough to merit improved performance. ! 270: */ ! 271: ! 272: public dumpvars(f, frame) ! 273: Symbol f; ! 274: Frame frame; ! 275: { ! 276: register Integer i; ! 277: register Symbol s; ! 278: ! 279: for (i = 0; i < HASHTABLESIZE; i++) { ! 280: for (s = hashtab[i]; s != nil; s = s->next_sym) { ! 281: if (container(s) == f) { ! 282: if (should_print(s)) { ! 283: printv(s, frame); ! 284: putchar('\n'); ! 285: } else if (s->class == MODULE) { ! 286: dumpvars(s, frame); ! 287: } ! 288: } ! 289: } ! 290: } ! 291: } ! 292: ! 293: /* ! 294: * Create base types. ! 295: */ ! 296: ! 297: public symbols_init() ! 298: { ! 299: t_boolean = maketype("$boolean", 0L, 1L); ! 300: t_int = maketype("$integer", 0x80000000L, 0x7fffffffL); ! 301: t_char = maketype("$char", 0L, 127L); ! 302: t_real = maketype("$real", 8L, 0L); ! 303: t_nil = maketype("$nil", 0L, 0L); ! 304: } ! 305: ! 306: /* ! 307: * Create a builtin type. ! 308: * Builtin types are circular in that btype->type->type = btype. ! 309: */ ! 310: ! 311: public Symbol maketype(name, lower, upper) ! 312: String name; ! 313: long lower; ! 314: long upper; ! 315: { ! 316: register Symbol s; ! 317: ! 318: s = newSymbol(identname(name, true), 0, TYPE, nil, nil); ! 319: s->language = findlanguage(".c"); ! 320: s->type = newSymbol(nil, 0, RANGE, s, nil); ! 321: s->type->symvalue.rangev.lower = lower; ! 322: s->type->symvalue.rangev.upper = upper; ! 323: return s; ! 324: } ! 325: ! 326: /* ! 327: * These functions are now compiled inline. ! 328: * ! 329: * public String symname(s) ! 330: Symbol s; ! 331: { ! 332: checkref(s); ! 333: return ident(s->name); ! 334: } ! 335: ! 336: * ! 337: * public Address codeloc(f) ! 338: Symbol f; ! 339: { ! 340: checkref(f); ! 341: if (not isblock(f)) { ! 342: panic("codeloc: \"%s\" is not a block", ident(f->name)); ! 343: } ! 344: return f->symvalue.funcv.beginaddr; ! 345: } ! 346: * ! 347: */ ! 348: ! 349: /* ! 350: * Reduce type to avoid worrying about type names. ! 351: */ ! 352: ! 353: public Symbol rtype(type) ! 354: Symbol type; ! 355: { ! 356: register Symbol t; ! 357: ! 358: t = type; ! 359: if (t != nil) { ! 360: if (t->class == VAR or t->class == FIELD or t->class == REF ) { ! 361: t = t->type; ! 362: } ! 363: while (t->class == TYPE or t->class == TAG) { ! 364: t = t->type; ! 365: } ! 366: } ! 367: return t; ! 368: } ! 369: ! 370: public Integer level(s) ! 371: Symbol s; ! 372: { ! 373: checkref(s); ! 374: return s->level; ! 375: } ! 376: ! 377: public Symbol container(s) ! 378: Symbol s; ! 379: { ! 380: checkref(s); ! 381: return s->block; ! 382: } ! 383: ! 384: /* ! 385: * Return the object address of the given symbol. ! 386: * ! 387: * There are the following possibilities: ! 388: * ! 389: * globals - just take offset ! 390: * locals - take offset from locals base ! 391: * arguments - take offset from argument base ! 392: * register - offset is register number ! 393: */ ! 394: ! 395: #define isglobal(s) (s->level == 1 or s->level == 2) ! 396: #define islocaloff(s) (s->level >= 3 and s->symvalue.offset < 0) ! 397: #define isparamoff(s) (s->level >= 3 and s->symvalue.offset >= 0) ! 398: #define isreg(s) (s->level < 0) ! 399: ! 400: public Address address(s, frame) ! 401: Symbol s; ! 402: Frame frame; ! 403: { ! 404: register Frame frp; ! 405: register Address addr; ! 406: register Symbol cur; ! 407: ! 408: checkref(s); ! 409: if (not isactive(s->block)) { ! 410: error("\"%s\" is not currently defined", symname(s)); ! 411: } else if (isglobal(s)) { ! 412: addr = s->symvalue.offset; ! 413: } else { ! 414: frp = frame; ! 415: if (frp == nil) { ! 416: cur = s->block; ! 417: while (cur != nil and cur->class == MODULE) { ! 418: cur = cur->block; ! 419: } ! 420: if (cur == nil) { ! 421: cur = whatblock(pc); ! 422: } ! 423: frp = findframe(cur); ! 424: if (frp == nil) { ! 425: panic("unexpected nil frame for \"%s\"", symname(s)); ! 426: } ! 427: } ! 428: if (islocaloff(s)) { ! 429: addr = locals_base(frp) + s->symvalue.offset; ! 430: } else if (isparamoff(s)) { ! 431: addr = args_base(frp) + s->symvalue.offset; ! 432: } else if (isreg(s)) { ! 433: addr = savereg(s->symvalue.offset, frp); ! 434: } else { ! 435: panic("address: bad symbol \"%s\"", symname(s)); ! 436: } ! 437: } ! 438: return addr; ! 439: } ! 440: ! 441: /* ! 442: * Define a symbol used to access register values. ! 443: */ ! 444: ! 445: public defregname(n, r) ! 446: Name n; ! 447: Integer r; ! 448: { ! 449: register Symbol s, t; ! 450: ! 451: s = insert(n); ! 452: t = newSymbol(nil, 0, PTR, t_int, nil); ! 453: t->language = findlanguage(".s"); ! 454: s->language = t->language; ! 455: s->class = VAR; ! 456: s->level = -3; ! 457: s->type = t; ! 458: s->block = program; ! 459: s->symvalue.offset = r; ! 460: } ! 461: ! 462: /* ! 463: * Resolve an "abstract" type reference. ! 464: * ! 465: * It is possible in C to define a pointer to a type, but never define ! 466: * the type in a particular source file. Here we try to resolve ! 467: * the type definition. This is problematic, it is possible to ! 468: * have multiple, different definitions for the same name type. ! 469: */ ! 470: ! 471: public findtype(s) ! 472: Symbol s; ! 473: { ! 474: register Symbol t, u, prev; ! 475: ! 476: u = s; ! 477: prev = nil; ! 478: while (u != nil and u->class != BADUSE) { ! 479: if (u->name != nil) { ! 480: prev = u; ! 481: } ! 482: u = u->type; ! 483: } ! 484: if (prev == nil) { ! 485: error("couldn't find link to type reference"); ! 486: } ! 487: find(t, prev->name) where ! 488: t->type != nil and t->class == prev->class and ! 489: t->type->class != BADUSE and t->block->class == MODULE ! 490: endfind(t); ! 491: if (t == nil) { ! 492: error("couldn't resolve reference"); ! 493: } else { ! 494: prev->type = t->type; ! 495: } ! 496: } ! 497: ! 498: /* ! 499: * Find the size in bytes of the given type. ! 500: * ! 501: * This is probably the WRONG thing to do. The size should be kept ! 502: * as an attribute in the symbol information as is done for structures ! 503: * and fields. I haven't gotten around to cleaning this up yet. ! 504: */ ! 505: ! 506: #define MAXUCHAR 255 ! 507: #define MAXUSHORT 65535L ! 508: #define MINCHAR -128 ! 509: #define MAXCHAR 127 ! 510: #define MINSHORT -32768 ! 511: #define MAXSHORT 32767 ! 512: ! 513: public Integer size(sym) ! 514: Symbol sym; ! 515: { ! 516: register Symbol s, t; ! 517: register int nel, elsize; ! 518: long lower, upper; ! 519: int r; ! 520: ! 521: t = sym; ! 522: checkref(t); ! 523: switch (t->class) { ! 524: case RANGE: ! 525: lower = t->symvalue.rangev.lower; ! 526: upper = t->symvalue.rangev.upper; ! 527: if (upper == 0 and lower > 0) { /* real */ ! 528: r = lower; ! 529: } else if ( ! 530: (lower >= MINCHAR and upper <= MAXCHAR) or ! 531: (lower >= 0 and upper <= MAXUCHAR) ! 532: ) { ! 533: r = sizeof(char); ! 534: } else if ( ! 535: (lower >= MINSHORT and upper <= MAXSHORT) or ! 536: (lower >= 0 and upper <= MAXUSHORT) ! 537: ) { ! 538: r = sizeof(short); ! 539: } else { ! 540: r = sizeof(long); ! 541: } ! 542: break; ! 543: ! 544: case ARRAY: ! 545: elsize = size(t->type); ! 546: nel = 1; ! 547: for (t = t->chain; t != nil; t = t->chain) { ! 548: if (t->symvalue.rangev.lowertype == R_ARG or ! 549: t->symvalue.rangev.lowertype == R_TEMP) { ! 550: if (not getbound(t, t->symvalue.rangev.lower, ! 551: t->symvalue.rangev.lowertype, &lower)) { ! 552: error("dynamic bounds not currently available"); ! 553: } ! 554: } else { ! 555: lower = t->symvalue.rangev.lower; ! 556: } ! 557: if (t->symvalue.rangev.uppertype == R_ARG or ! 558: t->symvalue.rangev.uppertype == R_TEMP) { ! 559: if (not getbound(t, t->symvalue.rangev.upper, ! 560: t->symvalue.rangev.uppertype, &upper)) { ! 561: error("dynamic bounds nor currently available"); ! 562: } ! 563: } else { ! 564: upper = t->symvalue.rangev.upper; ! 565: } ! 566: nel *= (upper-lower+1); ! 567: } ! 568: r = nel*elsize; ! 569: break; ! 570: ! 571: case REF: ! 572: case VAR: ! 573: case FVAR: ! 574: r = size(t->type); ! 575: /* ! 576: * ! 577: if (r < sizeof(Word) and isparam(t)) { ! 578: r = sizeof(Word); ! 579: } ! 580: */ ! 581: break; ! 582: ! 583: case CONST: ! 584: r = size(t->type); ! 585: break; ! 586: ! 587: case TYPE: ! 588: if (t->type->class == PTR and t->type->type->class == BADUSE) { ! 589: findtype(t); ! 590: } ! 591: r = size(t->type); ! 592: break; ! 593: ! 594: case TAG: ! 595: r = size(t->type); ! 596: break; ! 597: ! 598: case FIELD: ! 599: r = (t->symvalue.field.length + 7) div 8; ! 600: break; ! 601: ! 602: case RECORD: ! 603: case VARNT: ! 604: r = t->symvalue.offset; ! 605: if (r == 0 and t->chain != nil) { ! 606: panic("missing size information for record"); ! 607: } ! 608: break; ! 609: ! 610: case PTR: ! 611: case FILET: ! 612: r = sizeof(Word); ! 613: break; ! 614: ! 615: case SCAL: ! 616: r = sizeof(Word); ! 617: /* ! 618: * ! 619: if (t->symvalue.iconval > 255) { ! 620: r = sizeof(short); ! 621: } else { ! 622: r = sizeof(char); ! 623: } ! 624: * ! 625: */ ! 626: break; ! 627: ! 628: case FPROC: ! 629: case FFUNC: ! 630: r = sizeof(Word); ! 631: break; ! 632: ! 633: case PROC: ! 634: case FUNC: ! 635: case MODULE: ! 636: case PROG: ! 637: r = sizeof(Symbol); ! 638: break; ! 639: ! 640: default: ! 641: if (ord(t->class) > ord(TYPEREF)) { ! 642: panic("size: bad class (%d)", ord(t->class)); ! 643: } else { ! 644: error("improper operation on a %s", classname(t)); ! 645: } ! 646: /* NOTREACHED */ ! 647: } ! 648: return r; ! 649: } ! 650: ! 651: /* ! 652: * Test if a symbol is a parameter. This is true if there ! 653: * is a cycle from s->block to s via chain pointers. ! 654: */ ! 655: ! 656: public Boolean isparam(s) ! 657: Symbol s; ! 658: { ! 659: register Symbol t; ! 660: ! 661: t = s->block; ! 662: while (t != nil and t != s) { ! 663: t = t->chain; ! 664: } ! 665: return (Boolean) (t != nil); ! 666: } ! 667: ! 668: /* ! 669: * Test if a symbol is a var parameter, i.e. has class REF. ! 670: */ ! 671: ! 672: public Boolean isvarparam(s) ! 673: Symbol s; ! 674: { ! 675: return (Boolean) (s->class == REF); ! 676: } ! 677: ! 678: /* ! 679: * Test if a symbol is a variable (actually any addressible quantity ! 680: * with do). ! 681: */ ! 682: ! 683: public Boolean isvariable(s) ! 684: register Symbol s; ! 685: { ! 686: return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); ! 687: } ! 688: ! 689: /* ! 690: * Test if a symbol is a block, e.g. function, procedure, or the ! 691: * main program. ! 692: * ! 693: * This function is now expanded inline for efficiency. ! 694: * ! 695: * public Boolean isblock(s) ! 696: register Symbol s; ! 697: { ! 698: return (Boolean) ( ! 699: s->class == FUNC or s->class == PROC or ! 700: s->class == MODULE or s->class == PROG ! 701: ); ! 702: } ! 703: * ! 704: */ ! 705: ! 706: /* ! 707: * Test if a symbol is a module. ! 708: */ ! 709: ! 710: public Boolean ismodule(s) ! 711: register Symbol s; ! 712: { ! 713: return (Boolean) (s->class == MODULE); ! 714: } ! 715: ! 716: /* ! 717: * Test if a symbol is builtin, that is, a predefined type or ! 718: * reserved word. ! 719: */ ! 720: ! 721: public Boolean isbuiltin(s) ! 722: register Symbol s; ! 723: { ! 724: return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); ! 725: } ! 726: ! 727: /* ! 728: * Test if two types match. ! 729: * Equivalent names implies a match in any language. ! 730: * ! 731: * Special symbols must be handled with care. ! 732: */ ! 733: ! 734: public Boolean compatible(t1, t2) ! 735: register Symbol t1, t2; ! 736: { ! 737: Boolean b; ! 738: ! 739: if (t1 == t2) { ! 740: b = true; ! 741: } else if (t1 == nil or t2 == nil) { ! 742: b = false; ! 743: } else if (t1 == procsym) { ! 744: b = isblock(t2); ! 745: } else if (t2 == procsym) { ! 746: b = isblock(t1); ! 747: } else if (t1->language == nil) { ! 748: b = (Boolean) (t2->language == nil or ! 749: (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); ! 750: } else if (t2->language == nil) { ! 751: b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); ! 752: } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) { ! 753: b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); ! 754: } else { ! 755: b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); ! 756: } ! 757: return b; ! 758: } ! 759: ! 760: /* ! 761: * Check for a type of the given name. ! 762: */ ! 763: ! 764: public Boolean istypename(type, name) ! 765: Symbol type; ! 766: String name; ! 767: { ! 768: Symbol t; ! 769: Boolean b; ! 770: ! 771: t = type; ! 772: checkref(t); ! 773: b = (Boolean) ( ! 774: t->class == TYPE and t->name == identname(name, true) ! 775: ); ! 776: return b; ! 777: } ! 778: ! 779: /* ! 780: * Test if the name of a symbol is uniquely defined or not. ! 781: */ ! 782: ! 783: public Boolean isambiguous(s) ! 784: register Symbol s; ! 785: { ! 786: register Symbol t; ! 787: ! 788: find(t, s->name) where t != s endfind(t); ! 789: return (Boolean) (t != nil); ! 790: } ! 791: ! 792: typedef char *Arglist; ! 793: ! 794: #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] ! 795: ! 796: private Symbol mkstring(); ! 797: private Symbol namenode(); ! 798: ! 799: /* ! 800: * Determine the type of a parse tree. ! 801: * Also make some symbol-dependent changes to the tree such as ! 802: * changing removing RVAL nodes for constant symbols. ! 803: */ ! 804: ! 805: public assigntypes(p) ! 806: register Node p; ! 807: { ! 808: register Node p1; ! 809: register Symbol s; ! 810: ! 811: switch (p->op) { ! 812: case O_SYM: ! 813: p->nodetype = namenode(p); ! 814: break; ! 815: ! 816: case O_LCON: ! 817: p->nodetype = t_int; ! 818: break; ! 819: ! 820: case O_FCON: ! 821: p->nodetype = t_real; ! 822: break; ! 823: ! 824: case O_SCON: ! 825: p->value.scon = strdup(p->value.scon); ! 826: s = mkstring(p->value.scon); ! 827: if (s == t_char) { ! 828: p->op = O_LCON; ! 829: p->value.lcon = p->value.scon[0]; ! 830: } ! 831: p->nodetype = s; ! 832: break; ! 833: ! 834: case O_INDIR: ! 835: p1 = p->value.arg[0]; ! 836: chkclass(p1, PTR); ! 837: p->nodetype = rtype(p1->nodetype)->type; ! 838: break; ! 839: ! 840: case O_DOT: ! 841: p->nodetype = p->value.arg[1]->value.sym; ! 842: break; ! 843: ! 844: case O_RVAL: ! 845: p1 = p->value.arg[0]; ! 846: p->nodetype = p1->nodetype; ! 847: if (p1->op == O_SYM) { ! 848: if (p1->nodetype->class == FUNC) { ! 849: p->op = O_CALL; ! 850: p->value.arg[1] = nil; ! 851: } else if (p1->value.sym->class == CONST) { ! 852: if (compatible(p1->value.sym->type, t_real)) { ! 853: p->op = O_FCON; ! 854: p->value.fcon = p1->value.sym->symvalue.fconval; ! 855: p->nodetype = t_real; ! 856: dispose(p1); ! 857: } else { ! 858: p->op = O_LCON; ! 859: p->value.lcon = p1->value.sym->symvalue.iconval; ! 860: p->nodetype = p1->value.sym->type; ! 861: dispose(p1); ! 862: } ! 863: } else if (isreg(p1->value.sym)) { ! 864: p->op = O_SYM; ! 865: p->value.sym = p1->value.sym; ! 866: dispose(p1); ! 867: } ! 868: } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { ! 869: s = p1->value.arg[0]->value.sym; ! 870: if (isreg(s)) { ! 871: p1->op = O_SYM; ! 872: dispose(p1->value.arg[0]); ! 873: p1->value.sym = s; ! 874: p1->nodetype = s; ! 875: } ! 876: } ! 877: break; ! 878: ! 879: case O_CALL: ! 880: p1 = p->value.arg[0]; ! 881: p->nodetype = rtype(p1->nodetype)->type; ! 882: break; ! 883: ! 884: case O_TYPERENAME: ! 885: p->nodetype = p->value.arg[1]->nodetype; ! 886: break; ! 887: ! 888: case O_ITOF: ! 889: p->nodetype = t_real; ! 890: break; ! 891: ! 892: case O_NEG: ! 893: s = p->value.arg[0]->nodetype; ! 894: if (not compatible(s, t_int)) { ! 895: if (not compatible(s, t_real)) { ! 896: beginerrmsg(); ! 897: prtree(stderr, p->value.arg[0]); ! 898: fprintf(stderr, "is improper type"); ! 899: enderrmsg(); ! 900: } else { ! 901: p->op = O_NEGF; ! 902: } ! 903: } ! 904: p->nodetype = s; ! 905: break; ! 906: ! 907: case O_ADD: ! 908: case O_SUB: ! 909: case O_MUL: ! 910: case O_LT: ! 911: case O_LE: ! 912: case O_GT: ! 913: case O_GE: ! 914: case O_EQ: ! 915: case O_NE: ! 916: { ! 917: Boolean t1real, t2real; ! 918: Symbol t1, t2; ! 919: ! 920: t1 = rtype(p->value.arg[0]->nodetype); ! 921: t2 = rtype(p->value.arg[1]->nodetype); ! 922: t1real = compatible(t1, t_real); ! 923: t2real = compatible(t2, t_real); ! 924: if (t1real or t2real) { ! 925: p->op = (Operator) (ord(p->op) + 1); ! 926: if (not t1real) { ! 927: p->value.arg[0] = build(O_ITOF, p->value.arg[0]); ! 928: } else if (not t2real) { ! 929: p->value.arg[1] = build(O_ITOF, p->value.arg[1]); ! 930: } ! 931: } else { ! 932: if (t1real) { ! 933: convert(&(p->value.arg[0]), t_int, O_NOP); ! 934: } ! 935: if (t2real) { ! 936: convert(&(p->value.arg[1]), t_int, O_NOP); ! 937: } ! 938: } ! 939: if (ord(p->op) >= ord(O_LT)) { ! 940: p->nodetype = t_boolean; ! 941: } else { ! 942: if (t1real or t2real) { ! 943: p->nodetype = t_real; ! 944: } else { ! 945: p->nodetype = t_int; ! 946: } ! 947: } ! 948: break; ! 949: } ! 950: ! 951: case O_DIVF: ! 952: convert(&(p->value.arg[0]), t_real, O_ITOF); ! 953: convert(&(p->value.arg[1]), t_real, O_ITOF); ! 954: p->nodetype = t_real; ! 955: break; ! 956: ! 957: case O_DIV: ! 958: case O_MOD: ! 959: convert(&(p->value.arg[0]), t_int, O_NOP); ! 960: convert(&(p->value.arg[1]), t_int, O_NOP); ! 961: p->nodetype = t_int; ! 962: break; ! 963: ! 964: case O_AND: ! 965: case O_OR: ! 966: chkboolean(p->value.arg[0]); ! 967: chkboolean(p->value.arg[1]); ! 968: p->nodetype = t_boolean; ! 969: break; ! 970: ! 971: case O_QLINE: ! 972: p->nodetype = t_int; ! 973: break; ! 974: ! 975: default: ! 976: p->nodetype = nil; ! 977: break; ! 978: } ! 979: } ! 980: ! 981: /* ! 982: * Create a node for a name. The symbol for the name has already ! 983: * been chosen, either implicitly with "which" or explicitly from ! 984: * the dot routine. ! 985: */ ! 986: ! 987: private Symbol namenode(p) ! 988: Node p; ! 989: { ! 990: register Symbol r, s; ! 991: register Node np; ! 992: ! 993: s = p->value.sym; ! 994: if (s->class == REF) { ! 995: np = new(Node); ! 996: np->op = p->op; ! 997: np->nodetype = s; ! 998: np->value.sym = s; ! 999: p->op = O_INDIR; ! 1000: p->value.arg[0] = np; ! 1001: } ! 1002: /* ! 1003: * Old way ! 1004: * ! 1005: if (s->class == CONST or s->class == VAR or s->class == FVAR) { ! 1006: r = s->type; ! 1007: } else { ! 1008: r = s; ! 1009: } ! 1010: * ! 1011: */ ! 1012: return s; ! 1013: } ! 1014: ! 1015: /* ! 1016: * Convert a tree to a type via a conversion operator; ! 1017: * if this isn't possible generate an error. ! 1018: * ! 1019: * Note the tree is call by address, hence the #define below. ! 1020: */ ! 1021: ! 1022: private convert(tp, typeto, op) ! 1023: Node *tp; ! 1024: Symbol typeto; ! 1025: Operator op; ! 1026: { ! 1027: #define tree (*tp) ! 1028: ! 1029: Symbol s; ! 1030: ! 1031: s = rtype(tree->nodetype); ! 1032: typeto = rtype(typeto); ! 1033: if (compatible(typeto, t_real) and compatible(s, t_int)) { ! 1034: tree = build(op, tree); ! 1035: } else if (not compatible(s, typeto)) { ! 1036: beginerrmsg(); ! 1037: prtree(stderr, s); ! 1038: fprintf(stderr, " is improper type"); ! 1039: enderrmsg(); ! 1040: } else if (op != O_NOP and s != typeto) { ! 1041: tree = build(op, tree); ! 1042: } ! 1043: ! 1044: #undef tree ! 1045: } ! 1046: ! 1047: /* ! 1048: * Construct a node for the dot operator. ! 1049: * ! 1050: * If the left operand is not a record, but rather a procedure ! 1051: * or function, then we interpret the "." as referencing an ! 1052: * "invisible" variable; i.e. a variable within a dynamically ! 1053: * active block but not within the static scope of the current procedure. ! 1054: */ ! 1055: ! 1056: public Node dot(record, fieldname) ! 1057: Node record; ! 1058: Name fieldname; ! 1059: { ! 1060: register Node p; ! 1061: register Symbol s, t; ! 1062: ! 1063: if (isblock(record->nodetype)) { ! 1064: find(s, fieldname) where ! 1065: s->block == record->nodetype and ! 1066: s->class != FIELD and s->class != TAG ! 1067: endfind(s); ! 1068: if (s == nil) { ! 1069: beginerrmsg(); ! 1070: fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); ! 1071: printname(stderr, record->nodetype); ! 1072: enderrmsg(); ! 1073: } ! 1074: p = new(Node); ! 1075: p->op = O_SYM; ! 1076: p->value.sym = s; ! 1077: p->nodetype = namenode(p); ! 1078: } else { ! 1079: p = record; ! 1080: t = rtype(p->nodetype); ! 1081: if (t->class == PTR) { ! 1082: s = findfield(fieldname, t->type); ! 1083: } else { ! 1084: s = findfield(fieldname, t); ! 1085: } ! 1086: if (s == nil) { ! 1087: beginerrmsg(); ! 1088: fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); ! 1089: prtree(stderr, record); ! 1090: enderrmsg(); ! 1091: } ! 1092: if (t->class == PTR and not isreg(record->nodetype)) { ! 1093: p = build(O_INDIR, record); ! 1094: } ! 1095: p = build(O_DOT, p, build(O_SYM, s)); ! 1096: } ! 1097: return p; ! 1098: } ! 1099: ! 1100: /* ! 1101: * Return a tree corresponding to an array reference and do the ! 1102: * error checking. ! 1103: */ ! 1104: ! 1105: public Node subscript(a, slist) ! 1106: Node a, slist; ! 1107: { ! 1108: Symbol t; ! 1109: ! 1110: t = rtype(a->nodetype); ! 1111: if(t->language == nil) { ! 1112: error("unknown language"); ! 1113: } ! 1114: else { ! 1115: return ( (Node) ! 1116: (*language_op(t->language, L_BUILDAREF)) (a,slist) ! 1117: ); ! 1118: } ! 1119: } ! 1120: ! 1121: /* ! 1122: * Evaluate a subscript index. ! 1123: */ ! 1124: ! 1125: public int evalindex(s, i) ! 1126: Symbol s; ! 1127: long i; ! 1128: { ! 1129: Symbol t; ! 1130: ! 1131: t = rtype(s); ! 1132: if(t->language == nil) { ! 1133: error("unknown language"); ! 1134: } ! 1135: else { ! 1136: return ( ! 1137: (*language_op(t->language, L_EVALAREF)) (s,i) ! 1138: ); ! 1139: } ! 1140: } ! 1141: ! 1142: /* ! 1143: * Check to see if a tree is boolean-valued, if not it's an error. ! 1144: */ ! 1145: ! 1146: public chkboolean(p) ! 1147: register Node p; ! 1148: { ! 1149: if (p->nodetype != t_boolean) { ! 1150: beginerrmsg(); ! 1151: fprintf(stderr, "found "); ! 1152: prtree(stderr, p); ! 1153: fprintf(stderr, ", expected boolean expression"); ! 1154: enderrmsg(); ! 1155: } ! 1156: } ! 1157: ! 1158: /* ! 1159: * Check to make sure the given tree has a type of the given class. ! 1160: */ ! 1161: ! 1162: private chkclass(p, class) ! 1163: Node p; ! 1164: Symclass class; ! 1165: { ! 1166: struct Symbol tmpsym; ! 1167: ! 1168: tmpsym.class = class; ! 1169: if (rtype(p->nodetype)->class != class) { ! 1170: beginerrmsg(); ! 1171: fprintf(stderr, "\""); ! 1172: prtree(stderr, p); ! 1173: fprintf(stderr, "\" is not a %s", classname(&tmpsym)); ! 1174: enderrmsg(); ! 1175: } ! 1176: } ! 1177: ! 1178: /* ! 1179: * Construct a node for the type of a string. While we're at it, ! 1180: * scan the string for '' that collapse to ', and chop off the ends. ! 1181: */ ! 1182: ! 1183: private Symbol mkstring(str) ! 1184: String str; ! 1185: { ! 1186: register char *p, *q; ! 1187: register Symbol s; ! 1188: ! 1189: p = str; ! 1190: q = str; ! 1191: while (*p != '\0') { ! 1192: if (*p == '\\') { ! 1193: ++p; ! 1194: } ! 1195: *q = *p; ! 1196: ++p; ! 1197: ++q; ! 1198: } ! 1199: *q = '\0'; ! 1200: s = newSymbol(nil, 0, ARRAY, t_char, nil); ! 1201: s->language = findlanguage(".s"); ! 1202: s->chain = newSymbol(nil, 0, RANGE, t_int, nil); ! 1203: s->chain->language = s->language; ! 1204: s->chain->symvalue.rangev.lower = 1; ! 1205: s->chain->symvalue.rangev.upper = p - str + 1; ! 1206: return s; ! 1207: } ! 1208: ! 1209: /* ! 1210: * Free up the space allocated for a string type. ! 1211: */ ! 1212: ! 1213: public unmkstring(s) ! 1214: Symbol s; ! 1215: { ! 1216: dispose(s->chain); ! 1217: } ! 1218: ! 1219: /* ! 1220: * Figure out the "current" variable or function being referred to, ! 1221: * this is either the active one or the most visible from the ! 1222: * current scope. ! 1223: */ ! 1224: ! 1225: public Symbol which(n) ! 1226: Name n; ! 1227: { ! 1228: register Symbol s, p, t, f; ! 1229: ! 1230: find(s, n) where s->class != FIELD and s->class != TAG endfind(s); ! 1231: if (s == nil) { ! 1232: s = lookup(n); ! 1233: } ! 1234: if (s == nil) { ! 1235: error("\"%s\" is not defined", ident(n)); ! 1236: } else if (s == program or isbuiltin(s)) { ! 1237: t = s; ! 1238: } else { ! 1239: /* ! 1240: * Old way ! 1241: * ! 1242: if (not isactive(program)) { ! 1243: f = program; ! 1244: } else { ! 1245: f = whatblock(pc); ! 1246: if (f == nil) { ! 1247: panic("no block for addr 0x%x", pc); ! 1248: } ! 1249: } ! 1250: * ! 1251: * Now start with curfunc. ! 1252: */ ! 1253: p = curfunc; ! 1254: do { ! 1255: find(t, n) where ! 1256: t->block == p and t->class != FIELD and t->class != TAG ! 1257: endfind(t); ! 1258: p = p->block; ! 1259: } while (t == nil and p != nil); ! 1260: if (t == nil) { ! 1261: t = s; ! 1262: } ! 1263: } ! 1264: return t; ! 1265: } ! 1266: ! 1267: /* ! 1268: * Find the symbol which is has the same name and scope as the ! 1269: * given symbol but is of the given field. Return nil if there is none. ! 1270: */ ! 1271: ! 1272: public Symbol findfield(fieldname, record) ! 1273: Name fieldname; ! 1274: Symbol record; ! 1275: { ! 1276: register Symbol t; ! 1277: ! 1278: t = rtype(record)->chain; ! 1279: while (t != nil and t->name != fieldname) { ! 1280: t = t->chain; ! 1281: } ! 1282: return t; ! 1283: } ! 1284: ! 1285: public Boolean getbound(s,off,type,valp) ! 1286: Symbol s; ! 1287: int off; ! 1288: Rangetype type; ! 1289: int *valp; ! 1290: { ! 1291: Frame frp; ! 1292: Address addr; ! 1293: Symbol cur; ! 1294: ! 1295: if (not isactive(s->block)) { ! 1296: return(false); ! 1297: } ! 1298: cur = s->block; ! 1299: while (cur != nil and cur->class == MODULE) { /* WHY*/ ! 1300: cur = cur->block; ! 1301: } ! 1302: if(cur == nil) { ! 1303: cur = whatblock(pc); ! 1304: } ! 1305: frp = findframe(cur); ! 1306: if (frp == nil) { ! 1307: return(false); ! 1308: } ! 1309: if(type == R_TEMP) addr = locals_base(frp) + off; ! 1310: else if (type == R_ARG) addr = args_base(frp) + off; ! 1311: else return(false); ! 1312: dread(valp,addr,sizeof(long)); ! 1313: return(true); ! 1314: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.