aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-08-27 11:32:17 -0400
committerRuss Cox <rsc@golang.org>2014-08-27 11:32:17 -0400
commit25f6b02ab0db8e22994a3a68f4cb2857b788a63f (patch)
tree18ebdc29b6513e508ed78588698ba94ab8d1044a /src/cmd
parent0a7c7ac80e7c4ccd2b04b6b65100794adbd72ba5 (diff)
downloadgo-25f6b02ab0db8e22994a3a68f4cb2857b788a63f.tar.xz
cmd/cc, runtime: convert C compilers to use Go calling convention
To date, the C compilers and Go compilers differed only in how values were returned from functions. This made it difficult to call Go from C or C from Go if return values were involved. It also made assembly called from Go and assembly called from C different. This CL changes the C compiler to use the Go conventions, passing results on the stack, after the arguments. [Exception: this does not apply to C ... functions, because you can't know where on the stack the arguments end.] By doing this, the CL makes it possible to rewrite C functions into Go one at a time, without worrying about which languages call that function or which languages it calls. This CL also updates all the assembly files in package runtime to use the new conventions. Argument references of the form 40(SP) have been rewritten to the form name+10(FP) instead, and there are now Go func prototypes for every assembly function called from C or Go. This means that 'go vet runtime' checks effectively every assembly function, and go vet's output was used to automate the bulk of the conversion. Some functions, like seek and nsec on Plan 9, needed to be rewritten. Many assembly routines called from C were reading arguments incorrectly, using MOVL instead of MOVQ or vice versa, especially on the less used systems like openbsd. These were found by go vet and have been corrected too. If we're lucky, this may reduce flakiness on those systems. Tested on: darwin/386 darwin/amd64 linux/arm linux/386 linux/amd64 If this breaks another system, the bug is almost certainly in the sys_$GOOS_$GOARCH.s file, since the rest of the CL is tested by the combination of the above systems. LGTM=dvyukov, iant R=golang-codereviews, 0intro, dave, alex.brainman, dvyukov, iant CC=golang-codereviews, josharian, r https://golang.org/cl/135830043
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5c/cgen.c34
-rw-r--r--src/cmd/5c/gc.h4
-rw-r--r--src/cmd/5c/sgen.c2
-rw-r--r--src/cmd/5c/txt.c40
-rw-r--r--src/cmd/6c/cgen.c34
-rw-r--r--src/cmd/6c/gc.h4
-rw-r--r--src/cmd/6c/sgen.c2
-rw-r--r--src/cmd/6c/txt.c40
-rw-r--r--src/cmd/8c/cgen.c34
-rw-r--r--src/cmd/8c/gc.h4
-rw-r--r--src/cmd/8c/sgen.c2
-rw-r--r--src/cmd/8c/txt.c40
-rw-r--r--src/cmd/api/goapi.go1
-rw-r--r--src/cmd/cc/cc.h2
-rw-r--r--src/cmd/cc/dcl.c3
-rw-r--r--src/cmd/cc/pgen.c44
16 files changed, 221 insertions, 69 deletions
diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c
index 08ed36055a..5ea8eea073 100644
--- a/src/cmd/5c/cgen.c
+++ b/src/cmd/5c/cgen.c
@@ -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);
@@ -377,11 +377,11 @@ _cgen(Node *n, Node *nn, int inrel)
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 +823,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 +957,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 +1036,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 166900c3a9..7417b7dbe3 100644
--- a/src/cmd/5c/gc.h
+++ b/src/cmd/5c/gc.h
@@ -210,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
@@ -236,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/sgen.c b/src/cmd/5c/sgen.c
index efcc0437bb..a36612caa5 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/txt.c b/src/cmd/5c/txt.c
index a753510caa..af40220ccb 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
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
index bdef76ff08..b66c6add3e 100644
--- a/src/cmd/6c/cgen.c
+++ b/src/cmd/6c/cgen.c
@@ -51,7 +51,7 @@ cgen(Node *n, Node *nn)
}
if(n == Z || n->type == T)
return;
- if(typesu[n->type->etype]) {
+ if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
sugen(n, nn, n->type->width);
return;
}
@@ -88,7 +88,7 @@ cgen(Node *n, Node *nn)
if(cond(o) && typesu[l->type->etype])
break;
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
cgen(r, &nod);
regsalloc(&nod1, r);
@@ -135,7 +135,7 @@ cgen(Node *n, Node *nn)
if(!hardleft) {
if(nn != Z || r->addable < INDEXED || hardconst(r)) {
if(r->complex >= FNX && nn == Z)
- regret(&nod, r);
+ regret(&nod, r, 0, 0);
else
regalloc(&nod, r, nn);
cgen(r, &nod);
@@ -929,7 +929,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);
@@ -956,11 +956,13 @@ cgen(Node *n, Node *nn)
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
+ gpcdata(PCDATA_ArgSize, curarg);
+ gpcdata(PCDATA_ArgSize, -1);
+ if(nn != Z)
gmove(&nod, nn);
+ if(nod.op == OREGISTER)
regfree(&nod);
- }
break;
case OIND:
@@ -1382,7 +1384,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);
@@ -1535,7 +1537,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);
@@ -1617,6 +1619,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/6c/gc.h b/src/cmd/6c/gc.h
index bc4e36ccd8..aa9d95d21d 100644
--- a/src/cmd/6c/gc.h
+++ b/src/cmd/6c/gc.h
@@ -210,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
@@ -239,7 +239,7 @@ Node* nodfconst(double);
Node* nodgconst(vlong, Type*);
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/6c/sgen.c b/src/cmd/6c/sgen.c
index c048e784d4..d99510185e 100644
--- a/src/cmd/6c/sgen.c
+++ b/src/cmd/6c/sgen.c
@@ -36,7 +36,7 @@ gtext(Sym *s, int32 stkoff)
{
vlong v;
- v = ((uvlong)argsize() << 32) | (stkoff & 0xffffffff);
+ v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
if((textflag & NOSPLIT) && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c
index 4d07436c3f..3bdbf410ea 100644
--- a/src/cmd/6c/txt.c
+++ b/src/cmd/6c/txt.c
@@ -351,15 +351,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;
+
+ 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+7) & ~7;
+ regaalloc(n, nn);
+ return;
+ }
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET;
- nodreg(n, nn, r);
- reg[r]++;
+ 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->addable = 20;
+ n->xoffset = argsize(0);
+ return;
+ }
+
+ fatal(Z, "bad regret");
}
void
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c
index f541022456..8ac8e36009 100644
--- a/src/cmd/8c/cgen.c
+++ b/src/cmd/8c/cgen.c
@@ -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);
@@ -949,12 +949,12 @@ cgen(Node *n, Node *nn)
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 +1374,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 +1567,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 +1649,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 9c4613f562..aa3888d733 100644
--- a/src/cmd/8c/gc.h
+++ b/src/cmd/8c/gc.h
@@ -210,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
@@ -244,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/sgen.c b/src/cmd/8c/sgen.c
index 069bbc1fc3..d647010ef7 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/txt.c b/src/cmd/8c/txt.c
index 25082de05d..7f87a0a0d0 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
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 54c84b4d09..c3ab9c5bcf 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -385,6 +385,7 @@ func (w *Walker) parseFile(dir, file string) (*ast.File, error) {
" mcache struct{}; bucket struct{}; sudog struct{}; g struct{};" +
" hchan struct{}; chantype struct{}; waitq struct{};" +
" note struct{}; wincallbackcontext struct{};" +
+ " gobuf struct{}; funcval struct{};" +
"); " +
"const ( cb_max = 2000 )"
f, err = parser.ParseFile(fset, filename, src, 0)
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
index c8aac12530..1dae5acd90 100644
--- a/src/cmd/cc/cc.h
+++ b/src/cmd/cc/cc.h
@@ -794,7 +794,7 @@ void xcom(Node*);
int32 exreg(Type*);
int32 align(int32, Type*, int, int32*);
int32 maxround(int32, int32);
-int hasdotdotdot(void);
+int hasdotdotdot(Type*);
void linkarchinit(void);
extern schar ewidth[];
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c
index 051a6c0a74..7cda9f924d 100644
--- a/src/cmd/cc/dcl.c
+++ b/src/cmd/cc/dcl.c
@@ -697,7 +697,8 @@ argmark(Node *n, int pass)
{
Type *t;
- autoffset = align(0, thisfn->link, Aarg0, nil);
+ if(hasdotdotdot(thisfn->link))
+ autoffset = align(0, thisfn->link, Aarg0, nil);
stkoff = 0;
for(; n->left != Z; n = n->left) {
if(n->op != OFUNC || n->left->op != ONAME)
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
index 0ee13787f0..53410a11a0 100644
--- a/src/cmd/cc/pgen.c
+++ b/src/cmd/cc/pgen.c
@@ -56,24 +56,24 @@ makefuncdatasym(char *namefmt, int64 funcdatakind)
}
int
-hasdotdotdot(void)
+hasdotdotdot(Type *t)
{
- Type *t;
-
- for(t=thisfn->down; t!=T; t=t->down)
+ for(t=t->down; t!=T; t=t->down)
if(t->etype == TDOT)
return 1;
return 0;
}
vlong
-argsize(void)
+argsize(int doret)
{
Type *t;
int32 s;
//print("t=%T\n", thisfn);
- s = align(0, thisfn->link, Aarg0, nil);
+ s = 0;
+ if(hasdotdotdot(thisfn))
+ s = align(s, thisfn->link, Aarg0, nil);
for(t=thisfn->down; t!=T; t=t->down) {
switch(t->etype) {
case TVOID:
@@ -93,6 +93,14 @@ argsize(void)
s = (s+7) & ~7;
else
s = (s+3) & ~3;
+ if(doret && thisfn->link->etype != TVOID) {
+ s = align(s, thisfn->link, Aarg1, nil);
+ s = align(s, thisfn->link, Aarg2, nil);
+ if(thechar == '6')
+ s = (s+7) & ~7;
+ else
+ s = (s+3) & ~3;
+ }
return s;
}
@@ -129,7 +137,7 @@ codgen(Node *n, Node *nn)
* generate funcdata symbol for this function.
* data is filled in at the end of codgen().
*/
- isvarargs = hasdotdotdot();
+ isvarargs = hasdotdotdot(thisfn);
gcargs = nil;
if(!isvarargs)
gcargs = makefuncdatasym("gcargs·%d", FUNCDATA_ArgsPointerMaps);
@@ -212,7 +220,7 @@ supgen(Node *n)
void
gen(Node *n)
{
- Node *l, nod;
+ Node *l, nod, nod1;
Prog *sp, *spc, *spb;
Case *cn;
long sbc, scc;
@@ -273,14 +281,26 @@ loop:
gbranch(ORETURN);
break;
}
+ if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) {
+ regret(&nod, n, thisfn, 2);
+ sugen(l, &nod, n->type->width);
+ noretval(3);
+ gbranch(ORETURN);
+ break;
+ }
if(typecmplx[n->type->etype]) {
sugen(l, nodret, n->type->width);
noretval(3);
gbranch(ORETURN);
break;
}
- regret(&nod, n);
+ regret(&nod1, n, thisfn, 2);
+ nod = nod1;
+ if(nod.op != OREGISTER)
+ regalloc(&nod, n, Z);
cgen(l, &nod);
+ if(nod1.op != OREGISTER)
+ gmove(&nod, &nod1);
regfree(&nod);
if(typefd[n->type->etype])
noretval(1);
@@ -729,9 +749,11 @@ dumpgcargs(Type *fn, Sym *sym)
symoffset = 0;
gextern(sym, nodconst(1), symoffset, 4);
symoffset += 4;
- argbytes = (argsize() + ewidth[TIND] - 1);
+ argbytes = (argsize(1) + ewidth[TIND] - 1);
bv = bvalloc((argbytes / ewidth[TIND]) * BitsPerPointer);
- argoffset = align(0, fn->link, Aarg0, nil);
+ argoffset = 0;
+ if(hasdotdotdot(thisfn))
+ argoffset = align(0, fn->link, Aarg0, nil);
if(argoffset > 0) {
// The C calling convention returns structs by copying them to a
// location pointed to by a hidden first argument. This first