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