Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

asdl.c (9925B)


      1 #include "c.h"
      2 #include "rcc.h"
      3 #if WIN32
      4 #include <fcntl.h>
      5 #include <io.h>
      6 #endif
      7 
      8 
      9 static list_ty interfaces;
     10 static rcc_program_ty pickle;
     11 
     12 char *string(const char *str) {
     13 	return (char *)Atom_string(str);
     14 }
     15 
     16 char *stringd(long n) {
     17 	return (char *)Atom_int(n);
     18 }
     19 
     20 char *stringn(const char *str, int len) {
     21 	return (char *)Atom_new(str, len);
     22 }
     23 
     24 static void put(rcc_interface_ty node) {
     25 	Seq_addhi(interfaces, node);
     26 }
     27 
     28 static int typeuid(Type ty) {
     29 	rcc_type_ty type;
     30 
     31 	assert(ty);
     32 	if (ty->x.typeno != 0)
     33 		return ty->x.typeno;
     34 	ty->x.typeno = pickle->nuids++;
     35 	switch (ty->op) {
     36 #define xx(op) case op: type = rcc_##op(ty->size, ty->align); break
     37 	xx(INT);
     38 	xx(UNSIGNED);
     39 	xx(FLOAT);
     40 	xx(VOID);
     41 #undef xx
     42 #define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break
     43 	xx(POINTER);
     44 	xx(ARRAY);
     45 	xx(CONST);
     46 	xx(VOLATILE);
     47 #undef xx
     48 	case CONST+VOLATILE:
     49 		type = rcc_CONST(ty->size, ty->align, typeuid(ty->type));
     50 		break;
     51 	case ENUM: {
     52 		list_ty ids = Seq_new(0);
     53 		int i;
     54 		for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++)
     55 			Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name,
     56 				ty->u.sym->u.idlist[i]->u.value));
     57 		assert(i > 0);
     58 		type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids);
     59 		break;
     60 		}
     61 	case STRUCT: case UNION: {
     62 		list_ty fields = Seq_new(0);
     63 		Field p = fieldlist(ty);
     64 		for ( ; p != NULL; p = p->link)
     65 			Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb));
     66 		if (ty->op == STRUCT)
     67 			type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields);
     68 		else
     69 			type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields);
     70 		break;
     71 		}
     72 	case FUNCTION: {
     73 		list_ty formals = Seq_new(0);
     74 		if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) {
     75 			int i;
     76 			for (i = 0; ty->u.f.proto[i] != NULL; i++)
     77 				Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i])));
     78 		} else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL)
     79 			Seq_addhi(formals, to_generic_int(typeuid(voidtype)));
     80 		type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals);
     81 		break;
     82 		}
     83 	default: assert(0);
     84 	}
     85 	Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type));
     86 	return ty->x.typeno;
     87 }
     88 
     89 static int symboluid(Symbol p) {
     90 	assert(p);
     91 	assert(p->scope != CONSTANTS && p->scope != LABELS);
     92 	if (p->x.offset == 0)
     93 		p->x.offset = pickle->nuids++;
     94 	return p->x.offset;
     95 }
     96 
     97 static rcc_symbol_ty mk_symbol(Symbol p) {
     98 	int flags = 0, ref = 10000*p->ref;
     99 
    100 	if (p->ref > 0 && ref == 0)
    101 		ref++;
    102 #define xx(f,n) flags |= p->f<<n;
    103 	xx(structarg,0)
    104 	xx(addressed,1)
    105 	xx(computed,2)
    106 	xx(temporary,3)
    107 	xx(generated,4)
    108 #undef xx
    109 	return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags);
    110 }
    111 
    112 static rcc_real_ty mk_real(int size, Value v) {
    113 	unsigned *p = (unsigned *)&v.d;
    114 	return rcc_real(p[swap], p[1-swap]);
    115 }
    116 
    117 static void asdl_segment(int n) {
    118 	static int cseg;
    119 
    120 	if (cseg != n)
    121 		put(rcc_Segment(cseg = n));
    122 }
    123 
    124 static void asdl_address(Symbol q, Symbol p, long n) {
    125 	assert(q->x.offset == 0);
    126 	put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n));
    127 }
    128 
    129 static void asdl_blockbeg(Env *e) {
    130 	put(rcc_Blockbeg());
    131 }
    132 
    133 static void asdl_blockend(Env *e) {
    134 	put(rcc_Blockend());
    135 }
    136 
    137 static void asdl_defaddress(Symbol p) {
    138 	if (p->scope == LABELS)
    139 		put(rcc_Deflabel(p->u.l.label));
    140 	else
    141 		put(rcc_Defaddress(symboluid(p)));
    142 }
    143 
    144 static void asdl_defconst(int suffix, int size, Value v) {
    145 	switch (suffix) {
    146 	case I: put(rcc_Defconst(suffix, size, v.i)); return;
    147 	case U: put(rcc_Defconst(suffix, size, v.u)); return;
    148 	case P: put(rcc_Defconst(suffix, size, (unsigned long)v.p)); return;	/* FIXME */
    149 	case F: put(rcc_Defconstf(size, mk_real(size, v))); return;
    150 	assert(0);
    151 	}
    152 }
    153 
    154 static void asdl_defstring(int len, char *str) {
    155 	put(rcc_Defstring(Text_box(stringn(str, len), len)));
    156 }
    157 
    158 static void asdl_defsymbol(Symbol p) {
    159 	if (p->scope >= GLOBAL)
    160 		symboluid(p);
    161 }
    162 
    163 static Symbol temps;
    164 
    165 static rcc_node_ty visit(Node p) {
    166 	Symbol q;
    167 	rcc_node_ty left = NULL, right = NULL;
    168 	int suffix = optype(p->op), size = opsize(p->op);
    169 
    170 	assert(p);
    171 	for (q = temps; q; q = q->u.t.next)
    172 		if (q->u.t.cse == p) {
    173 			q->u.t.cse = NULL;
    174 			return rcc_CSE(0, 0, symboluid(q), visit(p));
    175 		}
    176 	if (p->kids[0] != NULL)
    177 		left = visit(p->kids[0]);
    178 	if (p->kids[1] != NULL)
    179 		right = visit(p->kids[1]);
    180 	switch (specific(p->op)) {
    181 	case CNST+F:
    182 		assert(p->syms[0]);
    183 		return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v));
    184 	case CALL+B:
    185 		assert(p->syms[0]);
    186 		assert(p->syms[0]->type);
    187 		return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type));
    188 	case RET+V:
    189 		return rcc_RET(suffix, size);
    190 	case LABEL+V:
    191 		assert(p->syms[0]);
    192 		return rcc_LABEL(suffix, size, p->syms[0]->u.l.label);
    193 	}
    194 	switch (generic(p->op)) {
    195 	case CNST:
    196 		assert(p->syms[0]);
    197 		return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i);	/* FIXME */
    198 	case ARG:
    199 		assert(p->syms[0]);
    200 		return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
    201 	case ASGN:
    202 		assert(p->syms[0]);
    203 		assert(p->syms[1]);
    204 		return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i);
    205 	case CVF: case CVI: case CVP: case CVU:
    206 		assert(p->syms[0]);
    207 		return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i);
    208 	case CALL:
    209 		assert(p->syms[0]);
    210 		assert(p->syms[0]->type);
    211 		return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type));
    212 #define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0]))
    213 	xx(ADDRG);
    214 	xx(ADDRF);
    215 #undef xx
    216 	case ADDRL:
    217 		if (!p->syms[0]->defined)
    218 			(*IR->local)(p->syms[0]);
    219 		p->syms[0]->defined = 1;
    220 		return rcc_ADDRL(suffix, size, symboluid(p->syms[0]));
    221 	case JUMP:
    222 		if (p->syms[0] != NULL)
    223 			return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label);
    224 		return rcc_Unary(suffix, size, generic(p->op), left);
    225 	case INDIR: case RET: case NEG: case BCOM: 
    226 		return rcc_Unary(suffix, size, generic(p->op), left);
    227 	case BOR: case BAND: case BXOR: case RSH: case LSH:
    228 	case ADD: case SUB: case DIV: case MUL: case MOD:
    229 		return rcc_Binary(suffix, size, generic(p->op), left, right);
    230 	case EQ: case NE: case GT: case GE: case LE: case LT:
    231 		assert(p->syms[0]);
    232 		return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label);
    233 	}
    234 	assert(0);
    235 	return NULL;
    236 }
    237 
    238 static void asdl_emit(Node p) {}
    239 
    240 static void asdl_local(Symbol p) {
    241 	assert(p->x.offset == 0);
    242 	put(rcc_Local(symboluid(p), mk_symbol(p)));
    243 	if (p->temporary && p->u.t.cse) {
    244 		p->u.t.next = temps;
    245 		temps = p;
    246 	}
    247 }
    248 
    249 static Symbol pending = NULL;
    250 
    251 static void dopending(Symbol p) {
    252 	if (pending != NULL) {
    253 		int uid = symboluid(pending);
    254 		rcc_symbol_ty symbol = mk_symbol(pending);
    255 		Seq_addhi(pickle->items, rcc_Symbol(uid, symbol));
    256 	}
    257 	pending = p;
    258 }
    259 
    260 
    261 static void asdl_export(Symbol p) {
    262 	put(rcc_Export(symboluid(p)));
    263 }
    264 
    265 static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
    266 	list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0);
    267 	int i;
    268 
    269 	dopending(f);
    270 	for (i = 0; caller[i] != NULL; i++) {
    271 		asdl_local(caller[i]);
    272 		Seq_addhi(callerlist, to_generic_int(symboluid(caller[i])));
    273 	}
    274 	for (i = 0; callee[i] != NULL; i++) {
    275 		asdl_local(callee[i]);
    276 		Seq_addhi(calleelist, to_generic_int(symboluid(callee[i])));
    277 	}
    278 	save = interfaces;
    279 	interfaces = codelist;
    280 	gencode(caller, callee);
    281 	asdl_segment(CODE);
    282 	emitcode();
    283 	interfaces = save;
    284 	put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist));
    285 }
    286 
    287 static Node asdl_gen(Node p) {
    288 	Node q;
    289 	list_ty forest = Seq_new(0);
    290 
    291 	for (q = p; p != NULL; p = p->link)
    292 		if (specific(p->op) == JUMP+V && specific(p->kids[0]->op) == ADDRG+P
    293 		&& p->kids[0]->syms[0]->scope == LABELS) {
    294 			p->syms[0] = p->kids[0]->syms[0];
    295 			p->kids[0] = NULL;
    296 		}
    297 	for (p = q; p != NULL; p = p->link)
    298 		Seq_addhi(forest, visit(p));
    299 	put(rcc_Forest(forest));
    300 	temps = NULL;
    301 	return q;
    302 }
    303 
    304 static void asdl_global(Symbol p) {
    305 	dopending(p);
    306 	put(rcc_Global(symboluid(p), p->u.seg));
    307 }
    308 
    309 static void asdl_import(Symbol p) {
    310 	dopending(p);
    311 	put(rcc_Import(symboluid(p)));
    312 }
    313 
    314 static void asdl_progbeg(int argc, char *argv[]) {
    315 	int i;
    316 
    317 #if WIN32
    318 	_setmode(_fileno(stdout), _O_BINARY);
    319 #endif
    320 	pickle = rcc_program(1, 0, Seq_new(0), Seq_new(0), argc, Seq_new(0));
    321 	for (i = 0; i < argc; i++)
    322 		Seq_addhi(pickle->argv, to_generic_string(Text_box(argv[i], strlen(argv[i]) + 1)));
    323 	interfaces = pickle->interfaces;
    324 }
    325 
    326 static int checkuid(list_ty list) {
    327 	int i, n = 0, count = Seq_length(list);
    328 
    329 	for (i = 0; i < count; i++) {
    330 		rcc_interface_ty in = Seq_get(list, i);
    331 		if (in->kind == rcc_Local_enum
    332 		||  in->kind == rcc_Address_enum)
    333 			n++;
    334 		else if (in->kind == rcc_Function_enum)
    335 			n += checkuid(in->v.rcc_Function.codelist);
    336 	}
    337 	return n;
    338 }
    339 
    340 static void asdl_progend(void) {
    341 	dopending(NULL);
    342 	{
    343 		int n = checkuid(pickle->interfaces) + Seq_length(pickle->items);
    344 		if (n != pickle->nuids - 1)
    345 			fprintf(stderr, "?bogus uid count: have %d should have %d\n",
    346 				n, pickle->nuids-1);
    347 	}
    348 	pickle->nlabels = genlabel(0);
    349 	write_int((int)(100*(assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
    350 ), stdout);
    351 	rcc_write_program(pickle, stdout);
    352 }
    353 static void asdl_space(int n) {
    354 	put(rcc_Space(n));
    355 }
    356 
    357 void asdl_init(int argc, char *argv[]) {
    358 	int i;
    359 	static int inited;
    360 
    361 	if (inited)
    362 		return;
    363 	inited = 1;
    364 	for (i = 1; i < argc; i++)
    365 		if (strcmp(argv[i], "-asdl") == 0) {
    366 #define xx(f) IR->f = asdl_##f
    367 		xx(address);
    368 		xx(blockbeg);
    369 		xx(blockend);
    370 		xx(defaddress);
    371 		xx(defconst);
    372 		xx(defstring);
    373 		xx(defsymbol);
    374 		xx(emit);
    375 		xx(export);
    376 		xx(function);
    377 		xx(gen);
    378 		xx(global);
    379 		xx(import);
    380 		xx(local);
    381 		xx(progbeg);
    382 		xx(progend);
    383 		xx(segment);
    384 		xx(space);
    385 #undef xx
    386 #define xx(f) IR->f = 0
    387 		xx(stabblock);
    388 		xx(stabend);
    389 		xx(stabfend);
    390 		xx(stabinit);
    391 		xx(stabline);
    392 		xx(stabsym);
    393 		xx(stabtype);
    394 #undef xx
    395 		IR->wants_dag = 0;
    396 		prunetemps = 0;	/* pass2 prunes useless temps */
    397 		assignargs = 0;	/* pass2 generates caller to callee assignments */
    398 		}
    399 }