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