summaryrefslogtreecommitdiff
path: root/src/cmd/5g/ggen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/ggen.c')
-rw-r--r--src/cmd/5g/ggen.c87
1 files changed, 63 insertions, 24 deletions
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 3243bb863..42a89415d 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -61,11 +61,14 @@ compile(Node *fn)
pl = newplist();
pl->name = curfn->nname;
+
+ setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
+ ginit();
genlist(curfn->enter);
pret = nil;
@@ -78,6 +81,7 @@ compile(Node *fn)
}
genlist(curfn->nbody);
+ gclean();
checklabels();
if(nerrors != 0)
goto ret;
@@ -87,29 +91,32 @@ compile(Node *fn)
if(pret)
patch(pret, pc);
+ ginit();
+ if(hasdefer)
+ ginscall(deferreturn, 0);
if(curfn->exit)
genlist(curfn->exit);
+ gclean();
if(nerrors != 0)
goto ret;
- if(hasdefer)
- ginscall(deferreturn, 0);
+ if(curfn->endlineno)
+ lineno = curfn->endlineno;
pc->as = ARET; // overwrite AEND
pc->lineno = lineno;
- /* TODO(kaib): Add back register optimizations
- if(!debug['N'] || debug['R'] || debug['P'])
+ if(!debug['N'] || debug['R'] || debug['P']) {
regopt(ptxt);
- */
+ }
// fill in argument size
ptxt->to.type = D_CONST2;
ptxt->reg = 0; // flags
- ptxt->to.offset2 = rnd(curfn->type->argwid, maxround);
+ ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
// fill in final stack size
if(stksize > maxstksize)
maxstksize = stksize;
- ptxt->to.offset = rnd(maxstksize+maxarg, maxround);
+ ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0;
if(debug['f'])
@@ -203,6 +210,7 @@ ginscall(Node *f, int proc)
void
cgen_callinter(Node *n, Node *res, int proc)
{
+ int r;
Node *i, *f;
Node tmpi, nodo, nodr, nodsp;
@@ -216,6 +224,14 @@ cgen_callinter(Node *n, Node *res, int proc)
i = i->left; // interface
+ // Release res register during genlist and cgen,
+ // which might have their own function calls.
+ r = -1;
+ if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
+ r = res->val.u.reg;
+ reg[r]--;
+ }
+
if(!i->addable) {
tempname(&tmpi, i->type);
cgen(i, &tmpi);
@@ -223,6 +239,8 @@ cgen_callinter(Node *n, Node *res, int proc)
}
genlist(n->list); // args
+ if(r >= 0)
+ reg[r]++;
regalloc(&nodr, types[tptr], res);
regalloc(&nodo, types[tptr], &nodr);
@@ -427,10 +445,10 @@ cgen_asop(Node *n)
case OOR:
a = optoas(n->etype, nl->type);
if(nl->addable) {
- regalloc(&n2, nl->type, N);
regalloc(&n3, nr->type, N);
- cgen(nl, &n2);
cgen(nr, &n3);
+ regalloc(&n2, nl->type, N);
+ cgen(nl, &n2);
gins(a, &n3, &n2);
cgen(&n2, nl);
regfree(&n2);
@@ -439,13 +457,14 @@ cgen_asop(Node *n)
}
if(nr->ullman < UINF)
if(sudoaddable(a, nl, &addr, &w)) {
+ w = optoas(OAS, nl->type);
regalloc(&n2, nl->type, N);
- regalloc(&n3, nr->type, N);
- p1 = gins(AMOVW, N, &n2);
+ p1 = gins(w, N, &n2);
p1->from = addr;
+ regalloc(&n3, nr->type, N);
cgen(nr, &n3);
gins(a, &n3, &n2);
- p1 = gins(AMOVW, &n2, N);
+ p1 = gins(w, &n2, N);
p1->to = addr;
regfree(&n2);
regfree(&n3);
@@ -544,7 +563,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
cgen(nl, &n1);
sc = mpgetfix(nr->val.u.xval);
if(sc == 0) {
- return;
+ // nothing to do
} else if(sc >= nl->type->width*8) {
if(op == ORSH && issigned[nl->type->etype])
gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
@@ -682,6 +701,29 @@ regcmp(const void *va, const void *vb)
static Prog* throwpc;
+// We're only going to bother inlining if we can
+// convert all the arguments to 32 bits safely. Can we?
+static int
+fix64(NodeList *nn, int n)
+{
+ NodeList *l;
+ Node *r;
+ int i;
+
+ l = nn;
+ for(i=0; i<n; i++) {
+ r = l->n->right;
+ if(is64(r->type) && !smallintconst(r)) {
+ if(r->op == OCONV)
+ r = r->left;
+ if(is64(r->type))
+ return 0;
+ }
+ l = l->next;
+ }
+ return 1;
+}
+
void
getargs(NodeList *nn, Node *reg, int n)
{
@@ -710,7 +752,7 @@ getargs(NodeList *nn, Node *reg, int n)
void
cmpandthrow(Node *nl, Node *nr)
{
- vlong cl, cr;
+ vlong cl;
Prog *p1;
int op;
Node *c, n1, n2;
@@ -720,17 +762,8 @@ cmpandthrow(Node *nl, Node *nr)
cl = mpgetfix(nl->val.u.xval);
if(cl == 0)
return;
- if(smallintconst(nr)) {
- cr = mpgetfix(nr->val.u.xval);
- if(cl > cr) {
- if(throwpc == nil) {
- throwpc = pc;
- ginscall(panicslice, 0);
- } else
- patch(gbranch(AB, T), throwpc);
- }
+ if(smallintconst(nr))
return;
- }
// put the constant on the right
op = brrev(op);
@@ -794,6 +827,8 @@ cgen_inline(Node *n, Node *res)
goto no;
if(!n->left->addable)
goto no;
+ if(n->left->sym == S)
+ goto no;
if(n->left->sym->pkg != runtimepkg)
goto no;
if(strcmp(n->left->sym->name, "slicearray") == 0)
@@ -811,6 +846,8 @@ cgen_inline(Node *n, Node *res)
slicearray:
if(!sleasy(res))
goto no;
+ if(!fix64(n->list, 5))
+ goto no;
getargs(n->list, nodes, 5);
// if(hb[3] > nel[1]) goto throw
@@ -902,6 +939,8 @@ slicearray:
return 1;
sliceslice:
+ if(!fix64(n->list, narg))
+ goto no;
ntemp.op = OXXX;
if(!sleasy(n->list->n->right)) {
Node *n0;