summaryrefslogtreecommitdiff
path: root/src/cmd/5g
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g')
-rw-r--r--src/cmd/5g/cgen.c81
-rw-r--r--src/cmd/5g/galign.c8
-rw-r--r--src/cmd/5g/gg.h12
-rw-r--r--src/cmd/5g/ggen.c25
-rw-r--r--src/cmd/5g/gsubr.c27
-rw-r--r--src/cmd/5g/opt.h20
-rw-r--r--src/cmd/5g/peep.c6
-rw-r--r--src/cmd/5g/reg.c12
8 files changed, 133 insertions, 58 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 9011b2022..c535cfbef 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -254,7 +254,6 @@ cgen(Node *n, Node *res)
case OOR:
case OXOR:
case OADD:
- case OADDPTR:
case OMUL:
a = optoas(n->op, nl->type);
goto sbop;
@@ -1107,11 +1106,10 @@ bgen(Node *n, int true, int likely, Prog *to)
{
int et, a;
Node *nl, *nr, *r;
- Node n1, n2, n3, n4, tmp;
+ Node n1, n2, n3, tmp;
NodeList *ll;
Prog *p1, *p2;
- USED(n4); // in unreachable code below
if(debug['g']) {
dump("\nbgen", n);
}
@@ -1497,7 +1495,7 @@ sgen(Node *n, Node *res, int64 w)
if(osrc < odst && odst < osrc+w)
dir = -dir;
- if(op == AMOVW && dir > 0 && c >= 4 && c <= 128) {
+ if(op == AMOVW && !nacl && dir > 0 && c >= 4 && c <= 128) {
r0.op = OREGISTER;
r0.val.u.reg = REGALLOC_R0;
r1.op = OREGISTER;
@@ -1524,7 +1522,7 @@ sgen(Node *n, Node *res, int64 w)
f = sysfunc("duffcopy");
p = gins(ADUFFCOPY, N, f);
afunclit(&p->to, f);
- // 8 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s
+ // 8 and 128 = magic constants: see ../../runtime/asm_arm.s
p->to.offset = 8*(128-c);
regfree(&tmp);
@@ -1636,7 +1634,10 @@ int
componentgen(Node *nr, Node *nl)
{
Node nodl, nodr, tmp;
+ Type *t;
int freel, freer;
+ vlong fldcount;
+ vlong loffset, roffset;
freel = 0;
freer = 0;
@@ -1646,8 +1647,33 @@ componentgen(Node *nr, Node *nl)
goto no;
case TARRAY:
- if(!isslice(nl->type))
+ t = nl->type;
+
+ // Slices are ok.
+ if(isslice(t))
+ break;
+ // Small arrays are ok.
+ if(t->bound > 0 && t->bound <= 3 && !isfat(t->type))
+ break;
+
+ goto no;
+
+ case TSTRUCT:
+ // Small structs with non-fat types are ok.
+ // Zero-sized structs are treated separately elsewhere.
+ fldcount = 0;
+ for(t=nl->type->type; t; t=t->down) {
+ if(isfat(t->type))
+ goto no;
+ if(t->etype != TFIELD)
+ fatal("componentgen: not a TFIELD: %lT", t);
+ fldcount++;
+ }
+ if(fldcount == 0 || fldcount > 4)
goto no;
+
+ break;
+
case TSTRING:
case TINTER:
break;
@@ -1675,6 +1701,7 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
+
// nl and nr are 'cadable' which basically means they are names (variables) now.
// If they are the same variable, don't generate any code, because the
// VARDEF we generate will mark the old value as dead incorrectly.
@@ -1684,8 +1711,25 @@ componentgen(Node *nr, Node *nl)
switch(nl->type->etype) {
case TARRAY:
+ // componentgen for arrays.
if(nl->op == ONAME)
gvardef(nl);
+ t = nl->type;
+ if(!isslice(t)) {
+ nodl.type = t->type;
+ nodr.type = nodl.type;
+ for(fldcount=0; fldcount < t->bound; fldcount++) {
+ if(nr == N)
+ clearslim(&nodl);
+ else
+ gmove(&nodr, &nodl);
+ nodl.xoffset += t->type->width;
+ nodr.xoffset += t->type->width;
+ }
+ goto yes;
+ }
+
+ // componentgen for slices.
nodl.xoffset += Array_array;
nodl.type = ptrto(nl->type->type);
@@ -1760,6 +1804,31 @@ componentgen(Node *nr, Node *nl)
gmove(&nodr, &nodl);
goto yes;
+
+ case TSTRUCT:
+ if(nl->op == ONAME)
+ gvardef(nl);
+ loffset = nodl.xoffset;
+ roffset = nodr.xoffset;
+ // funarg structs may not begin at offset zero.
+ if(nl->type->etype == TSTRUCT && nl->type->funarg && nl->type->type)
+ loffset -= nl->type->type->width;
+ if(nr != N && nr->type->etype == TSTRUCT && nr->type->funarg && nr->type->type)
+ roffset -= nr->type->type->width;
+
+ for(t=nl->type->type; t; t=t->down) {
+ nodl.xoffset = loffset + t->width;
+ nodl.type = t->type;
+
+ if(nr == N)
+ clearslim(&nodl);
+ else {
+ nodr.xoffset = roffset + t->width;
+ nodr.type = nodl.type;
+ gmove(&nodr, &nodl);
+ }
+ }
+ goto yes;
}
no:
diff --git a/src/cmd/5g/galign.c b/src/cmd/5g/galign.c
index a62102ef8..b4c45da69 100644
--- a/src/cmd/5g/galign.c
+++ b/src/cmd/5g/galign.c
@@ -23,10 +23,10 @@ vlong MAXWIDTH = (1LL<<32) - 1;
*/
Typedef typedefs[] =
{
- "int", TINT, TINT32,
- "uint", TUINT, TUINT32,
- "uintptr", TUINTPTR, TUINT32,
- 0
+ {"int", TINT, TINT32},
+ {"uint", TUINT, TUINT32},
+ {"uintptr", TUINTPTR, TUINT32},
+ {0}
};
void
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index 413e93c24..00914bfa3 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -11,10 +11,13 @@
#define TEXTFLAG reg
-#define REGALLOC_R0 0
-#define REGALLOC_RMAX REGEXT
-#define REGALLOC_F0 NREG
-#define REGALLOC_FMAX (REGALLOC_F0 + FREGEXT)
+enum
+{
+ REGALLOC_R0 = 0,
+ REGALLOC_RMAX = REGEXT,
+ REGALLOC_F0 = NREG,
+ REGALLOC_FMAX = REGALLOC_F0 + FREGEXT,
+};
EXTERN int32 dynloc;
EXTERN uchar reg[REGALLOC_FMAX+1];
@@ -106,7 +109,6 @@ void split64(Node*, Node*, Node*);
void splitclean(void);
Node* ncon(uint32 i);
void gtrack(Sym*);
-void gargsize(int32);
/*
* obj.c
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index fb32c2f36..53cddb760 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -76,7 +76,7 @@ zerorange(Prog *p, vlong frame, vlong lo, vlong hi, uint32 *r0)
if(cnt < 4*widthptr) {
for(i = 0; i < cnt; i += widthptr)
p = appendpp(p, AMOVW, D_REG, 0, 0, D_OREG, REGSP, 4+frame+lo+i);
- } else if(cnt <= 128*widthptr) {
+ } else if(!nacl && (cnt <= 128*widthptr)) {
p = appendpp(p, AADD, D_CONST, NREG, 4+frame+lo, D_REG, 1, 0);
p->reg = REGSP;
p = appendpp(p, ADUFFZERO, D_NONE, NREG, 0, D_OREG, NREG, 0);
@@ -179,28 +179,12 @@ fixautoused(Prog* p)
void
ginscall(Node *f, int proc)
{
- int32 arg;
Prog *p;
Node n1, r, r1, con;
if(f->type != T)
setmaxarg(f->type);
- arg = -1;
- // Most functions have a fixed-size argument block, so traceback uses that during unwind.
- // Not all, though: there are some variadic functions in package runtime,
- // and for those we emit call-specific metadata recorded by caller.
- // Reflect generates functions with variable argsize (see reflect.methodValueCall/makeFuncStub),
- // so we do this for all indirect calls as well.
- if(f->type != T && (f->sym == S || (f->sym != S && f->sym->pkg == runtimepkg) || proc == 1 || proc == 2)) {
- arg = f->type->argwid;
- if(proc == 1 || proc == 2)
- arg += 3*widthptr;
- }
-
- if(arg != -1)
- gargsize(arg);
-
switch(proc) {
default:
fatal("ginscall: bad proc %d", proc);
@@ -297,9 +281,6 @@ ginscall(Node *f, int proc)
}
break;
}
-
- if(arg != -1)
- gargsize(-1);
}
/*
@@ -906,11 +887,11 @@ clearfat(Node *nl)
patch(gbranch(ABNE, T, 0), pl);
regfree(&end);
- } else if(q >= 4) {
+ } else if(q >= 4 && !nacl) {
f = sysfunc("duffzero");
p = gins(ADUFFZERO, N, f);
afunclit(&p->to, f);
- // 4 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s
+ // 4 and 128 = magic constants: see ../../runtime/asm_arm.s
p->to.offset = 4*(128-q);
} else
while(q > 0) {
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index f66c87b5a..06e274e14 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -31,11 +31,11 @@
#include <u.h>
#include <libc.h>
#include "gg.h"
-#include "../../pkg/runtime/funcdata.h"
+#include "../../runtime/funcdata.h"
// TODO(rsc): Can make this bigger if we move
// the text segment up higher in 5l for all GOOS.
-// At the same time, can raise StackBig in ../../pkg/runtime/stack.h.
+// At the same time, can raise StackBig in ../../runtime/stack.h.
long unmappedzero = 4096;
void
@@ -206,17 +206,7 @@ ggloblnod(Node *nam)
}
void
-gargsize(int32 size)
-{
- Node n1, n2;
-
- nodconst(&n1, types[TINT32], PCDATA_ArgSize);
- nodconst(&n2, types[TINT32], size);
- gins(APCDATA, &n1, &n2);
-}
-
-void
-ggloblsym(Sym *s, int32 width, int dupok, int rodata)
+ggloblsym(Sym *s, int32 width, int8 flags)
{
Prog *p;
@@ -227,10 +217,7 @@ ggloblsym(Sym *s, int32 width, int dupok, int rodata)
p->to.type = D_CONST;
p->to.name = D_NONE;
p->to.offset = width;
- if(dupok)
- p->reg |= DUPOK;
- if(rodata)
- p->reg |= RODATA;
+ p->reg = flags;
}
void
@@ -374,7 +361,7 @@ regalloc(Node *n, Type *t, Node *o)
print("registers allocated at\n");
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
print("%d %p\n", i, regpc[i]);
- yyerror("out of fixed registers");
+ fatal("out of fixed registers");
goto err;
case TFLOAT32:
@@ -387,7 +374,7 @@ regalloc(Node *n, Type *t, Node *o)
for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
if(reg[i] == 0)
goto out;
- yyerror("out of floating point registers");
+ fatal("out of floating point registers");
goto err;
case TCOMPLEX64:
@@ -636,6 +623,7 @@ splitclean(void)
}
#define CASE(a,b) (((a)<<16)|((b)<<0))
+/*c2go int CASE(int, int); */
void
gmove(Node *f, Node *t)
@@ -1601,7 +1589,6 @@ optoas(int op, Type *t)
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
- case CASE(OADDPTR, TPTR32):
a = AADD;
break;
diff --git a/src/cmd/5g/opt.h b/src/cmd/5g/opt.h
index e3e3f78ed..1946c1d33 100644
--- a/src/cmd/5g/opt.h
+++ b/src/cmd/5g/opt.h
@@ -49,6 +49,24 @@
typedef struct Reg Reg;
typedef struct Rgn Rgn;
+/*c2go
+extern Node *Z;
+enum
+{
+ D_HI = D_NONE,
+ D_LO = D_NONE,
+ CLOAD = 5,
+ CREF = 5,
+ CINF = 1000,
+ LOOP = 3,
+};
+
+uint32 BLOAD(Reg*);
+uint32 BSTORE(Reg*);
+uint32 LOAD(Reg*);
+uint32 STORE(Reg*);
+*/
+
// A Reg is a wrapper around a single Prog (one instruction) that holds
// register optimization information while the optimizer runs.
// r->prog is the instruction.
@@ -71,8 +89,10 @@ struct Reg
int32 regu; // register used bitmap
};
#define R ((Reg*)0)
+/*c2go extern Reg *R; */
#define NRGN 600
+/*c2go enum { NRGN = 600 }; */
struct Rgn
{
Reg* enter;
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
index 4aa645206..639f4c5f6 100644
--- a/src/cmd/5g/peep.c
+++ b/src/cmd/5g/peep.c
@@ -564,6 +564,8 @@ gotit:
* ..
*/
#define FAIL(msg) { if(debug['P']) print("\t%s; FAILURE\n", msg); return 0; }
+/*c2go void FAIL(char*); */
+
int
shiftprop(Flow *r)
{
@@ -875,11 +877,15 @@ xtramodes(Graph *g, Flow *r, Adr *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/5g/reg.c b/src/cmd/5g/reg.c
index 4762df506..b78c268df 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -36,6 +36,11 @@
#define NREGVAR 32
#define REGBITS ((uint32)0xffffffff)
+/*c2go enum {
+ NREGVAR = 32,
+ REGBITS = 0xffffffff,
+};
+*/
void addsplits(void);
static Reg* firstr;
@@ -194,7 +199,7 @@ regopt(Prog *firstp)
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ABL && p->to.type == D_EXTERN)
+ if(p->as == ABL && p->to.name == D_EXTERN)
continue;
bit = mkvar(r, &p->from);
@@ -222,6 +227,10 @@ regopt(Prog *firstp)
for(z=0; z<BITS; z++)
r->set.b[z] |= bit.b[z];
}
+
+ /* the mod/div runtime routines smash R12 */
+ if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
+ r->set.b[0] |= RtoB(12);
}
if(firstr == R)
return;
@@ -1306,6 +1315,7 @@ void
addreg(Adr *a, int rn)
{
a->sym = nil;
+ a->node = nil;
a->name = D_NONE;
a->type = D_REG;
a->reg = rn;