Commit a00bfb5b authored by Russ Cox's avatar Russ Cox

8g:

  * floating point -> integer conversions.
    x86 defines that overflow/underflow
    results in 1<<15, 1<<31, 1<<63 for
    int16, int32, int64.  when building the
    unsigned conversions out of the native signed
    ones, 8g turns overflow/underflow into zero.
    the spec does not say what should happen.

  * many tiny bug fixes.  can run a large number
    of files from go/test now, and can fmt.Printf.

  * struggling with byte register allocation
    and float32 computation.

R=ken
OCL=29642
CL=29811
parent 7f9d2c82
...@@ -7,58 +7,6 @@ ...@@ -7,58 +7,6 @@
#include "gg.h" #include "gg.h"
static int cancgen64(Node *n, Node *res);
int
is64(Type *t)
{
if(t == T)
return 0;
switch(simtype[t->etype]) {
case TINT64:
case TUINT64:
case TPTR64:
return 1;
}
return 0;
}
int
noconv(Type *t1, Type *t2)
{
int e1, e2;
e1 = simtype[t1->etype];
e2 = simtype[t2->etype];
switch(e1) {
case TINT8:
case TUINT8:
return e2 == TINT8 || e2 == TUINT8;
case TINT16:
case TUINT16:
return e2 == TINT16 || e2 == TUINT16;
case TINT32:
case TUINT32:
case TPTR32:
return e2 == TINT32 || e2 == TUINT32 || e2 == TPTR32;
case TINT64:
case TUINT64:
case TPTR64:
return e2 == TINT64 || e2 == TUINT64 || e2 == TPTR64;
case TFLOAT32:
return e2 == TFLOAT32;
case TFLOAT64:
return e2 == TFLOAT64;
}
return 0;
}
/* /*
* generate: * generate:
* res = n; * res = n;
...@@ -84,11 +32,16 @@ cgen(Node *n, Node *res) ...@@ -84,11 +32,16 @@ cgen(Node *n, Node *res)
if(res == N || res->type == T) if(res == N || res->type == T)
fatal("cgen: res nil"); fatal("cgen: res nil");
// static initializations
if(initflag && gen_as_init(n, res))
return;
// function calls on both sides? introduce temporary // function calls on both sides? introduce temporary
if(n->ullman >= UINF && res->ullman >= UINF) { if(n->ullman >= UINF && res->ullman >= UINF) {
tempname(&n1, n->type); tempalloc(&n1, n->type);
cgen(n, &n1); cgen(n, &n1);
cgen(&n1, res); cgen(&n1, res);
tempfree(&n1);
return; return;
} }
...@@ -125,10 +78,6 @@ cgen(Node *n, Node *res) ...@@ -125,10 +78,6 @@ cgen(Node *n, Node *res)
// otherwise, the result is addressable but n is not. // otherwise, the result is addressable but n is not.
// let's do some computation. // let's do some computation.
// 64-bit ops are hard on 32-bit machine.
if(is64(n->type) && cancgen64(n, res))
return;
// use ullman to pick operand to eval first. // use ullman to pick operand to eval first.
nl = n->left; nl = n->left;
nr = n->right; nr = n->right;
...@@ -144,6 +93,25 @@ cgen(Node *n, Node *res) ...@@ -144,6 +93,25 @@ cgen(Node *n, Node *res)
return; return;
} }
// 64-bit ops are hard on 32-bit machine.
if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
switch(n->op) {
// math goes to cgen64.
case OMINUS:
case OCOM:
case OADD:
case OSUB:
case OMUL:
case OLSH:
case ORSH:
case OAND:
case OOR:
case OXOR:
cgen64(n, res);
return;
}
}
if(isfloat[n->type->etype] && isfloat[nl->type->etype]) if(isfloat[n->type->etype] && isfloat[nl->type->etype])
goto flt; goto flt;
...@@ -178,6 +146,7 @@ cgen(Node *n, Node *res) ...@@ -178,6 +146,7 @@ cgen(Node *n, Node *res)
return; return;
case OMINUS: case OMINUS:
case OCOM:
a = optoas(n->op, nl->type); a = optoas(n->op, nl->type);
goto uop; goto uop;
...@@ -218,8 +187,8 @@ cgen(Node *n, Node *res) ...@@ -218,8 +187,8 @@ cgen(Node *n, Node *res)
break; break;
case OLEN: case OLEN:
if(istype(nl->type, TSTRING) || istype(nl->type, TMAP)) { if(istype(nl->type, TMAP)) {
// both string and map have len in the first 32-bit word. // map has len in the first 32-bit word.
// a zero pointer means zero length // a zero pointer means zero length
tempalloc(&n1, types[tptr]); tempalloc(&n1, types[tptr]);
cgen(nl, &n1); cgen(nl, &n1);
...@@ -243,7 +212,9 @@ cgen(Node *n, Node *res) ...@@ -243,7 +212,9 @@ cgen(Node *n, Node *res)
regfree(&n1); regfree(&n1);
break; break;
} }
if(isslice(nl->type)) { if(istype(nl->type, TSTRING) || isslice(nl->type)) {
// both slice and string have len one pointer into the struct.
// a zero pointer means zero length
igen(nl, &n1, res); igen(nl, &n1, res);
n1.op = OINDREG; n1.op = OINDREG;
n1.type = types[TUINT32]; n1.type = types[TUINT32];
...@@ -289,10 +260,6 @@ cgen(Node *n, Node *res) ...@@ -289,10 +260,6 @@ cgen(Node *n, Node *res)
case OMOD: case OMOD:
case ODIV: case ODIV:
if(isfloat[n->type->etype]) {
a = optoas(n->op, nl->type);
goto abop;
}
cgen_div(n->op, nl, nr, res); cgen_div(n->op, nl, nr, res);
break; break;
...@@ -340,8 +307,19 @@ uop: // unary ...@@ -340,8 +307,19 @@ uop: // unary
return; return;
flt: // floating-point. 387 (not SSE2) to interoperate with 6c flt: // floating-point. 387 (not SSE2) to interoperate with 6c
nodreg(&f0, n->type, D_F0); nodreg(&f0, nl->type, D_F0);
nodreg(&f1, n->type, D_F0+1); nodreg(&f1, n->type, D_F0+1);
if(nr != N)
goto flt2;
// unary
cgen(nl, &f0);
if(n->op != OCONV)
gins(foptoas(n->op, n->type, 0), &f0, &f0);
gmove(&f0, res);
return;
flt2: // binary
if(nl->ullman >= nr->ullman) { if(nl->ullman >= nr->ullman) {
cgen(nl, &f0); cgen(nl, &f0);
if(nr->addable) if(nr->addable)
...@@ -402,7 +380,7 @@ agen(Node *n, Node *res) ...@@ -402,7 +380,7 @@ agen(Node *n, Node *res)
fatal("agen %O", n->op); fatal("agen %O", n->op);
case OCONV: case OCONV:
if(!eqtype(n->type, nl->type)) if(!cvttype(n->type, nl->type))
fatal("agen: non-trivial OCONV"); fatal("agen: non-trivial OCONV");
agen(nl, res); agen(nl, res);
break; break;
...@@ -427,8 +405,11 @@ agen(Node *n, Node *res) ...@@ -427,8 +405,11 @@ agen(Node *n, Node *res)
if(nr->addable) { if(nr->addable) {
agenr(nl, &n3, res); agenr(nl, &n3, res);
if(!isconst(nr, CTINT)) { if(!isconst(nr, CTINT)) {
tempalloc(&tmp, nr->type);
cgen(nr, &tmp);
regalloc(&n1, nr->type, N); regalloc(&n1, nr->type, N);
cgen(nr, &n1); gmove(&tmp, &n1);
tempfree(&tmp);
} }
} else if(nl->addable) { } else if(nl->addable) {
if(!isconst(nr, CTINT)) { if(!isconst(nr, CTINT)) {
...@@ -640,7 +621,7 @@ bgen(Node *n, int true, Prog *to) ...@@ -640,7 +621,7 @@ bgen(Node *n, int true, Prog *to)
{ {
int et, a; int et, a;
Node *nl, *nr, *r; Node *nl, *nr, *r;
Node n1, n2, tmp; Node n1, n2, tmp, t1, t2, ax;
Prog *p1, *p2; Prog *p1, *p2;
if(debug['g']) { if(debug['g']) {
...@@ -778,6 +759,37 @@ bgen(Node *n, int true, Prog *to) ...@@ -778,6 +759,37 @@ bgen(Node *n, int true, Prog *to)
break; break;
} }
if(isfloat[nr->type->etype]) {
nodreg(&tmp, nr->type, D_F0);
nodreg(&n2, nr->type, D_F0 + 1);
nodreg(&ax, types[TUINT16], D_AX);
et = simsimtype(nr->type);
if(et == TFLOAT64) {
// easy - do in FPU
cgen(nr, &tmp);
cgen(nl, &tmp);
gins(AFUCOMPP, &tmp, &n2);
} else {
// NOTE(rsc): This is wrong.
// It's right for comparison but presumably all the
// other ops have the same problem. We need to
// figure out what the right solution is, besides
// tell people to use float64.
tempalloc(&t1, types[TFLOAT32]);
tempalloc(&t2, types[TFLOAT32]);
cgen(nr, &t1);
cgen(nl, &t2);
gmove(&t1, &tmp);
gins(AFCOMFP, &t1, &tmp);
tempfree(&t2);
tempfree(&t1);
}
gins(AFSTSW, N, &ax);
gins(ASAHF, N, N);
patch(gbranch(optoas(brrev(a), nr->type), T), to);
break;
}
if(is64(nr->type)) { if(is64(nr->type)) {
if(!nl->addable) { if(!nl->addable) {
tempalloc(&n1, nl->type); tempalloc(&n1, nl->type);
...@@ -800,45 +812,43 @@ bgen(Node *n, int true, Prog *to) ...@@ -800,45 +812,43 @@ bgen(Node *n, int true, Prog *to)
a = optoas(a, nr->type); a = optoas(a, nr->type);
if(nr->ullman >= UINF) { if(nr->ullman >= UINF) {
regalloc(&n1, nr->type, N); tempalloc(&tmp, nr->type);
cgen(nr, &n1); cgen(nr, &tmp);
tempname(&tmp, nr->type);
gmove(&n1, &tmp);
regfree(&n1);
regalloc(&n1, nl->type, N); tempalloc(&n1, nl->type);
cgen(nl, &n1); cgen(nl, &n1);
regalloc(&n2, nr->type, &n2); regalloc(&n2, nr->type, N);
cgen(&tmp, &n2); cgen(&tmp, &n2);
gins(optoas(OCMP, nr->type), &n1, &n2); gins(optoas(OCMP, nr->type), &n1, &n2);
patch(gbranch(a, nr->type), to); patch(gbranch(a, nr->type), to);
tempfree(&n1);
regfree(&n1); tempfree(&tmp);
regfree(&n2); regfree(&n2);
break; break;
} }
regalloc(&n1, nl->type, N); tempalloc(&n1, nl->type);
cgen(nl, &n1); cgen(nl, &n1);
if(smallintconst(nr)) { if(smallintconst(nr)) {
gins(optoas(OCMP, nr->type), &n1, nr); gins(optoas(OCMP, nr->type), &n1, nr);
patch(gbranch(a, nr->type), to); patch(gbranch(a, nr->type), to);
regfree(&n1); tempfree(&n1);
break; break;
} }
tempalloc(&tmp, nr->type);
cgen(nr, &tmp);
regalloc(&n2, nr->type, N); regalloc(&n2, nr->type, N);
cgen(nr, &n2); gmove(&tmp, &n2);
tempfree(&tmp);
gins(optoas(OCMP, nr->type), &n1, &n2); gins(optoas(OCMP, nr->type), &n1, &n2);
patch(gbranch(a, nr->type), to); patch(gbranch(a, nr->type), to);
regfree(&n1);
regfree(&n2); regfree(&n2);
tempfree(&n1);
break; break;
} }
} }
...@@ -883,7 +893,7 @@ stkof(Node *n) ...@@ -883,7 +893,7 @@ stkof(Node *n)
void void
sgen(Node *n, Node *res, int w) sgen(Node *n, Node *res, int w)
{ {
Node nodl, nodr; Node dst, src, tdst, tsrc;
int32 c, q, odst, osrc; int32 c, q, odst, osrc;
if(debug['g']) { if(debug['g']) {
...@@ -904,22 +914,29 @@ sgen(Node *n, Node *res, int w) ...@@ -904,22 +914,29 @@ sgen(Node *n, Node *res, int w)
osrc = stkof(n); osrc = stkof(n);
odst = stkof(res); odst = stkof(res);
// TODO(rsc): Should these be tempalloc instead? nodreg(&dst, types[tptr], D_DI);
nodreg(&nodl, types[tptr], D_DI); nodreg(&src, types[tptr], D_SI);
nodreg(&nodr, types[tptr], D_SI);
tempalloc(&tsrc, types[tptr]);
if(n->ullman >= res->ullman) { tempalloc(&tdst, types[tptr]);
agen(n, &nodr); if(!n->addable)
agen(res, &nodl); agen(n, &tsrc);
} else { if(!res->addable)
agen(res, &nodl); agen(res, &tdst);
agen(n, &nodr); if(n->addable)
} agen(n, &src);
else
gmove(&tsrc, &src);
if(res->addable)
agen(res, &dst);
else
gmove(&tdst, &dst);
tempfree(&tdst);
tempfree(&tsrc);
c = w % 4; // bytes c = w % 4; // bytes
q = w / 4; // doublewords q = w / 4; // doublewords
gins(ACLD, N, N);
// if we are copying forward on the stack and // if we are copying forward on the stack and
// the src and dst overlap, then reverse direction // the src and dst overlap, then reverse direction
if(osrc < odst && odst < osrc+w) { if(osrc < odst && odst < osrc+w) {
...@@ -949,6 +966,7 @@ sgen(Node *n, Node *res, int w) ...@@ -949,6 +966,7 @@ sgen(Node *n, Node *res, int w)
// we leave with the flag clear // we leave with the flag clear
gins(ACLD, N, N); gins(ACLD, N, N);
} else { } else {
gins(ACLD, N, N); // paranoia. TODO(rsc): remove?
// normal direction // normal direction
if(q >= 4) { if(q >= 4) {
gconreg(AMOVL, q, D_CX); gconreg(AMOVL, q, D_CX);
...@@ -966,34 +984,13 @@ sgen(Node *n, Node *res, int w) ...@@ -966,34 +984,13 @@ sgen(Node *n, Node *res, int w)
} }
} }
void
nswap(Node *a, Node *b)
{
Node t;
t = *a;
*a = *b;
*b = t;
}
Node*
ncon(uint32 i)
{
static Node n;
if(n.type == T)
nodconst(&n, types[TUINT32], 0);
mpmovecfix(n.val.u.xval, i);
return &n;
}
/* /*
* attempt to generate 64-bit * attempt to generate 64-bit
* res = n * res = n
* return 1 on success, 0 if op not handled. * return 1 on success, 0 if op not handled.
*/ */
static int void
cancgen64(Node *n, Node *res) cgen64(Node *n, Node *res)
{ {
Node t1, t2, ax, dx, cx, ex, fx, *l, *r; Node t1, t2, ax, dx, cx, ex, fx, *l, *r;
Node lo1, lo2, lo3, hi1, hi2, hi3; Node lo1, lo2, lo3, hi1, hi2, hi3;
...@@ -1001,8 +998,6 @@ cancgen64(Node *n, Node *res) ...@@ -1001,8 +998,6 @@ cancgen64(Node *n, Node *res)
uint64 v; uint64 v;
uint32 lv, hv; uint32 lv, hv;
if(n->op == OCALL)
return 0;
if(res->op != OINDREG && res->op != ONAME) { if(res->op != OINDREG && res->op != ONAME) {
dump("n", n); dump("n", n);
dump("res", res); dump("res", res);
...@@ -1010,12 +1005,7 @@ cancgen64(Node *n, Node *res) ...@@ -1010,12 +1005,7 @@ cancgen64(Node *n, Node *res)
} }
switch(n->op) { switch(n->op) {
default: default:
return 0; fatal("cgen64 %O", n->op);
case ONAME:
case ODOT:
gmove(n, res);
return 1;
case OMINUS: case OMINUS:
cgen(n->left, res); cgen(n->left, res);
...@@ -1024,7 +1014,7 @@ cancgen64(Node *n, Node *res) ...@@ -1024,7 +1014,7 @@ cancgen64(Node *n, Node *res)
gins(AADCL, ncon(0), &hi1); gins(AADCL, ncon(0), &hi1);
gins(ANEGL, N, &hi1); gins(ANEGL, N, &hi1);
splitclean(); splitclean();
return 1; return;
case OCOM: case OCOM:
cgen(n->left, res); cgen(n->left, res);
...@@ -1032,7 +1022,7 @@ cancgen64(Node *n, Node *res) ...@@ -1032,7 +1022,7 @@ cancgen64(Node *n, Node *res)
gins(ANOTL, N, &lo1); gins(ANOTL, N, &lo1);
gins(ANOTL, N, &hi1); gins(ANOTL, N, &hi1);
splitclean(); splitclean();
return 1; return;
case OADD: case OADD:
case OSUB: case OSUB:
...@@ -1408,7 +1398,6 @@ out: ...@@ -1408,7 +1398,6 @@ out:
tempfree(&t2); tempfree(&t2);
if(l == &t1) if(l == &t1)
tempfree(&t1); tempfree(&t1);
return 1;
} }
/* /*
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include <u.h> #include <u.h>
#include <libc.h> #include <libc.h>
...@@ -68,7 +67,7 @@ EXTERN Node* throwreturn; ...@@ -68,7 +67,7 @@ EXTERN Node* throwreturn;
EXTERN int maxstksize; EXTERN int maxstksize;
/* /*
* gen.c * ggen.c
*/ */
void compile(Node*); void compile(Node*);
void proglist(void); void proglist(void);
...@@ -90,7 +89,7 @@ void checklabels(); ...@@ -90,7 +89,7 @@ void checklabels();
void ginscall(Node*, int); void ginscall(Node*, int);
/* /*
* cgen * cgen.c
*/ */
void agen(Node*, Node*); void agen(Node*, Node*);
void agenr(Node *n, Node *a, Node *res); void agenr(Node *n, Node *a, Node *res);
...@@ -103,10 +102,14 @@ Prog* gins(int, Node*, Node*); ...@@ -103,10 +102,14 @@ Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*); int samaddr(Node*, Node*);
void naddr(Node*, Addr*); void naddr(Node*, Addr*);
void cgen_aret(Node*, Node*); void cgen_aret(Node*, Node*);
int is64(Type*);
void cmp64(Node*, Node*, int, Prog*);
Node* ncon(uint32); Node* ncon(uint32);
/*
* cgen64.c
*/
void cmp64(Node*, Node*, int, Prog*);
void cgen64(Node*, Node*);
/* /*
* gsubr.c * gsubr.c
*/ */
...@@ -133,9 +136,10 @@ void tempfree(Node*); ...@@ -133,9 +136,10 @@ void tempfree(Node*);
Node* nodarg(Type*, int); Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int); void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int); void nodindreg(Node*, Type*, int);
void nodconst(Node*, Type*, vlong); void nodconst(Node*, Type*, int64);
void gconreg(int, vlong, int); void gconreg(int, vlong, int);
void datagostring(Strlit*, Addr*); void datagostring(Strlit*, Addr*);
void datastring(char*, int, Addr*);
void buildtxt(void); void buildtxt(void);
Plist* newplist(void); Plist* newplist(void);
int isfat(Type*); int isfat(Type*);
...@@ -145,6 +149,7 @@ int dotaddable(Node*, Node*); ...@@ -145,6 +149,7 @@ int dotaddable(Node*, Node*);
void afunclit(Addr*); void afunclit(Addr*);
void split64(Node*, Node*, Node*); void split64(Node*, Node*, Node*);
void splitclean(void); void splitclean(void);
void nswap(Node*, Node*);
/* /*
* list.c * list.c
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment