Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

symbolic.c (11511B)


      1 #include <time.h>
      2 #include <ctype.h>
      3 #include "c.h"
      4 
      5 #define I(f) s_##f
      6 
      7 static Node *tail;
      8 static int off, maxoff, uid = 0, verbose = 0, html = 0;
      9 
     10 static const char *yyBEGIN(const char *tag) {
     11 	if (html)
     12 		print("<%s>", tag);
     13 	return tag;
     14 }
     15 
     16 static void yyEND(const char *tag) {
     17 	if (html)
     18 		print("</%s>", tag);
     19 	if (isupper(*tag))
     20 		print("\n");
     21 }
     22 
     23 #define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag);
     24 #define END yyEND(yytag); } while (0)
     25 #define ITEM BEGIN(li)
     26 #define START BEGIN(LI)
     27 #define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); }
     28 #define NEWLINE print(html ? "<br>\n" : "\n")
     29 
     30 static void emitCoord(Coordinate src) {
     31 	if (src.file && *src.file) {
     32 		ANCHOR(href,print("%s", src.file)); print("%s", src.file); END;
     33 		print(":");
     34 	}
     35 	print("%d.%d", src.y, src.x);
     36 }
     37 
     38 static void emitString(int len, const char *s) {
     39 	for ( ; len-- > 0; s++)
     40 		if (*s == '&' && html)
     41 			print("&amp;");
     42 		else if (*s == '<' && html)
     43 			print("&lt;");
     44 		else if (*s == '>' && html)
     45 			print("&lt;");
     46 		else if (*s == '"' || *s == '\\')
     47 			print("\\%c", *s);
     48 		else if (*s >= ' ' && *s < 0177)
     49 			print("%c", *s);
     50 		else
     51 			print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
     52 }
     53 
     54 static void emitSymRef(Symbol p) {
     55 	(*IR->defsymbol)(p);
     56 	ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
     57 }
     58 
     59 static void emitSymbol(Symbol p) {
     60 	(*IR->defsymbol)(p);
     61 	ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
     62 	BEGIN(ul);
     63 #define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END
     64 	if (verbose && (src.y || src.x))
     65 		xx(src,emitCoord(p->src));
     66 	xx(type,print("%t", p->type));
     67 	xx(sclass,print("%k", p->sclass));
     68 	switch (p->scope) {
     69 	case CONSTANTS: xx(scope,print("CONSTANTS")); break;
     70 	case LABELS:    xx(scope,print("LABELS"));    break;
     71 	case GLOBAL:    xx(scope,print("GLOBAL"));    break;
     72 	case PARAM:     xx(scope,print("PARAM"));     break;
     73 	case LOCAL:     xx(scope,print("LOCAL"));     break;
     74 	default:
     75 		if (p->scope > LOCAL)
     76 			xx(scope,print("LOCAL+%d", p->scope-LOCAL));
     77 		else
     78 			xx(scope,print("%d", p->scope));
     79 	}
     80 	if (p->scope >= PARAM && p->sclass != STATIC)
     81 		xx(offset,print("%d", p->x.offset));
     82 	xx(ref,print("%f", p->ref));
     83 	if (p->temporary && p->u.t.cse)
     84 		xx(u.t.cse,print("%p", p->u.t.cse));
     85 	END;
     86 #undef xx
     87 }
     88 
     89 /* address - initialize q for addressing expression p+n */
     90 static void I(address)(Symbol q, Symbol p, long n) {
     91 	q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n);
     92 	(*IR->defsymbol)(q);
     93 	START; print("address "); emitSymbol(q); END;
     94 }
     95 
     96 /* blockbeg - start a block */
     97 static void I(blockbeg)(Env *e) {
     98 	e->offset = off;
     99 	START; print("blockbeg off=%d", off); END;
    100 }
    101 
    102 /* blockend - start a block */
    103 static void I(blockend)(Env *e) {
    104 	if (off > maxoff)
    105 		maxoff = off;
    106 	START; print("blockend off=%d", off); END;
    107 	off = e->offset;
    108 }
    109 
    110 /* defaddress - initialize an address */
    111 static void I(defaddress)(Symbol p){
    112 	START; print("defaddress "); emitSymRef(p); END;
    113 }
    114 
    115 /* defconst - define a constant */
    116 static void I(defconst)(int suffix, int size, Value v) {
    117 	START;
    118 	print("defconst ");
    119 	switch (suffix) {
    120 	case I:
    121 		print("int.%d ", size);
    122 		BEGIN(code);
    123 		if (size > sizeof (int))
    124 			print("%D", v.i);
    125 		else
    126 			print("%d", (int)v.i);
    127 		END;
    128 		break;
    129 	case U:
    130 		print("unsigned.%d ", size);
    131 		BEGIN(code);
    132 		if (size > sizeof (unsigned))
    133 			print("%U", v.u);
    134 		else
    135 			print("%u", (unsigned)v.u);
    136 		END;
    137 		break;
    138 	case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break;
    139 	case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break;
    140 	default: assert(0);
    141 	}
    142 	END;
    143 }
    144 
    145 /* defstring - emit a string constant */
    146 static void I(defstring)(int len, char *s) {
    147 	START; print("defstring ");
    148 	BEGIN(code); print("\""); emitString(len, s); print("\""); END;
    149 	END;
    150 }
    151 
    152 /* defsymbol - define a symbol: initialize p->x */
    153 static void I(defsymbol)(Symbol p) {
    154 	if (p->x.name == NULL)
    155 		p->x.name = stringd(++uid);
    156 }
    157 
    158 /* emit - emit the dags on list p */
    159 static void I(emit)(Node p){
    160 	ITEM;
    161 	if (!html)
    162 		print(" ");
    163 	for (; p; p = p->x.next) {
    164 		if (p->op == LABEL+V) {
    165 			assert(p->syms[0]);
    166 			ANCHOR(name,print("%s", p->syms[0]->x.name));
    167 			BEGIN(code); print("%s", p->syms[0]->name); END;
    168 			END;
    169 			print(":");
    170 		} else {
    171 			int i;
    172 			if (p->x.listed) {
    173 				BEGIN(strong); print("%d", p->x.inst); END; print("'");
    174 				print(" %s", opname(p->op));
    175 			} else
    176 				print("%d. %s", p->x.inst, opname(p->op));
    177 			if (p->count > 1)
    178 				print(" count=%d", p->count);
    179 			for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
    180 				print(" #%d", p->kids[i]->x.inst);
    181 			if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
    182 				print(" {%t}", p->syms[0]->type);
    183 			else
    184 				for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
    185 					print(" ");
    186 					if (p->syms[i]->scope == CONSTANTS)
    187 						print(p->syms[i]->name);
    188 					else
    189 						emitSymRef(p->syms[i]);
    190 				}
    191 		}
    192 		NEWLINE;
    193 	}
    194 	END;
    195 }
    196 
    197 /* export - announce p as exported */
    198 static void I(export)(Symbol p) {
    199 	START; print("export "); emitSymRef(p); END;
    200 }
    201 
    202 /* function - generate code for a function */
    203 static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
    204 	int i;
    205 
    206 	(*IR->defsymbol)(f);
    207 	off = 0;
    208 	for (i = 0; caller[i] && callee[i]; i++) {
    209 		off = roundup(off, caller[i]->type->align);
    210 		caller[i]->x.offset = callee[i]->x.offset = off;
    211 		off += caller[i]->type->size;
    212 	}
    213 	if (!html) {
    214 		print("function ");
    215 		emitSymbol(f);
    216 		print(" ncalls=%d\n", ncalls);
    217 		for (i = 0; caller[i]; i++)
    218 			START; print("caller "); emitSymbol(caller[i]); END;
    219 		for (i = 0; callee[i]; i++)
    220 			START; print("callee "); emitSymbol(callee[i]); END;
    221 	} else {
    222 		START;
    223 		print("function");
    224 		BEGIN(UL);
    225 #define xx(field,code) ITEM; print(#field "="); code; END
    226 		xx(f,emitSymbol(f));
    227 		xx(ncalls,print("%d", ncalls));
    228 		if (caller[0]) {
    229 			ITEM; print("caller"); BEGIN(OL);
    230 			for (i = 0; caller[i]; i++)
    231 				ITEM; emitSymbol(caller[i]); END;
    232 			END; END;
    233 			ITEM; print("callee"); BEGIN(OL);
    234 			for (i = 0; callee[i]; i++)
    235 				ITEM; emitSymbol(callee[i]); END;
    236 			END; END;
    237 		} else {
    238 			xx(caller,BEGIN(em); print("empty"); END);
    239 			xx(callee,BEGIN(em); print("empty"); END);
    240 		}
    241 		END;
    242 		END;
    243 	}
    244 	maxoff = off = 0;
    245 	gencode(caller, callee);
    246 	if (html)
    247 		START; print("emitcode"); BEGIN(ul); emitcode(); END; END;
    248 	else
    249 		emitcode();
    250 	START; print("maxoff=%d", maxoff); END;
    251 #undef xx
    252 }
    253 
    254 /* visit - generate code for *p */
    255 static int visit(Node p, int n) {
    256 	if (p && p->x.inst == 0) {
    257 		p->x.inst = ++n;
    258 		n = visit(p->kids[0], n);
    259 		n = visit(p->kids[1], n);
    260 		*tail = p;
    261 		tail = &p->x.next;
    262 	}
    263 	return n;
    264 }
    265 
    266 /* gen0 - generate code for the dags on list p */
    267 static Node I(gen)(Node p) {
    268 	int n;
    269 	Node nodelist;
    270 
    271 	tail = &nodelist;
    272 	for (n = 0; p; p = p->link) {
    273 		switch (generic(p->op)) {	/* check for valid forest */
    274 		case CALL:
    275 			assert(IR->wants_dag || p->count == 0);
    276 			break;
    277 		case ARG:
    278 		case ASGN: case JUMP: case LABEL: case RET:
    279 		case EQ: case GE: case GT: case LE: case LT: case NE:
    280 			assert(p->count == 0);
    281 			break;
    282 		case INDIR:
    283 			assert(IR->wants_dag && p->count > 0);
    284 			break;
    285 		default:
    286 			assert(0);
    287 		}
    288 		check(p);
    289 		p->x.listed = 1;
    290 		n = visit(p, n);
    291 	}
    292 	*tail = 0;
    293 	return nodelist;
    294 }
    295 
    296 /* global - announce a global */
    297 static void I(global)(Symbol p) {
    298 	START; print("global "); emitSymbol(p); END;
    299 }
    300 
    301 /* import - import a symbol */
    302 static void I(import)(Symbol p) {
    303 	START; print("import "); emitSymRef(p); END;
    304 }
    305 
    306 /* local - local variable */
    307 static void I(local)(Symbol p) {
    308 	if (p->temporary)
    309 		p->name = stringf("t%s", p->name);
    310 	(*IR->defsymbol)(p);
    311 	off = roundup(off, p->type->align);
    312 	p->x.offset = off;
    313 	off += p->type->size;
    314 	START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END;
    315 }
    316 
    317 /* progbeg - beginning of program */
    318 static void I(progbeg)(int argc, char *argv[]) {
    319 	int i;
    320 
    321 	for (i = 1; i < argc; i++)
    322 		if (strcmp(argv[i], "-v") == 0)
    323 			verbose++;
    324 		else if (strcmp(argv[i], "-html") == 0)
    325 			html++;
    326 	if (html) {
    327 		print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
    328 		print("<html>");
    329 		BEGIN(head);
    330 		if (firstfile && *firstfile)
    331 			BEGIN(title); emitString(strlen(firstfile), firstfile);	END;
    332 		print("<link rev=made href=\"mailto:drh@microsoft.com\">\n");
    333 		END;
    334 		print("<body>\n");
    335 		if (firstfile && *firstfile)
    336 			BEGIN(h1); emitString(strlen(firstfile), firstfile); END;
    337 		BEGIN(P); BEGIN(em);
    338 		print("Links lead from uses of identifiers and labels to their definitions.");
    339 		END; END;
    340 		print("<ul>\n");
    341 		START;
    342 		print("progbeg");
    343 		BEGIN(ol);
    344 		for (i = 1; i < argc; i++) {
    345 			ITEM;
    346 			BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END;
    347 			END;
    348 		}
    349 		END;
    350 		END;
    351 	}
    352 }
    353 
    354 /* progend - end of program */
    355 static void I(progend)(void) {
    356 	START; print("progend"); END;
    357 	if (html) {
    358 		time_t t;
    359 		print("</ul>\n");
    360 		time(&t);
    361 		print("<hr><address>%s</address>\n", ctime(&t));
    362 		print("</body></html>\n");
    363 	}
    364 }
    365 
    366 /* segment - switch to segment s */
    367 static void I(segment)(int s) {
    368 	START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END;
    369 }
    370 
    371 /* space - initialize n bytes of space */
    372 static void I(space)(int n) {
    373 	START; print("space %d", n); END;
    374 }
    375 
    376 static void I(stabblock)(int brace, int lev, Symbol *p) {}
    377 
    378 /* stabend - finalize stab output */
    379 static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
    380 	int i;
    381 
    382 	if (p)
    383 		emitSymRef(p);
    384 	print("\n");
    385 	if (cpp && sp)
    386 		for (i = 0; cpp[i] && sp[i]; i++) {
    387 			print("%w.%d: ", cpp[i], cpp[i]->x);
    388 			emitSymRef(sp[i]);
    389 			print("\n");
    390 		}
    391 }
    392 
    393 static void I(stabfend)(Symbol p, int lineno) {}
    394 static void I(stabinit)(char *file, int argc, char *argv[]) {}
    395 
    396 /* stabline - emit line number information for source coordinate *cp */
    397 static void I(stabline)(Coordinate *cp) {
    398 	if (cp->file)
    399 		print("%s:", cp->file);
    400 	print("%d.%d:\n", cp->y, cp->x);
    401 }
    402 
    403 static void I(stabsym)(Symbol p) {}
    404 static void I(stabtype)(Symbol p) {}
    405 
    406 Interface symbolicIR = {
    407 	1, 1, 0,	/* char */
    408 	2, 2, 0,	/* short */
    409 	4, 4, 0,	/* int */
    410 	4, 4, 0,	/* long */
    411 	4, 4, 0,	/* long long */
    412 	4, 4, 1,	/* float */
    413 	8, 8, 1,	/* double */
    414 	8, 8, 1,	/* long double */
    415 	4, 4, 0,	/* T* */
    416 	0, 4, 0,	/* struct */
    417 	0,		/* little_endian */
    418 	0,		/* mulops_calls */
    419 	0,		/* wants_callb */
    420 	1,		/* wants_argb */
    421 	1,		/* left_to_right */
    422 	1,		/* wants_dag */
    423 	0,		/* unsigned_char */
    424 	I(address),
    425 	I(blockbeg),
    426 	I(blockend),
    427 	I(defaddress),
    428 	I(defconst),
    429 	I(defstring),
    430 	I(defsymbol),
    431 	I(emit),
    432 	I(export),
    433 	I(function),
    434 	I(gen),
    435 	I(global),
    436 	I(import),
    437 	I(local),
    438 	I(progbeg),
    439 	I(progend),
    440 	I(segment),
    441 	I(space),
    442 	I(stabblock),
    443 	I(stabend),
    444 	I(stabfend),
    445 	I(stabinit),
    446 	I(stabline),
    447 	I(stabsym),
    448 	I(stabtype)
    449 };
    450 
    451 Interface symbolic64IR = {
    452 	1, 1, 0,	/* char */
    453 	2, 2, 0,	/* short */
    454 	4, 4, 0,	/* int */
    455 	8, 8, 0,	/* long */
    456 	8, 8, 0,	/* long long */
    457 	4, 4, 1,	/* float */
    458 	8, 8, 1,	/* double */
    459 	8, 8, 1,	/* long double */
    460 	8, 8, 0,	/* T* */
    461 	0, 1, 0,	/* struct */
    462 	1,		/* little_endian */
    463 	0,		/* mulops_calls */
    464 	0,		/* wants_callb */
    465 	1,		/* wants_argb */
    466 	1,		/* left_to_right */
    467 	1,		/* wants_dag */
    468 	0,		/* unsigned_char */
    469 	I(address),
    470 	I(blockbeg),
    471 	I(blockend),
    472 	I(defaddress),
    473 	I(defconst),
    474 	I(defstring),
    475 	I(defsymbol),
    476 	I(emit),
    477 	I(export),
    478 	I(function),
    479 	I(gen),
    480 	I(global),
    481 	I(import),
    482 	I(local),
    483 	I(progbeg),
    484 	I(progend),
    485 	I(segment),
    486 	I(space),
    487 	I(stabblock),
    488 	I(stabend),
    489 	I(stabfend),
    490 	I(stabinit),
    491 	I(stabline),
    492 	I(stabsym),
    493 	I(stabtype)
    494 };