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
b379d54d
Commit
b379d54d
authored
Oct 25, 2008
by
Ken Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
another step toward interface subtypes
put explicit ./ on some runtime tests R=r OCL=17839 CL=17839
parent
cc4dc5a2
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
595 additions
and
316 deletions
+595
-316
obj.c
src/cmd/6g/obj.c
+320
-194
go.h
src/cmd/gc/go.h
+18
-1
subr.c
src/cmd/gc/subr.c
+248
-0
walk.c
src/cmd/gc/walk.c
+0
-113
run.bash
src/run.bash
+3
-2
Makefile
usr/gri/pretty/Makefile
+1
-1
test.sh
usr/gri/pretty/test.sh
+5
-5
No files found.
src/cmd/6g/obj.c
View file @
b379d54d
...
...
@@ -455,84 +455,268 @@ sigcmp(Sig *a, Sig *b)
return
strcmp
(
a
->
name
,
b
->
name
);
}
static
Addr
at
,
ao
,
ac
,
ad
;
static
int
wi
,
ot
;
void
dumpsignatures
(
void
)
ginsatoa
(
int
fscale
,
int
toffset
)
{
Prog
*
p
;
p
=
pc
;
ot
=
rnd
(
ot
,
fscale
);
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
fscale
;
p
->
to
=
ao
;
p
->
to
.
offset
=
toffset
;
ot
+=
fscale
;
}
void
gensatac
(
int
fscale
,
int
toffset
)
{
Prog
*
p
;
p
=
pc
;
ot
=
rnd
(
ot
,
fscale
);
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
fscale
;
p
->
to
=
ac
;
p
->
to
.
offset
=
toffset
;
ot
+=
fscale
;
}
void
gensatad
(
Sym
*
s
)
{
Prog
*
p
;
p
=
pc
;
ot
=
rnd
(
ot
,
widthptr
);
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
widthptr
;
p
->
to
=
ad
;
p
->
to
.
sym
=
s
;
ot
+=
widthptr
;
}
void
gentramp
(
Type
*
t
,
Sig
*
b
)
{
Sym
*
e
;
int
c
,
d
;
e
=
lookup
(
b
->
name
);
for
(
d
=
0
;
d
<
nelem
(
dotlist
);
d
++
)
{
c
=
adddot1
(
e
,
t
,
d
);
if
(
c
==
1
)
goto
out
;
}
fatal
(
"gentramp"
);
out:
print
(
"gentramp %d
\n
"
,
d
);
print
(
" t = %lT
\n
"
,
t
);
print
(
" name = %s
\n
"
,
b
->
name
);
print
(
" sym = %S
\n
"
,
b
->
sym
);
print
(
" hash = 0x%ux
\n
"
,
b
->
hash
);
for
(
c
=
d
-
1
;
c
>=
0
;
c
--
)
{
print
(
" %d %d %S
\n
"
,
dotlist
[
c
].
ptr
,
dotlist
[
c
].
offset
,
dotlist
[
c
].
sym
);
}
//TEXT main·S_test2(SB),7,$0
// MOVQ 8(SP), AX
// MOVQ XX(AX), AX
// ADDQ $XX, AX
// MOVQ AX, 8(SP)
// JMP main·Sub_test2(SB)
}
void
dumpsigt
(
void
)
{
Dcl
*
d
,
*
x
;
Type
*
t
,
*
f
;
Sym
*
s1
,
*
s
;
int
et
,
o
,
wi
,
ot
;
int
et
,
o
;
Sig
*
a
,
*
b
;
Addr
at
,
ao
,
ac
,
ad
;
Prog
*
p
;
char
*
sp
;
char
buf
[
NSYMB
];
// copy externdcl list to signatlist
for
(
d
=
externdcl
;
d
!=
D
;
d
=
d
->
forw
)
{
/*
* put all the names into a linked
* list so that it may be generated in sorted order.
* the runtime will be linear rather than quadradic
*/
for
(
d
=
signatlist
;
d
!=
D
;
d
=
d
->
forw
)
{
if
(
d
->
op
!=
OTYPE
)
continue
;
t
=
d
->
dtype
;
if
(
t
==
T
)
et
=
t
->
etype
;
if
(
et
==
TINTER
)
continue
;
s
=
signame
(
t
,
0
);
at
.
sym
=
signame
(
t
,
d
->
block
);
if
(
at
.
sym
==
S
)
continue
;
// make unique
if
(
at
.
sym
->
local
!=
1
)
continue
;
at
.
sym
->
local
=
2
;
s
=
d
->
dsym
;
if
(
s
==
S
)
continue
;
x
=
mal
(
sizeof
(
*
d
));
x
->
op
=
OTYPE
;
x
->
dsym
=
d
->
dsym
;
x
->
dtype
=
d
->
dtype
;
x
->
forw
=
signatlist
;
x
->
block
=
0
;
signatlist
=
x
;
//print("SIG = %lS %lS %lT\n", d->dsym, s, t);
}
if
(
s
->
name
[
0
]
==
'_'
)
continue
;
/*
* put all the names into a linked
* list so that it may be generated in sorted order.
* the runtime will be linear rather than quadradic
*/
if
(
strcmp
(
s
->
opackage
,
package
)
!=
0
)
continue
;
memset
(
&
at
,
0
,
sizeof
(
at
));
memset
(
&
ao
,
0
,
sizeof
(
ao
));
memset
(
&
ac
,
0
,
sizeof
(
ac
));
memset
(
&
ad
,
0
,
sizeof
(
ad
));
expandmeth
(
s
,
t
);
// sig structure
at
.
type
=
D_EXTERN
;
at
.
index
=
D_NONE
;
at
.
sym
=
S
;
// fill in
at
.
offset
=
0
;
// fill in
a
=
nil
;
o
=
0
;
for
(
f
=
t
->
method
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
type
->
etype
!=
TFUNC
)
continue
;
// $string
ao
.
type
=
D_ADDR
;
ao
.
index
=
D_STATIC
;
ao
.
etype
=
TINT32
;
ao
.
sym
=
symstringo
;
ao
.
offset
=
0
;
// fill in
if
(
f
->
etype
!=
TFIELD
)
fatal
(
"dumpsignatures: not field"
);
// constant
ac
.
type
=
D_CONST
;
ac
.
index
=
D_NONE
;
ac
.
offset
=
0
;
// fill in
s1
=
f
->
sym
;
if
(
s1
==
nil
)
continue
;
// $method
ad
.
type
=
D_ADDR
;
ad
.
index
=
D_EXTERN
;
ad
.
sym
=
S
;
// fill in
ad
.
offset
=
0
;
b
=
mal
(
sizeof
(
*
b
));
b
->
link
=
a
;
a
=
b
;
wi
=
types
[
TINT32
]
->
width
;
a
->
name
=
s1
->
name
;
a
->
hash
=
PRIME8
*
stringhash
(
a
->
name
)
+
PRIME9
*
typehash
(
f
->
type
,
0
);
a
->
perm
=
o
;
snprint
(
namebuf
,
sizeof
(
namebuf
),
"%s_%s"
,
at
.
sym
->
name
+
5
,
f
->
sym
->
name
);
a
->
sym
=
lookup
(
namebuf
);
a
->
offset
=
f
->
embedded
;
// need trampoline
o
++
;
}
a
=
lsort
(
a
,
sigcmp
);
ot
=
0
;
ot
=
rnd
(
ot
,
maxround
);
// base structure
// sigi[0].name = ""
ginsatoa
(
widthptr
,
stringo
);
// save type name for runtime error message.
// TODO(rsc): the * is a botch but right more often than not.
snprint
(
buf
,
sizeof
buf
,
"*%#T"
,
t
);
datastring
(
buf
,
strlen
(
buf
)
+
1
);
// first field of an type signature contains
// the element parameters and is not a real entry
t
=
d
->
dtype
;
if
(
t
->
methptr
&
2
)
t
=
types
[
tptr
];
// sigi[0].hash = elemalg
gensatac
(
wi
,
algtype
(
t
));
// sigi[0].offset = width
gensatac
(
wi
,
t
->
width
);
// skip the function
gensatac
(
widthptr
,
0
);
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
{
ot
=
rnd
(
ot
,
maxround
);
// base structure
// sigx[++].name = "fieldname"
ginsatoa
(
widthptr
,
stringo
);
// sigx[++].hash = hashcode
gensatac
(
wi
,
b
->
hash
);
// sigt[++].offset = of embeded struct
gensatac
(
wi
,
0
);
// sigt[++].fun = &method
gensatad
(
b
->
sym
);
datastring
(
b
->
name
,
strlen
(
b
->
name
)
+
1
);
if
(
b
->
offset
)
gentramp
(
d
->
dtype
,
b
);
}
// nil field name at end
ot
=
rnd
(
ot
,
maxround
);
gensatac
(
widthptr
,
0
);
p
=
pc
;
gins
(
AGLOBL
,
N
,
N
);
p
->
from
=
at
;
p
->
to
=
ac
;
p
->
to
.
offset
=
ot
;
}
if
(
stringo
>
0
)
{
p
=
pc
;
gins
(
AGLOBL
,
N
,
N
);
p
->
from
=
ao
;
p
->
to
=
ac
;
p
->
to
.
offset
=
stringo
;
}
}
void
dumpsigi
(
void
)
{
Dcl
*
d
,
*
x
;
Type
*
t
,
*
f
;
Sym
*
s1
,
*
s
;
int
et
,
o
;
Sig
*
a
,
*
b
;
Prog
*
p
;
char
*
sp
;
char
buf
[
NSYMB
];
/*
* put all the names into a linked
* list so that it may be generated in sorted order.
* the runtime will be linear rather than quadradic
*/
for
(
d
=
signatlist
;
d
!=
D
;
d
=
d
->
forw
)
{
if
(
d
->
op
!=
OTYPE
)
continue
;
t
=
d
->
dtype
;
et
=
t
->
etype
;
if
(
et
!=
TINTER
)
continue
;
at
.
sym
=
signame
(
t
,
d
->
block
);
if
(
at
.
sym
==
S
)
continue
;
...
...
@@ -542,10 +726,6 @@ dumpsignatures(void)
continue
;
at
.
sym
->
local
=
2
;
//print("SIGNAME = %lS\n", at.sym);
et
=
t
->
etype
;
s
=
d
->
dsym
;
if
(
s
==
S
)
continue
;
...
...
@@ -556,14 +736,11 @@ dumpsignatures(void)
if
(
strcmp
(
s
->
opackage
,
package
)
!=
0
)
continue
;
//print("sigi: %S\n", s);
a
=
nil
;
o
=
0
;
f
=
t
->
method
;
if
(
et
==
TINTER
)
f
=
t
->
type
;
for
(;
f
!=
T
;
f
=
f
->
down
)
{
for
(
f
=
t
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
type
->
etype
!=
TFUNC
)
continue
;
...
...
@@ -597,162 +774,47 @@ dumpsignatures(void)
a
=
lsort
(
a
,
sigcmp
);
ot
=
0
;
ot
=
rnd
(
ot
,
maxround
);
// base structure
// sigi[0].name = ""
ot
=
rnd
(
ot
,
maxround
);
// array of structures
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
widthptr
;
p
->
to
=
ao
;
p
->
to
.
offset
=
stringo
;
ot
+=
widthptr
;
ginsatoa
(
widthptr
,
stringo
);
// save type name for runtime error message.
// TODO(rsc): the * is a botch but right more often than not.
if
(
et
==
TINTER
)
snprint
(
buf
,
sizeof
buf
,
"%#T"
,
t
);
else
snprint
(
buf
,
sizeof
buf
,
"*%#T"
,
t
);
snprint
(
buf
,
sizeof
buf
,
"%#T"
,
t
);
datastring
(
buf
,
strlen
(
buf
)
+
1
);
if
(
et
==
TINTER
)
{
// first field of an interface signature
// contains the count and is not a real entry
o
=
0
;
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
o
++
;
// sigi[0].hash = 0
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
0
;
ot
+=
wi
;
// sigi[0].offset = count
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
o
;
ot
+=
wi
;
}
else
{
// first field of an type signature contains
// the element parameters and is not a real entry
t
=
d
->
dtype
;
if
(
t
->
methptr
&
2
)
t
=
types
[
tptr
];
// sigi[0].hash = elemalg
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
algtype
(
t
);
ot
+=
wi
;
// sigi[0].offset = width
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
t
->
width
;
ot
+=
wi
;
// skip the function
ot
=
rnd
(
ot
,
widthptr
);
ot
+=
widthptr
;
}
// first field of an interface signature
// contains the count and is not a real entry
// sigi[0].hash = 0
gensatac
(
wi
,
0
);
// sigi[0].offset = count
o
=
0
;
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
o
++
;
gensatac
(
wi
,
o
);
for
(
b
=
a
;
b
!=
nil
;
b
=
b
->
link
)
{
//print(" %s\n", b->name);
ot
=
rnd
(
ot
,
maxround
);
// base structure
// sigx[++].name = "fieldname"
ot
=
rnd
(
ot
,
maxround
);
// array of structures
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
widthptr
;
p
->
to
=
ao
;
p
->
to
.
offset
=
stringo
;
ot
+=
widthptr
;
ginsatoa
(
widthptr
,
stringo
);
// sigx[++].hash = hashcode
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
b
->
hash
;
ot
+=
wi
;
if
(
et
==
TINTER
)
{
// sigi[++].perm = mapped offset of method
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
b
->
perm
;
ot
+=
wi
;
}
else
{
// sigt[++].offset = of embeded struct
ot
=
rnd
(
ot
,
wi
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
wi
;
p
->
to
=
ac
;
p
->
to
.
offset
=
b
->
offset
;
ot
+=
wi
;
// sigt[++].fun = &method
ot
=
rnd
(
ot
,
widthptr
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
widthptr
;
p
->
to
=
ad
;
p
->
to
.
sym
=
b
->
sym
;
ot
+=
widthptr
;
}
datastring
(
b
->
name
,
strlen
(
b
->
name
)
+
1
);
gensatac
(
wi
,
b
->
hash
);
// sigi[++].perm = mapped offset of method
gensatac
(
wi
,
b
->
perm
);
datastring
(
b
->
name
,
strlen
(
b
->
name
)
+
1
);
}
// nil field name at end
ot
=
rnd
(
ot
,
maxround
);
p
=
pc
;
gins
(
ADATA
,
N
,
N
);
p
->
from
=
at
;
p
->
from
.
offset
=
ot
;
p
->
from
.
scale
=
widthptr
;
p
->
to
=
ac
;
p
->
to
.
offset
=
0
;
ot
+=
widthptr
;
gensatac
(
widthptr
,
0
);
p
=
pc
;
gins
(
AGLOBL
,
N
,
N
);
...
...
@@ -769,3 +831,67 @@ dumpsignatures(void)
p
->
to
.
offset
=
stringo
;
}
}
void
dumpsignatures
(
void
)
{
Dcl
*
d
,
*
x
;
Type
*
t
;
Sym
*
s
;
memset
(
&
at
,
0
,
sizeof
(
at
));
memset
(
&
ao
,
0
,
sizeof
(
ao
));
memset
(
&
ac
,
0
,
sizeof
(
ac
));
memset
(
&
ad
,
0
,
sizeof
(
ad
));
wi
=
types
[
TINT32
]
->
width
;
// sig structure
at
.
type
=
D_EXTERN
;
at
.
index
=
D_NONE
;
at
.
sym
=
S
;
// fill in
at
.
offset
=
0
;
// fill in
// $string
ao
.
type
=
D_ADDR
;
ao
.
index
=
D_STATIC
;
ao
.
etype
=
TINT32
;
ao
.
sym
=
symstringo
;
ao
.
offset
=
0
;
// fill in
// constant
ac
.
type
=
D_CONST
;
ac
.
index
=
D_NONE
;
ac
.
offset
=
0
;
// fill in
// $method
ad
.
type
=
D_ADDR
;
ad
.
index
=
D_EXTERN
;
ad
.
sym
=
S
;
// fill in
ad
.
offset
=
0
;
// 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
;
s
=
signame
(
t
,
0
);
if
(
s
==
S
)
continue
;
x
=
mal
(
sizeof
(
*
d
));
x
->
op
=
OTYPE
;
x
->
dsym
=
d
->
dsym
;
x
->
dtype
=
d
->
dtype
;
x
->
forw
=
signatlist
;
x
->
block
=
0
;
signatlist
=
x
;
//print("SIG = %lS %lS %lT\n", d->dsym, s, t);
}
dumpsigi
();
dumpsigt
();
}
src/cmd/gc/go.h
View file @
b379d54d
...
...
@@ -208,6 +208,7 @@ struct Sym
uchar
exported
;
// exported
uchar
sym
;
// huffman encoding in object file
uchar
local
;
// created in this file
uchar
uniq
;
// imbedded field name first found
char
*
opackage
;
// original package name
char
*
package
;
// package name
...
...
@@ -398,6 +399,16 @@ struct Io
char
*
cp
;
// used for content when bin==nil
};
typedef
struct
Dlist
Dlist
;
struct
Dlist
{
Sym
*
sym
;
uchar
ptr
;
int
offset
;
};
EXTERN
Dlist
dotlist
[
10
];
// size is max depth of embeddeds
EXTERN
Io
curio
;
EXTERN
Io
pushedio
;
EXTERN
int32
lineno
;
...
...
@@ -631,6 +642,13 @@ int Nconv(Fmt*);
int
Wconv
(
Fmt
*
);
int
Zconv
(
Fmt
*
);
int
lookdot0
(
Sym
*
,
Type
*
);
int
adddot1
(
Sym
*
,
Type
*
,
int
);
Node
*
adddot
(
Node
*
);
void
expand0
(
Type
*
);
void
expand1
(
Type
*
,
int
);
void
expandmeth
(
Sym
*
,
Type
*
);
/*
* dcl.c
*/
...
...
@@ -748,7 +766,6 @@ Node* arraylit(Node*);
Node
*
maplit
(
Node
*
);
Node
*
selectas
(
Node
*
,
Node
*
);
Node
*
old2new
(
Node
*
,
Type
*
);
Node
*
adddot
(
Node
*
);
/*
* const.c
...
...
src/cmd/gc/subr.c
View file @
b379d54d
...
...
@@ -2377,3 +2377,251 @@ getinargx(Type *t)
{
return
*
getinarg
(
t
);
}
/*
* code to resolve elided DOTs
* in embedded types
*/
// search depth 0 --
// return count of fields+methods
// found with a given name
int
lookdot0
(
Sym
*
s
,
Type
*
t
)
{
Type
*
f
,
*
u
;
int
c
;
u
=
t
;
if
(
isptr
[
u
->
etype
])
u
=
u
->
type
;
c
=
0
;
if
(
u
->
etype
==
TSTRUCT
||
u
->
etype
==
TINTER
)
{
for
(
f
=
u
->
type
;
f
!=
T
;
f
=
f
->
down
)
if
(
f
->
sym
==
s
)
c
++
;
}
u
=
methtype
(
t
);
if
(
u
!=
T
)
{
for
(
f
=
u
->
method
;
f
!=
T
;
f
=
f
->
down
)
if
(
f
->
sym
==
s
&&
f
->
embedded
==
0
)
c
++
;
}
return
c
;
}
// search depth d --
// return count of fields+methods
// found at search depth.
// answer is in dotlist array and
// count of number of ways is returned.
int
adddot1
(
Sym
*
s
,
Type
*
t
,
int
d
)
{
Type
*
f
,
*
u
;
int
c
,
a
;
if
(
t
->
trecur
)
return
0
;
t
->
trecur
=
1
;
if
(
d
==
0
)
{
c
=
lookdot0
(
s
,
t
);
goto
out
;
}
c
=
0
;
u
=
t
;
if
(
isptr
[
u
->
etype
])
u
=
u
->
type
;
if
(
u
->
etype
!=
TSTRUCT
&&
u
->
etype
!=
TINTER
)
goto
out
;
d
--
;
for
(
f
=
u
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
!
f
->
embedded
)
continue
;
if
(
f
->
sym
==
S
)
continue
;
a
=
adddot1
(
s
,
f
->
type
,
d
);
if
(
a
!=
0
&&
c
==
0
)
{
dotlist
[
d
].
sym
=
f
->
sym
;
dotlist
[
d
].
offset
=
f
->
width
;
dotlist
[
d
].
ptr
=
0
;
if
(
isptr
[
f
->
type
->
etype
])
dotlist
[
d
].
ptr
=
1
;
}
c
+=
a
;
}
out:
t
->
trecur
=
0
;
return
c
;
}
// in T.field
// find missing fields that
// will give shortest unique addressing.
// modify the tree with missing type names.
Node
*
adddot
(
Node
*
n
)
{
Type
*
t
;
Sym
*
s
;
Node
*
l
;
int
c
,
d
;
walktype
(
n
->
left
,
Erv
);
t
=
n
->
left
->
type
;
if
(
t
==
T
)
return
n
;
if
(
n
->
right
->
op
!=
ONAME
)
return
n
;
s
=
n
->
right
->
sym
;
if
(
s
==
S
)
return
n
;
for
(
d
=
0
;
d
<
nelem
(
dotlist
);
d
++
)
{
c
=
adddot1
(
s
,
t
,
d
);
if
(
c
>
0
)
goto
out
;
}
return
n
;
out:
if
(
c
>
1
)
yyerror
(
"ambiguous DOT reference %S"
,
s
);
// rebuild elided dots
for
(
c
=
d
-
1
;
c
>=
0
;
c
--
)
{
n
=
nod
(
ODOT
,
n
,
n
->
right
);
n
->
left
->
right
=
newname
(
dotlist
[
c
].
sym
);
}
return
n
;
}
/*
* code to help generate trampoline
* functions for methods on embedded
* subtypes.
* these are approx the same as
* the corresponding adddot routines
* except that they expect to be called
* with unique tasks and they return
* the actual methods.
*/
typedef
struct
Symlink
Symlink
;
struct
Symlink
{
Type
*
field
;
uchar
good
;
Symlink
*
link
;
};
static
Symlink
*
slist
;
void
expand0
(
Type
*
t
)
{
Type
*
f
,
*
u
;
Symlink
*
sl
;
u
=
t
;
if
(
isptr
[
u
->
etype
])
u
=
u
->
type
;
u
=
methtype
(
t
);
if
(
u
!=
T
)
{
for
(
f
=
u
->
method
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
f
->
sym
->
uniq
)
continue
;
f
->
sym
->
uniq
=
1
;
sl
=
mal
(
sizeof
(
*
sl
));
sl
->
field
=
f
;
sl
->
link
=
slist
;
slist
=
sl
;
}
}
}
void
expand1
(
Type
*
t
,
int
d
)
{
Type
*
f
,
*
u
;
if
(
t
->
trecur
)
return
;
if
(
d
==
0
)
return
;
t
->
trecur
=
1
;
if
(
d
!=
nelem
(
dotlist
)
-
1
)
expand0
(
t
);
u
=
t
;
if
(
isptr
[
u
->
etype
])
u
=
u
->
type
;
if
(
u
->
etype
!=
TSTRUCT
&&
u
->
etype
!=
TINTER
)
goto
out
;
for
(
f
=
u
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
!
f
->
embedded
)
continue
;
if
(
f
->
sym
==
S
)
continue
;
expand1
(
f
->
type
,
d
-
1
);
}
out:
t
->
trecur
=
0
;
}
void
expandmeth
(
Sym
*
s
,
Type
*
t
)
{
Symlink
*
sl
;
Type
*
f
;
int
c
,
d
;
if
(
s
==
S
)
return
;
if
(
t
==
T
)
return
;
if
(
strcmp
(
s
->
name
,
"S"
)
!=
0
)
return
;
// generate all reachable methods
slist
=
nil
;
expand1
(
t
,
nelem
(
dotlist
)
-
1
);
// check each method to be uniquely reachable
for
(
sl
=
slist
;
sl
!=
nil
;
sl
=
sl
->
link
)
{
for
(
d
=
0
;
d
<
nelem
(
dotlist
);
d
++
)
{
c
=
adddot1
(
sl
->
field
->
sym
,
t
,
d
);
if
(
c
==
0
)
continue
;
if
(
c
==
1
)
sl
->
good
=
1
;
break
;
}
}
//print("expand %S: %lT", s, t);
for
(
sl
=
slist
;
sl
!=
nil
;
sl
=
sl
->
link
)
{
if
(
sl
->
good
)
{
// add it to the base type method list
f
=
typ
(
TFIELD
);
*
f
=
*
sl
->
field
;
f
->
embedded
=
1
;
// needs a trampoline
f
->
down
=
t
->
method
;
t
->
method
=
f
;
//print(" %T", f);
}
}
//print("\n");
}
src/cmd/gc/walk.c
View file @
b379d54d
...
...
@@ -3203,116 +3203,3 @@ loop:
r
=
listnext
(
&
saver
);
goto
loop
;
}
static
int
prdot
=
0
;
int
lookdot0
(
Sym
*
s
,
Type
*
t
)
{
Type
*
f
,
*
u
;
int
c
;
u
=
t
;
if
(
isptr
[
u
->
etype
])
u
=
u
->
type
;
c
=
0
;
if
(
u
->
etype
==
TSTRUCT
||
u
->
etype
==
TINTER
)
{
for
(
f
=
u
->
type
;
f
!=
T
;
f
=
f
->
down
)
if
(
f
->
sym
==
s
)
c
++
;
}
u
=
methtype
(
t
);
if
(
u
!=
T
)
{
for
(
f
=
u
->
method
;
f
!=
T
;
f
=
f
->
down
)
if
(
f
->
sym
==
s
)
{
if
(
prdot
)
print
(
"found method %S
\n
"
,
s
);
c
++
;
}
}
return
c
;
}
enum
{
maxembed
=
10
};
// max depth search for embedded types
static
Sym
*
dotlist
[
maxembed
+
1
];
// maxembed..1
int
adddot1
(
Sym
*
s
,
Type
*
t
,
int
d
)
{
Type
*
f
,
*
u
;
int
c
,
a
;
if
(
d
==
0
)
return
lookdot0
(
s
,
t
);
u
=
t
;
if
(
isptr
[
u
->
etype
])
u
=
u
->
type
;
if
(
u
->
etype
!=
TSTRUCT
&&
u
->
etype
!=
TINTER
)
return
0
;
c
=
0
;
for
(
f
=
u
->
type
;
f
!=
T
;
f
=
f
->
down
)
{
if
(
!
f
->
embedded
)
continue
;
if
(
f
->
sym
==
S
)
continue
;
a
=
adddot1
(
s
,
f
->
type
,
d
-
1
);
if
(
a
!=
0
&&
c
==
0
)
dotlist
[
d
]
=
f
->
sym
;
c
+=
a
;
}
return
c
;
}
Node
*
adddot
(
Node
*
n
)
{
Type
*
t
;
Sym
*
s
;
Node
*
l
;
int
c
,
d
;
walktype
(
n
->
left
,
Erv
);
t
=
n
->
left
->
type
;
if
(
t
==
T
)
return
n
;
if
(
n
->
right
->
op
!=
ONAME
)
return
n
;
s
=
n
->
right
->
sym
;
if
(
s
==
S
)
return
n
;
for
(
d
=
0
;
d
<
maxembed
;
d
++
)
{
c
=
adddot1
(
s
,
t
,
d
);
if
(
c
>
0
)
goto
out
;
}
if
(
prdot
)
{
print
(
"missed"
);
dump
(
""
,
n
);
}
return
n
;
out:
if
(
c
>
1
)
yyerror
(
"ambiguous DOT reference %S"
,
s
);
if
(
prdot
)
if
(
d
>
0
)
print
(
"add dots:"
);
// rebuild elided dots
for
(
c
=
d
;
c
>
0
;
c
--
)
{
n
=
nod
(
ODOT
,
n
,
n
->
right
);
n
->
left
->
right
=
newname
(
dotlist
[
c
]);
if
(
prdot
)
print
(
" %S"
,
dotlist
[
c
]);
}
if
(
prdot
)
if
(
d
>
0
)
print
(
"
\n
"
);
return
n
;
}
src/run.bash
View file @
b379d54d
...
...
@@ -6,8 +6,9 @@
set
-e
xcd
()
{
builtin cd
$1
echo
echo
---
cd
$1
builtin cd
$1
}
(
xcd lib/reflect
...
...
@@ -41,7 +42,7 @@ rm -f *.6 6.out
6g printf.go
6g main.go
6l main.6
6.out
./
6.out
)
(
xcd ../test
...
...
usr/gri/pretty/Makefile
View file @
b379d54d
...
...
@@ -9,7 +9,7 @@ pretty: pretty.6
$(L)
-o
pretty pretty.6
test
:
pretty
test.sh
./
test.sh
install
:
pretty
cp
pretty
$(HOME)
/bin/pretty
...
...
usr/gri/pretty/test.sh
View file @
b379d54d
...
...
@@ -61,7 +61,7 @@ cleanup() {
silent
()
{
cleanup
pretty
-s
$1
>
$TMP1
./
pretty
-s
$1
>
$TMP1
if
[
$?
!=
0
]
;
then
cat
$TMP1
echo
"Error (silent mode test): test.sh
$1
"
...
...
@@ -72,8 +72,8 @@ silent() {
idempotent
()
{
cleanup
pretty
$1
>
$TMP1
pretty
$TMP1
>
$TMP2
./
pretty
$1
>
$TMP1
./
pretty
$TMP1
>
$TMP2
cmp
-s
$TMP1
$TMP2
if
[
$?
!=
0
]
;
then
diff
$TMP1
$TMP2
...
...
@@ -85,7 +85,7 @@ idempotent() {
valid
()
{
cleanup
pretty
$1
>
$TMP1
./
pretty
$1
>
$TMP1
6g
-o
/dev/null
$TMP1
if
[
$?
!=
0
]
;
then
echo
"Error (validity test): test.sh
$1
"
...
...
@@ -122,7 +122,7 @@ runtests() {
# run selftest always
pretty
-t
selftest.go
>
$TMP1
./
pretty
-t
selftest.go
>
$TMP1
if
[
$?
!=
0
]
;
then
cat
$TMP1
echo
"Error (selftest): pretty -t selftest.go"
...
...
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