diff options
Diffstat (limited to 'src/cmd/8c')
-rw-r--r-- | src/cmd/8c/cgen.c | 38 | ||||
-rw-r--r-- | src/cmd/8c/gc.h | 5 | ||||
-rw-r--r-- | src/cmd/8c/reg.c | 9 | ||||
-rw-r--r-- | src/cmd/8c/sgen.c | 2 | ||||
-rw-r--r-- | src/cmd/8c/swt.c | 9 | ||||
-rw-r--r-- | src/cmd/8c/txt.c | 40 |
6 files changed, 71 insertions, 32 deletions
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c index f54102245..87e8fdad8 100644 --- a/src/cmd/8c/cgen.c +++ b/src/cmd/8c/cgen.c @@ -29,7 +29,7 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" /* ,x/^(print|prtree)\(/i/\/\/ */ @@ -49,7 +49,7 @@ cgen(Node *n, Node *nn) } if(n == Z || n->type == T) return; - if(typesuv[n->type->etype]) { + if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) { sugen(n, nn, n->type->width); return; } @@ -86,7 +86,7 @@ cgen(Node *n, Node *nn) if(cond(o) && typesuv[l->type->etype]) break; - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); @@ -147,7 +147,7 @@ cgen(Node *n, Node *nn) if(!hardleft) { if(nn != Z || r->addable < INDEXED) { if(r->complex >= FNX && nn == Z) - regret(&nod, r); + regret(&nod, r, 0, 0); else regalloc(&nod, r, nn); cgen(r, &nod); @@ -922,7 +922,7 @@ cgen(Node *n, Node *nn) if(l->op != OIND) diag(n, "bad function call"); - regret(&nod, l->left); + regret(&nod, l->left, 0, 0); cgen(l->left, &nod); regsalloc(&nod1, l->left); gmove(&nod, &nod1); @@ -938,7 +938,6 @@ cgen(Node *n, Node *nn) return; } gargs(r, &nod, &nod1); - gpcdata(PCDATA_ArgSize, curarg); if(l->addable < INDEXED) { reglcgen(&nod, l, nn); nod.op = OREGISTER; @@ -946,15 +945,14 @@ cgen(Node *n, Node *nn) regfree(&nod); } else gopcode(OFUNC, n->type, Z, l); - gpcdata(PCDATA_ArgSize, -1); if(REGARG >= 0 && reg[REGARG]) reg[REGARG]--; - if(nn != Z) { - regret(&nod, n); + regret(&nod, n, l->type, 1); // update maxarg if nothing else + if(nn != Z) gmove(&nod, nn); + if(nod.op == OREGISTER) regfree(&nod); - } else - if(typefd[n->type->etype]) + if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype]) gins(AFMOVDP, &fregnode0, &fregnode0); break; @@ -1374,7 +1372,7 @@ boolgen(Node *n, int true, Node *nn) if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); gmove(&nod, &nod1); @@ -1567,7 +1565,7 @@ sugen(Node *n, Node *nn, int32 w) if(nn != Z && side(nn)) { nod1 = *n; nod1.type = typ(TIND, n->type); - regret(&nod2, &nod1); + regret(&nod2, &nod1, 0, 0); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); cgen(&nod2, &nod0); @@ -1649,6 +1647,20 @@ sugen(Node *n, Node *nn, int32 w) break; case OFUNC: + if(!hasdotdotdot(n->left->type)) { + cgen(n, Z); + if(nn != Z) { + curarg -= n->type->width; + regret(&nod1, n, n->left->type, 1); + if(nn->complex >= FNX) { + regsalloc(&nod2, n); + cgen(&nod1, &nod2); + nod1 = nod2; + } + cgen(&nod1, nn); + } + break; + } if(nn == Z) { sugen(n, nodrat, w); break; diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h index 87b8e22bc..aa3888d73 100644 --- a/src/cmd/8c/gc.h +++ b/src/cmd/8c/gc.h @@ -143,7 +143,6 @@ EXTERN int32 cursafe; EXTERN Prog* lastp; EXTERN int32 maxargsafe; EXTERN int mnstring; -EXTERN int retok; EXTERN Node* nodrat; EXTERN Node* nodret; EXTERN Node* nodsafe; @@ -211,7 +210,7 @@ void xcom(Node*); void indx(Node*); int bcomplex(Node*, Node*); Prog* gtext(Sym*, int32); -vlong argsize(void); +vlong argsize(int); /* * cgen.c @@ -245,7 +244,7 @@ Node* nodconst(int32); Node* nodfconst(double); int nodreg(Node*, Node*, int); int isreg(Node*, int); -void regret(Node*, Node*); +void regret(Node*, Node*, Type*, int); void regalloc(Node*, Node*, Node*); void regfree(Node*); void regialloc(Node*, Node*, Node*); diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c index e6ba8bcb3..ea862f388 100644 --- a/src/cmd/8c/reg.c +++ b/src/cmd/8c/reg.c @@ -518,7 +518,7 @@ loop2: rgp->cost = change; nregion++; if(nregion >= NRGN) { - warn(Z, "too many regions"); + fatal(Z, "too many regions"); goto brk; } rgp++; @@ -746,11 +746,8 @@ mkvar(Reg *r, Addr *a) goto out; v++; } - if(nvar >= NVAR) { - if(debug['w'] > 1 && s) - warn(Z, "variable not optimized: %s", s->name); - goto none; - } + if(nvar >= NVAR) + fatal(Z, "variable not optimized: %s", s->name); i = nvar; nvar++; v = &var[i]; diff --git a/src/cmd/8c/sgen.c b/src/cmd/8c/sgen.c index 069bbc1fc..d647010ef 100644 --- a/src/cmd/8c/sgen.c +++ b/src/cmd/8c/sgen.c @@ -35,7 +35,7 @@ gtext(Sym *s, int32 stkoff) { int32 a; - a = argsize(); + a = argsize(1); if((textflag & NOSPLIT) != 0 && stkoff >= 128) yyerror("stack frame too large for NOSPLIT function"); diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c index ae36f84ea..d960519e3 100644 --- a/src/cmd/8c/swt.c +++ b/src/cmd/8c/swt.c @@ -255,10 +255,11 @@ align(int32 i, Type *t, int op, int32 *maxalign) { int32 o; Type *v; - int w; + int w, packw; o = i; w = 1; + packw = 0; switch(op) { default: diag(Z, "unknown align opcode %d", op); @@ -269,7 +270,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1) w = 1; if(packflg) - w = packflg; + packw = packflg; break; case Ael1: /* initial align of struct element */ @@ -285,7 +286,7 @@ align(int32 i, Type *t, int op, int32 *maxalign) if(w < 1 || w > SZ_LONG) fatal(Z, "align"); if(packflg) - w = packflg; + packw = packflg; break; case Ael2: /* width of a struct element */ @@ -320,6 +321,8 @@ align(int32 i, Type *t, int op, int32 *maxalign) o = align(o, t, Ael2, nil); break; } + if(packw != 0 && xround(o, w) != xround(o, packw)) + diag(Z, "#pragma pack changes offset of %T", t); o = xround(o, w); if(maxalign && *maxalign < w) *maxalign = w; diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c index 25082de05..7f87a0a0d 100644 --- a/src/cmd/8c/txt.c +++ b/src/cmd/8c/txt.c @@ -311,15 +311,43 @@ nodreg(Node *n, Node *nn, int r) } void -regret(Node *n, Node *nn) +regret(Node *n, Node *nn, Type *t, int mode) { int r; - r = REGRET; - if(typefd[nn->type->etype]) - r = FREGRET; - nodreg(n, nn, r); - reg[r]++; + if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { + r = REGRET; + if(typefd[nn->type->etype]) + r = FREGRET; + nodreg(n, nn, r); + reg[r]++; + return; + } + + if(mode == 1) { + // fetch returned value after call. + // already called gargs, so curarg is set. + curarg = (curarg+3) & ~3; + regaalloc(n, nn); + return; + } + + if(mode == 2) { + // store value to be returned. + // must compute arg offset. + if(t->etype != TFUNC) + fatal(Z, "bad regret func %T", t); + *n = *nn; + n->op = ONAME; + n->class = CPARAM; + n->sym = slookup(".retx"); + n->complex = 0; + n->addable = 20; + n->xoffset = argsize(0); + return; + } + + fatal(Z, "bad regret"); } void |