xref: /plan9-contrib/sys/src/cmd/spin/vars.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
1 /***** spin: vars.c *****/
2 
3 /*
4  * This file is part of the public release of Spin. It is subject to the
5  * terms in the LICENSE file that is included in this source directory.
6  * Tool documentation is available at http://spinroot.com
7  */
8 
9 #include "spin.h"
10 #include "y.tab.h"
11 
12 extern char	GBuf[];
13 extern int	analyze, jumpsteps, nproc, nstop, columns, old_priority_rules;
14 extern int	lineno, depth, verbose, xspin, limited_vis, Pid_nr;
15 extern Lextok	*Xu_List;
16 extern Ordered	*all_names;
17 extern RunList	*X_lst, *LastX;
18 extern short	no_arrays, Have_claim, terse;
19 extern Symbol	*Fname;
20 
21 extern void	sr_buf(int, int, const char *);
22 extern void	sr_mesg(FILE *, int, int, const char *);
23 
24 static int	getglobal(Lextok *);
25 static int	setglobal(Lextok *, int);
26 static int	maxcolnr = 1;
27 
28 int
getval(Lextok * sn)29 getval(Lextok *sn)
30 {	Symbol *s = sn->sym;
31 
32 	if (strcmp(s->name, "_") == 0)
33 	{	non_fatal("attempt to read value of '_'", 0);
34 		return 0;
35 	}
36 	if (strcmp(s->name, "_last") == 0)
37 		return (LastX)?LastX->pid:0;
38 	if (strcmp(s->name, "_p") == 0)
39 		return (X_lst && X_lst->pc)?X_lst->pc->seqno:0;
40 	if (strcmp(s->name, "_pid") == 0)
41 	{	if (!X_lst) return 0;
42 		return X_lst->pid - Have_claim;
43 	}
44 	if (strcmp(s->name, "_priority") == 0)
45 	{	if (!X_lst) return 0;
46 
47 		if (old_priority_rules)
48 		{	non_fatal("cannot refer to _priority with -o6", (char *) 0);
49 			return 1;
50 		}
51 		return X_lst->priority;
52 	}
53 
54 	if (strcmp(s->name, "_nr_pr") == 0)
55 	{	return nproc-nstop;	/* new 3.3.10 */
56 	}
57 
58 	if (s->context && s->type)
59 	{	return getlocal(sn);
60 	}
61 
62 	if (!s->type)	/* not declared locally */
63 	{	s = lookup(s->name); /* try global */
64 		sn->sym = s;	/* fix it */
65 	}
66 
67 	return getglobal(sn);
68 }
69 
70 int
setval(Lextok * v,int n)71 setval(Lextok *v, int n)
72 {
73 	if (strcmp(v->sym->name, "_last") == 0
74 	||  strcmp(v->sym->name, "_p") == 0
75 	||  strcmp(v->sym->name, "_pid") == 0
76 	||  strcmp(v->sym->name, "_nr_qs") == 0
77 	||  strcmp(v->sym->name, "_nr_pr") == 0)
78 	{	non_fatal("illegal assignment to %s", v->sym->name);
79 	}
80 	if (strcmp(v->sym->name, "_priority") == 0)
81 	{	if (old_priority_rules)
82 		{	non_fatal("cannot refer to _priority with -o6", (char *) 0);
83 			return 1;
84 		}
85 		if (!X_lst)
86 		{	non_fatal("no context for _priority", (char *) 0);
87 			return 1;
88 		}
89 		X_lst->priority = n;
90 	}
91 
92 	if (v->sym->context && v->sym->type)
93 		return setlocal(v, n);
94 	if (!v->sym->type)
95 		v->sym = lookup(v->sym->name);
96 	return setglobal(v, n);
97 }
98 
99 void
rm_selfrefs(Symbol * s,Lextok * i)100 rm_selfrefs(Symbol *s, Lextok *i)
101 {
102 	if (!i) return;
103 
104 	if (i->ntyp == NAME
105 	&&  strcmp(i->sym->name, s->name) == 0
106 	&& (	(!i->sym->context && !s->context)
107 	   ||	( i->sym->context &&  s->context
108 		&& strcmp(i->sym->context->name, s->context->name) == 0)))
109 	{	lineno  = i->ln;
110 		Fname   = i->fn;
111 		non_fatal("self-reference initializing '%s'", s->name);
112 		i->ntyp = CONST;
113 		i->val  = 0;
114 	} else
115 	{	rm_selfrefs(s, i->lft);
116 		rm_selfrefs(s, i->rgt);
117 	}
118 }
119 
120 int
checkvar(Symbol * s,int n)121 checkvar(Symbol *s, int n)
122 {	int	i, oln = lineno;	/* calls on eval() change it */
123 	Symbol	*ofnm = Fname;
124 	Lextok  *z, *y;
125 
126 	if (!in_bound(s, n))
127 		return 0;
128 
129 	if (s->type == 0)
130 	{	non_fatal("undecl var %s (assuming int)", s->name);
131 		s->type = INT;
132 	}
133 	/* not a STRUCT */
134 	if (s->val == (int *) 0)	/* uninitialized */
135 	{	s->val = (int *) emalloc(s->nel*sizeof(int));
136 		z = s->ini;
137 		for (i = 0; i < s->nel; i++)
138 		{	if (z && z->ntyp == ',')
139 			{	y = z->lft;
140 				z = z->rgt;
141 			} else
142 			{	y = z;
143 			}
144 			if (s->type != CHAN)
145 			{	rm_selfrefs(s, y);
146 				s->val[i] = eval(y);
147 			} else if (!analyze)
148 			{	s->val[i] = qmake(s);
149 	}	}	}
150 	lineno = oln;
151 	Fname  = ofnm;
152 
153 	return 1;
154 }
155 
156 static int
getglobal(Lextok * sn)157 getglobal(Lextok *sn)
158 {	Symbol *s = sn->sym;
159 	int i, n = eval(sn->lft);
160 
161 	if (s->type == 0 && X_lst && (i = find_lab(s, X_lst->n, 0)))	/* getglobal */
162 	{	printf("findlab through getglobal on %s\n", s->name);
163 		return i;	/* can this happen? */
164 	}
165 	if (s->type == STRUCT)
166 	{	return Rval_struct(sn, s, 1); /* 1 = check init */
167 	}
168 	if (checkvar(s, n))
169 	{	return cast_val(s->type, s->val[n], s->nbits);
170 	}
171 	return 0;
172 }
173 
174 int
cast_val(int t,int v,int w)175 cast_val(int t, int v, int w)
176 {	int i=0; short s=0; unsigned int u=0;
177 
178 	if (t == PREDEF || t == INT || t == CHAN) i = v;	/* predef means _ */
179 	else if (t == SHORT) s = (short) v;
180 	else if (t == BYTE || t == MTYPE)  u = (unsigned char)v;
181 	else if (t == BIT)   u = (unsigned char)(v&1);
182 	else if (t == UNSIGNED)
183 	{	if (w == 0)
184 			fatal("cannot happen, cast_val", (char *)0);
185 	/*	u = (unsigned)(v& ((1<<w)-1));		problem when w=32	*/
186 		u = (unsigned)(v& (~0u>>(8*sizeof(unsigned)-w)));	/* doug */
187 	}
188 
189 	if (v != i+s+ (int) u)
190 	{	char buf[64]; sprintf(buf, "%d->%d (%d)", v, i+s+(int)u, t);
191 		non_fatal("value (%s) truncated in assignment", buf);
192 	}
193 	return (int)(i+s+(int)u);
194 }
195 
196 static int
setglobal(Lextok * v,int m)197 setglobal(Lextok *v, int m)
198 {
199 	if (v->sym->type == STRUCT)
200 	{	(void) Lval_struct(v, v->sym, 1, m);
201 	} else
202 	{	int n = eval(v->lft);
203 		if (checkvar(v->sym, n))
204 		{	int oval = v->sym->val[n];
205 			int nval = cast_val(v->sym->type, m, v->sym->nbits);
206 			v->sym->val[n] = nval;
207 			if (oval != nval)
208 			{	v->sym->setat = depth;
209 	}	}	}
210 	return 1;
211 }
212 
213 void
dumpclaims(FILE * fd,int pid,char * s)214 dumpclaims(FILE *fd, int pid, char *s)
215 {	Lextok *m; int cnt = 0; int oPid = Pid_nr;
216 
217 	for (m = Xu_List; m; m = m->rgt)
218 		if (strcmp(m->sym->name, s) == 0)
219 		{	cnt=1;
220 			break;
221 		}
222 	if (cnt == 0) return;
223 
224 	Pid_nr = pid;
225 	fprintf(fd, "#ifndef XUSAFE\n");
226 	for (m = Xu_List; m; m = m->rgt)
227 	{	if (strcmp(m->sym->name, s) != 0)
228 			continue;
229 		no_arrays = 1;
230 		putname(fd, "\t\tsetq_claim(", m->lft, 0, "");
231 		no_arrays = 0;
232 		fprintf(fd, ", %d, ", m->val);
233 		terse = 1;
234 		putname(fd, "\"", m->lft, 0, "\", h, ");
235 		terse = 0;
236 		fprintf(fd, "\"%s\");\n", s);
237 	}
238 	fprintf(fd, "#endif\n");
239 	Pid_nr = oPid;
240 }
241 
242 void
dumpglobals(void)243 dumpglobals(void)
244 {	Ordered *walk;
245 	static Lextok *dummy = ZN;
246 	Symbol *sp;
247 	int j;
248 
249 	if (!dummy)
250 		dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
251 
252 	for (walk = all_names; walk; walk = walk->next)
253 	{	sp = walk->entry;
254 		if (!sp->type || sp->context || sp->owner
255 		||  sp->type == PROCTYPE  || sp->type == PREDEF
256 		||  sp->type == CODE_FRAG || sp->type == CODE_DECL
257 		||  (sp->type == MTYPE && ismtype(sp->name)))
258 			continue;
259 
260 		if (sp->type == STRUCT)
261 		{	if ((verbose&4) && !(verbose&64)
262 			&&  (sp->setat < depth
263 			&&   jumpsteps != depth))
264 			{	continue;
265 			}
266 			dump_struct(sp, sp->name, 0);
267 			continue;
268 		}
269 		for (j = 0; j < sp->nel; j++)
270 		{	int prefetch;
271 			char *s = 0;
272 			if (sp->type == CHAN)
273 			{	doq(sp, j, 0);
274 				continue;
275 			}
276 			if ((verbose&4) && !(verbose&64)
277 			&&  (sp->setat < depth
278 			&&   jumpsteps != depth))
279 			{	continue;
280 			}
281 
282 			dummy->sym = sp;
283 			dummy->lft->val = j;
284 			/* in case of cast_val warnings, do this first: */
285 			prefetch = getglobal(dummy);
286 			printf("\t\t%s", sp->name);
287 			if (sp->nel > 1 || sp->isarray) printf("[%d]", j);
288 			printf(" = ");
289 			if (sp->type == MTYPE
290 			&&  sp->mtype_name)
291 			{	s = sp->mtype_name->name;
292 			}
293 			sr_mesg(stdout, prefetch, sp->type == MTYPE, s);
294 			printf("\n");
295 			if (limited_vis && (sp->hidden&2))
296 			{	int colpos;
297 				GBuf[0] = '\0';
298 				if (!xspin)
299 				{	if (columns == 2)
300 						sprintf(GBuf, "~G%s = ", sp->name);
301 					else
302 						sprintf(GBuf, "%s = ", sp->name);
303 				}
304 				sr_buf(prefetch, sp->type == MTYPE, s);
305 				if (sp->colnr == 0)
306 				{	sp->colnr = (unsigned char) maxcolnr;
307 					maxcolnr = 1+(maxcolnr%10);
308 				}
309 				colpos = nproc+sp->colnr-1;
310 				if (columns == 2)
311 				{	pstext(colpos, GBuf);
312 					continue;
313 				}
314 				if (!xspin)
315 				{	printf("\t\t%s\n", GBuf);
316 					continue;
317 				}
318 				printf("MSC: ~G %s %s\n", sp->name, GBuf);
319 				printf("%3d:\tproc %3d (TRACK) line   1 \"var\" ",
320 					depth, colpos);
321 				printf("(state 0)\t[printf('MSC: globvar\\\\n')]\n");
322 				printf("\t\t%s", sp->name);
323 				if (sp->nel > 1 || sp->isarray) printf("[%d]", j);
324 				printf(" = %s\n", GBuf);
325 	}	}	}
326 }
327 
328 void
dumplocal(RunList * r,int final)329 dumplocal(RunList *r, int final)
330 {	static Lextok *dummy = ZN;
331 	Symbol *z, *s;
332 	int i;
333 
334 	if (!r) return;
335 
336 	s = r->symtab;
337 
338 	if (!dummy)
339 	{	dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
340 	}
341 
342 	for (z = s; z; z = z->next)
343 	{	if (z->type == STRUCT)
344 		{	dump_struct(z, z->name, r);
345 			continue;
346 		}
347 		for (i = 0; i < z->nel; i++)
348 		{	char *t = 0;
349 			if (z->type == CHAN)
350 			{	doq(z, i, r);
351 				continue;
352 			}
353 
354 			if ((verbose&4) && !(verbose&64)
355 			&&  !final
356 			&&  (z->setat < depth
357 			&&   jumpsteps != depth))
358 			{	continue;
359 			}
360 
361 			dummy->sym = z;
362 			dummy->lft->val = i;
363 
364 			printf("\t\t%s(%d):%s",
365 				r->n->name, r->pid - Have_claim, z->name);
366 			if (z->nel > 1 || z->isarray) printf("[%d]", i);
367 			printf(" = ");
368 
369 			if (z->type == MTYPE
370 			&&  z->mtype_name)
371 			{	t = z->mtype_name->name;
372 			}
373 			sr_mesg(stdout, getval(dummy), z->type == MTYPE, t);
374 			printf("\n");
375 			if (limited_vis && (z->hidden&2))
376 			{	int colpos;
377 				GBuf[0] = '\0';
378 				if (!xspin)
379 				{	if (columns == 2)
380 					sprintf(GBuf, "~G%s(%d):%s = ",
381 					r->n->name, r->pid, z->name);
382 					else
383 					sprintf(GBuf, "%s(%d):%s = ",
384 					r->n->name, r->pid, z->name);
385 				}
386 				sr_buf(getval(dummy), z->type==MTYPE, t);
387 				if (z->colnr == 0)
388 				{	z->colnr = (unsigned char) maxcolnr;
389 					maxcolnr = 1+(maxcolnr%10);
390 				}
391 				colpos = nproc+z->colnr-1;
392 				if (columns == 2)
393 				{	pstext(colpos, GBuf);
394 					continue;
395 				}
396 				if (!xspin)
397 				{	printf("\t\t%s\n", GBuf);
398 					continue;
399 				}
400 				printf("MSC: ~G %s(%d):%s %s\n",
401 					r->n->name, r->pid, z->name, GBuf);
402 
403 				printf("%3d:\tproc %3d (TRACK) line   1 \"var\" ",
404 					depth, colpos);
405 				printf("(state 0)\t[printf('MSC: locvar\\\\n')]\n");
406 				printf("\t\t%s(%d):%s",
407 					r->n->name, r->pid, z->name);
408 				if (z->nel > 1 || z->isarray) printf("[%d]", i);
409 				printf(" = %s\n", GBuf);
410 	}	}	}
411 }
412