199 lines
3.7 KiB
C
199 lines
3.7 KiB
C
#include "gc.h"
|
|
|
|
int
|
|
swcmp(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;
|
|
}
|
|
|
|
void
|
|
doswit(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['W'])
|
|
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]);
|
|
}
|
|
|
|
void
|
|
casf(void)
|
|
{
|
|
Case *c;
|
|
|
|
c = alloc(sizeof(*c));
|
|
c->link = cases;
|
|
cases = c;
|
|
}
|
|
|
|
long
|
|
outlstring(Rune *s, long n)
|
|
{
|
|
char buf[sizeof(Rune)];
|
|
int c, i;
|
|
long r;
|
|
|
|
if(suppress)
|
|
return nstring;
|
|
while(nstring % sizeof buf)
|
|
outstring("", 1);
|
|
r = nstring;
|
|
while(n > 0) {
|
|
c = *s++;
|
|
if(align(0, types[TCHAR], Aarg1)) {
|
|
for(i = sizeof buf; i > 0; c >>= 8)
|
|
buf[--i] = c;
|
|
} else {
|
|
for(i = 0; i < sizeof buf; c >>= 8)
|
|
buf[i++] = c;
|
|
}
|
|
outstring(buf, sizeof buf);
|
|
n -= sizeof buf;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void
|
|
nullwarn(Node *l, Node *r)
|
|
{
|
|
warn(Z, "result of operation not used");
|
|
if(l != Z)
|
|
cgen(l, Z);
|
|
if(r != Z)
|
|
cgen(r, Z);
|
|
}
|
|
|
|
void
|
|
ieeedtod(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);
|
|
}
|