diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 12e48c199328..64a655e911ef 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -8b9c7fb00ccaf1d4bcc8d581a1a4d46a35771b77 +63bc2430187efe5ff47e9c7b9cd6d40b350ee7d7 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 327f9403b39d..90f860bd7353 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -4157,45 +4157,43 @@ Type_conversion_expression::do_get_backend(Translate_context* context) 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()) { @@ -8397,8 +8395,16 @@ Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function, 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 { diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def index 2ef0f94133da..a9500797b4d4 100644 --- a/gcc/go/gofrontend/runtime.def +++ b/gcc/go/gofrontend/runtime.def @@ -47,7 +47,7 @@ DEF_GO_RUNTIME(INTSTRING, "runtime.intstring", P2(POINTER, INT64), R1(STRING)) // 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", @@ -249,17 +249,16 @@ DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0()) // 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", diff --git a/libgo/go/runtime/cgocheck.go b/libgo/go/runtime/cgocheck.go index c03bafe424c0..42fdfe80280b 100644 --- a/libgo/go/runtime/cgocheck.go +++ b/libgo/go/runtime/cgocheck.go @@ -76,23 +76,24 @@ func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) { 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) diff --git a/libgo/go/runtime/mbarrier.go b/libgo/go/runtime/mbarrier.go index e66b50d1927e..a4f9b3c03506 100644 --- a/libgo/go/runtime/mbarrier.go +++ b/libgo/go/runtime/mbarrier.go @@ -219,16 +219,14 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, 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 @@ -237,19 +235,19 @@ func typedslicecopy(typ *_type, dst, src slice) int { 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 } @@ -259,11 +257,11 @@ func typedslicecopy(typ *_type, dst, src slice) int { // 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 } @@ -293,7 +291,7 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int { 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 diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go index 1e8644665574..5d5506467156 100644 --- a/libgo/go/runtime/os_linux.go +++ b/libgo/go/runtime/os_linux.go @@ -207,13 +207,14 @@ func getHugePageSize() uintptr { 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 } diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go index b61c2b10c7e6..519735392a9b 100644 --- a/libgo/go/runtime/slice.go +++ b/libgo/go/runtime/slice.go @@ -199,14 +199,14 @@ func isPowerOfTwo(x uintptr) bool { 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 { @@ -216,43 +216,43 @@ func slicecopy(to, fm slice, width uintptr) int { 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 } diff --git a/libgo/go/runtime/string.go b/libgo/go/runtime/string.go index df4cae7bcef8..7b66a1b447d9 100644 --- a/libgo/go/runtime/string.go +++ b/libgo/go/runtime/string.go @@ -70,47 +70,50 @@ func concatstrings(buf *tmpBuf, p *string, n int) string { 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) } @@ -131,17 +134,19 @@ func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) { // 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 { @@ -232,7 +237,7 @@ func intstring(buf *[4]byte, v int64) (s string) { var b []byte if buf != nil { b = buf[:] - s = slicebytetostringtmp(b) + s = slicebytetostringtmp(&b[0], len(b)) } else { s, b = rawstring(4) }