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