mirror of
https://github.com/golang/go
synced 2024-11-26 04:47:57 -07:00
closures - 6g support
R=ken OCL=24501 CL=24566
This commit is contained in:
parent
0f4f2a6183
commit
0970c46863
@ -205,7 +205,7 @@ cgen(Node *n, Node *res)
|
|||||||
case ODOTPTR:
|
case ODOTPTR:
|
||||||
case OINDEX:
|
case OINDEX:
|
||||||
case OIND:
|
case OIND:
|
||||||
case ONAME: // PHEAP var
|
case ONAME: // PHEAP or PPARAMREF var
|
||||||
igen(n, &n1, res);
|
igen(n, &n1, res);
|
||||||
gmove(&n1, res);
|
gmove(&n1, res);
|
||||||
regfree(&n1);
|
regfree(&n1);
|
||||||
@ -526,9 +526,18 @@ agen(Node *n, Node *res)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ONAME:
|
case ONAME:
|
||||||
// should only get here for heap vars
|
// should only get here with names in this func.
|
||||||
if(!(n->class & PHEAP))
|
if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
|
||||||
|
dump("bad agen", n);
|
||||||
|
fatal("agen: bad ONAME funcdepth %d != %d",
|
||||||
|
n->funcdepth, funcdepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// should only get here for heap vars or paramref
|
||||||
|
if(!(n->class & PHEAP) && n->class != PPARAMREF) {
|
||||||
|
dump("bad agen", n);
|
||||||
fatal("agen: bad ONAME class %#x", n->class);
|
fatal("agen: bad ONAME class %#x", n->class);
|
||||||
|
}
|
||||||
cgen(n->heapaddr, res);
|
cgen(n->heapaddr, res);
|
||||||
if(n->xoffset != 0) {
|
if(n->xoffset != 0) {
|
||||||
nodconst(&n1, types[TINT64], n->xoffset);
|
nodconst(&n1, types[TINT64], n->xoffset);
|
||||||
|
216
src/cmd/gc/dcl.c
216
src/cmd/gc/dcl.c
@ -402,13 +402,12 @@ funchdr(Node *n)
|
|||||||
autodcl = dcl();
|
autodcl = dcl();
|
||||||
autodcl->back = autodcl;
|
autodcl->back = autodcl;
|
||||||
|
|
||||||
if(dclcontext != PEXTERN)
|
if(funcdepth == 0 && dclcontext != PEXTERN)
|
||||||
fatal("funchdr: dclcontext");
|
fatal("funchdr: dclcontext");
|
||||||
|
|
||||||
dclcontext = PAUTO;
|
dclcontext = PAUTO;
|
||||||
markdcl();
|
markdcl();
|
||||||
funcargs(n->type);
|
funcargs(n->type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -418,6 +417,8 @@ funcargs(Type *ft)
|
|||||||
Iter save;
|
Iter save;
|
||||||
int all;
|
int all;
|
||||||
|
|
||||||
|
funcdepth++;
|
||||||
|
|
||||||
// declare the this/in arguments
|
// declare the this/in arguments
|
||||||
t = funcfirst(&save, ft);
|
t = funcfirst(&save, ft);
|
||||||
while(t != T) {
|
while(t != T) {
|
||||||
@ -466,9 +467,176 @@ funcbody(Node *n)
|
|||||||
if(dclcontext != PAUTO)
|
if(dclcontext != PAUTO)
|
||||||
fatal("funcbody: dclcontext");
|
fatal("funcbody: dclcontext");
|
||||||
popdcl();
|
popdcl();
|
||||||
|
funcdepth--;
|
||||||
|
if(funcdepth == 0)
|
||||||
dclcontext = PEXTERN;
|
dclcontext = PEXTERN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
funclit0(Type *t)
|
||||||
|
{
|
||||||
|
Node *n;
|
||||||
|
|
||||||
|
n = nod(OXXX, N, N);
|
||||||
|
n->outer = funclit;
|
||||||
|
funclit = n;
|
||||||
|
|
||||||
|
funcargs(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
funclit1(Type *type, Node *body)
|
||||||
|
{
|
||||||
|
Node *func;
|
||||||
|
Node *a, *d, *f, *n, *args, *clos, *in, *out;
|
||||||
|
Type *ft, *t;
|
||||||
|
Iter save;
|
||||||
|
int narg, shift;
|
||||||
|
|
||||||
|
popdcl();
|
||||||
|
func = funclit;
|
||||||
|
funclit = func->outer;
|
||||||
|
|
||||||
|
// build up type of func f that we're going to compile.
|
||||||
|
// as we referred to variables from the outer function,
|
||||||
|
// we accumulated a list of PHEAP names in func.
|
||||||
|
//
|
||||||
|
narg = 0;
|
||||||
|
if(func->cvars == N)
|
||||||
|
ft = type;
|
||||||
|
else {
|
||||||
|
// add PHEAP versions as function arguments.
|
||||||
|
in = N;
|
||||||
|
for(a=listfirst(&save, &func->cvars); a; a=listnext(&save)) {
|
||||||
|
d = nod(ODCLFIELD, a, N);
|
||||||
|
d->type = ptrto(a->type);
|
||||||
|
in = list(in, d);
|
||||||
|
|
||||||
|
// while we're here, set up a->heapaddr for back end
|
||||||
|
n = nod(ONAME, N, N);
|
||||||
|
snprint(namebuf, sizeof namebuf, "&%s", a->sym->name);
|
||||||
|
n->sym = lookup(namebuf);
|
||||||
|
n->type = ptrto(a->type);
|
||||||
|
n->class = PPARAM;
|
||||||
|
n->xoffset = narg*types[tptr]->width;
|
||||||
|
n->addable = 1;
|
||||||
|
n->ullman = 1;
|
||||||
|
narg++;
|
||||||
|
a->heapaddr = n;
|
||||||
|
|
||||||
|
a->xoffset = 0;
|
||||||
|
|
||||||
|
// unlink from actual ONAME in symbol table
|
||||||
|
a->closure->closure = a->outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a dummy arg for the closure's caller pc
|
||||||
|
d = nod(ODCLFIELD, a, N);
|
||||||
|
d->type = types[TUINTPTR];
|
||||||
|
in = list(in, d);
|
||||||
|
|
||||||
|
// slide param offset to make room for ptrs above.
|
||||||
|
// narg+1 to skip over caller pc.
|
||||||
|
shift = (narg+1)*types[tptr]->width;
|
||||||
|
|
||||||
|
// now the original arguments.
|
||||||
|
for(t=structfirst(&save, getinarg(type)); t; t=structnext(&save)) {
|
||||||
|
d = nod(ODCLFIELD, t->nname, N);
|
||||||
|
d->type = t->type;
|
||||||
|
in = list(in, d);
|
||||||
|
|
||||||
|
a = t->nname;
|
||||||
|
if(a != N) {
|
||||||
|
if(a->stackparam != N)
|
||||||
|
a = a->stackparam;
|
||||||
|
a->xoffset += shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in = rev(in);
|
||||||
|
|
||||||
|
// out arguments
|
||||||
|
out = N;
|
||||||
|
for(t=structfirst(&save, getoutarg(type)); t; t=structnext(&save)) {
|
||||||
|
d = nod(ODCLFIELD, t->nname, N);
|
||||||
|
d->type = t->type;
|
||||||
|
out = list(out, d);
|
||||||
|
|
||||||
|
a = t->nname;
|
||||||
|
if(a != N) {
|
||||||
|
if(a->stackparam != N)
|
||||||
|
a = a->stackparam;
|
||||||
|
a->xoffset += shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out = rev(out);
|
||||||
|
|
||||||
|
ft = functype(N, in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// declare function.
|
||||||
|
vargen++;
|
||||||
|
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);
|
||||||
|
f = newname(lookup(namebuf));
|
||||||
|
addvar(f, ft, PFUNC);
|
||||||
|
f->funcdepth = 0;
|
||||||
|
|
||||||
|
// compile function
|
||||||
|
n = nod(ODCLFUNC, N, N);
|
||||||
|
n->nname = f;
|
||||||
|
n->type = ft;
|
||||||
|
if(body == N)
|
||||||
|
body = nod(ORETURN, N, N);
|
||||||
|
n->nbody = body;
|
||||||
|
compile(n);
|
||||||
|
funcdepth--;
|
||||||
|
|
||||||
|
// if there's no closure, we can use f directly
|
||||||
|
if(func->cvars == N)
|
||||||
|
return f;
|
||||||
|
|
||||||
|
// build up type for this instance of the closure func.
|
||||||
|
in = N;
|
||||||
|
d = nod(ODCLFIELD, N, N); // siz
|
||||||
|
d->type = types[TINT];
|
||||||
|
in = list(in, d);
|
||||||
|
d = nod(ODCLFIELD, N, N); // f
|
||||||
|
d->type = ft;
|
||||||
|
in = list(in, d);
|
||||||
|
for(a=listfirst(&save, &func->cvars); a; a=listnext(&save)) {
|
||||||
|
d = nod(ODCLFIELD, N, N); // arg
|
||||||
|
d->type = ptrto(a->type);
|
||||||
|
in = list(in, d);
|
||||||
|
}
|
||||||
|
in = rev(in);
|
||||||
|
|
||||||
|
d = nod(ODCLFIELD, N, N);
|
||||||
|
d->type = type;
|
||||||
|
out = d;
|
||||||
|
|
||||||
|
clos = syslook("closure", 1);
|
||||||
|
clos->type = functype(N, in, out);
|
||||||
|
|
||||||
|
// literal expression is sys.closure(siz, f, arg0, arg1, ...)
|
||||||
|
// which builds a function that calls f after filling in arg0,
|
||||||
|
// arg1, ... for the PHEAP arguments above.
|
||||||
|
args = N;
|
||||||
|
if(narg*8 > 100)
|
||||||
|
yyerror("closure needs too many variables; runtime will reject it");
|
||||||
|
a = nodintconst(narg*8);
|
||||||
|
args = list(args, a); // siz
|
||||||
|
args = list(args, f); // f
|
||||||
|
for(a=listfirst(&save, &func->cvars); a; a=listnext(&save)) {
|
||||||
|
d = oldname(a->sym);
|
||||||
|
addrescapes(d);
|
||||||
|
args = list(args, nod(OADDR, d, N));
|
||||||
|
}
|
||||||
|
args = rev(args);
|
||||||
|
|
||||||
|
return nod(OCALL, clos, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* turn a parsed struct into a type
|
* turn a parsed struct into a type
|
||||||
*/
|
*/
|
||||||
@ -657,28 +825,6 @@ markdcl(void)
|
|||||||
// print("markdcl\n");
|
// print("markdcl\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
markdclstack(void)
|
|
||||||
{
|
|
||||||
Sym *d, *s;
|
|
||||||
|
|
||||||
markdcl();
|
|
||||||
|
|
||||||
// copy the entire pop of the stack
|
|
||||||
// all the way back to block0.
|
|
||||||
// after this the symbol table is at
|
|
||||||
// block0 and popdcl will restore it.
|
|
||||||
for(d=dclstack; d!=S; d=d->link) {
|
|
||||||
if(d == b0stack)
|
|
||||||
break;
|
|
||||||
if(d->name != nil) {
|
|
||||||
s = pkglookup(d->name, d->package);
|
|
||||||
pushdcl(s);
|
|
||||||
dcopy(s, d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dumpdcl(char *st)
|
dumpdcl(char *st)
|
||||||
{
|
{
|
||||||
@ -755,6 +901,7 @@ addvar(Node *n, Type *t, int ctxt)
|
|||||||
s->offset = 0;
|
s->offset = 0;
|
||||||
s->lexical = LNAME;
|
s->lexical = LNAME;
|
||||||
|
|
||||||
|
n->funcdepth = funcdepth;
|
||||||
n->type = t;
|
n->type = t;
|
||||||
n->vargen = gen;
|
n->vargen = gen;
|
||||||
n->class = ctxt;
|
n->class = ctxt;
|
||||||
@ -909,6 +1056,7 @@ Node*
|
|||||||
oldname(Sym *s)
|
oldname(Sym *s)
|
||||||
{
|
{
|
||||||
Node *n;
|
Node *n;
|
||||||
|
Node *c;
|
||||||
|
|
||||||
n = s->oname;
|
n = s->oname;
|
||||||
if(n == N) {
|
if(n == N) {
|
||||||
@ -918,6 +1066,26 @@ oldname(Sym *s)
|
|||||||
n->addable = 1;
|
n->addable = 1;
|
||||||
n->ullman = 1;
|
n->ullman = 1;
|
||||||
}
|
}
|
||||||
|
if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
|
||||||
|
// inner func is referring to var
|
||||||
|
// in outer func.
|
||||||
|
if(n->closure == N || n->closure->funcdepth != funcdepth) {
|
||||||
|
// create new closure var.
|
||||||
|
c = nod(ONAME, N, N);
|
||||||
|
c->sym = s;
|
||||||
|
c->class = PPARAMREF;
|
||||||
|
c->type = n->type;
|
||||||
|
c->addable = 0;
|
||||||
|
c->ullman = 2;
|
||||||
|
c->funcdepth = funcdepth;
|
||||||
|
c->outer = n->closure;
|
||||||
|
n->closure = c;
|
||||||
|
c->closure = n;
|
||||||
|
funclit->cvars = list(c, funclit->cvars);
|
||||||
|
}
|
||||||
|
// return ref to closure var, not original
|
||||||
|
return n->closure;
|
||||||
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +187,7 @@ struct Node
|
|||||||
uchar colas; // OAS resulting from :=
|
uchar colas; // OAS resulting from :=
|
||||||
uchar diag; // already printed error about this
|
uchar diag; // already printed error about this
|
||||||
uchar noescape; // ONAME never move to heap
|
uchar noescape; // ONAME never move to heap
|
||||||
|
uchar funcdepth;
|
||||||
|
|
||||||
// most nodes
|
// most nodes
|
||||||
Node* left;
|
Node* left;
|
||||||
@ -209,6 +210,7 @@ struct Node
|
|||||||
Node* nname;
|
Node* nname;
|
||||||
Node* enter;
|
Node* enter;
|
||||||
Node* exit;
|
Node* exit;
|
||||||
|
Node* cvars; // closure params
|
||||||
|
|
||||||
// OLITERAL/OREGISTER
|
// OLITERAL/OREGISTER
|
||||||
Val val;
|
Val val;
|
||||||
@ -218,6 +220,10 @@ struct Node
|
|||||||
Node* stackparam; // OPARAM node referring to stack copy of param
|
Node* stackparam; // OPARAM node referring to stack copy of param
|
||||||
Node* alloc; // allocation call
|
Node* alloc; // allocation call
|
||||||
|
|
||||||
|
// ONAME closure param with PPARAMREF
|
||||||
|
Node* outer; // outer PPARAMREF in nested closure
|
||||||
|
Node* closure; // ONAME/PHEAP <-> ONAME/PPARAMREF
|
||||||
|
|
||||||
Sym* osym; // import
|
Sym* osym; // import
|
||||||
Sym* psym; // import
|
Sym* psym; // import
|
||||||
Sym* sym; // various
|
Sym* sym; // various
|
||||||
@ -414,6 +420,7 @@ enum
|
|||||||
PAUTO,
|
PAUTO,
|
||||||
PPARAM,
|
PPARAM,
|
||||||
PPARAMOUT,
|
PPARAMOUT,
|
||||||
|
PPARAMREF, // param passed by reference
|
||||||
PFUNC,
|
PFUNC,
|
||||||
|
|
||||||
PHEAP = 1<<7,
|
PHEAP = 1<<7,
|
||||||
@ -527,6 +534,10 @@ EXTERN int32 thunk;
|
|||||||
|
|
||||||
EXTERN int exporting;
|
EXTERN int exporting;
|
||||||
|
|
||||||
|
EXTERN int funcdepth;
|
||||||
|
|
||||||
|
EXTERN Node* funclit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* y.tab.c
|
* y.tab.c
|
||||||
*/
|
*/
|
||||||
@ -750,6 +761,9 @@ Node* embedded(Sym*);
|
|||||||
Node* variter(Node*, Type*, Node*);
|
Node* variter(Node*, Type*, Node*);
|
||||||
void constiter(Node*, Type*, Node*);
|
void constiter(Node*, Type*, Node*);
|
||||||
|
|
||||||
|
void funclit0(Type*);
|
||||||
|
Node* funclit1(Type*, Node*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* export.c
|
* export.c
|
||||||
*/
|
*/
|
||||||
|
@ -1245,33 +1245,15 @@ Bfntype:
|
|||||||
fnlitdcl:
|
fnlitdcl:
|
||||||
fntype
|
fntype
|
||||||
{
|
{
|
||||||
markdclstack(); // save dcl stack and revert to block0
|
markdcl();
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
funcargs($$);
|
funclit0($$);
|
||||||
}
|
}
|
||||||
|
|
||||||
fnliteral:
|
fnliteral:
|
||||||
fnlitdcl '{' ostmt_list '}'
|
fnlitdcl '{' ostmt_list '}'
|
||||||
{
|
{
|
||||||
popdcl();
|
$$ = funclit1($1, $3);
|
||||||
|
|
||||||
vargen++;
|
|
||||||
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);
|
|
||||||
|
|
||||||
$$ = newname(lookup(namebuf));
|
|
||||||
addvar($$, $1, PFUNC);
|
|
||||||
|
|
||||||
{
|
|
||||||
Node *n;
|
|
||||||
|
|
||||||
n = nod(ODCLFUNC, N, N);
|
|
||||||
n->nname = $$;
|
|
||||||
n->type = $1;
|
|
||||||
n->nbody = $3;
|
|
||||||
if(n->nbody == N)
|
|
||||||
n->nbody = nod(ORETURN, N, N);
|
|
||||||
compile(n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fnbody:
|
fnbody:
|
||||||
|
@ -880,6 +880,11 @@ Jconv(Fmt *fp)
|
|||||||
strncat(buf, buf1, sizeof(buf));
|
strncat(buf, buf1, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(n->xoffset != 0) {
|
||||||
|
snprint(buf1, sizeof(buf1), " x(%lld)", n->xoffset);
|
||||||
|
strncat(buf, buf1, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
if(n->class != 0) {
|
if(n->class != 0) {
|
||||||
snprint(buf1, sizeof(buf1), " class(%d)", n->class);
|
snprint(buf1, sizeof(buf1), " class(%d)", n->class);
|
||||||
strncat(buf, buf1, sizeof(buf));
|
strncat(buf, buf1, sizeof(buf));
|
||||||
@ -890,6 +895,12 @@ Jconv(Fmt *fp)
|
|||||||
strncat(buf, buf1, sizeof(buf));
|
strncat(buf, buf1, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(n->funcdepth != 0) {
|
||||||
|
snprint(buf1, sizeof(buf1), " f(%d)", n->funcdepth);
|
||||||
|
strncat(buf, buf1, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return fmtstrcpy(fp, buf);
|
return fmtstrcpy(fp, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2070,6 +2081,8 @@ ullmancalc(Node *n)
|
|||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
case ONAME:
|
case ONAME:
|
||||||
ul = 1;
|
ul = 1;
|
||||||
|
if(n->class == PPARAMREF || (n->class & PHEAP))
|
||||||
|
ul++;
|
||||||
goto out;
|
goto out;
|
||||||
case OCALL:
|
case OCALL:
|
||||||
case OCALLMETH:
|
case OCALLMETH:
|
||||||
|
@ -67,6 +67,8 @@ func arraysliced(old []any, lb int, hb int, width int) (ary []any);
|
|||||||
func arrayslices(old *any, nel int, lb int, hb int, width int) (ary []any);
|
func arrayslices(old *any, nel int, lb int, hb int, width int) (ary []any);
|
||||||
func arrays2d(old *any, nel int) (ary []any);
|
func arrays2d(old *any, nel int) (ary []any);
|
||||||
|
|
||||||
|
func closure(); // has args, but compiler fills in
|
||||||
|
|
||||||
// used by go programs
|
// used by go programs
|
||||||
|
|
||||||
func Breakpoint();
|
func Breakpoint();
|
||||||
|
@ -50,6 +50,7 @@ char *sysimport =
|
|||||||
"func sys.arraysliced (old []any, lb int, hb int, width int) (ary []any)\n"
|
"func sys.arraysliced (old []any, lb int, hb int, width int) (ary []any)\n"
|
||||||
"func sys.arrayslices (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
|
"func sys.arrayslices (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
|
||||||
"func sys.arrays2d (old *any, nel int) (ary []any)\n"
|
"func sys.arrays2d (old *any, nel int) (ary []any)\n"
|
||||||
|
"func sys.closure ()\n"
|
||||||
"func sys.Breakpoint ()\n"
|
"func sys.Breakpoint ()\n"
|
||||||
"func sys.Reflect (i interface { }) (? uint64, ? string, ? bool)\n"
|
"func sys.Reflect (i interface { }) (? uint64, ? string, ? bool)\n"
|
||||||
"func sys.Unreflect (? uint64, ? string, ? bool) (ret interface { })\n"
|
"func sys.Unreflect (? uint64, ? string, ? bool) (ret interface { })\n"
|
||||||
|
@ -294,7 +294,7 @@ loop:
|
|||||||
case ONAME:
|
case ONAME:
|
||||||
if(top == Etop)
|
if(top == Etop)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
if(!(n->class & PHEAP))
|
if(!(n->class & PHEAP) && n->class != PPARAMREF)
|
||||||
n->addable = 1;
|
n->addable = 1;
|
||||||
if(n->type == T) {
|
if(n->type == T) {
|
||||||
s = n->sym;
|
s = n->sym;
|
||||||
@ -2022,7 +2022,10 @@ loop:
|
|||||||
argtype(on, l->type); // any-1
|
argtype(on, l->type); // any-1
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(isptr[l->type->etype] || l->type->etype == TCHAN || l->type->etype == TMAP) {
|
if(isptr[l->type->etype]
|
||||||
|
|| l->type->etype == TCHAN
|
||||||
|
|| l->type->etype == TMAP
|
||||||
|
|| l->type->etype == TFUNC) {
|
||||||
on = syslook("printpointer", 1);
|
on = syslook("printpointer", 1);
|
||||||
argtype(on, l->type); // any-1
|
argtype(on, l->type); // any-1
|
||||||
break;
|
break;
|
||||||
@ -3668,22 +3671,22 @@ addrescapes(Node *n)
|
|||||||
case PPARAM:
|
case PPARAM:
|
||||||
if(debug['E'])
|
if(debug['E'])
|
||||||
print("%L %s %S escapes %p\n", n->lineno, pnames[n->class], n->sym, n);
|
print("%L %s %S escapes %p\n", n->lineno, pnames[n->class], n->sym, n);
|
||||||
n->class |= PHEAP;
|
|
||||||
n->addable = 0;
|
|
||||||
n->ullman = 2;
|
|
||||||
n->alloc = callnew(n->type);
|
|
||||||
|
|
||||||
// if func param, need separate temporary
|
// if func param, need separate temporary
|
||||||
// to hold heap pointer.
|
// to hold heap pointer.
|
||||||
if(n->class == PPARAM+PHEAP) {
|
if(n->class == PPARAM) {
|
||||||
// expression to refer to stack copy
|
// expression to refer to stack copy
|
||||||
n->stackparam = nod(OPARAM, n, N);
|
n->stackparam = nod(OPARAM, n, N);
|
||||||
n->stackparam->type = n->type;
|
n->stackparam->type = n->type;
|
||||||
n->stackparam->addable = 1;
|
n->stackparam->addable = 1;
|
||||||
n->stackparam->xoffset = n->xoffset;
|
n->stackparam->xoffset = n->xoffset;
|
||||||
n->xoffset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n->class |= PHEAP;
|
||||||
|
n->addable = 0;
|
||||||
|
n->ullman = 2;
|
||||||
|
n->alloc = callnew(n->type);
|
||||||
|
n->xoffset = 0;
|
||||||
|
|
||||||
// create stack variable to hold pointer to heap
|
// create stack variable to hold pointer to heap
|
||||||
n->heapaddr = nod(0, N, N);
|
n->heapaddr = nod(0, N, N);
|
||||||
tempname(n->heapaddr, ptrto(n->type));
|
tempname(n->heapaddr, ptrto(n->type));
|
||||||
@ -3721,9 +3724,7 @@ paramstoheap(Type **argin)
|
|||||||
|
|
||||||
nn = N;
|
nn = N;
|
||||||
for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
|
for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
|
||||||
if(t->sym == S)
|
v = t->nname;
|
||||||
continue;
|
|
||||||
v = t->sym->oname;
|
|
||||||
if(v == N || !(v->class & PHEAP))
|
if(v == N || !(v->class & PHEAP))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user