Charles.Forsyth20060303644188019 years agoHistory
715 lines · 11.7 KB · C
RawDownload
#include "gc.h" intswcmp(const void *a1, const void *a2){	C1 *p1, *p2; 	p1 = (C1*)a1;	p2 = (C1*)a2;	if(p1->val < p2->val)		return -1;	return  p1->val > p2->val;} voiddoswit(Node *n){	Case *c;	C1 *q, *iq;	long def, nc, i;	Node tn; 	def = 0;	nc = 0;	for(c = cases; c->link != C; c = c->link) {		if(c->def) {			if(def)				diag(n, "more than one default in switch");			def = c->label;			continue;		}		nc++;	} 	iq = alloc(nc*sizeof(C1));	q = iq;	for(c = cases; c->link != C; c = c->link) {		if(c->def)			continue;		q->label = c->label;		q->val = c->val;		q++;	}	qsort(iq, nc, sizeof(C1), swcmp);	if(def == 0)		def = breakpc;	for(i=0; i<nc-1; i++)		if(iq[i].val == iq[i+1].val)			diag(n, "duplicate cases in switch %ld", iq[i].val);	regalloc(&tn, &regnode, Z);	swit1(iq, nc, def, n, &tn);	regfree(&tn);} voidswit1(C1 *q, int nc, long def, Node *n, Node *tn){	C1 *r;	int i;	Prog *sp; 	if(nc < 5) {		for(i=0; i<nc; i++) {			if(sval(q->val)) {				gopcode(OEQ, n, Z, nodconst(q->val));			} else {				gopcode(OSUB, nodconst(q->val), n, tn);				gopcode(OEQ, tn, Z, nodconst(0));			}			patch(p, q->label);			q++;		}		gbranch(OGOTO);		patch(p, def);		return;	}	i = nc / 2;	r = q+i;	if(sval(r->val)) {		gopcode(OGT, n, Z, nodconst(r->val));		sp = p;	} else {		gopcode(OSUB, nodconst(r->val), n, tn);		gopcode(OGT, tn, Z, nodconst(0));		sp = p;	}	gbranch(OGOTO);	p->as = ABE;	patch(p, r->label);	swit1(q, i, def, n, tn); 	patch(sp, pc);	swit1(r+1, nc-i-1, def, n, tn);} voidcas(void){	Case *c; 	c = alloc(sizeof(*c));	c->link = cases;	cases = c;} voidbitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn){	int sh;	long v;	Node *l; 	/*	 * n1 gets adjusted/masked value	 * n2 gets address of cell	 * n3 gets contents of cell	 */	l = b->left;	if(n2 != Z) {		regalloc(n1, l, nn);		reglcgen(n2, l, Z);		regalloc(n3, l, Z);		gopcode(OAS, n2, Z, n3);		gopcode(OAS, n3, Z, n1);	} else {		regalloc(n1, l, nn);		cgen(l, n1);	}	if(b->type->shift == 0 && typeu[b->type->etype]) {		v = ~0 + (1L << b->type->nbits);		gopcode(OAND, nodconst(v), Z, n1);	} else {		sh = 32 - b->type->shift - b->type->nbits;		if(sh > 0)			gopcode(OASHL, nodconst(sh), Z, n1);		sh += b->type->shift;		if(sh > 0)			if(typeu[b->type->etype])				gopcode(OLSHR, nodconst(sh), Z, n1);			else				gopcode(OASHR, nodconst(sh), Z, n1);	}} voidbitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn){	long v;	Node nod, *l;	int sh; 	/*	 * n1 has adjusted/masked value	 * n2 has address of cell	 * n3 has contents of cell	 */	l = b->left;	regalloc(&nod, l, Z);	v = ~0 + (1L << b->type->nbits);	gopcode(OAND, nodconst(v), Z, n1);	gopcode(OAS, n1, Z, &nod);	if(nn != Z)		gopcode(OAS, n1, Z, nn);	sh = b->type->shift;	if(sh > 0)		gopcode(OASHL, nodconst(sh), Z, &nod);	v <<= sh;	gopcode(OAND, nodconst(~v), Z, n3);	gopcode(OOR, n3, Z, &nod);	gopcode(OAS, &nod, Z, n2); 	regfree(&nod);	regfree(n1);	regfree(n2);	regfree(n3);} longoutstring(char *s, long n){	long r; 	r = nstring;	while(n) {		string[mnstring] = *s++;		mnstring++;		nstring++;		if(mnstring >= NSNAME) {			gpseudo(ADATA, symstring, nodconst(0L));			p->from.offset += nstring - NSNAME;			p->reg = NSNAME;			p->to.type = D_SCONST;			memmove(p->to.sval, string, NSNAME);			mnstring = 0;		}		n--;	}	return r;} longoutlstring(ushort *s, long n){	char buf[2];	int c;	long r; 	while(nstring & 1)		outstring("", 1);	r = nstring;	while(n > 0) {		c = *s++;		if(align(0, types[TCHAR], Aarg1)) {			buf[0] = c>>8;			buf[1] = c;		} else {			buf[0] = c;			buf[1] = c>>8;		}		outstring(buf, 2);		n -= sizeof(ushort);	}	return r;} intmulcon(Node *n, Node *nn){	Node *l, *r, nod1, nod2;	Multab *m;	long v;	int o;	char code[sizeof(m->code)+2], *p; 	if(typefd[n->type->etype])		return 0;	l = n->left;	r = n->right;	if(l->op == OCONST) {		l = r;		r = n->left;	}	if(r->op != OCONST)		return 0;	v = convvtox(r->vconst, n->type->etype);	if(v != r->vconst) {		if(debug['M'])			print("%L multiply conv: %lld\n", n->lineno, r->vconst);		return 0;	}	m = mulcon0(n, v);	if(!m) {		if(debug['M'])			print("%L multiply table: %lld\n", n->lineno, r->vconst);		return 0;	} 	memmove(code, m->code, sizeof(m->code));	code[sizeof(m->code)] = 0; 	p = code;	if(p[1] == 'i')		p += 2;	regalloc(&nod1, n, nn);	cgen(l, &nod1);	if(v < 0)		gopcode(OSUB, &nod1, nodconst(0), &nod1);	regalloc(&nod2, n, Z); loop:	switch(*p) {	case 0:		regfree(&nod2);		gopcode(OAS, &nod1, Z, nn);		regfree(&nod1);		return 1;	case '+':		o = OADD;		goto addsub;	case '-':		o = OSUB;	addsub:	/* number is r,n,l */		v = p[1] - '0';		r = &nod1;		if(v&4)			r = &nod2;		n = &nod1;		if(v&2)			n = &nod2;		l = &nod1;		if(v&1)			l = &nod2;		gopcode(o, l, n, r);		break;	default: /* op is shiftcount, number is r,l */		v = p[1] - '0';		r = &nod1;		if(v&2)			r = &nod2;		l = &nod1;		if(v&1)			l = &nod2;		v = *p - 'a';		if(v < 0 || v >= 32) {			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);			break;		}		gopcode(OASHL, nodconst(v), l, r);		break;	}	p += 2;	goto loop;} voidnullwarn(Node *l, Node *r){	warn(Z, "result of operation not used");	if(l != Z)		cgen(l, Z);	if(r != Z)		cgen(r, Z);} voidsextern(Sym *s, Node *a, long o, long w){	long e, lw; 	for(e=0; e<w; e+=NSNAME) {		lw = NSNAME;		if(w-e < lw)			lw = w-e;		gpseudo(ADATA, s, nodconst(0));		p->from.offset += o+e;		p->reg = lw;		p->to.type = D_SCONST;		memmove(p->to.sval, a->cstring+e, lw);	}} voidgextern(Sym *s, Node *a, long o, long w){	if(a->op == OCONST && typev[a->type->etype]) {		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */			gpseudo(ADATA, s, nod32const(a->vconst>>32));		else			gpseudo(ADATA, s, nod32const(a->vconst));		p->from.offset += o;		p->reg = 4;		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */			gpseudo(ADATA, s, nod32const(a->vconst));		else			gpseudo(ADATA, s, nod32const(a->vconst>>32));		p->from.offset += o + 4;		p->reg = 4;		return;	}	gpseudo(ADATA, s, a);	p->from.offset += o;	p->reg = w;	if(p->to.type == D_OREG)		p->to.type = D_CONST;} void	zname(Biobuf*, Sym*, int);void	zaddr(Biobuf*, Adr*, int);void	zwrite(Biobuf*, Prog*, int, int);void	outhist(Biobuf*); voidoutcode(void){	struct { Sym *sym; short type; } h[NSYM];	Prog *p;	Sym *s;	int sf, st, t, sym; 	if(debug['S']) {		for(p = firstp; p != P; p = p->link)			if(p->as != ADATA && p->as != AGLOBL)				pc--;		for(p = firstp; p != P; p = p->link) {			print("%P\n", p);			if(p->as != ADATA && p->as != AGLOBL)				pc++;		}	}	outhist(&outbuf);	for(sym=0; sym<NSYM; sym++) {		h[sym].sym = S;		h[sym].type = 0;	}	sym = 1;	for(p = firstp; p != P; p = p->link) {	jackpot:		sf = 0;		s = p->from.sym;		while(s != S) {			sf = s->sym;			if(sf < 0 || sf >= NSYM)				sf = 0;			t = p->from.name;			if(h[sf].type == t)			if(h[sf].sym == s)				break;			s->sym = sym;			zname(&outbuf, s, t);			h[sym].sym = s;			h[sym].type = t;			sf = sym;			sym++;			if(sym >= NSYM)				sym = 1;			break;		}		st = 0;		s = p->to.sym;		while(s != S) {			st = s->sym;			if(st < 0 || st >= NSYM)				st = 0;			t = p->to.name;			if(h[st].type == t)			if(h[st].sym == s)				break;			s->sym = sym;			zname(&outbuf, s, t);			h[sym].sym = s;			h[sym].type = t;			st = sym;			sym++;			if(sym >= NSYM)				sym = 1;			if(st == sf)				goto jackpot;			break;		}		zwrite(&outbuf, p, sf, st);	}	firstp = P;	lastp = P;} voidzwrite(Biobuf *b, Prog *p, int sf, int st){	long l; 	Bputc(b, p->as);	Bputc(b, p->reg);	l = p->lineno;	Bputc(b, l);	Bputc(b, l>>8);	Bputc(b, l>>16);	Bputc(b, l>>24);	zaddr(b, &p->from, sf);	zaddr(b, &p->to, st);} voidouthist(Biobuf *b){	Hist *h;	char *p, *q, *op, c;	Prog pg;	int n; 	pg = zprog;	pg.as = AHISTORY;	c = pathchar();	for(h = hist; h != H; h = h->link) {		p = h->name;		op = 0;		/* on windows skip drive specifier in pathname */		if(systemtype(Windows) && p && p[1] == ':'){			p += 2;			c = *p;		}		if(p && p[0] != c && h->offset == 0 && pathname){			/* on windows skip drive specifier in pathname */			if(systemtype(Windows) && pathname[1] == ':') {				op = p;				p = pathname+2;				c = *p;			} else if(pathname[0] == c){				op = p;				p = pathname;			}		}		while(p) {			q = utfrune(p, c);			if(q) {				n = q-p;				if(n == 0){					n = 1;	/* leading "/" */					*p = '/';	/* don't emit "\" on windows */				}				q++;

Lines 1–500 of 715.