208 lines · 4.1 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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, *iqh, *iql;	long def, nc, i, j, isv, nh;	Prog *hsb;	Node *vr[2];	int dup; 	def = 0;	nc = 0;	isv = 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;		}		isv |= c->isv;		nc++;	}	if(typev[n->type->etype])		isv = 1;	else if(isv){		warn(n, "32-bit switch expression with 64-bit case constant");		isv = 0;	} 	iq = alloc(nc*sizeof(C1));	q = iq;	for(c = cases; c->link != C; c = c->link) {		if(c->def)			continue;		if(c->isv && !isv)			continue;	/* can never match */		q->label = c->label;		if(isv)			q->val = c->val;		else			q->val = (long)c->val;	/* cast ensures correct value for 32-bit switch on 64-bit architecture */		q++;	}	qsort(iq, nc, sizeof(C1), swcmp);	if(debug['K'])	for(i=0; i<nc; i++)		print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);	dup = 0;	for(i=0; i<nc-1; i++)		if(iq[i].val == iq[i+1].val) {			diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);			dup = 1;		}	if(dup)		return;	if(def == 0) {		def = breakpc;		nbreak++;	}	if(!isv || ewidth[TIND] > ewidth[TLONG] || n->op == OREGISTER) {		swit1(iq, nc, def, n);		return;	} 	/*	 * 64-bit case on 32-bit machine:	 * switch on high-order words, and	 * in each of those, switch on low-order words	 */	if(n->op != OREGPAIR)		fatal(n, "internal: expected register pair");	if(thechar == '8'){	/* TO DO: need an enquiry function */		vr[0] = n->left;	/* low */		vr[1] = n->right;	/* high */	}else{		vr[0] = n->right;		vr[1] = n->left;	}	vr[0]->type = types[TLONG];	vr[1]->type = types[TLONG];	gbranch(OGOTO);	hsb = p;	iqh = alloc(nc*sizeof(C1));	iql = alloc(nc*sizeof(C1));	nh = 0;	for(i=0; i<nc;){		iqh[nh].val = iq[i].val >> 32;		q = iql;		/* iq is sorted, so equal top halves are adjacent */		for(j = i; j < nc; j++){			if((iq[j].val>>32) != iqh[nh].val)				break;			q->val = (long)iq[j].val;			q->label = iq[j].label;			q++;		}		qsort(iql,  q-iql, sizeof(C1), swcmp);if(0){for(int k=0; k<(q-iql); k++)print("nh=%ld k=%d h=%#llux l=%#llux lab=%ld\n", nh, k, (vlong)iqh[nh].val,  (vlong)iql[k].val, iql[k].label);}		iqh[nh].label = pc;		nh++;		swit1(iql, q-iql, def, vr[0]);		i = j;	}	patch(hsb, pc);if(0){for(int k=0; k<nh; k++)print("k*=%d h=%#llux lab=%ld\n", k, (vlong)iqh[k].val,  iqh[k].label);}	swit1(iqh, nh, def, vr[1]);} voidcasf(void){	Case *c; 	c = alloc(sizeof(*c));	c->link = cases;	cases = c;} longoutlstring(TRune *s, long n){	char buf[sizeof(TRune)];	uint c;	int i;	long r; 	if(suppress)		return nstring;	while(nstring & (sizeof(TRune)-1))		outstring("", 1);	r = nstring;	while(n > 0) {		c = *s++;		if(align(0, types[TCHAR], Aarg1)) {			for(i = 0; i < sizeof(TRune); i++)				buf[i] = c>>(8*(sizeof(TRune) - i - 1));		} else {			for(i = 0; i < sizeof(TRune); i++)				buf[i] = c>>(8*i);		}		outstring(buf, sizeof(TRune));		n -= sizeof(TRune);	}	return r;} voidnullwarn(Node *l, Node *r){	warn(Z, "result of operation not used");	if(l != Z)		cgen(l, Z);	if(r != Z)		cgen(r, Z);} voidieeedtod(Ieee *ieee, double native){	double fr, ho, f;	int exp; 	if(native < 0) {		ieeedtod(ieee, -native);		ieee->h |= 0x80000000L;		return;	}	if(native == 0) {		ieee->l = 0;		ieee->h = 0;		return;	}	fr = frexp(native, &exp);	f = 2097152L;		/* shouldnt use fp constants here */	fr = modf(fr*f, &ho);	ieee->h = ho;	ieee->h &= 0xfffffL;	ieee->h |= (exp+1022L) << 20;	f = 65536L;	fr = modf(fr*f, &ho);	ieee->l = ho;	ieee->l <<= 16;	ieee->l |= (long)(fr*f);}