diff options
Diffstat (limited to 'gcc-4.8/libgo')
37 files changed, 559 insertions, 111 deletions
diff --git a/gcc-4.8/libgo/Makefile.am b/gcc-4.8/libgo/Makefile.am index c81c66cb0..199b44418 100644 --- a/gcc-4.8/libgo/Makefile.am +++ b/gcc-4.8/libgo/Makefile.am @@ -424,6 +424,7 @@ runtime_files = \ runtime/go-caller.c \ runtime/go-callers.c \ runtime/go-can-convert-interface.c \ + runtime/go-cdiv.c \ runtime/go-cgo.c \ runtime/go-check-interface.c \ runtime/go-construct-map.c \ @@ -1254,7 +1255,7 @@ go_go_build_files = \ go/go/build/build.go \ go/go/build/doc.go \ go/go/build/read.go \ - syslist.go + go/go/build/syslist.go go_go_doc_files = \ go/go/doc/comment.go \ go/go/doc/doc.go \ @@ -2712,15 +2713,6 @@ go/build/check: $(CHECK_DEPS) @$(CHECK) .PHONY: go/build/check -syslist.go: s-syslist; @true -s-syslist: Makefile - echo '// Generated automatically by make.' >syslist.go.tmp - echo 'package build' >>syslist.go.tmp - echo 'const goosList = "$(GOOS)"' >>syslist.go.tmp - echo 'const goarchList = "$(GOARCH)"' >>syslist.go.tmp - $(SHELL) $(srcdir)/../move-if-change syslist.go.tmp syslist.go - $(STAMP) $@ - @go_include@ go/doc.lo.dep go/doc.lo.dep: $(go_go_doc_files) $(BUILDDEPS) diff --git a/gcc-4.8/libgo/Makefile.in b/gcc-4.8/libgo/Makefile.in index 9e31e8ca2..61cca7385 100644 --- a/gcc-4.8/libgo/Makefile.in +++ b/gcc-4.8/libgo/Makefile.in @@ -195,7 +195,7 @@ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ @LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \ go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \ - go-callers.lo go-can-convert-interface.lo go-cgo.lo \ + go-callers.lo go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \ go-check-interface.lo go-construct-map.lo \ go-convert-interface.lo go-copy.lo go-defer.lo \ go-deferred-recover.lo go-eface-compare.lo \ @@ -757,6 +757,7 @@ runtime_files = \ runtime/go-caller.c \ runtime/go-callers.c \ runtime/go-can-convert-interface.c \ + runtime/go-cdiv.c \ runtime/go-cgo.c \ runtime/go-check-interface.c \ runtime/go-construct-map.c \ @@ -1446,7 +1447,7 @@ go_go_build_files = \ go/go/build/build.go \ go/go/build/doc.go \ go/go/build/read.go \ - syslist.go + go/go/build/syslist.go go_go_doc_files = \ go/go/doc/comment.go \ @@ -2368,6 +2369,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-callers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cdiv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@ @@ -2554,6 +2556,13 @@ go-can-convert-interface.lo: runtime/go-can-convert-interface.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-can-convert-interface.lo `test -f 'runtime/go-can-convert-interface.c' || echo '$(srcdir)/'`runtime/go-can-convert-interface.c +go-cdiv.lo: runtime/go-cdiv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-cdiv.lo -MD -MP -MF $(DEPDIR)/go-cdiv.Tpo -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-cdiv.Tpo $(DEPDIR)/go-cdiv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-cdiv.c' object='go-cdiv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c + go-cgo.lo: runtime/go-cgo.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-cgo.lo -MD -MP -MF $(DEPDIR)/go-cgo.Tpo -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-cgo.Tpo $(DEPDIR)/go-cgo.Plo @@ -5062,15 +5071,6 @@ go/build/check: $(CHECK_DEPS) @$(CHECK) .PHONY: go/build/check -syslist.go: s-syslist; @true -s-syslist: Makefile - echo '// Generated automatically by make.' >syslist.go.tmp - echo 'package build' >>syslist.go.tmp - echo 'const goosList = "$(GOOS)"' >>syslist.go.tmp - echo 'const goarchList = "$(GOARCH)"' >>syslist.go.tmp - $(SHELL) $(srcdir)/../move-if-change syslist.go.tmp syslist.go - $(STAMP) $@ - @go_include@ go/doc.lo.dep go/doc.lo.dep: $(go_go_doc_files) $(BUILDDEPS) diff --git a/gcc-4.8/libgo/config.h.in b/gcc-4.8/libgo/config.h.in index 1057d9e85..f6da8b982 100644 --- a/gcc-4.8/libgo/config.h.in +++ b/gcc-4.8/libgo/config.h.in @@ -39,6 +39,9 @@ /* Define to 1 if you have the `dl_iterate_phdr' function. */ #undef HAVE_DL_ITERATE_PHDR +/* Define to 1 if you have the `dup3' function. */ +#undef HAVE_DUP3 + /* Define to 1 if you have the `epoll_create1' function. */ #undef HAVE_EPOLL_CREATE1 @@ -66,6 +69,9 @@ /* Define if _Unwind_GetIPInfo is available. */ #undef HAVE_GETIPINFO +/* Define to 1 if you have the `getxattr' function. */ +#undef HAVE_GETXATTR + /* Define to 1 if you have the `inotify_add_watch' function. */ #undef HAVE_INOTIFY_ADD_WATCH @@ -111,6 +117,9 @@ /* Define to 1 if you have the <linux/rtnetlink.h> header file. */ #undef HAVE_LINUX_RTNETLINK_H +/* Define to 1 if you have the `listxattr' function. */ +#undef HAVE_LISTXATTR + /* Define to 1 if the system has the type `loff_t'. */ #undef HAVE_LOFF_T @@ -171,6 +180,9 @@ /* Define to 1 if you have the `pipe2' function. */ #undef HAVE_PIPE2 +/* Define to 1 if you have the `removexattr' function. */ +#undef HAVE_REMOVEXATTR + /* Define to 1 if you have the `renameat' function. */ #undef HAVE_RENAMEAT @@ -180,6 +192,9 @@ /* Define to 1 if you have the `setenv' function. */ #undef HAVE_SETENV +/* Define to 1 if you have the `setxattr' function. */ +#undef HAVE_SETXATTR + /* Define to 1 if you have the `sinl' function. */ #undef HAVE_SINL diff --git a/gcc-4.8/libgo/config/libtool.m4 b/gcc-4.8/libgo/config/libtool.m4 index 1a667d31a..f1ffebf99 100644 --- a/gcc-4.8/libgo/config/libtool.m4 +++ b/gcc-4.8/libgo/config/libtool.m4 @@ -1225,7 +1225,7 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext @@ -1239,7 +1239,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1258,7 +1261,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) diff --git a/gcc-4.8/libgo/configure b/gcc-4.8/libgo/configure index e54a2cd1b..112662d74 100755 --- a/gcc-4.8/libgo/configure +++ b/gcc-4.8/libgo/configure @@ -6501,7 +6501,7 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext @@ -6519,7 +6519,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -6538,7 +6541,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -11105,7 +11111,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11108 "configure" +#line 11114 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11211,7 +11217,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11214 "configure" +#line 11220 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14700,7 +14706,7 @@ else fi -for ac_func in accept4 epoll_create1 faccessat fallocate fchmodat fchownat futimesat inotify_add_watch inotify_init inotify_init1 inotify_rm_watch mkdirat mknodat openat pipe2 renameat sync_file_range splice tee unlinkat unshare utimensat +for ac_func in accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/gcc-4.8/libgo/configure.ac b/gcc-4.8/libgo/configure.ac index 81c0a88b0..8ce846d9f 100644 --- a/gcc-4.8/libgo/configure.ac +++ b/gcc-4.8/libgo/configure.ac @@ -503,7 +503,7 @@ AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv dl_iterate_phdr) AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes) AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes) -AC_CHECK_FUNCS(accept4 epoll_create1 faccessat fallocate fchmodat fchownat futimesat inotify_add_watch inotify_init inotify_init1 inotify_rm_watch mkdirat mknodat openat pipe2 renameat sync_file_range splice tee unlinkat unshare utimensat) +AC_CHECK_FUNCS(accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat) AC_TYPE_OFF_T AC_CHECK_TYPES([loff_t]) diff --git a/gcc-4.8/libgo/go/go/build/build.go b/gcc-4.8/libgo/go/go/build/build.go index cc89afb21..59ddcefd7 100644 --- a/gcc-4.8/libgo/go/go/build/build.go +++ b/gcc-4.8/libgo/go/go/build/build.go @@ -429,7 +429,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa switch ctxt.Compiler { case "gccgo": dir, elem := pathpkg.Split(p.ImportPath) - pkga = "pkg/gccgo/" + dir + "lib" + elem + ".a" + pkga = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + "/" + dir + "lib" + elem + ".a" case "gc": suffix := "" if ctxt.InstallSuffix != "" { diff --git a/gcc-4.8/libgo/go/go/build/syslist.go b/gcc-4.8/libgo/go/go/build/syslist.go new file mode 100644 index 000000000..a322c88c4 --- /dev/null +++ b/gcc-4.8/libgo/go/go/build/syslist.go @@ -0,0 +1,8 @@ +// Copyright 2011 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 build + +const goosList = "darwin dragonfly freebsd linux netbsd openbsd plan9 windows solaris " +const goarchList = "386 amd64 arm alpha m68k mipso32 mipsn32 mipsn64 mipso64 ppc ppc64 sparc sparc64 " diff --git a/gcc-4.8/libgo/go/net/fd_unix.go b/gcc-4.8/libgo/go/net/fd_unix.go index 8c59bff98..0f863aadd 100644 --- a/gcc-4.8/libgo/go/net/fd_unix.go +++ b/gcc-4.8/libgo/go/net/fd_unix.go @@ -9,6 +9,7 @@ package net import ( "io" "os" + "runtime" "sync" "syscall" "time" @@ -90,6 +91,16 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr) error { if err == nil || err == syscall.EISCONN { break } + + // On Solaris we can see EINVAL if the socket has + // already been accepted and closed by the server. + // Treat this as a successful connection--writes to + // the socket will see EOF. For details and a test + // case in C see http://golang.org/issue/6828. + if runtime.GOOS == "solaris" && err == syscall.EINVAL { + break + } + if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { return err } diff --git a/gcc-4.8/libgo/go/reflect/all_test.go b/gcc-4.8/libgo/go/reflect/all_test.go index 526f09bb2..50f49e066 100644 --- a/gcc-4.8/libgo/go/reflect/all_test.go +++ b/gcc-4.8/libgo/go/reflect/all_test.go @@ -1430,6 +1430,46 @@ func TestFunc(t *testing.T) { } } +type emptyStruct struct{} + +type nonEmptyStruct struct { + member int +} + +func returnEmpty() emptyStruct { + return emptyStruct{} +} + +func takesEmpty(e emptyStruct) { +} + +func returnNonEmpty(i int) nonEmptyStruct { + return nonEmptyStruct{member: i} +} + +func takesNonEmpty(n nonEmptyStruct) int { + return n.member +} + +func TestCallWithStruct(t *testing.T) { + r := ValueOf(returnEmpty).Call([]Value{}) + if len(r) != 1 || r[0].Type() != TypeOf(emptyStruct{}) { + t.Errorf("returning empty struct returned %s instead", r) + } + r = ValueOf(takesEmpty).Call([]Value{ValueOf(emptyStruct{})}) + if len(r) != 0 { + t.Errorf("takesEmpty returned values: %s", r) + } + r = ValueOf(returnNonEmpty).Call([]Value{ValueOf(42)}) + if len(r) != 1 || r[0].Type() != TypeOf(nonEmptyStruct{}) || r[0].Field(0).Int() != 42 { + t.Errorf("returnNonEmpty returned %s", r) + } + r = ValueOf(takesNonEmpty).Call([]Value{ValueOf(nonEmptyStruct{member: 42})}) + if len(r) != 1 || r[0].Type() != TypeOf(1) || r[0].Int() != 42 { + t.Errorf("takesNonEmpty returned %s", r) + } +} + func TestMakeFunc(t *testing.T) { switch runtime.GOARCH { case "amd64", "386": @@ -1587,9 +1627,13 @@ func TestMethod(t *testing.T) { } } -/* Not yet implemented for gccgo - func TestMethodValue(t *testing.T) { + switch runtime.GOARCH { + case "amd64", "386": + default: + t.Skip("reflect method values not implemented for " + runtime.GOARCH) + } + p := Point{3, 4} var i int64 @@ -1658,8 +1702,6 @@ func TestMethodValue(t *testing.T) { } } -*/ - // Reflect version of $GOROOT/test/method5.go // Concrete types implementing M method. @@ -1744,14 +1786,18 @@ type Tm4 struct { func (t4 Tm4) M(x int, b byte) (byte, int) { return b, x + 40 } func TestMethod5(t *testing.T) { - /* Not yet used for gccgo + switch runtime.GOARCH { + case "amd64", "386": + default: + t.Skip("reflect method values not implemented for " + runtime.GOARCH) + } + CheckF := func(name string, f func(int, byte) (byte, int), inc int) { b, x := f(1000, 99) if b != 99 || x != 1000+inc { t.Errorf("%s(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc) } } - */ CheckV := func(name string, i Value, inc int) { bx := i.Method(0).Call([]Value{ValueOf(1000), ValueOf(byte(99))}) @@ -1761,9 +1807,7 @@ func TestMethod5(t *testing.T) { t.Errorf("direct %s.M(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc) } - /* Not yet implemented for gccgo CheckF(name+".M", i.Method(0).Interface().(func(int, byte) (byte, int)), inc) - */ } var TinterType = TypeOf(new(Tinter)).Elem() diff --git a/gcc-4.8/libgo/go/reflect/makefunc.go b/gcc-4.8/libgo/go/reflect/makefunc.go index 3e8085bec..9f150ea65 100644 --- a/gcc-4.8/libgo/go/reflect/makefunc.go +++ b/gcc-4.8/libgo/go/reflect/makefunc.go @@ -17,6 +17,11 @@ type makeFuncImpl struct { code uintptr typ *funcType fn func([]Value) []Value + + // For gccgo we use the same entry point for functions and for + // method values. + method int + rcvr Value } // MakeFunc returns a new function of the given Type @@ -61,7 +66,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { dummy := makeFuncStub code := **(**uintptr)(unsafe.Pointer(&dummy)) - impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn} + impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn, method: -1} return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir} } @@ -85,15 +90,94 @@ func makeMethodValue(op string, v Value) Value { panic("reflect: internal error: invalid use of makePartialFunc") } + switch runtime.GOARCH { + case "amd64", "386": + default: + panic("reflect.makeMethodValue not implemented for " + runtime.GOARCH) + } + // Ignoring the flagMethod bit, v describes the receiver, not the method type. fl := v.flag & (flagRO | flagAddr | flagIndir) fl |= flag(v.typ.Kind()) << flagKindShift rcvr := Value{v.typ, v.val, fl} + // v.Type returns the actual type of the method value. + ft := v.Type().(*rtype) + + // Indirect Go func value (dummy) to obtain + // actual code address. (A Go func value is a pointer + // to a C function pointer. http://golang.org/s/go11func.) + dummy := makeFuncStub + code := **(**uintptr)(unsafe.Pointer(&dummy)) + // Cause panic if method is not appropriate. // The panic would still happen during the call if we omit this, // but we want Interface() and other operations to fail early. - methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift) + t, _, _ := methodReceiver(op, rcvr, int(v.flag)>>flagMethodShift) + + fv := &makeFuncImpl{ + code: code, + typ: (*funcType)(unsafe.Pointer(t)), + method: int(v.flag) >> flagMethodShift, + rcvr: rcvr, + } + + return Value{ft, unsafe.Pointer(&fv), v.flag&flagRO | flag(Func)<<flagKindShift | flagIndir} +} + +// makeValueMethod takes a method function and returns a function that +// takes a value receiver and calls the real method with a pointer to +// it. +func makeValueMethod(v Value) Value { + typ := v.typ + if typ.Kind() != Func { + panic("reflect: call of makeValueMethod with non-Func type") + } + if v.flag&flagMethodFn == 0 { + panic("reflect: call of makeValueMethod with non-MethodFn") + } - panic("reflect makeMethodValue not implemented") + switch runtime.GOARCH { + case "amd64", "386": + default: + panic("reflect.makeValueMethod not implemented for " + runtime.GOARCH) + } + + t := typ.common() + ftyp := (*funcType)(unsafe.Pointer(t)) + + // Indirect Go func value (dummy) to obtain + // actual code address. (A Go func value is a pointer + // to a C function pointer. http://golang.org/s/go11func.) + dummy := makeFuncStub + code := **(**uintptr)(unsafe.Pointer(&dummy)) + + impl := &makeFuncImpl{ + code: code, + typ: ftyp, + method: -2, + rcvr: v, + } + + return Value{t, unsafe.Pointer(&impl), flag(Func<<flagKindShift) | flagIndir} +} + +// Call the function represented by a makeFuncImpl. +func (c *makeFuncImpl) call(in []Value) []Value { + if c.method == -1 { + return c.fn(in) + } else if c.method == -2 { + if c.typ.IsVariadic() { + return c.rcvr.CallSlice(in) + } else { + return c.rcvr.Call(in) + } + } else { + m := c.rcvr.Method(c.method) + if c.typ.IsVariadic() { + return m.CallSlice(in) + } else { + return m.Call(in) + } + } } diff --git a/gcc-4.8/libgo/go/reflect/makefunc_386.S b/gcc-4.8/libgo/go/reflect/makefunc_386.S index 5878bc44c..0e2e76465 100644 --- a/gcc-4.8/libgo/go/reflect/makefunc_386.S +++ b/gcc-4.8/libgo/go/reflect/makefunc_386.S @@ -25,9 +25,13 @@ reflect.makeFuncStub: struct { esp uint32 // 0x0 eax uint32 // 0x4 - st0 uint64 // 0x8 + st0 float64 // 0x8 + sr bool // 0x10 + sf bool // 0x11 } - */ + The sr field is set by the function to a non-zero value if + the function takes a struct hidden pointer that must be + popped off the stack. */ pushl %ebp .LCFI0: @@ -45,6 +49,15 @@ reflect.makeFuncStub: leal 8(%ebp), %eax /* Set esp field in struct. */ movl %eax, -24(%ebp) + /* For MakeFunc functions that call recover. */ + movl 4(%ebp), %eax + movl %eax, (%esp) +#ifdef __PIC__ + call __go_makefunc_can_recover@PLT +#else + call __go_makefunc_can_recover +#endif + #ifdef __PIC__ call __go_get_closure@PLT #else @@ -62,9 +75,20 @@ reflect.makeFuncStub: call reflect.MakeFuncStubGo #endif + /* MakeFunc functions can no longer call recover. */ +#ifdef __PIC__ + call __go_makefunc_returning@PLT +#else + call __go_makefunc_returning +#endif + /* Set return registers. */ movl -20(%ebp), %eax + + cmpb $0, -7(%ebp) + je 2f + fldl -16(%ebp) #ifdef __SSE2__ @@ -73,12 +97,20 @@ reflect.makeFuncStub: movsd -16(%ebp), %xmm0 #endif +2: + movb -8(%ebp), %dl + addl $36, %esp popl %ebx .LCFI3: popl %ebp .LCFI4: + + testb %dl,%dl + jne 1f ret +1: + ret $4 .LFE1: #ifdef __ELF__ .size reflect.makeFuncStub, . - reflect.makeFuncStub diff --git a/gcc-4.8/libgo/go/reflect/makefunc_amd64.S b/gcc-4.8/libgo/go/reflect/makefunc_amd64.S index 9d12f193f..88302eee1 100644 --- a/gcc-4.8/libgo/go/reflect/makefunc_amd64.S +++ b/gcc-4.8/libgo/go/reflect/makefunc_amd64.S @@ -61,6 +61,14 @@ reflect.makeFuncStub: movdqa %xmm6, 0xa0(%rsp) movdqa %xmm7, 0xb0(%rsp) + /* For MakeFunc functions that call recover. */ + movq 8(%rbp), %rdi +#ifdef __PIC__ + call __go_makefunc_can_recover@PLT +#else + call __go_makefunc_can_recover +#endif + # Get function type. #ifdef __PIC__ call __go_get_closure@PLT @@ -77,6 +85,13 @@ reflect.makeFuncStub: call reflect.MakeFuncStubGo #endif + /* MakeFunc functions can no longer call recover. */ +#ifdef __PIC__ + call __go_makefunc_returning@PLT +#else + call __go_makefunc_returning +#endif + # The structure will be updated with any return values. Load # all possible return registers before returning to the caller. diff --git a/gcc-4.8/libgo/go/reflect/makefuncgo_386.go b/gcc-4.8/libgo/go/reflect/makefuncgo_386.go index 0fac1f488..45dd2d759 100644 --- a/gcc-4.8/libgo/go/reflect/makefuncgo_386.go +++ b/gcc-4.8/libgo/go/reflect/makefuncgo_386.go @@ -15,7 +15,9 @@ import "unsafe" type i386Regs struct { esp uint32 eax uint32 // Value to return in %eax. - st0 uint64 // Value to return in %st(0). + st0 float64 // Value to return in %st(0). + sr bool // Set to true if hidden struct pointer. + sf bool // Set to true if returning float } // MakeFuncStubGo implements the 386 calling convention for MakeFunc. @@ -56,10 +58,13 @@ func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) { in := make([]Value, 0, len(ftyp.in)) ap := uintptr(regs.esp) + regs.sr = false + regs.sf = false var retPtr unsafe.Pointer if retStruct { retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap)) ap += ptrSize + regs.sr = true } for _, rt := range ftyp.in { @@ -77,7 +82,7 @@ func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) { // Call the real function. - out := c.fn(in) + out := c.call(in) if len(out) != len(ftyp.out) { panic("reflect: wrong return count from function created by MakeFunc") @@ -123,13 +128,16 @@ func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) { v := out[0] w := v.iword() - if v.Kind() != Ptr && v.Kind() != UnsafePointer { - w = loadIword(unsafe.Pointer(w), v.typ.size) - } switch v.Kind() { - case Float32, Float64: - regs.st0 = uint64(uintptr(w)) - default: + case Ptr, UnsafePointer: regs.eax = uint32(uintptr(w)) + case Float32: + regs.st0 = float64(*(*float32)(unsafe.Pointer(w))) + regs.sf = true + case Float64: + regs.st0 = *(*float64)(unsafe.Pointer(w)) + regs.sf = true + default: + regs.eax = uint32(uintptr(loadIword(unsafe.Pointer(w), v.typ.size))) } } diff --git a/gcc-4.8/libgo/go/reflect/makefuncgo_amd64.go b/gcc-4.8/libgo/go/reflect/makefuncgo_amd64.go index ecc50a425..42fe03a93 100644 --- a/gcc-4.8/libgo/go/reflect/makefuncgo_amd64.go +++ b/gcc-4.8/libgo/go/reflect/makefuncgo_amd64.go @@ -319,7 +319,7 @@ argloop: // All the real arguments have been found and turned into // Value's. Call the real function. - out := c.fn(in) + out := c.call(in) if len(out) != len(ftyp.out) { panic("reflect: wrong return count from function created by MakeFunc") diff --git a/gcc-4.8/libgo/go/reflect/type.go b/gcc-4.8/libgo/go/reflect/type.go index d084f38eb..2b8342cb5 100644 --- a/gcc-4.8/libgo/go/reflect/type.go +++ b/gcc-4.8/libgo/go/reflect/type.go @@ -508,7 +508,7 @@ func (t *uncommonType) Method(i int) (m Method) { m.Type = toType(mt) x := new(unsafe.Pointer) *x = unsafe.Pointer(&p.tfn) - m.Func = Value{mt, unsafe.Pointer(x), fl | flagIndir} + m.Func = Value{mt, unsafe.Pointer(x), fl | flagIndir | flagMethodFn} m.Index = i return } diff --git a/gcc-4.8/libgo/go/reflect/value.go b/gcc-4.8/libgo/go/reflect/value.go index b199f7088..492155781 100644 --- a/gcc-4.8/libgo/go/reflect/value.go +++ b/gcc-4.8/libgo/go/reflect/value.go @@ -98,6 +98,7 @@ const ( flagIndir flagAddr flagMethod + flagMethodFn // gccgo: first fn parameter is always pointer flagKindShift = iota flagKindWidth = 5 // there are 27 kinds flagKindMask flag = 1<<flagKindWidth - 1 @@ -433,7 +434,7 @@ func (v Value) call(op string, in []Value) []Value { if v.flag&flagMethod != 0 { nin++ } - firstPointer := len(in) > 0 && t.In(0).Kind() != Ptr && v.flag&flagMethod == 0 && isMethod(v.typ) + firstPointer := len(in) > 0 && t.In(0).Kind() != Ptr && v.flag&flagMethodFn != 0 params := make([]unsafe.Pointer, nin) off := 0 if v.flag&flagMethod != 0 { @@ -484,33 +485,6 @@ func (v Value) call(op string, in []Value) []Value { return ret } -// gccgo specific test to see if typ is a method. We can tell by -// looking at the string to see if there is a receiver. We need this -// because for gccgo all methods take pointer receivers. -func isMethod(t *rtype) bool { - if Kind(t.kind) != Func { - return false - } - s := *t.string - parens := 0 - params := 0 - sawRet := false - for i, c := range s { - if c == '(' { - if parens == 0 { - params++ - } - parens++ - } else if c == ')' { - parens-- - } else if parens == 0 && c == ' ' && s[i+1] != '(' && !sawRet { - params++ - sawRet = true - } - } - return params > 2 -} - // methodReceiver returns information about the receiver // described by v. The Value v may or may not have the // flagMethod bit set, so the kind cached in v.flag should @@ -917,6 +891,16 @@ func valueInterface(v Value, safe bool) interface{} { v = makeMethodValue("Interface", v) } + if v.flag&flagMethodFn != 0 { + if v.typ.Kind() != Func { + panic("reflect: MethodFn of non-Func") + } + ft := (*funcType)(unsafe.Pointer(v.typ)) + if ft.in[0].Kind() != Ptr { + v = makeValueMethod(v) + } + } + k := v.kind() if k == Interface { // Special case: return the element inside the interface. @@ -1230,8 +1214,7 @@ func (v Value) Pointer() uintptr { // created via reflect have the same underlying code pointer, // so their Pointers are equal. The function used here must // match the one used in makeMethodValue. - // This is not properly implemented for gccgo. - f := Zero + f := makeFuncStub return **(**uintptr)(unsafe.Pointer(&f)) } p := v.val diff --git a/gcc-4.8/libgo/go/syscall/libcall_linux.go b/gcc-4.8/libgo/go/syscall/libcall_linux.go index 79de2f389..60eecd9ef 100644 --- a/gcc-4.8/libgo/go/syscall/libcall_linux.go +++ b/gcc-4.8/libgo/go/syscall/libcall_linux.go @@ -190,6 +190,9 @@ func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { //sys Adjtimex(buf *Timex) (state int, err error) //adjtimex(buf *Timex) _C_int +//sysnb Dup3(oldfd int, newfd int, flags int) (err error) +//dup3(oldfd _C_int, newfd _C_int, flags _C_int) _C_int + //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) //faccessat(dirfd _C_int, pathname *byte, mode _C_int, flags _C_int) _C_int @@ -268,6 +271,9 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, return origlen - len(buf), count, names } +//sys Getxattr(path string, attr string, dest []byte) (sz int, err error) +//getxattr(path *byte, attr *byte, buf *byte, count Size_t) Ssize_t + //sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) //inotify_add_watch(fd _C_int, pathname *byte, mask uint32) _C_int @@ -283,6 +289,9 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, //sys Klogctl(typ int, buf []byte) (n int, err error) //klogctl(typ _C_int, bufp *byte, len _C_int) _C_int +//sys Listxattr(path string, dest []byte) (sz int, err error) +//listxattr(path *byte, list *byte, size Size_t) Ssize_t + //sys Mkdirat(dirfd int, path string, mode uint32) (err error) //mkdirat(dirfd _C_int, path *byte, mode Mode_t) _C_int @@ -305,6 +314,9 @@ func Pipe2(p []int, flags int) (err error) { //sys PivotRoot(newroot string, putold string) (err error) //pivot_root(newroot *byte, putold *byte) _C_int +//sys Removexattr(path string, attr string) (err error) +//removexattr(path *byte, name *byte) _C_int + //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) //renameat(olddirfd _C_int, oldpath *byte, newdirfd _C_int, newpath *byte) _C_int @@ -338,6 +350,9 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sysnb Setresuid(ruid int, eguid int, suid int) (err error) //setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) _C_int +//sys Setxattr(path string, attr string, data []byte, flags int) (err error) +//setxattr(path *byte, name *byte, value *byte, size Size_t, flags _C_int) _C_int + //sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, err error) //splice(rfd _C_int, roff *_loff_t, wfd _C_int, woff *_loff_t, len Size_t, flags _C_uint) Ssize_t func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) { diff --git a/gcc-4.8/libgo/go/syscall/libcall_posix.go b/gcc-4.8/libgo/go/syscall/libcall_posix.go index 1e7823b54..91ff59b6c 100644 --- a/gcc-4.8/libgo/go/syscall/libcall_posix.go +++ b/gcc-4.8/libgo/go/syscall/libcall_posix.go @@ -238,6 +238,9 @@ func FDZero(set *FdSet) { //sysnb Getppid() (ppid int) //getppid() Pid_t +//sys Getpriority(which int, who int) (prio int, err error) +//getpriority(which _C_int, who _C_int) _C_int + //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) //getrlimit(resource _C_int, rlim *Rlimit) _C_int @@ -307,6 +310,9 @@ func Gettimeofday(tv *Timeval) (err error) { //sysnb Setpgid(pid int, pgid int) (err error) //setpgid(pid Pid_t, pgid Pid_t) _C_int +//sys Setpriority(which int, who int, prio int) (err error) +//setpriority(which _C_int, who _C_int, prio _C_int) _C_int + //sysnb Setreuid(ruid int, euid int) (err error) //setreuid(ruid Uid_t, euid Uid_t) _C_int diff --git a/gcc-4.8/libgo/go/syscall/socket.go b/gcc-4.8/libgo/go/syscall/socket.go index cc98d6b79..4a80a4cdb 100644 --- a/gcc-4.8/libgo/go/syscall/socket.go +++ b/gcc-4.8/libgo/go/syscall/socket.go @@ -25,7 +25,7 @@ type RawSockaddrAny struct { Pad [96]int8 } -const SizeofSockaddrAny = 0x1c +const SizeofSockaddrAny = 0x6c type SockaddrInet4 struct { Port int diff --git a/gcc-4.8/libgo/mksysinfo.sh b/gcc-4.8/libgo/mksysinfo.sh index 11bcb257a..71c328627 100755 --- a/gcc-4.8/libgo/mksysinfo.sh +++ b/gcc-4.8/libgo/mksysinfo.sh @@ -1035,6 +1035,10 @@ grep '^type _utimbuf ' gen-sysinfo.go | \ grep '^const _LOCK_' gen-sysinfo.go | sed -e 's/^\(const \)_\(LOCK_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +# The PRIO constants. +grep '^const _PRIO_' gen-sysinfo.go | \ + sed -e 's/^\(const \)_\(PRIO_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + # The GNU/Linux LINUX_REBOOT flags. grep '^const _LINUX_REBOOT_' gen-sysinfo.go | sed -e 's/^\(const \)_\(LINUX_REBOOT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} diff --git a/gcc-4.8/libgo/runtime/go-callers.c b/gcc-4.8/libgo/runtime/go-callers.c index 291dfd0d6..ae411d9c8 100644 --- a/gcc-4.8/libgo/runtime/go-callers.c +++ b/gcc-4.8/libgo/runtime/go-callers.c @@ -11,6 +11,13 @@ #include "runtime.h" #include "array.h" +/* This is set to non-zero when calling backtrace_full. This is used + to avoid getting hanging on a recursive lock in dl_iterate_phdr on + older versions of glibc when a SIGPROF signal arrives while + collecting a backtrace. */ + +uint32 runtime_in_callers; + /* Argument passed to callback function. */ struct callers_data @@ -111,8 +118,10 @@ runtime_callers (int32 skip, Location *locbuf, int32 m) data.skip = skip + 1; data.index = 0; data.max = m; + runtime_xadd (&runtime_in_callers, 1); backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback, &data); + runtime_xadd (&runtime_in_callers, -1); return data.index; } diff --git a/gcc-4.8/libgo/runtime/go-cdiv.c b/gcc-4.8/libgo/runtime/go-cdiv.c new file mode 100644 index 000000000..0a81e458c --- /dev/null +++ b/gcc-4.8/libgo/runtime/go-cdiv.c @@ -0,0 +1,46 @@ +/* go-cdiv.c -- complex division routines + + Copyright 2013 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. */ + +/* Calls to these functions are generated by the Go frontend for + division of complex64 or complex128. We use these because Go's + complex division expects slightly different results from the GCC + default. When dividing NaN+1.0i / 0+0i, Go expects NaN+NaNi but + GCC generates NaN+Infi. NaN+Infi seems wrong seems the rules of + C99 Annex G specify that if either side of a complex number is Inf, + the the whole number is Inf, but an operation involving NaN ought + to result in NaN, not Inf. */ + +__complex float +__go_complex64_div (__complex float a, __complex float b) +{ + if (__builtin_expect (b == 0+0i, 0)) + { + if (!__builtin_isinff (__real__ a) + && !__builtin_isinff (__imag__ a) + && (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a))) + { + /* Pass "1" to nanf to match math/bits.go. */ + return __builtin_nanf("1") + __builtin_nanf("1")*1i; + } + } + return a / b; +} + +__complex double +__go_complex128_div (__complex double a, __complex double b) +{ + if (__builtin_expect (b == 0+0i, 0)) + { + if (!__builtin_isinf (__real__ a) + && !__builtin_isinf (__imag__ a) + && (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a))) + { + /* Pass "1" to nan to match math/bits.go. */ + return __builtin_nan("1") + __builtin_nan("1")*1i; + } + } + return a / b; +} diff --git a/gcc-4.8/libgo/runtime/go-defer.c b/gcc-4.8/libgo/runtime/go-defer.c index 3955e0f5c..fed8db385 100644 --- a/gcc-4.8/libgo/runtime/go-defer.c +++ b/gcc-4.8/libgo/runtime/go-defer.c @@ -27,6 +27,7 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg) n->__pfn = pfn; n->__arg = arg; n->__retaddr = NULL; + n->__makefunc_can_recover = 0; g->defer = n; } diff --git a/gcc-4.8/libgo/runtime/go-defer.h b/gcc-4.8/libgo/runtime/go-defer.h index 0b20e8f6e..3298ce950 100644 --- a/gcc-4.8/libgo/runtime/go-defer.h +++ b/gcc-4.8/libgo/runtime/go-defer.h @@ -34,4 +34,10 @@ struct __go_defer_stack set by __go_set_defer_retaddr which is called by the thunks created by defer statements. */ const void *__retaddr; + + /* Set to true if a function created by reflect.MakeFunc is + permitted to recover. The return address of such a function + function will be somewhere in libffi, so __retaddr is not + useful. */ + _Bool __makefunc_can_recover; }; diff --git a/gcc-4.8/libgo/runtime/go-int-array-to-string.c b/gcc-4.8/libgo/runtime/go-int-array-to-string.c index 6cae2fd8c..e3c008a0b 100644 --- a/gcc-4.8/libgo/runtime/go-int-array-to-string.c +++ b/gcc-4.8/libgo/runtime/go-int-array-to-string.c @@ -30,6 +30,8 @@ __go_int_array_to_string (const void* p, intgo len) if (v < 0 || v > 0x10ffff) v = 0xfffd; + else if (0xd800 <= v && v <= 0xdfff) + v = 0xfffd; if (v <= 0x7f) slen += 1; @@ -56,6 +58,8 @@ __go_int_array_to_string (const void* p, intgo len) character. */ if (v < 0 || v > 0x10ffff) v = 0xfffd; + else if (0xd800 <= v && v <= 0xdfff) + v = 0xfffd; if (v <= 0x7f) *s++ = v; diff --git a/gcc-4.8/libgo/runtime/go-make-slice.c b/gcc-4.8/libgo/runtime/go-make-slice.c index 591ab37e0..f08cb012d 100644 --- a/gcc-4.8/libgo/runtime/go-make-slice.c +++ b/gcc-4.8/libgo/runtime/go-make-slice.c @@ -34,7 +34,10 @@ __go_make_slice2 (const struct __go_type_descriptor *td, uintptr_t len, std = (const struct __go_slice_type *) td; ilen = (intgo) len; - if (ilen < 0 || (uintptr_t) ilen != len) + if (ilen < 0 + || (uintptr_t) ilen != len + || (std->__element_type->__size > 0 + && len > MaxMem / std->__element_type->__size)) runtime_panicstring ("makeslice: len out of range"); icap = (intgo) cap; diff --git a/gcc-4.8/libgo/runtime/go-nosys.c b/gcc-4.8/libgo/runtime/go-nosys.c index 3ab5ea235..0a94de052 100644 --- a/gcc-4.8/libgo/runtime/go-nosys.c +++ b/gcc-4.8/libgo/runtime/go-nosys.c @@ -43,6 +43,17 @@ accept4 (int sockfd __attribute__ ((unused)), } #endif +#ifndef HAVE_DUP3 +int +dup3 (int oldfd __attribute__ ((unused)), + int newfd __attribute__ ((unused)), + int flags __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_EPOLL_CREATE1 int epoll_create1 (int flags __attribute__ ((unused))) @@ -112,6 +123,18 @@ futimesat (int dirfd __attribute__ ((unused)), } #endif +#ifndef HAVE_GETXATTR +ssize_t +getxattr (const char *path __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + void *value __attribute__ ((unused)), + size_t size __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_INOTIFY_ADD_WATCH int inotify_add_watch (int fd __attribute__ ((unused)), @@ -151,6 +174,17 @@ inotify_rm_watch (int fd __attribute__ ((unused)), } #endif +#ifndef HAVE_LISTXATTR +ssize_t +listxattr (const char *path __attribute__ ((unused)), + char *list __attribute__ ((unused)), + size_t size __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_MKDIRAT int mkdirat (int dirfd __attribute__ ((unused)), @@ -196,6 +230,16 @@ pipe2 (int pipefd[2] __attribute__ ((unused)), } #endif +#ifndef HAVE_REMOVEXATTR +int +removexattr (const char *path __attribute__ ((unused)), + const char *name __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_RENAMEAT int renameat (int olddirfd __attribute__ ((unused)), @@ -208,6 +252,19 @@ renameat (int olddirfd __attribute__ ((unused)), } #endif +#ifndef HAVE_SETXATTR +int +setxattr (const char *path __attribute__ ((unused)), + const char *name __attribute__ ((unused)), + const void *value __attribute__ ((unused)), + size_t size __attribute__ ((unused)), + int flags __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_SPLICE int splice (int fd __attribute__ ((unused)), diff --git a/gcc-4.8/libgo/runtime/go-recover.c b/gcc-4.8/libgo/runtime/go-recover.c index d6403e00d..ceb9b5725 100644 --- a/gcc-4.8/libgo/runtime/go-recover.c +++ b/gcc-4.8/libgo/runtime/go-recover.c @@ -16,12 +16,14 @@ __go_can_recover--this is, the thunk. */ _Bool -__go_can_recover (const void* retaddr) +__go_can_recover (const void *retaddr) { G *g; struct __go_defer_stack *d; const char* ret; const char* dret; + Location loc; + const byte *name; g = runtime_g (); @@ -52,7 +54,78 @@ __go_can_recover (const void* retaddr) #endif dret = (const char *) d->__retaddr; - return ret <= dret && ret + 16 >= dret; + if (ret <= dret && ret + 16 >= dret) + return 1; + + /* If the function calling recover was created by reflect.MakeFunc, + then RETADDR will be somewhere in libffi. Our caller is + permitted to recover if it was called from libffi. */ + if (!d->__makefunc_can_recover) + return 0; + + if (runtime_callers (2, &loc, 1) < 1) + return 0; + + /* If we have no function name, then we weren't called by Go code. + Guess that we were called by libffi. */ + if (loc.function.len == 0) + return 1; + + if (loc.function.len < 4) + return 0; + name = loc.function.str; + if (*name == '_') + { + if (loc.function.len < 5) + return 0; + ++name; + } + + if (name[0] == 'f' && name[1] == 'f' && name[2] == 'i' && name[3] == '_') + return 1; + + /* We may also be called by reflect.makeFuncImpl.call, for a + function created by reflect.MakeFunc. */ + if (__builtin_strstr ((const char *) name, "makeFuncImpl") != NULL) + return 1; + + return 0; +} + +/* This function is called when code is about to enter a function + created by reflect.MakeFunc. It is called by the function stub + used by MakeFunc. If the stub is permitted to call recover, then a + real MakeFunc function is permitted to call recover. */ + +void +__go_makefunc_can_recover (const void *retaddr) +{ + struct __go_defer_stack *d; + + d = runtime_g ()->defer; + if (d != NULL + && !d->__makefunc_can_recover + && __go_can_recover (retaddr)) + d->__makefunc_can_recover = 1; +} + +/* This function is called when code is about to exit a function + created by reflect.MakeFunc. It is called by the function stub + used by MakeFunc. It clears the __makefunc_can_recover field. + It's OK to always clear this field, because __go_can_recover will + only be called by a stub created for a function that calls recover. + That stub will not call a function created by reflect.MakeFunc, so + by the time we get here any caller higher up on the call stack no + longer needs the information. */ + +void +__go_makefunc_returning (void) +{ + struct __go_defer_stack *d; + + d = runtime_g ()->defer; + if (d != NULL) + d->__makefunc_can_recover = 0; } /* This is only called when it is valid for the caller to recover the diff --git a/gcc-4.8/libgo/runtime/go-reflect-call.c b/gcc-4.8/libgo/runtime/go-reflect-call.c index 5cf370798..12bd0d7c2 100644 --- a/gcc-4.8/libgo/runtime/go-reflect-call.c +++ b/gcc-4.8/libgo/runtime/go-reflect-call.c @@ -98,9 +98,12 @@ go_struct_to_ffi (const struct __go_struct_type *descriptor) const struct __go_struct_field *fields; int i; + field_count = descriptor->__fields.__count; + if (field_count == 0) { + return &ffi_type_void; + } ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); ret->type = FFI_TYPE_STRUCT; - field_count = descriptor->__fields.__count; fields = (const struct __go_struct_field *) descriptor->__fields.__values; ret->elements = (ffi_type **) __go_alloc ((field_count + 1) * sizeof (ffi_type *)); diff --git a/gcc-4.8/libgo/runtime/go-signal.c b/gcc-4.8/libgo/runtime/go-signal.c index 9771b71cf..41a807943 100644 --- a/gcc-4.8/libgo/runtime/go-signal.c +++ b/gcc-4.8/libgo/runtime/go-signal.c @@ -234,7 +234,7 @@ runtime_sighandler (int sig, Siginfo *info, G *g; g = runtime_g (); - runtime_traceback (g); + runtime_traceback (); runtime_tracebackothers (g); /* The gc library calls runtime_dumpregs here, and provides @@ -399,6 +399,9 @@ sig_tramp_info (int sig, Siginfo *info, void *context) { G *gp; M *mp; +#ifdef USING_SPLIT_STACK + void *stack_context[10]; +#endif /* We are now running on the stack registered via sigaltstack. (Actually there is a small span of time between runtime_siginit @@ -409,7 +412,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context) if (gp != NULL) { #ifdef USING_SPLIT_STACK - __splitstack_getcontext (&gp->stack_context[0]); + __splitstack_getcontext (&stack_context[0]); #endif } @@ -432,7 +435,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context) if (gp != NULL) { #ifdef USING_SPLIT_STACK - __splitstack_setcontext (&gp->stack_context[0]); + __splitstack_setcontext (&stack_context[0]); #endif } } diff --git a/gcc-4.8/libgo/runtime/malloc.goc b/gcc-4.8/libgo/runtime/malloc.goc index 8ccaa6b88..d6ecfe463 100644 --- a/gcc-4.8/libgo/runtime/malloc.goc +++ b/gcc-4.8/libgo/runtime/malloc.goc @@ -541,7 +541,6 @@ runtime_settype_flush(M *mp, bool sysalloc) // (Manually inlined copy of runtime_MHeap_Lookup) p = (uintptr)v>>PageShift; - if(sizeof(void*) == 8) p -= (uintptr)runtime_mheap->arena_start >> PageShift; s = runtime_mheap->map[p]; diff --git a/gcc-4.8/libgo/runtime/mgc0.c b/gcc-4.8/libgo/runtime/mgc0.c index c3b32111c..032a43d01 100644 --- a/gcc-4.8/libgo/runtime/mgc0.c +++ b/gcc-4.8/libgo/runtime/mgc0.c @@ -174,7 +174,7 @@ static struct { Obj *roots; uint32 nroot; uint32 rootcap; -} work; +} work __attribute__((aligned(8))); enum { GC_DEFAULT_PTR = GC_NUM_INSTR, @@ -239,7 +239,6 @@ markonly(void *obj) // (Manually inlined copy of MHeap_LookupMaybe.) k = (uintptr)obj>>PageShift; x = k; - if(sizeof(void*) == 8) x -= (uintptr)runtime_mheap->arena_start>>PageShift; s = runtime_mheap->map[x]; if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse) @@ -418,7 +417,6 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf // (Manually inlined copy of MHeap_LookupMaybe.) k = (uintptr)obj>>PageShift; x = k; - if(sizeof(void*) == 8) x -= (uintptr)arena_start>>PageShift; s = runtime_mheap->map[x]; if(s == nil || k < s->start || k - s->start >= s->npages || s->state != MSpanInUse) @@ -466,7 +464,6 @@ flushptrbuf(PtrTarget *ptrbuf, PtrTarget **ptrbufpos, Obj **_wp, Workbuf **_wbuf // Ask span about size class. // (Manually inlined copy of MHeap_Lookup.) x = (uintptr)obj >> PageShift; - if(sizeof(void*) == 8) x -= (uintptr)arena_start>>PageShift; s = runtime_mheap->map[x]; @@ -585,7 +582,6 @@ checkptr(void *obj, uintptr objti) if(t == nil) return; x = (uintptr)obj >> PageShift; - if(sizeof(void*) == 8) x -= (uintptr)(runtime_mheap->arena_start)>>PageShift; s = runtime_mheap->map[x]; objstart = (byte*)((uintptr)s->start<<PageShift); diff --git a/gcc-4.8/libgo/runtime/mheap.c b/gcc-4.8/libgo/runtime/mheap.c index b4d94b685..50ec1527f 100644 --- a/gcc-4.8/libgo/runtime/mheap.c +++ b/gcc-4.8/libgo/runtime/mheap.c @@ -150,7 +150,6 @@ HaveSpan: runtime_MSpan_Init(t, s->start + npage, s->npages - npage); s->npages = npage; p = t->start; - if(sizeof(void*) == 8) p -= ((uintptr)h->arena_start>>PageShift); if(p > 0) h->map[p-1] = s; @@ -169,7 +168,6 @@ HaveSpan: s->elemsize = (sizeclass==0 ? s->npages<<PageShift : (uintptr)runtime_class_to_size[sizeclass]); s->types.compression = MTypes_Empty; p = s->start; - if(sizeof(void*) == 8) p -= ((uintptr)h->arena_start>>PageShift); for(n=0; n<npage; n++) h->map[p+n] = s; @@ -241,7 +239,6 @@ MHeap_Grow(MHeap *h, uintptr npage) mstats.mspan_sys = h->spanalloc.sys; runtime_MSpan_Init(s, (uintptr)v>>PageShift, ask>>PageShift); p = s->start; - if(sizeof(void*) == 8) p -= ((uintptr)h->arena_start>>PageShift); h->map[p] = s; h->map[p + s->npages - 1] = s; @@ -259,7 +256,6 @@ runtime_MHeap_Lookup(MHeap *h, void *v) uintptr p; p = (uintptr)v; - if(sizeof(void*) == 8) p -= (uintptr)h->arena_start; return h->map[p >> PageShift]; } @@ -281,7 +277,6 @@ runtime_MHeap_LookupMaybe(MHeap *h, void *v) return nil; p = (uintptr)v>>PageShift; q = p; - if(sizeof(void*) == 8) q -= (uintptr)h->arena_start >> PageShift; s = h->map[q]; if(s == nil || p < s->start || p - s->start >= s->npages) @@ -332,7 +327,6 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) // Coalesce with earlier, later spans. p = s->start; - if(sizeof(void*) == 8) p -= (uintptr)h->arena_start >> PageShift; if(p > 0 && (t = h->map[p-1]) != nil && t->state != MSpanInUse) { tp = (uintptr*)(t->start<<PageShift); diff --git a/gcc-4.8/libgo/runtime/proc.c b/gcc-4.8/libgo/runtime/proc.c index 0e77a3e06..4ca975680 100644 --- a/gcc-4.8/libgo/runtime/proc.c +++ b/gcc-4.8/libgo/runtime/proc.c @@ -1716,10 +1716,30 @@ goexit0(G *gp) // entersyscall is going to return immediately after. void runtime_entersyscall(void) __attribute__ ((no_split_stack)); +static void doentersyscall(void) __attribute__ ((no_split_stack, noinline)); void runtime_entersyscall() { + // Save the registers in the g structure so that any pointers + // held in registers will be seen by the garbage collector. + getcontext(&g->gcregs); + + // Do the work in a separate function, so that this function + // doesn't save any registers on its own stack. If this + // function does save any registers, we might store the wrong + // value in the call to getcontext. + // + // FIXME: This assumes that we do not need to save any + // callee-saved registers to access the TLS variable g. We + // don't want to put the ucontext_t on the stack because it is + // large and we can not split the stack here. + doentersyscall(); +} + +static void +doentersyscall() +{ if(m->profilehz > 0) runtime_setprof(false); @@ -1736,10 +1756,6 @@ runtime_entersyscall() } #endif - // Save the registers in the g structure so that any pointers - // held in registers will be seen by the garbage collector. - getcontext(&g->gcregs); - g->status = Gsyscall; if(runtime_atomicload(&runtime_sched.sysmonwait)) { // TODO: fast atomic @@ -2239,6 +2255,14 @@ runtime_sigprof() if(prof.fn == nil || prof.hz == 0) return; + if(runtime_atomicload(&runtime_in_callers) > 0) { + // If SIGPROF arrived while already fetching runtime + // callers we can have trouble on older systems + // because the unwind library calls dl_iterate_phdr + // which was not recursive in the past. + return; + } + runtime_lock(&prof); if(prof.fn == nil) { runtime_unlock(&prof); diff --git a/gcc-4.8/libgo/runtime/runtime.h b/gcc-4.8/libgo/runtime/runtime.h index d2e7d4c11..964b2e31e 100644 --- a/gcc-4.8/libgo/runtime/runtime.h +++ b/gcc-4.8/libgo/runtime/runtime.h @@ -440,7 +440,7 @@ enum { }; void runtime_hashinit(void); -void runtime_traceback(); +void runtime_traceback(void); void runtime_tracebackothers(G*); /* @@ -756,6 +756,7 @@ extern struct backtrace_state *__go_get_backtrace_state(void); extern _Bool __go_file_line(uintptr, String*, String*, intgo *); extern byte* runtime_progname(); extern void runtime_main(void*); +extern uint32 runtime_in_callers; int32 getproccount(void); diff --git a/gcc-4.8/libgo/testsuite/gotest b/gcc-4.8/libgo/testsuite/gotest index 4015ed1e8..155c7a861 100755 --- a/gcc-4.8/libgo/testsuite/gotest +++ b/gcc-4.8/libgo/testsuite/gotest @@ -369,7 +369,7 @@ localname() { { text="T" case "$GOARCH" in - ppc64) text="D" ;; + ppc64) text="[TD]" ;; esac symtogo='sed -e s/_test/XXXtest/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/' |