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