2018-04-24 07:13:08 -06:00
|
|
|
// asmcheck
|
|
|
|
|
|
|
|
// Copyright 2018 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 codegen
|
|
|
|
|
|
|
|
// This file contains code generation tests related to the handling of
|
|
|
|
// string types.
|
|
|
|
|
|
|
|
func CountRunes(s string) int { // Issue #24923
|
|
|
|
// amd64:`.*countrunes`
|
|
|
|
return len([]rune(s))
|
|
|
|
}
|
cmd/compile: make []byte("...") more efficient
Do []byte(string) conversions more efficiently when the string
is a constant. Instead of calling stringtobyteslice, allocate
just the space we need and encode the initialization directly.
[]byte("foo") rewrites to the following pseudocode:
var s [3]byte // on heap or stack, depending on whether b escapes
s = *(*[3]byte)(&"foo"[0]) // initialize s from the string
b = s[:]
which generates this assembly:
0x001d 00029 (tmp1.go:9) LEAQ type.[3]uint8(SB), AX
0x0024 00036 (tmp1.go:9) MOVQ AX, (SP)
0x0028 00040 (tmp1.go:9) CALL runtime.newobject(SB)
0x002d 00045 (tmp1.go:9) MOVQ 8(SP), AX
0x0032 00050 (tmp1.go:9) MOVBLZX go.string."foo"+2(SB), CX
0x0039 00057 (tmp1.go:9) MOVWLZX go.string."foo"(SB), DX
0x0040 00064 (tmp1.go:9) MOVW DX, (AX)
0x0043 00067 (tmp1.go:9) MOVB CL, 2(AX)
// Then the slice is b = {AX, 3, 3}
The generated code is still not optimal, as it still does load/store
from read-only memory instead of constant stores. Next CL...
Update #26498
Fixes #10170
Change-Id: I4b990b19f9a308f60c8f4f148934acffefe0a5bd
Reviewed-on: https://go-review.googlesource.com/c/140698
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2018-10-08 18:46:45 -06:00
|
|
|
|
2023-05-22 22:23:48 -06:00
|
|
|
func CountBytes(s []byte) int {
|
|
|
|
// amd64:-`.*runtime.slicebytetostring`
|
|
|
|
return len(string(s))
|
|
|
|
}
|
|
|
|
|
cmd/compile: make []byte("...") more efficient
Do []byte(string) conversions more efficiently when the string
is a constant. Instead of calling stringtobyteslice, allocate
just the space we need and encode the initialization directly.
[]byte("foo") rewrites to the following pseudocode:
var s [3]byte // on heap or stack, depending on whether b escapes
s = *(*[3]byte)(&"foo"[0]) // initialize s from the string
b = s[:]
which generates this assembly:
0x001d 00029 (tmp1.go:9) LEAQ type.[3]uint8(SB), AX
0x0024 00036 (tmp1.go:9) MOVQ AX, (SP)
0x0028 00040 (tmp1.go:9) CALL runtime.newobject(SB)
0x002d 00045 (tmp1.go:9) MOVQ 8(SP), AX
0x0032 00050 (tmp1.go:9) MOVBLZX go.string."foo"+2(SB), CX
0x0039 00057 (tmp1.go:9) MOVWLZX go.string."foo"(SB), DX
0x0040 00064 (tmp1.go:9) MOVW DX, (AX)
0x0043 00067 (tmp1.go:9) MOVB CL, 2(AX)
// Then the slice is b = {AX, 3, 3}
The generated code is still not optimal, as it still does load/store
from read-only memory instead of constant stores. Next CL...
Update #26498
Fixes #10170
Change-Id: I4b990b19f9a308f60c8f4f148934acffefe0a5bd
Reviewed-on: https://go-review.googlesource.com/c/140698
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2018-10-08 18:46:45 -06:00
|
|
|
func ToByteSlice() []byte { // Issue #24698
|
2021-05-07 11:45:06 -06:00
|
|
|
// amd64:`LEAQ\ttype:\[3\]uint8`
|
cmd/compile: make []byte("...") more efficient
Do []byte(string) conversions more efficiently when the string
is a constant. Instead of calling stringtobyteslice, allocate
just the space we need and encode the initialization directly.
[]byte("foo") rewrites to the following pseudocode:
var s [3]byte // on heap or stack, depending on whether b escapes
s = *(*[3]byte)(&"foo"[0]) // initialize s from the string
b = s[:]
which generates this assembly:
0x001d 00029 (tmp1.go:9) LEAQ type.[3]uint8(SB), AX
0x0024 00036 (tmp1.go:9) MOVQ AX, (SP)
0x0028 00040 (tmp1.go:9) CALL runtime.newobject(SB)
0x002d 00045 (tmp1.go:9) MOVQ 8(SP), AX
0x0032 00050 (tmp1.go:9) MOVBLZX go.string."foo"+2(SB), CX
0x0039 00057 (tmp1.go:9) MOVWLZX go.string."foo"(SB), DX
0x0040 00064 (tmp1.go:9) MOVW DX, (AX)
0x0043 00067 (tmp1.go:9) MOVB CL, 2(AX)
// Then the slice is b = {AX, 3, 3}
The generated code is still not optimal, as it still does load/store
from read-only memory instead of constant stores. Next CL...
Update #26498
Fixes #10170
Change-Id: I4b990b19f9a308f60c8f4f148934acffefe0a5bd
Reviewed-on: https://go-review.googlesource.com/c/140698
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2018-10-08 18:46:45 -06:00
|
|
|
// amd64:`CALL\truntime\.newobject`
|
|
|
|
// amd64:-`.*runtime.stringtoslicebyte`
|
|
|
|
return []byte("foo")
|
|
|
|
}
|
2018-10-09 23:55:36 -06:00
|
|
|
|
2023-09-13 03:44:17 -06:00
|
|
|
func ConvertToByteSlice(a, b, c string) []byte {
|
|
|
|
// amd64:`.*runtime.concatbyte3`
|
|
|
|
return []byte(a + b + c)
|
|
|
|
}
|
|
|
|
|
2018-10-09 23:55:36 -06:00
|
|
|
// Loading from read-only symbols should get transformed into constants.
|
|
|
|
func ConstantLoad() {
|
|
|
|
// 12592 = 0x3130
|
|
|
|
// 50 = 0x32
|
|
|
|
// amd64:`MOVW\t\$12592, \(`,`MOVB\t\$50, 2\(`
|
|
|
|
// 386:`MOVW\t\$12592, \(`,`MOVB\t\$50, 2\(`
|
|
|
|
// arm:`MOVW\t\$48`,`MOVW\t\$49`,`MOVW\t\$50`
|
|
|
|
// arm64:`MOVD\t\$12592`,`MOVD\t\$50`
|
2019-07-09 12:30:13 -06:00
|
|
|
// wasm:`I64Const\t\$12592`,`I64Store16\t\$0`,`I64Const\t\$50`,`I64Store8\t\$2`
|
2021-03-16 03:04:31 -06:00
|
|
|
// mips64:`MOVV\t\$48`,`MOVV\t\$49`,`MOVV\t\$50`
|
2018-10-09 23:55:36 -06:00
|
|
|
bsink = []byte("012")
|
|
|
|
|
|
|
|
// 858927408 = 0x33323130
|
|
|
|
// 13620 = 0x3534
|
|
|
|
// amd64:`MOVL\t\$858927408`,`MOVW\t\$13620, 4\(`
|
|
|
|
// 386:`MOVL\t\$858927408`,`MOVW\t\$13620, 4\(`
|
|
|
|
// arm64:`MOVD\t\$858927408`,`MOVD\t\$13620`
|
2019-07-09 12:30:13 -06:00
|
|
|
// wasm:`I64Const\t\$858927408`,`I64Store32\t\$0`,`I64Const\t\$13620`,`I64Store16\t\$4`
|
2018-10-09 23:55:36 -06:00
|
|
|
bsink = []byte("012345")
|
|
|
|
|
|
|
|
// 3978425819141910832 = 0x3736353433323130
|
|
|
|
// 7306073769690871863 = 0x6564636261393837
|
|
|
|
// amd64:`MOVQ\t\$3978425819141910832`,`MOVQ\t\$7306073769690871863`
|
|
|
|
// 386:`MOVL\t\$858927408, \(`,`DUFFCOPY`
|
2022-08-04 03:43:44 -06:00
|
|
|
// arm64:`MOVD\t\$3978425819141910832`,`MOVD\t\$7306073769690871863`,`MOVD\t\$15`
|
2019-07-09 12:30:13 -06:00
|
|
|
// wasm:`I64Const\t\$3978425819141910832`,`I64Store\t\$0`,`I64Const\t\$7306073769690871863`,`I64Store\t\$7`
|
2018-10-09 23:55:36 -06:00
|
|
|
bsink = []byte("0123456789abcde")
|
2018-10-30 13:58:50 -06:00
|
|
|
|
|
|
|
// 56 = 0x38
|
|
|
|
// amd64:`MOVQ\t\$3978425819141910832`,`MOVB\t\$56`
|
|
|
|
bsink = []byte("012345678")
|
|
|
|
|
|
|
|
// 14648 = 0x3938
|
|
|
|
// amd64:`MOVQ\t\$3978425819141910832`,`MOVW\t\$14648`
|
|
|
|
bsink = []byte("0123456789")
|
|
|
|
|
|
|
|
// 1650538808 = 0x62613938
|
|
|
|
// amd64:`MOVQ\t\$3978425819141910832`,`MOVL\t\$1650538808`
|
|
|
|
bsink = []byte("0123456789ab")
|
2018-10-09 23:55:36 -06:00
|
|
|
}
|
|
|
|
|
2023-06-15 10:14:12 -06:00
|
|
|
// self-equality is always true. See issue 60777.
|
|
|
|
func EqualSelf(s string) bool {
|
|
|
|
// amd64:`MOVL\t\$1, AX`,-`.*memequal.*`
|
|
|
|
return s == s
|
|
|
|
}
|
|
|
|
func NotEqualSelf(s string) bool {
|
|
|
|
// amd64:`XORL\tAX, AX`,-`.*memequal.*`
|
|
|
|
return s != s
|
|
|
|
}
|
|
|
|
|
2018-10-09 23:55:36 -06:00
|
|
|
var bsink []byte
|