This patch changes the Go frontend and the libgo runtime package to
pass only ptr and len to some runtime calls, rather than passing an
entire slice.  This ports https://golang.org/cl/227163 to the Go
frontend.  This is a step toward moving up to the go1.15rc1 release.

The original change says "Some runtime calls accept a slice, but only
use ptr and len.  This change modifies most such routines to accept
only ptr and len."

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
108fdcc56ee49dd7dc8314ce5022191f406a125f
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 12e48c19932..64a655e911e 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 327f9403b39..90f860bd735 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 2ef0f94133d..a9500797b4d 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 c03bafe424c..42fdfe80280 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 e66b50d1927..a4f9b3c0350 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 1e864466557..5d550646715 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 b61c2b10c7e..519735392a9 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 df4cae7bcef..7b66a1b447d 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)
        }

Reply via email to