|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)symbols.c 5.5 (Berkeley) 5/11/88";
9: #endif not lint
10:
11: static char rcsid[] = "$Header: symbols.c,v 1.4 88/04/02 01:29:03 donn Exp $";
12:
13: /*
14: * Symbol management.
15: */
16:
17: #include "defs.h"
18: #include "symbols.h"
19: #include "languages.h"
20: #include "printsym.h"
21: #include "tree.h"
22: #include "operators.h"
23: #include "eval.h"
24: #include "mappings.h"
25: #include "events.h"
26: #include "process.h"
27: #include "runtime.h"
28: #include "machine.h"
29: #include "names.h"
30:
31: #ifndef public
32: typedef struct Symbol *Symbol;
33:
34: #include "machine.h"
35: #include "names.h"
36: #include "languages.h"
37: #include "tree.h"
38:
39: /*
40: * Symbol classes
41: */
42:
43: typedef enum {
44: BADUSE, CONST, TYPE, VAR, ARRAY, OPENARRAY, DYNARRAY, SUBARRAY,
45: PTRFILE, RECORD, FIELD,
46: PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE,
47: LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT,
48: FPROC, FFUNC, MODULE, TAG, COMMON, EXTREF, TYPEREF
49: } Symclass;
50:
51: typedef enum { R_CONST, R_TEMP, R_ARG, R_ADJUST } Rangetype;
52:
53: #define INREG 0
54: #define STK 1
55: #define EXT 2
56:
57: typedef unsigned integer Storage;
58:
59: struct Symbol {
60: Name name;
61: Language language;
62: Symclass class : 8;
63: Storage storage : 2;
64: unsigned int level : 6; /* for variables stored on stack only */
65: Symbol type;
66: Symbol chain;
67: union {
68: Node constval; /* value of constant symbol */
69: int offset; /* variable address */
70: long iconval; /* integer constant value */
71: double fconval; /* floating constant value */
72: int ndims; /* no. of dimensions for dynamic/sub-arrays */
73: struct { /* field offset and size (both in bits) */
74: int offset;
75: int length;
76: } field;
77: struct { /* common offset and chain; used to relocate */
78: int offset; /* vars in global BSS */
79: Symbol chain;
80: } common;
81: struct { /* range bounds */
82: Rangetype lowertype : 16;
83: Rangetype uppertype : 16;
84: long lower;
85: long upper;
86: } rangev;
87: struct {
88: int offset : 16; /* offset for of function value */
89: Boolean src : 1; /* true if there is source line info */
90: Boolean inline : 1; /* true if no separate act. rec. */
91: Boolean intern : 1; /* internal calling sequence */
92: int unused : 13;
93: Address beginaddr; /* address of function code */
94: } funcv;
95: struct { /* variant record info */
96: int size;
97: Symbol vtorec;
98: Symbol vtag;
99: } varnt;
100: String typeref; /* type defined by "<module>:<type>" */
101: Symbol extref; /* indirect symbol for external reference */
102: } symvalue;
103: Symbol block; /* symbol containing this symbol */
104: Symbol next_sym; /* hash chain */
105: };
106:
107: /*
108: * Basic types.
109: */
110:
111: Symbol t_boolean;
112: Symbol t_char;
113: Symbol t_int;
114: Symbol t_real;
115: Symbol t_nil;
116: Symbol t_addr;
117:
118: Symbol program;
119: Symbol curfunc;
120:
121: boolean showaggrs;
122:
123: #define symname(s) ident(s->name)
124: #define codeloc(f) ((f)->symvalue.funcv.beginaddr)
125: #define isblock(s) (Boolean) ( \
126: s->class == FUNC or s->class == PROC or \
127: s->class == MODULE or s->class == PROG \
128: )
129: #define isroutine(s) (Boolean) ( \
130: s->class == FUNC or s->class == PROC \
131: )
132:
133: #define nosource(f) (not (f)->symvalue.funcv.src)
134: #define isinline(f) ((f)->symvalue.funcv.inline)
135:
136: #define isreg(s) (s->storage == INREG)
137:
138: #include "tree.h"
139:
140: /*
141: * Some macros to make finding a symbol with certain attributes.
142: */
143:
144: #define find(s, withname) \
145: { \
146: s = lookup(withname); \
147: while (s != nil and not (s->name == (withname) and
148:
149: #define where /* qualification */
150:
151: #define endfind(s) )) { \
152: s = s->next_sym; \
153: } \
154: }
155:
156: #endif
157:
158: /*
159: * Symbol table structure currently does not support deletions.
160: * Hash table size is a power of two to make hashing faster.
161: * Using a non-prime is ok since we aren't doing rehashing.
162: */
163:
164: #define HASHTABLESIZE 8192
165:
166: private Symbol hashtab[HASHTABLESIZE];
167:
168: #define hash(name) ((((unsigned) name) >> 2) & (HASHTABLESIZE - 1))
169:
170: /*
171: * Allocate a new symbol.
172: */
173:
174: #define SYMBLOCKSIZE 1000
175:
176: typedef struct Sympool {
177: struct Symbol sym[SYMBLOCKSIZE];
178: struct Sympool *prevpool;
179: } *Sympool;
180:
181: private Sympool sympool = nil;
182: private Integer nleft = 0;
183:
184: public Symbol symbol_alloc()
185: {
186: register Sympool newpool;
187:
188: if (nleft <= 0) {
189: newpool = new(Sympool);
190: bzero(newpool, sizeof(*newpool));
191: newpool->prevpool = sympool;
192: sympool = newpool;
193: nleft = SYMBLOCKSIZE;
194: }
195: --nleft;
196: return &(sympool->sym[nleft]);
197: }
198:
199: public symbol_dump (func)
200: Symbol func;
201: {
202: register Symbol s;
203: register integer i;
204:
205: printf(" symbols in %s \n",symname(func));
206: for (i = 0; i < HASHTABLESIZE; i++) {
207: for (s = hashtab[i]; s != nil; s = s->next_sym) {
208: if (s->block == func) {
209: psym(s);
210: }
211: }
212: }
213: }
214:
215: /*
216: * Free all the symbols currently allocated.
217: */
218:
219: public symbol_free()
220: {
221: Sympool s, t;
222: register Integer i;
223:
224: s = sympool;
225: while (s != nil) {
226: t = s->prevpool;
227: dispose(s);
228: s = t;
229: }
230: for (i = 0; i < HASHTABLESIZE; i++) {
231: hashtab[i] = nil;
232: }
233: sympool = nil;
234: nleft = 0;
235: }
236:
237: /*
238: * Create a new symbol with the given attributes.
239: */
240:
241: public Symbol newSymbol(name, blevel, class, type, chain)
242: Name name;
243: Integer blevel;
244: Symclass class;
245: Symbol type;
246: Symbol chain;
247: {
248: register Symbol s;
249:
250: s = symbol_alloc();
251: s->name = name;
252: s->language = primlang;
253: s->storage = EXT;
254: s->level = blevel;
255: s->class = class;
256: s->type = type;
257: s->chain = chain;
258: return s;
259: }
260:
261: /*
262: * Insert a symbol into the hash table.
263: */
264:
265: public Symbol insert(name)
266: Name name;
267: {
268: register Symbol s;
269: register unsigned int h;
270:
271: h = hash(name);
272: s = symbol_alloc();
273: s->name = name;
274: s->next_sym = hashtab[h];
275: hashtab[h] = s;
276: return s;
277: }
278:
279: /*
280: * Symbol lookup.
281: */
282:
283: public Symbol lookup(name)
284: Name name;
285: {
286: register Symbol s;
287: register unsigned int h;
288:
289: h = hash(name);
290: s = hashtab[h];
291: while (s != nil and s->name != name) {
292: s = s->next_sym;
293: }
294: return s;
295: }
296:
297: /*
298: * Delete a symbol from the symbol table.
299: */
300:
301: public delete (s)
302: Symbol s;
303: {
304: register Symbol t;
305: register unsigned int h;
306:
307: h = hash(s->name);
308: t = hashtab[h];
309: if (t == nil) {
310: panic("delete of non-symbol '%s'", symname(s));
311: } else if (t == s) {
312: hashtab[h] = s->next_sym;
313: } else {
314: while (t->next_sym != s) {
315: t = t->next_sym;
316: if (t == nil) {
317: panic("delete of non-symbol '%s'", symname(s));
318: }
319: }
320: t->next_sym = s->next_sym;
321: }
322: }
323:
324: /*
325: * Dump out all the variables associated with the given
326: * procedure, function, or program associated with the given stack frame.
327: *
328: * This is quite inefficient. We traverse the entire symbol table
329: * each time we're called. The assumption is that this routine
330: * won't be called frequently enough to merit improved performance.
331: */
332:
333: public dumpvars(f, frame)
334: Symbol f;
335: Frame frame;
336: {
337: register Integer i;
338: register Symbol s;
339:
340: for (i = 0; i < HASHTABLESIZE; i++) {
341: for (s = hashtab[i]; s != nil; s = s->next_sym) {
342: if (container(s) == f) {
343: if (should_print(s)) {
344: printv(s, frame);
345: putchar('\n');
346: } else if (s->class == MODULE) {
347: dumpvars(s, frame);
348: }
349: }
350: }
351: }
352: }
353:
354: /*
355: * Create a builtin type.
356: * Builtin types are circular in that btype->type->type = btype.
357: */
358:
359: private Symbol maketype(name, lower, upper)
360: String name;
361: long lower;
362: long upper;
363: {
364: register Symbol s;
365: Name n;
366:
367: if (name == nil) {
368: n = nil;
369: } else {
370: n = identname(name, true);
371: }
372: s = insert(n);
373: s->language = primlang;
374: s->level = 0;
375: s->class = TYPE;
376: s->type = nil;
377: s->chain = nil;
378: s->type = newSymbol(nil, 0, RANGE, s, nil);
379: s->type->symvalue.rangev.lower = lower;
380: s->type->symvalue.rangev.upper = upper;
381: return s;
382: }
383:
384: /*
385: * Create the builtin symbols.
386: */
387:
388: public symbols_init ()
389: {
390: Symbol s;
391:
392: t_boolean = maketype("$boolean", 0L, 1L);
393: t_int = maketype("$integer", 0x80000000L, 0x7fffffffL);
394: t_char = maketype("$char", 0L, 255L);
395: t_real = maketype("$real", 8L, 0L);
396: t_nil = maketype("$nil", 0L, 0L);
397: t_addr = insert(identname("$address", true));
398: t_addr->language = primlang;
399: t_addr->level = 0;
400: t_addr->class = TYPE;
401: t_addr->type = newSymbol(nil, 1, PTR, t_int, nil);
402: s = insert(identname("true", true));
403: s->class = CONST;
404: s->type = t_boolean;
405: s->symvalue.constval = build(O_LCON, 1L);
406: s->symvalue.constval->nodetype = t_boolean;
407: s = insert(identname("false", true));
408: s->class = CONST;
409: s->type = t_boolean;
410: s->symvalue.constval = build(O_LCON, 0L);
411: s->symvalue.constval->nodetype = t_boolean;
412: }
413:
414: /*
415: * Reduce type to avoid worrying about type names.
416: */
417:
418: public Symbol rtype(type)
419: Symbol type;
420: {
421: register Symbol t;
422:
423: t = type;
424: if (t != nil) {
425: if (t->class == VAR or t->class == CONST or
426: t->class == FIELD or t->class == REF
427: ) {
428: t = t->type;
429: }
430: if (t->class == TYPEREF) {
431: resolveRef(t);
432: }
433: while (t->class == TYPE or t->class == TAG) {
434: t = t->type;
435: if (t->class == TYPEREF) {
436: resolveRef(t);
437: }
438: }
439: }
440: return t;
441: }
442:
443: /*
444: * Find the end of a module name. Return nil if there is none
445: * in the given string.
446: */
447:
448: private String findModuleMark (s)
449: String s;
450: {
451: register char *p, *r;
452: register boolean done;
453:
454: p = s;
455: done = false;
456: do {
457: if (*p == ':') {
458: done = true;
459: r = p;
460: } else if (*p == '\0') {
461: done = true;
462: r = nil;
463: } else {
464: ++p;
465: }
466: } while (not done);
467: return r;
468: }
469:
470: /*
471: * Resolve a type reference by modifying to be the appropriate type.
472: *
473: * If the reference has a name, then it refers to an opaque type and
474: * the actual type is directly accessible. Otherwise, we must use
475: * the type reference string, which is of the form "module:{module:}name".
476: */
477:
478: public resolveRef (t)
479: Symbol t;
480: {
481: register char *p;
482: char *start;
483: Symbol s, m, outer;
484: Name n;
485:
486: if (t->name != nil) {
487: s = t;
488: } else {
489: start = t->symvalue.typeref;
490: outer = program;
491: p = findModuleMark(start);
492: while (p != nil) {
493: *p = '\0';
494: n = identname(start, true);
495: find(m, n) where m->block == outer endfind(m);
496: if (m == nil) {
497: p = nil;
498: outer = nil;
499: s = nil;
500: } else {
501: outer = m;
502: start = p + 1;
503: p = findModuleMark(start);
504: }
505: }
506: if (outer != nil) {
507: n = identname(start, true);
508: find(s, n) where s->block == outer endfind(s);
509: }
510: }
511: if (s != nil and s->type != nil) {
512: t->name = s->type->name;
513: t->class = s->type->class;
514: t->type = s->type->type;
515: t->chain = s->type->chain;
516: t->symvalue = s->type->symvalue;
517: t->block = s->type->block;
518: }
519: }
520:
521: public integer regnum (s)
522: Symbol s;
523: {
524: integer r;
525:
526: checkref(s);
527: if (s->storage == INREG) {
528: r = s->symvalue.offset;
529: } else {
530: r = -1;
531: }
532: return r;
533: }
534:
535: public Symbol container(s)
536: Symbol s;
537: {
538: checkref(s);
539: return s->block;
540: }
541:
542: public Node constval(s)
543: Symbol s;
544: {
545: checkref(s);
546: if (s->class != CONST) {
547: error("[internal error: constval(non-CONST)]");
548: }
549: return s->symvalue.constval;
550: }
551:
552: /*
553: * Return the object address of the given symbol.
554: *
555: * There are the following possibilities:
556: *
557: * globals - just take offset
558: * locals - take offset from locals base
559: * arguments - take offset from argument base
560: * register - offset is register number
561: */
562:
563: #define isglobal(s) (s->storage == EXT)
564: #define islocaloff(s) (s->storage == STK and s->symvalue.offset < 0)
565: #define isparamoff(s) (s->storage == STK and s->symvalue.offset >= 0)
566:
567: public Address address (s, frame)
568: Symbol s;
569: Frame frame;
570: {
571: register Frame frp;
572: register Address addr;
573: register Symbol cur;
574:
575: checkref(s);
576: if (not isactive(s->block)) {
577: error("\"%s\" is not currently defined", symname(s));
578: } else if (isglobal(s)) {
579: addr = s->symvalue.offset;
580: } else {
581: frp = frame;
582: if (frp == nil) {
583: cur = s->block;
584: while (cur != nil and cur->class == MODULE) {
585: cur = cur->block;
586: }
587: if (cur == nil) {
588: frp = nil;
589: } else {
590: frp = findframe(cur);
591: if (frp == nil) {
592: error("[internal error: unexpected nil frame for \"%s\"]",
593: symname(s)
594: );
595: }
596: }
597: }
598: if (islocaloff(s)) {
599: addr = locals_base(frp) + s->symvalue.offset;
600: } else if (isparamoff(s)) {
601: addr = args_base(frp) + s->symvalue.offset;
602: } else if (isreg(s)) {
603: addr = savereg(s->symvalue.offset, frp);
604: } else {
605: panic("address: bad symbol \"%s\"", symname(s));
606: }
607: }
608: return addr;
609: }
610:
611: /*
612: * Define a symbol used to access register values.
613: */
614:
615: public defregname (n, r)
616: Name n;
617: integer r;
618: {
619: Symbol s;
620:
621: s = insert(n);
622: s->language = t_addr->language;
623: s->class = VAR;
624: s->storage = INREG;
625: s->level = 3;
626: s->type = t_addr;
627: s->symvalue.offset = r;
628: }
629:
630: /*
631: * Resolve an "abstract" type reference.
632: *
633: * It is possible in C to define a pointer to a type, but never define
634: * the type in a particular source file. Here we try to resolve
635: * the type definition. This is problematic, it is possible to
636: * have multiple, different definitions for the same name type.
637: */
638:
639: public findtype(s)
640: Symbol s;
641: {
642: register Symbol t, u, prev;
643:
644: u = s;
645: prev = nil;
646: while (u != nil and u->class != BADUSE) {
647: if (u->name != nil) {
648: prev = u;
649: }
650: u = u->type;
651: }
652: if (prev == nil) {
653: error("couldn't find link to type reference");
654: }
655: t = lookup(prev->name);
656: while (t != nil and
657: not (
658: t != prev and t->name == prev->name and
659: t->block->class == MODULE and t->class == prev->class and
660: t->type != nil and t->type->type != nil and
661: t->type->type->class != BADUSE
662: )
663: ) {
664: t = t->next_sym;
665: }
666: if (t == nil) {
667: error("couldn't resolve reference");
668: } else {
669: prev->type = t->type;
670: }
671: }
672:
673: /*
674: * Find the size in bytes of the given type.
675: *
676: * This is probably the WRONG thing to do. The size should be kept
677: * as an attribute in the symbol information as is done for structures
678: * and fields. I haven't gotten around to cleaning this up yet.
679: */
680:
681: #define MAXUCHAR 255
682: #define MAXUSHORT 65535L
683: #define MINCHAR -128
684: #define MAXCHAR 127
685: #define MINSHORT -32768
686: #define MAXSHORT 32767
687:
688: public findbounds (u, lower, upper)
689: Symbol u;
690: long *lower, *upper;
691: {
692: Rangetype lbt, ubt;
693: long lb, ub;
694:
695: if (u->class == RANGE) {
696: lbt = u->symvalue.rangev.lowertype;
697: ubt = u->symvalue.rangev.uppertype;
698: lb = u->symvalue.rangev.lower;
699: ub = u->symvalue.rangev.upper;
700: if (lbt == R_ARG or lbt == R_TEMP) {
701: if (not getbound(u, lb, lbt, lower)) {
702: error("dynamic bounds not currently available");
703: }
704: } else {
705: *lower = lb;
706: }
707: if (ubt == R_ARG or ubt == R_TEMP) {
708: if (not getbound(u, ub, ubt, upper)) {
709: error("dynamic bounds not currently available");
710: }
711: } else {
712: *upper = ub;
713: }
714: } else if (u->class == SCAL) {
715: *lower = 0;
716: *upper = u->symvalue.iconval - 1;
717: } else {
718: error("[internal error: unexpected array bound type]");
719: }
720: }
721:
722: public integer size(sym)
723: Symbol sym;
724: {
725: register Symbol s, t, u;
726: register integer nel, elsize;
727: long lower, upper;
728: integer r, off, len;
729:
730: t = sym;
731: checkref(t);
732: if (t->class == TYPEREF) {
733: resolveRef(t);
734: }
735: switch (t->class) {
736: case RANGE:
737: lower = t->symvalue.rangev.lower;
738: upper = t->symvalue.rangev.upper;
739: if (upper == 0 and lower > 0) {
740: /* real */
741: r = lower;
742: } else if (lower > upper) {
743: /* unsigned long */
744: r = sizeof(long);
745: } else if (
746: (lower >= MINCHAR and upper <= MAXCHAR) or
747: (lower >= 0 and upper <= MAXUCHAR)
748: ) {
749: r = sizeof(char);
750: } else if (
751: (lower >= MINSHORT and upper <= MAXSHORT) or
752: (lower >= 0 and upper <= MAXUSHORT)
753: ) {
754: r = sizeof(short);
755: } else {
756: r = sizeof(long);
757: }
758: break;
759:
760: case ARRAY:
761: elsize = size(t->type);
762: nel = 1;
763: for (t = t->chain; t != nil; t = t->chain) {
764: u = rtype(t);
765: findbounds(u, &lower, &upper);
766: nel *= (upper-lower+1);
767: }
768: r = nel*elsize;
769: break;
770:
771: case OPENARRAY:
772: case DYNARRAY:
773: r = (t->symvalue.ndims + 1) * sizeof(Word);
774: break;
775:
776: case SUBARRAY:
777: r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
778: break;
779:
780: case REF:
781: case VAR:
782: r = size(t->type);
783: /*
784: *
785: if (r < sizeof(Word) and isparam(t)) {
786: r = sizeof(Word);
787: }
788: */
789: break;
790:
791: case FVAR:
792: case CONST:
793: case TAG:
794: r = size(t->type);
795: break;
796:
797: case TYPE:
798: /*
799: * This causes problems on the IRIS because of the compiler bug
800: * with stab offsets for parameters. Not sure it's really
801: * necessary anyway.
802: */
803: # ifndef IRIS
804: if (t->type->class == PTR and t->type->type->class == BADUSE) {
805: findtype(t);
806: }
807: # endif
808: r = size(t->type);
809: break;
810:
811: case FIELD:
812: off = t->symvalue.field.offset;
813: len = t->symvalue.field.length;
814: r = (off + len + 7) div 8 - (off div 8);
815: break;
816:
817: case RECORD:
818: case VARNT:
819: r = t->symvalue.offset;
820: if (r == 0 and t->chain != nil) {
821: panic("missing size information for record");
822: }
823: break;
824:
825: case PTR:
826: case TYPEREF:
827: case FILET:
828: r = sizeof(Word);
829: break;
830:
831: case SCAL:
832: r = sizeof(Word);
833: /*
834: *
835: if (t->symvalue.iconval > 255) {
836: r = sizeof(short);
837: } else {
838: r = sizeof(char);
839: }
840: *
841: */
842: break;
843:
844: case FPROC:
845: case FFUNC:
846: r = sizeof(Word);
847: break;
848:
849: case PROC:
850: case FUNC:
851: case MODULE:
852: case PROG:
853: r = sizeof(Symbol);
854: break;
855:
856: case SET:
857: u = rtype(t->type);
858: switch (u->class) {
859: case RANGE:
860: r = u->symvalue.rangev.upper - u->symvalue.rangev.lower + 1;
861: break;
862:
863: case SCAL:
864: r = u->symvalue.iconval;
865: break;
866:
867: default:
868: error("expected range for set base type");
869: break;
870: }
871: r = (r + BITSPERBYTE - 1) div BITSPERBYTE;
872: break;
873:
874: /*
875: * These can happen in C (unfortunately) for unresolved type references
876: * Assume they are pointers.
877: */
878: case BADUSE:
879: r = sizeof(Address);
880: break;
881:
882: default:
883: if (ord(t->class) > ord(TYPEREF)) {
884: panic("size: bad class (%d)", ord(t->class));
885: } else {
886: fprintf(stderr, "can't compute size of a %s\n", classname(t));
887: }
888: r = 0;
889: break;
890: }
891: return r;
892: }
893:
894: /*
895: * Return the size associated with a symbol that takes into account
896: * reference parameters. This might be better as the normal size function, but
897: * too many places already depend on it working the way it does.
898: */
899:
900: public integer psize (s)
901: Symbol s;
902: {
903: integer r;
904: Symbol t;
905:
906: if (s->class == REF) {
907: t = rtype(s->type);
908: if (t->class == OPENARRAY) {
909: r = (t->symvalue.ndims + 1) * sizeof(Word);
910: } else if (t->class == SUBARRAY) {
911: r = (2 * t->symvalue.ndims + 1) * sizeof(Word);
912: } else {
913: r = sizeof(Word);
914: }
915: } else {
916: r = size(s);
917: }
918: return r;
919: }
920:
921: /*
922: * Test if a symbol is a parameter. This is true if there
923: * is a cycle from s->block to s via chain pointers.
924: */
925:
926: public Boolean isparam(s)
927: Symbol s;
928: {
929: register Symbol t;
930:
931: t = s->block;
932: while (t != nil and t != s) {
933: t = t->chain;
934: }
935: return (Boolean) (t != nil);
936: }
937:
938: /*
939: * Test if a type is an open array parameter type.
940: */
941:
942: public boolean isopenarray (type)
943: Symbol type;
944: {
945: Symbol t;
946:
947: t = rtype(type);
948: return (boolean) (t->class == OPENARRAY);
949: }
950:
951: /*
952: * Test if a symbol is a var parameter, i.e. has class REF.
953: */
954:
955: public Boolean isvarparam(s)
956: Symbol s;
957: {
958: return (Boolean) (s->class == REF);
959: }
960:
961: /*
962: * Test if a symbol is a variable (actually any addressible quantity
963: * with do).
964: */
965:
966: public Boolean isvariable(s)
967: Symbol s;
968: {
969: return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF);
970: }
971:
972: /*
973: * Test if a symbol is a constant.
974: */
975:
976: public Boolean isconst(s)
977: Symbol s;
978: {
979: return (Boolean) (s->class == CONST);
980: }
981:
982: /*
983: * Test if a symbol is a module.
984: */
985:
986: public Boolean ismodule(s)
987: register Symbol s;
988: {
989: return (Boolean) (s->class == MODULE);
990: }
991:
992: /*
993: * Mark a procedure or function as internal, meaning that it is called
994: * with a different calling sequence.
995: */
996:
997: public markInternal (s)
998: Symbol s;
999: {
1000: s->symvalue.funcv.intern = true;
1001: }
1002:
1003: public boolean isinternal (s)
1004: Symbol s;
1005: {
1006: return s->symvalue.funcv.intern;
1007: }
1008:
1009: /*
1010: * Decide if a field begins or ends on a bit rather than byte boundary.
1011: */
1012:
1013: public Boolean isbitfield(s)
1014: register Symbol s;
1015: {
1016: boolean b;
1017: register integer off, len;
1018: register Symbol t;
1019:
1020: off = s->symvalue.field.offset;
1021: len = s->symvalue.field.length;
1022: if ((off mod BITSPERBYTE) != 0 or (len mod BITSPERBYTE) != 0) {
1023: b = true;
1024: } else {
1025: t = rtype(s->type);
1026: b = (Boolean) (
1027: (t->class == SCAL and len != (sizeof(int)*BITSPERBYTE)) or
1028: len != (size(t)*BITSPERBYTE)
1029: );
1030: }
1031: return b;
1032: }
1033:
1034: private boolean primlang_typematch (t1, t2)
1035: Symbol t1, t2;
1036: {
1037: return (boolean) (
1038: (t1 == t2) or
1039: (
1040: t1->class == RANGE and t2->class == RANGE and
1041: t1->symvalue.rangev.lower == t2->symvalue.rangev.lower and
1042: t1->symvalue.rangev.upper == t2->symvalue.rangev.upper
1043: ) or (
1044: t1->class == PTR and t2->class == RANGE and
1045: t2->symvalue.rangev.upper >= t2->symvalue.rangev.lower
1046: ) or (
1047: t2->class == PTR and t1->class == RANGE and
1048: t1->symvalue.rangev.upper >= t1->symvalue.rangev.lower
1049: )
1050: );
1051: }
1052:
1053: /*
1054: * Test if two types match.
1055: * Equivalent names implies a match in any language.
1056: *
1057: * Special symbols must be handled with care.
1058: */
1059:
1060: public Boolean compatible(t1, t2)
1061: register Symbol t1, t2;
1062: {
1063: Boolean b;
1064: Symbol rt1, rt2;
1065:
1066: if (t1 == t2) {
1067: b = true;
1068: } else if (t1 == nil or t2 == nil) {
1069: b = false;
1070: } else if (t1 == procsym) {
1071: b = isblock(t2);
1072: } else if (t2 == procsym) {
1073: b = isblock(t1);
1074: } else if (t1->language == nil) {
1075: if (t2->language == nil) {
1076: b = false;
1077: } else if (t2->language == primlang) {
1078: b = (boolean) primlang_typematch(rtype(t1), rtype(t2));
1079: } else {
1080: b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
1081: }
1082: } else if (t1->language == primlang) {
1083: if (t2->language == primlang or t2->language == nil) {
1084: b = primlang_typematch(rtype(t1), rtype(t2));
1085: } else {
1086: b = (boolean) (*language_op(t2->language, L_TYPEMATCH))(t1, t2);
1087: }
1088: } else {
1089: b = (boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2);
1090: }
1091: return b;
1092: }
1093:
1094: /*
1095: * Check for a type of the given name.
1096: */
1097:
1098: public Boolean istypename(type, name)
1099: Symbol type;
1100: String name;
1101: {
1102: register Symbol t;
1103: Boolean b;
1104:
1105: t = type;
1106: if (t == nil) {
1107: b = false;
1108: } else {
1109: b = (Boolean) (
1110: t->class == TYPE and streq(ident(t->name), name)
1111: );
1112: }
1113: return b;
1114: }
1115:
1116: /*
1117: * Determine if a (value) parameter should actually be passed by address.
1118: */
1119:
1120: public boolean passaddr (p, exprtype)
1121: Symbol p, exprtype;
1122: {
1123: boolean b;
1124: Language def;
1125:
1126: if (p == nil) {
1127: def = findlanguage(".c");
1128: b = (boolean) (*language_op(def, L_PASSADDR))(p, exprtype);
1129: } else if (p->language == nil or p->language == primlang) {
1130: b = false;
1131: } else if (isopenarray(p->type)) {
1132: b = true;
1133: } else {
1134: b = (boolean) (*language_op(p->language, L_PASSADDR))(p, exprtype);
1135: }
1136: return b;
1137: }
1138:
1139: /*
1140: * Test if the name of a symbol is uniquely defined or not.
1141: */
1142:
1143: public Boolean isambiguous(s)
1144: register Symbol s;
1145: {
1146: register Symbol t;
1147:
1148: find(t, s->name) where t != s endfind(t);
1149: return (Boolean) (t != nil);
1150: }
1151:
1152: typedef char *Arglist;
1153:
1154: #define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
1155:
1156: private Symbol mkstring();
1157:
1158: /*
1159: * Determine the type of a parse tree.
1160: *
1161: * Also make some symbol-dependent changes to the tree such as
1162: * removing indirection for constant or register symbols.
1163: */
1164:
1165: public assigntypes (p)
1166: register Node p;
1167: {
1168: register Node p1;
1169: register Symbol s;
1170:
1171: switch (p->op) {
1172: case O_SYM:
1173: p->nodetype = p->value.sym;
1174: break;
1175:
1176: case O_LCON:
1177: p->nodetype = t_int;
1178: break;
1179:
1180: case O_CCON:
1181: p->nodetype = t_char;
1182: break;
1183:
1184: case O_FCON:
1185: p->nodetype = t_real;
1186: break;
1187:
1188: case O_SCON:
1189: p->nodetype = mkstring(p->value.scon);
1190: break;
1191:
1192: case O_INDIR:
1193: p1 = p->value.arg[0];
1194: s = rtype(p1->nodetype);
1195: if (s->class != PTR) {
1196: beginerrmsg();
1197: fprintf(stderr, "\"");
1198: prtree(stderr, p1);
1199: fprintf(stderr, "\" is not a pointer");
1200: enderrmsg();
1201: }
1202: p->nodetype = rtype(p1->nodetype)->type;
1203: break;
1204:
1205: case O_DOT:
1206: p->nodetype = p->value.arg[1]->value.sym;
1207: break;
1208:
1209: case O_RVAL:
1210: p1 = p->value.arg[0];
1211: p->nodetype = p1->nodetype;
1212: if (p1->op == O_SYM) {
1213: if (p1->nodetype->class == PROC or p->nodetype->class == FUNC) {
1214: p->op = p1->op;
1215: p->value.sym = p1->value.sym;
1216: p->nodetype = p1->nodetype;
1217: dispose(p1);
1218: } else if (p1->value.sym->class == CONST) {
1219: p->op = p1->op;
1220: p->value = p1->value;
1221: p->nodetype = p1->nodetype;
1222: dispose(p1);
1223: } else if (isreg(p1->value.sym)) {
1224: p->op = O_SYM;
1225: p->value.sym = p1->value.sym;
1226: dispose(p1);
1227: }
1228: } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) {
1229: s = p1->value.arg[0]->value.sym;
1230: if (isreg(s)) {
1231: p1->op = O_SYM;
1232: dispose(p1->value.arg[0]);
1233: p1->value.sym = s;
1234: p1->nodetype = s;
1235: }
1236: }
1237: break;
1238:
1239: case O_COMMA:
1240: p->nodetype = p->value.arg[0]->nodetype;
1241: break;
1242:
1243: case O_CALLPROC:
1244: case O_CALL:
1245: p1 = p->value.arg[0];
1246: p->nodetype = rtype(p1->nodetype)->type;
1247: break;
1248:
1249: case O_TYPERENAME:
1250: p->nodetype = p->value.arg[1]->nodetype;
1251: break;
1252:
1253: case O_ITOF:
1254: p->nodetype = t_real;
1255: break;
1256:
1257: case O_NEG:
1258: s = p->value.arg[0]->nodetype;
1259: if (not compatible(s, t_int)) {
1260: if (not compatible(s, t_real)) {
1261: beginerrmsg();
1262: fprintf(stderr, "\"");
1263: prtree(stderr, p->value.arg[0]);
1264: fprintf(stderr, "\" is improper type");
1265: enderrmsg();
1266: } else {
1267: p->op = O_NEGF;
1268: }
1269: }
1270: p->nodetype = s;
1271: break;
1272:
1273: case O_ADD:
1274: case O_SUB:
1275: case O_MUL:
1276: binaryop(p, nil);
1277: break;
1278:
1279: case O_LT:
1280: case O_LE:
1281: case O_GT:
1282: case O_GE:
1283: case O_EQ:
1284: case O_NE:
1285: binaryop(p, t_boolean);
1286: break;
1287:
1288: case O_DIVF:
1289: convert(&(p->value.arg[0]), t_real, O_ITOF);
1290: convert(&(p->value.arg[1]), t_real, O_ITOF);
1291: p->nodetype = t_real;
1292: break;
1293:
1294: case O_DIV:
1295: case O_MOD:
1296: convert(&(p->value.arg[0]), t_int, O_NOP);
1297: convert(&(p->value.arg[1]), t_int, O_NOP);
1298: p->nodetype = t_int;
1299: break;
1300:
1301: case O_AND:
1302: case O_OR:
1303: chkboolean(p->value.arg[0]);
1304: chkboolean(p->value.arg[1]);
1305: p->nodetype = t_boolean;
1306: break;
1307:
1308: case O_QLINE:
1309: p->nodetype = t_int;
1310: break;
1311:
1312: default:
1313: p->nodetype = nil;
1314: break;
1315: }
1316: }
1317:
1318: /*
1319: * Process a binary arithmetic or relational operator.
1320: * Convert from integer to real if necessary.
1321: */
1322:
1323: private binaryop (p, t)
1324: Node p;
1325: Symbol t;
1326: {
1327: Node p1, p2;
1328: Boolean t1real, t2real;
1329: Symbol t1, t2;
1330:
1331: p1 = p->value.arg[0];
1332: p2 = p->value.arg[1];
1333: t1 = rtype(p1->nodetype);
1334: t2 = rtype(p2->nodetype);
1335: t1real = compatible(t1, t_real);
1336: t2real = compatible(t2, t_real);
1337: if (t1real or t2real) {
1338: p->op = (Operator) (ord(p->op) + 1);
1339: if (not t1real) {
1340: p->value.arg[0] = build(O_ITOF, p1);
1341: } else if (not t2real) {
1342: p->value.arg[1] = build(O_ITOF, p2);
1343: }
1344: p->nodetype = t_real;
1345: } else {
1346: if (size(p1->nodetype) > sizeof(integer)) {
1347: beginerrmsg();
1348: fprintf(stderr, "operation not defined on \"");
1349: prtree(stderr, p1);
1350: fprintf(stderr, "\"");
1351: enderrmsg();
1352: } else if (size(p2->nodetype) > sizeof(integer)) {
1353: beginerrmsg();
1354: fprintf(stderr, "operation not defined on \"");
1355: prtree(stderr, p2);
1356: fprintf(stderr, "\"");
1357: enderrmsg();
1358: }
1359: p->nodetype = t_int;
1360: }
1361: if (t != nil) {
1362: p->nodetype = t;
1363: }
1364: }
1365:
1366: /*
1367: * Convert a tree to a type via a conversion operator;
1368: * if this isn't possible generate an error.
1369: */
1370:
1371: private convert(tp, typeto, op)
1372: Node *tp;
1373: Symbol typeto;
1374: Operator op;
1375: {
1376: Node tree;
1377: Symbol s, t;
1378:
1379: tree = *tp;
1380: s = rtype(tree->nodetype);
1381: t = rtype(typeto);
1382: if (compatible(t, t_real) and compatible(s, t_int)) {
1383: /* we can convert int => floating but not the reverse */
1384: tree = build(op, tree);
1385: } else if (not compatible(s, t)) {
1386: beginerrmsg();
1387: prtree(stderr, tree);
1388: fprintf(stderr, ": illegal type in operation");
1389: enderrmsg();
1390: }
1391: *tp = tree;
1392: }
1393:
1394: /*
1395: * Construct a node for the dot operator.
1396: *
1397: * If the left operand is not a record, but rather a procedure
1398: * or function, then we interpret the "." as referencing an
1399: * "invisible" variable; i.e. a variable within a dynamically
1400: * active block but not within the static scope of the current procedure.
1401: */
1402:
1403: public Node dot(record, fieldname)
1404: Node record;
1405: Name fieldname;
1406: {
1407: register Node rec, p;
1408: register Symbol s, t;
1409:
1410: rec = record;
1411: if (isblock(rec->nodetype)) {
1412: find(s, fieldname) where
1413: s->block == rec->nodetype and
1414: s->class != FIELD
1415: endfind(s);
1416: if (s == nil) {
1417: beginerrmsg();
1418: fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname));
1419: printname(stderr, rec->nodetype);
1420: enderrmsg();
1421: }
1422: p = new(Node);
1423: p->op = O_SYM;
1424: p->value.sym = s;
1425: p->nodetype = s;
1426: } else {
1427: p = rec;
1428: t = rtype(p->nodetype);
1429: if (t->class == PTR) {
1430: s = findfield(fieldname, t->type);
1431: } else {
1432: s = findfield(fieldname, t);
1433: }
1434: if (s == nil) {
1435: beginerrmsg();
1436: fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname));
1437: prtree(stderr, rec);
1438: enderrmsg();
1439: }
1440: if (t->class != PTR or isreg(rec->nodetype)) {
1441: p = unrval(p);
1442: }
1443: p->nodetype = t_addr;
1444: p = build(O_DOT, p, build(O_SYM, s));
1445: }
1446: return build(O_RVAL, p);
1447: }
1448:
1449: /*
1450: * Return a tree corresponding to an array reference and do the
1451: * error checking.
1452: */
1453:
1454: public Node subscript(a, slist)
1455: Node a, slist;
1456: {
1457: Symbol t;
1458: Node p;
1459:
1460: t = rtype(a->nodetype);
1461: if (t->language == nil or t->language == primlang) {
1462: p = (Node) (*language_op(findlanguage(".s"), L_BUILDAREF))(a, slist);
1463: } else {
1464: p = (Node) (*language_op(t->language, L_BUILDAREF))(a, slist);
1465: }
1466: return build(O_RVAL, p);
1467: }
1468:
1469: /*
1470: * Evaluate a subscript index.
1471: */
1472:
1473: public int evalindex(s, base, i)
1474: Symbol s;
1475: Address base;
1476: long i;
1477: {
1478: Symbol t;
1479: int r;
1480:
1481: t = rtype(s);
1482: if (t->language == nil or t->language == primlang) {
1483: r = ((*language_op(findlanguage(".s"), L_EVALAREF)) (s, base, i));
1484: } else {
1485: r = ((*language_op(t->language, L_EVALAREF)) (s, base, i));
1486: }
1487: return r;
1488: }
1489:
1490: /*
1491: * Check to see if a tree is boolean-valued, if not it's an error.
1492: */
1493:
1494: public chkboolean(p)
1495: register Node p;
1496: {
1497: if (p->nodetype != t_boolean) {
1498: beginerrmsg();
1499: fprintf(stderr, "found ");
1500: prtree(stderr, p);
1501: fprintf(stderr, ", expected boolean expression");
1502: enderrmsg();
1503: }
1504: }
1505:
1506: /*
1507: * Construct a node for the type of a string.
1508: */
1509:
1510: private Symbol mkstring(str)
1511: String str;
1512: {
1513: register Symbol s;
1514:
1515: s = newSymbol(nil, 0, ARRAY, t_char, nil);
1516: s->chain = newSymbol(nil, 0, RANGE, t_int, nil);
1517: s->chain->language = s->language;
1518: s->chain->symvalue.rangev.lower = 1;
1519: s->chain->symvalue.rangev.upper = strlen(str) + 1;
1520: return s;
1521: }
1522:
1523: /*
1524: * Free up the space allocated for a string type.
1525: */
1526:
1527: public unmkstring(s)
1528: Symbol s;
1529: {
1530: dispose(s->chain);
1531: }
1532:
1533: /*
1534: * Figure out the "current" variable or function being referred to
1535: * by the name n.
1536: */
1537:
1538: private boolean stwhich(), dynwhich();
1539:
1540: public Symbol which (n)
1541: Name n;
1542: {
1543: Symbol s;
1544:
1545: s = lookup(n);
1546: if (s == nil) {
1547: error("\"%s\" is not defined", ident(n));
1548: } else if (not stwhich(&s) and isambiguous(s) and not dynwhich(&s)) {
1549: printf("[using ");
1550: printname(stdout, s);
1551: printf("]\n");
1552: }
1553: return s;
1554: }
1555:
1556: /*
1557: * Static search.
1558: */
1559:
1560: private boolean stwhich (var_s)
1561: Symbol *var_s;
1562: {
1563: Name n; /* name of desired symbol */
1564: Symbol s; /* iteration variable for symbols with name n */
1565: Symbol f; /* iteration variable for blocks containing s */
1566: integer count; /* number of levels from s->block to curfunc */
1567: Symbol t; /* current best answer for stwhich(n) */
1568: integer mincount; /* relative level for current best answer (t) */
1569: boolean b; /* return value, true if symbol found */
1570:
1571: s = *var_s;
1572: n = s->name;
1573: t = s;
1574: mincount = 10000; /* force first match to set mincount */
1575: do {
1576: if (s->name == n and s->class != FIELD and s->class != TAG) {
1577: f = curfunc;
1578: count = 0;
1579: while (f != nil and f != s->block) {
1580: ++count;
1581: f = f->block;
1582: }
1583: if (f != nil and count < mincount) {
1584: t = s;
1585: mincount = count;
1586: b = true;
1587: }
1588: }
1589: s = s->next_sym;
1590: } while (s != nil);
1591: if (mincount != 10000) {
1592: *var_s = t;
1593: b = true;
1594: } else {
1595: b = false;
1596: }
1597: return b;
1598: }
1599:
1600: /*
1601: * Dynamic search.
1602: */
1603:
1604: private boolean dynwhich (var_s)
1605: Symbol *var_s;
1606: {
1607: Name n; /* name of desired symbol */
1608: Symbol s; /* iteration variable for possible symbols */
1609: Symbol f; /* iteration variable for active functions */
1610: Frame frp; /* frame associated with stack walk */
1611: boolean b; /* return value */
1612:
1613: f = curfunc;
1614: frp = curfuncframe();
1615: n = (*var_s)->name;
1616: b = false;
1617: if (frp != nil) {
1618: frp = nextfunc(frp, &f);
1619: while (frp != nil) {
1620: s = *var_s;
1621: while (s != nil and
1622: (
1623: s->name != n or s->block != f or
1624: s->class == FIELD or s->class == TAG
1625: )
1626: ) {
1627: s = s->next_sym;
1628: }
1629: if (s != nil) {
1630: *var_s = s;
1631: b = true;
1632: break;
1633: }
1634: if (f == program) {
1635: break;
1636: }
1637: frp = nextfunc(frp, &f);
1638: }
1639: }
1640: return b;
1641: }
1642:
1643: /*
1644: * Find the symbol that has the same name and scope as the
1645: * given symbol but is of the given field. Return nil if there is none.
1646: */
1647:
1648: public Symbol findfield (fieldname, record)
1649: Name fieldname;
1650: Symbol record;
1651: {
1652: register Symbol t;
1653:
1654: t = rtype(record)->chain;
1655: while (t != nil and t->name != fieldname) {
1656: t = t->chain;
1657: }
1658: return t;
1659: }
1660:
1661: public Boolean getbound(s,off,type,valp)
1662: Symbol s;
1663: int off;
1664: Rangetype type;
1665: int *valp;
1666: {
1667: Frame frp;
1668: Address addr;
1669: Symbol cur;
1670:
1671: if (not isactive(s->block)) {
1672: return(false);
1673: }
1674: cur = s->block;
1675: while (cur != nil and cur->class == MODULE) { /* WHY*/
1676: cur = cur->block;
1677: }
1678: if(cur == nil) {
1679: cur = whatblock(pc);
1680: }
1681: frp = findframe(cur);
1682: if (frp == nil) {
1683: return(false);
1684: }
1685: if(type == R_TEMP) addr = locals_base(frp) + off;
1686: else if (type == R_ARG) addr = args_base(frp) + off;
1687: else return(false);
1688: dread(valp,addr,sizeof(long));
1689: return(true);
1690: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.