xref: /aosp_15_r20/external/mesa3d/src/freedreno/rnn/rnn.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2010-2011 Marcin Kościelnicki <[email protected]>
3  * Copyright © 2010 Luca Barbieri <[email protected]>
4  * Copyright © 2010 Francisco Jerez <[email protected]>
5  * Copyright © 2010 Martin Peres <[email protected]>
6  * Copyright © 2010 Marcin Slusarz <[email protected]>
7  * All Rights Reserved.
8  * SPDX-License-Identifier: MIT
9  */
10 
11 /* workaround libxml2 silliness: */
12 #pragma GCC diagnostic ignored "-Wpointer-sign"
13 
14 #include <libxml/xmlversion.h>
15 #include <libxml/parser.h>
16 #include <libxml/xpath.h>
17 #include <libxml/xmlreader.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <limits.h>
21 #include <ctype.h>
22 #include <stdio.h>
23 #include "rnn.h"
24 #include "util.h"
25 
26 #include "util/u_debug.h"
27 
catstr(char * a,char * b)28 static char *catstr (char *a, char *b) {
29 	char *res;
30 
31 	if (!a)
32 		return b;
33 
34 	return asprintf(&res, "%s_%s", a, b) < 0 ? NULL : res;
35 }
36 
strdiff(const char * a,const char * b)37 static int strdiff (const char *a, const char *b) {
38 	if (!a && !b)
39 		return 0;
40 	if (!a || !b)
41 		return 1;
42 	return strcmp (a, b);
43 }
44 
45 static void rnn_err(struct rnndb *db, const char *format, ...) _util_printf_format(2, 3);
46 
rnn_err(struct rnndb * db,const char * format,...)47 static void rnn_err(struct rnndb *db, const char *format, ...)
48 {
49 	va_list ap;
50 	va_start(ap, format);
51 	vfprintf(stderr, format, ap);
52 	va_end(ap);
53 	db->estatus = 1;
54 }
55 
rnn_init(void)56 void rnn_init(void) {
57 	LIBXML_TEST_VERSION
58 	xmlInitParser();
59 }
60 
rnn_newdb(void)61 struct rnndb *rnn_newdb(void) {
62 	struct rnndb *db = calloc(sizeof *db, 1);
63 	return db;
64 }
65 
getcontent(xmlNode * attr)66 static char *getcontent (xmlNode *attr) {
67 	xmlNode *chain = attr->children;
68 	size_t size = 0;
69 	char *content, *p;
70 	while (chain) {
71 		if (chain->type == XML_TEXT_NODE)
72 			size += strlen(chain->content);
73 		chain = chain->next;
74 	}
75 	p = content = malloc(size + 1);
76 	chain = attr->children;
77 	while (chain) {
78 		if (chain->type == XML_TEXT_NODE) {
79 			char* sp = chain->content;
80 			if(p == content) {
81 				while(isspace(*sp))
82 					++sp;
83 			}
84 			size_t len = strlen(sp);
85 			memcpy(p, sp, len);
86 			p += len;
87 		}
88 		chain = chain->next;
89 	}
90 	while(p != content && isspace(p[-1]))
91 		--p;
92 	*p = 0;
93 	return content;
94 }
95 
getattrib(struct rnndb * db,char * file,int line,xmlAttr * attr)96 static char *getattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
97 	xmlNode *chain = attr->children;
98 	while (chain) {
99 		if (chain->type != XML_TEXT_NODE) {
100 			rnn_err(db, "%s:%d: unknown attribute child \"%s\" in attribute \"%s\"\n", file, line, chain->name, attr->name);
101 		} else {
102 			return chain->content;
103 		}
104 		chain = chain->next;
105 	}
106 	return "";
107 }
108 
getboolattrib(struct rnndb * db,char * file,int line,xmlAttr * attr)109 static int getboolattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
110 	char *c = getattrib(db, file, line, attr);
111 	if (!strcmp(c, "yes") || !strcmp(c, "1") || !strcmp(c, "true"))
112 		return 1;
113 	if (!strcmp(c, "no") || !strcmp(c, "0") || !strcmp(c, "false"))
114 		return 0;
115 	rnn_err(db, "%s:%d: invalid boolean value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
116 	return 0;
117 }
118 
getnum(struct rnndb * db,char * file,int line,xmlAttr * attr,char * c)119 static uint64_t getnum(struct rnndb *db, char *file, int line, xmlAttr *attr, char *c)
120 {
121 	char *cc;
122 	uint64_t res;
123 	if (strchr(c, 'x') || strchr(c, 'X'))
124 		res = strtoull(c, &cc, 16);
125 	else
126 		res = strtoull(c, &cc, 10);
127 	if (*cc)  {
128 		rnn_err(db, "%s:%d: invalid numeric value \"%s\" in attribute \"%s\"\n", file, line, c, attr->name);
129 	}
130 	return res;
131 }
132 
getnumattrib(struct rnndb * db,char * file,int line,xmlAttr * attr)133 static uint64_t getnumattrib (struct rnndb *db, char *file, int line, xmlAttr *attr) {
134 	char *c = getattrib(db, file, line, attr);
135 	return getnum(db, file, line, attr, c);
136 }
137 
138 static int trytop (struct rnndb *db, char *file, xmlNode *node);
139 
trydoc(struct rnndb * db,char * file,xmlNode * node)140 static int trydoc (struct rnndb *db, char *file, xmlNode *node) {
141 	if (!strcmp(node->name, "brief")) {
142 		return 1;
143 	} else if (!strcmp(node->name, "doc")) {
144 		return 1;
145 	}
146 	return 0;
147 }
148 
149 static struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node);
150 static struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node);
151 
trytypetag(struct rnndb * db,char * file,xmlNode * node,struct rnntypeinfo * ti)152 static int trytypetag (struct rnndb *db, char *file, xmlNode *node, struct rnntypeinfo *ti) {
153 	if (!strcmp(node->name, "value")) {
154 		struct rnnvalue *val = parsevalue(db, file, node);
155 		if (val)
156 			ADDARRAY(ti->vals, val);
157 		return 1;
158 	} else if (!strcmp(node->name, "bitfield")) {
159 		struct rnnbitfield *bf = parsebitfield(db, file, node);
160 		if (bf)
161 			ADDARRAY(ti->bitfields, bf);
162 		return 1;
163 	}
164 	return 0;
165 }
trytypeattr(struct rnndb * db,char * file,xmlNode * node,xmlAttr * attr,struct rnntypeinfo * ti)166 static int trytypeattr (struct rnndb *db, char *file, xmlNode *node, xmlAttr *attr, struct rnntypeinfo *ti) {
167 	if (!strcmp(attr->name, "shr")) {
168 		ti->shr = getnumattrib(db, file, node->line, attr);
169 		return 1;
170 	} else if (!strcmp(attr->name, "min")) {
171 		ti->min = getnumattrib(db, file, node->line, attr);
172 		ti->minvalid = 1;
173 		return 1;
174 	} else if (!strcmp(attr->name, "max")) {
175 		ti->max = getnumattrib(db, file, node->line, attr);
176 		ti->maxvalid = 1;
177 		return 1;
178 	} else if (!strcmp(attr->name, "align")) {
179 		ti->align = getnumattrib(db, file, node->line, attr);
180 		ti->alignvalid = 1;
181 		return 1;
182 	} else if (!strcmp(attr->name, "type")) {
183 		ti->name = strdup(getattrib(db, file, node->line, attr));;
184 		return 1;
185 	} else if (!strcmp(attr->name, "radix")) {
186 		ti->radix = getnumattrib(db, file, node->line, attr);
187 		ti->radixvalid = 1;
188 		return 1;
189 	} else if (!strcmp(attr->name, "pos")) {
190 		ti->high = ti->low = getnumattrib(db, file, node->line, attr);
191 		return 1;
192 	} else if (!strcmp(attr->name, "low")) {
193 		ti->low = getnumattrib(db, file, node->line, attr);
194 		return 1;
195 	} else if (!strcmp(attr->name, "high")) {
196 		ti->high = getnumattrib(db, file, node->line, attr);
197 		return 1;
198 	} else if (!strcmp(attr->name, "addvariant")) {
199 		ti->addvariant = getboolattrib(db, file, node->line, attr);
200 		return 1;
201 	}
202 	return 0;
203 }
204 
parsevalue(struct rnndb * db,char * file,xmlNode * node)205 static struct rnnvalue *parsevalue(struct rnndb *db, char *file, xmlNode *node) {
206 	struct rnnvalue *val = calloc(sizeof *val, 1);
207 	val->file = file;
208 	xmlAttr *attr = node->properties;
209 	while (attr) {
210 		if (!strcmp(attr->name, "name")) {
211 			val->name = strdup(getattrib(db, file, node->line, attr));
212 		} else if (!strcmp(attr->name, "value")) {
213 			val->value = getnumattrib(db, file, node->line, attr);
214 			val->valvalid = 1;
215 		} else if (!strcmp(attr->name, "varset")) {
216 			val->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
217 		} else if (!strcmp(attr->name, "variants")) {
218 			val->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
219 		} else {
220 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for value\n", file, node->line, attr->name);
221 		}
222 		attr = attr->next;
223 	}
224 	xmlNode *chain = node->children;
225 	while (chain) {
226 		if (chain->type != XML_ELEMENT_NODE) {
227 		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
228 			rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
229 		}
230 		chain = chain->next;
231 	}
232 	if (!val->name) {
233 		rnn_err(db, "%s:%d: nameless value\n", file, node->line);
234 		return 0;
235 	} else {
236 		return val;
237 	}
238 }
239 
parsespectype(struct rnndb * db,char * file,xmlNode * node)240 static void parsespectype(struct rnndb *db, char *file, xmlNode *node) {
241 	struct rnnspectype *res = calloc (sizeof *res, 1);
242 	res->file = file;
243 	xmlAttr *attr = node->properties;
244 	int i;
245 	while (attr) {
246 		if (!strcmp(attr->name, "name")) {
247 			res->name = strdup(getattrib(db, file, node->line, attr));
248 		} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
249 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for spectype\n", file, node->line, attr->name);
250 		}
251 		attr = attr->next;
252 	}
253 	if (!res->name) {
254 		rnn_err(db, "%s:%d: nameless spectype\n", file, node->line);
255 		return;
256 	}
257 	for (i = 0; i < db->spectypesnum; i++)
258 		if (!strcmp(db->spectypes[i]->name, res->name)) {
259 			rnn_err(db, "%s:%d: duplicated spectype name %s\n", file, node->line, res->name);
260 			return;
261 		}
262 	ADDARRAY(db->spectypes, res);
263 	xmlNode *chain = node->children;
264 	while (chain) {
265 		if (chain->type != XML_ELEMENT_NODE) {
266 		} else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
267 			rnn_err(db, "%s:%d: wrong tag in spectype: <%s>\n", file, chain->line, chain->name);
268 		}
269 		chain = chain->next;
270 	}
271 }
272 
parseenum(struct rnndb * db,char * file,xmlNode * node)273 static void parseenum(struct rnndb *db, char *file, xmlNode *node) {
274 	xmlAttr *attr = node->properties;
275 	char *name = 0;
276 	int isinline = 0;
277 	int bare = 0;
278 	char *prefixstr = 0;
279 	char *varsetstr = 0;
280 	char *variantsstr = 0;
281 	int i;
282 	while (attr) {
283 		if (!strcmp(attr->name, "name")) {
284 			name = getattrib(db, file, node->line, attr);
285 		} else if (!strcmp(attr->name, "bare")) {
286 			bare = getboolattrib(db, file, node->line, attr);
287 		} else if (!strcmp(attr->name, "inline")) {
288 			isinline = getboolattrib(db, file, node->line, attr);
289 		} else if (!strcmp(attr->name, "prefix")) {
290 			prefixstr = strdup(getattrib(db, file, node->line, attr));
291 		} else if (!strcmp(attr->name, "varset")) {
292 			varsetstr = strdup(getattrib(db, file, node->line, attr));
293 		} else if (!strcmp(attr->name, "variants")) {
294 			variantsstr = strdup(getattrib(db, file, node->line, attr));
295 		} else {
296 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for enum\n", file, node->line, attr->name);
297 		}
298 		attr = attr->next;
299 	}
300 	if (!name) {
301 		rnn_err(db, "%s:%d: nameless enum\n", file, node->line);
302 		return;
303 	}
304 	struct rnnenum *cur = 0;
305 	for (i = 0; i < db->enumsnum; i++)
306 		if (!strcmp(db->enums[i]->name, name)) {
307 			cur = db->enums[i];
308 			break;
309 		}
310 	if (cur) {
311 		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
312 				strdiff(cur->varinfo.varsetstr, varsetstr) ||
313 				strdiff(cur->varinfo.variantsstr, variantsstr) ||
314 				cur->isinline != isinline || cur->bare != bare) {
315 			rnn_err(db, "%s:%d: merge fail for enum %s\n", file, node->line, node->name);
316 		}
317 	} else {
318 		cur = calloc(sizeof *cur, 1);
319 		cur->name = strdup(name);
320 		cur->isinline = isinline;
321 		cur->bare = bare;
322 		cur->varinfo.prefixstr = prefixstr;
323 		cur->varinfo.varsetstr = varsetstr;
324 		cur->varinfo.variantsstr = variantsstr;
325 		cur->file = file;
326 		ADDARRAY(db->enums, cur);
327 	}
328 	xmlNode *chain = node->children;
329 	while (chain) {
330 		if (chain->type != XML_ELEMENT_NODE) {
331 		} else if (!strcmp(chain->name, "value")) {
332 			struct rnnvalue *val = parsevalue(db, file, chain);
333 			if (val)
334 				ADDARRAY(cur->vals, val);
335 		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
336 			rnn_err(db, "%s:%d: wrong tag in enum: <%s>\n", file, chain->line, chain->name);
337 		}
338 		chain = chain->next;
339 	}
340 }
341 
parsebitfield(struct rnndb * db,char * file,xmlNode * node)342 static struct rnnbitfield *parsebitfield(struct rnndb *db, char *file, xmlNode *node) {
343 	struct rnnbitfield *bf = calloc(sizeof *bf, 1);
344 	bf->file = file;
345 	xmlAttr *attr = node->properties;
346 	bf->typeinfo.low = bf->typeinfo.high = -1;
347 	while (attr) {
348 		if (!strcmp(attr->name, "name")) {
349 			bf->name = strdup(getattrib(db, file, node->line, attr));
350 		} else if (!strcmp(attr->name, "varset")) {
351 			bf->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
352 		} else if (!strcmp(attr->name, "variants")) {
353 			bf->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
354 		} else if (!trytypeattr(db, file, node, attr, &bf->typeinfo)) {
355 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitfield\n", file, node->line, attr->name);
356 		}
357 		attr = attr->next;
358 	}
359 	xmlNode *chain = node->children;
360 	while (chain) {
361 		if (chain->type != XML_ELEMENT_NODE) {
362 		} else if (!trytypetag(db, file, chain, &bf->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
363 			rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
364 		}
365 		chain = chain->next;
366 	}
367 	if (!bf->name) {
368 		rnn_err(db, "%s:%d: nameless bitfield\n", file, node->line);
369 		return 0;
370 	} else if (bf->typeinfo.low < 0|| bf->typeinfo.high < 0 || bf->typeinfo.high < bf->typeinfo.low) {
371 		rnn_err(db, "%s:%d: bitfield has wrong placement\n", file, node->line);
372 		return 0;
373 	} else {
374 		return bf;
375 	}
376 }
377 
parsebitset(struct rnndb * db,char * file,xmlNode * node)378 static void parsebitset(struct rnndb *db, char *file, xmlNode *node) {
379 	xmlAttr *attr = node->properties;
380 	char *name = 0;
381 	int isinline = 0;
382 	int bare = 0;
383 	char *prefixstr = 0;
384 	char *varsetstr = 0;
385 	char *variantsstr = 0;
386 	int i;
387 	while (attr) {
388 		if (!strcmp(attr->name, "name")) {
389 			name = getattrib(db, file, node->line, attr);
390 		} else if (!strcmp(attr->name, "bare")) {
391 			bare = getboolattrib(db, file, node->line, attr);
392 		} else if (!strcmp(attr->name, "inline")) {
393 			isinline = getboolattrib(db, file, node->line, attr);
394 		} else if (!strcmp(attr->name, "prefix")) {
395 			prefixstr = strdup(getattrib(db, file, node->line, attr));
396 		} else if (!strcmp(attr->name, "varset")) {
397 			varsetstr = strdup(getattrib(db, file, node->line, attr));
398 		} else if (!strcmp(attr->name, "variants")) {
399 			variantsstr = strdup(getattrib(db, file, node->line, attr));
400 		} else {
401 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for bitset\n", file, node->line, attr->name);
402 		}
403 		attr = attr->next;
404 	}
405 	if (!name) {
406 		rnn_err(db, "%s:%d: nameless bitset\n", file, node->line);
407 		return;
408 	}
409 	struct rnnbitset *cur = 0;
410 	for (i = 0; i < db->bitsetsnum; i++)
411 		if (!strcmp(db->bitsets[i]->name, name)) {
412 			cur = db->bitsets[i];
413 			break;
414 		}
415 	if (cur) {
416 		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
417 				strdiff(cur->varinfo.varsetstr, varsetstr) ||
418 				strdiff(cur->varinfo.variantsstr, variantsstr) ||
419 				cur->isinline != isinline || cur->bare != bare) {
420 			rnn_err(db, "%s:%d: merge fail for bitset %s\n", file, node->line, node->name);
421 		}
422 	} else {
423 		cur = calloc(sizeof *cur, 1);
424 		cur->name = strdup(name);
425 		cur->isinline = isinline;
426 		cur->bare = bare;
427 		cur->varinfo.prefixstr = prefixstr;
428 		cur->varinfo.varsetstr = varsetstr;
429 		cur->varinfo.variantsstr = variantsstr;
430 		cur->file = file;
431 		ADDARRAY(db->bitsets, cur);
432 	}
433 	xmlNode *chain = node->children;
434 	while (chain) {
435 		if (chain->type != XML_ELEMENT_NODE) {
436 		} else if (!strcmp(chain->name, "bitfield")) {
437 			struct rnnbitfield *bf = parsebitfield(db, file, chain);
438 			if (bf)
439 				ADDARRAY(cur->bitfields, bf);
440 		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
441 			rnn_err(db, "%s:%d: wrong tag in bitset: <%s>\n", file, chain->line, chain->name);
442 		}
443 		chain = chain->next;
444 	}
445 }
446 
trydelem(struct rnndb * db,char * file,xmlNode * node)447 static struct rnndelem *trydelem(struct rnndb *db, char *file, xmlNode *node) {
448 	if (!strcmp(node->name, "use-group")) {
449 		struct rnndelem *res = calloc(sizeof *res, 1);
450 		res->file = file;
451 		res->type = RNN_ETYPE_USE_GROUP;
452 		xmlAttr *attr = node->properties;
453 		while (attr) {
454 			if (!strcmp(attr->name, "ref")) {
455 				res->name = strdup(getattrib(db, file, node->line, attr));
456 			} else {
457 				rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
458 			}
459 			attr = attr->next;
460 		}
461 		if (!res->name) {
462 			rnn_err(db, "%s:%d: nameless use-group\n", file, node->line);
463 			return 0;
464 		}
465 		return res;
466 	} else if (!strcmp(node->name, "stripe") || !strcmp(node->name, "array")) {
467 		struct rnndelem *res = calloc(sizeof *res, 1);
468 		if (!strcmp(node->name, "array"))
469 			res->name = "";
470 		res->type = (strcmp(node->name, "stripe")?RNN_ETYPE_ARRAY:RNN_ETYPE_STRIPE);
471 		res->length = 1;
472 		res->file = file;
473 		xmlAttr *attr = node->properties;
474 		while (attr) {
475 			if (!strcmp(attr->name, "name")) {
476 				res->name = strdup(getattrib(db, file, node->line, attr));
477 			} else if (!strcmp(attr->name, "offset")) {
478 				res->offset = getnumattrib(db, file, node->line, attr);
479 			} else if (!strcmp(attr->name, "offsets")) {
480 				char *str = strdup(getattrib(db, file, node->line, attr));
481 				char *tok, *save, *tmp = str;
482 				while ((tok = strtok_r(str, ",", &save))) {
483 					uint64_t offset = getnum(db, file, node->line, attr, tok);
484 					ADDARRAY(res->offsets, offset);
485 					str = NULL;
486 				}
487 				if (str)
488 					fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str);
489 				free(tmp);
490 			} else if (!strcmp(attr->name, "doffset")) {
491 				/* dynamic runtime determined offset: */
492 				res->doffset = strdup(getattrib(db, file, node->line, attr));
493 			} else if (!strcmp(attr->name, "doffsets")) {
494 				/* dynamic runtime determined offsets: */
495 				char *str = strdup(getattrib(db, file, node->line, attr));
496 				char *tok, *save, *tmp = str;
497 				while ((tok = strtok_r(str, ",", &save))) {
498 					char *doffset = strdup(tok);
499 					ADDARRAY(res->doffsets, doffset);
500 					str = NULL;
501 				}
502 				if (str)
503 					fprintf(stderr, "%s:%d: invalid offsets: %s\n", file, node->line, str);
504 				free(tmp);
505 			} else if (!strcmp(attr->name, "length")) {
506 				res->length = getnumattrib(db, file, node->line, attr);
507 			} else if (!strcmp(attr->name, "stride")) {
508 				res->stride = getnumattrib(db, file, node->line, attr);
509 			} else if (!strcmp(attr->name, "prefix")) {
510 				res->varinfo.prefixstr = strdup(getattrib(db, file, node->line, attr));
511 			} else if (!strcmp(attr->name, "varset")) {
512 				res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
513 			} else if (!strcmp(attr->name, "variants")) {
514 				res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
515 			} else if (!strcmp(attr->name, "index")) {
516 				const char *enumname = getattrib(db, file, node->line, attr);
517 				res->index = rnn_findenum(db, enumname);
518 				if (!res->index) {
519 					rnn_err(db, "%s:%d: invalid enum name \"%s\"\n", file, node->line, enumname);
520 				}
521 			} else if (!strcmp(attr->name, "usage")) {
522 				// no-op
523 			} else {
524 				rnn_err(db, "%s:%d: wrong attribute \"%s\" for %s\n", file, node->line, attr->name, node->name);
525 			}
526 			attr = attr->next;
527 		}
528 		xmlNode *chain = node->children;
529 		while (chain) {
530 			struct rnndelem *delem;
531 			if (chain->type != XML_ELEMENT_NODE) {
532 			} else if ((delem = trydelem(db, file, chain))) {
533 				ADDARRAY(res->subelems, delem);
534 			} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
535 				rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
536 			}
537 			chain = chain->next;
538 		}
539 
540 		/* Sanity checking */
541 		if (res->type == RNN_ETYPE_ARRAY && res->stride == 0) {
542 			fprintf(stderr, "%s: Array %s's stride is undefined. Aborting.\n", file, res->name);
543 			exit(-1);
544 		}
545 		return res;
546 
547 	}
548 	int width;
549 	if (!strcmp(node->name, "reg8"))
550 		width = 8;
551 	else if (!strcmp(node->name, "reg16"))
552 		width = 16;
553 	else if (!strcmp(node->name, "reg32"))
554 		width = 32;
555 	else if (!strcmp(node->name, "reg64"))
556 		width = 64;
557 	else
558 		return 0;
559 	struct rnndelem *res = calloc(sizeof *res, 1);
560 	res->file = file;
561 	res->type = RNN_ETYPE_REG;
562 	res->width = width;
563 	res->length = 1;
564 	res->access = RNN_ACCESS_RW;
565 	xmlAttr *attr = node->properties;
566 	res->typeinfo.low = 0;
567 	res->typeinfo.high = width - 1;
568 	while (attr) {
569 		if (!strcmp(attr->name, "name")) {
570 			res->name = strdup(getattrib(db, file, node->line, attr));
571 		} else if (!strcmp(attr->name, "offset")) {
572 			res->offset = getnumattrib(db, file, node->line, attr);
573 		} else if (!strcmp(attr->name, "length")) {
574 			res->length = getnumattrib(db, file, node->line, attr);
575 		} else if (!strcmp(attr->name, "stride")) {
576 			res->stride = getnumattrib(db, file, node->line, attr);
577 		} else if (!strcmp(attr->name, "varset")) {
578 			res->varinfo.varsetstr = strdup(getattrib(db, file, node->line, attr));
579 		} else if (!strcmp(attr->name, "variants")) {
580 			res->varinfo.variantsstr = strdup(getattrib(db, file, node->line, attr));
581 		} else if (!strcmp(attr->name, "access")) {
582 			char *str = getattrib(db, file, node->line, attr);
583 			if (!strcmp(str, "r"))
584 				res->access = RNN_ACCESS_R;
585 			else if (!strcmp(str, "w"))
586 				res->access = RNN_ACCESS_W;
587 			else if (!strcmp(str, "rw"))
588 				res->access = RNN_ACCESS_RW;
589 			else
590 				fprintf (stderr, "%s:%d: wrong access type \"%s\" for register\n", file, node->line, str);
591 		} else if (!strcmp(attr->name, "usage")) {
592 			// no-op
593 		} else if (!trytypeattr(db, file, node, attr, &res->typeinfo)) {
594 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for register\n", file, node->line, attr->name);
595 		}
596 		attr = attr->next;
597 	}
598 	xmlNode *chain = node->children;
599 	while (chain) {
600 		if (chain->type != XML_ELEMENT_NODE) {
601 		} else if (!trytypetag(db, file, chain, &res->typeinfo) && !trytop(db, file, chain) && !trydoc(db, file, chain)) {
602 			rnn_err(db, "%s:%d: wrong tag in %s: <%s>\n", file, chain->line, node->name, chain->name);
603 		}
604 		chain = chain->next;
605 	}
606 	if (!res->name) {
607 		rnn_err(db, "%s:%d: nameless register\n", file, node->line);
608 		return 0;
609 	} else {
610 	}
611 	return res;
612 }
613 
parsegroup(struct rnndb * db,char * file,xmlNode * node)614 static void parsegroup(struct rnndb *db, char *file, xmlNode *node) {
615 	xmlAttr *attr = node->properties;
616 	char *name = 0;
617 	int i;
618 	while (attr) {
619 		if (!strcmp(attr->name, "name")) {
620 			name = getattrib(db, file, node->line, attr);
621 		} else {
622 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for group\n", file, node->line, attr->name);
623 		}
624 		attr = attr->next;
625 	}
626 	if (!name) {
627 		rnn_err(db, "%s:%d: nameless group\n", file, node->line);
628 		return;
629 	}
630 	struct rnngroup *cur = 0;
631 	for (i = 0; i < db->groupsnum; i++)
632 		if (!strcmp(db->groups[i]->name, name)) {
633 			cur = db->groups[i];
634 			break;
635 		}
636 	if (!cur) {
637 		cur = calloc(sizeof *cur, 1);
638 		cur->name = strdup(name);
639 		ADDARRAY(db->groups, cur);
640 	}
641 	xmlNode *chain = node->children;
642 	while (chain) {
643 		struct rnndelem *delem;
644 		if (chain->type != XML_ELEMENT_NODE) {
645 		} else if ((delem = trydelem(db, file, chain))) {
646 			ADDARRAY(cur->subelems, delem);
647 		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
648 			rnn_err(db, "%s:%d: wrong tag in group: <%s>\n", file, chain->line, chain->name);
649 		}
650 		chain = chain->next;
651 	}
652 }
653 
parsedomain(struct rnndb * db,char * file,xmlNode * node)654 static void parsedomain(struct rnndb *db, char *file, xmlNode *node) {
655 	xmlAttr *attr = node->properties;
656 	char *name = 0;
657 	uint64_t size = 0; int width = 8;
658 	int bare = 0;
659 	char *prefixstr = 0;
660 	char *varsetstr = 0;
661 	char *variantsstr = 0;
662 	int i;
663 	while (attr) {
664 		if (!strcmp(attr->name, "name")) {
665 			name = getattrib(db, file, node->line, attr);
666 		} else if (!strcmp(attr->name, "bare")) {
667 			bare = getboolattrib(db, file, node->line, attr);
668 		} else if (!strcmp(attr->name, "size")) {
669 			size = getnumattrib(db, file, node->line, attr);
670 		} else if (!strcmp(attr->name, "width")) {
671 			width = getnumattrib(db, file, node->line, attr);
672 		} else if (!strcmp(attr->name, "prefix")) {
673 			prefixstr = strdup(getattrib(db, file, node->line, attr));
674 		} else if (!strcmp(attr->name, "varset")) {
675 			varsetstr = strdup(getattrib(db, file, node->line, attr));
676 		} else if (!strcmp(attr->name, "variants")) {
677 			variantsstr = strdup(getattrib(db, file, node->line, attr));
678 		} else {
679 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for domain\n", file, node->line, attr->name);
680 		}
681 		attr = attr->next;
682 	}
683 	if (!name) {
684 		rnn_err(db, "%s:%d: nameless domain\n", file, node->line);
685 		return;
686 	}
687 	struct rnndomain *cur = 0;
688 	for (i = 0; i < db->domainsnum; i++)
689 		if (!strcmp(db->domains[i]->name, name)) {
690 			cur = db->domains[i];
691 			break;
692 		}
693 	if (cur) {
694 		if (strdiff(cur->varinfo.prefixstr, prefixstr) ||
695 				strdiff(cur->varinfo.varsetstr, varsetstr) ||
696 				strdiff(cur->varinfo.variantsstr, variantsstr) ||
697 				cur->width != width ||
698 				cur->bare != bare ||
699 				(size && cur->size && size != cur->size)) {
700 			rnn_err(db, "%s:%d: merge fail for domain %s\n", file, node->line, node->name);
701 		} else {
702 			if (size)
703 				cur->size = size;
704 		}
705 	} else {
706 		cur = calloc(sizeof *cur, 1);
707 		cur->name = strdup(name);
708 		cur->bare = bare;
709 		cur->width = width;
710 		cur->size = size;
711 		cur->varinfo.prefixstr = prefixstr;
712 		cur->varinfo.varsetstr = varsetstr;
713 		cur->varinfo.variantsstr = variantsstr;
714 		cur->file = file;
715 		ADDARRAY(db->domains, cur);
716 	}
717 	xmlNode *chain = node->children;
718 	while (chain) {
719 		struct rnndelem *delem;
720 		if (chain->type != XML_ELEMENT_NODE) {
721 		} else if ((delem = trydelem(db, file, chain))) {
722 			ADDARRAY(cur->subelems, delem);
723 		} else if (!trytop(db, file, chain) && !trydoc(db, file, chain)) {
724 			rnn_err(db, "%s:%d: wrong tag in domain: <%s>\n", file, chain->line, chain->name);
725 		}
726 		chain = chain->next;
727 	}
728 }
729 
parsecopyright(struct rnndb * db,char * file,xmlNode * node)730 static void parsecopyright(struct rnndb *db, char *file, xmlNode *node) {
731 	struct rnncopyright* copyright = &db->copyright;
732 	xmlAttr *attr = node->properties;
733 	while (attr) {
734 		if (!strcmp(attr->name, "year")) {
735 			unsigned firstyear = getnumattrib(db, file, node->line, attr);
736 			if(!copyright->firstyear || firstyear < copyright->firstyear)
737 				copyright->firstyear = firstyear;
738 		} else {
739 			rnn_err(db, "%s:%d: wrong attribute \"%s\" for copyright\n", file, node->line, attr->name);
740 		}
741 		attr = attr->next;
742 	}
743 	xmlNode *chain = node->children;
744 	while (chain) {
745 		if (chain->type != XML_ELEMENT_NODE) {
746 		} else if (!strcmp(chain->name, "license"))
747 			if(copyright->license) {
748 				if(strcmp(copyright->license, node->content)) {
749 					fprintf(stderr, "fatal error: multiple different licenses specified!\n");
750 					abort(); /* TODO: do something better here, but headergen, xml2html, etc. should not produce anything in this case */
751 				}
752 			} else
753 				copyright->license = getcontent(chain);
754 		else if (!strcmp(chain->name, "author")) {
755 			struct rnnauthor* author = calloc(sizeof *author, 1);
756 			xmlAttr* authorattr = chain->properties;
757 			xmlNode *authorchild = chain->children;
758 			author->contributions = getcontent(chain);
759 			while (authorattr) {
760 				if (!strcmp(authorattr->name, "name"))
761 					author->name = strdup(getattrib(db, file, chain->line, authorattr));
762 				else if (!strcmp(authorattr->name, "email"))
763 					author->email = strdup(getattrib(db, file, chain->line, authorattr));
764 				else {
765 					rnn_err(db, "%s:%d: wrong attribute \"%s\" for author\n", file, chain->line, authorattr->name);
766 				}
767 				authorattr = authorattr->next;
768 			}
769 			while(authorchild)  {
770 				if (authorchild->type != XML_ELEMENT_NODE) {
771 				} else if (!strcmp(authorchild->name, "nick")) {
772 					xmlAttr* nickattr = authorchild->properties;
773 					char* nickname = 0;
774 					while(nickattr) {
775 						if (!strcmp(nickattr->name, "name"))
776 							nickname = strdup(getattrib(db, file, authorchild->line, nickattr));
777 						else {
778 							rnn_err(db, "%s:%d: wrong attribute \"%s\" for nick\n", file, authorchild->line, nickattr->name);
779 						}
780 						nickattr = nickattr->next;
781 					}
782 					if(!nickname) {
783 						rnn_err(db, "%s:%d: missing \"name\" attribute for nick\n", file, authorchild->line);
784 					} else
785 						ADDARRAY(author->nicknames, nickname);
786 				} else {
787 					rnn_err(db, "%s:%d: wrong tag in author: <%s>\n", file, authorchild->line, authorchild->name);
788 				}
789 				authorchild = authorchild->next;
790 			}
791 			ADDARRAY(copyright->authors, author);
792 		} else {
793 			rnn_err(db, "%s:%d: wrong tag in copyright: <%s>\n", file, chain->line, chain->name);
794 		}
795 		chain = chain->next;
796 	}
797 }
798 
trytop(struct rnndb * db,char * file,xmlNode * node)799 static int trytop (struct rnndb *db, char *file, xmlNode *node) {
800 	if (!strcmp(node->name, "enum")) {
801 		parseenum(db, file, node);
802 		return 1;
803 	} else if (!strcmp(node->name, "bitset")) {
804 		parsebitset(db, file, node);
805 		return 1;
806 	} else if (!strcmp(node->name, "group")) {
807 		parsegroup(db, file, node);
808 		return 1;
809 	} else if (!strcmp(node->name, "domain")) {
810 		parsedomain(db, file, node);
811 		return 1;
812 	} else if (!strcmp(node->name, "spectype")) {
813 		parsespectype(db, file, node);
814 		return 1;
815 	} else if (!strcmp(node->name, "import")) {
816 		xmlAttr *attr = node->properties;
817 		char *subfile = 0;
818 		while (attr) {
819 			if (!strcmp(attr->name, "file")) {
820 				subfile = getattrib(db, file, node->line, attr);
821 			} else {
822 				rnn_err(db, "%s:%d: wrong attribute \"%s\" for import\n", file, node->line, attr->name);
823 			}
824 			attr = attr->next;
825 		}
826 		if (!subfile) {
827 			rnn_err(db, "%s:%d: missing \"file\" attribute for import\n", file, node->line);
828 		} else {
829 			rnn_parsefile(db, subfile);
830 		}
831 		return 1;
832 	} else if (!strcmp(node->name, "copyright")) {
833 		parsecopyright(db, file, node);
834 		return 1;
835 	}
836 	return 0;
837 }
838 
find_file(const char * file_orig)839 static char * find_file(const char *file_orig)
840 {
841 	const char *rnn_path = getenv("RNN_PATH");
842 	char *fname;
843 
844 	if (!rnn_path)
845 		rnn_path = RNN_DEF_PATH;
846 
847 	FILE *file = find_in_path(file_orig, rnn_path, &fname);
848 	if (!file) {
849 		fprintf (stderr, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", file_orig);
850 		return NULL;
851 	}
852 	fclose(file);
853 
854 	return fname;
855 }
856 
validate_doc(struct rnndb * db,xmlDocPtr doc,xmlNodePtr database)857 static int validate_doc(struct rnndb *db, xmlDocPtr doc, xmlNodePtr database)
858 {
859 	/* find the schemaLocation property: */
860 	xmlAttrPtr attr = database->properties;
861 	const char *schema_name = NULL;
862 	char *schema_path;
863 
864 	while (attr) {
865 		if (!strcmp(attr->name, "schemaLocation")) {
866 			xmlNodePtr data = attr->children;
867 			schema_name = data->content;
868 			/* we expect this to look like <namespace url> schema.xsd.. I think
869 			 * technically it is supposed to be just a URL, but that doesn't
870 			 * quite match up to what we do.. Just skip over everything up to
871 			 * and including the first whitespace character:
872 			 */
873 			while (schema_name && (schema_name[0] != ' '))
874 				schema_name++;
875 			schema_name++;
876 			break;
877 		}
878 	}
879 
880 	if (!schema_name) {
881 		rnn_err(db, "could not find schema.  Missing schemaLocation?");
882 		return 0;
883 	}
884 
885 	schema_path = find_file(schema_name);
886 	if (!schema_path) {
887 		rnn_err(db, "%s: couldn't find database file. Please set the env var RNN_PATH.\n", schema_name);
888 		return 0;
889 	}
890 
891 	xmlSchemaParserCtxtPtr parser = xmlSchemaNewParserCtxt(schema_path);
892 	xmlSchemaPtr schema = xmlSchemaParse(parser);
893 	xmlSchemaValidCtxtPtr validCtxt = xmlSchemaNewValidCtxt(schema);
894 	int ret = xmlSchemaValidateDoc(validCtxt, doc);
895 
896 	xmlSchemaFreeValidCtxt(validCtxt);
897 	xmlSchemaFree(schema);
898 	xmlSchemaFreeParserCtxt(parser);
899 
900 	free(schema_path);
901 
902 	return ret;
903 }
904 
rnn_parsefile(struct rnndb * db,char * file_orig)905 void rnn_parsefile (struct rnndb *db, char *file_orig) {
906 	int i;
907 	char *fname;
908 
909 	fname = find_file(file_orig);
910 	if (!fname) {
911 		db->estatus = 1;
912 		return;
913 	}
914 
915 	for (i = 0; i < db->filesnum; i++)
916 		if (!strcmp(db->files[i], fname))
917 			return;
918 
919 	ADDARRAY(db->files, fname);
920 	xmlDocPtr doc = xmlParseFile(fname);
921 	if (!doc) {
922 		rnn_err(db, "%s: couldn't open database file. Please set the env var RNN_PATH.\n", fname);
923 		return;
924 	}
925 	xmlNode *root = doc->children;
926 	while (root) {
927 		if (root->type != XML_ELEMENT_NODE) {
928 		} else if (strcmp(root->name, "database")) {
929 			rnn_err(db, "%s:%d: wrong top-level tag <%s>\n", fname, root->line, root->name);
930 		} else {
931 			xmlNode *chain = root->children;
932 			if (validate_doc(db, doc, root)) {
933 				rnn_err(db, "%s: database file has errors\n", fname);
934 				return;
935 			}
936 			while (chain) {
937 				if (chain->type != XML_ELEMENT_NODE) {
938 				} else if (!trytop(db, fname, chain) && !trydoc(db, fname, chain)) {
939 					rnn_err(db, "%s:%d: wrong tag in database: <%s>\n", fname, chain->line, chain->name);
940 				}
941 				chain = chain->next;
942 			}
943 		}
944 		root = root->next;
945 	}
946 	xmlFreeDoc(doc);
947 }
948 
copyvalue(struct rnnvalue * val,char * file)949 static struct rnnvalue *copyvalue (struct rnnvalue *val, char *file) {
950 	struct rnnvalue *res = calloc (sizeof *res, 1);
951 	res->name = val->name;
952 	res->valvalid = val->valvalid;
953 	res->value = val->value;
954 	res->varinfo = val->varinfo;
955 	res->file = file;
956 	return res;
957 }
958 
959 static struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file);
960 
961 
copytypeinfo(struct rnntypeinfo * dst,struct rnntypeinfo * src,char * file)962 static void copytypeinfo (struct rnntypeinfo *dst, struct rnntypeinfo *src, char *file) {
963 	int i;
964 	dst->name = src->name;
965 	dst->shr = src->shr;
966 	dst->low = src->low;
967 	dst->high = src->high;
968 	dst->min = src->min;
969 	dst->max = src->max;
970 	dst->align = src->align;
971 	dst->addvariant = src->addvariant;
972 	for (i = 0; i < src->valsnum; i++)
973 		ADDARRAY(dst->vals, copyvalue(src->vals[i], file));
974 	for (i = 0; i < src->bitfieldsnum; i++)
975 		ADDARRAY(dst->bitfields, copybitfield(src->bitfields[i], file));
976 }
977 
copybitfield(struct rnnbitfield * bf,char * file)978 static struct rnnbitfield *copybitfield (struct rnnbitfield *bf, char *file) {
979 	struct rnnbitfield *res = calloc (sizeof *res, 1);
980 	res->name = bf->name;
981 	res->varinfo = bf->varinfo;
982 	res->file = file;
983 	copytypeinfo(&res->typeinfo, &bf->typeinfo, file);
984 	return res;
985 }
986 
copydelem(struct rnndelem * elem,char * file)987 static struct rnndelem *copydelem (struct rnndelem *elem, char *file) {
988 	struct rnndelem *res = calloc (sizeof *res, 1);
989 	res->type = elem->type;
990 	res->name = elem->name;
991 	res->width = elem->width;
992 	res->access = elem->access;
993 	res->offset = elem->offset;
994 	res->length = elem->length;
995 	res->stride = elem->stride;
996 	res->varinfo = elem->varinfo;
997 	res->file = file;
998 	copytypeinfo(&res->typeinfo, &elem->typeinfo, file);
999 	int i;
1000 	for (i = 0; i < elem->subelemsnum; i++)
1001 		ADDARRAY(res->subelems, copydelem(elem->subelems[i], file));
1002 	for (i = 0; i < elem->offsetsnum; i++)
1003 		ADDARRAY(res->offsets, elem->offsets[i]);
1004 	return res;
1005 }
1006 
copyvarset(struct rnnvarset * varset)1007 static struct rnnvarset *copyvarset (struct rnnvarset *varset) {
1008 	struct rnnvarset *res = calloc(sizeof *res, 1);
1009 	res->venum = varset->venum;
1010 	res->variants = calloc(sizeof *res->variants, res->venum->valsnum);
1011 	int i;
1012 	for (i = 0; i < res->venum->valsnum; i++)
1013 		res->variants[i] = varset->variants[i];
1014 	return res;
1015 }
1016 
1017 static void prepenum(struct rnndb *db, struct rnnenum *en);
1018 
findvidx(struct rnndb * db,struct rnnenum * en,char * name)1019 static int findvidx (struct rnndb *db, struct rnnenum *en, char *name) {
1020 	int i;
1021 	for (i = 0; i < en->valsnum; i++)
1022 		if (!strcmp(en->vals[i]->name, name))
1023 			return i;
1024 	rnn_err(db, "Cannot find variant %s in enum %s!\n", name, en->name);
1025 	return -1;
1026 }
1027 
prepvarinfo(struct rnndb * db,char * what,struct rnnvarinfo * vi,struct rnnvarinfo * parent)1028 static void prepvarinfo (struct rnndb *db, char *what, struct rnnvarinfo *vi, struct rnnvarinfo *parent) {
1029 	if (parent)
1030 		vi->prefenum = parent->prefenum;
1031 	if (vi->prefixstr) {
1032 		if (!strcmp(vi->prefixstr, "none"))
1033 			vi->prefenum = 0;
1034 		else
1035 			vi->prefenum = rnn_findenum(db, vi->prefixstr); // XXX
1036 	}
1037 	int i;
1038 	if (parent)
1039 		for (i = 0; i < parent->varsetsnum; i++)
1040 			ADDARRAY(vi->varsets, copyvarset(parent->varsets[i]));
1041 	struct rnnenum *varset = vi->prefenum;
1042 	if (!varset && !vi->varsetstr && parent)
1043 		vi->varsetstr = parent->varsetstr;
1044 	if (vi->varsetstr)
1045 		varset = rnn_findenum(db, vi->varsetstr);
1046 	if (vi->variantsstr) {
1047 		char *vars = vi->variantsstr;
1048 		if (!varset) {
1049 			rnn_err(db, "%s: tried to use variants without active varset!\n", what);
1050 			return;
1051 		}
1052 		struct rnnvarset *vs = 0;
1053 		int nvars = varset->valsnum;
1054 		for (i = 0; i < vi->varsetsnum; i++)
1055 			if (vi->varsets[i]->venum == varset) {
1056 				vs = vi->varsets[i];
1057 				break;
1058 			}
1059 		if (!vs) {
1060 			vs = calloc (sizeof *vs, 1);
1061 			vs->venum = varset;
1062 			vs->variants = calloc(sizeof *vs->variants, nvars);
1063 			for (i = 0; i < nvars; i++)
1064 				vs->variants[i] = 1;
1065 			ADDARRAY(vi->varsets, vs);
1066 		}
1067 		while (1) {
1068 			while (*vars == ' ') vars++;
1069 			if (*vars == 0)
1070 				break;
1071 			char *split = vars;
1072 			while (*split != ':' && *split != '-' && *split != ' '  && *split != 0)
1073 				split++;
1074 			char *first = 0;
1075 			if (split != vars)
1076 				first = strndup(vars, split-vars);
1077 			if (*split == ' ' || *split == 0) {
1078 				int idx = findvidx(db, varset, first);
1079 				if (idx != -1)
1080 					vs->variants[idx] |= 2;
1081 				vars = split;
1082 			} else {
1083 				char *end = split+1;
1084 				while (*end != ' '  && *end != 0)
1085 					end++;
1086 				char *second = 0;
1087 				if (end != split+1)
1088 					second = strndup(split+1, end-split-1);
1089 				int idx1 = 0;
1090 				if (first)
1091 					idx1 = findvidx(db, varset, first);
1092 				int idx2 = nvars;
1093 				if (second) {
1094 					idx2 = findvidx(db, varset, second);
1095 					if (*split == '-')
1096 						idx2++;
1097 				}
1098 				if (idx1 != -1 && idx2 != -1)
1099 					for (i = idx1; i < idx2; i++)
1100 						vs->variants[i] |= 2;
1101 				vars = end;
1102 				free(second);
1103 			}
1104 			free(first);
1105 		}
1106 		vi->dead = 1;
1107 		for (i = 0; i < nvars; i++) {
1108 			vs->variants[i] = (vs->variants[i] == 3);
1109 			if (vs->variants[i])
1110 				vi->dead = 0;
1111 		}
1112 	}
1113 	if (vi->dead)
1114 		return;
1115 	if (vi->prefenum) {
1116 		struct rnnvarset *vs = 0;
1117 		for (i = 0; i < vi->varsetsnum; i++)
1118 			if (vi->varsets[i]->venum == vi->prefenum) {
1119 				vs = vi->varsets[i];
1120 				break;
1121 			}
1122 		if (vs) {
1123 			for (i = 0; i < vi->prefenum->valsnum; i++)
1124 				if (vs->variants[i]) {
1125 					vi->prefix = vi->prefenum->vals[i]->name;
1126 					return;
1127 				}
1128 		} else {
1129 			vi->prefix = vi->prefenum->vals[0]->name;
1130 		}
1131 	}
1132 }
1133 
prepvalue(struct rnndb * db,struct rnnvalue * val,char * prefix,struct rnnvarinfo * parvi)1134 static void prepvalue(struct rnndb *db, struct rnnvalue *val, char *prefix, struct rnnvarinfo *parvi) {
1135 	val->fullname = catstr(prefix, val->name);
1136 	prepvarinfo (db, val->fullname, &val->varinfo, parvi);
1137 	if (val->varinfo.dead)
1138 		return;
1139 	if (val->varinfo.prefix)
1140 		val->fullname = catstr(val->varinfo.prefix, val->fullname);
1141 }
1142 
1143 static void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi);
1144 
preptypeinfo(struct rnndb * db,struct rnntypeinfo * ti,char * prefix,struct rnnvarinfo * vi,char * file)1145 static void preptypeinfo(struct rnndb *db, struct rnntypeinfo *ti, char *prefix, struct rnnvarinfo *vi, char *file) {
1146 	int i;
1147 	if (ti->name) {
1148 		struct rnnenum *en = rnn_findenum (db, ti->name);
1149 		struct rnnbitset *bs = rnn_findbitset (db, ti->name);
1150 		struct rnnspectype *st = rnn_findspectype (db, ti->name);
1151 		if (en) {
1152 			if (en->isinline) {
1153 				ti->type = RNN_TTYPE_INLINE_ENUM;
1154 				int j;
1155 				for (j = 0; j < en->valsnum; j++)
1156 					ADDARRAY(ti->vals, copyvalue(en->vals[j], file));
1157 			} else {
1158 				ti->type = RNN_TTYPE_ENUM;
1159 				ti->eenum = en;
1160 			}
1161 		} else if (bs) {
1162 			if (bs->isinline) {
1163 				ti->type = RNN_TTYPE_INLINE_BITSET;
1164 				int j;
1165 				for (j = 0; j < bs->bitfieldsnum; j++)
1166 					ADDARRAY(ti->bitfields, copybitfield(bs->bitfields[j], file));
1167 			} else {
1168 				ti->type = RNN_TTYPE_BITSET;
1169 				ti->ebitset = bs;
1170 			}
1171 		} else if (st) {
1172 			ti->type = RNN_TTYPE_SPECTYPE;
1173 			ti->spectype = st;
1174 		} else if (!strcmp(ti->name, "hex")) {
1175 			ti->type = RNN_TTYPE_HEX;
1176 		} else if (!strcmp(ti->name, "float")) {
1177 			ti->type = RNN_TTYPE_FLOAT;
1178 		} else if (!strcmp(ti->name, "uint")) {
1179 			ti->type = RNN_TTYPE_UINT;
1180 		} else if (!strcmp(ti->name, "int")) {
1181 			ti->type = RNN_TTYPE_INT;
1182 		} else if (!strcmp(ti->name, "boolean")) {
1183 			ti->type = RNN_TTYPE_BOOLEAN;
1184 		} else if (!strcmp(ti->name, "bitfield")) {
1185 			ti->type = RNN_TTYPE_INLINE_BITSET;
1186 		} else if (!strcmp(ti->name, "enum")) {
1187 			ti->type = RNN_TTYPE_INLINE_ENUM;
1188 		} else if (!strcmp(ti->name, "fixed")) {
1189 			ti->type = RNN_TTYPE_FIXED;
1190 		} else if (!strcmp(ti->name, "ufixed")) {
1191 			ti->type = RNN_TTYPE_UFIXED;
1192 		} else if (!strcmp(ti->name, "a3xx_regid")) {
1193 			ti->type = RNN_TTYPE_A3XX_REGID;
1194 		} else if (!strcmp(ti->name, "waddress") || !strcmp(ti->name, "address")) {
1195 			ti->type = RNN_TTYPE_HEX;
1196 		} else {
1197 			ti->type = RNN_TTYPE_HEX;
1198 			rnn_err(db, "%s: unknown type %s\n", prefix, ti->name);
1199 		}
1200 	} else if (ti->bitfieldsnum) {
1201 		ti->name = "bitfield";
1202 		ti->type = RNN_TTYPE_INLINE_BITSET;
1203 	} else if (ti->valsnum) {
1204 		ti->name = "enum";
1205 		ti->type = RNN_TTYPE_INLINE_ENUM;
1206 	} else if (ti->low == 0 && ti->high == 0) {
1207 		ti->name = "boolean";
1208 		ti->type = RNN_TTYPE_BOOLEAN;
1209 	} else {
1210 		ti->name = "hex";
1211 		ti->type = RNN_TTYPE_HEX;
1212 	}
1213 	if (ti->addvariant && ti->type != RNN_TTYPE_ENUM) {
1214 		rnn_err(db, "%s: addvariant specified on non-enum type %s\n", prefix, ti->name);
1215 	}
1216 	for (i = 0; i < ti->bitfieldsnum; i++) {
1217 		prepbitfield(db,  ti->bitfields[i], prefix, vi);
1218 		if (ti->bitfields[i]->typeinfo.addvariant) {
1219 			for (int j = 0; j < i; j++) {
1220 				if (!ti->bitfields[j]->typeinfo.addvariant) {
1221 					struct rnnbitfield *t = ti->bitfields[j];
1222 					ti->bitfields[j] = ti->bitfields[i];
1223 					ti->bitfields[i] = t;
1224 					break;
1225 				}
1226 			}
1227 		}
1228 	}
1229 	for (i = 0; i < ti->valsnum; i++)
1230 		prepvalue(db, ti->vals[i], prefix, vi);
1231 }
1232 
prepbitfield(struct rnndb * db,struct rnnbitfield * bf,char * prefix,struct rnnvarinfo * parvi)1233 static void prepbitfield(struct rnndb *db, struct rnnbitfield *bf, char *prefix, struct rnnvarinfo *parvi) {
1234 	bf->fullname = catstr(prefix, bf->name);
1235 	prepvarinfo (db, bf->fullname, &bf->varinfo, parvi);
1236 	if (bf->varinfo.dead)
1237 		return;
1238 	preptypeinfo(db, &bf->typeinfo, bf->fullname, &bf->varinfo, bf->file);
1239 	if (bf->varinfo.prefix)
1240 		bf->fullname = catstr(bf->varinfo.prefix, bf->fullname);
1241 }
1242 
prepdelem(struct rnndb * db,struct rnndelem * elem,char * prefix,struct rnnvarinfo * parvi,int width)1243 static void prepdelem(struct rnndb *db, struct rnndelem *elem, char *prefix, struct rnnvarinfo *parvi, int width) {
1244 	if (elem->type == RNN_ETYPE_USE_GROUP) {
1245 		int i;
1246 		struct rnngroup *gr = 0;
1247 		for (i = 0; i < db->groupsnum; i++)
1248 			if (!strcmp(db->groups[i]->name, elem->name)) {
1249 				gr = db->groups[i];
1250 				break;
1251 			}
1252 		if (gr) {
1253 			for (i = 0; i < gr->subelemsnum; i++)
1254 				ADDARRAY(elem->subelems, copydelem(gr->subelems[i], elem->file));
1255 		} else {
1256 			rnn_err(db, "group %s not found!\n", elem->name);
1257 		}
1258 		elem->type = RNN_ETYPE_STRIPE;
1259 		elem->length = 1;
1260 		elem->name = 0;
1261 	}
1262 	if (elem->name) {
1263 		if (elem->varinfo.variantsstr && !strstr(elem->varinfo.variantsstr, "-")) {
1264 			/* Special hack for headergen2 to deal with variant regs (like a6xx vs
1265 			 * a7xx).. gen_header.py handles this differently by generating C++
1266 			 * template based reg builder to handle variants.  But for now we still
1267 			 * need something that can be used for kernel headers.
1268 			 */
1269 			elem->fullname = catstr(elem->varinfo.variantsstr, elem->name);
1270 		} else {
1271 			elem->fullname = catstr(prefix, elem->name);
1272 		}
1273 	}
1274 	prepvarinfo (db, elem->fullname?elem->fullname:prefix, &elem->varinfo, parvi);
1275 	if (elem->varinfo.dead)
1276 		return;
1277 	if (elem->length != 1 && !elem->stride) {
1278 		if (elem->type != RNN_ETYPE_REG) {
1279 			rnn_err(db, "%s has non-1 length, but no stride!\n", elem->fullname);
1280 		} else {
1281 			elem->stride = elem->width/width;
1282 		}
1283 	}
1284 	preptypeinfo(db, &elem->typeinfo, elem->name?elem->fullname:prefix, &elem->varinfo, elem->file);
1285 
1286 	int i;
1287 	for (i = 0; i < elem->subelemsnum; i++)
1288 		prepdelem(db,  elem->subelems[i], elem->name?elem->fullname:prefix, &elem->varinfo, width);
1289 	if (elem->varinfo.prefix && elem->name)
1290 		elem->fullname = catstr(elem->varinfo.prefix, elem->fullname);
1291 }
1292 
prepdomain(struct rnndb * db,struct rnndomain * dom)1293 static void prepdomain(struct rnndb *db, struct rnndomain *dom) {
1294 	prepvarinfo (db, dom->name, &dom->varinfo, 0);
1295 	int i;
1296 	for (i = 0; i < dom->subelemsnum; i++)
1297 		prepdelem(db, dom->subelems[i], dom->bare?0:dom->name, &dom->varinfo, dom->width);
1298 	dom->fullname = catstr(dom->varinfo.prefix, dom->name);
1299 }
1300 
prepenum(struct rnndb * db,struct rnnenum * en)1301 static void prepenum(struct rnndb *db, struct rnnenum *en) {
1302 	if (en->prepared)
1303 		return;
1304 	prepvarinfo (db, en->name, &en->varinfo, 0);
1305 	int i;
1306 	if (en->isinline)
1307 		return;
1308 	for (i = 0; i < en->valsnum; i++)
1309 		prepvalue(db, en->vals[i], en->bare?0:en->name, &en->varinfo);
1310 	en->fullname = catstr(en->varinfo.prefix, en->name);
1311 	en->prepared = 1;
1312 }
1313 
prepbitset(struct rnndb * db,struct rnnbitset * bs)1314 static void prepbitset(struct rnndb *db, struct rnnbitset *bs) {
1315 	prepvarinfo (db, bs->name, &bs->varinfo, 0);
1316 	int i;
1317 	if (bs->isinline)
1318 		return;
1319 	for (i = 0; i < bs->bitfieldsnum; i++)
1320 		prepbitfield(db, bs->bitfields[i], bs->bare?0:bs->name, &bs->varinfo);
1321 	bs->fullname = catstr(bs->varinfo.prefix, bs->name);
1322 }
1323 
prepspectype(struct rnndb * db,struct rnnspectype * st)1324 static void prepspectype(struct rnndb *db, struct rnnspectype *st) {
1325 	preptypeinfo(db, &st->typeinfo, st->name, 0, st->file); // XXX doesn't exactly make sense...
1326 }
1327 
rnn_prepdb(struct rnndb * db)1328 void rnn_prepdb (struct rnndb *db) {
1329 	int i;
1330 	for (i = 0; i < db->enumsnum; i++)
1331 		prepenum(db, db->enums[i]);
1332 	for (i = 0; i < db->bitsetsnum; i++)
1333 		prepbitset(db, db->bitsets[i]);
1334 	for (i = 0; i < db->domainsnum; i++)
1335 		prepdomain(db, db->domains[i]);
1336 	for (i = 0; i < db->spectypesnum; i++)
1337 		prepspectype(db, db->spectypes[i]);
1338 }
1339 
rnn_findenum(struct rnndb * db,const char * name)1340 struct rnnenum *rnn_findenum (struct rnndb *db, const char *name) {
1341 	int i;
1342 	for (i = 0; i < db->enumsnum; i++)
1343 		if (!strcmp(db->enums[i]->name, name))
1344 			return db->enums[i];
1345 	return 0;
1346 }
1347 
rnn_findbitset(struct rnndb * db,const char * name)1348 struct rnnbitset *rnn_findbitset (struct rnndb *db, const char *name) {
1349 	int i;
1350 	for (i = 0; i < db->bitsetsnum; i++)
1351 		if (!strcmp(db->bitsets[i]->name, name))
1352 			return db->bitsets[i];
1353 	return 0;
1354 }
1355 
rnn_finddomain(struct rnndb * db,const char * name)1356 struct rnndomain *rnn_finddomain (struct rnndb *db, const char *name) {
1357 	int i;
1358 	for (i = 0; i < db->domainsnum; i++)
1359 		if (!strcmp(db->domains[i]->name, name))
1360 			return db->domains[i];
1361 	return 0;
1362 }
1363 
rnn_findspectype(struct rnndb * db,const char * name)1364 struct rnnspectype *rnn_findspectype (struct rnndb *db, const char *name) {
1365 	int i;
1366 	for (i = 0; i < db->spectypesnum; i++)
1367 		if (!strcmp(db->spectypes[i]->name, name))
1368 			return db->spectypes[i];
1369 	return 0;
1370 }
1371