From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31931 invoked by alias); 20 May 2011 00:19:36 -0000 Received: (qmail 31842 invoked by uid 22791); 20 May 2011 00:19:28 -0000 X-SWARE-Spam-Status: No, hits=-0.7 required=5.0 tests=AWL,BAYES_50,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_PASS,TW_BF,TW_FD,TW_FN,TW_TD,TW_XT,T_RP_MATCHES_RCVD,T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.67) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 20 May 2011 00:19:06 +0000 Received: from hpaq2.eem.corp.google.com (hpaq2.eem.corp.google.com [172.25.149.2]) by smtp-out.google.com with ESMTP id p4K0J3T1029940 for ; Thu, 19 May 2011 17:19:03 -0700 Received: from pxi9 (pxi9.prod.google.com [10.243.27.9]) by hpaq2.eem.corp.google.com with ESMTP id p4K0IsBB026718 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Thu, 19 May 2011 17:19:02 -0700 Received: by pxi9 with SMTP id 9so2220836pxi.0 for ; Thu, 19 May 2011 17:19:01 -0700 (PDT) Received: by 10.68.36.73 with SMTP id o9mr5769353pbj.67.1305850741655; Thu, 19 May 2011 17:19:01 -0700 (PDT) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id 8sm2078804pbw.23.2011.05.19.17.18.57 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 19 May 2011 17:19:00 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Update to current Go library Date: Fri, 20 May 2011 09:44:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-05/txt/msg01427.txt.bz2 --=-=-= Content-length: 449 I have committed a patch to update libgo to the current version of the Go library. This patch includes some minor changes to the Go frontend and to the testsuite. The patch is too large to include here, but most of it is simply a copy of the changes to the master Go library. I have appended the changes to the files which are not in the master library. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=foo.patch Content-Description: patch Content-length: 67123 Index: gcc/go/gofrontend/types.h =================================================================== --- gcc/go/gofrontend/types.h (revision 173742) +++ gcc/go/gofrontend/types.h (working copy) @@ -1044,7 +1044,7 @@ class Type // Build a composite literal for one method. Expression* method_constructor(Gogo*, Type* method_type, const std::string& name, - const Method*) const; + const Method*, bool only_value_methods) const; static tree build_receive_return_type(tree type); Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 173742) +++ gcc/go/gofrontend/types.cc (working copy) @@ -1432,7 +1432,7 @@ Type::methods_constructor(Gogo* gogo, Ty p != smethods.end(); ++p) vals->push_back(this->method_constructor(gogo, method_type, p->first, - p->second)); + p->second, only_value_methods)); return Expression::make_slice_composite_literal(methods_type, vals, bloc); } @@ -1444,7 +1444,8 @@ Type::methods_constructor(Gogo* gogo, Ty Expression* Type::method_constructor(Gogo*, Type* method_type, const std::string& method_name, - const Method* m) const + const Method* m, + bool only_value_methods) const { source_location bloc = BUILTINS_LOCATION; @@ -1487,6 +1488,25 @@ Type::method_constructor(Gogo*, Type* me ++p; go_assert(p->field_name() == "typ"); + if (!only_value_methods && m->is_value_method()) + { + // This is a value method on a pointer type. Change the type of + // the method to use a pointer receiver. The implementation + // always uses a pointer receiver anyhow. + Type* rtype = mtype->receiver()->type(); + Type* prtype = Type::make_pointer_type(rtype); + Typed_identifier* receiver = + new Typed_identifier(mtype->receiver()->name(), prtype, + mtype->receiver()->location()); + mtype = Type::make_function_type(receiver, + (mtype->parameters() == NULL + ? NULL + : mtype->parameters()->copy()), + (mtype->results() == NULL + ? NULL + : mtype->results()->copy()), + mtype->location()); + } vals->push_back(Expression::make_type_descriptor(mtype, bloc)); ++p; @@ -2779,14 +2799,7 @@ Function_type::type_descriptor_params(Ty + (receiver != NULL ? 1 : 0)); if (receiver != NULL) - { - Type* rtype = receiver->type(); - // The receiver is always passed as a pointer. FIXME: Is this - // right? Should that fact affect the type descriptor? - if (rtype->points_to() == NULL) - rtype = Type::make_pointer_type(rtype); - vals->push_back(Expression::make_type_descriptor(rtype, bloc)); - } + vals->push_back(Expression::make_type_descriptor(receiver->type(), bloc)); if (params != NULL) { @@ -4822,9 +4835,10 @@ Array_type::make_array_type_descriptor_t Type* uintptr_type = Type::lookup_integer_type("uintptr"); Struct_type* sf = - Type::make_builtin_struct_type(3, + Type::make_builtin_struct_type(4, "", tdt, "elem", ptdt, + "slice", ptdt, "len", uintptr_type); ret = Type::make_builtin_named_type("ArrayType", sf); @@ -4891,6 +4905,11 @@ Array_type::array_type_descriptor(Gogo* vals->push_back(Expression::make_type_descriptor(this->element_type_, bloc)); ++p; + go_assert(p->field_name() == "slice"); + Type* slice_type = Type::make_array_type(this->element_type_, NULL); + vals->push_back(Expression::make_type_descriptor(slice_type, bloc)); + + ++p; go_assert(p->field_name() == "len"); vals->push_back(Expression::make_cast(p->type(), this->length_, bloc)); @@ -5375,8 +5394,9 @@ Channel_type::do_make_expression_tree(Tr Gogo* gogo = context->gogo(); tree channel_type = type_to_tree(this->get_backend(gogo)); - tree element_tree = type_to_tree(this->element_type_->get_backend(gogo)); - tree element_size_tree = size_in_bytes(element_tree); + Type* ptdt = Type::make_type_descriptor_ptr_type(); + tree element_type_descriptor = + this->element_type_->type_descriptor_pointer(gogo); tree bad_index = NULL_TREE; @@ -5402,8 +5422,8 @@ Channel_type::do_make_expression_tree(Tr "__go_new_channel", 2, channel_type, - sizetype, - element_size_tree, + type_to_tree(ptdt->get_backend(gogo)), + element_type_descriptor, sizetype, expr_tree); if (ret == error_mark_node) @@ -6242,7 +6262,16 @@ Interface_type::do_reflection(Gogo* gogo if (p != this->methods_->begin()) ret->append(";"); ret->push_back(' '); - ret->append(Gogo::unpack_hidden_name(p->name())); + if (!Gogo::is_hidden_name(p->name())) + ret->append(p->name()); + else + { + // This matches what the gc compiler does. + std::string prefix = Gogo::hidden_name_prefix(p->name()); + ret->append(prefix.substr(prefix.find('.') + 1)); + ret->push_back('.'); + ret->append(Gogo::unpack_hidden_name(p->name())); + } std::string sub = p->type()->reflection(gogo); go_assert(sub.compare(0, 4, "func") == 0); sub = sub.substr(4); Index: libgo/Makefile.am =================================================================== --- libgo/Makefile.am (revision 173685) +++ libgo/Makefile.am (working copy) @@ -248,7 +248,8 @@ toolexeclibgogo_DATA = \ go/printer.gox \ go/scanner.gox \ go/token.gox \ - go/typechecker.gox + go/typechecker.gox \ + go/types.gox toolexeclibgohashdir = $(toolexeclibgodir)/hash @@ -262,14 +263,19 @@ toolexeclibgohttpdir = $(toolexeclibgodi toolexeclibgohttp_DATA = \ http/cgi.gox \ + http/fcgi.gox \ http/httptest.gox \ - http/pprof.gox + http/pprof.gox \ + http/spdy.gox toolexeclibgoimagedir = $(toolexeclibgodir)/image toolexeclibgoimage_DATA = \ + image/gif.gox \ image/jpeg.gox \ - image/png.gox + image/png.gox \ + image/tiff.gox \ + image/ycbcr.gox toolexeclibgoindexdir = $(toolexeclibgodir)/index @@ -303,6 +309,7 @@ endif toolexeclibgoos_DATA = \ $(os_inotify_gox) \ + os/user.gox \ os/signal.gox toolexeclibgopathdir = $(toolexeclibgodir)/path @@ -404,6 +411,7 @@ runtime_files = \ runtime/go-send-nb-big.c \ runtime/go-send-nb-small.c \ runtime/go-send-small.c \ + runtime/go-setenv.c \ runtime/go-signal.c \ runtime/go-strcmp.c \ runtime/go-string-to-byte-array.c \ @@ -560,6 +568,7 @@ go_http_files = \ go/http/persist.go \ go/http/request.go \ go/http/response.go \ + go/http/reverseproxy.go \ go/http/server.go \ go/http/status.go \ go/http/transfer.go \ @@ -656,8 +665,17 @@ go_net_newpollserver_file = go/net/newpo endif # !LIBGO_IS_LINUX endif # !LIBGO_IS_RTEMS +if LIBGO_IS_LINUX +go_net_cgo_file = go/net/cgo_linux.go +go_net_sock_file = go/net/sock_linux.go +else +go_net_cgo_file = go/net/cgo_bsd.go +go_net_sock_file = go/net/sock_bsd.go +endif + go_net_files = \ - go/net/cgo_stub.go \ + go/net/cgo_unix.go \ + $(go_net_cgo_file) \ go/net/dial.go \ go/net/dnsclient.go \ go/net/dnsconfig.go \ @@ -676,6 +694,7 @@ go_net_files = \ go/net/pipe.go \ go/net/port.go \ go/net/sock.go \ + $(go_net_sock_file) \ go/net/tcpsock.go \ go/net/udpsock.go \ go/net/unixsock.go @@ -1002,7 +1021,6 @@ go_crypto_subtle_files = \ go/crypto/subtle/constant_time.go go_crypto_tls_files = \ go/crypto/tls/alert.go \ - go/crypto/tls/ca_set.go \ go/crypto/tls/cipher_suites.go \ go/crypto/tls/common.go \ go/crypto/tls/conn.go \ @@ -1015,6 +1033,8 @@ go_crypto_tls_files = \ go_crypto_twofish_files = \ go/crypto/twofish/twofish.go go_crypto_x509_files = \ + go/crypto/x509/cert_pool.go \ + go/crypto/x509/verify.go \ go/crypto/x509/x509.go go_crypto_xtea_files = \ go/crypto/xtea/block.go \ @@ -1130,6 +1150,12 @@ go_go_typechecker_files = \ go/go/typechecker/type.go \ go/go/typechecker/typechecker.go \ go/go/typechecker/universe.go +go_go_types_files = \ + go/go/types/const.go \ + go/go/types/exportdata.go \ + go/go/types/gcimporter.go \ + go/go/types/types.go \ + go/go/types/universe.go go_hash_adler32_files = \ go/hash/adler32/adler32.go @@ -1143,21 +1169,39 @@ go_hash_fnv_files = \ go_http_cgi_files = \ go/http/cgi/child.go \ go/http/cgi/host.go +go_http_fcgi_files = \ + go/http/fcgi/child.go \ + go/http/fcgi/fcgi.go go_http_httptest_files = \ go/http/httptest/recorder.go \ go/http/httptest/server.go go_http_pprof_files = \ go/http/pprof/pprof.go +go_http_spdy_files = \ + go/http/spdy/protocol.go + +go_image_gif_files = \ + go/image/gif/reader.go go_image_jpeg_files = \ + go/image/jpeg/fdct.go \ go/image/jpeg/huffman.go \ go/image/jpeg/idct.go \ - go/image/jpeg/reader.go + go/image/jpeg/reader.go \ + go/image/jpeg/writer.go go_image_png_files = \ go/image/png/reader.go \ go/image/png/writer.go +go_image_tiff_files = \ + go/image/tiff/buffer.go \ + go/image/tiff/consts.go \ + go/image/tiff/reader.go + +go_image_ycbcr_files = \ + go/image/ycbcr/ycbcr.go + go_index_suffixarray_files = \ go/index/suffixarray/qsufsort.go \ go/index/suffixarray/suffixarray.go @@ -1167,6 +1211,7 @@ go_io_ioutil_files = \ go/io/ioutil/tempfile.go go_mime_multipart_files = \ + go/mime/multipart/formdata.go \ go/mime/multipart/multipart.go go_net_dict_files = \ @@ -1182,6 +1227,10 @@ go_net_textproto_files = \ go_os_inotify_files = \ go/os/inotify/inotify_linux.go +go_os_user_files = \ + go/os/user/user.go \ + go/os/user/lookup_unix.go + go_os_signal_files = \ go/os/signal/signal.go \ unix.go @@ -1485,21 +1534,28 @@ libgo_go_objs = \ go/scanner.lo \ go/token.lo \ go/typechecker.lo \ + go/types.lo \ hash/adler32.lo \ hash/crc32.lo \ hash/crc64.lo \ hash/fnv.lo \ http/cgi.lo \ + http/fcgi.lo \ http/httptest.lo \ http/pprof.lo \ + http/spdy.lo \ + image/gif.lo \ image/jpeg.lo \ image/png.lo \ + image/tiff.lo \ + image/ycbcr.lo \ index/suffixarray.lo \ io/ioutil.lo \ mime/multipart.lo \ net/dict.lo \ net/textproto.lo \ $(os_lib_inotify_lo) \ + os/user.lo \ os/signal.lo \ path/filepath.lo \ rpc/jsonrpc.lo \ @@ -1711,11 +1767,12 @@ html/check: $(CHECK_DEPS) @$(CHECK) .PHONY: html/check -http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \ - crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \ - io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \ - net.gox net/textproto.gox os.gox path.gox path/filepath.gox \ - sort.gox strconv.gox strings.gox sync.gox time.gox utf8.gox +http/http.lo: $(go_http_files) bufio.gox bytes.gox compress/gzip.gox \ + container/vector.gox crypto/rand.gox crypto/tls.gox \ + encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \ + mime.gox mime/multipart.gox net.gox net/textproto.gox os.gox \ + path.gox path/filepath.gox sort.gox strconv.gox strings.gox \ + sync.gox time.gox utf8.gox $(BUILDPACKAGE) http/check: $(CHECK_DEPS) @$(CHECK) @@ -1755,7 +1812,7 @@ math/check: $(CHECK_DEPS) @$(CHECK) .PHONY: math/check -mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox os.gox strings.gox \ +mime/mime.lo: $(go_mime_files) bufio.gox bytes.gox fmt.gox os.gox strings.gox \ sync.gox unicode.gox $(BUILDPACKAGE) mime/check: $(CHECK_DEPS) @@ -1763,8 +1820,8 @@ mime/check: $(CHECK_DEPS) .PHONY: mime/check net/net.lo: $(go_net_files) bytes.gox fmt.gox io.gox os.gox rand.gox \ - reflect.gox strconv.gox strings.gox sync.gox syscall.gox \ - time.gox + reflect.gox sort.gox strconv.gox strings.gox sync.gox \ + syscall.gox time.gox $(BUILDPACKAGE) net/check: $(CHECK_DEPS) @$(CHECK_ON_REQUEST) @@ -1945,8 +2002,8 @@ xml/check: $(CHECK_DEPS) @$(CHECK) .PHONY: xml/check -archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox os.gox strconv.gox \ - strings.gox +archive/tar.lo: $(go_archive_tar_files) bytes.gox io.gox io/ioutil.gox os.gox \ + strconv.gox strings.gox $(BUILDPACKAGE) archive/tar/check: $(CHECK_DEPS) @$(MKDIR_P) archive/tar @@ -2148,8 +2205,7 @@ crypto/ripemd160/check: $(CHECK_DEPS) .PHONY: crypto/ripemd160/check crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \ - crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \ - sync.gox + crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox $(BUILDPACKAGE) crypto/rsa/check: $(CHECK_DEPS) @$(MKDIR_P) crypto/rsa @@ -2184,13 +2240,13 @@ crypto/subtle/check: $(CHECK_DEPS) @$(CHECK) .PHONY: crypto/subtle/check -crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \ - container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \ - crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \ - crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \ - crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \ - crypto/x509.gox encoding/pem.gox fmt.gox hash.gox io.gox \ - io/ioutil.gox net.gox os.gox strings.gox sync.gox time.gox +crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \ + crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \ + crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \ + crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \ + crypto/x509.gox encoding/pem.gox hash.gox io.gox \ + io/ioutil.gox net.gox os.gox strconv.gox strings.gox sync.gox \ + time.gox $(BUILDPACKAGE) crypto/tls/check: $(CHECK_DEPS) @$(MKDIR_P) crypto/tls @@ -2204,9 +2260,10 @@ crypto/twofish/check: $(CHECK_DEPS) @$(CHECK) .PHONY: crypto/twofish/check -crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \ - crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \ - strings.gox time.gox +crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox bytes.gox \ + container/vector.gox crypto.gox crypto/rsa.gox \ + crypto/sha1.gox encoding/pem.gox hash.gox os.gox strings.gox \ + time.gox $(BUILDPACKAGE) crypto/x509/check: $(CHECK_DEPS) @$(MKDIR_P) crypto/x509 @@ -2220,9 +2277,8 @@ crypto/xtea/check: $(CHECK_DEPS) @$(CHECK) .PHONY: crypto/xtea/check -crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bytes.gox \ - crypto/openpgp/error.gox encoding/base64.gox \ - encoding/line.gox io.gox os.gox +crypto/openpgp/armor.lo: $(go_crypto_openpgp_armor_files) bufio.gox bytes.gox \ + crypto/openpgp/error.gox encoding/base64.gox io.gox os.gox $(BUILDPACKAGE) crypto/openpgp/armor/check: $(CHECK_DEPS) @$(MKDIR_P) crypto/openpgp/armor @@ -2374,7 +2430,7 @@ exp/datafmt/check: $(CHECK_DEPS) @$(CHECK) .PHONY: exp/datafmt/check -exp/draw.lo: $(go_exp_draw_files) image.gox os.gox +exp/draw.lo: $(go_exp_draw_files) image.gox image/ycbcr.gox os.gox $(BUILDPACKAGE) exp/draw/check: $(CHECK_DEPS) @$(MKDIR_P) exp/draw @@ -2448,6 +2504,15 @@ go/typechecker/check: $(CHECK_DEPS) @$(CHECK) .PHONY: go/typechecker/check +go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \ + go/token.gox io.gox os.gox path/filepath.gox runtime.gox \ + scanner.gox strconv.gox strings.gox + $(BUILDPACKAGE) +go/types/check: $(CHECK_DEPS) + @$(MKDIR_P) go/types + @$(CHECK) +.PHONY: go/types/check + hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox $(BUILDPACKAGE) hash/adler32/check: $(CHECK_DEPS) @@ -2476,15 +2541,25 @@ hash/fnv/check: $(CHECK_DEPS) @$(CHECK) .PHONY: hash/fnv/check -http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox encoding/line.gox \ - exec.gox fmt.gox http.gox io.gox io/ioutil.gox log.gox \ - os.gox path/filepath.gox regexp.gox strconv.gox strings.gox +http/cgi.lo: $(go_http_cgi_files) bufio.gox bytes.gox crypto/tls.gox \ + exec.gox fmt.gox http.gox net.gox io.gox io/ioutil.gox \ + log.gox os.gox path/filepath.gox regexp.gox strconv.gox \ + strings.gox $(BUILDPACKAGE) http/cgi/check: $(CHECK_DEPS) @$(MKDIR_P) http/cgi @$(CHECK) .PHONY: http/cgi/check +http/fcgi.lo: $(go_http_fcgi_files) bufio.gox bytes.gox encoding/binary.gox \ + fmt.gox http.gox http/cgi.gox io.gox net.gox os.gox sync.gox \ + time.gox + $(BUILDPACKAGE) +http/fcgi/check: $(CHECK_DEPS) + @$(MKDIR_P) http/fcgi + @$(CHECK) +.PHONY: http/fcgi/check + http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \ crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox $(BUILDPACKAGE) @@ -2493,15 +2568,33 @@ http/httptest/check: $(CHECK_DEPS) @$(CHECK) .PHONY: http/httptest/check -http/pprof.lo: $(go_http_pprof_files) bufio.gox fmt.gox http.gox os.gox \ - runtime.gox runtime/pprof.gox strconv.gox strings.gox +http/pprof.lo: $(go_http_pprof_files) bufio.gox bytes.gox fmt.gox http.gox \ + os.gox runtime.gox runtime/pprof.gox strconv.gox strings.gox $(BUILDPACKAGE) http/pprof/check: $(CHECK_DEPS) @$(MKDIR_P) http/pprof @$(CHECK) .PHONY: http/pprof/check -image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox io.gox os.gox +http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \ + encoding/binary.gox http.gox io.gox os.gox strconv.gox \ + strings.gox sync.gox + $(BUILDPACKAGE) +http/spdy/check: $(CHECK_DEPS) + @$(MKDIR_P) http/spdy + @$(CHECK) +.PHONY: http/spdy/check + +image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \ + image.gox io.gox os.gox + $(BUILDPACKAGE) +image/gif/check: $(CHECK_DEPS) + @$(MKDIR_P) image/gif + @$(CHECK) +.PHONY: image/gif/check + +image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \ + io.gox os.gox $(BUILDPACKAGE) image/jpeg/check: $(CHECK_DEPS) @$(MKDIR_P) image/jpeg @@ -2516,6 +2609,21 @@ image/png/check: $(CHECK_DEPS) @$(CHECK) .PHONY: image/png/check +image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \ + encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox + $(BUILDPACKAGE) +image/tiff/check: $(CHECK_DEPS) + @$(MKDIR_P) image/tiff + @$(CHECK) +.PHONY: image/tiff/check + +image/ycbcr.lo: $(go_image_ycbcr_files) image.gox + $(BUILDPACKAGE) +image/ycbcr/check: $(CHECK_DEPS) + @$(MKDIR_P) image/ycbcr + @$(CHECK) +.PHONY: image/ycbcr/check + index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \ sort.gox $(BUILDPACKAGE) @@ -2532,8 +2640,9 @@ io/ioutil/check: $(CHECK_DEPS) @$(CHECK) .PHONY: io/ioutil/check -mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox io.gox \ - mime.gox net/textproto.gox os.gox regexp.gox strings.gox +mime/multipart.lo: $(go_mime_multipart_files) bufio.gox bytes.gox fmt.gox \ + io.gox io/ioutil.gox mime.gox net/textproto.gox os.gox \ + regexp.gox $(BUILDPACKAGE) mime/multipart/check: $(CHECK_DEPS) @$(MKDIR_P) mime/multipart @@ -2560,6 +2669,14 @@ os/inotify/check: $(CHECK_DEPS) @$(CHECK) .PHONY: os/inotify/check +os/user.lo: $(go_os_user_files) fmt.gox os.gox runtime.gox strconv.gox \ + strings.gox syscall.gox + $(BUILDPACKAGE) +os/user/check: $(CHECK_DEPS) + @$(MKDIR_P) os/user + @$(CHECK) +.PHONY: os/user/check + os/signal.lo: $(go_os_signal_files) runtime.gox strconv.gox $(BUILDPACKAGE) os/signal/check: $(CHECK_DEPS) @@ -2886,6 +3003,8 @@ go/token.gox: go/token.lo $(BUILDGOX) go/typechecker.gox: go/typechecker.lo $(BUILDGOX) +go/types.gox: go/types.lo + $(BUILDGOX) hash/adler32.gox: hash/adler32.lo $(BUILDGOX) @@ -2898,15 +3017,25 @@ hash/fnv.gox: hash/fnv.lo http/cgi.gox: http/cgi.lo $(BUILDGOX) +http/fcgi.gox: http/fcgi.lo + $(BUILDGOX) http/httptest.gox: http/httptest.lo $(BUILDGOX) http/pprof.gox: http/pprof.lo $(BUILDGOX) +http/spdy.gox: http/spdy.lo + $(BUILDGOX) +image/gif.gox: image/gif.lo + $(BUILDGOX) image/jpeg.gox: image/jpeg.lo $(BUILDGOX) image/png.gox: image/png.lo $(BUILDGOX) +image/tiff.gox: image/tiff.lo + $(BUILDGOX) +image/ycbcr.gox: image/ycbcr.lo + $(BUILDGOX) index/suffixarray.gox: index/suffixarray.lo $(BUILDGOX) @@ -2924,6 +3053,8 @@ net/textproto.gox: net/textproto.lo os/inotify.gox: os/inotify.lo $(BUILDGOX) +os/user.gox: os/user.lo + $(BUILDGOX) os/signal.gox: os/signal.lo $(BUILDGOX) @@ -3054,22 +3185,30 @@ TEST_PACKAGES = \ exp/datafmt/check \ exp/draw/check \ exp/eval/check \ + go/ast/check \ go/parser/check \ go/printer/check \ go/scanner/check \ go/token/check \ go/typechecker/check \ + $(go_types_check_omitted_since_it_calls_6g) \ hash/adler32/check \ hash/crc32/check \ hash/crc64/check \ hash/fnv/check \ http/cgi/check \ + http/fcgi/check \ + http/spdy/check \ + image/jpeg/check \ image/png/check \ + image/tiff/check \ + image/ycbcr/check \ index/suffixarray/check \ io/ioutil/check \ mime/multipart/check \ net/textproto/check \ $(os_inotify_check) \ + os/user/check \ os/signal/check \ path/filepath/check \ rpc/jsonrpc/check \ Index: libgo/MERGE =================================================================== --- libgo/MERGE (revision 173685) +++ libgo/MERGE (working copy) @@ -1,4 +1,4 @@ -f618e5e0991d +aea0ba6e5935 The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. Index: libgo/mksysinfo.sh =================================================================== --- libgo/mksysinfo.sh (revision 173685) +++ libgo/mksysinfo.sh (working copy) @@ -74,6 +74,8 @@ cat > sysinfo.c < #endif #include +#include +#include EOF ${CC} -fdump-go-spec=gen-sysinfo.go -std=gnu99 -S -o sysinfo.s sysinfo.c @@ -403,6 +405,10 @@ else echo "type Rusage struct {}" >> ${OUT} fi +# The RUSAGE constants. +grep '^const _RUSAGE_' gen-sysinfo.go | \ + sed -e 's/^\(const \)_\(RUSAGE_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + # The utsname struct. grep '^type _utsname ' gen-sysinfo.go | \ sed -e 's/_utsname/Utsname/' \ @@ -456,4 +462,20 @@ if test "$fd_set" != ""; then fi echo "type fds_bits_type $fds_bits_type" >> ${OUT} +# The addrinfo struct. +grep '^type _addrinfo ' gen-sysinfo.go | \ + sed -e 's/_addrinfo/Addrinfo/g' \ + -e 's/ ai_/ Ai_/g' \ + >> ${OUT} + +# The addrinfo flags. +grep '^const _AI_' gen-sysinfo.go | \ + sed -e 's/^\(const \)_\(AI_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} + +# The passwd struct. +grep '^type _passwd ' gen-sysinfo.go | \ + sed -e 's/_passwd/Passwd/' \ + -e 's/ pw_/ Pw_/g' \ + >> ${OUT} + exit $? Index: libgo/runtime/go-reflect-chan.c =================================================================== --- libgo/runtime/go-reflect-chan.c (revision 173685) +++ libgo/runtime/go-reflect-chan.c (working copy) @@ -8,30 +8,54 @@ #include #include "config.h" +#include "go-alloc.h" +#include "go-assert.h" +#include "go-panic.h" #include "go-type.h" #include "channel.h" /* This file implements support for reflection on channels. These functions are called from reflect/value.go. */ -extern unsigned char *makechan (const struct __go_type_descriptor *, uint32_t) +extern uintptr_t makechan (const struct __go_type_descriptor *, uint32_t) asm ("libgo_reflect.reflect.makechan"); -unsigned char * +uintptr_t makechan (const struct __go_type_descriptor *typ, uint32_t size) { - return (unsigned char *) __go_new_channel (typ->__size, size); + struct __go_channel *channel; + void *ret; + + __go_assert (typ->__code == GO_CHAN); + typ = ((const struct __go_channel_type *) typ)->__element_type; + + channel = __go_new_channel (typ, size); + + ret = __go_alloc (sizeof (void *)); + __builtin_memcpy (ret, &channel, sizeof (void *)); + return (uintptr_t) ret; } -extern void chansend (unsigned char *, unsigned char *, _Bool *) +extern _Bool chansend (uintptr_t, uintptr_t, _Bool) asm ("libgo_reflect.reflect.chansend"); -void -chansend (unsigned char *ch, unsigned char *val, _Bool *selected) +_Bool +chansend (uintptr_t ch, uintptr_t val_i, _Bool nb) { struct __go_channel *channel = (struct __go_channel *) ch; + uintptr_t element_size; + void *pv; + + if (channel == NULL) + __go_panic_msg ("send to nil channel"); + + if (__go_is_pointer_type (channel->element_type)) + pv = &val_i; + else + pv = (void *) val_i; - if (channel->element_size <= sizeof (uint64_t)) + element_size = channel->element_type->__size; + if (element_size <= sizeof (uint64_t)) { union { @@ -41,35 +65,60 @@ chansend (unsigned char *ch, unsigned ch __builtin_memset (u.b, 0, sizeof (uint64_t)); #ifndef WORDS_BIGENDIAN - __builtin_memcpy (u.b, val, channel->element_size); + __builtin_memcpy (u.b, pv, element_size); #else - __builtin_memcpy (u.b + sizeof (uint64_t) - channel->element_size, val, - channel->element_size); + __builtin_memcpy (u.b + sizeof (uint64_t) - element_size, pv, + element_size); #endif - if (selected == NULL) - __go_send_small (channel, u.v, 0); + if (nb) + return __go_send_nonblocking_small (channel, u.v); else - *selected = __go_send_nonblocking_small (channel, u.v); + { + __go_send_small (channel, u.v, 0); + return 1; + } } else { - if (selected == NULL) - __go_send_big (channel, val, 0); + if (nb) + return __go_send_nonblocking_big (channel, pv); else - *selected = __go_send_nonblocking_big (channel, val); + { + __go_send_big (channel, pv, 0); + return 1; + } } } -extern void chanrecv (unsigned char *, unsigned char *, _Bool *, _Bool *) +struct chanrecv_ret +{ + uintptr_t val; + _Bool selected; + _Bool received; +}; + +extern struct chanrecv_ret chanrecv (uintptr_t, _Bool) asm ("libgo_reflect.reflect.chanrecv"); -void -chanrecv (unsigned char *ch, unsigned char *val, _Bool *selected, - _Bool *received) +struct chanrecv_ret +chanrecv (uintptr_t ch, _Bool nb) { struct __go_channel *channel = (struct __go_channel *) ch; + void *pv; + uintptr_t element_size; + struct chanrecv_ret ret; + + element_size = channel->element_type->__size; - if (channel->element_size <= sizeof (uint64_t)) + if (__go_is_pointer_type (channel->element_type)) + pv = &ret.val; + else + { + pv = __go_alloc (element_size); + ret.val = (uintptr_t) pv; + } + + if (element_size <= sizeof (uint64_t)) { union { @@ -77,74 +126,73 @@ chanrecv (unsigned char *ch, unsigned ch uint64_t v; } u; - if (selected == NULL) - u.v = __go_receive_small_closed (channel, 0, received); + if (!nb) + { + u.v = __go_receive_small_closed (channel, 0, &ret.received); + ret.selected = 1; + } else { struct __go_receive_nonblocking_small s; s = __go_receive_nonblocking_small (channel); - *selected = s.__success || s.__closed; - if (received != NULL) - *received = s.__success; + ret.selected = s.__success || s.__closed; + ret.received = s.__success; u.v = s.__val; } #ifndef WORDS_BIGENDIAN - __builtin_memcpy (val, u.b, channel->element_size); + __builtin_memcpy (pv, u.b, element_size); #else - __builtin_memcpy (val, u.b + sizeof (uint64_t) - channel->element_size, - channel->element_size); + __builtin_memcpy (pv, u.b + sizeof (uint64_t) - element_size, + element_size); #endif } else { - if (selected == NULL) + if (!nb) { - _Bool success; - - success = __go_receive_big (channel, val, 0); - if (received != NULL) - *received = success; + ret.received = __go_receive_big (channel, pv, 0); + ret.selected = 1; } else { _Bool got; _Bool closed; - got = __go_receive_nonblocking_big (channel, val, &closed); - *selected = got || closed; - if (received != NULL) - *received = got; + got = __go_receive_nonblocking_big (channel, pv, &closed); + ret.selected = got || closed; + ret.received = got; } } + + return ret; } -extern void chanclose (unsigned char *) - asm ("libgo_reflect.reflect.chanclose"); +extern void chanclose (uintptr_t) asm ("libgo_reflect.reflect.chanclose"); void -chanclose (unsigned char *ch) +chanclose (uintptr_t ch) { struct __go_channel *channel = (struct __go_channel *) ch; __go_builtin_close (channel); } -extern int32_t chanlen (unsigned char *) asm ("libgo_reflect.reflect.chanlen"); +extern int32_t chanlen (uintptr_t) asm ("libgo_reflect.reflect.chanlen"); int32_t -chanlen (unsigned char *ch) +chanlen (uintptr_t ch) { struct __go_channel *channel = (struct __go_channel *) ch; return (int32_t) __go_chan_len (channel); } -extern int32_t chancap (unsigned char *) asm ("libgo_reflect.reflect.chancap"); +extern int32_t chancap (uintptr_t) asm ("libgo_reflect.reflect.chancap"); int32_t -chancap (unsigned char *ch) +chancap (uintptr_t ch) { struct __go_channel *channel = (struct __go_channel *) ch; Index: libgo/runtime/channel.h =================================================================== --- libgo/runtime/channel.h (revision 173685) +++ libgo/runtime/channel.h (working copy) @@ -7,6 +7,8 @@ #include #include +#include "go-type.h" + /* This structure is used when a select is waiting for a synchronous channel. */ @@ -34,8 +36,8 @@ struct __go_channel /* A condition variable. This is signalled when data is added to the channel and when data is removed from the channel. */ pthread_cond_t cond; - /* The size of elements on this channel. */ - size_t element_size; + /* The type of elements on this channel. */ + const struct __go_type_descriptor *element_type; /* True if a goroutine is waiting to send on a synchronous channel. */ _Bool waiting_to_send; @@ -82,7 +84,8 @@ typedef struct __go_channel __go_channel acquired while this mutex is held. */ extern pthread_mutex_t __go_select_data_mutex; -extern struct __go_channel *__go_new_channel (uintptr_t, uintptr_t); +extern struct __go_channel * +__go_new_channel (const struct __go_type_descriptor *, uintptr_t); extern _Bool __go_synch_with_select (struct __go_channel *, _Bool); Index: libgo/runtime/go-signal.c =================================================================== --- libgo/runtime/go-signal.c (revision 173685) +++ libgo/runtime/go-signal.c (working copy) @@ -245,3 +245,26 @@ runtime_resetcpuprofiler(int32 hz) m->profilehz = hz; } + +/* Used by the os package to raise SIGPIPE. */ + +void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe"); + +void +os_sigpipe (void) +{ + struct sigaction sa; + int i; + + memset (&sa, 0, sizeof sa); + + sa.sa_handler = SIG_DFL; + + i = sigemptyset (&sa.sa_mask); + __go_assert (i == 0); + + if (sigaction (SIGPIPE, &sa, NULL) != 0) + abort (); + + raise (SIGPIPE); +} Index: libgo/runtime/go-send-big.c =================================================================== --- libgo/runtime/go-send-big.c (revision 173685) +++ libgo/runtime/go-send-big.c (working copy) @@ -12,19 +12,20 @@ void __go_send_big (struct __go_channel* channel, const void *val, _Bool for_select) { + uintptr_t element_size; size_t alloc_size; size_t offset; if (channel == NULL) __go_panic_msg ("send to nil channel"); - alloc_size = ((channel->element_size + sizeof (uint64_t) - 1) - / sizeof (uint64_t)); + element_size = channel->element_type->__size; + alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); __go_send_acquire (channel, for_select); offset = channel->next_store * alloc_size; - __builtin_memcpy (&channel->data[offset], val, channel->element_size); + __builtin_memcpy (&channel->data[offset], val, element_size); __go_send_release (channel); } Index: libgo/runtime/iface.goc =================================================================== --- libgo/runtime/iface.goc (revision 173685) +++ libgo/runtime/iface.goc (working copy) @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. package runtime +#include "go-panic.h" #include "go-type.h" #include "interface.h" #define nil NULL @@ -33,6 +34,8 @@ func ifacetype(i interface) (d *const_de // Convert an empty interface to an empty interface. func ifaceE2E2(e empty_interface) (ret empty_interface, ok bool) { + if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) + __go_panic_msg("invalid interface value"); ret = e; ok = ret.__type_descriptor != nil; } @@ -52,6 +55,8 @@ func ifaceI2E2(i interface) (ret empty_i // Convert an empty interface to a non-empty interface. func ifaceE2I2(inter *descriptor, e empty_interface) (ret interface, ok bool) { + if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) + __go_panic_msg("invalid interface value"); if (e.__type_descriptor == nil) { ret.__methods = nil; ret.__object = nil; @@ -81,6 +86,8 @@ func ifaceI2I2(inter *descriptor, i inte // Convert an empty interface to a pointer type. func ifaceE2T2P(inter *descriptor, e empty_interface) (ret *void, ok bool) { + if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) + __go_panic_msg("invalid interface value"); if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) { ret = nil; ok = 0; @@ -104,6 +111,8 @@ func ifaceI2T2P(inter *descriptor, i int // Convert an empty interface to a non-pointer type. func ifaceE2T2(inter *descriptor, e empty_interface, ret *void) (ok bool) { + if(((uintptr_t)e.__type_descriptor&reflectFlags) != 0) + __go_panic_msg("invalid interface value"); if (!__go_type_descriptors_equal(inter, e.__type_descriptor)) { __builtin_memset(ret, 0, inter->__size); ok = 0; Index: libgo/runtime/go-send-nb-small.c =================================================================== --- libgo/runtime/go-send-nb-small.c (revision 173685) +++ libgo/runtime/go-send-nb-small.c (working copy) @@ -93,7 +93,7 @@ __go_send_nonblocking_acquire (struct __ _Bool __go_send_nonblocking_small (struct __go_channel *channel, uint64_t val) { - __go_assert (channel->element_size <= sizeof (uint64_t)); + __go_assert (channel->element_type->__size <= sizeof (uint64_t)); if (!__go_send_nonblocking_acquire (channel)) return 0; Index: libgo/runtime/chan.goc =================================================================== --- libgo/runtime/chan.goc (revision 173685) +++ libgo/runtime/chan.goc (working copy) @@ -13,7 +13,8 @@ typedef struct __go_channel chan; /* Do a channel receive with closed status. */ func chanrecv2(c *chan, val *byte) (received bool) { - if (c->element_size > 8) { + uintptr_t element_size = c->element_type->__size; + if (element_size > 8) { return __go_receive_big(c, val, 0); } else { union { @@ -23,10 +24,9 @@ func chanrecv2(c *chan, val *byte) (rece u.v = __go_receive_small_closed(c, 0, &received); #ifndef WORDS_BIGENDIAN - __builtin_memcpy(val, u.b, c->element_size); + __builtin_memcpy(val, u.b, element_size); #else - __builtin_memcpy(val, u.b + 8 - c->element_size, - c->element_size); + __builtin_memcpy(val, u.b + 8 - element_size, element_size); #endif return received; } @@ -35,7 +35,8 @@ func chanrecv2(c *chan, val *byte) (rece /* Do a channel receive with closed status for a select statement. */ func chanrecv3(c *chan, val *byte) (received bool) { - if (c->element_size > 8) { + uintptr_t element_size = c->element_type->__size; + if (element_size > 8) { return __go_receive_big(c, val, 1); } else { union { @@ -45,10 +46,9 @@ func chanrecv3(c *chan, val *byte) (rece u.v = __go_receive_small_closed(c, 1, &received); #ifndef WORDS_BIGENDIAN - __builtin_memcpy(val, u.b, c->element_size); + __builtin_memcpy(val, u.b, element_size); #else - __builtin_memcpy(val, u.b + 8 - c->element_size, - c->element_size); + __builtin_memcpy(val, u.b + 8 - element_size, element_size); #endif return received; } Index: libgo/runtime/go-reflect-call.c =================================================================== --- libgo/runtime/go-reflect-call.c (revision 173685) +++ libgo/runtime/go-reflect-call.c (working copy) @@ -14,9 +14,32 @@ #include "go-type.h" #include "runtime.h" -/* Forward declaration. */ - -static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *); +/* The functions in this file are only called from reflect_call. As + reflect_call calls a libffi function, which will be compiled + without -fsplit-stack, it will always run with a large stack. */ + +static ffi_type *go_array_to_ffi (const struct __go_array_type *) + __attribute__ ((no_split_stack)); +static ffi_type *go_slice_to_ffi (const struct __go_slice_type *) + __attribute__ ((no_split_stack)); +static ffi_type *go_struct_to_ffi (const struct __go_struct_type *) + __attribute__ ((no_split_stack)); +static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack)); +static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack)); +static ffi_type *go_complex_to_ffi (ffi_type *) + __attribute__ ((no_split_stack)); +static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *) + __attribute__ ((no_split_stack)); +static ffi_type *go_func_return_ffi (const struct __go_func_type *) + __attribute__ ((no_split_stack)); +static void go_func_to_cif (const struct __go_func_type *, _Bool, _Bool, + ffi_cif *) + __attribute__ ((no_split_stack)); +static size_t go_results_size (const struct __go_func_type *) + __attribute__ ((no_split_stack)); +static void go_set_results (const struct __go_func_type *, unsigned char *, + void **) + __attribute__ ((no_split_stack)); /* Return an ffi_type for a Go array type. The libffi library does not have any builtin support for passing arrays as values. We work @@ -31,7 +54,6 @@ go_array_to_ffi (const struct __go_array uintptr_t i; ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - __builtin_memset (ret, 0, sizeof (ffi_type)); ret->type = FFI_TYPE_STRUCT; len = descriptor->__len; ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *)); @@ -52,7 +74,6 @@ go_slice_to_ffi ( ffi_type *ret; ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - __builtin_memset (ret, 0, sizeof (ffi_type)); ret->type = FFI_TYPE_STRUCT; ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *)); ret->elements[0] = &ffi_type_pointer; @@ -73,7 +94,6 @@ go_struct_to_ffi (const struct __go_stru int i; ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - __builtin_memset (ret, 0, sizeof (ffi_type)); ret->type = FFI_TYPE_STRUCT; field_count = descriptor->__fields.__count; fields = (const struct __go_struct_field *) descriptor->__fields.__values; @@ -237,7 +257,6 @@ go_func_return_ffi (const struct __go_fu return go_type_to_ffi (types[0]); ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); - __builtin_memset (ret, 0, sizeof (ffi_type)); ret->type = FFI_TYPE_STRUCT; ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *)); for (i = 0; i < count; ++i) @@ -251,7 +270,7 @@ go_func_return_ffi (const struct __go_fu static void go_func_to_cif (const struct __go_func_type *func, _Bool is_interface, - ffi_cif *cif) + _Bool is_method, ffi_cif *cif) { int num_params; const struct __go_type_descriptor **in_types; @@ -268,10 +287,19 @@ go_func_to_cif (const struct __go_func_t num_args = num_params + (is_interface ? 1 : 0); args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *)); + i = 0; + off = 0; if (is_interface) - args[0] = &ffi_type_pointer; - off = is_interface ? 1 : 0; - for (i = 0; i < num_params; ++i) + { + args[0] = &ffi_type_pointer; + off = 1; + } + else if (is_method) + { + args[0] = &ffi_type_pointer; + i = 1; + } + for (; i < num_params; ++i) args[i + off] = go_type_to_ffi (in_types[i]); rettype = go_func_return_ffi (func); @@ -354,13 +382,14 @@ go_set_results (const struct __go_func_t void reflect_call (const struct __go_func_type *func_type, const void *func_addr, - _Bool is_interface, void **params, void **results) + _Bool is_interface, _Bool is_method, void **params, + void **results) { ffi_cif cif; unsigned char *call_result; __go_assert (func_type->__common.__code == GO_FUNC); - go_func_to_cif (func_type, is_interface, &cif); + go_func_to_cif (func_type, is_interface, is_method, &cif); call_result = (unsigned char *) malloc (go_results_size (func_type)); Index: libgo/runtime/go-reflect-map.c =================================================================== --- libgo/runtime/go-reflect-map.c (revision 173685) +++ libgo/runtime/go-reflect-map.c (working copy) @@ -8,69 +8,125 @@ #include #include "go-alloc.h" +#include "go-panic.h" #include "go-type.h" #include "map.h" /* This file implements support for reflection on maps. These functions are called from reflect/value.go. */ -extern _Bool mapaccess (unsigned char *, unsigned char *, unsigned char *) +struct mapaccess_ret +{ + uintptr_t val; + _Bool pres; +}; + +extern struct mapaccess_ret mapaccess (uintptr_t, uintptr_t) asm ("libgo_reflect.reflect.mapaccess"); -_Bool -mapaccess (unsigned char *m, unsigned char *key, unsigned char *val) +struct mapaccess_ret +mapaccess (uintptr_t m, uintptr_t key_i) { struct __go_map *map = (struct __go_map *) m; + void *key; + const struct __go_type_descriptor *key_descriptor; void *p; const struct __go_type_descriptor *val_descriptor; + struct mapaccess_ret ret; + void *val; + void *pv; + + if (map == NULL) + __go_panic_msg ("lookup in nil map"); + + key_descriptor = map->__descriptor->__map_descriptor->__key_type; + if (__go_is_pointer_type (key_descriptor)) + key = &key_i; + else + key = (void *) key_i; p = __go_map_index (map, key, 0); + + val_descriptor = map->__descriptor->__map_descriptor->__val_type; + if (__go_is_pointer_type (val_descriptor)) + { + val = NULL; + pv = &val; + } + else + { + val = __go_alloc (val_descriptor->__size); + pv = val; + } + if (p == NULL) - return 0; + ret.pres = 0; else { - val_descriptor = map->__descriptor->__map_descriptor->__val_type; - __builtin_memcpy (val, p, val_descriptor->__size); - return 1; + __builtin_memcpy (pv, p, val_descriptor->__size); + ret.pres = 1; } + + ret.val = (uintptr_t) val; + return ret; } -extern void mapassign (unsigned char *, unsigned char *, unsigned char *) +extern void mapassign (uintptr_t, uintptr_t, uintptr_t, _Bool) asm ("libgo_reflect.reflect.mapassign"); void -mapassign (unsigned char *m, unsigned char *key, unsigned char *val) +mapassign (uintptr_t m, uintptr_t key_i, uintptr_t val_i, _Bool pres) { struct __go_map *map = (struct __go_map *) m; + const struct __go_type_descriptor *key_descriptor; + void *key; + + if (map == NULL) + __go_panic_msg ("lookup in nil map"); - if (val == NULL) + key_descriptor = map->__descriptor->__map_descriptor->__key_type; + if (__go_is_pointer_type (key_descriptor)) + key = &key_i; + else + key = (void *) key_i; + + if (!pres) __go_map_delete (map, key); else { void *p; const struct __go_type_descriptor *val_descriptor; + void *pv; p = __go_map_index (map, key, 1); + val_descriptor = map->__descriptor->__map_descriptor->__val_type; - __builtin_memcpy (p, val, val_descriptor->__size); + if (__go_is_pointer_type (val_descriptor)) + pv = &val_i; + else + pv = (void *) val_i; + __builtin_memcpy (p, pv, val_descriptor->__size); } } -extern int32_t maplen (unsigned char *) +extern int32_t maplen (uintptr_t) asm ("libgo_reflect.reflect.maplen"); int32_t -maplen (unsigned char *m __attribute__ ((unused))) +maplen (uintptr_t m) { struct __go_map *map = (struct __go_map *) m; + + if (map == NULL) + return 0; return (int32_t) map->__element_count; } -extern unsigned char *mapiterinit (unsigned char *) +extern unsigned char *mapiterinit (uintptr_t) asm ("libgo_reflect.reflect.mapiterinit"); unsigned char * -mapiterinit (unsigned char *m) +mapiterinit (uintptr_t m) { struct __go_hash_iter *it; @@ -88,35 +144,67 @@ mapiternext (unsigned char *it) __go_mapiternext ((struct __go_hash_iter *) it); } -extern _Bool mapiterkey (unsigned char *, unsigned char *) +struct mapiterkey_ret +{ + uintptr_t key; + _Bool ok; +}; + +extern struct mapiterkey_ret mapiterkey (unsigned char *) asm ("libgo_reflect.reflect.mapiterkey"); -_Bool -mapiterkey (unsigned char *ita, unsigned char *key) +struct mapiterkey_ret +mapiterkey (unsigned char *ita) { struct __go_hash_iter *it = (struct __go_hash_iter *) ita; + struct mapiterkey_ret ret; if (it->entry == NULL) - return 0; + { + ret.key = 0; + ret.ok = 0; + } else { - __go_mapiter1 (it, key); - return 1; + const struct __go_type_descriptor *key_descriptor; + void *key; + void *pk; + + key_descriptor = it->map->__descriptor->__map_descriptor->__key_type; + if (__go_is_pointer_type (key_descriptor)) + { + key = NULL; + pk = &key; + } + else + { + key = __go_alloc (key_descriptor->__size); + pk = key; + } + + __go_mapiter1 (it, pk); + + ret.key = (uintptr_t) key; + ret.ok = 1; } + + return ret; } /* Make a new map. We have to build our own map descriptor. */ -extern unsigned char *makemap (const struct __go_map_type *) +extern uintptr_t makemap (const struct __go_map_type *) asm ("libgo_reflect.reflect.makemap"); -unsigned char * +uintptr_t makemap (const struct __go_map_type *t) { struct __go_map_descriptor *md; unsigned int o; const struct __go_type_descriptor *kt; const struct __go_type_descriptor *vt; + struct __go_map* map; + void *ret; /* FIXME: Reference count. */ md = (struct __go_map_descriptor *) __go_alloc (sizeof (*md)); @@ -135,5 +223,9 @@ makemap (const struct __go_map_type *t) o = (o + vt->__field_align - 1) & ~ (vt->__field_align - 1); md->__entry_size = o; - return (unsigned char *) __go_new_map (md, 0); + map = __go_new_map (md, 0); + + ret = __go_alloc (sizeof (void *)); + __builtin_memcpy (ret, &map, sizeof (void *)); + return (uintptr_t) ret; } Index: libgo/runtime/go-setenv.c =================================================================== --- libgo/runtime/go-setenv.c (revision 0) +++ libgo/runtime/go-setenv.c (revision 0) @@ -0,0 +1,50 @@ +/* go-setenv.c -- set the C environment from Go. + + 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. */ + +#include +#include + +#include "go-alloc.h" +#include "go-string.h" + +/* Set the C environment from Go. This is called by os.Setenv. */ + +void setenv_c (struct __go_string, struct __go_string) + __asm__ ("libgo_os.os.setenv_c"); + +void +setenv_c (struct __go_string k, struct __go_string v) +{ + const unsigned char *ks; + unsigned char *kn; + const unsigned char *vs; + unsigned char *vn; + + ks = k.__data; + kn = NULL; + if (ks[k.__length] != 0) + { + kn = __go_alloc (k.__length + 1); + __builtin_memcpy (kn, k.__data, k.__length); + ks = kn; + } + + vs = v.__data; + vn = NULL; + if (vs[v.__length] != 0) + { + vn = __go_alloc (v.__length + 1); + __builtin_memcpy (vn, v.__data, v.__length); + vs = vn; + } + + setenv ((const char *) ks, (const char *) vs, 1); + + if (kn != NULL) + __go_free (kn); + if (vn != NULL) + __go_free (vn); +} Index: libgo/runtime/go-unsafe-newarray.c =================================================================== --- libgo/runtime/go-unsafe-newarray.c (revision 173685) +++ libgo/runtime/go-unsafe-newarray.c (working copy) @@ -5,6 +5,7 @@ license that can be found in the LICENSE file. */ #include "go-alloc.h" +#include "go-panic.h" #include "go-type.h" #include "interface.h" @@ -21,6 +22,9 @@ NewArray (struct __go_empty_interface ty { const struct __go_type_descriptor *descriptor; + if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); + /* FIXME: We should check __type_descriptor to verify that this is really a type descriptor. */ descriptor = (const struct __go_type_descriptor *) type.__object; Index: libgo/runtime/mcache.c =================================================================== --- libgo/runtime/mcache.c (revision 173685) +++ libgo/runtime/mcache.c (working copy) @@ -22,6 +22,8 @@ runtime_MCache_Alloc(MCache *c, int32 si // Replenish using central lists. n = runtime_MCentral_AllocList(&runtime_mheap.central[sizeclass], runtime_class_to_transfercount[sizeclass], &first); + if(n == 0) + runtime_throw("out of memory"); l->list = first; l->nlist = n; c->size += n*size; Index: libgo/runtime/go-reflect.c =================================================================== --- libgo/runtime/go-reflect.c (revision 173685) +++ libgo/runtime/go-reflect.c (working copy) @@ -121,6 +121,9 @@ Reflect (struct __go_empty_interface e) { struct reflect_ret ret; + if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); + if (e.__type_descriptor == NULL) { ret.rettype.__type_descriptor = NULL; @@ -166,6 +169,9 @@ Typeof (const struct __go_empty_interfac { struct __go_empty_interface ret; + if (((uintptr_t) e.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); + if (e.__type_descriptor == NULL) { ret.__type_descriptor = NULL; Index: libgo/runtime/go-interface-eface-compare.c =================================================================== --- libgo/runtime/go-interface-eface-compare.c (revision 173685) +++ libgo/runtime/go-interface-eface-compare.c (working copy) @@ -4,6 +4,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ +#include "go-panic.h" #include "interface.h" /* Compare a non-empty interface value with an empty interface value. @@ -16,6 +17,8 @@ __go_interface_empty_compare (struct __g { const struct __go_type_descriptor *left_descriptor; + if (((uintptr_t) right.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); if (left.__methods == NULL && right.__type_descriptor == NULL) return 0; if (left.__methods == NULL || right.__type_descriptor == NULL) Index: libgo/runtime/go-send-nb-big.c =================================================================== --- libgo/runtime/go-send-nb-big.c (revision 173685) +++ libgo/runtime/go-send-nb-big.c (working copy) @@ -11,17 +11,18 @@ _Bool __go_send_nonblocking_big (struct __go_channel* channel, const void *val) { + uintptr_t element_size; size_t alloc_size; size_t offset; - alloc_size = ((channel->element_size + sizeof (uint64_t) - 1) - / sizeof (uint64_t)); + element_size = channel->element_type->__size; + alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); if (!__go_send_nonblocking_acquire (channel)) return 0; offset = channel->next_store * alloc_size; - __builtin_memcpy (&channel->data[offset], val, channel->element_size); + __builtin_memcpy (&channel->data[offset], val, element_size); __go_send_release (channel); Index: libgo/runtime/go-type.h =================================================================== --- libgo/runtime/go-type.h (revision 173685) +++ libgo/runtime/go-type.h (working copy) @@ -149,6 +149,9 @@ struct __go_array_type /* The element type. */ struct __go_type_descriptor *__element_type; + /* The type of a slice of the same element type. */ + struct __go_type_descriptor *__slice_type; + /* The length of the array. */ uintptr_t __len; }; @@ -289,6 +292,15 @@ struct __go_struct_type struct __go_open_array __fields; }; +/* If an empty interface has these bits set in its type pointer, it + was copied from a reflect.Value and is not a valid empty + interface. */ + +enum +{ + reflectFlags = 3, +}; + /* Whether a type descriptor is a pointer. */ static inline _Bool Index: libgo/runtime/malloc.goc =================================================================== --- libgo/runtime/malloc.goc (revision 173685) +++ libgo/runtime/malloc.goc (working copy) @@ -386,7 +386,7 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr return nil; if(p < h->arena_start || (uintptr)(p+n - h->arena_start) >= MaxArena32) { - runtime_printf("runtime: memory allocated by OS not in usable range"); + runtime_printf("runtime: memory allocated by OS not in usable range\n"); runtime_SysFree(p, n); return nil; } Index: libgo/runtime/go-send-small.c =================================================================== --- libgo/runtime/go-send-small.c (revision 173685) +++ libgo/runtime/go-send-small.c (working copy) @@ -147,7 +147,7 @@ __go_send_small (struct __go_channel *ch if (channel == NULL) __go_panic_msg ("send to nil channel"); - __go_assert (channel->element_size <= sizeof (uint64_t)); + __go_assert (channel->element_type->__size <= sizeof (uint64_t)); __go_send_acquire (channel, for_select); Index: libgo/runtime/go-new-channel.c =================================================================== --- libgo/runtime/go-new-channel.c (revision 173685) +++ libgo/runtime/go-new-channel.c (working copy) @@ -13,12 +13,16 @@ #include "channel.h" struct __go_channel* -__go_new_channel (uintptr_t element_size, uintptr_t entries) +__go_new_channel (const struct __go_type_descriptor *element_type, + uintptr_t entries) { + uintptr_t element_size; struct __go_channel* ret; size_t alloc_size; int i; + element_size = element_type->__size; + if ((uintptr_t) (int) entries != entries || entries > (uintptr_t) -1 / element_size) __go_panic_msg ("chan size out of range"); @@ -40,7 +44,7 @@ __go_new_channel (uintptr_t element_size __go_assert (i == 0); i = pthread_cond_init (&ret->cond, NULL); __go_assert (i == 0); - ret->element_size = element_size; + ret->element_type = element_type; ret->waiting_to_send = 0; ret->waiting_to_receive = 0; ret->selected_for_send = 0; Index: libgo/runtime/go-rec-big.c =================================================================== --- libgo/runtime/go-rec-big.c (revision 173685) +++ libgo/runtime/go-rec-big.c (working copy) @@ -15,23 +15,24 @@ _Bool __go_receive_big (struct __go_channel *channel, void *val, _Bool for_select) { + uintptr_t element_size; size_t alloc_size; size_t offset; if (channel == NULL) __go_panic_msg ("receive from nil channel"); - alloc_size = ((channel->element_size + sizeof (uint64_t) - 1) - / sizeof (uint64_t)); + element_size = channel->element_type->__size; + alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); if (!__go_receive_acquire (channel, for_select)) { - __builtin_memset (val, 0, channel->element_size); + __builtin_memset (val, 0, element_size); return 0; } offset = channel->next_fetch * alloc_size; - __builtin_memcpy (val, &channel->data[offset], channel->element_size); + __builtin_memcpy (val, &channel->data[offset], element_size); __go_receive_release (channel); Index: libgo/runtime/go-rec-nb-small.c =================================================================== --- libgo/runtime/go-rec-nb-small.c (revision 173685) +++ libgo/runtime/go-rec-nb-small.c (working copy) @@ -94,9 +94,11 @@ __go_receive_nonblocking_acquire (struct struct __go_receive_nonblocking_small __go_receive_nonblocking_small (struct __go_channel *channel) { + uintptr_t element_size; struct __go_receive_nonblocking_small ret; - __go_assert (channel->element_size <= sizeof (uint64_t)); + element_size = channel->element_type->__size; + __go_assert (element_size <= sizeof (uint64_t)); int data = __go_receive_nonblocking_acquire (channel); if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA) Index: libgo/runtime/go-type-eface.c =================================================================== --- libgo/runtime/go-type-eface.c (revision 173685) +++ libgo/runtime/go-type-eface.c (working copy) @@ -5,6 +5,7 @@ license that can be found in the LICENSE file. */ #include "interface.h" +#include "go-panic.h" #include "go-type.h" /* A hash function for an empty interface. */ @@ -43,6 +44,9 @@ __go_type_equal_empty_interface (const v v2 = (const struct __go_empty_interface *) vv2; v1_descriptor = v1->__type_descriptor; v2_descriptor = v2->__type_descriptor; + if (((uintptr_t) v1_descriptor & reflectFlags) != 0 + || ((uintptr_t) v2_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); if (v1_descriptor == NULL || v2_descriptor == NULL) return v1_descriptor == v2_descriptor; if (!__go_type_descriptors_equal (v1_descriptor, v2_descriptor)) Index: libgo/runtime/runtime.h =================================================================== --- libgo/runtime/runtime.h (revision 173685) +++ libgo/runtime/runtime.h (working copy) @@ -194,8 +194,8 @@ void runtime_resetcpuprofiler(int32); void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32); struct __go_func_type; -void reflect_call(const struct __go_func_type *, const void *, _Bool, void **, - void **) +void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool, + void **, void **) asm ("libgo_reflect.reflect.call"); #ifdef __rtems__ Index: libgo/runtime/go-unreflect.c =================================================================== --- libgo/runtime/go-unreflect.c (revision 173685) +++ libgo/runtime/go-unreflect.c (working copy) @@ -5,6 +5,7 @@ license that can be found in the LICENSE file. */ #include "go-alloc.h" +#include "go-panic.h" #include "go-type.h" #include "interface.h" @@ -19,6 +20,9 @@ Unreflect (struct __go_empty_interface t { struct __go_empty_interface ret; + if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); + /* FIXME: We should check __type_descriptor to verify that this is really a type descriptor. */ ret.__type_descriptor = type.__object; Index: libgo/runtime/go-rec-nb-big.c =================================================================== --- libgo/runtime/go-rec-nb-big.c (revision 173685) +++ libgo/runtime/go-rec-nb-big.c (working copy) @@ -14,23 +14,24 @@ _Bool __go_receive_nonblocking_big (struct __go_channel* channel, void *val, _Bool *closed) { + uintptr_t element_size; size_t alloc_size; size_t offset; - alloc_size = ((channel->element_size + sizeof (uint64_t) - 1) - / sizeof (uint64_t)); + element_size = channel->element_type->__size; + alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); int data = __go_receive_nonblocking_acquire (channel); if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA) { - __builtin_memset (val, 0, channel->element_size); + __builtin_memset (val, 0, element_size); if (closed != NULL) *closed = data == RECEIVE_NONBLOCKING_ACQUIRE_CLOSED; return 0; } offset = channel->next_fetch * alloc_size; - __builtin_memcpy (val, &channel->data[offset], channel->element_size); + __builtin_memcpy (val, &channel->data[offset], element_size); __go_receive_release (channel); Index: libgo/runtime/go-eface-val-compare.c =================================================================== --- libgo/runtime/go-eface-val-compare.c (revision 173685) +++ libgo/runtime/go-eface-val-compare.c (working copy) @@ -4,6 +4,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ +#include "go-panic.h" #include "go-type.h" #include "interface.h" @@ -19,6 +20,8 @@ __go_empty_interface_value_compare ( const struct __go_type_descriptor *left_descriptor; left_descriptor = left.__type_descriptor; + if (((uintptr_t) left_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); if (left_descriptor == NULL) return 1; if (!__go_type_descriptors_equal (left_descriptor, right_descriptor)) Index: libgo/runtime/reflect.goc =================================================================== --- libgo/runtime/reflect.goc (revision 173685) +++ libgo/runtime/reflect.goc (working copy) @@ -5,31 +5,27 @@ package reflect #include "go-type.h" #include "interface.h" -#define nil NULL -typedef unsigned char byte; +#include "runtime.h" +#include "go-panic.h" +typedef struct __go_type_descriptor Type; typedef struct __go_interface Iface; typedef struct __go_empty_interface Eface; -func setiface(typ *byte, x *byte, ret *byte) { - struct __go_interface_type *t; - const struct __go_type_descriptor* xt; +func ifaceE2I(inter *Type, e Eface, ret *Iface) { + const Type *t; + Eface err; - /* FIXME: We should check __type_descriptor to verify that - this is really a type descriptor. */ - t = (struct __go_interface_type *)typ; - if(t->__methods.__count == 0) { - // already an empty interface - *(Eface*)ret = *(Eface*)x; - return; + if(((uintptr)e.__type_descriptor&reflectFlags) != 0) + runtime_throw("invalid interface value"); + t = e.__type_descriptor; + if(t == nil) { + // explicit conversions require non-nil interface value. + newTypeAssertionError(nil, nil, inter, + nil, nil, inter->__reflection, + nil, &err); + __go_panic(err); } - xt = ((Eface*)x)->__type_descriptor; - if(xt == nil) { - // can assign nil to any interface - ((Iface*)ret)->__methods = nil; - ((Iface*)ret)->__object = nil; - return; - } - ((Iface*)ret)->__methods = __go_convert_interface(&t->__common, xt); - ((Iface*)ret)->__object = ((Eface*)x)->__object; + ret->__object = e.__object; + ret->__methods = __go_convert_interface(inter, t); } Index: libgo/runtime/go-unsafe-new.c =================================================================== --- libgo/runtime/go-unsafe-new.c (revision 173685) +++ libgo/runtime/go-unsafe-new.c (working copy) @@ -5,6 +5,7 @@ license that can be found in the LICENSE file. */ #include "go-alloc.h" +#include "go-panic.h" #include "go-type.h" #include "interface.h" @@ -20,6 +21,9 @@ New (struct __go_empty_interface type) { const struct __go_type_descriptor *descriptor; + if (((uintptr_t) type.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); + /* FIXME: We should check __type_descriptor to verify that this is really a type descriptor. */ descriptor = (const struct __go_type_descriptor *) type.__object; Index: libgo/runtime/go-rec-small.c =================================================================== --- libgo/runtime/go-rec-small.c (revision 173685) +++ libgo/runtime/go-rec-small.c (working copy) @@ -266,12 +266,14 @@ uint64_t __go_receive_small_closed (struct __go_channel *channel, _Bool for_select, _Bool *received) { + uintptr_t element_size; uint64_t ret; if (channel == NULL) __go_panic_msg ("receive from nil channel"); - __go_assert (channel->element_size <= sizeof (uint64_t)); + element_size = channel->element_type->__size; + __go_assert (element_size <= sizeof (uint64_t)); if (!__go_receive_acquire (channel, for_select)) { Index: libgo/runtime/mgc0.c =================================================================== --- libgo/runtime/mgc0.c (revision 173685) +++ libgo/runtime/mgc0.c (working copy) @@ -90,6 +90,11 @@ scanblock(byte *b, int64 n) void **bw, **w, **ew; Workbuf *wbuf; + if((int64)(uintptr)n != n || n < 0) { + // runtime_printf("scanblock %p %lld\n", b, (long long)n); + runtime_throw("scanblock"); + } + // Memory arena parameters. arena_start = runtime_mheap.arena_start; @@ -602,7 +607,7 @@ runfinq(void* dummy) next = f->next; params[0] = &f->arg; - reflect_call(f->ft, (void*)f->fn, 0, params, nil); + reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil); f->fn = nil; f->arg = nil; f->next = nil; Index: libgo/runtime/go-eface-compare.c =================================================================== --- libgo/runtime/go-eface-compare.c (revision 173685) +++ libgo/runtime/go-eface-compare.c (working copy) @@ -4,6 +4,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ +#include "go-panic.h" #include "interface.h" /* Compare two interface values. Return 0 for equal, not zero for not @@ -16,6 +17,11 @@ __go_empty_interface_compare (struct __g const struct __go_type_descriptor *left_descriptor; left_descriptor = left.__type_descriptor; + + if (((uintptr_t) left_descriptor & reflectFlags) != 0 + || ((uintptr_t) right.__type_descriptor & reflectFlags) != 0) + __go_panic_msg ("invalid interface value"); + if (left_descriptor == NULL && right.__type_descriptor == NULL) return 0; if (left_descriptor == NULL || right.__type_descriptor == NULL) Index: libgo/runtime/mheap.c =================================================================== --- libgo/runtime/mheap.c (revision 173685) +++ libgo/runtime/mheap.c (working copy) @@ -181,9 +181,7 @@ MHeap_Grow(MHeap *h, uintptr npage) // Allocate a multiple of 64kB (16 pages). npage = (npage+15)&~15; ask = npage< (uintptr)(h->arena_end - h->arena_used)) - return false; - if(ask < HeapAllocChunk && HeapAllocChunk <= h->arena_end - h->arena_used) + if(ask < HeapAllocChunk) ask = HeapAllocChunk; v = runtime_MHeap_SysAlloc(h, ask); @@ -192,8 +190,10 @@ MHeap_Grow(MHeap *h, uintptr npage) ask = npage<