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
d6b29259
Commit
d6b29259
authored
May 11, 2011
by
Luuk van Dijk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gc: inline append when len<cap
issue 1604 R=rsc, bradfitz CC=golang-dev
https://golang.org/cl/4313062
parent
b276293a
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
419 additions
and
112 deletions
+419
-112
src/cmd/6g/cgen.c
src/cmd/6g/cgen.c
+29
-9
src/cmd/6g/ggen.c
src/cmd/6g/ggen.c
+23
-11
src/cmd/6g/gsubr.c
src/cmd/6g/gsubr.c
+33
-8
src/cmd/6g/reg.c
src/cmd/6g/reg.c
+4
-1
src/cmd/8g/cgen.c
src/cmd/8g/cgen.c
+29
-11
src/cmd/8g/ggen.c
src/cmd/8g/ggen.c
+21
-8
src/cmd/8g/gsubr.c
src/cmd/8g/gsubr.c
+53
-11
src/cmd/gc/builtin.c.boot
src/cmd/gc/builtin.c.boot
+3
-0
src/cmd/gc/runtime.go
src/cmd/gc/runtime.go
+1
-0
src/cmd/gc/subr.c
src/cmd/gc/subr.c
+8
-4
src/cmd/gc/walk.c
src/cmd/gc/walk.c
+109
-27
src/pkg/runtime/append_test.go
src/pkg/runtime/append_test.go
+51
-0
src/pkg/runtime/slice.c
src/pkg/runtime/slice.c
+55
-22
No files found.
src/cmd/6g/cgen.c
View file @
d6b29259
...
@@ -283,11 +283,9 @@ cgen(Node *n, Node *res)
...
@@ -283,11 +283,9 @@ cgen(Node *n, Node *res)
if
(
istype
(
nl
->
type
,
TSTRING
)
||
isslice
(
nl
->
type
))
{
if
(
istype
(
nl
->
type
,
TSTRING
)
||
isslice
(
nl
->
type
))
{
// both slice and string have len one pointer into the struct.
// both slice and string have len one pointer into the struct.
// a zero pointer means zero length
// a zero pointer means zero length
regalloc
(
&
n1
,
types
[
tptr
],
res
);
igen
(
nl
,
&
n1
,
res
);
agen
(
nl
,
&
n1
);
n1
.
op
=
OINDREG
;
n1
.
type
=
types
[
TUINT32
];
n1
.
type
=
types
[
TUINT32
];
n1
.
xoffset
=
Array_nel
;
n1
.
xoffset
+
=
Array_nel
;
gmove
(
&
n1
,
res
);
gmove
(
&
n1
,
res
);
regfree
(
&
n1
);
regfree
(
&
n1
);
break
;
break
;
...
@@ -319,11 +317,9 @@ cgen(Node *n, Node *res)
...
@@ -319,11 +317,9 @@ cgen(Node *n, Node *res)
break
;
break
;
}
}
if
(
isslice
(
nl
->
type
))
{
if
(
isslice
(
nl
->
type
))
{
regalloc
(
&
n1
,
types
[
tptr
],
res
);
igen
(
nl
,
&
n1
,
res
);
agen
(
nl
,
&
n1
);
n1
.
op
=
OINDREG
;
n1
.
type
=
types
[
TUINT32
];
n1
.
type
=
types
[
TUINT32
];
n1
.
xoffset
=
Array_cap
;
n1
.
xoffset
+
=
Array_cap
;
gmove
(
&
n1
,
res
);
gmove
(
&
n1
,
res
);
regfree
(
&
n1
);
regfree
(
&
n1
);
break
;
break
;
...
@@ -542,7 +538,8 @@ agen(Node *n, Node *res)
...
@@ -542,7 +538,8 @@ agen(Node *n, Node *res)
gmove
(
&
n1
,
&
n3
);
gmove
(
&
n1
,
&
n3
);
}
}
ginscon
(
optoas
(
OADD
,
types
[
tptr
]),
v
*
w
,
&
n3
);
if
(
v
*
w
!=
0
)
ginscon
(
optoas
(
OADD
,
types
[
tptr
]),
v
*
w
,
&
n3
);
gmove
(
&
n3
,
res
);
gmove
(
&
n3
,
res
);
regfree
(
&
n3
);
regfree
(
&
n3
);
break
;
break
;
...
@@ -682,6 +679,28 @@ ret:
...
@@ -682,6 +679,28 @@ ret:
void
void
igen
(
Node
*
n
,
Node
*
a
,
Node
*
res
)
igen
(
Node
*
n
,
Node
*
a
,
Node
*
res
)
{
{
Type
*
fp
;
Iter
flist
;
switch
(
n
->
op
)
{
case
ONAME
:
if
((
n
->
class
&
PHEAP
)
||
n
->
class
==
PPARAMREF
)
break
;
*
a
=
*
n
;
return
;
case
OCALLFUNC
:
fp
=
structfirst
(
&
flist
,
getoutarg
(
n
->
left
->
type
));
cgen_call
(
n
,
0
);
memset
(
a
,
0
,
sizeof
*
a
);
a
->
op
=
OINDREG
;
a
->
val
.
u
.
reg
=
D_SP
;
a
->
addable
=
1
;
a
->
xoffset
=
fp
->
width
;
a
->
type
=
n
->
type
;
return
;
}
regalloc
(
a
,
types
[
tptr
],
res
);
regalloc
(
a
,
types
[
tptr
],
res
);
agen
(
n
,
a
);
agen
(
n
,
a
);
a
->
op
=
OINDREG
;
a
->
op
=
OINDREG
;
...
@@ -848,6 +867,7 @@ bgen(Node *n, int true, Prog *to)
...
@@ -848,6 +867,7 @@ bgen(Node *n, int true, Prog *to)
n2
=
n1
;
n2
=
n1
;
n2
.
op
=
OINDREG
;
n2
.
op
=
OINDREG
;
n2
.
xoffset
=
Array_array
;
n2
.
xoffset
=
Array_array
;
n2
.
type
=
types
[
tptr
];
nodconst
(
&
tmp
,
types
[
tptr
],
0
);
nodconst
(
&
tmp
,
types
[
tptr
],
0
);
gins
(
optoas
(
OCMP
,
types
[
tptr
]),
&
n2
,
&
tmp
);
gins
(
optoas
(
OCMP
,
types
[
tptr
]),
&
n2
,
&
tmp
);
patch
(
gbranch
(
a
,
types
[
tptr
]),
to
);
patch
(
gbranch
(
a
,
types
[
tptr
]),
to
);
...
...
src/cmd/6g/ggen.c
View file @
d6b29259
...
@@ -201,7 +201,7 @@ cgen_callinter(Node *n, Node *res, int proc)
...
@@ -201,7 +201,7 @@ cgen_callinter(Node *n, Node *res, int proc)
regalloc
(
&
nodo
,
types
[
tptr
],
&
nodr
);
regalloc
(
&
nodo
,
types
[
tptr
],
&
nodr
);
nodo
.
op
=
OINDREG
;
nodo
.
op
=
OINDREG
;
agen
(
i
,
&
nodr
);
// REG = &inter
agen
(
i
,
&
nodr
);
// REG = &inter
nodindreg
(
&
nodsp
,
types
[
tptr
],
D_SP
);
nodindreg
(
&
nodsp
,
types
[
tptr
],
D_SP
);
nodo
.
xoffset
+=
widthptr
;
nodo
.
xoffset
+=
widthptr
;
...
@@ -1206,7 +1206,7 @@ cgen_inline(Node *n, Node *res)
...
@@ -1206,7 +1206,7 @@ cgen_inline(Node *n, Node *res)
Node
nodes
[
5
];
Node
nodes
[
5
];
Node
n1
,
n2
,
nres
,
ntemp
;
Node
n1
,
n2
,
nres
,
ntemp
;
vlong
v
;
vlong
v
;
int
i
,
narg
;
int
i
,
narg
,
nochk
;
if
(
n
->
op
!=
OCALLFUNC
)
if
(
n
->
op
!=
OCALLFUNC
)
goto
no
;
goto
no
;
...
@@ -1242,6 +1242,7 @@ slicearray:
...
@@ -1242,6 +1242,7 @@ slicearray:
// len = hb[3] - lb[2] (destroys hb)
// len = hb[3] - lb[2] (destroys hb)
n2
=
*
res
;
n2
=
*
res
;
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
3
])
&&
smallintconst
(
&
nodes
[
2
]))
{
if
(
smallintconst
(
&
nodes
[
3
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
3
].
val
.
u
.
xval
)
-
v
=
mpgetfix
(
nodes
[
3
].
val
.
u
.
xval
)
-
...
@@ -1260,6 +1261,7 @@ slicearray:
...
@@ -1260,6 +1261,7 @@ slicearray:
// cap = nel[1] - lb[2] (destroys nel)
// cap = nel[1] - lb[2] (destroys nel)
n2
=
*
res
;
n2
=
*
res
;
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
2
]))
{
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
)
-
v
=
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
)
-
...
@@ -1288,6 +1290,7 @@ slicearray:
...
@@ -1288,6 +1290,7 @@ slicearray:
// ary = old[0] + (lb[2] * width[4]) (destroys old)
// ary = old[0] + (lb[2] * width[4]) (destroys old)
n2
=
*
res
;
n2
=
*
res
;
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
4
]))
{
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
4
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
*
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
*
...
@@ -1311,6 +1314,7 @@ slicearray:
...
@@ -1311,6 +1314,7 @@ slicearray:
return
1
;
return
1
;
sliceslice:
sliceslice:
nochk
=
n
->
etype
;
// skip bounds checking
ntemp
.
op
=
OXXX
;
ntemp
.
op
=
OXXX
;
if
(
!
sleasy
(
n
->
list
->
n
->
right
))
{
if
(
!
sleasy
(
n
->
list
->
n
->
right
))
{
Node
*
n0
;
Node
*
n0
;
...
@@ -1340,11 +1344,13 @@ sliceslice:
...
@@ -1340,11 +1344,13 @@ sliceslice:
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
n2
.
type
=
types
[
TUINT32
];
cmpandthrow
(
&
nodes
[
1
],
&
n2
);
if
(
!
nochk
)
cmpandthrow
(
&
nodes
[
1
],
&
n2
);
// ret.nel = old.nel[0]-lb[1];
// ret.nel = old.nel[0]-lb[1];
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
N
);
regalloc
(
&
n1
,
types
[
TUINT32
],
N
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
@@ -1353,22 +1359,24 @@ sliceslice:
...
@@ -1353,22 +1359,24 @@ sliceslice:
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
regfree
(
&
n1
);
}
else
{
// old[lb:hb]
}
else
{
// old[lb:hb]
// if(hb[2] > old.cap[0]) goto throw;
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
n2
.
type
=
types
[
TUINT32
];
cmpandthrow
(
&
nodes
[
2
],
&
n2
);
if
(
!
nochk
)
{
// if(hb[2] > old.cap[0]) goto throw;
// if(lb[1] > hb[2]) goto throw;
cmpandthrow
(
&
nodes
[
2
],
&
n2
);
cmpandthrow
(
&
nodes
[
1
],
&
nodes
[
2
]);
// if(lb[1] > hb[2]) goto throw;
cmpandthrow
(
&
nodes
[
1
],
&
nodes
[
2
]);
}
// ret.len = hb[2]-lb[1]; (destroys hb[2])
// ret.len = hb[2]-lb[1]; (destroys hb[2])
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
1
]))
{
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
1
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
-
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
-
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
);
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
);
...
@@ -1387,6 +1395,7 @@ sliceslice:
...
@@ -1387,6 +1395,7 @@ sliceslice:
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
&
nodes
[
2
]);
regalloc
(
&
n1
,
types
[
TUINT32
],
&
nodes
[
2
]);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
@@ -1395,13 +1404,15 @@ sliceslice:
...
@@ -1395,13 +1404,15 @@ sliceslice:
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
regfree
(
&
n1
);
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
regalloc
(
&
n1
,
types
[
tptr
],
&
nodes
[
1
]);
regalloc
(
&
n1
,
types
[
tptr
],
&
nodes
[
1
]);
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
3
]))
{
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
3
]))
{
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n2
,
&
n1
);
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n2
,
&
n1
);
...
@@ -1418,6 +1429,7 @@ sliceslice:
...
@@ -1418,6 +1429,7 @@ sliceslice:
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n1
,
&
n2
);
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
regfree
(
&
n1
);
...
...
src/cmd/6g/gsubr.c
View file @
d6b29259
...
@@ -48,7 +48,7 @@ clearp(Prog *p)
...
@@ -48,7 +48,7 @@ clearp(Prog *p)
/*
/*
* generate and return proc with p->as = as,
* generate and return proc with p->as = as,
* linked into program.
pc is next instruction.
* linked into program. pc is next instruction.
*/
*/
Prog
*
Prog
*
prog
(
int
as
)
prog
(
int
as
)
...
@@ -330,11 +330,13 @@ regfree(Node *n)
...
@@ -330,11 +330,13 @@ regfree(Node *n)
{
{
int
i
;
int
i
;
if
(
n
->
op
==
ONAME
&&
iscomplex
[
n
->
type
->
etype
]
)
if
(
n
->
op
==
ONAME
)
return
;
return
;
if
(
n
->
op
!=
OREGISTER
&&
n
->
op
!=
OINDREG
)
if
(
n
->
op
!=
OREGISTER
&&
n
->
op
!=
OINDREG
)
fatal
(
"regfree: not a register"
);
fatal
(
"regfree: not a register"
);
i
=
n
->
val
.
u
.
reg
;
i
=
n
->
val
.
u
.
reg
;
if
(
i
==
D_SP
)
return
;
if
(
i
<
0
||
i
>=
sizeof
(
reg
))
if
(
i
<
0
||
i
>=
sizeof
(
reg
))
fatal
(
"regfree: reg out of range"
);
fatal
(
"regfree: reg out of range"
);
if
(
reg
[
i
]
<=
0
)
if
(
reg
[
i
]
<=
0
)
...
@@ -888,7 +890,7 @@ Prog*
...
@@ -888,7 +890,7 @@ Prog*
gins
(
int
as
,
Node
*
f
,
Node
*
t
)
gins
(
int
as
,
Node
*
f
,
Node
*
t
)
{
{
// Node nod;
// Node nod;
// int32 v
;
int32
w
;
Prog
*
p
;
Prog
*
p
;
Addr
af
,
at
;
Addr
af
,
at
;
...
@@ -933,6 +935,27 @@ gins(int as, Node *f, Node *t)
...
@@ -933,6 +935,27 @@ gins(int as, Node *f, Node *t)
p
->
to
=
at
;
p
->
to
=
at
;
if
(
debug
[
'g'
])
if
(
debug
[
'g'
])
print
(
"%P
\n
"
,
p
);
print
(
"%P
\n
"
,
p
);
w
=
0
;
switch
(
as
)
{
case
AMOVB
:
w
=
1
;
break
;
case
AMOVW
:
w
=
2
;
break
;
case
AMOVL
:
w
=
4
;
break
;
case
AMOVQ
:
w
=
8
;
break
;
}
if
(
w
!=
0
&&
f
!=
N
&&
(
af
.
width
>
w
||
at
.
width
>
w
))
{
fatal
(
"bad width: %P (%d, %d)
\n
"
,
p
,
af
.
width
,
at
.
width
);
}
return
p
;
return
p
;
}
}
...
@@ -947,7 +970,7 @@ checkoffset(Addr *a, int canemitcode)
...
@@ -947,7 +970,7 @@ checkoffset(Addr *a, int canemitcode)
fatal
(
"checkoffset %#llx, cannot emit code"
,
a
->
offset
);
fatal
(
"checkoffset %#llx, cannot emit code"
,
a
->
offset
);
// cannot rely on unmapped nil page at 0 to catch
// cannot rely on unmapped nil page at 0 to catch
// reference with large offset.
instead, emit explicit
// reference with large offset. instead, emit explicit
// test of 0(reg).
// test of 0(reg).
p
=
gins
(
ATESTB
,
nodintconst
(
0
),
N
);
p
=
gins
(
ATESTB
,
nodintconst
(
0
),
N
);
p
->
to
=
*
a
;
p
->
to
=
*
a
;
...
@@ -1106,8 +1129,9 @@ naddr(Node *n, Addr *a, int canemitcode)
...
@@ -1106,8 +1129,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// len(nil)
break
;
// len(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_nel
;
a
->
offset
+=
Array_nel
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
checkoffset
(
a
,
canemitcode
);
break
;
break
;
...
@@ -1117,8 +1141,9 @@ naddr(Node *n, Addr *a, int canemitcode)
...
@@ -1117,8 +1141,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// cap(nil)
break
;
// cap(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_cap
;
a
->
offset
+=
Array_cap
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_cap
<
unmappedzero
)
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_cap
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
checkoffset
(
a
,
canemitcode
);
break
;
break
;
...
@@ -1962,12 +1987,12 @@ oindex:
...
@@ -1962,12 +1987,12 @@ oindex:
if
(
o
&
OAddable
)
{
if
(
o
&
OAddable
)
{
n2
=
*
l
;
n2
=
*
l
;
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
TUINT64
];
n2
.
type
=
types
[
tptr
];
gmove
(
&
n2
,
reg
);
gmove
(
&
n2
,
reg
);
}
else
{
}
else
{
n2
=
*
reg
;
n2
=
*
reg
;
n2
.
xoffset
=
Array_array
;
n2
.
op
=
OINDREG
;
n2
.
op
=
OINDREG
;
n2
.
xoffset
=
Array_array
;
n2
.
type
=
types
[
tptr
];
n2
.
type
=
types
[
tptr
];
gmove
(
&
n2
,
reg
);
gmove
(
&
n2
,
reg
);
}
}
...
...
src/cmd/6g/reg.c
View file @
d6b29259
...
@@ -873,14 +873,17 @@ mkvar(Reg *r, Adr *a)
...
@@ -873,14 +873,17 @@ mkvar(Reg *r, Adr *a)
// if they overlaps, disable both
// if they overlaps, disable both
if
(
overlap
(
v
->
offset
,
v
->
width
,
o
,
w
))
{
if
(
overlap
(
v
->
offset
,
v
->
width
,
o
,
w
))
{
// print("disable overlap %s %d %d %d %d, %E != %E\n", s->name, v->offset, v->width, o, w, v->etype, et);
v
->
addr
=
1
;
v
->
addr
=
1
;
flag
=
1
;
flag
=
1
;
}
}
}
}
}
}
if
(
a
->
pun
)
if
(
a
->
pun
)
{
// print("disable pun %s\n", s->name);
flag
=
1
;
flag
=
1
;
}
switch
(
et
)
{
switch
(
et
)
{
case
0
:
case
0
:
case
TFUNC
:
case
TFUNC
:
...
...
src/cmd/8g/cgen.c
View file @
d6b29259
...
@@ -232,6 +232,7 @@ cgen(Node *n, Node *res)
...
@@ -232,6 +232,7 @@ cgen(Node *n, Node *res)
cgen
(
nl
,
res
);
cgen
(
nl
,
res
);
break
;
break
;
}
}
tempname
(
&
n2
,
n
->
type
);
tempname
(
&
n2
,
n
->
type
);
mgen
(
nl
,
&
n1
,
res
);
mgen
(
nl
,
&
n1
,
res
);
gmove
(
&
n1
,
&
n2
);
gmove
(
&
n1
,
&
n2
);
...
@@ -277,15 +278,10 @@ cgen(Node *n, Node *res)
...
@@ -277,15 +278,10 @@ cgen(Node *n, Node *res)
if
(
istype
(
nl
->
type
,
TSTRING
)
||
isslice
(
nl
->
type
))
{
if
(
istype
(
nl
->
type
,
TSTRING
)
||
isslice
(
nl
->
type
))
{
// both slice and string have len one pointer into the struct.
// both slice and string have len one pointer into the struct.
igen
(
nl
,
&
n1
,
res
);
igen
(
nl
,
&
n1
,
res
);
n1
.
op
=
OREGISTER
;
// was OINDREG
regalloc
(
&
n2
,
types
[
TUINT32
],
&
n1
);
n1
.
op
=
OINDREG
;
n1
.
type
=
types
[
TUINT32
];
n1
.
type
=
types
[
TUINT32
];
n1
.
xoffset
=
Array_nel
;
n1
.
xoffset
+=
Array_nel
;
gmove
(
&
n1
,
&
n2
);
gmove
(
&
n1
,
res
);
gmove
(
&
n2
,
res
);
regfree
(
&
n1
);
regfree
(
&
n1
);
regfree
(
&
n2
);
break
;
break
;
}
}
fatal
(
"cgen: OLEN: unknown type %lT"
,
nl
->
type
);
fatal
(
"cgen: OLEN: unknown type %lT"
,
nl
->
type
);
...
@@ -594,9 +590,10 @@ agen(Node *n, Node *res)
...
@@ -594,9 +590,10 @@ agen(Node *n, Node *res)
gmove
(
&
n1
,
&
n3
);
gmove
(
&
n1
,
&
n3
);
}
}
nodconst
(
&
n2
,
types
[
tptr
],
v
*
w
);
if
(
v
*
w
!=
0
)
{
gins
(
optoas
(
OADD
,
types
[
tptr
]),
&
n2
,
&
n3
);
nodconst
(
&
n2
,
types
[
tptr
],
v
*
w
);
gins
(
optoas
(
OADD
,
types
[
tptr
]),
&
n2
,
&
n3
);
}
gmove
(
&
n3
,
res
);
gmove
(
&
n3
,
res
);
regfree
(
&
n3
);
regfree
(
&
n3
);
break
;
break
;
...
@@ -729,7 +726,27 @@ void
...
@@ -729,7 +726,27 @@ void
igen
(
Node
*
n
,
Node
*
a
,
Node
*
res
)
igen
(
Node
*
n
,
Node
*
a
,
Node
*
res
)
{
{
Node
n1
;
Node
n1
;
Type
*
fp
;
Iter
flist
;
switch
(
n
->
op
)
{
case
ONAME
:
if
((
n
->
class
&
PHEAP
)
||
n
->
class
==
PPARAMREF
)
break
;
*
a
=
*
n
;
return
;
case
OCALLFUNC
:
fp
=
structfirst
(
&
flist
,
getoutarg
(
n
->
left
->
type
));
cgen_call
(
n
,
0
);
memset
(
a
,
0
,
sizeof
*
a
);
a
->
op
=
OINDREG
;
a
->
val
.
u
.
reg
=
D_SP
;
a
->
addable
=
1
;
a
->
xoffset
=
fp
->
width
;
a
->
type
=
n
->
type
;
return
;
}
// release register for now, to avoid
// release register for now, to avoid
// confusing tempname.
// confusing tempname.
if
(
res
!=
N
&&
res
->
op
==
OREGISTER
)
if
(
res
!=
N
&&
res
->
op
==
OREGISTER
)
...
@@ -919,6 +936,7 @@ bgen(Node *n, int true, Prog *to)
...
@@ -919,6 +936,7 @@ bgen(Node *n, int true, Prog *to)
n2
=
n1
;
n2
=
n1
;
n2
.
op
=
OINDREG
;
n2
.
op
=
OINDREG
;
n2
.
xoffset
=
Array_array
;
n2
.
xoffset
=
Array_array
;
n2
.
type
=
types
[
tptr
];
nodconst
(
&
tmp
,
types
[
tptr
],
0
);
nodconst
(
&
tmp
,
types
[
tptr
],
0
);
gins
(
optoas
(
OCMP
,
types
[
tptr
]),
&
n2
,
&
tmp
);
gins
(
optoas
(
OCMP
,
types
[
tptr
]),
&
n2
,
&
tmp
);
patch
(
gbranch
(
a
,
types
[
tptr
]),
to
);
patch
(
gbranch
(
a
,
types
[
tptr
]),
to
);
...
...
src/cmd/8g/ggen.c
View file @
d6b29259
...
@@ -915,7 +915,7 @@ cgen_inline(Node *n, Node *res)
...
@@ -915,7 +915,7 @@ cgen_inline(Node *n, Node *res)
Node
nodes
[
5
];
Node
nodes
[
5
];
Node
n1
,
n2
,
nres
,
ntemp
;
Node
n1
,
n2
,
nres
,
ntemp
;
vlong
v
;
vlong
v
;
int
i
,
narg
;
int
i
,
narg
,
nochk
;
if
(
n
->
op
!=
OCALLFUNC
)
if
(
n
->
op
!=
OCALLFUNC
)
goto
no
;
goto
no
;
...
@@ -953,6 +953,7 @@ slicearray:
...
@@ -953,6 +953,7 @@ slicearray:
// len = hb[3] - lb[2] (destroys hb)
// len = hb[3] - lb[2] (destroys hb)
n2
=
*
res
;
n2
=
*
res
;
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
3
])
&&
smallintconst
(
&
nodes
[
2
]))
{
if
(
smallintconst
(
&
nodes
[
3
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
3
].
val
.
u
.
xval
)
-
v
=
mpgetfix
(
nodes
[
3
].
val
.
u
.
xval
)
-
...
@@ -971,6 +972,7 @@ slicearray:
...
@@ -971,6 +972,7 @@ slicearray:
// cap = nel[1] - lb[2] (destroys nel)
// cap = nel[1] - lb[2] (destroys nel)
n2
=
*
res
;
n2
=
*
res
;
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
2
]))
{
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
2
]))
{
v
=
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
)
-
v
=
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
)
-
...
@@ -999,6 +1001,7 @@ slicearray:
...
@@ -999,6 +1001,7 @@ slicearray:
// ary = old[0] + (lb[2] * width[4]) (destroys old)
// ary = old[0] + (lb[2] * width[4]) (destroys old)
n2
=
*
res
;
n2
=
*
res
;
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
4
]))
{
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
4
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
*
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
*
...
@@ -1026,6 +1029,7 @@ slicearray:
...
@@ -1026,6 +1029,7 @@ slicearray:
sliceslice:
sliceslice:
if
(
!
fix64
(
n
->
list
,
narg
))
if
(
!
fix64
(
n
->
list
,
narg
))
goto
no
;
goto
no
;
nochk
=
n
->
etype
;
// skip bounds checking
ntemp
.
op
=
OXXX
;
ntemp
.
op
=
OXXX
;
if
(
!
sleasy
(
n
->
list
->
n
->
right
))
{
if
(
!
sleasy
(
n
->
list
->
n
->
right
))
{
Node
*
n0
;
Node
*
n0
;
...
@@ -1055,11 +1059,13 @@ sliceslice:
...
@@ -1055,11 +1059,13 @@ sliceslice:
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
n2
.
type
=
types
[
TUINT32
];
cmpandthrow
(
&
nodes
[
1
],
&
n2
);
if
(
!
nochk
)
cmpandthrow
(
&
nodes
[
1
],
&
n2
);
// ret.nel = old.nel[0]-lb[1];
// ret.nel = old.nel[0]-lb[1];
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
N
);
regalloc
(
&
n1
,
types
[
TUINT32
],
N
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
@@ -1068,22 +1074,25 @@ sliceslice:
...
@@ -1068,22 +1074,25 @@ sliceslice:
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
regfree
(
&
n1
);
}
else
{
// old[lb:hb]
}
else
{
// old[lb:hb]
// if(hb[2] > old.cap[0]) goto throw;
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
n2
.
type
=
types
[
TUINT32
];
cmpandthrow
(
&
nodes
[
2
],
&
n2
);
if
(
!
nochk
)
{
// if(hb[2] > old.cap[0]) goto throw;
// if(lb[1] > hb[2]) goto throw;
cmpandthrow
(
&
nodes
[
2
],
&
n2
);
cmpandthrow
(
&
nodes
[
1
],
&
nodes
[
2
]);
// if(lb[1] > hb[2]) goto throw;
cmpandthrow
(
&
nodes
[
1
],
&
nodes
[
2
]);
}
// ret.len = hb[2]-lb[1]; (destroys hb[2])
// ret.len = hb[2]-lb[1]; (destroys hb[2])
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_nel
;
n2
.
xoffset
+=
Array_nel
;
n2
.
type
=
types
[
TUINT32
];
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
1
]))
{
if
(
smallintconst
(
&
nodes
[
2
])
&&
smallintconst
(
&
nodes
[
1
]))
{
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
-
v
=
mpgetfix
(
nodes
[
2
].
val
.
u
.
xval
)
-
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
);
mpgetfix
(
nodes
[
1
].
val
.
u
.
xval
);
...
@@ -1102,6 +1111,7 @@ sliceslice:
...
@@ -1102,6 +1111,7 @@ sliceslice:
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
// ret.cap = old.cap[0]-lb[1]; (uses hb[2])
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
regalloc
(
&
n1
,
types
[
TUINT32
],
&
nodes
[
2
]);
regalloc
(
&
n1
,
types
[
TUINT32
],
&
nodes
[
2
]);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n2
,
&
n1
);
...
@@ -1110,12 +1120,14 @@ sliceslice:
...
@@ -1110,12 +1120,14 @@ sliceslice:
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_cap
;
n2
.
xoffset
+=
Array_cap
;
n2
.
type
=
types
[
TUINT32
];
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
gins
(
optoas
(
OAS
,
types
[
TUINT32
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
regfree
(
&
n1
);
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
// ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1])
n2
=
nodes
[
0
];
n2
=
nodes
[
0
];
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
regalloc
(
&
n1
,
types
[
tptr
],
&
nodes
[
1
]);
regalloc
(
&
n1
,
types
[
tptr
],
&
nodes
[
1
]);
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
3
]))
{
if
(
smallintconst
(
&
nodes
[
1
])
&&
smallintconst
(
&
nodes
[
3
]))
{
...
@@ -1135,6 +1147,7 @@ sliceslice:
...
@@ -1135,6 +1147,7 @@ sliceslice:
n2
=
nres
;
n2
=
nres
;
n2
.
xoffset
+=
Array_array
;
n2
.
xoffset
+=
Array_array
;
n2
.
type
=
types
[
tptr
];
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n1
,
&
n2
);
gins
(
optoas
(
OAS
,
types
[
tptr
]),
&
n1
,
&
n2
);
regfree
(
&
n1
);
regfree
(
&
n1
);
...
...
src/cmd/8g/gsubr.c
View file @
d6b29259
...
@@ -698,7 +698,6 @@ ginit(void)
...
@@ -698,7 +698,6 @@ ginit(void)
reg
[
i
]
=
1
;
reg
[
i
]
=
1
;
for
(
i
=
D_AL
;
i
<=
D_DI
;
i
++
)
for
(
i
=
D_AL
;
i
<=
D_DI
;
i
++
)
reg
[
i
]
=
0
;
reg
[
i
]
=
0
;
for
(
i
=
0
;
i
<
nelem
(
resvd
);
i
++
)
for
(
i
=
0
;
i
<
nelem
(
resvd
);
i
++
)
reg
[
resvd
[
i
]]
++
;
reg
[
resvd
[
i
]]
++
;
}
}
...
@@ -789,6 +788,8 @@ err:
...
@@ -789,6 +788,8 @@ err:
return
;
return
;
out:
out:
if
(
i
==
D_SP
)
print
(
"alloc SP
\n
"
);
if
(
reg
[
i
]
==
0
)
{
if
(
reg
[
i
]
==
0
)
{
regpc
[
i
]
=
(
ulong
)
__builtin_return_address
(
0
);
regpc
[
i
]
=
(
ulong
)
__builtin_return_address
(
0
);
if
(
i
==
D_AX
||
i
==
D_CX
||
i
==
D_DX
||
i
==
D_SP
)
{
if
(
i
==
D_AX
||
i
==
D_CX
||
i
==
D_DX
||
i
==
D_SP
)
{
...
@@ -804,10 +805,14 @@ void
...
@@ -804,10 +805,14 @@ void
regfree
(
Node
*
n
)
regfree
(
Node
*
n
)
{
{
int
i
;
int
i
;
if
(
n
->
op
==
ONAME
)
return
;
if
(
n
->
op
!=
OREGISTER
&&
n
->
op
!=
OINDREG
)
if
(
n
->
op
!=
OREGISTER
&&
n
->
op
!=
OINDREG
)
fatal
(
"regfree: not a register"
);
fatal
(
"regfree: not a register"
);
i
=
n
->
val
.
u
.
reg
;
i
=
n
->
val
.
u
.
reg
;
if
(
i
==
D_SP
)
return
;
if
(
i
<
0
||
i
>=
sizeof
(
reg
))
if
(
i
<
0
||
i
>=
sizeof
(
reg
))
fatal
(
"regfree: reg out of range"
);
fatal
(
"regfree: reg out of range"
);
if
(
reg
[
i
]
<=
0
)
if
(
reg
[
i
]
<=
0
)
...
@@ -1129,6 +1134,9 @@ gmove(Node *f, Node *t)
...
@@ -1129,6 +1134,9 @@ gmove(Node *f, Node *t)
case
CASE
(
TINT8
,
TUINT8
):
case
CASE
(
TINT8
,
TUINT8
):
case
CASE
(
TUINT8
,
TINT8
):
case
CASE
(
TUINT8
,
TINT8
):
case
CASE
(
TUINT8
,
TUINT8
):
case
CASE
(
TUINT8
,
TUINT8
):
a
=
AMOVB
;
break
;
case
CASE
(
TINT16
,
TINT8
):
// truncate
case
CASE
(
TINT16
,
TINT8
):
// truncate
case
CASE
(
TUINT16
,
TINT8
):
case
CASE
(
TUINT16
,
TINT8
):
case
CASE
(
TINT32
,
TINT8
):
case
CASE
(
TINT32
,
TINT8
):
...
@@ -1138,7 +1146,7 @@ gmove(Node *f, Node *t)
...
@@ -1138,7 +1146,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TINT32
,
TUINT8
):
case
CASE
(
TINT32
,
TUINT8
):
case
CASE
(
TUINT32
,
TUINT8
):
case
CASE
(
TUINT32
,
TUINT8
):
a
=
AMOVB
;
a
=
AMOVB
;
break
;
goto
rsrc
;
case
CASE
(
TINT64
,
TINT8
):
// truncate low word
case
CASE
(
TINT64
,
TINT8
):
// truncate low word
case
CASE
(
TUINT64
,
TINT8
):
case
CASE
(
TUINT64
,
TINT8
):
...
@@ -1146,7 +1154,7 @@ gmove(Node *f, Node *t)
...
@@ -1146,7 +1154,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TUINT64
,
TUINT8
):
case
CASE
(
TUINT64
,
TUINT8
):
split64
(
f
,
&
flo
,
&
fhi
);
split64
(
f
,
&
flo
,
&
fhi
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
g
ins
(
AMOVB
,
&
flo
,
&
r1
);
g
move
(
&
flo
,
&
r1
);
gins
(
AMOVB
,
&
r1
,
t
);
gins
(
AMOVB
,
&
r1
,
t
);
splitclean
();
splitclean
();
return
;
return
;
...
@@ -1155,12 +1163,15 @@ gmove(Node *f, Node *t)
...
@@ -1155,12 +1163,15 @@ gmove(Node *f, Node *t)
case
CASE
(
TINT16
,
TUINT16
):
case
CASE
(
TINT16
,
TUINT16
):
case
CASE
(
TUINT16
,
TINT16
):
case
CASE
(
TUINT16
,
TINT16
):
case
CASE
(
TUINT16
,
TUINT16
):
case
CASE
(
TUINT16
,
TUINT16
):
a
=
AMOVW
;
break
;
case
CASE
(
TINT32
,
TINT16
):
// truncate
case
CASE
(
TINT32
,
TINT16
):
// truncate
case
CASE
(
TUINT32
,
TINT16
):
case
CASE
(
TUINT32
,
TINT16
):
case
CASE
(
TINT32
,
TUINT16
):
case
CASE
(
TINT32
,
TUINT16
):
case
CASE
(
TUINT32
,
TUINT16
):
case
CASE
(
TUINT32
,
TUINT16
):
a
=
AMOVW
;
a
=
AMOVW
;
break
;
goto
rsrc
;
case
CASE
(
TINT64
,
TINT16
):
// truncate low word
case
CASE
(
TINT64
,
TINT16
):
// truncate low word
case
CASE
(
TUINT64
,
TINT16
):
case
CASE
(
TUINT64
,
TINT16
):
...
@@ -1168,7 +1179,7 @@ gmove(Node *f, Node *t)
...
@@ -1168,7 +1179,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TUINT64
,
TUINT16
):
case
CASE
(
TUINT64
,
TUINT16
):
split64
(
f
,
&
flo
,
&
fhi
);
split64
(
f
,
&
flo
,
&
fhi
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
g
ins
(
AMOVW
,
&
flo
,
&
r1
);
g
move
(
&
flo
,
&
r1
);
gins
(
AMOVW
,
&
r1
,
t
);
gins
(
AMOVW
,
&
r1
,
t
);
splitclean
();
splitclean
();
return
;
return
;
...
@@ -1186,7 +1197,7 @@ gmove(Node *f, Node *t)
...
@@ -1186,7 +1197,7 @@ gmove(Node *f, Node *t)
case
CASE
(
TUINT64
,
TUINT32
):
case
CASE
(
TUINT64
,
TUINT32
):
split64
(
f
,
&
flo
,
&
fhi
);
split64
(
f
,
&
flo
,
&
fhi
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
nodreg
(
&
r1
,
t
->
type
,
D_AX
);
g
ins
(
AMOVL
,
&
flo
,
&
r1
);
g
move
(
&
flo
,
&
r1
);
gins
(
AMOVL
,
&
r1
,
t
);
gins
(
AMOVL
,
&
r1
,
t
);
splitclean
();
splitclean
();
return
;
return
;
...
@@ -1340,14 +1351,14 @@ gmove(Node *f, Node *t)
...
@@ -1340,14 +1351,14 @@ gmove(Node *f, Node *t)
case
TUINT8
:
case
TUINT8
:
gins
(
ATESTL
,
ncon
(
0xffffff00
),
&
t1
);
gins
(
ATESTL
,
ncon
(
0xffffff00
),
&
t1
);
p1
=
gbranch
(
AJEQ
,
T
);
p1
=
gbranch
(
AJEQ
,
T
);
gins
(
AMOV
B
,
ncon
(
0
),
&
t1
);
gins
(
AMOV
L
,
ncon
(
0
),
&
t1
);
patch
(
p1
,
pc
);
patch
(
p1
,
pc
);
gmove
(
&
t1
,
t
);
gmove
(
&
t1
,
t
);
break
;
break
;
case
TUINT16
:
case
TUINT16
:
gins
(
ATESTL
,
ncon
(
0xffff0000
),
&
t1
);
gins
(
ATESTL
,
ncon
(
0xffff0000
),
&
t1
);
p1
=
gbranch
(
AJEQ
,
T
);
p1
=
gbranch
(
AJEQ
,
T
);
gins
(
AMOV
W
,
ncon
(
0
),
&
t1
);
gins
(
AMOV
L
,
ncon
(
0
),
&
t1
);
patch
(
p1
,
pc
);
patch
(
p1
,
pc
);
gmove
(
&
t1
,
t
);
gmove
(
&
t1
,
t
);
break
;
break
;
...
@@ -1571,6 +1582,14 @@ gmove(Node *f, Node *t)
...
@@ -1571,6 +1582,14 @@ gmove(Node *f, Node *t)
gins
(
a
,
f
,
t
);
gins
(
a
,
f
,
t
);
return
;
return
;
rsrc:
// requires register source
regalloc
(
&
r1
,
f
->
type
,
t
);
gmove
(
f
,
&
r1
);
gins
(
a
,
&
r1
,
t
);
regfree
(
&
r1
);
return
;
rdst:
rdst:
// requires register destination
// requires register destination
regalloc
(
&
r1
,
t
->
type
,
t
);
regalloc
(
&
r1
,
t
->
type
,
t
);
...
@@ -1623,6 +1642,7 @@ gins(int as, Node *f, Node *t)
...
@@ -1623,6 +1642,7 @@ gins(int as, Node *f, Node *t)
{
{
Prog
*
p
;
Prog
*
p
;
Addr
af
,
at
;
Addr
af
,
at
;
int
w
;
if
(
as
==
AFMOVF
&&
f
&&
f
->
op
==
OREGISTER
&&
t
&&
t
->
op
==
OREGISTER
)
if
(
as
==
AFMOVF
&&
f
&&
f
->
op
==
OREGISTER
&&
t
&&
t
->
op
==
OREGISTER
)
fatal
(
"gins MOVF reg, reg"
);
fatal
(
"gins MOVF reg, reg"
);
...
@@ -1648,6 +1668,26 @@ gins(int as, Node *f, Node *t)
...
@@ -1648,6 +1668,26 @@ gins(int as, Node *f, Node *t)
p
->
to
=
at
;
p
->
to
=
at
;
if
(
debug
[
'g'
])
if
(
debug
[
'g'
])
print
(
"%P
\n
"
,
p
);
print
(
"%P
\n
"
,
p
);
w
=
0
;
switch
(
as
)
{
case
AMOVB
:
w
=
1
;
break
;
case
AMOVW
:
w
=
2
;
break
;
case
AMOVL
:
w
=
4
;
break
;
}
if
(
1
&&
w
!=
0
&&
f
!=
N
&&
(
af
.
width
>
w
||
at
.
width
>
w
))
{
dump
(
"bad width from:"
,
f
);
dump
(
"bad width to:"
,
t
);
fatal
(
"bad width: %P (%d, %d)
\n
"
,
p
,
af
.
width
,
at
.
width
);
}
return
p
;
return
p
;
}
}
...
@@ -1799,8 +1839,9 @@ naddr(Node *n, Addr *a, int canemitcode)
...
@@ -1799,8 +1839,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// len(nil)
break
;
// len(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_nel
;
a
->
offset
+=
Array_nel
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
checkoffset
(
a
,
canemitcode
);
break
;
break
;
...
@@ -1810,8 +1851,9 @@ naddr(Node *n, Addr *a, int canemitcode)
...
@@ -1810,8 +1851,9 @@ naddr(Node *n, Addr *a, int canemitcode)
naddr
(
n
->
left
,
a
,
canemitcode
);
naddr
(
n
->
left
,
a
,
canemitcode
);
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
if
(
a
->
type
==
D_CONST
&&
a
->
offset
==
0
)
break
;
// cap(nil)
break
;
// cap(nil)
a
->
etype
=
TUINT
;
a
->
etype
=
TUINT
32
;
a
->
offset
+=
Array_cap
;
a
->
offset
+=
Array_cap
;
a
->
width
=
4
;
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
if
(
a
->
offset
>=
unmappedzero
&&
a
->
offset
-
Array_nel
<
unmappedzero
)
checkoffset
(
a
,
canemitcode
);
checkoffset
(
a
,
canemitcode
);
break
;
break
;
...
...
src/cmd/gc/builtin.c.boot
View file @
d6b29259
char *runtimeimport =
char *runtimeimport =
"package runtime\n"
"package runtime\n"
"import runtime \"runtime\"\n"
"func \"\".new (? int32) *any\n"
"func \"\".new (? int32) *any\n"
"func \"\".panicindex ()\n"
"func \"\".panicindex ()\n"
"func \"\".panicslice ()\n"
"func \"\".panicslice ()\n"
...
@@ -81,6 +82,7 @@ char *runtimeimport =
...
@@ -81,6 +82,7 @@ char *runtimeimport =
"func \"\".selectgo (sel *uint8)\n"
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
"func \"\".block ()\n"
"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
"func \"\".growslice (typ *uint8, old []any, cap int64) []any\n"
"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
...
@@ -98,6 +100,7 @@ char *runtimeimport =
...
@@ -98,6 +100,7 @@ char *runtimeimport =
"$$\n";
"$$\n";
char *unsafeimport =
char *unsafeimport =
"package unsafe\n"
"package unsafe\n"
"import runtime \"runtime\"\n"
"type \"\".Pointer uintptr\n"
"type \"\".Pointer uintptr\n"
"func \"\".Offsetof (? any) int\n"
"func \"\".Offsetof (? any) int\n"
"func \"\".Sizeof (? any) int\n"
"func \"\".Sizeof (? any) int\n"
...
...
src/cmd/gc/runtime.go
View file @
d6b29259
...
@@ -110,6 +110,7 @@ func selectgo(sel *byte)
...
@@ -110,6 +110,7 @@ func selectgo(sel *byte)
func
block
()
func
block
()
func
makeslice
(
typ
*
byte
,
nel
int64
,
cap
int64
)
(
ary
[]
any
)
func
makeslice
(
typ
*
byte
,
nel
int64
,
cap
int64
)
(
ary
[]
any
)
func
growslice
(
typ
*
byte
,
old
[]
any
,
n
int64
)
(
ary
[]
any
)
func
sliceslice1
(
old
[]
any
,
lb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
sliceslice1
(
old
[]
any
,
lb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
sliceslice
(
old
[]
any
,
lb
uint64
,
hb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
sliceslice
(
old
[]
any
,
lb
uint64
,
hb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
slicearray
(
old
*
any
,
nel
uint64
,
lb
uint64
,
hb
uint64
,
width
uint64
)
(
ary
[]
any
)
func
slicearray
(
old
*
any
,
nel
uint64
,
lb
uint64
,
hb
uint64
,
width
uint64
)
(
ary
[]
any
)
...
...
src/cmd/gc/subr.c
View file @
d6b29259
...
@@ -1073,6 +1073,9 @@ Jconv(Fmt *fp)
...
@@ -1073,6 +1073,9 @@ Jconv(Fmt *fp)
if
(
n
->
implicit
!=
0
)
if
(
n
->
implicit
!=
0
)
fmtprint
(
fp
,
" implicit(%d)"
,
n
->
implicit
);
fmtprint
(
fp
,
" implicit(%d)"
,
n
->
implicit
);
if
(
n
->
pun
!=
0
)
fmtprint
(
fp
,
" pun(%d)"
,
n
->
pun
);
return
0
;
return
0
;
}
}
...
@@ -1141,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
...
@@ -1141,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
Type
*
t1
;
Type
*
t1
;
Sym
*
s
;
Sym
*
s
;
if
(
debug
[
'r'
])
{
if
(
0
&&
debug
[
'r'
])
{
debug
[
'r'
]
=
0
;
debug
[
'r'
]
=
0
;
fmtprint
(
fp
,
"%T (orig=%T)"
,
t
,
t
->
orig
);
fmtprint
(
fp
,
"%T (orig=%T)"
,
t
,
t
->
orig
);
debug
[
'r'
]
=
1
;
debug
[
'r'
]
=
1
;
...
@@ -3109,7 +3112,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
...
@@ -3109,7 +3112,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
Type
*
tpad
;
Type
*
tpad
;
int
isddd
;
int
isddd
;
if
(
debug
[
'r'
])
if
(
0
&&
debug
[
'r'
])
print
(
"genwrapper rcvrtype=%T method=%T newnam=%S
\n
"
,
print
(
"genwrapper rcvrtype=%T method=%T newnam=%S
\n
"
,
rcvr
,
method
,
newnam
);
rcvr
,
method
,
newnam
);
...
@@ -3163,7 +3166,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
...
@@ -3163,7 +3166,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn
->
nbody
=
list1
(
n
);
fn
->
nbody
=
list1
(
n
);
}
}
if
(
debug
[
'r'
])
if
(
0
&&
debug
[
'r'
])
dumplist
(
"genwrapper body"
,
fn
->
nbody
);
dumplist
(
"genwrapper body"
,
fn
->
nbody
);
funcbody
(
fn
);
funcbody
(
fn
);
...
@@ -3258,8 +3261,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
...
@@ -3258,8 +3261,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
// the method does not exist for value types.
// the method does not exist for value types.
rcvr
=
getthisx
(
tm
->
type
)
->
type
->
type
;
rcvr
=
getthisx
(
tm
->
type
)
->
type
->
type
;
if
(
isptr
[
rcvr
->
etype
]
&&
!
isptr
[
t0
->
etype
]
&&
!
followptr
&&
!
isifacemethod
(
tm
->
type
))
{
if
(
isptr
[
rcvr
->
etype
]
&&
!
isptr
[
t0
->
etype
]
&&
!
followptr
&&
!
isifacemethod
(
tm
->
type
))
{
if
(
debug
[
'r'
])
if
(
0
&&
debug
[
'r'
])
yyerror
(
"interface pointer mismatch"
);
yyerror
(
"interface pointer mismatch"
);
*
m
=
im
;
*
m
=
im
;
*
samename
=
nil
;
*
samename
=
nil
;
*
ptr
=
1
;
*
ptr
=
1
;
...
...
src/cmd/gc/walk.c
View file @
d6b29259
...
@@ -18,12 +18,14 @@ static NodeList* paramstoheap(Type **argin, int out);
...
@@ -18,12 +18,14 @@ static NodeList* paramstoheap(Type **argin, int out);
static
NodeList
*
reorder1
(
NodeList
*
);
static
NodeList
*
reorder1
(
NodeList
*
);
static
NodeList
*
reorder3
(
NodeList
*
);
static
NodeList
*
reorder3
(
NodeList
*
);
static
Node
*
addstr
(
Node
*
,
NodeList
**
);
static
Node
*
addstr
(
Node
*
,
NodeList
**
);
static
Node
*
appendslice
(
Node
*
,
NodeList
**
);
static
Node
*
append
(
Node
*
,
NodeList
**
);
static
Node
*
append
(
Node
*
,
NodeList
**
);
static
int
oasappend
(
Node
**
,
NodeList
**
);
static
NodeList
*
walkdefstack
;
static
NodeList
*
walkdefstack
;
// can this code branch reach the end
// can this code branch reach the end
// without an un
dcont
itional RETURN
// without an un
cond
itional RETURN
// this is hard, so it is conservative
// this is hard, so it is conservative
static
int
static
int
walkret
(
NodeList
*
l
)
walkret
(
NodeList
*
l
)
...
@@ -805,18 +807,20 @@ walkexpr(Node **np, NodeList **init)
...
@@ -805,18 +807,20 @@ walkexpr(Node **np, NodeList **init)
n
->
ninit
=
nil
;
n
->
ninit
=
nil
;
walkexpr
(
&
n
->
left
,
init
);
walkexpr
(
&
n
->
left
,
init
);
n
->
left
=
safeexpr
(
n
->
left
,
init
);
n
->
left
=
safeexpr
(
n
->
left
,
init
);
if
(
oaslit
(
n
,
init
))
if
(
oaslit
(
n
,
init
))
goto
ret
;
goto
ret
;
walkexpr
(
&
n
->
right
,
init
);
l
=
n
->
left
;
if
(
oasappend
(
&
n
,
init
))
r
=
n
->
right
;
if
(
l
==
N
||
r
==
N
)
goto
ret
;
goto
ret
;
r
=
ascompatee1
(
n
->
op
,
l
,
r
,
init
);
if
(
r
!=
N
)
{
walkexpr
(
&
n
->
right
,
init
);
if
(
n
->
left
!=
N
&&
n
->
right
!=
N
)
{
r
=
convas
(
nod
(
OAS
,
n
->
left
,
n
->
right
),
init
);
r
->
dodata
=
n
->
dodata
;
r
->
dodata
=
n
->
dodata
;
n
=
r
;
n
=
r
;
}
}
goto
ret
;
goto
ret
;
case
OAS2
:
case
OAS2
:
...
@@ -1134,6 +1138,7 @@ walkexpr(Node **np, NodeList **init)
...
@@ -1134,6 +1138,7 @@ walkexpr(Node **np, NodeList **init)
case
OINDEXMAP
:
case
OINDEXMAP
:
if
(
n
->
etype
==
1
)
if
(
n
->
etype
==
1
)
goto
ret
;
goto
ret
;
t
=
n
->
left
->
type
;
t
=
n
->
left
->
type
;
n
=
mkcall1
(
mapfn
(
"mapaccess1"
,
t
),
t
->
type
,
init
,
n
->
left
,
n
->
right
);
n
=
mkcall1
(
mapfn
(
"mapaccess1"
,
t
),
t
->
type
,
init
,
n
->
left
,
n
->
right
);
goto
ret
;
goto
ret
;
...
@@ -1188,6 +1193,7 @@ walkexpr(Node **np, NodeList **init)
...
@@ -1188,6 +1193,7 @@ walkexpr(Node **np, NodeList **init)
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
// sliceslice1(old []any, lb uint64, width uint64) (ary []any)
// sliceslice1(old []any, lb uint64, width uint64) (ary []any)
t
=
n
->
type
;
t
=
n
->
type
;
et
=
n
->
etype
;
if
(
n
->
right
->
left
==
N
)
if
(
n
->
right
->
left
==
N
)
l
=
nodintconst
(
0
);
l
=
nodintconst
(
0
);
else
else
...
@@ -1210,6 +1216,7 @@ walkexpr(Node **np, NodeList **init)
...
@@ -1210,6 +1216,7 @@ walkexpr(Node **np, NodeList **init)
l
,
l
,
nodintconst
(
t
->
type
->
width
));
nodintconst
(
t
->
type
->
width
));
}
}
n
->
etype
=
et
;
// preserve no-typecheck flag from OSLICE to the slice* call.
goto
ret
;
goto
ret
;
slicearray:
slicearray:
...
@@ -1332,7 +1339,10 @@ walkexpr(Node **np, NodeList **init)
...
@@ -1332,7 +1339,10 @@ walkexpr(Node **np, NodeList **init)
goto
ret
;
goto
ret
;
case
OAPPEND
:
case
OAPPEND
:
n
=
append
(
n
,
init
);
if
(
n
->
isddd
)
n
=
appendslice
(
n
,
init
);
else
n
=
append
(
n
,
init
);
goto
ret
;
goto
ret
;
case
OCOPY
:
case
OCOPY
:
...
@@ -1953,23 +1963,18 @@ callnew(Type *t)
...
@@ -1953,23 +1963,18 @@ callnew(Type *t)
static
Node
*
static
Node
*
convas
(
Node
*
n
,
NodeList
**
init
)
convas
(
Node
*
n
,
NodeList
**
init
)
{
{
Node
*
l
,
*
r
;
Type
*
lt
,
*
rt
;
Type
*
lt
,
*
rt
;
if
(
n
->
op
!=
OAS
)
if
(
n
->
op
!=
OAS
)
fatal
(
"convas: not OAS %O"
,
n
->
op
);
fatal
(
"convas: not OAS %O"
,
n
->
op
);
n
->
typecheck
=
1
;
lt
=
T
;
n
->
typecheck
=
1
;
rt
=
T
;
l
=
n
->
left
;
if
(
n
->
left
==
N
||
n
->
right
==
N
)
r
=
n
->
right
;
if
(
l
==
N
||
r
==
N
)
goto
out
;
goto
out
;
lt
=
l
->
type
;
lt
=
n
->
left
->
type
;
rt
=
r
->
type
;
rt
=
n
->
right
->
type
;
if
(
lt
==
T
||
rt
==
T
)
if
(
lt
==
T
||
rt
==
T
)
goto
out
;
goto
out
;
...
@@ -1987,7 +1992,7 @@ convas(Node *n, NodeList **init)
...
@@ -1987,7 +1992,7 @@ convas(Node *n, NodeList **init)
if
(
eqtype
(
lt
,
rt
))
if
(
eqtype
(
lt
,
rt
))
goto
out
;
goto
out
;
n
->
right
=
assignconv
(
r
,
lt
,
"assignment"
);
n
->
right
=
assignconv
(
n
->
right
,
lt
,
"assignment"
);
walkexpr
(
&
n
->
right
,
init
);
walkexpr
(
&
n
->
right
,
init
);
out:
out:
...
@@ -2364,21 +2369,24 @@ addstr(Node *n, NodeList **init)
...
@@ -2364,21 +2369,24 @@ addstr(Node *n, NodeList **init)
return
r
;
return
r
;
}
}
static
Node
*
appendslice
(
Node
*
n
,
NodeList
**
init
)
{
Node
*
f
;
f
=
syslook
(
"appendslice"
,
1
);
argtype
(
f
,
n
->
type
);
argtype
(
f
,
n
->
type
->
type
);
argtype
(
f
,
n
->
type
);
return
mkcall1
(
f
,
n
->
type
,
init
,
typename
(
n
->
type
),
n
->
list
->
n
,
n
->
list
->
next
->
n
);
}
static
Node
*
static
Node
*
append
(
Node
*
n
,
NodeList
**
init
)
append
(
Node
*
n
,
NodeList
**
init
)
{
{
int
i
,
j
;
int
i
,
j
;
Node
*
f
,
*
r
;
Node
*
f
,
*
r
;
NodeList
*
in
,
*
args
;
NodeList
*
in
,
*
args
;
if
(
n
->
isddd
)
{
f
=
syslook
(
"appendslice"
,
1
);
argtype
(
f
,
n
->
type
);
argtype
(
f
,
n
->
type
->
type
);
argtype
(
f
,
n
->
type
);
r
=
mkcall1
(
f
,
n
->
type
,
init
,
typename
(
n
->
type
),
n
->
list
->
n
,
n
->
list
->
next
->
n
);
return
r
;
}
j
=
count
(
n
->
list
)
-
1
;
j
=
count
(
n
->
list
)
-
1
;
f
=
syslook
(
"append"
,
1
);
f
=
syslook
(
"append"
,
1
);
...
@@ -2404,3 +2412,77 @@ append(Node *n, NodeList **init)
...
@@ -2404,3 +2412,77 @@ append(Node *n, NodeList **init)
return
r
;
return
r
;
}
}
// expand s = append(s, a [, b]* ) to
//
// const argc = len(args) - 1
// if cap(s) - len(s) < argc {
// s = growslice(s, argc)
// }
// n := len(s)
// s = s[:n+argc]
// s[n] = a
// s[n+1] = b
// ...
//
static
int
oasappend
(
Node
**
np
,
NodeList
**
init
)
{
NodeList
*
l
,
*
a
;
Node
*
n
,
*
ns
,
*
nn
,
*
na
,
*
nx
,
*
fn
;
int
argc
;
n
=
*
np
;
// Check that it's an assignment of the form s = append(s, elem), where s is ONAME.
if
(
n
->
right
==
N
||
n
->
right
->
op
!=
OAPPEND
||
n
->
right
->
isddd
||
n
->
left
==
N
||
n
->
left
->
op
!=
ONAME
||
n
->
left
!=
n
->
right
->
list
->
n
)
return
0
;
ns
=
cheapexpr
(
n
->
left
,
init
);
walkexprlistsafe
(
n
->
right
->
list
,
init
);
argc
=
count
(
n
->
right
->
list
)
-
1
;
if
(
argc
<
1
)
{
n
->
op
=
OEMPTY
;
return
1
;
}
na
=
nodintconst
(
argc
);
// const argc
nx
=
nod
(
OIF
,
N
,
N
);
// if cap(s) - len(s) < argc
nx
->
lineno
=
n
->
lineno
;
nx
->
ntest
=
nod
(
OLT
,
nod
(
OSUB
,
nod
(
OCAP
,
ns
,
N
),
nod
(
OLEN
,
ns
,
N
)),
na
);
fn
=
syslook
(
"growslice"
,
1
);
// growslice(<type>, old []T, n int64) (ret []T)
argtype
(
fn
,
ns
->
type
->
type
);
// 1 old []any
argtype
(
fn
,
ns
->
type
->
type
);
// 2 ret []any
nx
->
nbody
=
list1
(
nod
(
OAS
,
ns
,
mkcall1
(
fn
,
ns
->
type
,
&
nx
->
ninit
,
typename
(
ns
->
type
),
ns
,
conv
(
na
,
types
[
TINT64
]))));
l
=
list1
(
nx
);
nn
=
nod
(
OXXX
,
N
,
N
);
// var n
tempname
(
nn
,
types
[
TINT
]);
l
=
list
(
l
,
nod
(
OAS
,
nn
,
nod
(
OLEN
,
ns
,
N
)));
// n = len(s)
nx
=
nod
(
OSLICE
,
ns
,
nod
(
OKEY
,
N
,
nod
(
OADD
,
nn
,
na
)));
// ...s[:n+argc]
nx
->
etype
=
1
;
// disable bounds check
l
=
list
(
l
,
nod
(
OAS
,
ns
,
nx
));
// s = s[:n+argc]
for
(
a
=
n
->
right
->
list
->
next
;
a
!=
nil
;
a
=
a
->
next
)
{
nx
=
nod
(
OINDEX
,
ns
,
nn
);
// s[n] ...
nx
->
etype
=
1
;
// disable bounds check
l
=
list
(
l
,
nod
(
OAS
,
nx
,
a
->
n
));
// s[n] = arg
if
(
a
->
next
!=
nil
)
l
=
list
(
l
,
nod
(
OAS
,
nn
,
nod
(
OADD
,
nn
,
nodintconst
(
1
))));
// n = n + 1
}
typechecklist
(
l
,
Etop
);
*
np
=
liststmt
(
l
);
walkstmt
(
np
);
return
1
;
}
src/pkg/runtime/append_test.go
0 → 100644
View file @
d6b29259
// Copyright 2011 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.
package
runtime_test
import
"testing"
const
N
=
20
func
BenchmarkAppend
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
x
:=
make
([]
int
,
0
,
N
)
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
x
=
x
[
0
:
0
]
for
j
:=
0
;
j
<
N
;
j
++
{
x
=
append
(
x
,
j
)
}
}
}
func
BenchmarkAppendSpecialCase
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
x
:=
make
([]
int
,
0
,
N
)
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
x
=
x
[
0
:
0
]
for
j
:=
0
;
j
<
N
;
j
++
{
if
len
(
x
)
<
cap
(
x
)
{
x
=
x
[
:
len
(
x
)
+
1
]
x
[
len
(
x
)
-
1
]
=
j
}
else
{
x
=
append
(
x
,
j
)
}
}
}
}
var
x
=
make
([]
int
,
0
,
10
)
func
f
()
int
{
x
[
:
1
][
0
]
=
3
return
2
}
func
TestSideEffectOrder
(
t
*
testing
.
T
)
{
x
=
append
(
x
,
1
,
f
())
if
x
[
0
]
!=
1
||
x
[
1
]
!=
2
{
t
.
Error
(
"append failed: "
,
x
[
0
],
x
[
1
])
}
}
src/pkg/runtime/slice.c
View file @
d6b29259
...
@@ -9,6 +9,8 @@
...
@@ -9,6 +9,8 @@
static
int32
debug
=
0
;
static
int32
debug
=
0
;
static
void
makeslice1
(
SliceType
*
,
int32
,
int32
,
Slice
*
);
static
void
makeslice1
(
SliceType
*
,
int32
,
int32
,
Slice
*
);
static
void
growslice1
(
SliceType
*
,
Slice
,
int32
,
Slice
*
);
static
void
appendslice1
(
SliceType
*
,
Slice
,
Slice
,
Slice
*
);
void
runtime
·
slicecopy
(
Slice
to
,
Slice
fm
,
uintptr
width
,
int32
ret
);
void
runtime
·
slicecopy
(
Slice
to
,
Slice
fm
,
uintptr
width
,
int32
ret
);
// see also unsafe·NewArray
// see also unsafe·NewArray
...
@@ -46,8 +48,6 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
...
@@ -46,8 +48,6 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
ret
->
array
=
runtime
·
mal
(
size
);
ret
->
array
=
runtime
·
mal
(
size
);
}
}
static
void
appendslice1
(
SliceType
*
,
Slice
,
Slice
,
Slice
*
);
// append(type *Type, n int, old []T, ...,) []T
// append(type *Type, n int, old []T, ...,) []T
#pragma textflag 7
#pragma textflag 7
void
void
...
@@ -72,36 +72,69 @@ runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
...
@@ -72,36 +72,69 @@ runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
static
void
static
void
appendslice1
(
SliceType
*
t
,
Slice
x
,
Slice
y
,
Slice
*
ret
)
appendslice1
(
SliceType
*
t
,
Slice
x
,
Slice
y
,
Slice
*
ret
)
{
{
Slice
newx
;
int32
m
;
int32
m
;
uintptr
w
;
uintptr
w
;
if
(
x
.
len
+
y
.
len
<
x
.
len
)
m
=
x
.
len
+
y
.
len
;
if
(
m
<
x
.
len
)
runtime
·
throw
(
"append: slice overflow"
);
runtime
·
throw
(
"append: slice overflow"
);
if
(
m
>
x
.
cap
)
growslice1
(
t
,
x
,
m
,
ret
);
else
*
ret
=
x
;
w
=
t
->
elem
->
size
;
w
=
t
->
elem
->
size
;
if
(
x
.
len
+
y
.
len
>
x
.
cap
)
{
runtime
·
memmove
(
ret
->
array
+
ret
->
len
*
w
,
y
.
array
,
y
.
len
*
w
);
m
=
x
.
cap
;
ret
->
len
+=
y
.
len
;
if
(
m
==
0
)
}
m
=
y
.
len
;
else
{
// growslice(type *Type, x, []T, n int64) []T
do
{
void
if
(
x
.
len
<
1024
)
runtime
·
growslice
(
SliceType
*
t
,
Slice
old
,
int64
n
,
Slice
ret
)
m
+=
m
;
{
else
int64
cap
;
m
+=
m
/
4
;
}
while
(
m
<
x
.
len
+
y
.
len
);
if
(
n
<
1
)
}
runtime
·
panicstring
(
"growslice: invalid n"
);
makeslice1
(
t
,
x
.
len
,
m
,
&
newx
);
runtime
·
memmove
(
newx
.
array
,
x
.
array
,
x
.
len
*
w
);
cap
=
old
.
cap
+
n
;
x
=
newx
;
if
((
int32
)
cap
!=
cap
||
cap
>
((
uintptr
)
-
1
)
/
t
->
elem
->
size
)
runtime
·
panicstring
(
"growslice: cap out of range"
);
growslice1
(
t
,
old
,
cap
,
&
ret
);
FLUSH
(
&
ret
);
if
(
debug
)
{
runtime
·
printf
(
"growslice(%S,"
,
*
t
->
string
);
runtime
·
printslice
(
old
);
runtime
·
printf
(
", new cap=%D) ="
,
cap
);
runtime
·
printslice
(
ret
);
}
}
runtime
·
memmove
(
x
.
array
+
x
.
len
*
w
,
y
.
array
,
y
.
len
*
w
);
x
.
len
+=
y
.
len
;
*
ret
=
x
;
}
}
static
void
growslice1
(
SliceType
*
t
,
Slice
x
,
int32
newcap
,
Slice
*
ret
)
{
int32
m
;
m
=
x
.
cap
;
if
(
m
==
0
)
m
=
newcap
;
else
{
do
{
if
(
x
.
len
<
1024
)
m
+=
m
;
else
m
+=
m
/
4
;
}
while
(
m
<
newcap
);
}
makeslice1
(
t
,
x
.
len
,
m
,
ret
);
runtime
·
memmove
(
ret
->
array
,
x
.
array
,
ret
->
len
*
t
->
elem
->
size
);
}
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
// sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any);
void
void
...
...
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