1 #include "gc.h"
2
3 int
swcmp(const void * a1,const void * a2)4 swcmp(const void *a1, const 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
doswit(Node * n)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 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);}
114 iqh[nh].label = pc;
115 nh++;
116 swit1(iql, q-iql, def, vr[0]);
117 i = j;
118 }
119 patch(hsb, pc);
120 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);}
121 swit1(iqh, nh, def, vr[1]);
122 }
123
124 void
casf(void)125 casf(void)
126 {
127 Case *c;
128
129 c = alloc(sizeof(*c));
130 c->link = cases;
131 cases = c;
132 }
133
134 long
outlstring(TRune * s,long n)135 outlstring(TRune *s, long n)
136 {
137 char buf[sizeof(TRune)];
138 uint c;
139 int i;
140 long r;
141
142 if(suppress)
143 return nstring;
144 while(nstring & (sizeof(TRune)-1))
145 outstring("", 1);
146 r = nstring;
147 while(n > 0) {
148 c = *s++;
149 if(align(0, types[TCHAR], Aarg1)) {
150 for(i = 0; i < sizeof(TRune); i++)
151 buf[i] = c>>(8*(sizeof(TRune) - i - 1));
152 } else {
153 for(i = 0; i < sizeof(TRune); i++)
154 buf[i] = c>>(8*i);
155 }
156 outstring(buf, sizeof(TRune));
157 n -= sizeof(TRune);
158 }
159 return r;
160 }
161
162 void
nullwarn(Node * l,Node * r)163 nullwarn(Node *l, Node *r)
164 {
165 warn(Z, "result of operation not used");
166 if(l != Z)
167 cgen(l, Z);
168 if(r != Z)
169 cgen(r, Z);
170 }
171
172 void
ieeedtod(Ieee * ieee,double native)173 ieeedtod(Ieee *ieee, double native)
174 {
175 double fr, ho, f;
176 int exp;
177
178 if(native < 0) {
179 ieeedtod(ieee, -native);
180 ieee->h |= 0x80000000L;
181 return;
182 }
183 if(native == 0) {
184 ieee->l = 0;
185 ieee->h = 0;
186 return;
187 }
188 fr = frexp(native, &exp);
189 f = 2097152L; /* shouldnt use fp constants here */
190 fr = modf(fr*f, &ho);
191 ieee->h = ho;
192 ieee->h &= 0xfffffL;
193 ieee->h |= (exp+1022L) << 20;
194 f = 65536L;
195 fr = modf(fr*f, &ho);
196 ieee->l = ho;
197 ieee->l <<= 16;
198 ieee->l |= (long)(fr*f);
199 }
200