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