Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

pass2.c (16805B)


      1 #include "c.h"
      2 #include "rcc.h"
      3 #if WIN32
      4 #include <fcntl.h>
      5 #include <io.h>
      6 #endif
      7 
      8 
      9 Interface *IR = NULL;
     10 int Aflag;		/* >= 0 if -A specified */
     11 int Pflag;		/* != 0 if -P specified */
     12 int glevel;		/* == [0-9] if -g[0-9] specified */
     13 int xref;		/* != 0 for cross-reference data */
     14 Symbol YYnull;		/* _YYnull  symbol if -n or -nvalidate specified */
     15 Symbol YYcheck;		/* _YYcheck symbol if -nvalidate,check specified */
     16 
     17 static int verbose = 1;
     18 #define VERBOSE(n,arg) (verbose >= n ? (void)(arg):(void)0)
     19 static int nuids;
     20 static rcc_item_ty *items;
     21 static void **itemmap;
     22 
     23 static void *uid2type(int uid) {
     24 	assert(uid >= 0 && uid < nuids);
     25 	if (itemmap[uid] == NULL) {
     26 		Type ty;
     27 		rcc_type_ty type = (void *)items[uid];
     28 		assert(items[uid]);
     29 		assert(items[uid]->uid == uid);
     30 		assert(items[uid]->kind == rcc_Type_enum);
     31 		type = items[uid]->v.rcc_Type.type;
     32 		assert(type);
     33 		switch (type->kind) {
     34 		case rcc_INT_enum:
     35 			ty = btot(INT, type->size);
     36 			assert(ty->align == type->align);
     37 			break;
     38 		case rcc_UNSIGNED_enum:
     39 			ty = btot(UNSIGNED, type->size);
     40 			assert(ty->align == type->align);
     41 			break;
     42 		case rcc_FLOAT_enum:
     43 			ty = btot(FLOAT, type->size);
     44 			assert(ty->align == type->align);
     45 			break;
     46 		case rcc_VOID_enum:
     47 			ty = voidtype;
     48 			break;
     49 		case rcc_POINTER_enum:
     50 			ty = ptr(uid2type(type->v.rcc_POINTER.type));
     51 			break;
     52 		case rcc_ARRAY_enum:
     53 			ty = uid2type(type->v.rcc_ARRAY.type);
     54 			assert(ty->size > 0);
     55 			ty = array(ty, type->size/ty->size, 0);
     56 			break;
     57 		case rcc_CONST_enum:
     58 			ty = qual(CONST, uid2type(type->v.rcc_CONST.type));
     59 			break;
     60 		case rcc_VOLATILE_enum:
     61 			ty = qual(VOLATILE, uid2type(type->v.rcc_VOLATILE.type));
     62 			break;
     63 		case rcc_ENUM_enum: {
     64 			int i, n = Seq_length(type->v.rcc_ENUM.ids);
     65 			ty = newstruct(ENUM, string(type->v.rcc_ENUM.tag));
     66 			ty->type = inttype;
     67 			ty->size = ty->type->size;
     68 			ty->align = ty->type->align;
     69 			ty->u.sym->u.idlist = newarray(n + 1, sizeof *ty->u.sym->u.idlist, PERM);
     70 			for (i = 0; i < n; i++) {
     71 				rcc_enum__ty e = Seq_remlo(type->v.rcc_ENUM.ids);
     72 				Symbol p = install(e->id, &identifiers, GLOBAL, PERM);
     73 				p->type = ty;
     74 				p->sclass = ENUM;
     75 				p->u.value = e->value;
     76 				ty->u.sym->u.idlist[i] = p;
     77 				free(e);
     78 			}
     79 			ty->u.sym->u.idlist[i] = NULL;
     80 			Seq_free(&type->v.rcc_ENUM.ids);
     81 			break;
     82 			}
     83 		case rcc_STRUCT_enum: case rcc_UNION_enum: {
     84 			int i, n;
     85 			Field *tail;
     86 			list_ty fields;
     87 			if (type->kind == rcc_STRUCT_enum) {
     88 				ty = newstruct(STRUCT, string(type->v.rcc_STRUCT.tag));
     89 				fields = type->v.rcc_STRUCT.fields;
     90 			} else {
     91 				ty = newstruct(UNION, string(type->v.rcc_UNION.tag));
     92 				fields = type->v.rcc_UNION.fields;
     93 			}
     94 			itemmap[uid] = ty;	/* recursive types */
     95 			ty->size = type->size;
     96 			ty->align = type->align;
     97 			tail = &ty->u.sym->u.s.flist;
     98 			n = Seq_length(fields);
     99 			for (i = 0; i < n; i++) {
    100 				rcc_field_ty field = Seq_remlo(fields);
    101 				NEW0(*tail, PERM);
    102 				(*tail)->name = (char *)field->id;
    103 				(*tail)->type = uid2type(field->type);
    104 				(*tail)->offset = field->offset;
    105 				(*tail)->bitsize = field->bitsize;
    106 				(*tail)->lsb = field->lsb;
    107 				if (isconst((*tail)->type))
    108 					ty->u.sym->u.s.cfields = 1;
    109 				if (isvolatile((*tail)->type))
    110 					ty->u.sym->u.s.vfields = 1;
    111 				tail = &(*tail)->link;
    112 				free(field);
    113 			}
    114 			Seq_free(&fields);
    115 			break;
    116 			}
    117 		case rcc_FUNCTION_enum: {
    118 			int n = Seq_length(type->v.rcc_FUNCTION.formals);
    119 			if (n > 0) {
    120 				int i;
    121 				Type *proto = newarray(n + 1, sizeof *proto, PERM);
    122 				for (i = 0; i < n; i++) {
    123 					int *formal = Seq_remlo(type->v.rcc_FUNCTION.formals);
    124 					proto[i] = uid2type(*formal);
    125 					free(formal);
    126 				}
    127 				proto[i] = NULL;
    128 				ty = func(uid2type(type->v.rcc_FUNCTION.type), proto, 0);
    129 			} else
    130 				ty = func(uid2type(type->v.rcc_FUNCTION.type), NULL, 1);
    131 			Seq_free(&type->v.rcc_FUNCTION.formals);
    132 			break;
    133 			}
    134 		default: assert(0);
    135 		}
    136 		if (itemmap[uid] == NULL) {
    137 			itemmap[uid] = ty;
    138 			free(type);
    139 			free(items[uid]);
    140 			items[uid] = NULL;
    141 		} else
    142 			assert(itemmap[uid] == ty);
    143 	}
    144 	return itemmap[uid];
    145 }
    146 
    147 static Symbol uid2symbol(int uid) {
    148 	assert(uid >= 0 && uid < nuids);
    149 	if (itemmap[uid] == NULL) {
    150 		Symbol p;
    151 		rcc_symbol_ty symbol;
    152 		assert(items[uid]);
    153 		assert(items[uid]->uid == uid);
    154 		assert(items[uid]->kind == rcc_Symbol_enum);
    155 		symbol = items[uid]->v.rcc_Symbol.symbol;
    156 		assert(symbol);
    157 		NEW0(p, PERM);
    158 		p->name = (char *)symbol->id;
    159 		p->scope = symbol->scope;
    160 		p->sclass = symbol->sclass;
    161 		p->type = uid2type(symbol->type);
    162 #define xx(f,n) p->f = symbol->flags>>n;
    163 		xx(structarg,0)
    164 		xx(addressed,1)
    165 		xx(computed,2)
    166 		xx(temporary,3)
    167 		xx(generated,4)
    168 #undef xx
    169 		p->ref = symbol->ref/10000.0;
    170 		assert(p->scope != CONSTANTS && p->scope != LABELS);
    171 		if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
    172 			(*IR->defsymbol)(p);
    173 		itemmap[uid] = p;
    174 		free(symbol);
    175 		free(items[uid]);
    176 		items[uid] = NULL;
    177 	}
    178 	return itemmap[uid];
    179 }
    180 
    181 #define xx(s) static void do##s(rcc_interface_ty);
    182 xx(Export)
    183 xx(Import)
    184 xx(Global)
    185 xx(Local)
    186 xx(Address)
    187 xx(Segment)
    188 xx(Defaddress)
    189 xx(Deflabel)
    190 xx(Defconst)
    191 xx(Defconstf)
    192 xx(Defstring)
    193 xx(Space)
    194 xx(Function)
    195 xx(Blockbeg)
    196 xx(Blockend)
    197 xx(Forest)
    198 #undef xx
    199 static void (*doX[])(rcc_interface_ty in) = {
    200 #define xx(s) 0,
    201 xx(Export)
    202 xx(Import)
    203 xx(Global)
    204 xx(Local)
    205 xx(Address)
    206 xx(Segment)
    207 xx(Defaddress)
    208 xx(Deflabel)
    209 xx(Defconst)
    210 xx(Defconstf)
    211 xx(Defstring)
    212 xx(Space)
    213 xx(Function)
    214 xx(Blockbeg)
    215 xx(Blockend)
    216 xx(Forest)
    217 	0
    218 #undef xx
    219 };
    220 
    221 static void interface(rcc_interface_ty in) {
    222 	assert(in);
    223 	(*doX[in->kind])(in);
    224 	free(in);
    225 }
    226 
    227 static void doExport(rcc_interface_ty in) {
    228 	(*IR->export)(uid2symbol(in->v.rcc_Export.p));
    229 }
    230 
    231 static void doImport(rcc_interface_ty in) {
    232 	Symbol p = uid2symbol(in->v.rcc_Export.p);
    233 
    234 	(*IR->import)(p);
    235 	p->defined = 1;
    236 }
    237 
    238 static void doGlobal(rcc_interface_ty in) {
    239 	Symbol p = uid2symbol(in->v.rcc_Global.p);
    240 
    241 	p->u.seg = in->v.rcc_Global.seg;
    242 	(*IR->global)(p);
    243 	p->defined = 1;
    244 }
    245 
    246 static void doLocal(rcc_interface_ty in) {
    247 	int uid = in->v.rcc_Local.uid;
    248 
    249 	assert(uid >= 0 && uid < nuids);
    250 	assert(items[uid] == NULL);
    251 	items[uid] = rcc_Symbol(uid, in->v.rcc_Local.p);
    252 	if (in->v.rcc_Local.p->scope >= LOCAL)
    253 		addlocal(uid2symbol(uid));
    254 }
    255 
    256 static void doAddress(rcc_interface_ty in) {
    257 	int uid = in->v.rcc_Address.uid;
    258 	Symbol p = uid2symbol(in->v.rcc_Address.p);
    259 
    260 	assert(uid >= 0 && uid < nuids);
    261 	assert(items[uid] == NULL);
    262 	items[uid] = rcc_Symbol(uid, in->v.rcc_Address.q);
    263 	if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN)
    264 		(*IR->address)(uid2symbol(uid), p, in->v.rcc_Address.n);
    265 	else {
    266 		Code cp = code(Address);
    267 		cp->u.addr.sym = uid2symbol(uid);
    268 		cp->u.addr.base = p;
    269 		cp->u.addr.offset = in->v.rcc_Address.n;
    270 	}
    271 }
    272 
    273 static void doSegment(rcc_interface_ty in) {
    274 	(*IR->segment)(in->v.rcc_Segment.seg);
    275 }
    276 
    277 static void doDefaddress(rcc_interface_ty in) {
    278 	(*IR->defaddress)(uid2symbol(in->v.rcc_Defaddress.p));
    279 }
    280 
    281 static void doDeflabel(rcc_interface_ty in) {
    282 	(*IR->defaddress)(findlabel(in->v.rcc_Deflabel.label));
    283 }
    284 
    285 static void doDefconst(rcc_interface_ty in) {
    286 	Value v;
    287 
    288 	v.i = in->v.rcc_Defconst.value;
    289 	(*IR->defconst)(in->v.rcc_Defconst.suffix, in->v.rcc_Defconst.size, v);
    290 }
    291 
    292 static void doDefconstf(rcc_interface_ty in) {
    293 	Value v;
    294 	unsigned *p = (unsigned *)&v.d;
    295 
    296 	p[swap]   = in->v.rcc_Defconstf.value->msb;
    297 	p[1-swap] = in->v.rcc_Defconstf.value->lsb;
    298 	(*IR->defconst)(F, in->v.rcc_Defconstf.size, v);
    299 	free(in->v.rcc_Defconstf.value);
    300 }
    301 
    302 static void doDefstring(rcc_interface_ty in) {
    303 	(*IR->defstring)(in->v.rcc_Defstring.s.len, (char *)in->v.rcc_Defstring.s.str);
    304 	free((char *)in->v.rcc_Defstring.s.str);
    305 }
    306 
    307 static void doSpace(rcc_interface_ty in) {
    308 	(*IR->space)(in->v.rcc_Space.n);
    309 }
    310 
    311 static void doFunction(rcc_interface_ty in) {
    312 	int i, n;
    313 	Symbol *caller, *callee;
    314 
    315 	/*
    316 	 Initialize:
    317 	  define the function symbol,
    318 	  initialize callee and caller arrays.
    319 	*/
    320 	cfunc = uid2symbol(in->v.rcc_Function.f);
    321 	labels = table(NULL, LABELS);
    322 	enterscope();
    323 	n = Seq_length(in->v.rcc_Function.caller);
    324 	caller = newarray(n + 1, sizeof *caller, FUNC);
    325 	for (i = 0; i < n; i++) {
    326 		int *uid = Seq_remlo(in->v.rcc_Function.caller);
    327 		caller[i] = uid2symbol(*uid);
    328 		free(uid);
    329 	}
    330 	caller[i] = NULL;
    331 	Seq_free(&in->v.rcc_Function.caller);
    332 	callee = newarray(n + 1, sizeof *callee, FUNC);
    333 	for (i = 0; i < n; i++) {
    334 		int *uid = Seq_remlo(in->v.rcc_Function.callee);
    335 		callee[i] = uid2symbol(*uid);
    336 		free(uid);
    337 	}
    338 	callee[i] = NULL;
    339 	Seq_free(&in->v.rcc_Function.callee);
    340 	cfunc->u.f.callee = callee;
    341 	cfunc->defined = 1;
    342 	/*
    343 	 Initialize the code list,
    344 	  traverse the interfaces inside the function;
    345 	  each call appends code list entries.
    346 	*/
    347 	codelist = &codehead;
    348 	codelist->next = NULL;
    349 	n = Seq_length(in->v.rcc_Function.codelist);
    350 	for (i = 0; i < n; i++)
    351 		interface(Seq_remlo(in->v.rcc_Function.codelist));
    352 	Seq_free(&in->v.rcc_Function.codelist);
    353 	/*
    354 	 Call the back end,
    355 	 Wrap-up.
    356 	*/
    357 	exitscope();
    358 	(*IR->function)(cfunc, caller, callee, in->v.rcc_Function.ncalls);
    359 	cfunc = NULL;
    360 	labels = NULL;
    361 }
    362 
    363 static struct block {
    364 	Code begin;
    365 	struct block *prev;
    366 } *blockstack = NULL;
    367 
    368 static void doBlockbeg(rcc_interface_ty in) {
    369 	struct block *b;
    370 	Code cp = code(Blockbeg);
    371 
    372 	enterscope();
    373 	cp->u.block.level = level;
    374 	cp->u.block.locals = newarray(1, sizeof *cp->u.block.locals, FUNC);
    375 	cp->u.block.locals[0] = NULL;
    376 	cp->u.block.identifiers = NULL;
    377 	cp->u.block.types = NULL;
    378 	NEW(b, FUNC);
    379 	b->begin = cp;
    380 	b->prev = blockstack;
    381 	blockstack = b;
    382 }
    383 
    384 static void doBlockend(rcc_interface_ty in) {
    385 	assert(blockstack);
    386 	code(Blockend)->u.begin = blockstack->begin;
    387 	blockstack = blockstack->prev;
    388 	exitscope();
    389 }
    390 
    391 static Node visit(rcc_node_ty node) {
    392 	int op;
    393 	Node left = NULL, right = NULL, p = NULL;
    394 	Symbol sym = NULL;
    395 
    396 	switch (node->kind) {
    397 #define T(x) rcc_##x##_enum
    398 	case T(CSE): {
    399 		Symbol q = uid2symbol(node->v.rcc_CSE.uid);
    400 		assert(q->temporary);
    401 		q->u.t.cse = p = visit(node->v.rcc_CSE.node);
    402 		break;
    403 		}
    404 	case T(CNST): {
    405 		Value v;
    406 		v.i = node->v.rcc_CNST.value;
    407 		sym = constant(btot(node->suffix, node->size), v);
    408 		op = CNST;
    409 		break;
    410 		}
    411 	case T(CNSTF): {
    412 		Value v;
    413 		unsigned *p = (unsigned *)&v.d;
    414 		p[swap]   = node->v.rcc_CNSTF.value->msb;
    415 		p[1-swap] = node->v.rcc_CNSTF.value->lsb;
    416 		sym = constant(btot(node->suffix, node->size), v);
    417 		free(node->v.rcc_CNSTF.value);
    418 		op = CNST;
    419 		break;
    420 		}
    421 	case T(ARG):
    422 		p = newnode(ARG + node->suffix + sizeop(node->size),
    423 			visit(node->v.rcc_ARG.left), NULL,
    424 			intconst(node->v.rcc_ARG.len));
    425 		p->syms[1] = intconst(node->v.rcc_ARG.align);
    426 		break;
    427 	case T(ASGN):
    428 		p = newnode(ASGN + node->suffix + sizeop(node->size),
    429 			visit(node->v.rcc_ASGN.left), visit(node->v.rcc_ASGN.right),
    430 			intconst(node->v.rcc_ASGN.len));
    431 		p->syms[1] = intconst(node->v.rcc_ASGN.align);
    432 		break;
    433 	case T(CVT):
    434 		op = node->v.rcc_CVT.op;
    435 		left = visit(node->v.rcc_CVT.left);
    436 		sym = intconst(node->v.rcc_CVT.fromsize);
    437 		break;
    438 	case T(CALL):
    439 		op = CALL;
    440 		left = visit(node->v.rcc_CALL.left);
    441 		NEW0(sym, FUNC);
    442 		sym->type = uid2type(node->v.rcc_CALL.type);
    443 		break;
    444 	case T(CALLB):
    445 		op = CALL;
    446 		left  = visit(node->v.rcc_CALLB.left);
    447 		right = visit(node->v.rcc_CALLB.right);
    448 		NEW0(sym, FUNC);
    449 		sym->type = uid2type(node->v.rcc_CALLB.type);
    450 		break;
    451 	case T(RET):
    452 		op = RET;
    453 		break;
    454 	case T(ADDRG):
    455 		op = ADDRG;
    456 		sym = uid2symbol(node->v.rcc_ADDRG.uid);
    457 		break;
    458 	case T(ADDRL):
    459 		op = ADDRL;
    460 		sym = uid2symbol(node->v.rcc_ADDRG.uid);
    461 		break;
    462 	case T(ADDRF):
    463 		op = ADDRF;
    464 		sym = uid2symbol(node->v.rcc_ADDRG.uid);
    465 		break;
    466 	case T(Unary):
    467 		op = node->v.rcc_Unary.op;
    468 		left = visit(node->v.rcc_Unary.left);
    469 		break;
    470 	case T(Binary):
    471 		op = node->v.rcc_Binary.op;
    472 		left  = visit(node->v.rcc_Binary.left);
    473 		right = visit(node->v.rcc_Binary.right);
    474 		break;
    475 	case T(Compare):
    476 		op = node->v.rcc_Compare.op;
    477 		left  = visit(node->v.rcc_Compare.left);
    478 		right = visit(node->v.rcc_Compare.right);
    479 		sym = findlabel(node->v.rcc_Compare.label);
    480 		break;
    481 	case T(LABEL):
    482 		op = LABEL;
    483 		sym = findlabel(node->v.rcc_LABEL.label);
    484 		break;
    485 	case T(BRANCH):
    486 		op = JUMP;
    487 		left = newnode(ADDRG+P+sizeop(voidptype->size), NULL, NULL, findlabel(node->v.rcc_BRANCH.label));
    488 		break;
    489 #undef T
    490 	default: assert(0);
    491 	}
    492 	if (p == NULL)
    493 		p = newnode(op + node->suffix + sizeop(node->size), left, right, sym);
    494 	free(node);
    495 	return p;
    496 }
    497 
    498 static void doForest(rcc_interface_ty in) {
    499 	Node *tail = &code(Gen)->u.forest;
    500 	int i, n = Seq_length(in->v.rcc_Forest.nodes);
    501 
    502 	for (i = 0; i < n; i++) {
    503 		*tail = visit(Seq_remlo(in->v.rcc_Forest.nodes));
    504 		assert(*tail);
    505 		tail = &(*tail)->link;
    506 	}
    507 	*tail = NULL;
    508 	Seq_free(&in->v.rcc_Forest.nodes);
    509 }
    510 
    511 int main(int argc, char *argv[]) {
    512 	int i, version;
    513 	float stamp = (assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
    514 ;
    515 	char *infile = NULL, *outfile = NULL;
    516 	rcc_program_ty pickle;
    517 
    518 	for (i = 1; i < argc; i++)
    519 		if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
    520 			if (infile == NULL)
    521 				infile = argv[i];
    522 			else if (outfile == NULL)
    523 				outfile = argv[i];
    524 		}
    525 	if (infile != NULL && strcmp(infile, "-") != 0
    526 	&& freopen(infile, "rb", stdin) == NULL) {
    527 		fprint(stderr, "%s: can't read `%s'\n", argv[0], infile);
    528 		exit(EXIT_FAILURE);
    529 	}
    530 #if WIN32
    531 	else
    532 		_setmode(_fileno(stdin), _O_BINARY);
    533 #endif
    534 	if (outfile != NULL && strcmp(outfile, "-") != 0
    535 	&& freopen(outfile, "w", stdout) == NULL) {
    536 		fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile);
    537 		exit(EXIT_FAILURE);
    538 	}
    539 	version = read_int(stdin);
    540 	assert(version/100 == (int)stamp);
    541 	pickle = rcc_read_program(stdin);
    542 	argc = pickle->argc;
    543 	argv = newarray(argc + 1, sizeof *argv, PERM);
    544 	{
    545 		for (i = 0; i < argc; i++) {
    546 			string_ty *arg = Seq_remlo(pickle->argv);
    547 			argv[i] = (char *)arg->str;
    548 			free(arg);
    549 		}
    550 		argv[i] = NULL;
    551 		assert(i == argc);
    552 		Seq_free(&pickle->argv);
    553 	}
    554 	for (i = argc - 1; i > 0; i--)
    555 		if (strncmp(argv[i], "-target=", 8) == 0)
    556 			break;
    557 	if (i > 0) {
    558 		int j;
    559 		for (j = 0; bindings[j].name && bindings[j].ir; j++)
    560 			if (strcmp(&argv[i][8], bindings[j].name) == 0) {
    561 				IR = bindings[j].ir;
    562 				break;
    563 			}
    564 	}
    565 	if (!IR) {
    566 		fprint(stderr, "%s: unknown target", argv[0]);
    567 		if (i > 0)
    568 			fprint(stderr, " `%s'", &argv[i][8]);
    569 		fprint(stderr, "; must specify one of\n");
    570 		for (i = 0; bindings[i].name; i++)
    571 			fprint(stderr, "\t-target=%s\n", bindings[i].name);
    572 		exit(EXIT_FAILURE);
    573 	}
    574 	IR->wants_dag = 0;	/* pickle's hold trees */
    575 	init(argc, argv);
    576 	genlabel(pickle->nlabels);
    577 	level = GLOBAL;
    578 	{
    579 		int i, count;
    580 		nuids = pickle->nuids;
    581 		items = newarray(nuids, sizeof *items, PERM);
    582 		itemmap = newarray(nuids, sizeof *items, PERM);
    583 		for (i = 0; i < nuids; i++) {
    584 			itemmap[i] = NULL;
    585 			items[i] = NULL;
    586 		}
    587 		(*IR->progbeg)(argc, argv);
    588 		count = Seq_length(pickle->items);
    589 		for (i = 0; i < count; i++) {
    590 			rcc_item_ty item = Seq_remlo(pickle->items);
    591 			int uid = item->uid;
    592 			assert(uid >= 0 && uid < nuids);
    593 			assert(items[uid] == NULL);
    594 			items[uid] = item;
    595 		}
    596 		Seq_free(&pickle->items);
    597 #define xx(s) assert(rcc_##s##_enum < sizeof doX/sizeof doX[0] && doX[rcc_##s##_enum]==0); \
    598 	      doX[rcc_##s##_enum] = do##s;
    599 	      xx(Export)
    600 	      xx(Import)
    601 	      xx(Global)
    602 	      xx(Local)
    603 	      xx(Address)
    604 	      xx(Segment)
    605 	      xx(Defaddress)
    606 	      xx(Deflabel)
    607 	      xx(Defconst)
    608 	      xx(Defconstf)
    609 	      xx(Defstring)
    610 	      xx(Space)
    611 	      xx(Function)
    612 	      xx(Blockbeg)
    613 	      xx(Blockend)
    614 	      xx(Forest)
    615 #undef xx
    616 		count = Seq_length(pickle->interfaces);
    617 		for (i = 0; i < count; i++)
    618 			interface(Seq_remlo(pickle->interfaces));
    619 		Seq_free(&pickle->interfaces);
    620 		free(pickle);
    621 		(*IR->progend)();
    622 	}
    623 	deallocate(PERM);
    624 	return errcnt > 0;
    625 }
    626 
    627 /* main_init - process program arguments */
    628 void main_init(int argc, char *argv[]) {
    629 	int i;
    630 	static int inited;
    631 
    632 	if (inited)
    633 		return;
    634 	inited = 1;
    635 	for (i = 1; i < argc; i++)
    636 		if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0)
    637 			glevel = 2;
    638 		else if (strcmp(argv[i], "-w") == 0)
    639 			wflag++;
    640 		else if (strcmp(argv[i], "-v") == 0) {
    641 			fprint(stderr, "%s %s\n", argv[0], rcsid);
    642 			verbose++;
    643 		} else if (strncmp(argv[i], "-errout=", 8) == 0) {
    644 			FILE *f = fopen(argv[i]+8, "w");
    645 			if (f == NULL) {
    646 				fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8);
    647 				exit(EXIT_FAILURE);
    648 			}
    649 			fclose(f);
    650 			f = freopen(argv[i]+8, "w", stderr);
    651 			assert(f);
    652 		} else if (strncmp(argv[i], "-e", 2) == 0) {
    653 			int x;
    654 			if ((x = strtol(&argv[i][2], NULL, 0)) > 0)
    655 				errlimit = x;
    656 		}
    657 }
    658 
    659 void init(int argc, char *argv[]) {
    660 	{extern void main_init(int, char *[]); main_init(argc, argv);}
    661 	{extern void prof_init(int, char *[]); prof_init(argc, argv);}
    662 	{extern void trace_init(int, char *[]); trace_init(argc, argv);}
    663 	{extern void type_init(int, char *[]); type_init(argc, argv);}
    664 	{extern void x86linux_init(int, char *[]); x86linux_init(argc, argv);}
    665 }