Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
541e638f
Commit
541e638f
authored
Jul 07, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
6g, 8g: generate data structures for new reflect interface (CL 31107)
R=ken OCL=31122 CL=31278
parent
c7513eac
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
808 additions
and
506 deletions
+808
-506
src/cmd/6g/gobj.c
src/cmd/6g/gobj.c
+40
-0
src/cmd/8g/gobj.c
src/cmd/8g/gobj.c
+41
-0
src/cmd/gc/Makefile
src/cmd/gc/Makefile
+1
-0
src/cmd/gc/align.c
src/cmd/gc/align.c
+4
-0
src/cmd/gc/builtin.c.boot
src/cmd/gc/builtin.c.boot
+14
-13
src/cmd/gc/go.h
src/cmd/gc/go.h
+7
-4
src/cmd/gc/obj.c
src/cmd/gc/obj.c
+1
-412
src/cmd/gc/reflect.c
src/cmd/gc/reflect.c
+692
-0
src/cmd/gc/subr.c
src/cmd/gc/subr.c
+0
-58
src/cmd/gc/unsafe.go
src/cmd/gc/unsafe.go
+3
-3
src/cmd/gc/walk.c
src/cmd/gc/walk.c
+5
-16
No files found.
src/cmd/6g/gobj.c
View file @
541e638f
...
...
@@ -488,6 +488,46 @@ dstringptr(Sym *s, int off, char *str)
return
off
;
}
int
dgostrlitptr
(
Sym
*
s
,
int
off
,
Strlit
*
lit
)
{
Prog
*
p
;
if
(
lit
==
nil
)
return
duintptr
(
s
,
off
,
0
);
off
=
rnd
(
off
,
widthptr
);
p
=
gins
(
ADATA
,
N
,
N
);
p
->
from
.
type
=
D_EXTERN
;
p
->
from
.
index
=
D_NONE
;
p
->
from
.
sym
=
s
;
p
->
from
.
offset
=
off
;
p
->
from
.
scale
=
widthptr
;
datagostring
(
lit
,
&
p
->
to
);
p
->
to
.
index
=
p
->
to
.
type
;
p
->
to
.
type
=
D_ADDR
;
p
->
to
.
etype
=
TINT32
;
off
+=
widthptr
;
return
off
;
}
int
dgostringptr
(
Sym
*
s
,
int
off
,
char
*
str
)
{
int
n
;
Strlit
*
lit
;
if
(
str
==
nil
)
return
duintptr
(
s
,
off
,
0
);
n
=
strlen
(
str
);
lit
=
mal
(
sizeof
*
lit
+
n
);
strcpy
(
lit
->
s
,
str
);
lit
->
len
=
n
;
return
dgostrlitptr
(
s
,
off
,
lit
);
}
int
duintxx
(
Sym
*
s
,
int
off
,
uint64
v
,
int
wid
)
{
...
...
src/cmd/8g/gobj.c
View file @
541e638f
...
...
@@ -486,6 +486,47 @@ dstringptr(Sym *s, int off, char *str)
return
off
;
}
int
dgostrlitptr
(
Sym
*
s
,
int
off
,
Strlit
*
lit
)
{
Prog
*
p
;
if
(
lit
==
nil
)
return
duintptr
(
s
,
off
,
0
);
off
=
rnd
(
off
,
widthptr
);
p
=
gins
(
ADATA
,
N
,
N
);
p
->
from
.
type
=
D_EXTERN
;
p
->
from
.
index
=
D_NONE
;
p
->
from
.
sym
=
s
;
p
->
from
.
offset
=
off
;
p
->
from
.
scale
=
widthptr
;
datagostring
(
lit
,
&
p
->
to
);
p
->
to
.
index
=
p
->
to
.
type
;
p
->
to
.
type
=
D_ADDR
;
p
->
to
.
etype
=
TINT32
;
off
+=
widthptr
;
return
off
;
}
int
dgostringptr
(
Sym
*
s
,
int
off
,
char
*
str
)
{
int
n
;
Strlit
*
lit
;
if
(
str
==
nil
)
return
duintptr
(
s
,
off
,
0
);
n
=
strlen
(
str
);
lit
=
mal
(
sizeof
*
lit
+
n
);
strcpy
(
lit
->
s
,
str
);
lit
->
len
=
n
;
return
dgostrlitptr
(
s
,
off
,
lit
);
}
int
duintxx
(
Sym
*
s
,
int
off
,
uint64
v
,
int
wid
)
{
...
...
src/cmd/gc/Makefile
View file @
541e638f
...
...
@@ -15,6 +15,7 @@ YFILES=\
go.y
\
OFILES
=
\
reflect.
$O
\
y.tab.
$O
\
lex.
$O
\
subr.
$O
\
...
...
src/cmd/gc/align.c
View file @
541e638f
...
...
@@ -243,6 +243,10 @@ typeinit(void)
isptr
[
TPTR32
]
=
1
;
isptr
[
TPTR64
]
=
1
;
isforw
[
TFORW
]
=
1
;
isforw
[
TFORWSTRUCT
]
=
1
;
isforw
[
TFORWINTER
]
=
1
;
issigned
[
TINT
]
=
1
;
issigned
[
TINT8
]
=
1
;
issigned
[
TINT16
]
=
1
;
...
...
src/cmd/gc/builtin.c.boot
View file @
541e638f
...
...
@@ -26,17 +26,17 @@ char *sysimport =
"func sys.stringiter (? string, ? int) (? int)\n"
"func sys.stringiter2 (? string, ? int) (retk int, retv int)\n"
"func sys.ifaceI2E (iface any) (ret any)\n"
"func sys.ifaceE2I (
sigi
*uint8, iface any) (ret any)\n"
"func sys.ifaceT2E (
sigt
*uint8, elem any) (ret any)\n"
"func sys.ifaceE2T (
sigt
*uint8, elem any) (ret any)\n"
"func sys.ifaceE2I2 (
sigi
*uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceE2T2 (
sigt
*uint8, elem any) (ret any, ok bool)\n"
"func sys.ifaceT2I (
sigi *uint8, sigt
*uint8, elem any) (ret any)\n"
"func sys.ifaceI2T (
sigt
*uint8, iface any) (ret any)\n"
"func sys.ifaceI2T2 (
sigt
*uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceI2I (
sigi
*uint8, iface any) (ret any)\n"
"func sys.ifaceI2Ix (
sigi
*uint8, iface any) (ret any)\n"
"func sys.ifaceI2I2 (
sigi
*uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceE2I (
typ
*uint8, iface any) (ret any)\n"
"func sys.ifaceT2E (
typ
*uint8, elem any) (ret any)\n"
"func sys.ifaceE2T (
typ
*uint8, elem any) (ret any)\n"
"func sys.ifaceE2I2 (
typ
*uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceE2T2 (
typ
*uint8, elem any) (ret any, ok bool)\n"
"func sys.ifaceT2I (
typ1 *uint8, typ2
*uint8, elem any) (ret any)\n"
"func sys.ifaceI2T (
typ
*uint8, iface any) (ret any)\n"
"func sys.ifaceI2T2 (
typ
*uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceI2I (
typ
*uint8, iface any) (ret any)\n"
"func sys.ifaceI2Ix (
typ
*uint8, iface any) (ret any)\n"
"func sys.ifaceI2I2 (
typ
*uint8, iface any) (ret any, ok bool)\n"
"func sys.ifaceeq (i1 any, i2 any) (ret bool)\n"
"func sys.efaceeq (i1 any, i2 any) (ret bool)\n"
"func sys.ifacethash (i1 any) (ret uint32)\n"
...
...
@@ -80,7 +80,8 @@ char *unsafeimport =
"func unsafe.Offsetof (? any) (? int)\n"
"func unsafe.Sizeof (? any) (? int)\n"
"func unsafe.Alignof (? any) (? int)\n"
"func unsafe.Reflect (i interface { }) (? uint64, ? string, ? bool)\n"
"func unsafe.Unreflect (? uint64, ? string, ? bool) (ret interface { })\n"
"func unsafe.Typeof (i interface { }) (typ interface { })\n"
"func unsafe.Reflect (i interface { }) (typ interface { }, addr unsafe.Pointer)\n"
"func unsafe.Unreflect (typ interface { }, addr unsafe.Pointer) (ret interface { })\n"
"\n"
"$$\n";
src/cmd/gc/go.h
View file @
541e638f
...
...
@@ -391,6 +391,7 @@ enum
enum
{
/* types of channel */
/* must match ../../pkg/nreflect/type.go:/Chandir */
Cxxx
,
Crecv
=
1
<<
0
,
Csend
=
1
<<
1
,
...
...
@@ -457,7 +458,10 @@ typedef struct Sig Sig;
struct
Sig
{
char
*
name
;
Sym
*
sym
;
char
*
package
;
Sym
*
isym
;
Sym
*
tsym
;
Type
*
type
;
uint32
hash
;
int32
perm
;
int32
offset
;
...
...
@@ -736,7 +740,7 @@ int isnilinter(Type*);
int
isddd
(
Type
*
);
Type
*
maptype
(
Type
*
,
Type
*
);
Type
*
methtype
(
Type
*
);
Node
*
sig
name
(
Type
*
);
Node
*
type
name
(
Type
*
);
int
eqtype
(
Type
*
,
Type
*
);
int
cvttype
(
Type
*
,
Type
*
);
int
eqtypenoname
(
Type
*
,
Type
*
);
...
...
@@ -782,7 +786,6 @@ Type* funcnext(Iter*);
int
brcom
(
int
);
int
brrev
(
int
);
void
setmaxarg
(
Type
*
);
Sig
*
lsort
(
Sig
*
,
int
(
*
)(
Sig
*
,
Sig
*
));
int
dotoffset
(
Node
*
,
int
*
,
Node
**
);
void
tempname
(
Node
*
,
Type
*
);
...
...
@@ -1073,7 +1076,7 @@ int isfat(Type*);
void
clearfat
(
Node
*
n
);
void
cgen
(
Node
*
,
Node
*
);
void
gused
(
Node
*
);
void
dump
signature
s
(
void
);
void
dump
typestruct
s
(
void
);
void
dumpfuncs
(
void
);
void
dumpdata
(
void
);
void
ggloblnod
(
Node
*
nam
,
int32
width
);
...
...
src/cmd/gc/obj.c
View file @
541e638f
...
...
@@ -28,7 +28,7 @@ dumpobj(void)
newplist
();
dumpglobls
();
dump
signature
s
();
dump
typestruct
s
();
dumpdata
();
dumpfuncs
();
...
...
@@ -169,414 +169,3 @@ duintptr(Sym *s, int off, uint64 v)
{
return
duintxx
(
s
,
off
,
v
,
widthptr
);
}
static
int
sigcmp
(
Sig
*
a
,
Sig
*
b
)
{
return
strcmp
(
a
->
name
,
b
->
name
);
}
/*
* Add DATA for signature s.
* progt - type in program
* ifacet - type stored in interface (==progt if small, ==ptrto(progt) if large)
* rcvrt - type used as method interface. eqtype(ifacet, rcvrt) is always true,
* but ifacet might have a name that rcvrt does not.
* methodt - type with methods hanging off it (progt==*methodt sometimes)
*
* memory layout is Sigt struct from iface.c:
* struct Sigt
* {
* byte* name; // name of basic type
* Sigt* link; // for linking into hash tables
* uint32 thash; // hash of type
* uint32 mhash; // hash of methods
* uint16 width; // width of base type in bytes
* uint16 alg; // algorithm
* struct {
* byte* fname;
* uint32 fhash; // hash of type
* uint32 offset; // offset of substruct
* void (*fun)(void);
* } meth[1]; // one or more - last name is nil
* };
*/
void
dumpsigt
(
Type
*
progt
,
Type
*
ifacet
,
Type
*
rcvrt
,
Type
*
methodt
,
Sym
*
s
)
{
Type
*
f
;
int
o
;
Sig
*
a
,
*
b
;
char
buf
[
NSYMB
];
Type
*
this
;
Prog
*
oldlist
;
Sym
*
method
;
uint32
sighash
;
int
ot
;
if
(
debug
[
'r'
])
{
print
(
"dumpsigt progt=%T ifacet=%T rcvrt=%T methodt=%T s=%S
\n
"
,
progt
,
ifacet
,
rcvrt
,
methodt
,
s
);
}
a
=
nil
;
o
=
0
;
oldlist
=
nil
;
sighash
=
typehash
(
progt
,
1
,
0
);
for
(
f
=
methodt
->
method
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
type
->
etype
!=
TFUNC
)
continue
;
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"dumpsignatures: not field"
);
method
=
f
->
sym
;
if
(
method
==
nil
)
continue
;
// get receiver type for this particular method.
this
=
getthisx
(
f
->
type
)
->
type
->
type
;
if
(
f
->
embedded
!=
2
&&
isptr
[
this
->
etype
]
&&
!
isptr
[
progt
->
etype
]
&&
!
isifacemethod
(
f
))
{
// pointer receiver method but value method set.
// ignore.
if
(
debug
[
'r'
])
print
(
"ignore %T for %T
\n
"
,
f
,
progt
);
continue
;
}
b
=
mal
(
sizeof
(
*
b
));
b
->
link
=
a
;
a
=
b
;
a
->
name
=
method
->
name
;
a
->
hash
=
PRIME8
*
stringhash
(
a
->
name
)
+
PRIME9
*
typehash
(
f
->
type
,
0
,
0
);
if
(
!
exportname
(
a
->
name
))
a
->
hash
+=
PRIME10
*
stringhash
(
package
);
a
->
perm
=
o
;
a
->
sym
=
methodsym
(
method
,
rcvrt
);
sighash
=
sighash
*
100003
+
a
->
hash
;
if
(
!
a
->
sym
->
siggen
)
{
a
->
sym
->
siggen
=
1
;
if
(
!
eqtype
(
this
,
ifacet
))
{
if
(
oldlist
==
nil
)
oldlist
=
pc
;
// It would be okay to call genwrapper here always,
// but we can generate more efficient code
// using genembedtramp if all that is necessary
// is a pointer adjustment and a JMP.
if
(
f
->
embedded
&&
isptr
[
ifacet
->
etype
]
&&
!
isifacemethod
(
f
))
genembedtramp
(
ifacet
,
f
,
a
->
sym
);
else
genwrapper
(
ifacet
,
f
,
a
->
sym
);
}
}
o
++
;
}
// restore data output
if
(
oldlist
)
{
// old list ended with AEND; change to ANOP
// so that the trampolines that follow can be found.
nopout
(
oldlist
);
// start new data list
newplist
();
}
a
=
lsort
(
a
,
sigcmp
);
ot
=
0
;
ot
=
rnd
(
ot
,
maxround
);
// base structure
// base of type signature contains parameters
snprint
(
buf
,
sizeof
buf
,
"%#T"
,
progt
);
ot
=
dstringptr
(
s
,
ot
,
buf
);
// name
ot
=
duintptr
(
s
,
ot
,
0
);
// skip link
ot
=
duint32
(
s
,
ot
,
typehash
(
progt
,
1
,
0
));
// thash
ot
=
duint32
(
s
,
ot
,
sighash
);
// mhash
ot
=
duint16
(
s
,
ot
,
progt
->
width
);
// width
ot
=
duint16
(
s
,
ot
,
algtype
(
progt
));
// algorithm
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
{
ot
=
rnd
(
ot
,
maxround
);
// base of substructure
ot
=
dstringptr
(
s
,
ot
,
b
->
name
);
// field name
ot
=
duint32
(
s
,
ot
,
b
->
hash
);
// hash
ot
=
duint32
(
s
,
ot
,
0
);
// offset
ot
=
dsymptr
(
s
,
ot
,
b
->
sym
,
0
);
// &method
}
// nil field name at end
ot
=
rnd
(
ot
,
maxround
);
ot
=
duintptr
(
s
,
ot
,
0
);
// set DUPOK to allow other .6s to contain
// the same signature. only one will be chosen.
// should only happen for empty signatures
ggloblsym
(
s
,
ot
,
a
==
nil
);
}
/*
* memory layout is Sigi struct from iface.c:
* struct Sigi
* {
* byte* name;
* uint32 hash;
* uint32 size; // number of methods
* struct {
* byte* fname;
* uint32 fhash;
* uint32 perm; // location of fun in Sigt
* } meth[1]; // [size+1] - last name is nil
* };
*/
void
dumpsigi
(
Type
*
t
,
Sym
*
s
)
{
Type
*
f
;
Sym
*
s1
;
int
o
;
Sig
*
a
,
*
b
;
char
buf
[
NSYMB
];
uint32
sighash
;
int
ot
;
a
=
nil
;
o
=
0
;
sighash
=
0
;
for
(
f
=
t
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
type
->
etype
!=
TFUNC
)
continue
;
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"dumpsignatures: not field"
);
s1
=
f
->
sym
;
if
(
s1
==
nil
)
continue
;
b
=
mal
(
sizeof
(
*
b
));
b
->
link
=
a
;
a
=
b
;
a
->
name
=
s1
->
name
;
a
->
hash
=
PRIME8
*
stringhash
(
a
->
name
)
+
PRIME9
*
typehash
(
f
->
type
,
0
,
0
);
if
(
!
exportname
(
a
->
name
))
a
->
hash
+=
PRIME10
*
stringhash
(
package
);
a
->
perm
=
o
;
a
->
sym
=
methodsym
(
f
->
sym
,
t
);
a
->
offset
=
0
;
sighash
=
sighash
*
100003
+
a
->
hash
;
o
++
;
}
a
=
lsort
(
a
,
sigcmp
);
ot
=
0
;
ot
=
rnd
(
ot
,
maxround
);
// base structure
// sigi[0].name = type name, for runtime error message
snprint
(
buf
,
sizeof
buf
,
"%#T"
,
t
);
ot
=
dstringptr
(
s
,
ot
,
buf
);
// first field of an interface signature
// contains the count and is not a real entry
// sigi[0].hash = sighash
ot
=
duint32
(
s
,
ot
,
sighash
);
// sigi[0].offset = count
o
=
0
;
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
o
++
;
ot
=
duint32
(
s
,
ot
,
o
);
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
{
//print(" %s\n", b->name);
ot
=
rnd
(
ot
,
maxround
);
// base structure
// sigx[++].name = "fieldname"
// sigx[++].hash = hashcode
// sigi[++].perm = mapped offset of method
ot
=
dstringptr
(
s
,
ot
,
b
->
name
);
ot
=
duint32
(
s
,
ot
,
b
->
hash
);
ot
=
duint32
(
s
,
ot
,
b
->
perm
);
}
// nil field name at end
ot
=
rnd
(
ot
,
maxround
);
ot
=
duintptr
(
s
,
ot
,
0
);
// TODO(rsc): DUPOK should not be necessary here,
// and I am a bit worried that it is. If I turn it off,
// I get multiple definitions for sigi.dotdotdot.
ggloblsym
(
s
,
ot
,
1
);
}
void
dumpsignatures
(
void
)
{
int
et
;
Dcl
*
d
,
*
x
;
Type
*
t
,
*
progt
,
*
methodt
,
*
ifacet
,
*
rcvrt
;
Sym
*
s
;
Node
*
n
;
// copy externdcl list to signatlist
for
(
d
=
externdcl
;
d
!=
D
;
d
=
d
->
forw
)
{
if
(
d
->
op
!=
OTYPE
)
continue
;
t
=
d
->
dtype
;
if
(
t
==
T
)
continue
;
n
=
signame
(
t
);
if
(
n
==
N
||
n
->
sym
==
S
)
continue
;
s
=
n
->
sym
;
x
=
mal
(
sizeof
(
*
d
));
x
->
op
=
OTYPE
;
if
(
t
->
etype
==
TINTER
)
x
->
dtype
=
t
;
else
x
->
dtype
=
ptrto
(
t
);
x
->
forw
=
signatlist
;
x
->
block
=
0
;
signatlist
=
x
;
//print("SIG = %lS %lS %lT\n", d->dsym, s, t);
}
// process signatlist
for
(
d
=
signatlist
;
d
!=
D
;
d
=
d
->
forw
)
{
if
(
d
->
op
!=
OTYPE
)
continue
;
t
=
d
->
dtype
;
et
=
t
->
etype
;
n
=
signame
(
t
);
//print("signame %S for %T\n", s, t);
if
(
n
==
N
||
n
->
sym
==
S
)
continue
;
s
=
n
->
sym
;
// only emit one
if
(
s
->
siggen
)
continue
;
s
->
siggen
=
1
;
// interface is easy
if
(
et
==
TINTER
||
et
==
TDDD
)
{
if
(
t
->
sym
&&
!
t
->
local
)
continue
;
dumpsigi
(
t
,
s
);
continue
;
}
// non-interface is more complex
progt
=
t
;
methodt
=
t
;
ifacet
=
t
;
rcvrt
=
t
;
// if there's a pointer, methods are on base.
methodt
=
methtype
(
progt
);
if
(
methodt
==
T
)
{
// if that failed, go back to progt,
// assuming we're writing out a signature
// for a type with no methods
methodt
=
progt
;
}
else
{
expandmeth
(
methodt
->
sym
,
methodt
);
}
// if ifacet is too wide, the methods will see a pointer.
if
(
ifacet
->
width
>
widthptr
)
{
ifacet
=
ptrto
(
progt
);
rcvrt
=
ptrto
(
progt
);
}
// don't emit non-trivial signatures for types defined outside this file.
// non-trivial signatures might also drag in generated trampolines,
// and ar can't handle duplicate functions.
// only pay attention to types with symbols, because
// the ... structs and maybe other internal structs
// don't get marked as local.
if
(
methodt
->
method
&&
methodt
->
sym
&&
!
methodt
->
local
)
continue
;
//print("s=%S\n", s);
dumpsigt
(
progt
,
ifacet
,
rcvrt
,
methodt
,
s
);
}
}
Sig
*
lsort
(
Sig
*
l
,
int
(
*
f
)(
Sig
*
,
Sig
*
))
{
Sig
*
l1
,
*
l2
,
*
le
;
if
(
l
==
0
||
l
->
link
==
0
)
return
l
;
l1
=
l
;
l2
=
l
;
for
(;;)
{
l2
=
l2
->
link
;
if
(
l2
==
0
)
break
;
l2
=
l2
->
link
;
if
(
l2
==
0
)
break
;
l1
=
l1
->
link
;
}
l2
=
l1
->
link
;
l1
->
link
=
0
;
l1
=
lsort
(
l
,
f
);
l2
=
lsort
(
l2
,
f
);
/* set up lead element */
if
((
*
f
)(
l1
,
l2
)
<
0
)
{
l
=
l1
;
l1
=
l1
->
link
;
}
else
{
l
=
l2
;
l2
=
l2
->
link
;
}
le
=
l
;
for
(;;)
{
if
(
l1
==
0
)
{
while
(
l2
)
{
le
->
link
=
l2
;
le
=
l2
;
l2
=
l2
->
link
;
}
le
->
link
=
0
;
break
;
}
if
(
l2
==
0
)
{
while
(
l1
)
{
le
->
link
=
l1
;
le
=
l1
;
l1
=
l1
->
link
;
}
break
;
}
if
((
*
f
)(
l1
,
l2
)
<
0
)
{
le
->
link
=
l1
;
le
=
l1
;
l1
=
l1
->
link
;
}
else
{
le
->
link
=
l2
;
le
=
l2
;
l2
=
l2
->
link
;
}
}
le
->
link
=
0
;
return
l
;
}
src/cmd/gc/reflect.c
0 → 100644
View file @
541e638f
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go.h"
/*
* runtime interface and reflection data structures
*/
static
Sym
*
dtypesym
(
Type
*
);
static
int
sigcmp
(
Sig
*
a
,
Sig
*
b
)
{
return
strcmp
(
a
->
name
,
b
->
name
);
}
static
Sig
*
lsort
(
Sig
*
l
,
int
(
*
f
)(
Sig
*
,
Sig
*
))
{
Sig
*
l1
,
*
l2
,
*
le
;
if
(
l
==
0
||
l
->
link
==
0
)
return
l
;
l1
=
l
;
l2
=
l
;
for
(;;)
{
l2
=
l2
->
link
;
if
(
l2
==
0
)
break
;
l2
=
l2
->
link
;
if
(
l2
==
0
)
break
;
l1
=
l1
->
link
;
}
l2
=
l1
->
link
;
l1
->
link
=
0
;
l1
=
lsort
(
l
,
f
);
l2
=
lsort
(
l2
,
f
);
/* set up lead element */
if
((
*
f
)(
l1
,
l2
)
<
0
)
{
l
=
l1
;
l1
=
l1
->
link
;
}
else
{
l
=
l2
;
l2
=
l2
->
link
;
}
le
=
l
;
for
(;;)
{
if
(
l1
==
0
)
{
while
(
l2
)
{
le
->
link
=
l2
;
le
=
l2
;
l2
=
l2
->
link
;
}
le
->
link
=
0
;
break
;
}
if
(
l2
==
0
)
{
while
(
l1
)
{
le
->
link
=
l1
;
le
=
l1
;
l1
=
l1
->
link
;
}
break
;
}
if
((
*
f
)(
l1
,
l2
)
<
0
)
{
le
->
link
=
l1
;
le
=
l1
;
l1
=
l1
->
link
;
}
else
{
le
->
link
=
l2
;
le
=
l2
;
l2
=
l2
->
link
;
}
}
le
->
link
=
0
;
return
l
;
}
/*
* f is method type, with receiver.
* return function type, receiver as first argument.
*/
static
Type
*
methodfunc
(
Type
*
f
)
{
Node
*
in
,
*
out
,
*
d
;
Type
*
t
;
in
=
N
;
if
(
!
isifacemethod
(
f
))
{
d
=
nod
(
ODCLFIELD
,
N
,
N
);
d
->
type
=
getthisx
(
f
->
type
)
->
type
->
type
;
in
=
list
(
in
,
d
);
}
for
(
t
=
getinargx
(
f
->
type
)
->
type
;
t
;
t
=
t
->
down
)
{
d
=
nod
(
ODCLFIELD
,
N
,
N
);
d
->
type
=
t
->
type
;
in
=
list
(
in
,
d
);
}
out
=
N
;
for
(
t
=
getoutargx
(
f
->
type
)
->
type
;
t
;
t
=
t
->
down
)
{
d
=
nod
(
ODCLFIELD
,
N
,
N
);
d
->
type
=
t
->
type
;
out
=
list
(
out
,
d
);
}
return
functype
(
N
,
rev
(
in
),
rev
(
out
));
}
/*
* return methods of non-interface type t,
* sorted by hash.
* generates stub functions as needed.
*/
static
Sig
*
methods
(
Type
*
t
)
{
int
o
;
Type
*
f
,
*
mt
,
*
it
,
*
this
;
Sig
*
a
,
*
b
;
Sym
*
method
;
Prog
*
oldlist
;
// named method type
mt
=
methtype
(
t
);
if
(
mt
==
T
)
return
nil
;
expandmeth
(
mt
->
sym
,
mt
);
// type stored in interface word
it
=
t
;
if
(
it
->
width
>
widthptr
)
it
=
ptrto
(
t
);
// make list of methods for t,
// generating code if necessary.
a
=
nil
;
o
=
0
;
oldlist
=
nil
;
for
(
f
=
mt
->
method
;
f
;
f
=
f
->
down
)
{
if
(
f
->
type
->
etype
!=
TFUNC
)
continue
;
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"methods: not field"
);
method
=
f
->
sym
;
if
(
method
==
nil
)
continue
;
// get receiver type for this particular method.
// if pointer receiver but non-pointer t and
// this is not an embedded pointer inside a struct,
// method does not apply.
this
=
getthisx
(
f
->
type
)
->
type
->
type
;
if
(
isptr
[
this
->
etype
]
&&
!
isptr
[
t
->
etype
]
&&
f
->
embedded
!=
2
&&
!
isifacemethod
(
f
))
continue
;
b
=
mal
(
sizeof
(
*
b
));
b
->
link
=
a
;
a
=
b
;
a
->
name
=
method
->
name
;
a
->
hash
=
PRIME8
*
stringhash
(
a
->
name
)
+
PRIME9
*
typehash
(
f
->
type
,
0
,
0
);
if
(
!
exportname
(
a
->
name
))
{
a
->
package
=
method
->
package
;
a
->
hash
+=
PRIME10
*
stringhash
(
a
->
package
);
}
a
->
perm
=
o
++
;
a
->
isym
=
methodsym
(
method
,
it
);
a
->
tsym
=
methodsym
(
method
,
t
);
a
->
type
=
methodfunc
(
f
);
if
(
!
a
->
isym
->
siggen
)
{
a
->
isym
->
siggen
=
1
;
if
(
!
eqtype
(
this
,
it
))
{
if
(
oldlist
==
nil
)
oldlist
=
pc
;
// Is okay to call genwrapper here always,
// but we can generate more efficient code
// using genembedtramp if all that is necessary
// is a pointer adjustment and a JMP.
if
(
isptr
[
it
->
etype
]
&&
isptr
[
this
->
etype
]
&&
f
->
embedded
&&
!
isifacemethod
(
f
))
genembedtramp
(
it
,
f
,
a
->
isym
);
else
genwrapper
(
it
,
f
,
a
->
isym
);
}
}
if
(
!
a
->
tsym
->
siggen
)
{
a
->
tsym
->
siggen
=
1
;
if
(
!
eqtype
(
this
,
t
))
{
if
(
oldlist
==
nil
)
oldlist
=
pc
;
if
(
isptr
[
it
->
etype
]
&&
isptr
[
this
->
etype
]
&&
f
->
embedded
&&
!
isifacemethod
(
f
))
genembedtramp
(
t
,
f
,
a
->
tsym
);
else
genwrapper
(
t
,
f
,
a
->
tsym
);
}
}
}
// restore data output
if
(
oldlist
)
{
// old list ended with AEND; change to ANOP
// so that the trampolines that follow can be found.
nopout
(
oldlist
);
// start new data list
newplist
();
}
return
lsort
(
a
,
sigcmp
);
}
/*
* return methods of interface type t, sorted by hash.
*/
Sig
*
imethods
(
Type
*
t
)
{
Sig
*
a
,
*
b
;
int
o
;
Type
*
f
;
a
=
nil
;
o
=
0
;
for
(
f
=
t
->
type
;
f
;
f
=
f
->
down
)
{
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"imethods: not field"
);
if
(
f
->
type
->
etype
!=
TFUNC
||
f
->
sym
==
nil
)
continue
;
b
=
mal
(
sizeof
(
*
b
));
b
->
link
=
a
;
a
=
b
;
a
->
name
=
f
->
sym
->
name
;
a
->
hash
=
PRIME8
*
stringhash
(
a
->
name
)
+
PRIME9
*
typehash
(
f
->
type
,
0
,
0
);
if
(
!
exportname
(
a
->
name
))
{
a
->
package
=
f
->
sym
->
package
;
a
->
hash
+=
PRIME10
*
stringhash
(
a
->
package
);
}
a
->
perm
=
o
++
;
a
->
offset
=
0
;
a
->
type
=
methodfunc
(
f
);
}
return
lsort
(
a
,
sigcmp
);
}
/*
* uncommonType
* ../../pkg/runtime/type.go:/uncommonType
*/
static
Sym
*
dextratype
(
Type
*
t
)
{
int
ot
,
n
;
char
*
p
;
Sym
*
s
;
Sig
*
a
,
*
m
;
m
=
methods
(
t
);
if
(
t
->
sym
==
nil
&&
m
==
nil
)
return
nil
;
n
=
0
;
for
(
a
=
m
;
a
;
a
=
a
->
link
)
{
dtypesym
(
a
->
type
);
n
++
;
}
p
=
smprint
(
"%#-T"
,
t
);
s
=
pkglookup
(
p
,
"extratype"
);
ot
=
0
;
if
(
t
->
sym
)
{
ot
=
dgostringptr
(
s
,
ot
,
t
->
sym
->
name
);
if
(
t
!=
types
[
t
->
etype
])
ot
=
dgostringptr
(
s
,
ot
,
t
->
sym
->
package
);
else
ot
=
dgostringptr
(
s
,
ot
,
nil
);
}
else
{
ot
=
dgostringptr
(
s
,
ot
,
nil
);
ot
=
dgostringptr
(
s
,
ot
,
nil
);
}
// slice header
ot
=
dsymptr
(
s
,
ot
,
s
,
ot
+
widthptr
+
2
*
4
);
ot
=
duint32
(
s
,
ot
,
n
);
ot
=
duint32
(
s
,
ot
,
n
);
// methods
for
(
a
=
m
;
a
;
a
=
a
->
link
)
{
// method
// ../../pkg/runtime/type.go:/method
ot
=
duint32
(
s
,
ot
,
a
->
hash
);
ot
=
rnd
(
ot
,
widthptr
);
ot
=
dgostringptr
(
s
,
ot
,
a
->
name
);
ot
=
dgostringptr
(
s
,
ot
,
a
->
package
);
ot
=
dsymptr
(
s
,
ot
,
dtypesym
(
a
->
type
),
0
);
if
(
a
->
isym
)
ot
=
dsymptr
(
s
,
ot
,
a
->
isym
,
0
);
else
ot
=
duintptr
(
s
,
ot
,
0
);
if
(
a
->
tsym
)
ot
=
dsymptr
(
s
,
ot
,
a
->
tsym
,
0
);
else
ot
=
duintptr
(
s
,
ot
,
0
);
}
ggloblsym
(
s
,
ot
,
1
);
return
s
;
}
static
char
*
structnames
[]
=
{
[
TINT
]
=
"*runtime.IntType"
,
[
TUINT
]
=
"*runtime.UintType"
,
[
TINT8
]
=
"*runtime.Int8Type"
,
[
TUINT8
]
=
"*runtime.Uint8Type"
,
[
TINT16
]
=
"*runtime.Int16Type"
,
[
TUINT16
]
=
"*runtime.Uint16Type"
,
[
TINT32
]
=
"*runtime.Int32Type"
,
[
TUINT32
]
=
"*runtime.Uint32Type"
,
[
TINT64
]
=
"*runtime.Int64Type"
,
[
TUINT64
]
=
"*runtime.Uint64Type"
,
[
TUINTPTR
]
=
"*runtime.UintptrType"
,
[
TFLOAT
]
=
"*runtime.FloatType"
,
[
TFLOAT32
]
=
"*runtime.Float32Type"
,
[
TFLOAT64
]
=
"*runtime.Float64Type"
,
[
TBOOL
]
=
"*runtime.BoolType"
,
[
TSTRING
]
=
"*runtime.StringType"
,
[
TDDD
]
=
"*runtime.DotDotDotType"
,
[
TPTR32
]
=
"*runtime.PtrType"
,
[
TPTR64
]
=
"*runtime.PtrType"
,
[
TSTRUCT
]
=
"*runtime.StructType"
,
[
TINTER
]
=
"*runtime.InterfaceType"
,
[
TCHAN
]
=
"*runtime.ChanType"
,
[
TMAP
]
=
"*runtime.MapType"
,
[
TARRAY
]
=
"*runtime.ArrayType"
,
[
TFUNC
]
=
"*runtime.FuncType"
,
};
static
Sym
*
typestruct
(
Type
*
t
)
{
char
*
name
;
int
et
;
et
=
t
->
etype
;
if
(
et
<
0
||
et
>=
nelem
(
structnames
)
||
(
name
=
structnames
[
et
])
==
nil
)
{
fatal
(
"typestruct %lT"
,
t
);
return
nil
;
// silence gcc
}
if
(
isslice
(
t
))
name
=
"*runtime.SliceType"
;
if
(
isptr
[
et
]
&&
t
->
type
->
etype
==
TANY
)
name
=
"*runtime.UnsafePointerType"
;
return
pkglookup
(
name
,
"type"
);
}
/*
* commonType
* ../../pkg/runtime/type.go:/commonType
*/
static
int
dcommontype
(
Sym
*
s
,
int
ot
,
Type
*
t
)
{
int
i
;
Sym
*
s1
;
Type
*
elem
;
char
*
p
;
s1
=
dextratype
(
t
);
// empty interface pointing at this type.
// all the references that we emit are *interface{};
// they point here.
ot
=
rnd
(
ot
,
widthptr
);
ot
=
dsymptr
(
s
,
ot
,
typestruct
(
t
),
0
);
ot
=
dsymptr
(
s
,
ot
,
s
,
2
*
widthptr
);
// ../../pkg/runtime/type.go:/commonType
// actual type structure
// type commonType struct {
// size uintptr;
// hash uint32;
// alg uint8;
// align uint8;
// fieldAlign uint8;
// string *string;
// *nameInfo;
// }
ot
=
duintptr
(
s
,
ot
,
t
->
width
);
ot
=
duint32
(
s
,
ot
,
typehash
(
t
,
1
,
0
));
ot
=
duint8
(
s
,
ot
,
algtype
(
t
));
elem
=
t
;
while
(
elem
->
etype
==
TARRAY
&&
elem
->
bound
>=
0
)
elem
=
elem
->
type
;
i
=
elem
->
width
;
if
(
i
>
maxround
)
i
=
maxround
;
ot
=
duint8
(
s
,
ot
,
i
);
// align
ot
=
duint8
(
s
,
ot
,
i
);
// fieldAlign
p
=
smprint
(
"%#-T"
,
t
);
ot
=
dgostringptr
(
s
,
ot
,
p
);
// string
free
(
p
);
if
(
s1
)
ot
=
dsymptr
(
s
,
ot
,
s1
,
0
);
// extraType
else
ot
=
duintptr
(
s
,
ot
,
0
);
return
ot
;
}
Sym
*
typesym
(
Type
*
t
)
{
char
*
p
;
Sym
*
s
;
p
=
smprint
(
"%#-T"
,
t
);
s
=
pkglookup
(
p
,
"type"
);
free
(
p
);
return
s
;
}
Node
*
typename
(
Type
*
t
)
{
Sym
*
s
;
Node
*
n
;
Dcl
*
d
;
s
=
typesym
(
t
);
if
(
s
->
def
==
N
)
{
n
=
nod
(
ONAME
,
N
,
N
);
n
->
sym
=
s
;
n
->
type
=
types
[
TUINT8
];
n
->
addable
=
1
;
n
->
ullman
=
1
;
n
->
class
=
PEXTERN
;
n
->
xoffset
=
0
;
s
->
def
=
n
;
// copy to signatlist
d
=
dcl
();
d
->
dsym
=
s
;
d
->
dtype
=
t
;
d
->
op
=
OTYPE
;
d
->
forw
=
signatlist
;
signatlist
=
d
;
}
n
=
nod
(
OADDR
,
s
->
def
,
N
);
n
->
type
=
ptrto
(
s
->
def
->
type
);
n
->
addable
=
1
;
n
->
ullman
=
2
;
return
n
;
}
Sym
*
dtypesym
(
Type
*
t
)
{
int
ot
,
n
;
Sym
*
s
,
*
s1
,
*
s2
;
Sig
*
a
,
*
m
;
Type
*
t1
;
s
=
typesym
(
t
);
if
(
s
->
siggen
)
return
s
;
s
->
siggen
=
1
;
// special case (look for runtime below):
// when compiling package runtime,
// emit the type structures for int, float, etc.
t1
=
T
;
if
(
isptr
[
t
->
etype
])
t1
=
t
->
type
;
if
(
strcmp
(
package
,
"runtime"
)
==
0
)
{
if
(
t
==
types
[
t
->
etype
])
goto
ok
;
if
(
t1
&&
t1
==
types
[
t1
->
etype
])
goto
ok
;
}
// named types from other files are defined in those files
if
(
t
->
sym
&&
!
t
->
local
)
return
s
;
if
(
!
t
->
sym
&&
t1
&&
t1
->
sym
&&
!
t1
->
local
)
return
s
;
if
(
isforw
[
t
->
etype
]
||
(
t1
&&
isforw
[
t1
->
etype
]))
return
s
;
ok:
ot
=
0
;
switch
(
t
->
etype
)
{
default:
ot
=
dcommontype
(
s
,
ot
,
t
);
break
;
case
TARRAY
:
// ../../pkg/runtime/type.go:/ArrayType
s1
=
dtypesym
(
t
->
type
);
ot
=
dcommontype
(
s
,
ot
,
t
);
ot
=
dsymptr
(
s
,
ot
,
s1
,
0
);
if
(
t
->
bound
<
0
)
ot
=
duintptr
(
s
,
ot
,
-
1
);
else
ot
=
duintptr
(
s
,
ot
,
t
->
bound
);
break
;
case
TCHAN
:
// ../../pkg/runtime/type.go:/ChanType
s1
=
dtypesym
(
t
->
type
);
ot
=
dcommontype
(
s
,
ot
,
t
);
ot
=
dsymptr
(
s
,
ot
,
s1
,
0
);
ot
=
duintptr
(
s
,
ot
,
t
->
chan
);
break
;
case
TFORWSTRUCT
:
case
TFORWINTER
:
return
s
;
case
TFUNC
:
for
(
t1
=
getthisx
(
t
)
->
type
;
t1
;
t1
=
t1
->
down
)
dtypesym
(
t1
->
type
);
for
(
t1
=
getinargx
(
t
)
->
type
;
t1
;
t1
=
t1
->
down
)
dtypesym
(
t1
->
type
);
for
(
t1
=
getoutargx
(
t
)
->
type
;
t1
;
t1
=
t1
->
down
)
dtypesym
(
t1
->
type
);
ot
=
dcommontype
(
s
,
ot
,
t
);
// two slice headers: in and out.
ot
=
dsymptr
(
s
,
ot
,
s
,
ot
+
2
*
(
widthptr
+
2
*
4
));
n
=
t
->
thistuple
+
t
->
intuple
;
ot
=
duint32
(
s
,
ot
,
n
);
ot
=
duint32
(
s
,
ot
,
n
);
ot
=
dsymptr
(
s
,
ot
,
s
,
ot
+
1
*
(
widthptr
+
2
*
4
)
+
n
*
widthptr
);
ot
=
duint32
(
s
,
ot
,
t
->
outtuple
);
ot
=
duint32
(
s
,
ot
,
t
->
outtuple
);
// slice data
for
(
t1
=
getthisx
(
t
)
->
type
;
t1
;
t1
=
t1
->
down
,
n
++
)
ot
=
dsymptr
(
s
,
ot
,
dtypesym
(
t1
->
type
),
0
);
for
(
t1
=
getinargx
(
t
)
->
type
;
t1
;
t1
=
t1
->
down
,
n
++
)
ot
=
dsymptr
(
s
,
ot
,
dtypesym
(
t1
->
type
),
0
);
for
(
t1
=
getoutargx
(
t
)
->
type
;
t1
;
t1
=
t1
->
down
,
n
++
)
ot
=
dsymptr
(
s
,
ot
,
dtypesym
(
t1
->
type
),
0
);
break
;
case
TINTER
:
m
=
imethods
(
t
);
n
=
0
;
for
(
a
=
m
;
a
;
a
=
a
->
link
)
{
dtypesym
(
a
->
type
);
n
++
;
}
// ../../pkg/runtime/type.go:/InterfaceType
ot
=
dcommontype
(
s
,
ot
,
t
);
ot
=
dsymptr
(
s
,
ot
,
s
,
ot
+
widthptr
+
2
*
4
);
ot
=
duint32
(
s
,
ot
,
n
);
ot
=
duint32
(
s
,
ot
,
n
);
for
(
a
=
m
;
a
;
a
=
a
->
link
)
{
// ../../pkg/runtime/type.go:/imethod
ot
=
duint32
(
s
,
ot
,
a
->
hash
);
ot
=
duint32
(
s
,
ot
,
a
->
perm
);
ot
=
dgostringptr
(
s
,
ot
,
a
->
name
);
ot
=
dgostringptr
(
s
,
ot
,
a
->
package
);
ot
=
dsymptr
(
s
,
ot
,
dtypesym
(
a
->
type
),
0
);
}
break
;
case
TMAP
:
// ../../pkg/runtime/type.go:/MapType
s1
=
dtypesym
(
t
->
down
);
s2
=
dtypesym
(
t
->
type
);
ot
=
dcommontype
(
s
,
ot
,
t
);
ot
=
dsymptr
(
s
,
ot
,
s1
,
0
);
ot
=
dsymptr
(
s
,
ot
,
s2
,
0
);
break
;
case
TPTR32
:
case
TPTR64
:
if
(
t
->
type
->
etype
==
TANY
)
{
ot
=
dcommontype
(
s
,
ot
,
t
);
break
;
}
// ../../pkg/runtime/type.go:/PtrType
s1
=
dtypesym
(
t
->
type
);
ot
=
dcommontype
(
s
,
ot
,
t
);
ot
=
dsymptr
(
s
,
ot
,
s1
,
0
);
break
;
case
TSTRUCT
:
// ../../pkg/runtime/type.go:/StructType
// for security, only the exported fields.
n
=
0
;
for
(
t1
=
t
->
type
;
t1
!=
T
;
t1
=
t1
->
down
)
{
dtypesym
(
t1
->
type
);
n
++
;
}
ot
=
dcommontype
(
s
,
ot
,
t
);
ot
=
dsymptr
(
s
,
ot
,
s
,
ot
+
widthptr
+
2
*
4
);
ot
=
duint32
(
s
,
ot
,
n
);
ot
=
duint32
(
s
,
ot
,
n
);
for
(
t1
=
t
->
type
;
t1
!=
T
;
t1
=
t1
->
down
)
{
// ../../pkg/runtime/type.go:/structField
if
(
t1
->
sym
)
{
ot
=
dgostringptr
(
s
,
ot
,
t1
->
sym
->
name
);
if
(
exportname
(
t1
->
sym
->
name
))
ot
=
dgostringptr
(
s
,
ot
,
nil
);
else
ot
=
dgostringptr
(
s
,
ot
,
t1
->
sym
->
package
);
}
else
{
ot
=
dgostringptr
(
s
,
ot
,
nil
);
ot
=
dgostringptr
(
s
,
ot
,
nil
);
}
ot
=
dsymptr
(
s
,
ot
,
dtypesym
(
t1
->
type
),
0
);
ot
=
dgostrlitptr
(
s
,
ot
,
t1
->
note
);
ot
=
duintptr
(
s
,
ot
,
t1
->
width
);
// field offset
}
break
;
}
ggloblsym
(
s
,
ot
,
1
);
return
s
;
}
void
dumptypestructs
(
void
)
{
int
i
;
Dcl
*
d
,
*
x
;
Type
*
t
;
// copy types from externdcl list to signatlist
for
(
d
=
externdcl
;
d
!=
D
;
d
=
d
->
forw
)
{
if
(
d
->
op
!=
OTYPE
)
continue
;
t
=
d
->
dtype
;
x
=
mal
(
sizeof
(
*
x
));
x
->
op
=
OTYPE
;
x
->
dtype
=
t
;
x
->
forw
=
signatlist
;
x
->
block
=
0
;
signatlist
=
x
;
}
// process signatlist
for
(
d
=
signatlist
;
d
!=
D
;
d
=
d
->
forw
)
{
if
(
d
->
op
!=
OTYPE
)
continue
;
t
=
d
->
dtype
;
dtypesym
(
t
);
if
(
t
->
sym
&&
!
isptr
[
t
->
etype
])
dtypesym
(
ptrto
(
t
));
}
// do basic types if compiling package runtime, type.go.
// they have to be in at least one package,
// and reflect is always loaded implicitly,
// so this is as good as any.
// another possible choice would be package main,
// but using runtime means fewer copies in .6 files.
if
(
strcmp
(
package
,
"runtime"
)
==
0
&&
strcmp
(
filename
,
"type"
)
==
0
)
{
for
(
i
=
1
;
i
<=
TBOOL
;
i
++
)
if
(
i
!=
TFLOAT80
)
dtypesym
(
ptrto
(
types
[
i
]));
dtypesym
(
ptrto
(
types
[
TSTRING
]));
dtypesym
(
typ
(
TDDD
));
dtypesym
(
ptrto
(
pkglookup
(
"Pointer"
,
"unsafe"
)
->
def
->
type
));
}
}
src/cmd/gc/subr.c
View file @
541e638f
...
...
@@ -1613,64 +1613,6 @@ iscomposite(Type *t)
return
0
;
}
Node
*
signame
(
Type
*
t
)
{
Sym
*
ss
;
char
*
e
;
Dcl
*
x
;
char
buf
[
NSYMB
];
//print("signame %T\n", t);
if
(
t
==
T
)
goto
bad
;
e
=
"sigt"
;
if
(
t
->
etype
==
TINTER
||
t
->
etype
==
TDDD
)
e
=
"sigi"
;
// name is exported name, like *[]byte or *Struct or Interface
// (special symbols don't bother the linker).
snprint
(
buf
,
sizeof
(
buf
),
"%#T"
,
t
);
// special case: empty interface is named sigi.empty
// so that it can be referred to by the runtime.
if
(
strcmp
(
buf
,
"interface { }"
)
==
0
)
strcpy
(
buf
,
"empty"
);
// special case: sigi.... is just too hard to read in assembly.
if
(
strcmp
(
buf
,
"..."
)
==
0
)
strcpy
(
buf
,
"dotdotdot"
);
ss
=
pkglookup
(
buf
,
e
);
if
(
ss
->
def
==
N
)
{
ss
->
def
=
newname
(
ss
);
ss
->
def
->
type
=
types
[
TUINT8
];
ss
->
def
->
class
=
PEXTERN
;
}
//print("siggen %T %d\n", t, t->siggen);
if
(
!
t
->
siggen
)
{
// special case: don't generate the empty interface
if
(
strcmp
(
buf
,
"empty"
)
==
0
)
goto
out
;
// record internal type for signature generation
x
=
mal
(
sizeof
(
*
x
));
x
->
op
=
OTYPE
;
x
->
dtype
=
t
;
x
->
forw
=
signatlist
;
t
->
siggen
=
1
;
signatlist
=
x
;
}
out:
return
ss
->
def
;
bad:
return
N
;
}
int
eqtype1
(
Type
*
t1
,
Type
*
t2
,
int
d
,
int
names
)
{
...
...
src/cmd/gc/unsafe.go
View file @
541e638f
...
...
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
PACKAGE
type
Pointer
*
any
;
func
Offsetof
(
any
)
int
;
func
Sizeof
(
any
)
int
;
func
Alignof
(
any
)
int
;
func
Reflect
(
i
interface
{
})
(
uint64
,
string
,
bool
);
func
Unreflect
(
uint64
,
string
,
bool
)
(
ret
interface
{
});
func
Typeof
(
i
interface
{
})
(
typ
interface
{});
func
Reflect
(
i
interface
{
})
(
typ
interface
{},
addr
Pointer
);
func
Unreflect
(
typ
interface
{},
addr
Pointer
)
(
ret
interface
{
});
src/cmd/gc/walk.c
View file @
541e638f
...
...
@@ -1940,7 +1940,6 @@ loop:
Type
*
sigtype
(
Type
*
st
)
{
Dcl
*
x
;
Sym
*
s
;
Type
*
t
;
static
int
sigdddgen
;
...
...
@@ -1954,16 +1953,6 @@ sigtype(Type *st)
t
=
dodcltype
(
t
);
updatetype
(
t
,
st
);
t
->
local
=
1
;
// record internal type for signature generation
x
=
mal
(
sizeof
(
*
x
));
x
->
op
=
OTYPE
;
x
->
dsym
=
s
;
x
->
dtype
=
t
;
x
->
forw
=
signatlist
;
x
->
block
=
block
;
signatlist
=
x
;
return
t
;
}
...
...
@@ -3260,10 +3249,10 @@ ifacecvt(Type *tl, Node *n, int et)
a
=
n
;
// elem
r
=
a
;
a
=
nod
(
OADDR
,
signame
(
tr
),
N
);
// sigt
a
=
typename
(
tr
);
// sigt
r
=
list
(
a
,
r
);
a
=
nod
(
OADDR
,
signame
(
tl
),
N
);
// sigi
a
=
typename
(
tl
);
// sigi
r
=
list
(
a
,
r
);
on
=
syslook
(
"ifaceT2I"
,
1
);
...
...
@@ -3284,7 +3273,7 @@ ifacecvt(Type *tl, Node *n, int et)
a
=
n
;
// interface
r
=
a
;
a
=
nod
(
OADDR
,
signame
(
tl
),
N
);
// sigi or sigt
a
=
typename
(
tl
);
// sigi or sigt
r
=
list
(
a
,
r
);
on
=
syslook
(
ifacename
[
et
],
1
);
...
...
@@ -3308,7 +3297,7 @@ ifacecvt(Type *tl, Node *n, int et)
a
=
n
;
// elem
r
=
a
;
a
=
nod
(
OADDR
,
signame
(
tr
),
N
);
// sigt
a
=
typename
(
tr
);
// sigt
r
=
list
(
a
,
r
);
on
=
syslook
(
"ifaceT2E"
,
1
);
...
...
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