123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- #include "gc.h"
- int
- swcmp(void *a1, 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['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);
- iqh[nh].label = pc;
- nh++;
- swit1(iql, q-iql, def, vr[0]);
- i = j;
- }
- patch(hsb, pc);
- swit1(iqh, nh, def, vr[1]);
- }
- void
- casf(void)
- {
- Case *c;
- c = alloc(sizeof(*c));
- c->link = cases;
- cases = c;
- }
- long
- outlstring(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;
- }
- 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);
- }
|