xref: /inferno-os/utils/cc/acid.c (revision 50b0dbb170df61467e42c7ea4deb0b5692d15f4c)
1 #include "cc.h"
2 
3 static char *kwd[] =
4 {
5 	"$adt", "$aggr", "$append", "$builtin", "$complex", "$defn",
6 	"$delete", "$do", "$else", "$eval", "$head", "$if",
7 	"$local", "$loop", "$return", "$tail", "$then",
8 	"$union", "$whatis", "$while",
9 };
10 
11 char*
12 amap(char *s)
13 {
14 	int i, bot, top, new;
15 
16 	bot = 0;
17 	top = bot + nelem(kwd) - 1;
18 	while(bot <= top){
19 		new = bot + (top - bot)/2;
20 		i = strcmp(kwd[new]+1, s);
21 		if(i == 0)
22 			return kwd[new];
23 
24 		if(i < 0)
25 			bot = new + 1;
26 		else
27 			top = new - 1;
28 	}
29 	return s;
30 }
31 
32 Sym*
33 acidsue(Type *t)
34 {
35 	int h;
36 	Sym *s;
37 
38 	if(t != T)
39 	for(h=0; h<nelem(hash); h++)
40 		for(s = hash[h]; s != S; s = s->link)
41 			if(s->suetag && s->suetag->link == t)
42 				return s;
43 	return 0;
44 }
45 
46 Sym*
47 acidfun(Type *t)
48 {
49 	int h;
50 	Sym *s;
51 
52 	for(h=0; h<nelem(hash); h++)
53 		for(s = hash[h]; s != S; s = s->link)
54 			if(s->type == t)
55 				return s;
56 	return 0;
57 }
58 
59 char	acidchar[NTYPE];
60 Init	acidcinit[] =
61 {
62 	TCHAR,		'C',	0,
63 	TUCHAR,		'b',	0,
64 	TSHORT,		'd',	0,
65 	TUSHORT,	'u',	0,
66 	TLONG,		'D',	0,
67 	TULONG,		'U',	0,
68 	TVLONG,		'V',	0,
69 	TUVLONG,	'W',	0,
70 	TFLOAT,		'f',	0,
71 	TDOUBLE,	'F',	0,
72 	TARRAY,		'a',	0,
73 	TIND,		'X',	0,
74 	-1,		0,	0,
75 };
76 
77 static void
78 acidinit(void)
79 {
80 	Init *p;
81 
82 	for(p=acidcinit; p->code >= 0; p++)
83 		acidchar[p->code] = p->value;
84 
85 	acidchar[TINT] = acidchar[TLONG];
86 	acidchar[TUINT] = acidchar[TULONG];
87 	if(types[TINT]->width != types[TLONG]->width) {
88 		acidchar[TINT] = acidchar[TSHORT];
89 		acidchar[TUINT] = acidchar[TUSHORT];
90 		if(types[TINT]->width != types[TSHORT]->width)
91 			warn(Z, "acidmember int not long or short");
92 	}
93 	if(types[TIND]->width == types[TUVLONG]->width)
94 		acidchar[TIND] = 'Y';
95 
96 }
97 
98 void
99 acidmember(Type *t, long off, int flag)
100 {
101 	Sym *s, *s1;
102 	Type *l;
103 	static int acidcharinit = 0;
104 
105 	if(acidcharinit == 0) {
106 		acidinit();
107 		acidcharinit = 1;
108 	}
109 	s = t->sym;
110 	switch(t->etype) {
111 	default:
112 		Bprint(&outbuf, "	T%d\n", t->etype);
113 		break;
114 
115 	case TIND:
116 		if(s == S)
117 			break;
118 		if(flag) {
119 			for(l=t; l->etype==TIND; l=l->link)
120 				;
121 			if(typesu[l->etype]) {
122 				s1 = acidsue(l->link);
123 				if(s1 != S) {
124 					Bprint(&outbuf, "	'A' %s %ld %s;\n",
125 						amap(s1->name),
126 						t->offset+off, amap(s->name));
127 					break;
128 				}
129 			}
130 		} else {
131 			Bprint(&outbuf,
132 				"\tprint(\"\t%s\t\", addr.%s\\X, \"\\n\");\n",
133 				amap(s->name), amap(s->name));
134 			break;
135 		}
136 
137 	case TINT:
138 	case TUINT:
139 	case TCHAR:
140 	case TUCHAR:
141 	case TSHORT:
142 	case TUSHORT:
143 	case TLONG:
144 	case TULONG:
145 	case TVLONG:
146 	case TUVLONG:
147 	case TFLOAT:
148 	case TDOUBLE:
149 	case TARRAY:
150 		if(s == S)
151 			break;
152 		if(flag) {
153 			Bprint(&outbuf, "	'%c' %ld %s;\n",
154 			acidchar[t->etype], t->offset+off, amap(s->name));
155 		} else {
156 			Bprint(&outbuf, "\tprint(\"\t%s\t\", addr.%s, \"\\n\");\n",
157 				amap(s->name), amap(s->name));
158 		}
159 		break;
160 
161 	case TSTRUCT:
162 	case TUNION:
163 		s1 = acidsue(t->link);
164 		if(s1 == S)
165 			break;
166 		if(flag) {
167 			if(s == S) {
168 				Bprint(&outbuf, "	{\n");
169 				for(l = t->link; l != T; l = l->down)
170 					acidmember(l, t->offset+off, flag);
171 				Bprint(&outbuf, "	};\n");
172 			} else {
173 				Bprint(&outbuf, "	%s %ld %s;\n",
174 					amap(s1->name),
175 					t->offset+off, amap(s->name));
176 			}
177 		} else {
178 			if(s != S) {
179 				Bprint(&outbuf, "\tprint(\"%s %s {\\n\");\n",
180 					amap(s1->name), amap(s->name));
181 				Bprint(&outbuf, "\t%s(addr.%s);\n",
182 					amap(s1->name), amap(s->name));
183 				Bprint(&outbuf, "\tprint(\"}\\n\");\n");
184 			} else {
185 				Bprint(&outbuf, "\tprint(\"%s {\\n\");\n",
186 					amap(s1->name));
187 				Bprint(&outbuf, "\t\t%s(addr+%ld);\n",
188 					amap(s1->name), t->offset+off);
189 				Bprint(&outbuf, "\tprint(\"}\\n\");\n");
190 			}
191 		}
192 		break;
193 	}
194 }
195 
196 void
197 acidtype(Type *t)
198 {
199 	Sym *s;
200 	Type *l;
201 	Io *i;
202 	int n;
203 	char *an;
204 
205 	if(!debug['a'])
206 		return;
207 	if(debug['a'] > 1) {
208 		n = 0;
209 		for(i=iostack; i; i=i->link)
210 			n++;
211 		if(n > 1)
212 			return;
213 	}
214 	s = acidsue(t->link);
215 	if(s == S)
216 		return;
217 	switch(t->etype) {
218 	default:
219 		Bprint(&outbuf, "T%d\n", t->etype);
220 		return;
221 
222 	case TUNION:
223 	case TSTRUCT:
224 		if(debug['s'])
225 			goto asmstr;
226 		an = amap(s->name);
227 		Bprint(&outbuf, "sizeof%s = %ld;\n", an, t->width);
228 		Bprint(&outbuf, "aggr %s\n{\n", an);
229 		for(l = t->link; l != T; l = l->down)
230 			acidmember(l, 0, 1);
231 		Bprint(&outbuf, "};\n\n");
232 
233 		Bprint(&outbuf, "defn\n%s(addr) {\n\tcomplex %s addr;\n", an, an);
234 		for(l = t->link; l != T; l = l->down)
235 			acidmember(l, 0, 0);
236 		Bprint(&outbuf, "};\n\n");
237 		break;
238 	asmstr:
239 		if(s == S)
240 			break;
241 		for(l = t->link; l != T; l = l->down)
242 			if(l->sym != S)
243 				Bprint(&outbuf, "#define\t%s.%s\t%ld\n",
244 					s->name,
245 					l->sym->name,
246 					l->offset);
247 		break;
248 	}
249 }
250 
251 void
252 acidvar(Sym *s)
253 {
254 	int n;
255 	Io *i;
256 	Type *t;
257 	Sym *s1, *s2;
258 
259 	if(!debug['a'] || debug['s'])
260 		return;
261 	if(debug['a'] > 1) {
262 		n = 0;
263 		for(i=iostack; i; i=i->link)
264 			n++;
265 		if(n > 1)
266 			return;
267 	}
268 	t = s->type;
269 	while(t && t->etype == TIND)
270 		t = t->link;
271 	if(t == T)
272 		return;
273 	if(t->etype == TENUM) {
274 		Bprint(&outbuf, "%s = ", amap(s->name));
275 		if(!typefd[t->etype])
276 			Bprint(&outbuf, "%lld;\n", s->vconst);
277 		else
278 			Bprint(&outbuf, "%f\n;", s->fconst);
279 		return;
280 	}
281 	if(!typesu[t->etype])
282 		return;
283 	s1 = acidsue(t->link);
284 	if(s1 == S)
285 		return;
286 	switch(s->class) {
287 	case CAUTO:
288 	case CPARAM:
289 		s2 = acidfun(thisfn);
290 		if(s2)
291 			Bprint(&outbuf, "complex %s %s:%s;\n",
292 				amap(s1->name), amap(s2->name), amap(s->name));
293 		break;
294 
295 	case CSTATIC:
296 	case CEXTERN:
297 	case CGLOBL:
298 	case CLOCAL:
299 		Bprint(&outbuf, "complex %s %s;\n",
300 			amap(s1->name), amap(s->name));
301 		break;
302 	}
303 }
304