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