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