1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 // For gccgo, use go:linkname to rename compiler-called functions to
10 // themselves, so that the compiler will export them.
12 //go:linkname concatstrings runtime.concatstrings
13 //go:linkname concatstring2 runtime.concatstring2
14 //go:linkname concatstring3 runtime.concatstring3
15 //go:linkname concatstring4 runtime.concatstring4
16 //go:linkname concatstring5 runtime.concatstring5
17 //go:linkname slicebytetostring runtime.slicebytetostring
18 //go:linkname slicebytetostringtmp runtime.slicebytetostringtmp
19 //go:linkname stringtoslicebyte runtime.stringtoslicebyte
20 //go:linkname stringtoslicerune runtime.stringtoslicerune
21 //go:linkname slicerunetostring runtime.slicerunetostring
22 //go:linkname intstring runtime.intstring
23 // Temporary for C code to call:
24 //go:linkname gostringnocopy runtime.gostringnocopy
25 //go:linkname findnull runtime.findnull
27 // The constant is known to the compiler.
28 // There is no fundamental theory behind this number.
29 const tmpStringBufSize
= 32
31 type tmpBuf
[tmpStringBufSize
]byte
33 // concatstrings implements a Go string concatenation x+y+z+...
34 // The operands are passed in the slice a.
35 // If buf != nil, the compiler has determined that the result does not
36 // escape the calling function, so the string data can be stored in buf
38 func concatstrings(buf
*tmpBuf
, a
[]string) string {
48 throw("string concatenation too long")
58 // If there is just one string and either it is not on the stack
59 // or our result does not escape the calling frame (buf != nil),
60 // then we can return that string directly.
61 // Commented out for gccgo--no implementation of stringDataOnStack.
62 // if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) {
65 s
, b
:= rawstringtmp(buf
, l
)
73 func concatstring2(buf
*tmpBuf
, a
[2]string) string {
74 return concatstrings(buf
, a
[:])
77 func concatstring3(buf
*tmpBuf
, a
[3]string) string {
78 return concatstrings(buf
, a
[:])
81 func concatstring4(buf
*tmpBuf
, a
[4]string) string {
82 return concatstrings(buf
, a
[:])
85 func concatstring5(buf
*tmpBuf
, a
[5]string) string {
86 return concatstrings(buf
, a
[:])
89 // Buf is a fixed-size buffer for the result,
90 // it is not nil if the result does not escape.
91 func slicebytetostring(buf
*tmpBuf
, b
[]byte) (str
string) {
94 // Turns out to be a relatively common case.
95 // Consider that you want to parse out data between parens in "foo()bar",
96 // you find the indices and convert the subslice to string.
100 racereadrangepc(unsafe
.Pointer(&b
[0]),
103 funcPC(slicebytetostring
))
106 msanread(unsafe
.Pointer(&b
[0]), uintptr(l
))
110 if buf
!= nil && len(b
) <= len(buf
) {
111 p
= unsafe
.Pointer(buf
)
113 p
= mallocgc(uintptr(len(b
)), nil, false)
115 stringStructOf(&str
).str
= p
116 stringStructOf(&str
).len = len(b
)
117 memmove(p
, (*(*slice
)(unsafe
.Pointer(&b
))).array
, uintptr(len(b
)))
121 func rawstringtmp(buf
*tmpBuf
, l
int) (s
string, b
[]byte) {
122 if buf
!= nil && l
<= len(buf
) {
124 s
= slicebytetostringtmp(b
)
131 // slicebytetostringtmp returns a "string" referring to the actual []byte bytes.
133 // Callers need to ensure that the returned string will not be used after
134 // the calling goroutine modifies the original slice or synchronizes with
135 // another goroutine.
137 // The function is only called when instrumenting
138 // and otherwise intrinsified by the compiler.
140 // Some internal compiler optimizations use this function.
141 // - Used for m[string(k)] lookup where m is a string-keyed map and k is a []byte.
142 // - Used for "<"+string(b)+">" concatenation where b is []byte.
143 // - Used for string(b)=="foo" comparison where b is []byte.
144 func slicebytetostringtmp(b
[]byte) string {
145 if raceenabled
&& len(b
) > 0 {
146 racereadrangepc(unsafe
.Pointer(&b
[0]),
149 funcPC(slicebytetostringtmp
))
151 if msanenabled
&& len(b
) > 0 {
152 msanread(unsafe
.Pointer(&b
[0]), uintptr(len(b
)))
154 return *(*string)(unsafe
.Pointer(&b
))
157 func stringtoslicebyte(buf
*tmpBuf
, s
string) []byte {
159 if buf
!= nil && len(s
) <= len(buf
) {
163 b
= rawbyteslice(len(s
))
169 func stringtoslicerune(buf
*[tmpStringBufSize
]rune
, s
string) []rune
{
171 // unlike slicerunetostring, no race because strings are immutable.
178 if buf
!= nil && n
<= len(buf
) {
179 *buf
= [tmpStringBufSize
]rune
{}
186 for _
, r
:= range s
{
193 func slicerunetostring(buf
*tmpBuf
, a
[]rune
) string {
194 if raceenabled
&& len(a
) > 0 {
195 racereadrangepc(unsafe
.Pointer(&a
[0]),
196 uintptr(len(a
))*unsafe
.Sizeof(a
[0]),
198 funcPC(slicerunetostring
))
200 if msanenabled
&& len(a
) > 0 {
201 msanread(unsafe
.Pointer(&a
[0]), uintptr(len(a
))*unsafe
.Sizeof(a
[0]))
205 for _
, r
:= range a
{
206 size1
+= encoderune(dum
[:], r
)
208 s
, b
:= rawstringtmp(buf
, size1
+3)
210 for _
, r
:= range a
{
215 size2
+= encoderune(b
[size2
:], r
)
220 type stringStruct
struct {
225 // Variant with *byte pointer type for DWARF debugging.
226 type stringStructDWARF
struct {
231 func stringStructOf(sp
*string) *stringStruct
{
232 return (*stringStruct
)(unsafe
.Pointer(sp
))
235 func intstring(buf
*[4]byte, v
int64) string {
240 s
= slicebytetostringtmp(b
)
244 if int64(rune(v
)) != v
{
247 n
:= encoderune(b
, rune(v
))
251 // rawstring allocates storage for a new string. The returned
252 // string and byte slice both refer to the same storage.
253 // The storage is not zeroed. Callers should use
254 // b to set the string contents and then drop b.
255 func rawstring(size
int) (s
string, b
[]byte) {
256 p
:= mallocgc(uintptr(size
), nil, false)
258 stringStructOf(&s
).str
= p
259 stringStructOf(&s
).len = size
261 *(*slice
)(unsafe
.Pointer(&b
)) = slice
{p
, size
, size
}
266 // rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
267 func rawbyteslice(size
int) (b
[]byte) {
268 cap := roundupsize(uintptr(size
))
269 p
:= mallocgc(cap, nil, false)
270 if cap != uintptr(size
) {
271 memclrNoHeapPointers(add(p
, uintptr(size
)), cap-uintptr(size
))
274 *(*slice
)(unsafe
.Pointer(&b
)) = slice
{p
, size
, int(cap)}
278 // rawruneslice allocates a new rune slice. The rune slice is not zeroed.
279 func rawruneslice(size
int) (b
[]rune
) {
280 if uintptr(size
) > _MaxMem
/4 {
281 throw("out of memory")
283 mem
:= roundupsize(uintptr(size
) * 4)
284 p
:= mallocgc(mem
, nil, false)
285 if mem
!= uintptr(size
)*4 {
286 memclrNoHeapPointers(add(p
, uintptr(size
)*4), mem
-uintptr(size
)*4)
289 *(*slice
)(unsafe
.Pointer(&b
)) = slice
{p
, size
, int(mem
/ 4)}
294 func gobytes(p
*byte, n
int) []byte {
296 return make([]byte, 0)
299 memmove(unsafe
.Pointer(&x
[0]), unsafe
.Pointer(p
), uintptr(n
))
303 func gostring(p
*byte) string {
309 memmove(unsafe
.Pointer(&b
[0]), unsafe
.Pointer(p
), uintptr(l
))
313 func gostringn(p
*byte, l
int) string {
318 memmove(unsafe
.Pointer(&b
[0]), unsafe
.Pointer(p
), uintptr(l
))
322 func index(s
, t
string) int {
326 for i
:= 0; i
< len(s
); i
++ {
327 if s
[i
] == t
[0] && hasprefix(s
[i
:], t
) {
334 func contains(s
, t
string) bool {
335 return index(s
, t
) >= 0
338 func hasprefix(s
, t
string) bool {
339 return len(s
) >= len(t
) && s
[:len(t
)] == t
344 maxInt
= int(maxUint
>> 1)
347 // atoi parses an int from a string s.
348 // The bool result reports whether s is a number
349 // representable by a value of type int.
350 func atoi(s
string) (int, bool) {
362 for i
:= 0; i
< len(s
); i
++ {
364 if c
< '0' || c
> '9' {
372 un1
:= un
+ uint(c
) - '0'
380 if !neg
&& un
> uint(maxInt
) {
383 if neg
&& un
> uint(maxInt
)+1 {
395 // atoi32 is like atoi but for integers
396 // that fit into an int32.
397 func atoi32(s
string) (int32, bool) {
398 if n
, ok
:= atoi(s
); n
== int(int32(n
)) {
405 func findnull(s
*byte) int {
409 p
:= (*[_MaxMem
/2 - 1]byte)(unsafe
.Pointer(s
))
417 func findnullw(s
*uint16) int {
421 p
:= (*[_MaxMem
/2/2 - 1]uint16)(unsafe
.Pointer(s
))
430 func gostringnocopy(str
*byte) string {
431 ss
:= stringStruct
{str
: unsafe
.Pointer(str
), len: findnull(str
)}
432 s
:= *(*string)(unsafe
.Pointer(&ss
))
436 func gostringw(strw
*uint16) string {
438 str
:= (*[_MaxMem
/2/2 - 1]uint16)(unsafe
.Pointer(strw
))
440 for i
:= 0; str
[i
] != 0; i
++ {
441 n1
+= encoderune(buf
[:], rune(str
[i
]))
443 s
, b
:= rawstring(n1
+ 4)
445 for i
:= 0; str
[i
] != 0; i
++ {
450 n2
+= encoderune(b
[n2
:], rune(str
[i
]))
452 b
[n2
] = 0 // for luck
456 // These two functions are called by code generated by cgo -gccgo.
458 //go:linkname __go_byte_array_to_string __go_byte_array_to_string
459 func __go_byte_array_to_string(p unsafe
.Pointer
, l
int) string {
463 s
, c
:= rawstringtmp(nil, l
)
464 memmove(unsafe
.Pointer(&c
[0]), p
, uintptr(l
))
468 //go:linkname __go_string_to_byte_array __go_string_to_byte_array
469 func __go_string_to_byte_array(s
string) []byte {
470 return stringtoslicebyte(nil, s
)