1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)symbols.c 1.8 05/18/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 530 if(t->symvalue.rangev.lowertype == R_ARG 531 or t->symvalue.rangev.lowertype == R_TEMP ) { 532 if( ! getbound(t, t->symvalue.rangev.lower, 533 t->symvalue.rangev.lowertype, &lower)) 534 error(" dynamic bounds not currently available "); 535 } 536 else lower = t->symvalue.rangev.lower; 537 538 if(t->symvalue.rangev.uppertype == R_ARG 539 or t->symvalue.rangev.uppertype == R_TEMP ) { 540 if( ! getbound(t, t->symvalue.rangev.upper, 541 t->symvalue.rangev.uppertype, &upper)) 542 error(" dynamic bounds not currently available "); 543 } 544 else upper = t->symvalue.rangev.upper; 545 nel *= (upper-lower+1); 546 } 547 r = nel*elsize; 548 break; 549 550 case REF: 551 case VAR: 552 case FVAR: 553 r = size(t->type); 554 /* 555 * 556 if (r < sizeof(Word) and isparam(t)) { 557 r = sizeof(Word); 558 } 559 */ 560 break; 561 562 case CONST: 563 r = size(t->type); 564 break; 565 566 case TYPE: 567 if (t->type->class == PTR and t->type->type->class == BADUSE) { 568 findtype(t); 569 } 570 r = size(t->type); 571 break; 572 573 case TAG: 574 r = size(t->type); 575 break; 576 577 case FIELD: 578 r = (t->symvalue.field.length + 7) div 8; 579 break; 580 581 case RECORD: 582 case VARNT: 583 r = t->symvalue.offset; 584 if (r == 0 and t->chain != nil) { 585 panic("missing size information for record"); 586 } 587 break; 588 589 case PTR: 590 case FILET: 591 r = sizeof(Word); 592 break; 593 594 case SCAL: 595 if (t->symvalue.iconval > 255) { 596 r = sizeof(short); 597 } else { 598 r = sizeof(char); 599 } 600 break; 601 602 case FPROC: 603 case FFUNC: 604 r = sizeof(Word); 605 break; 606 607 case PROC: 608 case FUNC: 609 case MODULE: 610 case PROG: 611 r = sizeof(Symbol); 612 break; 613 614 default: 615 if (ord(t->class) > ord(TYPEREF)) { 616 panic("size: bad class (%d)", ord(t->class)); 617 } else { 618 error("improper operation on a %s", classname(t)); 619 } 620 /* NOTREACHED */ 621 } 622 return r; 623 } 624 625 /* 626 * Test if a symbol is a parameter. This is true if there 627 * is a cycle from s->block to s via chain pointers. 628 */ 629 630 public Boolean isparam(s) 631 Symbol s; 632 { 633 register Symbol t; 634 635 t = s->block; 636 while (t != nil and t != s) { 637 t = t->chain; 638 } 639 return (Boolean) (t != nil); 640 } 641 642 /* 643 * Test if a symbol is a var parameter, i.e. has class REF. 644 */ 645 646 public Boolean isvarparam(s) 647 Symbol s; 648 { 649 return (Boolean) (s->class == REF); 650 } 651 652 /* 653 * Test if a symbol is a variable (actually any addressible quantity 654 * with do). 655 */ 656 657 public Boolean isvariable(s) 658 register Symbol s; 659 { 660 return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 661 } 662 663 /* 664 * Test if a symbol is a block, e.g. function, procedure, or the 665 * main program. 666 * 667 * This function is now expanded inline for efficiency. 668 * 669 * public Boolean isblock(s) 670 register Symbol s; 671 { 672 return (Boolean) ( 673 s->class == FUNC or s->class == PROC or 674 s->class == MODULE or s->class == PROG 675 ); 676 } 677 * 678 */ 679 680 /* 681 * Test if a symbol is a module. 682 */ 683 684 public Boolean ismodule(s) 685 register Symbol s; 686 { 687 return (Boolean) (s->class == MODULE); 688 } 689 690 /* 691 * Test if a symbol is builtin, that is, a predefined type or 692 * reserved word. 693 */ 694 695 public Boolean isbuiltin(s) 696 register Symbol s; 697 { 698 return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 699 } 700 701 /* 702 * Test if two types match. 703 * Equivalent names implies a match in any language. 704 * 705 * Special symbols must be handled with care. 706 */ 707 708 public Boolean compatible(t1, t2) 709 register Symbol t1, t2; 710 { 711 Boolean b; 712 713 if (t1 == t2) { 714 b = true; 715 } else if (t1 == nil or t2 == nil) { 716 b = false; 717 } else if (t1 == procsym) { 718 b = isblock(t2); 719 } else if (t2 == procsym) { 720 b = isblock(t1); 721 } else if (t1->language == nil) { 722 b = (Boolean) (t2->language == nil or 723 (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); 724 } else if (t2->language == nil) { 725 b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 726 } else if ( isbuiltin(t1) or isbuiltin(t1->type) ) { 727 b = (Boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2); 728 } else { 729 b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 730 } 731 return b; 732 } 733 734 /* 735 * Check for a type of the given name. 736 */ 737 738 public Boolean istypename(type, name) 739 Symbol type; 740 String name; 741 { 742 Symbol t; 743 Boolean b; 744 745 t = type; 746 checkref(t); 747 b = (Boolean) ( 748 t->class == TYPE and t->name == identname(name, true) 749 ); 750 return b; 751 } 752 753 /* 754 * Test if the name of a symbol is uniquely defined or not. 755 */ 756 757 public Boolean isambiguous(s) 758 register Symbol s; 759 { 760 register Symbol t; 761 762 find(t, s->name) where t != s endfind(t); 763 return (Boolean) (t != nil); 764 } 765 766 typedef char *Arglist; 767 768 #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 769 770 private Symbol mkstring(); 771 private Symbol namenode(); 772 773 /* 774 * Determine the type of a parse tree. 775 * Also make some symbol-dependent changes to the tree such as 776 * changing removing RVAL nodes for constant symbols. 777 */ 778 779 public assigntypes(p) 780 register Node p; 781 { 782 register Node p1; 783 register Symbol s; 784 785 switch (p->op) { 786 case O_SYM: 787 p->nodetype = namenode(p); 788 break; 789 790 case O_LCON: 791 p->nodetype = t_int; 792 break; 793 794 case O_FCON: 795 p->nodetype = t_real; 796 break; 797 798 case O_SCON: 799 p->value.scon = strdup(p->value.scon); 800 s = mkstring(p->value.scon); 801 if (s == t_char) { 802 p->op = O_LCON; 803 p->value.lcon = p->value.scon[0]; 804 } 805 p->nodetype = s; 806 break; 807 808 case O_INDIR: 809 p1 = p->value.arg[0]; 810 chkclass(p1, PTR); 811 p->nodetype = rtype(p1->nodetype)->type; 812 break; 813 814 case O_DOT: 815 p->nodetype = p->value.arg[1]->value.sym; 816 break; 817 818 case O_RVAL: 819 p1 = p->value.arg[0]; 820 p->nodetype = p1->nodetype; 821 if (p1->op == O_SYM) { 822 if (p1->nodetype->class == FUNC) { 823 p->op = O_CALL; 824 p->value.arg[1] = nil; 825 } else if (p1->value.sym->class == CONST) { 826 if (compatible(p1->value.sym->type, t_real)) { 827 p->op = O_FCON; 828 p->value.fcon = p1->value.sym->symvalue.fconval; 829 p->nodetype = t_real; 830 dispose(p1); 831 } else { 832 p->op = O_LCON; 833 p->value.lcon = p1->value.sym->symvalue.iconval; 834 p->nodetype = p1->value.sym->type; 835 dispose(p1); 836 } 837 } else if (isreg(p1->value.sym)) { 838 p->op = O_SYM; 839 p->value.sym = p1->value.sym; 840 dispose(p1); 841 } 842 } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 843 s = p1->value.arg[0]->value.sym; 844 if (isreg(s)) { 845 p1->op = O_SYM; 846 dispose(p1->value.arg[0]); 847 p1->value.sym = s; 848 p1->nodetype = s; 849 } 850 } 851 break; 852 853 /* 854 * Perform a cast if the call is of the form "type(expr)". 855 */ 856 case O_CALL: 857 p1 = p->value.arg[0]; 858 p->nodetype = rtype(p1->nodetype)->type; 859 break; 860 861 case O_TYPERENAME: 862 p->nodetype = p->value.arg[1]->nodetype; 863 break; 864 865 case O_ITOF: 866 p->nodetype = t_real; 867 break; 868 869 case O_NEG: 870 s = p->value.arg[0]->nodetype; 871 if (not compatible(s, t_int)) { 872 if (not compatible(s, t_real)) { 873 beginerrmsg(); 874 prtree(stderr, p->value.arg[0]); 875 fprintf(stderr, "is improper type"); 876 enderrmsg(); 877 } else { 878 p->op = O_NEGF; 879 } 880 } 881 p->nodetype = s; 882 break; 883 884 case O_ADD: 885 case O_SUB: 886 case O_MUL: 887 case O_LT: 888 case O_LE: 889 case O_GT: 890 case O_GE: 891 case O_EQ: 892 case O_NE: 893 { 894 Boolean t1real, t2real; 895 Symbol t1, t2; 896 897 t1 = rtype(p->value.arg[0]->nodetype); 898 t2 = rtype(p->value.arg[1]->nodetype); 899 t1real = compatible(t1, t_real); 900 t2real = compatible(t2, t_real); 901 if (t1real or t2real) { 902 p->op = (Operator) (ord(p->op) + 1); 903 if (not t1real) { 904 p->value.arg[0] = build(O_ITOF, p->value.arg[0]); 905 } else if (not t2real) { 906 p->value.arg[1] = build(O_ITOF, p->value.arg[1]); 907 } 908 } else { 909 if (t1real) { 910 convert(&(p->value.arg[0]), t_int, O_NOP); 911 } 912 if (t2real) { 913 convert(&(p->value.arg[1]), t_int, O_NOP); 914 } 915 } 916 if (ord(p->op) >= ord(O_LT)) { 917 p->nodetype = t_boolean; 918 } else { 919 if (t1real or t2real) { 920 p->nodetype = t_real; 921 } else { 922 p->nodetype = t_int; 923 } 924 } 925 break; 926 } 927 928 case O_DIVF: 929 convert(&(p->value.arg[0]), t_real, O_ITOF); 930 convert(&(p->value.arg[1]), t_real, O_ITOF); 931 p->nodetype = t_real; 932 break; 933 934 case O_DIV: 935 case O_MOD: 936 convert(&(p->value.arg[0]), t_int, O_NOP); 937 convert(&(p->value.arg[1]), t_int, O_NOP); 938 p->nodetype = t_int; 939 break; 940 941 case O_AND: 942 case O_OR: 943 chkboolean(p->value.arg[0]); 944 chkboolean(p->value.arg[1]); 945 p->nodetype = t_boolean; 946 break; 947 948 case O_QLINE: 949 p->nodetype = t_int; 950 break; 951 952 default: 953 p->nodetype = nil; 954 break; 955 } 956 } 957 958 /* 959 * Create a node for a name. The symbol for the name has already 960 * been chosen, either implicitly with "which" or explicitly from 961 * the dot routine. 962 */ 963 964 private Symbol namenode(p) 965 Node p; 966 { 967 register Symbol r, s; 968 register Node np; 969 970 s = p->value.sym; 971 if (s->class == REF) { 972 np = new(Node); 973 np->op = p->op; 974 np->nodetype = s; 975 np->value.sym = s; 976 p->op = O_INDIR; 977 p->value.arg[0] = np; 978 } 979 /* 980 * Old way 981 * 982 if (s->class == CONST or s->class == VAR or s->class == FVAR) { 983 r = s->type; 984 } else { 985 r = s; 986 } 987 * 988 */ 989 return s; 990 } 991 992 /* 993 * Convert a tree to a type via a conversion operator; 994 * if this isn't possible generate an error. 995 * 996 * Note the tree is call by address, hence the #define below. 997 */ 998 999 private convert(tp, typeto, op) 1000 Node *tp; 1001 Symbol typeto; 1002 Operator op; 1003 { 1004 #define tree (*tp) 1005 1006 Symbol s; 1007 1008 s = rtype(tree->nodetype); 1009 typeto = rtype(typeto); 1010 if (compatible(typeto, t_real) and compatible(s, t_int)) { 1011 tree = build(op, tree); 1012 } else if (not compatible(s, typeto)) { 1013 beginerrmsg(); 1014 prtree(stderr, s); 1015 fprintf(stderr, " is improper type"); 1016 enderrmsg(); 1017 } else if (op != O_NOP and s != typeto) { 1018 tree = build(op, tree); 1019 } 1020 1021 #undef tree 1022 } 1023 1024 /* 1025 * Construct a node for the dot operator. 1026 * 1027 * If the left operand is not a record, but rather a procedure 1028 * or function, then we interpret the "." as referencing an 1029 * "invisible" variable; i.e. a variable within a dynamically 1030 * active block but not within the static scope of the current procedure. 1031 */ 1032 1033 public Node dot(record, fieldname) 1034 Node record; 1035 Name fieldname; 1036 { 1037 register Node p; 1038 register Symbol s, t; 1039 1040 if (isblock(record->nodetype)) { 1041 find(s, fieldname) where 1042 s->block == record->nodetype and 1043 s->class != FIELD and s->class != TAG 1044 endfind(s); 1045 if (s == nil) { 1046 beginerrmsg(); 1047 fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 1048 printname(stderr, record->nodetype); 1049 enderrmsg(); 1050 } 1051 p = new(Node); 1052 p->op = O_SYM; 1053 p->value.sym = s; 1054 p->nodetype = namenode(p); 1055 } else { 1056 p = record; 1057 t = rtype(p->nodetype); 1058 if (t->class == PTR) { 1059 s = findfield(fieldname, t->type); 1060 } else { 1061 s = findfield(fieldname, t); 1062 } 1063 if (s == nil) { 1064 beginerrmsg(); 1065 fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 1066 prtree(stderr, record); 1067 enderrmsg(); 1068 } 1069 if (t->class == PTR and not isreg(record->nodetype)) { 1070 p = build(O_INDIR, record); 1071 } 1072 p = build(O_DOT, p, build(O_SYM, s)); 1073 } 1074 return p; 1075 } 1076 1077 /* 1078 * Return a tree corresponding to an array reference and do the 1079 * error checking. 1080 */ 1081 1082 public Node subscript(a, slist) 1083 Node a, slist; 1084 { 1085 Symbol t; 1086 1087 t = rtype(a->nodetype); 1088 if(t->language == nil) { 1089 error("unknown language"); 1090 } 1091 else { 1092 return ( (Node) 1093 (*language_op(t->language, L_BUILDAREF)) (a,slist) 1094 ); 1095 } 1096 } 1097 1098 /* 1099 * Evaluate a subscript index. 1100 */ 1101 1102 public int evalindex(s, i) 1103 Symbol s; 1104 long i; 1105 { 1106 Symbol t; 1107 1108 t = rtype(s); 1109 if(t->language == nil) { 1110 error("unknown language"); 1111 } 1112 else { 1113 return ( 1114 (*language_op(t->language, L_EVALAREF)) (s,i) 1115 ); 1116 } 1117 } 1118 1119 /* 1120 * Check to see if a tree is boolean-valued, if not it's an error. 1121 */ 1122 1123 public chkboolean(p) 1124 register Node p; 1125 { 1126 if (p->nodetype != t_boolean) { 1127 beginerrmsg(); 1128 fprintf(stderr, "found "); 1129 prtree(stderr, p); 1130 fprintf(stderr, ", expected boolean expression"); 1131 enderrmsg(); 1132 } 1133 } 1134 1135 /* 1136 * Check to make sure the given tree has a type of the given class. 1137 */ 1138 1139 private chkclass(p, class) 1140 Node p; 1141 Symclass class; 1142 { 1143 struct Symbol tmpsym; 1144 1145 tmpsym.class = class; 1146 if (rtype(p->nodetype)->class != class) { 1147 beginerrmsg(); 1148 fprintf(stderr, "\""); 1149 prtree(stderr, p); 1150 fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 1151 enderrmsg(); 1152 } 1153 } 1154 1155 /* 1156 * Construct a node for the type of a string. While we're at it, 1157 * scan the string for '' that collapse to ', and chop off the ends. 1158 */ 1159 1160 private Symbol mkstring(str) 1161 String str; 1162 { 1163 register char *p, *q; 1164 register Symbol s; 1165 1166 p = str; 1167 q = str; 1168 while (*p != '\0') { 1169 if (*p == '\\') { 1170 ++p; 1171 } 1172 *q = *p; 1173 ++p; 1174 ++q; 1175 } 1176 *q = '\0'; 1177 s = newSymbol(nil, 0, ARRAY, t_char, nil); 1178 s->language = findlanguage(".s"); 1179 s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1180 s->chain->language = s->language; 1181 s->chain->symvalue.rangev.lower = 1; 1182 s->chain->symvalue.rangev.upper = p - str + 1; 1183 return s; 1184 } 1185 1186 /* 1187 * Free up the space allocated for a string type. 1188 */ 1189 1190 public unmkstring(s) 1191 Symbol s; 1192 { 1193 dispose(s->chain); 1194 } 1195 1196 /* 1197 * Figure out the "current" variable or function being referred to, 1198 * this is either the active one or the most visible from the 1199 * current scope. 1200 */ 1201 1202 public Symbol which(n) 1203 Name n; 1204 { 1205 register Symbol s, p, t, f; 1206 1207 find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 1208 if (s == nil) { 1209 s = lookup(n); 1210 } 1211 if (s == nil) { 1212 error("\"%s\" is not defined", ident(n)); 1213 } else if (s == program or isbuiltin(s)) { 1214 t = s; 1215 } else { 1216 /* 1217 * Old way 1218 * 1219 if (not isactive(program)) { 1220 f = program; 1221 } else { 1222 f = whatblock(pc); 1223 if (f == nil) { 1224 panic("no block for addr 0x%x", pc); 1225 } 1226 } 1227 * 1228 * Now start with curfunc. 1229 */ 1230 p = curfunc; 1231 do { 1232 find(t, n) where 1233 t->block == p and t->class != FIELD and t->class != TAG 1234 endfind(t); 1235 p = p->block; 1236 } while (t == nil and p != nil); 1237 if (t == nil) { 1238 t = s; 1239 } 1240 } 1241 return t; 1242 } 1243 1244 /* 1245 * Find the symbol which is has the same name and scope as the 1246 * given symbol but is of the given field. Return nil if there is none. 1247 */ 1248 1249 public Symbol findfield(fieldname, record) 1250 Name fieldname; 1251 Symbol record; 1252 { 1253 register Symbol t; 1254 1255 t = rtype(record)->chain; 1256 while (t != nil and t->name != fieldname) { 1257 t = t->chain; 1258 } 1259 return t; 1260 } 1261 1262 public Boolean getbound(s,off,type,valp) 1263 Symbol s; 1264 int off; 1265 Rangetype type; 1266 int *valp; 1267 { 1268 Frame frp; 1269 Address addr; 1270 Symbol cur; 1271 1272 if (not isactive(s->block)) { 1273 return(false); 1274 } 1275 cur = s->block; 1276 while (cur != nil and cur->class == MODULE) { /* WHY*/ 1277 cur = cur->block; 1278 } 1279 if(cur == nil) { 1280 cur = whatblock(pc); 1281 } 1282 frp = findframe(cur); 1283 if (frp == nil) { 1284 return(false); 1285 } 1286 if(type == R_TEMP) addr = locals_base(frp) + off; 1287 else if (type == R_ARG) addr = args_base(frp) + off; 1288 else return(false); 1289 dread(valp,addr,sizeof(long)); 1290 return(true); 1291 } 1292