Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
0970c468
Commit
0970c468
authored
Feb 06, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
closures - 6g support
R=ken OCL=24501 CL=24566
parent
0f4f2a61
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
251 additions
and
61 deletions
+251
-61
cgen.c
src/cmd/6g/cgen.c
+12
-3
dcl.c
src/cmd/gc/dcl.c
+193
-25
go.h
src/cmd/gc/go.h
+14
-0
go.y
src/cmd/gc/go.y
+3
-21
subr.c
src/cmd/gc/subr.c
+13
-0
sys.go
src/cmd/gc/sys.go
+2
-0
sysimport.c
src/cmd/gc/sysimport.c
+1
-0
walk.c
src/cmd/gc/walk.c
+13
-12
No files found.
src/cmd/6g/cgen.c
View file @
0970c468
...
...
@@ -205,7 +205,7 @@ cgen(Node *n, Node *res)
case
ODOTPTR
:
case
OINDEX
:
case
OIND
:
case
ONAME
:
// PHEAP var
case
ONAME
:
// PHEAP
or PPARAMREF
var
igen
(
n
,
&
n1
,
res
);
gmove
(
&
n1
,
res
);
regfree
(
&
n1
);
...
...
@@ -526,9 +526,18 @@ agen(Node *n, Node *res)
break
;
case
ONAME
:
// should only get here for heap vars
if
(
!
(
n
->
class
&
PHEAP
))
// should only get here with names in this func.
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
);
}
cgen
(
n
->
heapaddr
,
res
);
if
(
n
->
xoffset
!=
0
)
{
nodconst
(
&
n1
,
types
[
TINT64
],
n
->
xoffset
);
...
...
src/cmd/gc/dcl.c
View file @
0970c468
...
...
@@ -402,13 +402,12 @@ funchdr(Node *n)
autodcl
=
dcl
();
autodcl
->
back
=
autodcl
;
if
(
dclcontext
!=
PEXTERN
)
if
(
funcdepth
==
0
&&
dclcontext
!=
PEXTERN
)
fatal
(
"funchdr: dclcontext"
);
dclcontext
=
PAUTO
;
markdcl
();
funcargs
(
n
->
type
);
}
void
...
...
@@ -418,6 +417,8 @@ funcargs(Type *ft)
Iter
save
;
int
all
;
funcdepth
++
;
// declare the this/in arguments
t
=
funcfirst
(
&
save
,
ft
);
while
(
t
!=
T
)
{
...
...
@@ -466,9 +467,176 @@ funcbody(Node *n)
if
(
dclcontext
!=
PAUTO
)
fatal
(
"funcbody: dclcontext"
);
popdcl
();
dclcontext
=
PEXTERN
;
funcdepth
--
;
if
(
funcdepth
==
0
)
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
*/
...
...
@@ -657,28 +825,6 @@ markdcl(void)
// 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
dumpdcl
(
char
*
st
)
{
...
...
@@ -755,6 +901,7 @@ addvar(Node *n, Type *t, int ctxt)
s
->
offset
=
0
;
s
->
lexical
=
LNAME
;
n
->
funcdepth
=
funcdepth
;
n
->
type
=
t
;
n
->
vargen
=
gen
;
n
->
class
=
ctxt
;
...
...
@@ -909,6 +1056,7 @@ Node*
oldname
(
Sym
*
s
)
{
Node
*
n
;
Node
*
c
;
n
=
s
->
oname
;
if
(
n
==
N
)
{
...
...
@@ -918,6 +1066,26 @@ oldname(Sym *s)
n
->
addable
=
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
;
}
...
...
src/cmd/gc/go.h
View file @
0970c468
...
...
@@ -187,6 +187,7 @@ struct Node
uchar
colas
;
// OAS resulting from :=
uchar
diag
;
// already printed error about this
uchar
noescape
;
// ONAME never move to heap
uchar
funcdepth
;
// most nodes
Node
*
left
;
...
...
@@ -209,6 +210,7 @@ struct Node
Node
*
nname
;
Node
*
enter
;
Node
*
exit
;
Node
*
cvars
;
// closure params
// OLITERAL/OREGISTER
Val
val
;
...
...
@@ -218,6 +220,10 @@ struct Node
Node
*
stackparam
;
// OPARAM node referring to stack copy of param
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
*
psym
;
// import
Sym
*
sym
;
// various
...
...
@@ -414,6 +420,7 @@ enum
PAUTO
,
PPARAM
,
PPARAMOUT
,
PPARAMREF
,
// param passed by reference
PFUNC
,
PHEAP
=
1
<<
7
,
...
...
@@ -527,6 +534,10 @@ EXTERN int32 thunk;
EXTERN
int
exporting
;
EXTERN
int
funcdepth
;
EXTERN
Node
*
funclit
;
/*
* y.tab.c
*/
...
...
@@ -750,6 +761,9 @@ Node* embedded(Sym*);
Node
*
variter
(
Node
*
,
Type
*
,
Node
*
);
void
constiter
(
Node
*
,
Type
*
,
Node
*
);
void
funclit0
(
Type
*
);
Node
*
funclit1
(
Type
*
,
Node
*
);
/*
* export.c
*/
...
...
src/cmd/gc/go.y
View file @
0970c468
...
...
@@ -1245,33 +1245,15 @@ Bfntype:
fnlitdcl
:
fntype
{
markdcl
stack
();
//
save
dcl
stack
and
revert
to
block0
markdcl
();
$$
=
$
1
;
func
args
($$);
func
lit0
($$);
}
fnliteral
:
fnlitdcl
'{'
ostmt_list
'}'
{
popdcl
();
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
);
}
$$
=
funclit1
($
1
,
$
3
);
}
fnbody
:
...
...
src/cmd/gc/subr.c
View file @
0970c468
...
...
@@ -880,6 +880,11 @@ Jconv(Fmt *fp)
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
)
{
snprint
(
buf1
,
sizeof
(
buf1
),
" class(%d)"
,
n
->
class
);
strncat
(
buf
,
buf1
,
sizeof
(
buf
));
...
...
@@ -890,6 +895,12 @@ Jconv(Fmt *fp)
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
);
}
...
...
@@ -2070,6 +2081,8 @@ ullmancalc(Node *n)
case
OLITERAL
:
case
ONAME
:
ul
=
1
;
if
(
n
->
class
==
PPARAMREF
||
(
n
->
class
&
PHEAP
))
ul
++
;
goto
out
;
case
OCALL
:
case
OCALLMETH
:
...
...
src/cmd/gc/sys.go
View file @
0970c468
...
...
@@ -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
arrays2d
(
old
*
any
,
nel
int
)
(
ary
[]
any
);
func
closure
();
// has args, but compiler fills in
// used by go programs
func
Breakpoint
();
...
...
src/cmd/gc/sysimport.c
View file @
0970c468
...
...
@@ -50,6 +50,7 @@ char *sysimport =
"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.arrays2d (old *any, nel int) (ary []any)
\n
"
"func sys.closure ()
\n
"
"func sys.Breakpoint ()
\n
"
"func sys.Reflect (i interface { }) (? uint64, ? string, ? bool)
\n
"
"func sys.Unreflect (? uint64, ? string, ? bool) (ret interface { })
\n
"
...
...
src/cmd/gc/walk.c
View file @
0970c468
...
...
@@ -294,7 +294,7 @@ loop:
case
ONAME
:
if
(
top
==
Etop
)
goto
nottop
;
if
(
!
(
n
->
class
&
PHEAP
))
if
(
!
(
n
->
class
&
PHEAP
)
&&
n
->
class
!=
PPARAMREF
)
n
->
addable
=
1
;
if
(
n
->
type
==
T
)
{
s
=
n
->
sym
;
...
...
@@ -2022,7 +2022,10 @@ loop:
argtype
(
on
,
l
->
type
);
// any-1
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
);
argtype
(
on
,
l
->
type
);
// any-1
break
;
...
...
@@ -3668,22 +3671,22 @@ addrescapes(Node *n)
case
PPARAM
:
if
(
debug
[
'E'
])
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
// to hold heap pointer.
if
(
n
->
class
==
PPARAM
+
PHEAP
)
{
if
(
n
->
class
==
PPARAM
)
{
// expression to refer to stack copy
n
->
stackparam
=
nod
(
OPARAM
,
n
,
N
);
n
->
stackparam
->
type
=
n
->
type
;
n
->
stackparam
->
addable
=
1
;
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
n
->
heapaddr
=
nod
(
0
,
N
,
N
);
tempname
(
n
->
heapaddr
,
ptrto
(
n
->
type
));
...
...
@@ -3721,9 +3724,7 @@ paramstoheap(Type **argin)
nn
=
N
;
for
(
t
=
structfirst
(
&
savet
,
argin
);
t
!=
T
;
t
=
structnext
(
&
savet
))
{
if
(
t
->
sym
==
S
)
continue
;
v
=
t
->
sym
->
oname
;
v
=
t
->
nname
;
if
(
v
==
N
||
!
(
v
->
class
&
PHEAP
))
continue
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment