-8b9c7fb00ccaf1d4bcc8d581a1a4d46a35771b77
+63bc2430187efe5ff47e9c7b9cd6d40b350ee7d7
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
go_assert(e->integer_type() != NULL);
go_assert(this->expr_->is_variable());
- Runtime::Function code;
+ Expression* buf;
+ if (this->no_escape_ && !this->no_copy_)
+ {
+ Type* byte_type = Type::lookup_integer_type("uint8");
+ Expression* buflen =
+ Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
+ Type* array_type = Type::make_array_type(byte_type, buflen);
+ buf = Expression::make_allocation(array_type, loc);
+ buf->allocation_expression()->set_allocate_on_stack();
+ buf->allocation_expression()->set_no_zero();
+ }
+ else
+ buf = Expression::make_nil(loc);
+
if (e->integer_type()->is_byte())
{
+ Expression* ptr =
+ Expression::make_slice_info(this->expr_, SLICE_INFO_VALUE_POINTER,
+ loc);
+ Expression* len =
+ Expression::make_slice_info(this->expr_, SLICE_INFO_LENGTH, loc);
if (this->no_copy_)
{
if (gogo->debug_optimization())
go_debug(loc, "no copy string([]byte)");
- Expression* ptr = Expression::make_slice_info(this->expr_,
- SLICE_INFO_VALUE_POINTER,
- loc);
- Expression* len = Expression::make_slice_info(this->expr_,
- SLICE_INFO_LENGTH,
- loc);
Expression* str = Expression::make_string_value(ptr, len, loc);
return str->get_backend(context);
}
- code = Runtime::SLICEBYTETOSTRING;
+ return Runtime::make_call(Runtime::SLICEBYTETOSTRING, loc, 3, buf,
+ ptr, len)->get_backend(context);
}
else
{
go_assert(e->integer_type()->is_rune());
- code = Runtime::SLICERUNETOSTRING;
- }
-
- Expression* buf;
- if (this->no_escape_)
- {
- Type* byte_type = Type::lookup_integer_type("uint8");
- Expression* buflen =
- Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
- Type* array_type = Type::make_array_type(byte_type, buflen);
- buf = Expression::make_allocation(array_type, loc);
- buf->allocation_expression()->set_allocate_on_stack();
- buf->allocation_expression()->set_no_zero();
- }
- else
- buf = Expression::make_nil(loc);
- return Runtime::make_call(code, loc, 2, buf,
- this->expr_)->get_backend(context);
+ return Runtime::make_call(Runtime::SLICERUNETOSTRING, loc, 2, buf,
+ this->expr_)->get_backend(context);
+ }
}
else if (type->is_slice_type() && expr_type->is_string_type())
{
if (et->has_pointer())
{
Expression* td = Expression::make_type_descriptor(et, loc);
+ Expression* pd =
+ Expression::make_slice_info(arg1, SLICE_INFO_VALUE_POINTER, loc);
+ Expression* ld =
+ Expression::make_slice_info(arg1, SLICE_INFO_LENGTH, loc);
+ Expression* ps =
+ Expression::make_slice_info(arg2, SLICE_INFO_VALUE_POINTER, loc);
+ Expression* ls =
+ Expression::make_slice_info(arg2, SLICE_INFO_LENGTH, loc);
ret = Runtime::make_call(Runtime::TYPEDSLICECOPY, loc,
- 3, td, arg1, arg2);
+ 5, td, pd, ld, ps, ls);
}
else
{
// Convert a []byte to a string.
DEF_GO_RUNTIME(SLICEBYTETOSTRING, "runtime.slicebytetostring",
- P2(POINTER, SLICE), R1(STRING))
+ P3(POINTER, POINTER, INT), R1(STRING))
// Convert a []rune to a string.
DEF_GO_RUNTIME(SLICERUNETOSTRING, "runtime.slicerunetostring",
// Copy.
-DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", P3(SLICE, SLICE, UINTPTR),
- R1(INT))
+DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy",
+ P5(POINTER, INT, POINTER, INT, UINTPTR), R1(INT))
// Copy from string.
-DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", P2(SLICE, STRING),
- R1(INT))
+DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy",
+ P3(POINTER, INT, STRING), R1(INT))
// Copy of value containing pointers.
DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
- P3(TYPE, SLICE, SLICE), R1(INT))
-
+ P5(TYPE, POINTER, INT, POINTER, INT), R1(INT))
// Grow a slice for append.
DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice",
cgoCheckTypedBlock(typ, src, off, size)
}
-// cgoCheckSliceCopy is called when copying n elements of a slice from
-// src to dst. typ is the element type of the slice.
+// cgoCheckSliceCopy is called when copying n elements of a slice.
+// src and dst are pointers to the first element of the slice.
+// typ is the element type of the slice.
// It throws if the program is copying slice elements that contain Go pointers
// into non-Go memory.
//go:nosplit
//go:nowritebarrier
-func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
+func cgoCheckSliceCopy(typ *_type, dst, src unsafe.Pointer, n int) {
if typ.ptrdata == 0 {
return
}
- if !cgoIsGoPointer(src.array) {
+ if !cgoIsGoPointer(src) {
return
}
- if cgoIsGoPointer(dst.array) {
+ if cgoIsGoPointer(dst) {
return
}
- p := src.array
+ p := src
for i := 0; i < n; i++ {
cgoCheckTypedBlock(typ, p, 0, typ.size)
p = add(p, typ.size)
}
//go:nosplit
-func typedslicecopy(typ *_type, dst, src slice) int {
- n := dst.len
- if n > src.len {
- n = src.len
+func typedslicecopy(typ *_type, dstPtr unsafe.Pointer, dstLen int, srcPtr unsafe.Pointer, srcLen int) int {
+ n := dstLen
+ if n > srcLen {
+ n = srcLen
}
if n == 0 {
return 0
}
- dstp := dst.array
- srcp := src.array
// The compiler emits calls to typedslicecopy before
// instrumentation runs, so unlike the other copying and
if raceenabled {
callerpc := getcallerpc()
pc := funcPC(slicecopy)
- racewriterangepc(dstp, uintptr(n)*typ.size, callerpc, pc)
- racereadrangepc(srcp, uintptr(n)*typ.size, callerpc, pc)
+ racewriterangepc(dstPtr, uintptr(n)*typ.size, callerpc, pc)
+ racereadrangepc(srcPtr, uintptr(n)*typ.size, callerpc, pc)
}
if msanenabled {
- msanwrite(dstp, uintptr(n)*typ.size)
- msanread(srcp, uintptr(n)*typ.size)
+ msanwrite(dstPtr, uintptr(n)*typ.size)
+ msanread(srcPtr, uintptr(n)*typ.size)
}
if writeBarrier.cgo {
- cgoCheckSliceCopy(typ, dst, src, n)
+ cgoCheckSliceCopy(typ, dstPtr, srcPtr, n)
}
- if dstp == srcp {
+ if dstPtr == srcPtr {
return n
}
// before calling typedslicecopy.
size := uintptr(n) * typ.size
if writeBarrier.needed {
- bulkBarrierPreWrite(uintptr(dstp), uintptr(srcp), size)
+ bulkBarrierPreWrite(uintptr(dstPtr), uintptr(srcPtr), size)
}
// See typedmemmove for a discussion of the race between the
// barrier and memmove.
- memmove(dstp, srcp, size)
+ memmove(dstPtr, srcPtr, size)
return n
}
memmove(dst.array, src.array, size)
return n
}
- return typedslicecopy(elemType, dst, src)
+ return typedslicecopy(elemType, dst.array, dst.len, src.array, src.len)
}
// typedmemclr clears the typed memory at ptr with type typ. The
if fd < 0 {
return 0
}
- n := read(fd, noescape(unsafe.Pointer(&numbuf[0])), int32(len(numbuf)))
+ ptr := noescape(unsafe.Pointer(&numbuf[0]))
+ n := read(fd, ptr, int32(len(numbuf)))
closefd(fd)
if n <= 0 {
return 0
}
- l := n - 1 // remove trailing newline
- v, ok := atoi(slicebytetostringtmp(numbuf[:l]))
+ n-- // remove trailing newline
+ v, ok := atoi(slicebytetostringtmp((*byte)(ptr), int(n)))
if !ok || v < 0 {
v = 0
}
return x&(x-1) == 0
}
-func slicecopy(to, fm slice, width uintptr) int {
- if fm.len == 0 || to.len == 0 {
+func slicecopy(toPtr unsafe.Pointer, toLen int, fmPtr unsafe.Pointer, fmLen int, width uintptr) int {
+ if fmLen == 0 || toLen == 0 {
return 0
}
- n := fm.len
- if to.len < n {
- n = to.len
+ n := fmLen
+ if toLen < n {
+ n = toLen
}
if width == 0 {
if raceenabled {
callerpc := getcallerpc()
pc := funcPC(slicecopy)
- racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
- racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
+ racewriterangepc(toPtr, uintptr(n*int(width)), callerpc, pc)
+ racereadrangepc(fmPtr, uintptr(n*int(width)), callerpc, pc)
}
if msanenabled {
- msanwrite(to.array, uintptr(n*int(width)))
- msanread(fm.array, uintptr(n*int(width)))
+ msanwrite(toPtr, uintptr(n*int(width)))
+ msanread(fmPtr, uintptr(n*int(width)))
}
size := uintptr(n) * width
if size == 1 { // common case worth about 2x to do here
// TODO: is this still worth it with new memmove impl?
- *(*byte)(to.array) = *(*byte)(fm.array) // known to be a byte pointer
+ *(*byte)(toPtr) = *(*byte)(fmPtr) // known to be a byte pointer
} else {
- memmove(to.array, fm.array, size)
+ memmove(toPtr, fmPtr, size)
}
return n
}
-func slicestringcopy(to []byte, fm string) int {
- if len(fm) == 0 || len(to) == 0 {
+func slicestringcopy(toPtr *byte, toLen int, fm string) int {
+ if len(fm) == 0 || toLen == 0 {
return 0
}
n := len(fm)
- if len(to) < n {
- n = len(to)
+ if toLen < n {
+ n = toLen
}
if raceenabled {
callerpc := getcallerpc()
pc := funcPC(slicestringcopy)
- racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
+ racewriterangepc(unsafe.Pointer(toPtr), uintptr(n), callerpc, pc)
}
if msanenabled {
- msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
+ msanwrite(unsafe.Pointer(toPtr), uintptr(n))
}
- memmove(unsafe.Pointer(&to[0]), stringStructOf(&fm).str, uintptr(n))
+ memmove(unsafe.Pointer(toPtr), stringStructOf(&fm).str, uintptr(n))
return n
}
return s
}
+// slicebytetostring converts a byte slice to a string.
+// It is inserted by the compiler into generated code.
+// ptr is a pointer to the first element of the slice;
+// n is the length of the slice.
// Buf is a fixed-size buffer for the result,
// it is not nil if the result does not escape.
-func slicebytetostring(buf *tmpBuf, b []byte) (str string) {
- l := len(b)
- if l == 0 {
+func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) {
+ if n == 0 {
// Turns out to be a relatively common case.
// Consider that you want to parse out data between parens in "foo()bar",
// you find the indices and convert the subslice to string.
return ""
}
if raceenabled {
- racereadrangepc(unsafe.Pointer(&b[0]),
- uintptr(l),
+ racereadrangepc(unsafe.Pointer(ptr),
+ uintptr(n),
getcallerpc(),
funcPC(slicebytetostring))
}
if msanenabled {
- msanread(unsafe.Pointer(&b[0]), uintptr(l))
+ msanread(unsafe.Pointer(ptr), uintptr(n))
}
- if l == 1 {
- stringStructOf(&str).str = unsafe.Pointer(&staticbytes[b[0]])
+ if n == 1 {
+ stringStructOf(&str).str = unsafe.Pointer(&staticbytes[*ptr])
stringStructOf(&str).len = 1
return
}
var p unsafe.Pointer
- if buf != nil && len(b) <= len(buf) {
+ if buf != nil && n <= len(buf) {
p = unsafe.Pointer(buf)
} else {
- p = mallocgc(uintptr(len(b)), nil, false)
+ p = mallocgc(uintptr(n), nil, false)
}
stringStructOf(&str).str = p
- stringStructOf(&str).len = len(b)
- memmove(p, (*(*slice)(unsafe.Pointer(&b))).array, uintptr(len(b)))
+ stringStructOf(&str).len = n
+ memmove(p, unsafe.Pointer(ptr), uintptr(n))
return
}
func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
if buf != nil && l <= len(buf) {
b = buf[:l]
- s = slicebytetostringtmp(b)
+ s = slicebytetostringtmp(&b[0], len(b))
} else {
s, b = rawstring(l)
}
// where k is []byte, T1 to Tn is a nesting of struct and array literals.
// - Used for "<"+string(b)+">" concatenation where b is []byte.
// - Used for string(b)=="foo" comparison where b is []byte.
-func slicebytetostringtmp(b []byte) string {
- if raceenabled && len(b) > 0 {
- racereadrangepc(unsafe.Pointer(&b[0]),
- uintptr(len(b)),
+func slicebytetostringtmp(ptr *byte, n int) (str string) {
+ if raceenabled && n > 0 {
+ racereadrangepc(unsafe.Pointer(ptr),
+ uintptr(n),
getcallerpc(),
funcPC(slicebytetostringtmp))
}
- if msanenabled && len(b) > 0 {
- msanread(unsafe.Pointer(&b[0]), uintptr(len(b)))
+ if msanenabled && n > 0 {
+ msanread(unsafe.Pointer(ptr), uintptr(n))
}
- return *(*string)(unsafe.Pointer(&b))
+ stringStructOf(&str).str = unsafe.Pointer(ptr)
+ stringStructOf(&str).len = n
+ return
}
func stringtoslicebyte(buf *tmpBuf, s string) []byte {
var b []byte
if buf != nil {
b = buf[:]
- s = slicebytetostringtmp(b)
+ s = slicebytetostringtmp(&b[0], len(b))
} else {
s, b = rawstring(4)
}