summaryrefslogtreecommitdiff
path: root/src/cmd/8c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8c')
-rw-r--r--src/cmd/8c/cgen.c38
-rw-r--r--src/cmd/8c/gc.h5
-rw-r--r--src/cmd/8c/reg.c9
-rw-r--r--src/cmd/8c/sgen.c2
-rw-r--r--src/cmd/8c/swt.c9
-rw-r--r--src/cmd/8c/txt.c40
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