diff options
Diffstat (limited to 'src/cmd/6c')
-rw-r--r-- | src/cmd/6c/cgen.c | 48 | ||||
-rw-r--r-- | src/cmd/6c/gc.h | 3 | ||||
-rw-r--r-- | src/cmd/6c/swt.c | 19 |
3 files changed, 64 insertions, 6 deletions
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c index 7f717dcbb..71822586c 100644 --- a/src/cmd/6c/cgen.c +++ b/src/cmd/6c/cgen.c @@ -1237,11 +1237,12 @@ void boolgen(Node *n, int true, Node *nn) { int o; - Prog *p1, *p2; + Prog *p1, *p2, *p3; Node *l, *r, nod, nod1; int32 curs; if(debug['g']) { + print("boolgen %d\n", true); prtree(nn, "boolgen lhs"); prtree(n, "boolgen"); } @@ -1353,6 +1354,15 @@ boolgen(Node *n, int true, Node *nn) case OLO: case OLS: o = n->op; + if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) { + // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs. + // Jump around instead. + boolgen(n, 0, Z); + p1 = p; + gbranch(OGOTO); + patch(p1, pc); + goto com; + } if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { @@ -1367,6 +1377,10 @@ boolgen(Node *n, int true, Node *nn) break; } if(immconst(l)) { + // NOTE: Reversing the comparison here is wrong + // for floating point ordering comparisons involving NaN, + // but we don't have any of those yet so we don't + // bother worrying about it. o = invrel[relindex(o)]; /* bad, 13 is address of external that becomes constant */ if(r->addable < INDEXED || r->addable == 13) { @@ -1388,10 +1402,11 @@ boolgen(Node *n, int true, Node *nn) cgen(r, &nod1); gopcode(o, l->type, &nod, &nod1); regfree(&nod1); - } else + } else { gopcode(o, l->type, &nod, r); + } regfree(&nod); - goto com; + goto fixfloat; } regalloc(&nod, r, nn); cgen(r, &nod); @@ -1406,6 +1421,33 @@ boolgen(Node *n, int true, Node *nn) } else gopcode(o, l->type, l, &nod); regfree(&nod); + fixfloat: + if(typefd[l->type->etype]) { + switch(o) { + case OEQ: + // Already emitted AJEQ; want AJEQ and AJPC. + p1 = p; + gbranch(OGOTO); + p2 = p; + patch(p1, pc); + gins(AJPC, Z, Z); + patch(p2, pc); + break; + + case ONE: + // Already emitted AJNE; want AJNE or AJPS. + p1 = p; + gins(AJPS, Z, Z); + p2 = p; + gbranch(OGOTO); + p3 = p; + patch(p1, pc); + patch(p2, pc); + gbranch(OGOTO); + patch(p3, pc); + break; + } + } com: if(nn != Z) { diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h index 0c23b115c..b0081abb5 100644 --- a/src/cmd/6c/gc.h +++ b/src/cmd/6c/gc.h @@ -299,7 +299,8 @@ void gpseudo(int, Sym*, Node*); int swcmp(const void*, const void*); void doswit(Node*); void swit1(C1*, int, int32, Node*); -void cas(void); +void swit2(C1*, int, int32, Node*); +void newcase(void); void bitload(Node*, Node*, Node*, Node*, Node*); void bitstore(Node*, Node*, Node*, Node*, Node*); int32 outstring(char*, int32); diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c index 3de86306d..f16d0f78a 100644 --- a/src/cmd/6c/swt.c +++ b/src/cmd/6c/swt.c @@ -33,6 +33,21 @@ void swit1(C1 *q, int nc, int32 def, Node *n) { + Node nreg; + + regalloc(&nreg, n, Z); + if(typev[n->type->etype]) + nreg.type = types[TVLONG]; + else + nreg.type = types[TLONG]; + cgen(n, &nreg); + swit2(q, nc, def, &nreg); + regfree(&nreg); +} + +void +swit2(C1 *q, int nc, int32 def, Node *n) +{ C1 *r; int i; Prog *sp; @@ -58,12 +73,12 @@ swit1(C1 *q, int nc, int32 def, Node *n) gbranch(OGOTO); p->as = AJEQ; patch(p, r->label); - swit1(q, i, def, n); + swit2(q, i, def, n); if(debug['W']) print("case < %.8llux\n", r->val); patch(sp, pc); - swit1(r+1, nc-i-1, def, n); + swit2(r+1, nc-i-1, def, n); } void |