diff options
Diffstat (limited to 'src/cmd/5c')
-rw-r--r-- | src/cmd/5c/cgen.c | 38 | ||||
-rw-r--r-- | src/cmd/5c/gc.h | 5 | ||||
-rw-r--r-- | src/cmd/5c/peep.c | 4 | ||||
-rw-r--r-- | src/cmd/5c/reg.c | 19 | ||||
-rw-r--r-- | src/cmd/5c/sgen.c | 2 | ||||
-rw-r--r-- | src/cmd/5c/swt.c | 11 | ||||
-rw-r--r-- | src/cmd/5c/txt.c | 40 |
7 files changed, 86 insertions, 33 deletions
diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c index 08ed36055..5a049ae62 100644 --- a/src/cmd/5c/cgen.c +++ b/src/cmd/5c/cgen.c @@ -29,7 +29,7 @@ // THE SOFTWARE. #include "gc.h" -#include "../../pkg/runtime/funcdata.h" +#include "../../runtime/funcdata.h" void _cgen(Node *n, Node *nn, int inrel) @@ -46,7 +46,7 @@ _cgen(Node *n, Node *nn, int inrel) } 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; } @@ -75,7 +75,7 @@ _cgen(Node *n, Node *nn, int inrel) if(r != Z && r->complex >= FNX) switch(o) { default: - regret(&nod, r); + regret(&nod, r, 0, 0); cgen(r, &nod); regsalloc(&nod1, r); @@ -107,7 +107,7 @@ _cgen(Node *n, Node *nn, int inrel) if(l->addable >= INDEXED && l->complex < FNX) { 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); @@ -348,7 +348,7 @@ _cgen(Node *n, Node *nn, int inrel) 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); gopcode(OAS, &nod, Z, &nod1); @@ -366,22 +366,20 @@ _cgen(Node *n, Node *nn, int inrel) if(REGARG >= 0) o = reg[REGARG]; gargs(r, &nod, &nod1); - gpcdata(PCDATA_ArgSize, curarg); if(l->addable < INDEXED) { reglcgen(&nod, l, Z); gopcode(OFUNC, Z, Z, &nod); regfree(&nod); } else gopcode(OFUNC, Z, Z, l); - gpcdata(PCDATA_ArgSize, -1); if(REGARG >= 0) if(o != reg[REGARG]) reg[REGARG]--; - if(nn != Z) { - regret(&nod, n); - gopcode(OAS, &nod, Z, nn); + regret(&nod, n, l->type, 1); + if(nn != Z) + gmove(&nod, nn); + if(nod.op == OREGISTER) regfree(&nod); - } break; case OIND: @@ -823,7 +821,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); cgenrel(r, &nod); regsalloc(&nod1, r); gopcode(OAS, &nod, Z, &nod1); @@ -957,7 +955,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); gopcode(OAS, &nod2, Z, &nod0); @@ -1036,6 +1034,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/5c/gc.h b/src/cmd/5c/gc.h index 40d3a2b07..7417b7dbe 100644 --- a/src/cmd/5c/gc.h +++ b/src/cmd/5c/gc.h @@ -144,7 +144,6 @@ EXTERN Prog* lastp; EXTERN int32 maxargsafe; EXTERN int mnstring; EXTERN Multab multab[20]; -EXTERN int retok; extern int hintabsize; EXTERN Node* nodrat; EXTERN Node* nodret; @@ -211,7 +210,7 @@ void usedset(Node*, int); void xcom(Node*); int bcomplex(Node*, Node*); Prog* gtext(Sym*, int32); -vlong argsize(void); +vlong argsize(int); /* * cgen.c @@ -237,7 +236,7 @@ Node* nodconst(int32); Node* nod32const(vlong); Node* nodfconst(double); void nodreg(Node*, Node*, int); -void regret(Node*, Node*); +void regret(Node*, Node*, Type*, int); int tmpreg(void); void regalloc(Node*, Node*, Node*); void regfree(Node*); diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c index 143400a63..1de56b594 100644 --- a/src/cmd/5c/peep.c +++ b/src/cmd/5c/peep.c @@ -853,11 +853,15 @@ xtramodes(Reg *r, Addr *a) switch (p1->from.type) { case D_REG: /* register offset */ + if(nacl) + return 0; a->type = D_SHIFT; a->offset = p1->from.reg; break; case D_SHIFT: /* scaled register offset */ + if(nacl) + return 0; a->type = D_SHIFT; case D_CONST: /* immediate offset */ diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c index b9ac21abd..9024d5f49 100644 --- a/src/cmd/5c/reg.c +++ b/src/cmd/5c/reg.c @@ -204,6 +204,16 @@ regopt(Prog *p) break; } + /* the mod/div runtime routines smash R12 */ + switch(p->as) { + case AMOD: + case AMODU: + case ADIV: + case ADIVU: + regbits |= RtoB(12); + break; + } + if(p->as == AMOVM) { if(p->from.type == D_CONST) z = p->from.offset; @@ -396,7 +406,7 @@ loop2: rgp->cost = change; nregion++; if(nregion >= NRGN) { - warn(Z, "too many regions"); + fatal(Z, "too many regions"); goto brk; } rgp++; @@ -632,11 +642,8 @@ mkvar(Addr *a, int docon) if(s) if(s->name[0] == '.') goto none; - 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/5c/sgen.c b/src/cmd/5c/sgen.c index efcc0437b..a36612caa 100644 --- a/src/cmd/5c/sgen.c +++ b/src/cmd/5c/sgen.c @@ -36,7 +36,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/5c/swt.c b/src/cmd/5c/swt.c index fd81a4e68..f39963b8f 100644 --- a/src/cmd/5c/swt.c +++ b/src/cmd/5c/swt.c @@ -60,7 +60,7 @@ swit2(C1 *q, int nc, int32 def, Node *n) if(nc >= 3) { i = (q+nc-1)->val - (q+0)->val; - if(i > 0 && i < nc*2) + if(!nacl && i > 0 && i < nc*2) goto direct; } if(nc < 5) { @@ -374,10 +374,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); @@ -388,7 +389,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 */ @@ -404,7 +405,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 */ @@ -440,6 +441,8 @@ align(int32 i, Type *t, int op, int32 *maxalign) w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ 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 != nil && *maxalign < w) *maxalign = w; diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c index a753510ca..af40220cc 100644 --- a/src/cmd/5c/txt.c +++ b/src/cmd/5c/txt.c @@ -274,15 +274,43 @@ nodreg(Node *n, Node *nn, int reg) } 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+NREG; - nodreg(n, nn, r); - reg[r]++; + if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) { + r = REGRET; + if(typefd[nn->type->etype]) + r = FREGRET+NREG; + 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(".ret"); + n->complex = nodret->complex; + n->xoffset = argsize(0); + n->addable = 20; + return; + } + + fatal(Z, "bad regret"); } int |