|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)symbols.c 1.11 8/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.