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