xref: /inferno-os/utils/cc/pswt.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
1 #include "gc.h"
2 
3 int
4 swcmp(void *a1, void *a2)
5 {
6 	C1 *p1, *p2;
7 
8 	p1 = (C1*)a1;
9 	p2 = (C1*)a2;
10 	if(p1->val < p2->val)
11 		return -1;
12 	return p1->val > p2->val;
13 }
14 
15 void
16 doswit(Node *n)
17 {
18 	Case *c;
19 	C1 *q, *iq, *iqh, *iql;
20 	long def, nc, i, j, isv, nh;
21 	Prog *hsb;
22 	Node *vr[2];
23 	int dup;
24 
25 	def = 0;
26 	nc = 0;
27 	isv = 0;
28 	for(c = cases; c->link != C; c = c->link) {
29 		if(c->def) {
30 			if(def)
31 				diag(n, "more than one default in switch");
32 			def = c->label;
33 			continue;
34 		}
35 		isv |= c->isv;
36 		nc++;
37 	}
38 	if(typev[n->type->etype])
39 		isv = 1;
40 	else if(isv){
41 		warn(n, "32-bit switch expression with 64-bit case constant");
42 		isv = 0;
43 	}
44 
45 	iq = alloc(nc*sizeof(C1));
46 	q = iq;
47 	for(c = cases; c->link != C; c = c->link) {
48 		if(c->def)
49 			continue;
50 		if(c->isv && !isv)
51 			continue;	/* can never match */
52 		q->label = c->label;
53 		if(isv)
54 			q->val = c->val;
55 		else
56 			q->val = (long)c->val;	/* cast ensures correct value for 32-bit switch on 64-bit architecture */
57 		q++;
58 	}
59 	qsort(iq, nc, sizeof(C1), swcmp);
60 	if(debug['K'])
61 	for(i=0; i<nc; i++)
62 		print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);
63 	dup = 0;
64 	for(i=0; i<nc-1; i++)
65 		if(iq[i].val == iq[i+1].val) {
66 			diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
67 			dup = 1;
68 		}
69 	if(dup)
70 		return;
71 	if(def == 0) {
72 		def = breakpc;
73 		nbreak++;
74 	}
75 	if(!isv || ewidth[TIND] > ewidth[TLONG] || n->op == OREGISTER) {
76 		swit1(iq, nc, def, n);
77 		return;
78 	}
79 
80 	/*
81 	 * 64-bit case on 32-bit machine:
82 	 * switch on high-order words, and
83 	 * in each of those, switch on low-order words
84 	 */
85 	if(n->op != OREGPAIR)
86 		fatal(n, "internal: expected register pair");
87 	if(thechar == '8'){	/* TO DO: need an enquiry function */
88 		vr[0] = n->left;	/* low */
89 		vr[1] = n->right;	/* high */
90 	}else{
91 		vr[0] = n->right;
92 		vr[1] = n->left;
93 	}
94 	vr[0]->type = types[TLONG];
95 	vr[1]->type = types[TLONG];
96 	gbranch(OGOTO);
97 	hsb = p;
98 	iqh = alloc(nc*sizeof(C1));
99 	iql = alloc(nc*sizeof(C1));
100 	nh = 0;
101 	for(i=0; i<nc;){
102 		iqh[nh].val = iq[i].val >> 32;
103 		q = iql;
104 		/* iq is sorted, so equal top halves are adjacent */
105 		for(j = i; j < nc; j++){
106 			if((iq[j].val>>32) != iqh[nh].val)
107 				break;
108 			q->val = (long)iq[j].val;
109 			q->label = iq[j].label;
110 			q++;
111 		}
112 		qsort(iql,  q-iql, sizeof(C1), swcmp);
113 		iqh[nh].label = pc;
114 		nh++;
115 		swit1(iql, q-iql, def, vr[0]);
116 		i = j;
117 	}
118 	patch(hsb, pc);
119 	swit1(iqh, nh, def, vr[1]);
120 }
121 
122 void
123 casf(void)
124 {
125 	Case *c;
126 
127 	c = alloc(sizeof(*c));
128 	c->link = cases;
129 	cases = c;
130 }
131 
132 long
133 outlstring(TRune *s, long n)
134 {
135 	char buf[sizeof(TRune)];
136 	uint c;
137 	int i;
138 	long r;
139 
140 	if(suppress)
141 		return nstring;
142 	while(nstring & (sizeof(TRune)-1))
143 		outstring("", 1);
144 	r = nstring;
145 	while(n > 0) {
146 		c = *s++;
147 		if(align(0, types[TCHAR], Aarg1)) {
148 			for(i = 0; i < sizeof(TRune); i++)
149 				buf[i] = c>>(8*(sizeof(TRune) - i - 1));
150 		} else {
151 			for(i = 0; i < sizeof(TRune); i++)
152 				buf[i] = c>>(8*i);
153 		}
154 		outstring(buf, sizeof(TRune));
155 		n -= sizeof(TRune);
156 	}
157 	return r;
158 }
159 
160 void
161 nullwarn(Node *l, Node *r)
162 {
163 	warn(Z, "result of operation not used");
164 	if(l != Z)
165 		cgen(l, Z);
166 	if(r != Z)
167 		cgen(r, Z);
168 }
169 
170 void
171 ieeedtod(Ieee *ieee, double native)
172 {
173 	double fr, ho, f;
174 	int exp;
175 
176 	if(native < 0) {
177 		ieeedtod(ieee, -native);
178 		ieee->h |= 0x80000000L;
179 		return;
180 	}
181 	if(native == 0) {
182 		ieee->l = 0;
183 		ieee->h = 0;
184 		return;
185 	}
186 	fr = frexp(native, &exp);
187 	f = 2097152L;		/* shouldnt use fp constants here */
188 	fr = modf(fr*f, &ho);
189 	ieee->h = ho;
190 	ieee->h &= 0xfffffL;
191 	ieee->h |= (exp+1022L) << 20;
192 	f = 65536L;
193 	fr = modf(fr*f, &ho);
194 	ieee->l = ho;
195 	ieee->l <<= 16;
196 	ieee->l |= (long)(fr*f);
197 }
198