Big merge of changes to gofrontend repo that were postponed due to the

GCC release freeze.

	* go-backend.c: Include "go-c.h".
	* go-gcc.cc (Gcc_backend::write_export_data): New method.

	* go-gcc.cc (Gcc_backend::Gcc_backend): Declare
	__builtin_prefetch.
	* Make-lang.in (GO_OBJS): Add go/wb.o.

commit 884c9f2cafb3fc1decaca70f1817ae269e4c6889
Author: Than McIntosh <thanm@google.com>
Date:   Mon Jan 23 15:07:07 2017 -0500

    compiler: insert additional conversion for type desc ptr expr
    
    Change the method Type::type_descriptor_pointer to apply an additional
    type conversion to its result Bexpression, to avoid type clashes in
    the back end. The backend expression for a given type descriptor var
    is given a type of "_type", however the virtual calls that create the
    variable use types derived from _type, hence the need to force a
    conversion.
    
    Reviewed-on: https://go-review.googlesource.com/35506


commit 5f0647c71e3b29eddcd0eecc44e7ba44ae7fc8dd
Author: Than McIntosh <thanm@google.com>
Date:   Mon Jan 23 15:22:26 2017 -0500

    compiler: insure tree integrity in Call_expression::set_result
    
    Depending on the back end, it can be problematic to reuse Bexpressions
    (passing the same Bexpression to more than one Backend call to create
    additional Bexpressions or Bstatements). The Call_expression::set_result
    method was reusing its Bexpression input in more than one tree
    context; the fix is to pass in an Expression instead and generate
    multiple Bexpression references to it within the method.
    
    Reviewed-on: https://go-review.googlesource.com/35505


commit 7a8e49870885af898c3c790275e513d1764a2828
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Jan 24 21:19:06 2017 -0800

    runtime: copy more of the scheduler from the Go 1.8 runtime
    
    Copies mstart, newm, m0, g0, and friends.
    
    Reviewed-on: https://go-review.googlesource.com/35645


commit 3546e2f002d0277d805ec59c5403bc1d4eda4ed9
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Jan 26 19:47:37 2017 -0800

    runtime: remove a few C functions that are no longer used
    
    Reviewed-on: https://go-review.googlesource.com/35849


commit a71b835254f6d3164a0e6beaf54f2b175d1a6a92
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Jan 26 16:51:16 2017 -0800

    runtime: copy over more of the Go 1.8 scheduler
    
    In particular __go_go (aka newproc) and goexit[01].
    
    Reviewed-on: https://go-review.googlesource.com/35847


commit c3ffff725adbe54d8283c373b6aa7dc95d6fc27f
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Jan 27 16:58:20 2017 -0800

    runtime: copy syscall handling from Go 1.8 runtime
    
    Entering a syscall still has to start in C, to save the registers.
    Fix entersyscallblock to save them more reliably.
    
    This copies over the tracing code for syscalls, which we previously
    weren't doing, and lets us turn on runtime/trace/check.
    
    Reviewed-on: https://go-review.googlesource.com/35912


commit d5b921de4a28b04000fc4c8dac7f529a4a624dfc
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Jan 27 18:34:11 2017 -0800

    runtime: copy SIGPROF handling from Go 1.8 runtime
    
    Also copy over Breakpoint.
    
    Fix Func.Name and Func.Entry to not crash on a nil Func.
    
    Reviewed-on: https://go-review.googlesource.com/35913


commit cc60235e55aef14b15c3d2114030245beb3adfef
Author: Than McIntosh <thanm@google.com>
Date:   Mon Feb 6 11:12:12 2017 -0500

    compiler: convert go_write_export_data to Backend method.
    
    Convert the helper function 'go_write_export_data' into a Backend
    class method, to allow for an implementation of this function that
    needs to access backend state.
    
    Reviewed-on: https://go-review.googlesource.com/36357


commit e387439bfd24d5e142874b8e68e7039f74c744d7
Author: Than McIntosh <thanm@google.com>
Date:   Wed Feb 8 11:13:46 2017 -0500

    compiler: insert backend conversion in temporary statement init
    
    Insert an additional type conversion in Temporary_statement::do_get_backend
    when assigning a Bexpression initializer to the temporary variable, to
    avoid potential clashes in the back end. This can come up when assigning
    something of concrete pointer-to-function type to a variable of generic
    pointer-to-function type.
    
    Reviewed-on: https://go-review.googlesource.com/36591


commit c5acf0ce09e61ff623847a35a99da465b8571609
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 1 17:57:53 2017 +0100

    libgo: build tags for aix
    
    Build tags for the libgo source files required to build
    libgo on AIX.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37633


commit 67ed19616898ea18a101ec9325b82d028cd395d9
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 2 15:41:31 2017 +0100

    libgo: handle AIX tag in match.sh and gotest
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37638


commit 83ea2d694c10b2dd83fc8620c43da13d20db754e
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 1 17:48:16 2017 +0100

    libgo: add AIX support in configure and Makefile
    
    - support for GOOS=aix
    - CFLAGS/GOCFLAGS/LDFLAGS for AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37632


commit 35d577fe22ffa16a3ccaadf5dae9f6f425c8ec8c
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Mon Mar 6 15:00:15 2017 +0100

    runtime: adapt memory management to AIX mmap
    
    On AIX:
    * mmap does not allow to map an already mapped range,
    * mmap range start at 0x30000000 for 32 bits processes,
    * mmap range start at 0x70000000_00000000 for 64 bits processes
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37845


commit 4e49e56a5fd4072b4ca7fcefe4158d6885d9ee62
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Mon Mar 6 13:42:26 2017 +0100

    runtime: add getproccount implementation for AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37844


commit ff626470294237ac664127894826614edc46a3d0
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Mon Mar 6 17:31:21 2017 +0100

    runtime: handle ERESTART errno with AIX's wait4
    
    On AIX, wait4 may return with errno set to ERESTART, which causes unexepected
    behavior (for instance, go build may exit with the message "wait: restart
    system call" after running a command, even if it was successfull).
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37846


commit 37daabbfc83d533b826ef9ab10e2dee7406e7198
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Mon Mar 6 11:02:58 2017 +0100

    runtime: support for AIX's procfs tree
    
    On AIX, the process executable file is available under /proc/<pid>/object/a.out
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37842


commit a0275c039d56acf4bf48151978c1a4ec5758cc2c
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Mar 8 07:00:05 2017 -0800

    libgo/Makefile.am: don't use nonportable \n or \t in sed expression
    
    The resulting zstdpktlist.go is less pretty, but it works.
    
    Reviewed-on: https://go-review.googlesource.com/37940


commit 29b190f76105aafa2b50b48249afdafecc97a4be
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 9 16:02:34 2017 +0100

    runtime: netpoll and semaphores for AIX
    
    semaphore implementation based on Solaris implementation in
    libgo/go/runtime/os_solaris.go
    
    netpoll is just a stub to avoid build failure on AIX.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37966


commit 55ca6d3f3cddf0ff9ccb074b2694da9fc54de7ec
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 9 15:38:30 2017 +0100

    libmain: ensure initfn is called when loading a go library
    
    AIX does not support .init_array.
    The alterative is to export the __go_init function and tell the linker
    it is an init function with the -Wl,-binitfini:__go_init option.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37965


commit 349a30d17d880ac8bc1a35e1a2ffee6d6e870ae9
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Mar 10 11:15:08 2017 +0100

    libgo: use an import list for missing symbols
    
    libgo depends on symbols provided by Go programs at runtime. On AIX,
    this requires either to build libgo with -Wl,-berok linker option and
    the programs with -Wl,-brtl, or to provide a list of imported symbols
    when building libgo. The second options seems preferable, to avoid
    requiring an additional option for every Go program.
    
    There are also some symbols that are specific to GNU ld and do not
    exist when linking with AIX ld (__data_start, __edata, __etext and
    __bss_start).
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37969


commit 91db0ea1ff068ca1d97b9c99612100ea5b96ddb2
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 8 15:34:45 2017 +0100

    crypto/x509: add certificate files locations for AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/37952


commit 92e521c854e91709b949548c47e267377850f26a
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Mar 10 14:10:11 2017 -0800

    compiler: fix check for pointer in Temporary_reference_expression
    
    The check for an unrepresentable pointer in
    Temporary_reference_expression::do_get_backend was incorrectly
    translated from C to Go in https://golang.org/cl/14346043.  Fix the
    check to use points_to rather than has_pointer and deref.  This should
    not make any difference in practice as either way the condition will
    only be true for a pointer to void, but points_to is correct and more
    efficient.
    
    Reviewed-on: https://go-review.googlesource.com/38009


commit 9a0b676e59e7171a630c48fdc3d4de6712bad0ca
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 16 16:51:53 2017 +0100

    libgo: add missing _arpcom struct to *sysinfo.go
    
    This struct is filtered due to having a field of type _in6_addr,
    but other types exported to *sysinfo.go are depending on it.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38251


commit 61262a757bdd3d9a595ab6a90f68c0c4ebed7bc1
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 16 18:27:46 2017 +0100

    syscall: raw_ptrace stub for AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38253


commit 8029632b50880fd9b5e39299c738b38e3386595f
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 15 16:58:37 2017 +0100

    libgo: adapt runtime.inc to AIX
    
    * Two AIX types are wrongfully exported to runtime.inc as their names
      make them look like a Go type.
    * The sigset go type conflicts with a system sigset type.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38192


commit 25f3a90d14bc268479369ecc0eada72791612f86
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 15 16:58:37 2017 +0100

    libgo: update Makefile.in, accidentally omitted from last change
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38310


commit d52b4895616b66f93b460366527e74336829aaa5
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 16 18:39:26 2017 +0100

    syscall: TIOCSCTTY does not exist on AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38254


commit ff1ec3847a4472008e5d53a98b6694b1e54ca322
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 16 18:07:34 2017 +0100

    syscall: syscall does not exist on AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38252


commit c1ee60dabf0b243a0b0286215481a5d326c34596
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Mar 17 17:18:18 2017 +0100

    net: EAI_OVERFLOW does not exist on AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38266


commit ad4ad29aed9f70b14b39b488bfeb9ee745382ec4
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Mar 17 17:23:56 2017 +0100

    net: sockopt/sockoptip stubs for AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38267


commit 5d7db2d7542fe7082f426d42f8c2ce14aad6df55
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Mar 17 16:35:05 2017 +0100

    os/user: add listgroups stub for AIX
    
    This is required to build os/user.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38263


commit 4e57a7973e9fa4cb5ab977c6d792e62a8f7c5795
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 22 11:11:30 2017 +0100

    os: fix readdirnames for AIX
    
    Largefile implementation should be used on AIX.
    
    readdir64_r function returns 9 and sets result to NULL when
    reaching end of directory, so this return code should not
    always be considered as an error.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38359


commit b34036967d1ec57b25e3debe077439b4210a1d4a
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Mar 17 17:39:31 2017 +0100

    libgo: adapt sigtab.go to AIX
    
    On AIX, _NSIG is not directly defined to its integer value in
    gen-sysinfo.go.
    The real value is _SIGMAX32+1 or _SIGMAX64+1, depending if we are
    building a 32bit ligbo or a 64bit libgo, so we need to read one of
    those constants to set nsig value in mksigtab.sh
    
    This change also ensures that all signal numbers from 0 to nsig-1
    are referenced in sigtable.
    
    Reviewed-on: https://go-review.googlesource.com/38268


commit 20991c32671a183ec859b4f285df37fdd4634247
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 23 17:28:09 2017 +0100

    syscall: missing import in socket_bsd.go
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38369


commit c34754bd9adf5496c4c26257eaa50793553c11e8
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 22 17:57:01 2017 +0100

    sycall: WCOREDUMP macro is not defined on AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38363


commit 4f38813482227b12ea0ac6ac1b981ff9ef9853ef
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 23 17:44:43 2017 +0100

    libgo: additional build tags for AIX
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38510


commit d117ede6ff5a7083e9c40eba28a0f94f3535d773
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 23 17:48:46 2017 +0100

    go/build: add AIX to "go build" command known OS
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38511


commit 7b0ddaa6a6a71f9eb1c374122d29775b13c2cac5
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Mar 23 09:57:01 2017 -0700

    compiler: don't crash if imported package imports this one
    
    When building a test it's OK if test code imports a package that
    imports this one. The go tool is supposed to catch cases where this
    creates an impossible initialization order. The compiler already has
    code to permit this in Gogo::add_import_init_fn. This CL avoids a
    compiler crash on a similar case when writing out the export data.
    
    I have no test case for this. Basically it pushes a compiler crash
    into an error reported elsewhere.
    
    Problem was reported by Tony Reix.
    
    Reviewed-on: https://go-review.googlesource.com/38462


commit 925636975d075e3e3353823b09db3f933f23cb03
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Mar 29 14:14:18 2017 -0700

    runtime: copy finalizer support from Go 1.8 runtime
    
    Reviewed-on: https://go-review.googlesource.com/38794


commit 1ccb22b96cb3b1011db0e427877d9ddecb577fa9
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Mar 30 15:21:06 2017 +0200

    runtime: initcontext and setcontext stubs for AIX
    
    Further investigations are required to understand the clobbering
    issue and implement a proper fix. Until then, those stubs are
    required to allow the build to complete.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38930


commit 27db481f369b54256063c72b911d22390c59199c
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 29 18:07:25 2017 +0200

    os: fix Readlink failure on AIX
    
    AIX readlink routine returns an error if the link is longer
    than the buffer, instead of truncating the link.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38700


commit c93babbf48eddd0bc34d4179ffb302dc60087299
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 29 17:26:35 2017 +0200

    compiler: implement support for reading AIX big archives
    
    This is required to read go export from a Go library.
    
    Code courtesy of Damien Bergamini from Atos Infogérance.
    
    Issue golang/go#19200
    Reviewed-on: https://go-review.googlesource.com/38698


commit 930dd53482bdee3a9074850d168d0b9d7819c135
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 6 18:50:11 2017 -0700

    compiler: fix whether conversions are static initializers
    
    The compiler was incorrectly treating type conversions from string to
    int or vice-versa as static initializers.  That doesn't work, as those
    conversions are implemented via a function call.
    
    This case may never actually arise but it seems like the right thing to do.
    
    Reviewed-on: https://go-review.googlesource.com/39872


commit f02691e4195728dbf06f4dde0853c6bccc922183
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 6 17:24:08 2017 -0700

    compiler, runtime: don't let slices point past end of memory block
    
    When Go code uses a slice expression like [:len(str)] or [:cap(slice)],
    it's natural for the resulting pointer to point just past the end of
    the memory block.  If the next memory block is not live, we now have a
    live pointer to a dead block, which will unnecessarily keep the block
    alive.  That wastes space, and with the new Go 1.8 GC (not yet
    committed) will trigger an error when using GODEBUG=gccheckmark=1.
    
    This changes the implementation of slice expressions to not move the
    pointer if the resulting string length or slice capacity is 0.  When
    the length/capacity is zero, the pointer is never used anyhow.
    
    Reviewed-on: https://go-review.googlesource.com/39870


commit 17527c35b027e1afcc318faf5563909e1e9d44a6
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 6 15:30:11 2017 -0700

    compiler: emit write barriers
    
    The Go 1.8 concurrent GC requires optional write barriers for all
    assignments that may change pointer values in the heap or in a global
    variable.  For details see https://blog.golang.org/go15gc.
    
    This changes the gofrontend code to emit write barriers as needed.
    This is in preparation for future changes.  At the moment the write
    barriers will do nothing.  They test runtime.writeBarrier.enabled,
    which will never be non-zero.  They call simple functions which just
    do a move without doing any of the other operations required by the
    write barrier.
    
    Reviewed-on: https://go-review.googlesource.com/39852


commit c0b00f072bf34b2c288e1271ec8118b88c4f6f6f
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Tue Apr 11 17:47:29 2017 +0200

    libgo: allow building gox files from PIC objects
    
    libtool builds non-PIC objects in the same directory as .lo files
    and PIC objects in a .libs subdirectory.
    BUILDGOX rule uses the non-PIC objects to build the gox files,
    but on AIX only the PIC objects are built.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/40355


commit ea0f3da174c5503a209043f14ddda34871cfec52
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 6 19:06:14 2017 -0700

    compiler: add code to generate a ptrmask for a type
    
    The Go 1.8 garbage collector uses a ptrmask for all types below a
    certain size.  A ptrmask is simply a bit vector with a single bit for
    each pointer-sized word in the value.  The bit is 1 if the type has a
    pointer in that position, 0 if it does not.
    
    This change adds code to the compiler to generate a ptrmask.  The code
    is not used by anything yet, it is just compiled.  It will be used
    when we switch over to the Go 1.8 garbage collector.
    
    The new Array_type::int_length method, and the new memory_size
    methods, will also be used by other patches coming later.
    
    Reviewed-on: https://go-review.googlesource.com/39873


commit 3029e1df3be3614d196a03c15e50e68ff850aa4c
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 7 10:31:39 2017 -0700

    compiler: add code to generate a gcprog for a type
    
    The Go 1.8 garbage collector uses a gcprog for all types above a
    certain size.  A gcprog describes where the pointers are in the type,
    using a simple bytecode machine that supports repeating bits.  The
    effect is to permit using much less space to describe arrays.  The
    format is described in runtime/mbitmap.go in the docs for runGCProg.
    This is not yet added to the gofrontend, but can be seen in the gc sources.
    
    This change adds code to the compiler to generate a gcprog.  The code
    is not used by anything yet, it is just compiled.  It will be used
    when we switch over to the Go 1.8 garbage collector.
    
    Reviewed-on: https://go-review.googlesource.com/39923


commit 8b01ef1e9176d20f4c9e667972fe031069a4d057
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 13 07:00:35 2017 -0700

    compiler: add ptrdata computations and expressions
    
    For the upcoming Go 1.8 GC we need to compute the "ptrdata" of a type:
    the number of bytes in the type that can contain pointers.  For types
    that do not contain pointers this number is zero.  For many types it
    is a number larger than zero but smaller than the total size of the
    type.  The Go 1.8 GC uses this number to make loops looking for
    pointers run faster by not scanning the suffix of a value that can not
    contain a pointer.
    
    Unfortunately there are two subtly different definitions of ptrdata,
    and we need both.  The first is the simple one: the prefix that can
    contain pointers.  The second is the number of bytes described by the
    gcprog for the type.  Recall that we describe the exact position of
    pointers in a type using either a ptrmask or a gcprog.  The ptrmask is
    simpler, the gcprog uses less space.  We use the gcprog for large
    types, currently defined as types that are more than 2048 bytes.  When
    the Go 1.8 runtime expands a gcprog, it verifies that the gcprog
    describes exactly the same number of bytes as the ptrdata field in the
    type descriptor.  If the last pointer-containing portion of a type is
    an array, and if the elements of the array have a ptrdata that is less
    than the size of the element type, then the simple definition of the
    ptrdata will not include the final non-pointer-containing bytes of the
    last element of the array.  However, the gcprog will define the array
    using a repeat count, and will therefore include the full size of the
    last element of the array.  So for a type that needs a gcprog, the
    ptrdata field in the type descriptor must be the size of the data
    described by the gcprog, and that is not necessarily the same as the
    simple ptrdata.
    
    It might seem that we can always use the gcprog version of the ptrdata
    calculation, since that is what will appear in a type descriptor, but
    it turns out that for global variables we always use a ptrmask, not a
    gcprog, even if the global variable is large.  This is because gcprogs
    are handled by expanding them into a ptrmask at runtime, and for a
    global variable there is no natural place to put the ptrmask.  Simpler
    to always use the ptrmask.  That means that we need to describe the
    size of the ptrmask, and that means that we need an expression for the
    simple form of the ptrdata.
    
    This CL implements the ptrdata calculation.  This code is not actually
    used yet.  It will be used later when the Go 1.8 GC is committed.
    
    Reviewed-on: https://go-review.googlesource.com/40573


commit 7a37331303b572412179a08141f1dd35339d40c8
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 06:55:48 2017 -0700

    compiler: zero length arrays never contain pointers
    
    Reviewed-on: https://go-review.googlesource.com/40696


commit c242f0508a64d3d74a28d498cbaeda785ff76258
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 07:26:54 2017 -0700

    bytes: disable allocations test on gccgo
    
    It turns out that testing.AllocsPerRun has not been producing correct
    results with the current gccgo memory allocator.  When we update to
    the Go 1.8 memory allocator, testing.AllocsPerRun will work again, and
    this test will fail due to lack of escape analysis.
    
    Reviewed-on: https://go-review.googlesource.com/40700


commit 0dc369f1d63376a36bfb0999a1b0377fd444bfab
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Tue Apr 11 16:22:38 2017 +0200

    os: alternative way to find executable path, using Args[0]
    
    AIX does not provide a proper way to find the original
    executable path from procfs, which contains just an
    hardlink.
    Executable path can be found using Args[0], Getcwd and
    $PATH.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/40353


commit f9bad1342569b338e3b2ea9f12ffc6d3d3fa3028
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 08:01:19 2017 -0700

    compiler: don't write struct with multiple sink fields to C header file
    
    When writing a struct to the C header file used by the C runtime code,
    a single sink field is fine: it will be called "_", which is valid C.
    There are structs with single sink fields that we want to write out,
    such as finblock.  As it happens, though, the Go 1.8 runtime has a
    struct with two sink fields, gcControllerState, which will produce a C
    definition with two fields named "_", which will fail.  Since we don't
    need to know that struct in C, rather than fix the general case, just
    punt if the struct has multiple sink fields.
    
    After the conversion to the Go 1.8 GC, we may be able to get rid of
    the C header file anyhow.  I'm not sure yet.
    
    Reviewed-on: https://go-review.googlesource.com/40701


commit cfc28901a572aeb15b2f10a38f79eec04c64dfb2
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 10:07:23 2017 -0700

    runtime: disable allocations test on gccgo
    
    It turns out that testing.AllocsPerRun has not been producing correct
    results with the current gccgo memory allocator.  When we update to
    the Go 1.8 memory allocator, testing.AllocsPerRun will work again, and
    these tests will fail due to lack of escape analysis.
    
    Reviewed-on: https://go-review.googlesource.com/40703


commit 36fedd76edaa48b9ec09709a70d9e4abaddf0caf
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 10:47:06 2017 -0700

    runtime: remove unused size argument from hash/equal fns
    
    The size argument was removed from hash and equal functions in CL
    34983.  Somehow I missed removing them from three of the predefined
    functions.
    
    Reviewed-on: https://go-review.googlesource.com/40770


commit 90f6accb48d2e78cad8955b9292933f6ce3fe4c8
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 13:23:05 2017 -0700

    runtime: remove unused stack.go
    
    We're never going to use stack.go for gccgo.  Although a build tag
    keeps it from being built, even having it around can be confusing.
    Remove it.
    
    Reviewed-on: https://go-review.googlesource.com/40774


commit befa71603fc66a214e01ac219f2bba36e19f136f
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 13:18:34 2017 -0700

    runtime: build fastlog
    
    Take out the build tags which were preventing fastlog2 from being
    built.  It's used by the upcoming Go 1.8 GC.
    
    Reviewed-on: https://go-review.googlesource.com/40773


commit b7e19e9be4ab4c3cd8f4c9506d79a8cd56bace40
Author: Ian Lance Taylor <iant@golang.org>
Date:   Fri Apr 14 10:04:23 2017 -0700

    runtime: add tests from Go 1.8
    
    Some runtime package tests never made it into the gofrontend repo for
    some reason.  Add them now.
    Reviewed-on: https://go-review.googlesource.com/40869


commit 1feef185aebd71bc2a09b9a04287461806096610
Author: Ian Lance Taylor <iant@golang.org>
Date:   Mon Apr 17 16:26:11 2017 -0700

    runtime: change mcall to take a Go function value
    
    For future work in bringing in the Go 1.8 GC, change the mcall
    function to take a Go function value, which means that mcall can take
    a closure rather than just a straight C function pointer.
    
    As part of this change move kickoff from C to Go, which we want to do
    anyhow so that we run the write barriers that it generates.
    
    Reviewed-on: https://go-review.googlesource.com/40935


commit c3db34f4efc2d610f74a01dd2ad7775f48889b29
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Tue Apr 11 16:11:26 2017 +0200

    runtime: netpoll implementation for AIX
    
    Code courtesy of Damien Bergamini from Atos Infogérance.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/40352


commit f5634dff40e53ad9ce61afd67fd07334e3af9d1f
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Apr 18 22:06:07 2017 -0700

    runtime: move mstart from Go to C
    
    The assignments done in mstart must be done without write barriers, as
    mstart is running without an m or p.  In the gc toolchain the
    equivalent code to intialize g and g->m is written in assembler;
    on GNU/Linux, it's in the clone function.
    
    Reviewed-on: https://go-review.googlesource.com/40989


commit 671d7c74592f4b6fe3665af279482ba0ea47ca2d
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Apr 18 17:47:28 2017 -0700

    compiler: varargs slices do not escape in runtime
    
    Also, don't try to allocate an empty slice on the stack, as it will
    confuse the GCC backend.
    
    Also add a few trivial style, code formatting, and debug output fixes.
    
    Updates golang/go#17431
    
    Reviewed-on: https://go-review.googlesource.com/40983


commit 94699d25f31353bf03419eda56b15993a39f3275
Author: Ian Lance Taylor <iant@golang.org>
Date:   Tue Apr 18 17:30:09 2017 -0700

    compiler: add Ptrmask_symbol_expression
    
    Add an expression to evaluate to the ptrmask for a type.  This will be
    used for global variables, which always use a ptrmask no matter how
    large they are.
    
    Reviewed-on: https://go-review.googlesource.com/40981


commit bfff1654eac5b9288fa6c431e66cba8c9da6a660
Author: Ian Lance Taylor <iant@golang.org>
Date:   Mon Apr 17 10:51:16 2017 -0700

    runtime: change g's in systemstack
    
    The systemstack function in the gc toolchain changes to a different g.
    This is often used to get more stack space; the gofrontend uses a
    different stack growth mechanism that does not require changing g's,
    so we've been running with a version of systemstack that keeps the
    same g.  However, the garbage collector has various tests to verify
    that it is running on g0 rather than on a normal g.  For simplicity,
    change the gofrontend version of systemstack to change to a different
    g just as the gc toolchain does.
    
    This permits us to uncomment some sanity checks in notetsleep.
    Doing that requires us to fix up a couple of places where C code calls
    {start,stop}TheWorldWithSema while not on g0.
    
    Note that this does slow down some code in the runtime package unnecessarily.
    It may be useful to find some places where the runtime calls
    systemstack only to get more stack space and change it to use some
    other function.  That other function would act like systemstack in the
    gc toolchain but simply call the argument in the gofrontend.
    
    Reviewed-on: https://go-review.googlesource.com/40973


commit b2ccc7601ce71a7c5732154cf9b2eeea64681469
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 10:36:12 2017 -0700

    compiler, runtime: include ptrmask in GC roots
    
    Change the list of registered GC roots to include a ptrmask,
    and change the data structures to be easily used from Go code.
    The new ptrmask will be used by the Go 1.8 GC to only scan pointers.
    Tweak the current GC to use the new structures, but ignore the new
    ptrmask information for now.
    
    The new GC root data includes the size of the variable.  The size is
    not currently used, but will be used later by the cgo checking code.
    
    Reviewed-on: https://go-review.googlesource.com/41075


commit 9e065149970bc180e4ca83bb99c74d9c4f43b47b
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 12:23:16 2017 -0700

    compiler, runtime: don't pass size to __go_new
    
    There is no reason to pass the size to __go_new, as the type
    descriptor includes the size anyhow.  This makes the function
    correspond to the Go 1.8 function runtime.newobject, which is what we
    will use when we update to the Go 1.8 memory allocator.
    
    Reviewed-on: https://go-review.googlesource.com/41080


commit c321de7b738c4a3387c1842919c9305acfa04c57
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 13:13:56 2017 -0700

    compiler, runtime, reflect: make type descriptors more like Go 1.8
    
    Change the type descriptor structure to be more like the one in the Go
    1.8 runtime.  Specifically we add the ptrdata field, rename the gc
    field to gcdata and change the type to *byte, and rearrange a few of
    the fields.  The structure is still not identical to the Go 1.8
    structure--we don't use any of the tricks to reduce overall executable
    size--but it is more similar.
    
    For now we don't use the new ptrdata field, and the gcdata field is
    still the old format rather than the new Go 1.8 ptrmask/gcprog format.
    
    Reviewed-on: https://go-review.googlesource.com/41081


commit 7b70c52cddeebea9ebeac003f8c6aad59497e5f0
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 14:54:29 2017 -0700

    reflect: make sure to clear unusable hash/equal function
    
    Otherwise we wind up copying the one from the prototype, which is wrong.
    
    Also rewrite the hash/equal functions to look like the ones in Go 1.8,
    mainly a matter of changing names and using arrayAt.
    
    Reviewed-on: https://go-review.googlesource.com/41133


commit 84d26f467f7de8bdbb0d230458135fe1b6b2a99d
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 14:59:13 2017 -0700

    runtime: remove duplicate declarations of SetFinalizer/KeepAlive
    
    These should have been removed in CL 38794.  It's a bug that the
    compiler even permits these duplicate declarations.
    
    Reviewed-on: https://go-review.googlesource.com/41134


commit f85ff7e64c24031f6d0bd7c9c426b6176cb95160
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 15:56:32 2017 -0700

    runtime: don't crash if panicstring called with no m
    
    It's possible for runtime_panicstring to be called with no m if a
    signal handler, or scheduler innards, do something wrong.  If that
    happens carry on with the panic rather than crashing.
    
    Reviewed-on: https://go-review.googlesource.com/41137


commit 5b362b04f642afb8b20715930416fc3b7d91bb12
Author: Than McIntosh <thanm@google.com>
Date:   Fri Mar 31 14:35:48 2017 -0400

    compiler: fix for expr sharing introduced by Order_eval::statement.
    
    When processing an expression statement with a top-level call
    that returns multiple results, Order_eval::statement can wind up
    creating a tree that has multiple references to the same call,
    which results in a confusing AST dump. Change the implementation
    to avoid introducing this unwanted sharing.
    
    Reviewed-on: https://go-review.googlesource.com/39210


commit b05b4260a68695bf9c9cc29e14ae86ca2699458a
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 16:00:28 2017 -0700

    runtime: restore correct m in gtraceback
    
    If gtraceback is used to get a stack trace of a g running in the same m,
    as can happen if we collect a stack trace from a g0, then restore the
    old m value, don't clear it.
    
    Reviewed-on: https://go-review.googlesource.com/41138


commit ca8bbf4dfac19b3f4f7ce21a688b96a418c75031
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 16:03:24 2017 -0700

    runtime: set startpc field when starting a new goroutine
    
    This puts the right value in a trace--previously it was always zero.
    
    Reviewed-on: https://go-review.googlesource.com/41139


commit ca8bbf4dfac19b3f4f7ce21a688b96a418c75031
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 16:03:24 2017 -0700

    runtime: set startpc field when starting a new goroutine
    
    This puts the right value in a trace--previously it was always zero.
    
    Reviewed-on: https://go-review.googlesource.com/41139


commit 887690dce42d7bf8f711f8ea082e4928fb70f2a5
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 17:06:11 2017 -0700

    runtime: add prefetch functions
    
    The Go 1.8 GC uses prefetch functions.  Add versions for gccgo that
    call __builtin_prefetch.  Uncomment the test for them in testAtomic64.
    Don't force the check function to return early, as now taking the
    address of a local variable in the runtime package does not force it
    onto the heap.
    
    Reviewed-on: https://go-review.googlesource.com/41144


commit 4269db69f9184e5a45c54aaee7352425a1f88bff
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 17:55:21 2017 -0700

    runtime: split up ticks to get correct alignment
    
    On 32-bit x86 a uint64 variable by itself is aligned to an 8-byte boundary.
    A uint64 field in a struct is aligned to a 4-byte boundary.
    The runtime.ticks variable has a uint64 field that must be aligned
    to an 8-byte boundary.  Rather than rely on luck, split up the struct
    into separate vars so that the required alignment happens reliably.
    
    It would be much nicer if issue golang/go#19057 were fixed somehow,
    but that is for another day.
    
    Reviewed-on: https://go-review.googlesource.com/41143


commit 66926cabdbdbf3431b4f172f7756e195c1c6c513
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Apr 20 17:15:38 2017 +0200

    libgo: fix bad value for O_CLOEXEC on AIX 7.1
    
    On AIX 7.1, O_CLOEXEC is defined as 0x0000001000000000, which
    creates an integer constant overflow error when building libgo.
    
    This affects only 7.1, O_CLOEXEC is not defined on 6.1 (and
    defaults to O in sysinfo.go) and is defined as 0x00800000 on
    AIX 7.2.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/41214


commit af288ff10aeafc47651f5def327ed56425d5be19
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 20 17:15:02 2017 -0700

    runtime: preserve stack context in tracebackothers
    
    The tracebackothers function works by saving the current stack context
    in the goroutine's context field and then calling gogo to switch to a
    new goroutine.  The new goroutine will collect its own stack trace and
    then call gogo to switch back to the original goroutine.  This works
    fine, but if the original goroutine was called by mcall then the
    contents of its context field are needed to return from the mcall.
    Fix this by saving the stack context across the calls to the other
    goroutines.
    
    Reviewed-on: https://go-review.googlesource.com/41293


commit 43101e5956e793f1b4de05c15d7738c785e927df
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Apr 21 10:58:52 2017 +0200

    os/user: use _posix_* libc functions
    
    libc getpwnam_r function has a different signature, we must use
    _posix_getpwnam_r instead (by default, the pwd.h system include
     file defines getpwnam_r as a static function calling
    _posix_getpwnam_r, so a C program calling getpwnam_r will indeed
    reference the _posix_getpwnam_r symbol).
    
    Idem for getpwuid_r, getgrnam_r and getgrgid_r.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/41334


commit 71e1fec4d2a536591ea6657a06916a17b5127071
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Apr 19 21:24:48 2017 -0700

    runtime: don't use pointers in g_ucontext_t or stackcontext
    
    The g_ucontext_t type holds registers saved for a goroutine.  We have
    to scan it for pointers, but since registers don't necessarily hold
    pointers we have to scan it conservatively.  That means that it should
    not have a pointer type, since the GC will always scan pointers.
    Instead it needs special treatment to be scanned conservatively.
    The current GC doesn't care when a pointer type holds a non-pointer,
    but the Go 1.8 GC does.
    
    For the current GC this means we have to explicitly scan the
    g_ucontext_t values in a G.
    
    While we're at it change stackcontext to be uintptr too.  The entries
    in stackcontext never hold pointers that the Go GC cares about.
    
    Reviewed-on: https://go-review.googlesource.com/41270


commit eab2960aee91d3e3a6baa5b1bce01262d24c714f
Author: Ian Lance Taylor <iant@golang.org>
Date:   Thu Apr 20 17:08:19 2017 -0700

    runtime/internal/sys: define Goexperiment
    
    The gc toolchain defines Goexperiment based on the environment
    variable GOEXPERIMENT when the toolchain is built.  We just always set
    Goexperiment to the empty string.
    
    Reviewed-on: https://go-review.googlesource.com/41292


commit be4a751943265c0637da859d15a4faf162f5c478
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Thu Apr 20 14:04:35 2017 +0200

    net: sockopt implementation for AIX
    
    This is a copy of the Linux implementation, it allows to
    run some simple client/server applications on AIX, while
    the current sockopt stubs don't.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/41213


commit 46a669c4ca5b80fd6f6a0a42095804d9f704611d
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Mar 29 17:55:06 2017 +0200

    math: fix sign for atan/expm1/log1p(-0)
    
    AIX libc returns +0 for atan(-0), expm1(-0) and log1p(-0),
    while matching Go functions must return -0.
    
    Code courtesy of Tony Reix.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/38699


commit 53b0e809130038a46f0a3d2870e3905f44ab888d
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Apr 26 17:29:22 2017 +0200

    runtime: fix context clobbering on AIX
    
    On AIX 64-bits, r13 is a pointer to thread data.
    setcontext() overwrites r13 with the value saved by getcontext().
    So, when a goroutine is scheduled on a new thread, r13 will point
    to the old thread data after calling setcontext().
    
    Code courtesy of Damien Bergamini.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/41854


commit f8d5ebd71c71e6e777200530d8204b92619157f8
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Wed Apr 26 18:01:19 2017 +0200

    runtime: fix wrong time calculation in semasleep
    
    tv_nsec is added twice when calculating the sleep end time.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/41855


commit ef56097f4ea848d48fbf61eba1c757fe7fce99d3
Author: Matthieu Sarter <matthieu.sarter.external@atos.net>
Date:   Fri Apr 28 10:27:32 2017 +0200

    libgo: pass $(NM) value when running benchmarks
    
    On AIX, we need to use "nm -B" instead of "nm", to have the
    epxected output format, so the configured $(NM) value from
    the Makefile should be exported before running gotest, which
    defaults to "nm" if $NM is not set.
    
    Issue golang/go#19200
    
    Reviewed-on: https://go-review.googlesource.com/42051


commit 0fb550083ae474fb964435927b899ec8e4b62771
Author: Ian Lance Taylor <iant@golang.org>
Date:   Wed Nov 16 21:12:53 2016 -0800

    runtime: copy garbage collector from Go 1.8 runtime
    
    This giant patch replaces the old Go 1.4 memory allocator and garbage
    collector with the new Go 1.8 code.  The memory allocator is fairly
    similar, though now written in Go rather than C.  The garbage
    collector is completely different.  It now uses ptrmask and gcprog
    information, which requires changes in the compiler and the reflect
    package as well as the runtime.  And, of course, the garbage collector
    now runs concurrently with program execution.
    
    In the gc toolchain the garbage collector is strict and precise at all
    levels.  In the gofrontend we do not have stack maps, so stacks, and
    register values, are collected conservatively.  That means that an
    old, no longer used, pointer on a stack or in a register can cause a
    memory object to live longer than it should.  That in turns means that
    we must disable some checks for invalid pointers in the garbage
    collection code.  Not only can we get an invalid pointer on the stack;
    the concurrent nature of the collector means that we can in effect
    resurrect a block that was already unmarked but that the collector had
    not yet gotten around to freeing, and that block can in turn point to
    other blocks that the collector had managed to already free.  So we
    must disable pointer checks in general.  In effect we are relying on
    the fact that the strict pointer checks in the gc toolchain ensure
    that the garbage collector is correct, and we just assume that it is
    correct for the gofrontend since we are using the same code.
    
    Reviewed-on: https://go-review.googlesource.com/41307


commit a95078d501175240d095500a8c5fbfb21bec65cb
Author: Ian Lance Taylor <iant@golang.org>
Date:   Mon Apr 24 16:33:47 2017 -0700

    libgo/Makefile: clean more files
    
    Fix up the mostlyclean, clean, and distclean targets to better follow
    https://www.gnu.org/prep/standards/html_node/Standard-Targets.html.
    
    Reviewed-on: https://go-review.googlesource.com/41625


commit 5956bf1055451cf4239cdfeca259c23b1ded54d8
Author: Ian Lance Taylor <iant@golang.org>
Date:   Mon May 8 13:35:11 2017 -0700

    libgo: delete goc2c
    
    The last .goc file has been removed, so remove goc2c.
    
    The goc2c program was my first contribution to the gc repository that
    was more than 100 lines:
    2b57a1124e
    The program was used in gc for a few years under various guises but
    was finally removed in https://golang.org/cl/132680043.  Now we can
    remove it from gofrontend as well.
    
    Reviewed-on: https://go-review.googlesource.com/42911


commit a222e35d041de0cd42506b61c93b8209e07702b9
Author: Than McIntosh <thanm@google.com>
Date:   Tue May 9 10:33:10 2017 -0400

    compiler: set "need_init_fn" when adding gc root
    
    Variables that back slice initializers in certain cases have to be
    added to the gc roots list, since they can be modified at runtime. The
    code that was doing this addition did not update the flag that tracks
    whether the package being compiled needs an initializer function,
    which resulted in the call in question being left out of the final
    generated code in certain cases. Fix is to change Gogo::add_gc_root()
    to update the "needs init" flag.
    
    Reviewed-on: https://go-review.googlesource.com/43030


commit 822ab419bf7d1c705cdce1c12133e7a11f56be2e
Author: Than McIntosh <thanm@google.com>
Date:   Tue May 9 11:36:51 2017 -0400

    compiler: fix variable context nit in write barrier generation
    
    Update the write barrier generation code to insure that the "lvalue
    context" tag on the space var expression is set only in the case where
    the expr feeds directly into an assignment. This is somewhat
    counter-intuitive, but needed in the case where the backend looks at
    context tags.
    
    Reviewed-on: https://go-review.googlesource.com/43031

From-SVN: r247848
This commit is contained in:
Ian Lance Taylor 2017-05-10 17:26:09 +00:00
parent 0f3744176f
commit f163907e0a
219 changed files with 17997 additions and 10934 deletions

View File

@ -1,3 +1,14 @@
2017-05-10 Than McIntosh <thanm@google.com>
* go-backend.c: Include "go-c.h".
* go-gcc.cc (Gcc_backend::write_export_data): New method.
2017-05-10 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::Gcc_backend): Declare
__builtin_prefetch.
* Make-lang.in (GO_OBJS): Add go/wb.o.
2017-03-28 Than McIntosh <thanm@google.com>
PR go/80226

View File

@ -72,7 +72,8 @@ GO_OBJS = \
go/runtime.o \
go/statements.o \
go/types.o \
go/unsafe.o
go/unsafe.o \
go/wb.o
go_OBJS = $(GO_OBJS) go/gospec.o

View File

@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "output.h" /* for assemble_string */
#include "common/common-target.h"
#include "go-c.h"
/* The segment name we pass to simple_object_start_read to find Go
export data. */

View File

@ -506,6 +506,10 @@ class Gcc_backend : public Backend
const std::vector<Bfunction*>&,
const std::vector<Bvariable*>&);
void
write_export_data(const char* bytes, unsigned int size);
private:
// Make a Bexpression from a tree.
Bexpression*
@ -748,6 +752,13 @@ Gcc_backend::Gcc_backend()
this->define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL,
build_function_type(void_type_node, void_list_node),
false, true);
// The runtime uses __builtin_prefetch.
this->define_builtin(BUILT_IN_PREFETCH, "__builtin_prefetch", NULL,
build_varargs_function_type_list(void_type_node,
const_ptr_type_node,
NULL_TREE),
false, false);
}
// Get an unnamed integer type.
@ -3212,6 +3223,13 @@ Gcc_backend::write_global_definitions(
delete[] defs;
}
void
Gcc_backend::write_export_data(const char* bytes, unsigned int size)
{
go_write_export_data(bytes, size);
}
// Define a builtin function. BCODE is the builtin function code
// defined by builtins.def. NAME is the name of the builtin function.
// LIBNAME is the name of the corresponding library function, and is

View File

@ -1,4 +1,4 @@
a4f445e18fb06a032a4399859f432e03245f1a7d
822ab419bf7d1c705cdce1c12133e7a11f56be2e
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -750,6 +750,11 @@ class Backend
const std::vector<Bexpression*>& constant_decls,
const std::vector<Bfunction*>& function_decls,
const std::vector<Bvariable*>& variable_decls) = 0;
// Write SIZE bytes of export data from BYTES to the proper
// section in the output object file.
virtual void
write_export_data(const char* bytes, unsigned int size) = 0;
};
#endif // !defined(GO_BACKEND_H)

View File

@ -14,6 +14,9 @@
#include "statements.h"
#include "export.h"
#include "go-linemap.h"
#include "backend.h"
// This file handles exporting global declarations.
// Class Export.
@ -359,6 +362,10 @@ Export::write_imported_init_fns(const std::string& package_name,
++p)
{
const Import_init* ii = *p;
if (ii->init_name() == import_init_fn)
continue;
this->write_c_string(" ");
this->write_string(ii->package_name());
this->write_c_string(" ");
@ -727,7 +734,8 @@ Export::Stream::write_checksum(const std::string& s)
// Class Stream_to_section.
Stream_to_section::Stream_to_section()
Stream_to_section::Stream_to_section(Backend* backend)
: backend_(backend)
{
}
@ -736,5 +744,5 @@ Stream_to_section::Stream_to_section()
void
Stream_to_section::do_write(const char* bytes, size_t length)
{
go_write_export_data (bytes, length);
this->backend_->write_export_data (bytes, length);
}

View File

@ -16,6 +16,7 @@ class Bindings;
class Type;
class Package;
class Import_init_set;
class Backend;
// Codes used for the builtin types. These are all negative to make
// them easily distinct from the codes assigned by Export::write_type.
@ -236,11 +237,14 @@ class Export : public String_dump
class Stream_to_section : public Export::Stream
{
public:
Stream_to_section();
Stream_to_section(Backend*);
protected:
void
do_write(const char*, size_t);
private:
Backend* backend_;
};
#endif // !defined(GO_EXPORT_H)

View File

@ -900,8 +900,8 @@ Temporary_reference_expression::do_get_backend(Translate_context* context)
// the circularity down one level.
Type* stype = this->statement_->type();
if (!this->is_lvalue_
&& stype->has_pointer()
&& stype->deref()->is_void_type())
&& stype->points_to() != NULL
&& stype->points_to()->is_void_type())
{
Btype* btype = this->type()->base()->get_backend(gogo);
ret = gogo->backend()->convert_expression(btype, ret, this->location());
@ -3311,7 +3311,18 @@ Type_conversion_expression::do_is_static_initializer() const
if (Type::are_identical(type, expr_type, false, NULL))
return true;
return type->is_basic_type() && expr_type->is_basic_type();
if (type->is_string_type() && expr_type->is_string_type())
return true;
if ((type->is_numeric_type()
|| type->is_boolean_type()
|| type->points_to() != NULL)
&& (expr_type->is_numeric_type()
|| expr_type->is_boolean_type()
|| expr_type->points_to() != NULL))
return true;
return false;
}
// Return the constant numeric value if there is one.
@ -3570,7 +3581,18 @@ Unsafe_type_conversion_expression::do_is_static_initializer() const
if (Type::are_convertible(type, expr_type, NULL))
return true;
return type->is_basic_type() && expr_type->is_basic_type();
if (type->is_string_type() && expr_type->is_string_type())
return true;
if ((type->is_numeric_type()
|| type->is_boolean_type()
|| type->points_to() != NULL)
&& (expr_type->is_numeric_type()
|| expr_type->is_boolean_type()
|| expr_type->points_to() != NULL))
return true;
return false;
}
// Convert to backend representation.
@ -3669,6 +3691,48 @@ Expression::make_unsafe_cast(Type* type, Expression* expr,
// Class Unary_expression.
// Call the address_taken method of the operand if needed. This is
// called after escape analysis but before inserting write barriers.
void
Unary_expression::check_operand_address_taken(Gogo* gogo)
{
if (this->op_ != OPERATOR_AND)
return;
// If this->escapes_ is false at this point, then it was set to
// false by an explicit call to set_does_not_escape, and the value
// does not escape. If this->escapes_ is true, we may be able to
// set it to false if taking the address of a variable that does not
// escape.
Node* n = Node::make_node(this);
if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
this->escapes_ = false;
// When compiling the runtime, the address operator does not cause
// local variables to escape. When escape analysis becomes the
// default, this should be changed to make it an error if we have an
// address operator that escapes.
if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
this->escapes_ = false;
Named_object* var = NULL;
if (this->expr_->var_expression() != NULL)
var = this->expr_->var_expression()->named_object();
else if (this->expr_->enclosed_var_expression() != NULL)
var = this->expr_->enclosed_var_expression()->variable();
if (this->escapes_ && var != NULL)
{
if (var->is_variable())
this->escapes_ = var->var_value()->escapes();
if (var->is_result_variable())
this->escapes_ = var->result_var_value()->escapes();
}
this->expr_->address_taken(this->escapes_);
}
// If we are taking the address of a composite literal, and the
// contents are not constant, then we want to make a heap expression
// instead.
@ -3795,40 +3859,6 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*,
}
}
if (this->op_ == OPERATOR_AND)
{
// If this->escapes_ is false at this point, then it was set to
// false by an explicit call to set_does_not_escape, and the
// value does not escape. If this->escapes_ is true, we may be
// able to set it to false if taking the address of a variable
// that does not escape.
Node* n = Node::make_node(this);
if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
this->escapes_ = false;
// When compiling the runtime, the address operator does not
// cause local variables to escape. When escape analysis
// becomes the default, this should be changed to make it an
// error if we have an address operator that escapes.
if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
this->escapes_ = false;
Named_object* var = NULL;
if (this->expr_->var_expression() != NULL)
var = this->expr_->var_expression()->named_object();
else if (this->expr_->enclosed_var_expression() != NULL)
var = this->expr_->enclosed_var_expression()->variable();
if (this->escapes_ && var != NULL)
{
if (var->is_variable())
this->escapes_ = var->var_value()->escapes();
if (var->is_result_variable())
this->escapes_ = var->result_var_value()->escapes();
}
this->expr_->address_taken(this->escapes_);
}
if (this->create_temp_ && !this->expr_->is_variable())
{
Temporary_statement* temp =
@ -7759,7 +7789,16 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
lhs = Expression::make_index(ref, ref2, NULL, NULL, loc);
gogo->lower_expression(function, inserter, &lhs);
gogo->flatten_expression(function, inserter, &lhs);
assign = Statement::make_assignment(lhs, *pa, loc);
// The flatten pass runs after the write barrier pass, so we
// need to insert a write barrier here if necessary.
if (!gogo->assign_needs_write_barrier(lhs))
assign = Statement::make_assignment(lhs, *pa, loc);
else
{
Function* f = function == NULL ? NULL : function->func_value();
assign = gogo->assign_with_write_barrier(f, NULL, inserter,
lhs, *pa, loc);
}
inserter->insert(assign);
}
}
@ -9539,6 +9578,12 @@ Call_expression::lower_varargs(Gogo* gogo, Named_object* function,
Type* varargs_type, size_t param_count,
Slice_storage_escape_disp escape_disp)
{
// When compiling the runtime, varargs slices do not escape. When
// escape analysis becomes the default, this should be changed to
// make it an error if we have a varargs slice that escapes.
if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
escape_disp = SLICE_STORAGE_DOES_NOT_ESCAPE;
if (this->varargs_are_lowered_)
return;
@ -10250,16 +10295,13 @@ Call_expression::do_get_backend(Translate_context* context)
if (this->results_ != NULL)
{
go_assert(this->call_temp_ != NULL);
Expression* call_ref =
Expression::make_temporary_reference(this->call_temp_, location);
Bexpression* bcall_ref = call_ref->get_backend(context);
Bexpression* bcall_ref = this->call_result_ref(context);
Bfunction* bfunction = context->function()->func_value()->get_decl();
Bstatement* assn_stmt =
gogo->backend()->assignment_statement(bfunction,
bcall_ref, call, location);
this->call_ = this->set_results(context, bcall_ref);
this->call_ = this->set_results(context);
Bexpression* set_and_call =
gogo->backend()->compound_expression(assn_stmt, this->call_,
@ -10271,16 +10313,32 @@ Call_expression::do_get_backend(Translate_context* context)
return this->call_;
}
// Return the backend representation of a reference to the struct used
// to capture the result of a multiple-output call.
Bexpression*
Call_expression::call_result_ref(Translate_context* context)
{
go_assert(this->call_temp_ != NULL);
Location location = this->location();
Expression* call_ref =
Expression::make_temporary_reference(this->call_temp_, location);
Bexpression* bcall_ref = call_ref->get_backend(context);
return bcall_ref;
}
// Set the result variables if this call returns multiple results.
Bexpression*
Call_expression::set_results(Translate_context* context, Bexpression* call)
Call_expression::set_results(Translate_context* context)
{
Gogo* gogo = context->gogo();
Bexpression* results = NULL;
Location loc = this->location();
go_assert(this->call_temp_ != NULL);
size_t rc = this->result_count();
for (size_t i = 0; i < rc; ++i)
{
@ -10296,12 +10354,15 @@ Call_expression::set_results(Translate_context* context, Bexpression* call)
Bfunction* bfunction = context->function()->func_value()->get_decl();
Bexpression* result_ref = ref->get_backend(context);
Bexpression* bcall_ref = this->call_result_ref(context);
Bexpression* call_result =
gogo->backend()->struct_field_expression(call, i, loc);
gogo->backend()->struct_field_expression(bcall_ref, i, loc);
Bstatement* assn_stmt =
gogo->backend()->assignment_statement(bfunction,
result_ref, call_result, loc);
bcall_ref = this->call_result_ref(context);
call_result = gogo->backend()->struct_field_expression(bcall_ref, i, loc);
Bexpression* result =
gogo->backend()->compound_expression(assn_stmt, call_result, loc);
@ -10860,7 +10921,7 @@ Array_index_expression::do_flatten(Gogo*, Named_object*,
inserter->insert(temp);
this->end_ = Expression::make_temporary_reference(temp, loc);
}
if (cap!= NULL && !cap->is_variable())
if (cap != NULL && !cap->is_variable())
{
temp = Statement::make_temporary(NULL, cap, loc);
inserter->insert(temp);
@ -11047,16 +11108,28 @@ Array_index_expression::do_get_backend(Translate_context* context)
bad_index, loc);
}
Expression* valptr = array_type->get_value_pointer(gogo, this->array_);
Bexpression* val = valptr->get_backend(context);
val = gogo->backend()->pointer_offset_expression(val, start, loc);
Bexpression* result_length =
gogo->backend()->binary_expression(OPERATOR_MINUS, end, start, loc);
Bexpression* result_capacity =
gogo->backend()->binary_expression(OPERATOR_MINUS, cap_arg, start, loc);
// If the new capacity is zero, don't change val. Otherwise we can
// get a pointer to the next object in memory, keeping it live
// unnecessarily. When the capacity is zero, the actual pointer
// value doesn't matter.
Bexpression* zero =
Expression::make_integer_ul(0, int_type, loc)->get_backend(context);
Bexpression* cond =
gogo->backend()->binary_expression(OPERATOR_EQEQ, result_capacity, zero,
loc);
Bexpression* offset = gogo->backend()->conditional_expression(bfn, int_btype,
cond, zero,
start, loc);
Expression* valptr = array_type->get_value_pointer(gogo, this->array_);
Bexpression* val = valptr->get_backend(context);
val = gogo->backend()->pointer_offset_expression(val, offset, loc);
Btype* struct_btype = this->type()->get_backend(gogo);
std::vector<Bexpression*> init;
init.push_back(val);
@ -13065,10 +13138,12 @@ Slice_construction_expression::do_flatten(Gogo* gogo, Named_object* no,
this->Array_construction_expression::do_flatten(gogo, no, inserter);
// Create a stack-allocated storage temp if storage won't escape
if (!this->storage_escapes_ && this->slice_storage_ == NULL)
if (!this->storage_escapes_
&& this->slice_storage_ == NULL
&& this->element_count() > 0)
{
Location loc = this->location();
this->array_val_ = create_array_val();
this->array_val_ = this->create_array_val();
go_assert(this->array_val_);
Temporary_statement* temp =
Statement::make_temporary(this->valtype_, this->array_val_, loc);
@ -13098,7 +13173,7 @@ Bexpression*
Slice_construction_expression::do_get_backend(Translate_context* context)
{
if (this->array_val_ == NULL)
this->array_val_ = create_array_val();
this->array_val_ = this->create_array_val();
if (this->array_val_ == NULL)
{
go_assert(this->type()->is_error());
@ -14216,14 +14291,15 @@ Heap_expression::do_type()
Bexpression*
Heap_expression::do_get_backend(Translate_context* context)
{
if (this->expr_->is_error_expression() || this->expr_->type()->is_error())
Type* etype = this->expr_->type();
if (this->expr_->is_error_expression() || etype->is_error())
return context->backend()->error_expression();
Location loc = this->location();
Gogo* gogo = context->gogo();
Btype* btype = this->type()->get_backend(gogo);
Expression* alloc = Expression::make_allocation(this->expr_->type(), loc);
Expression* alloc = Expression::make_allocation(etype, loc);
Node* n = Node::make_node(this);
if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
alloc->allocation_expression()->set_allocate_on_stack();
@ -14236,14 +14312,43 @@ Heap_expression::do_get_backend(Translate_context* context)
Bvariable* space_temp =
gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
space, true, loc, &decl);
space = gogo->backend()->var_expression(space_temp, VE_lvalue, loc);
Btype* expr_btype = this->expr_->type()->get_backend(gogo);
Bexpression* ref =
gogo->backend()->indirect_expression(expr_btype, space, true, loc);
Btype* expr_btype = etype->get_backend(gogo);
Bexpression* bexpr = this->expr_->get_backend(context);
Bstatement* assn = gogo->backend()->assignment_statement(fndecl, ref,
bexpr, loc);
// If this assignment needs a write barrier, call typedmemmove. We
// don't do this in the write barrier pass because in some cases
// backend conversion can introduce new Heap_expression values.
Bstatement* assn;
if (!etype->has_pointer())
{
space = gogo->backend()->var_expression(space_temp, VE_lvalue, loc);
Bexpression* ref =
gogo->backend()->indirect_expression(expr_btype, space, true, loc);
assn = gogo->backend()->assignment_statement(fndecl, ref, bexpr, loc);
}
else
{
Bstatement* edecl;
Bvariable* btemp =
gogo->backend()->temporary_variable(fndecl, context->bblock(),
expr_btype, bexpr, true, loc,
&edecl);
Bexpression* btempref = gogo->backend()->var_expression(btemp,
VE_lvalue, loc);
Bexpression* addr = gogo->backend()->address_expression(btempref, loc);
Expression* td = Expression::make_type_descriptor(etype, loc);
Type* etype_ptr = Type::make_pointer_type(etype);
space = gogo->backend()->var_expression(space_temp, VE_rvalue, loc);
Expression* elhs = Expression::make_backend(space, etype_ptr, loc);
Expression* erhs = Expression::make_backend(addr, etype_ptr, loc);
Expression* call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
td, elhs, erhs);
Bexpression* bcall = call->get_backend(context);
Bstatement* s = gogo->backend()->expression_statement(fndecl, bcall);
assn = gogo->backend()->compound_statement(edecl, s);
}
decl = gogo->backend()->compound_statement(decl, assn);
space = gogo->backend()->var_expression(space_temp, VE_rvalue, loc);
return gogo->backend()->compound_expression(decl, space, loc);
@ -14468,7 +14573,7 @@ class GC_symbol_expression : public Expression
protected:
Type*
do_type()
{ return Type::lookup_integer_type("uintptr"); }
{ return Type::make_pointer_type(Type::lookup_integer_type("uint8")); }
bool
do_is_static_initializer() const
@ -14513,6 +14618,91 @@ Expression::make_gc_symbol(Type* type)
return new GC_symbol_expression(type);
}
// An expression that evaluates to a pointer to a symbol holding the
// ptrmask data of a type.
class Ptrmask_symbol_expression : public Expression
{
public:
Ptrmask_symbol_expression(Type* type)
: Expression(EXPRESSION_PTRMASK_SYMBOL, Linemap::predeclared_location()),
type_(type)
{}
protected:
Type*
do_type()
{ return Type::make_pointer_type(Type::lookup_integer_type("uint8")); }
bool
do_is_static_initializer() const
{ return true; }
void
do_determine_type(const Type_context*)
{ }
Expression*
do_copy()
{ return this; }
Bexpression*
do_get_backend(Translate_context*);
void
do_dump_expression(Ast_dump_context*) const;
private:
// The type that this ptrmask symbol describes.
Type* type_;
};
// Return the ptrmask variable.
Bexpression*
Ptrmask_symbol_expression::do_get_backend(Translate_context* context)
{
Gogo* gogo = context->gogo();
// If this type does not need a gcprog, then we can use the standard
// GC symbol.
int64_t ptrsize, ptrdata;
if (!this->type_->needs_gcprog(gogo, &ptrsize, &ptrdata))
return this->type_->gc_symbol_pointer(gogo);
// Otherwise we have to build a ptrmask variable, and return a
// pointer to it.
Bvariable* bvar = this->type_->gc_ptrmask_var(gogo, ptrsize, ptrdata);
Location bloc = Linemap::predeclared_location();
Bexpression* bref = gogo->backend()->var_expression(bvar, VE_rvalue, bloc);
Bexpression* baddr = gogo->backend()->address_expression(bref, bloc);
Type* uint8_type = Type::lookup_integer_type("uint8");
Type* pointer_uint8_type = Type::make_pointer_type(uint8_type);
Btype* ubtype = pointer_uint8_type->get_backend(gogo);
return gogo->backend()->convert_expression(ubtype, baddr, bloc);
}
// Dump AST for a ptrmask symbol expression.
void
Ptrmask_symbol_expression::do_dump_expression(
Ast_dump_context* ast_dump_context) const
{
ast_dump_context->ostream() << "ptrmask(";
ast_dump_context->dump_type(this->type_);
ast_dump_context->ostream() << ")";
}
// Make a ptrmask symbol expression.
Expression*
Expression::make_ptrmask_symbol(Type* type)
{
return new Ptrmask_symbol_expression(type);
}
// An expression which evaluates to some characteristic of a type.
// This is only used to initialize fields of a type descriptor. Using
// a new expression class is slightly inefficient but gives us a good
@ -14565,6 +14755,8 @@ Type_info_expression::do_type()
switch (this->type_info_)
{
case TYPE_INFO_SIZE:
case TYPE_INFO_BACKEND_PTRDATA:
case TYPE_INFO_DESCRIPTOR_PTRDATA:
return Type::lookup_integer_type("uintptr");
case TYPE_INFO_ALIGNMENT:
case TYPE_INFO_FIELD_ALIGNMENT:
@ -14593,6 +14785,12 @@ Type_info_expression::do_get_backend(Translate_context* context)
case TYPE_INFO_FIELD_ALIGNMENT:
ok = this->type_->backend_type_field_align(gogo, &val);
break;
case TYPE_INFO_BACKEND_PTRDATA:
ok = this->type_->backend_type_ptrdata(gogo, &val);
break;
case TYPE_INFO_DESCRIPTOR_PTRDATA:
ok = this->type_->descriptor_ptrdata(gogo, &val);
break;
default:
go_unreachable();
}
@ -14618,7 +14816,9 @@ Type_info_expression::do_dump_expression(
ast_dump_context->ostream() <<
(this->type_info_ == TYPE_INFO_ALIGNMENT ? "alignment"
: this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT ? "field alignment"
: this->type_info_ == TYPE_INFO_SIZE ? "size "
: this->type_info_ == TYPE_INFO_SIZE ? "size"
: this->type_info_ == TYPE_INFO_BACKEND_PTRDATA ? "backend_ptrdata"
: this->type_info_ == TYPE_INFO_DESCRIPTOR_PTRDATA ? "descriptor_ptrdata"
: "unknown");
ast_dump_context->ostream() << ")";
}
@ -15924,6 +16124,73 @@ Numeric_constant::mpfr_to_unsigned_long(const mpfr_t fval,
return ret;
}
// Express value as memory size if possible.
bool
Numeric_constant::to_memory_size(int64_t* val) const
{
switch (this->classification_)
{
case NC_INT:
case NC_RUNE:
return this->mpz_to_memory_size(this->u_.int_val, val);
case NC_FLOAT:
return this->mpfr_to_memory_size(this->u_.float_val, val);
case NC_COMPLEX:
if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
return false;
return this->mpfr_to_memory_size(mpc_realref(this->u_.complex_val), val);
default:
go_unreachable();
}
}
// Express integer as memory size if possible.
bool
Numeric_constant::mpz_to_memory_size(const mpz_t ival, int64_t* val) const
{
if (mpz_sgn(ival) < 0)
return false;
if (mpz_fits_slong_p(ival))
{
*val = static_cast<int64_t>(mpz_get_si(ival));
return true;
}
// Test >= 64, not > 64, because an int64_t can hold 63 bits of a
// positive value.
if (mpz_sizeinbase(ival, 2) >= 64)
return false;
mpz_t q, r;
mpz_init(q);
mpz_init(r);
mpz_tdiv_q_2exp(q, ival, 32);
mpz_tdiv_r_2exp(r, ival, 32);
go_assert(mpz_fits_ulong_p(q) && mpz_fits_ulong_p(r));
*val = ((static_cast<int64_t>(mpz_get_ui(q)) << 32)
+ static_cast<int64_t>(mpz_get_ui(r)));
mpz_clear(r);
mpz_clear(q);
return true;
}
// Express floating point value as memory size if possible.
bool
Numeric_constant::mpfr_to_memory_size(const mpfr_t fval, int64_t* val) const
{
if (!mpfr_integer_p(fval))
return false;
mpz_t ival;
mpz_init(ival);
mpfr_get_z(ival, fval, GMP_RNDN);
bool ret = this->mpz_to_memory_size(ival, val);
mpz_clear(ival);
return ret;
}
// Convert value to integer if possible.
bool

View File

@ -128,6 +128,7 @@ class Expression
EXPRESSION_RECEIVE,
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_GC_SYMBOL,
EXPRESSION_PTRMASK_SYMBOL,
EXPRESSION_TYPE_INFO,
EXPRESSION_SLICE_INFO,
EXPRESSION_SLICE_VALUE,
@ -402,6 +403,13 @@ class Expression
static Expression*
make_gc_symbol(Type* type);
// Make an expression that evaluates to the address of a ptrmask
// symbol for TYPE. For most types this will be the same as
// make_gc_symbol, but for larger types make_gc_symbol will return a
// gcprog while this will return a ptrmask.
static Expression*
make_ptrmask_symbol(Type* type);
// Make an expression which evaluates to some characteristic of a
// type. These are only used for type descriptors, so there is no
// location parameter.
@ -413,7 +421,15 @@ class Expression
TYPE_INFO_ALIGNMENT,
// The required alignment of a value of the type when used as a
// field in a struct.
TYPE_INFO_FIELD_ALIGNMENT
TYPE_INFO_FIELD_ALIGNMENT,
// The size of the prefix of a value of the type that contains
// all the pointers. This is 0 for a type that contains no
// pointers. It is always <= TYPE_INFO_SIZE.
TYPE_INFO_BACKEND_PTRDATA,
// Like TYPE_INFO_BACKEND_PTRDATA, but the ptrdata value that we
// want to store in a type descriptor. They are the same for
// most types, but can differ for a type that uses a gcprog.
TYPE_INFO_DESCRIPTOR_PTRDATA
};
static Expression*
@ -1774,6 +1790,10 @@ class Unary_expression : public Expression
this->is_slice_init_ = true;
}
// Call the address_taken method on the operand if necessary.
void
check_operand_address_taken(Gogo*);
// Apply unary opcode OP to UNC, setting NC. Return true if this
// could be done, false if not. On overflow, issues an error and
// sets *ISSUED_ERROR.
@ -2270,7 +2290,10 @@ class Call_expression : public Expression
Expression**);
Bexpression*
set_results(Translate_context*, Bexpression*);
set_results(Translate_context*);
Bexpression*
call_result_ref(Translate_context* context);
// The function to call.
Expression* fn_;
@ -4011,6 +4034,13 @@ class Numeric_constant
To_unsigned_long
to_unsigned_long(unsigned long* val) const;
// If the value can be expressed as an integer that describes the
// size of an object in memory, set *VAL and return true.
// Otherwise, return false. Currently we use int64_t to represent a
// memory size, as in Type::backend_type_size.
bool
to_memory_size(int64_t* val) const;
// If the value can be expressed as an int, return true and
// initialize and set VAL. This will return false for a value with
// an explicit float or complex type, even if the value is integral.
@ -4052,6 +4082,12 @@ class Numeric_constant
To_unsigned_long
mpfr_to_unsigned_long(const mpfr_t fval, unsigned long *val) const;
bool
mpz_to_memory_size(const mpz_t ival, int64_t* val) const;
bool
mpfr_to_memory_size(const mpfr_t fval, int64_t* val) const;
bool
check_int_type(Integer_type*, bool, Location);

View File

@ -158,6 +158,9 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
// Write out queued up functions for hash and comparison of types.
::gogo->write_specific_type_functions();
// Add write barriers.
::gogo->add_write_barriers();
// Flatten the parse tree.
::gogo->flatten();

View File

@ -720,15 +720,18 @@ Gogo::init_imports(std::vector<Bstatement*>& init_stmts, Bfunction *bfunction)
// roots during the mark phase. We build a struct that is easy to
// hook into a list of roots.
// struct __go_gc_root_list
// {
// struct __go_gc_root_list* __next;
// struct __go_gc_root
// {
// void* __decl;
// size_t __size;
// } __roots[];
// };
// type gcRoot struct {
// decl unsafe.Pointer // Pointer to variable.
// size uintptr // Total size of variable.
// ptrdata uintptr // Length of variable's gcdata.
// gcdata *byte // Pointer mask.
// }
//
// type gcRootList struct {
// next *gcRootList
// count int
// roots [...]gcRoot
// }
// The last entry in the roots array has a NULL decl field.
@ -737,28 +740,35 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
std::vector<Bstatement*>& init_stmts,
Bfunction* init_bfn)
{
if (var_gc.empty())
if (var_gc.empty() && this->gc_roots_.empty())
return;
Type* pvt = Type::make_pointer_type(Type::make_void_type());
Type* uint_type = Type::lookup_integer_type("uint");
Struct_type* root_type = Type::make_builtin_struct_type(2,
"__decl", pvt,
"__size", uint_type);
Type* uintptr_type = Type::lookup_integer_type("uintptr");
Type* byte_type = this->lookup_global("byte")->type_value();
Type* pointer_byte_type = Type::make_pointer_type(byte_type);
Struct_type* root_type =
Type::make_builtin_struct_type(4,
"decl", pvt,
"size", uintptr_type,
"ptrdata", uintptr_type,
"gcdata", pointer_byte_type);
Location builtin_loc = Linemap::predeclared_location();
unsigned roots_len = var_gc.size() + this->gc_roots_.size() + 1;
unsigned long roots_len = var_gc.size() + this->gc_roots_.size();
Expression* length = Expression::make_integer_ul(roots_len, NULL,
builtin_loc);
Array_type* root_array_type = Type::make_array_type(root_type, length);
root_array_type->set_is_array_incomparable();
Type* ptdt = Type::make_type_descriptor_ptr_type();
Struct_type* root_list_type =
Type::make_builtin_struct_type(2,
"__next", ptdt,
"__roots", root_array_type);
// Build an initializer for the __roots array.
Type* int_type = Type::lookup_integer_type("int");
Struct_type* root_list_type =
Type::make_builtin_struct_type(3,
"next", pvt,
"count", int_type,
"roots", root_array_type);
// Build an initializer for the roots array.
Expression_list* roots_init = new Expression_list();
@ -772,11 +782,22 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
Expression* decl = Expression::make_var_reference(*p, no_loc);
Expression* decl_addr =
Expression::make_unary(OPERATOR_AND, decl, no_loc);
decl_addr->unary_expression()->set_does_not_escape();
decl_addr = Expression::make_cast(pvt, decl_addr, no_loc);
init->push_back(decl_addr);
Expression* decl_size =
Expression::make_type_info(decl->type(), Expression::TYPE_INFO_SIZE);
init->push_back(decl_size);
Expression* size =
Expression::make_type_info(decl->type(),
Expression::TYPE_INFO_SIZE);
init->push_back(size);
Expression* ptrdata =
Expression::make_type_info(decl->type(),
Expression::TYPE_INFO_BACKEND_PTRDATA);
init->push_back(ptrdata);
Expression* gcdata = Expression::make_ptrmask_symbol(decl->type());
init->push_back(gcdata);
Expression* root_ctor =
Expression::make_struct_composite_literal(root_type, init, no_loc);
@ -791,37 +812,35 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
Expression* expr = *p;
Location eloc = expr->location();
init->push_back(expr);
init->push_back(Expression::make_cast(pvt, expr, eloc));
Type* type = expr->type()->points_to();
go_assert(type != NULL);
Expression* size =
Expression::make_type_info(type, Expression::TYPE_INFO_SIZE);
Expression::make_type_info(type,
Expression::TYPE_INFO_SIZE);
init->push_back(size);
Expression* ptrdata =
Expression::make_type_info(type,
Expression::TYPE_INFO_BACKEND_PTRDATA);
init->push_back(ptrdata);
Expression* gcdata = Expression::make_ptrmask_symbol(type);
init->push_back(gcdata);
Expression* root_ctor =
Expression::make_struct_composite_literal(root_type, init, eloc);
roots_init->push_back(root_ctor);
}
// The list ends with a NULL entry.
Expression_list* null_init = new Expression_list();
Expression* nil = Expression::make_nil(builtin_loc);
null_init->push_back(nil);
Expression *zero = Expression::make_integer_ul(0, NULL, builtin_loc);
null_init->push_back(zero);
Expression* null_root_ctor =
Expression::make_struct_composite_literal(root_type, null_init,
builtin_loc);
roots_init->push_back(null_root_ctor);
// Build a constructor for the struct.
Expression_list* root_list_init = new Expression_list();
root_list_init->push_back(nil);
root_list_init->push_back(Expression::make_nil(builtin_loc));
root_list_init->push_back(Expression::make_integer_ul(roots_len, int_type,
builtin_loc));
Expression* roots_ctor =
Expression::make_array_composite_literal(root_array_type, roots_init,
@ -1216,24 +1235,31 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits)
}
// VAR_INITS is in the correct order. For each VAR in VAR_INITS,
// check for a loop of VAR on itself. We only do this if
// INIT is not NULL and there is no dependency; when INIT is
// NULL, it means that PREINIT sets VAR, which we will
// check for a loop of VAR on itself.
// interpret as a loop.
for (Var_inits::const_iterator p = var_inits->begin();
p != var_inits->end();
++p)
{
Named_object* var = p->var();
Expression* init = var->var_value()->init();
Block* preinit = var->var_value()->preinit();
Named_object* dep = gogo->var_depends_on(var->var_value());
if (init != NULL && dep == NULL
&& expression_requires(init, preinit, NULL, var))
go_error_at(var->location(),
"initialization expression for %qs depends upon itself",
var->message_name().c_str());
}
gogo->check_self_dep(p->var());
}
// Give an error if the initialization expression for VAR depends on
// itself. We only check if INIT is not NULL and there is no
// dependency; when INIT is NULL, it means that PREINIT sets VAR,
// which we will interpret as a loop.
void
Gogo::check_self_dep(Named_object* var)
{
Expression* init = var->var_value()->init();
Block* preinit = var->var_value()->preinit();
Named_object* dep = this->var_depends_on(var->var_value());
if (init != NULL
&& dep == NULL
&& expression_requires(init, preinit, NULL, var))
go_error_at(var->location(),
"initialization expression for %qs depends upon itself",
var->message_name().c_str());
}
// Write out the global definitions.
@ -1425,8 +1451,18 @@ Gogo::write_globals()
var_inits.push_back(Var_init(no, zero_stmt));
}
// Collect a list of all global variables with pointers,
// to register them for the garbage collector.
if (!is_sink && var->type()->has_pointer())
var_gc.push_back(no);
{
// Avoid putting runtime.gcRoots itself on the list.
if (this->compiling_runtime()
&& this->package_name() == "runtime"
&& Gogo::unpack_hidden_name(no->name()) == "gcRoots")
;
else
var_gc.push_back(no);
}
}
}
@ -3584,14 +3620,14 @@ class Order_eval : public Traverse
// Implement the order of evaluation rules for a statement.
int
Order_eval::statement(Block* block, size_t* pindex, Statement* s)
Order_eval::statement(Block* block, size_t* pindex, Statement* stmt)
{
// FIXME: This approach doesn't work for switch statements, because
// we add the new statements before the whole switch when we need to
// instead add them just before the switch expression. The right
// fix is probably to lower switch statements with nonconstant cases
// to a series of conditionals.
if (s->switch_statement() != NULL)
if (stmt->switch_statement() != NULL)
return TRAVERSE_CONTINUE;
Find_eval_ordering find_eval_ordering;
@ -3599,11 +3635,11 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
// If S is a variable declaration, then ordinary traversal won't do
// anything. We want to explicitly traverse the initialization
// expression if there is one.
Variable_declaration_statement* vds = s->variable_declaration_statement();
Variable_declaration_statement* vds = stmt->variable_declaration_statement();
Expression* init = NULL;
Expression* orig_init = NULL;
if (vds == NULL)
s->traverse_contents(&find_eval_ordering);
stmt->traverse_contents(&find_eval_ordering);
else
{
init = vds->var()->var_value()->init();
@ -3636,7 +3672,7 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
// usually leave it in place.
if (c == 1)
{
switch (s->classification())
switch (stmt->classification())
{
case Statement::STATEMENT_ASSIGNMENT:
// For an assignment statement, we need to evaluate an
@ -3653,7 +3689,7 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
// move. We need to move any subexpressions in case they
// are themselves call statements that require passing a
// closure.
Expression* expr = s->expression_statement()->expr();
Expression* expr = stmt->expression_statement()->expr();
if (expr->call_expression() != NULL
&& expr->call_expression()->result_count() == 0)
break;
@ -3666,7 +3702,8 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
}
}
bool is_thunk = s->thunk_statement() != NULL;
bool is_thunk = stmt->thunk_statement() != NULL;
Expression_statement* es = stmt->expression_statement();
for (Find_eval_ordering::const_iterator p = find_eval_ordering.begin();
p != find_eval_ordering.end();
++p)
@ -3697,9 +3734,14 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
//
// Since a given call expression can be shared by multiple
// Call_result_expressions, avoid hoisting the call the
// second time we see it here.
// second time we see it here. In addition, don't try to
// hoist the top-level multi-return call in the statement,
// since doing this would result a tree with more than one copy
// of the call.
if (this->remember_expression(*pexpr))
s = NULL;
else if (es != NULL && *pexpr == es->expr())
s = NULL;
else
s = Statement::make_statement(*pexpr, true);
}
@ -4448,9 +4490,7 @@ Expression*
Gogo::allocate_memory(Type* type, Location location)
{
Expression* td = Expression::make_type_descriptor(type, location);
Expression* size =
Expression::make_type_info(type, Expression::TYPE_INFO_SIZE);
return Runtime::make_call(Runtime::NEW, location, 2, td, size);
return Runtime::make_call(Runtime::NEW, location, 1, td);
}
// Traversal class used to check for return statements.
@ -4502,7 +4542,7 @@ Gogo::do_exports()
{
// For now we always stream to a section. Later we may want to
// support streaming to a separate file.
Stream_to_section stream;
Stream_to_section stream(this->backend());
// Write out either the prefix or pkgpath depending on how we were
// invoked.
@ -6696,11 +6736,19 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
asm_name.append(n);
}
asm_name = go_encode_id(asm_name);
bool is_hidden = Gogo::is_hidden_name(name);
// Hack to export runtime.writeBarrier. FIXME.
// This is because go:linkname doesn't work on variables.
if (gogo->compiling_runtime()
&& var_name == "runtime.writeBarrier")
is_hidden = false;
bvar = backend->global_variable(var_name,
asm_name,
btype,
package != NULL,
Gogo::is_hidden_name(name),
is_hidden,
this->in_unique_section_,
this->location_);
}

View File

@ -585,7 +585,10 @@ class Gogo
// variable initializers that would otherwise not be seen.
void
add_gc_root(Expression* expr)
{ this->gc_roots_.push_back(expr); }
{
this->set_need_init_fn();
this->gc_roots_.push_back(expr);
}
// Traverse the tree. See the Traverse class.
void
@ -693,6 +696,23 @@ class Gogo
void
order_evaluations();
// Add write barriers as needed.
void
add_write_barriers();
// Return whether an assignment that sets LHS to RHS needs a write
// barrier.
bool
assign_needs_write_barrier(Expression* lhs);
// Return an assignment that sets LHS to RHS using a write barrier.
// This returns an if statement that checks whether write barriers
// are enabled. If not, it does LHS = RHS, otherwise it calls the
// appropriate write barrier function.
Statement*
assign_with_write_barrier(Function*, Block*, Statement_inserter*,
Expression* lhs, Expression* rhs, Location);
// Flatten parse tree.
void
flatten();
@ -737,6 +757,10 @@ class Gogo
named_types_are_converted() const
{ return this->named_types_are_converted_; }
// Give an error if the initialization of VAR depends on itself.
void
check_self_dep(Named_object*);
// Write out the global values.
void
write_globals();
@ -805,6 +829,12 @@ class Gogo
std::vector<Bstatement*>&,
Bfunction* init_bfunction);
Named_object*
write_barrier_variable();
Statement*
check_write_barrier(Block*, Statement*, Statement*);
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
@ -1096,6 +1126,11 @@ class Function
set_asm_name(const std::string& asm_name)
{ this->asm_name_ = asm_name; }
// Return the pragmas for this function.
unsigned int
pragmas() const
{ return this->pragmas_; }
// Set the pragmas for this function.
void
set_pragmas(unsigned int pragmas)
@ -1648,7 +1683,7 @@ class Variable
set_is_used()
{ this->is_used_ = true; }
// Clear the initial value; used for error handling.
// Clear the initial value; used for error handling and write barriers.
void
clear_init()
{ this->init_ = NULL; }

View File

@ -25,8 +25,33 @@ static const char armagt[] =
'!', '<', 't', 'h', 'i', 'n', '>', '\n'
};
static const char armagb[] =
{
'<', 'b', 'i', 'g', 'a', 'f', '>', '\n'
};
static const char arfmag[2] = { '`', '\n' };
// Archive fixed length header for AIX big format.
struct Archive_fl_header
{
// Archive magic string.
char fl_magic[8];
// Offset to member table.
char fl_memoff[20];
// Offset to global symbol table.
char fl_gstoff[20];
// Offset to global symbol table for 64-bit objects.
char fl_gst64off[20];
// Offset to first archive member.
char fl_fstmoff[20];
// Offset to last archive member.
char fl_lstmoff[20];
// Offset to first member on free list.
char fl_freeoff[20];
};
// The header of an entry in an archive. This is all readable text,
// padded with spaces where necesary.
@ -48,6 +73,29 @@ struct Archive_header
char ar_fmag[2];
};
// The header of an entry in an AIX big archive.
// This is followed by ar_namlen bytes + 2 bytes for arfmag.
struct Archive_big_header
{
// The file size in decimal.
char ar_size[20];
// The next member offset in decimal.
char ar_nxtmem[20];
// The previous member offset in decimal.
char ar_prvmem[20];
// The file modification time in decimal.
char ar_date[12];
// The user's UID in decimal.
char ar_uid[12];
// The user's GID in decimal.
char ar_gid[12];
// The file mode in octal.
char ar_mode[12];
// The file name length in decimal.
char ar_namlen[4];
};
// The functions in this file extract Go export data from an archive.
const int Import::archive_magic_len;
@ -59,7 +107,8 @@ bool
Import::is_archive_magic(const char* bytes)
{
return (memcmp(bytes, armag, Import::archive_magic_len) == 0
|| memcmp(bytes, armagt, Import::archive_magic_len) == 0);
|| memcmp(bytes, armagt, Import::archive_magic_len) == 0
|| memcmp(bytes, armagb, Import::archive_magic_len) == 0);
}
// An object used to read an archive file.
@ -68,8 +117,9 @@ class Archive_file
{
public:
Archive_file(const std::string& filename, int fd, Location location)
: filename_(filename), fd_(fd), filesize_(-1), extended_names_(),
is_thin_archive_(false), location_(location), nested_archives_()
: filename_(filename), fd_(fd), filesize_(-1), first_member_offset_(0),
extended_names_(), is_thin_archive_(false), is_big_archive_(false),
location_(location), nested_archives_()
{ }
// Initialize.
@ -86,11 +136,21 @@ class Archive_file
filesize() const
{ return this->filesize_; }
// Return the offset of the first member.
off_t
first_member_offset() const
{ return this->first_member_offset_; }
// Return whether this is a thin archive.
bool
is_thin_archive() const
{ return this->is_thin_archive_; }
// Return whether this is a big archive.
bool
is_big_archive() const
{ return this->is_big_archive_; }
// Return the location of the import statement.
Location
location() const
@ -100,10 +160,15 @@ class Archive_file
bool
read(off_t offset, off_t size, char*);
// Read the archive header at OFF, setting *PNAME, *SIZE, and
// *NESTED_OFF.
// Parse a decimal in readable text.
bool
read_header(off_t off, std::string* pname, off_t* size, off_t* nested_off);
parse_decimal(const char* str, off_t size, long* res) const;
// Read the archive header at OFF, setting *PNAME, *SIZE,
// *NESTED_OFF and *NEXT_OFF.
bool
read_header(off_t off, std::string* pname, off_t* size, off_t* nested_off,
off_t* next_off);
// Interpret the header of HDR, the header of the archive member at
// file offset OFF. Return whether it succeeded. Set *SIZE to the
@ -120,6 +185,25 @@ class Archive_file
std::string* memname);
private:
// Initialize a big archive (AIX)
bool
initialize_big_archive();
// Initialize a normal archive
bool
initialize_archive();
// Read the big archive header at OFF, setting *PNAME, *SIZE and *NEXT_OFF.
bool
read_big_archive_header(off_t off, std::string* pname,
off_t* size, off_t* next_off);
// Read the normal archive header at OFF, setting *PNAME, *SIZE,
// *NESTED_OFF and *NEXT_OFF.
bool
read_archive_header(off_t off, std::string* pname, off_t* size,
off_t* nested_off, off_t* next_off);
// For keeping track of open nested archives in a thin archive file.
typedef std::map<std::string, Archive_file*> Nested_archive_table;
@ -129,10 +213,14 @@ class Archive_file
int fd_;
// The file size;
off_t filesize_;
// The first member offset;
off_t first_member_offset_;
// The extended name table.
std::string extended_names_;
// Whether this is a thin archive.
bool is_thin_archive_;
// Whether this is a big archive.
bool is_big_archive_;
// The location of the import statements.
Location location_;
// Table of nested archives.
@ -157,9 +245,60 @@ Archive_file::initialize()
go_error_at(this->location_, "%s: %m", this->filename_.c_str());
return false;
}
this->is_thin_archive_ = memcmp(buf, armagt, sizeof(armagt)) == 0;
if (memcmp(buf, armagt, sizeof(armagt)) == 0)
this->is_thin_archive_ = true;
else if (memcmp(buf, armagb, sizeof(armagb)) == 0)
this->is_big_archive_ = true;
if (this->filesize_ == sizeof(armag))
if (this->is_big_archive_)
return this->initialize_big_archive();
else
return this->initialize_archive();
}
// Initialize a big archive (AIX).
bool
Archive_file::initialize_big_archive()
{
Archive_fl_header flhdr;
// Read the fixed length header.
if (::lseek(this->fd_, 0, SEEK_SET) < 0
|| ::read(this->fd_, &flhdr, sizeof(flhdr)) != sizeof(flhdr))
{
go_error_at(this->location_, "%s: could not read archive header",
this->filename_.c_str());
return false;
}
// Parse offset of the first member.
long off;
if (!this->parse_decimal(flhdr.fl_fstmoff, sizeof(flhdr.fl_fstmoff), &off))
{
char* buf = new char[sizeof(flhdr.fl_fstmoff) + 1];
memcpy(buf, flhdr.fl_fstmoff, sizeof(flhdr.fl_fstmoff));
go_error_at(this->location_,
("%s: malformed first member offset in archive header"
" (expected decimal, got %s)"),
this->filename_.c_str(), buf);
delete[] buf;
return false;
}
if (off == 0) // Empty archive.
this->first_member_offset_ = this->filesize_;
else
this->first_member_offset_ = off;
return true;
}
// Initialize a normal archive.
bool
Archive_file::initialize_archive()
{
this->first_member_offset_ = sizeof(armag);
if (this->first_member_offset_ == this->filesize_)
{
// Empty archive.
return true;
@ -168,15 +307,14 @@ Archive_file::initialize()
// Look for the extended name table.
std::string filename;
off_t size;
if (!this->read_header(sizeof(armagt), &filename, &size, NULL))
off_t next_off;
if (!this->read_header(this->first_member_offset_, &filename,
&size, NULL, &next_off))
return false;
if (filename.empty())
{
// We found the symbol table.
off_t off = sizeof(armagt) + sizeof(Archive_header) + size;
if ((off & 1) != 0)
++off;
if (!this->read_header(off, &filename, &size, NULL))
if (!this->read_header(next_off, &filename, &size, NULL, NULL))
filename.clear();
}
if (filename == "/")
@ -210,19 +348,142 @@ Archive_file::read(off_t offset, off_t size, char* buf)
return true;
}
// Parse a decimal in readable text.
bool
Archive_file::parse_decimal(const char* str, off_t size, long* res) const
{
char* buf = new char[size + 1];
memcpy(buf, str, size);
char* ps = buf + size;
while (ps > buf && ps[-1] == ' ')
--ps;
*ps = '\0';
errno = 0;
char* end;
*res = strtol(buf, &end, 10);
if (*end != '\0'
|| *res < 0
|| (*res == LONG_MAX && errno == ERANGE))
{
delete[] buf;
return false;
}
delete[] buf;
return true;
}
// Read the header at OFF. Set *PNAME to the name, *SIZE to the size,
// and *NESTED_OFF to the nested offset.
// *NESTED_OFF to the nested offset, and *NEXT_OFF to the next member offset.
bool
Archive_file::read_header(off_t off, std::string* pname, off_t* size,
off_t* nested_off)
off_t* nested_off, off_t* next_off)
{
Archive_header hdr;
if (::lseek(this->fd_, off, SEEK_SET) < 0)
{
go_error_at(this->location_, "%s: %m", this->filename_.c_str());
return false;
}
if (this->is_big_archive_)
return this->read_big_archive_header(off, pname, size, next_off);
else
return this->read_archive_header(off, pname, size, nested_off, next_off);
}
// Read the big archive header at OFF, setting *PNAME, *SIZE and *NEXT_OFF.
bool
Archive_file::read_big_archive_header(off_t off, std::string* pname,
off_t* size, off_t* next_off)
{
Archive_big_header hdr;
ssize_t got;
got = ::read(this->fd_, &hdr, sizeof hdr);
if (got != sizeof hdr)
{
if (got < 0)
go_error_at(this->location_, "%s: %m", this->filename_.c_str());
else if (got > 0)
go_error_at(this->location_, "%s: short entry header at %ld",
this->filename_.c_str(), static_cast<long>(off));
else
go_error_at(this->location_, "%s: unexpected EOF at %ld",
this->filename_.c_str(), static_cast<long>(off));
}
long local_size;
if (!this->parse_decimal(hdr.ar_size, sizeof(hdr.ar_size), &local_size))
{
char* buf = new char[sizeof(hdr.ar_size) + 1];
memcpy(buf, hdr.ar_size, sizeof(hdr.ar_size));
go_error_at(this->location_,
("%s: malformed ar_size in entry header at %ld"
" (expected decimal, got %s)"),
this->filename_.c_str(), static_cast<long>(off), buf);
delete[] buf;
return false;
}
*size = local_size;
long namlen;
if (!this->parse_decimal(hdr.ar_namlen, sizeof(hdr.ar_namlen), &namlen))
{
char* buf = new char[sizeof(hdr.ar_namlen) + 1];
memcpy(buf, hdr.ar_namlen, sizeof(hdr.ar_namlen));
go_error_at(this->location_,
("%s: malformed ar_namlen in entry header at %ld"
" (expected decimal, got %s)"),
this->filename_.c_str(), static_cast<long>(off), buf);
delete[] buf;
return false;
}
// Read member name following member header.
char* rdbuf = new char[namlen];
got = ::read(this->fd_, rdbuf, namlen);
if (got != namlen)
{
go_error_at(this->location_,
"%s: malformed member name in entry header at %ld",
this->filename_.c_str(), static_cast<long>(off));
delete[] rdbuf;
return false;
}
pname->assign(rdbuf, namlen);
delete[] rdbuf;
long local_next_off;
if (!this->parse_decimal(hdr.ar_nxtmem, sizeof(hdr.ar_nxtmem), &local_next_off))
{
char* buf = new char[sizeof(hdr.ar_nxtmem) + 1];
memcpy(buf, hdr.ar_nxtmem, sizeof(hdr.ar_nxtmem));
go_error_at(this->location_,
("%s: malformed ar_nxtmem in entry header at %ld"
" (expected decimal, got %s)"),
this->filename_.c_str(), static_cast<long>(off), buf);
delete[] buf;
return false;
}
if (next_off != NULL)
{
if (local_next_off == 0) // Last member.
*next_off = this->filesize_;
else
*next_off = local_next_off;
}
return true;
}
// Read the normal archive header at OFF, setting *PNAME, *SIZE,
// *NESTED_OFF and *NEXT_OFF.
bool
Archive_file::read_archive_header(off_t off, std::string* pname, off_t* size,
off_t* nested_off, off_t* next_off)
{
Archive_header hdr;
ssize_t got = ::read(this->fd_, &hdr, sizeof hdr);
if (got != sizeof hdr)
{
@ -240,6 +501,17 @@ Archive_file::read_header(off_t off, std::string* pname, off_t* size,
return false;
if (nested_off != NULL)
*nested_off = local_nested_off;
off_t local_next_off;
local_next_off = off + sizeof(Archive_header);
if (!this->is_thin_archive_ || pname->empty() || *pname == "/")
local_next_off += *size;
if ((local_next_off & 1) != 0)
++local_next_off;
if (local_next_off > this->filesize_) // Last member.
local_next_off = this->filesize_;
if (next_off != NULL)
*next_off = local_next_off;
return true;
}
@ -258,25 +530,14 @@ Archive_file::interpret_header(const Archive_header* hdr, off_t off,
return false;
}
const int size_string_size = sizeof hdr->ar_size;
char size_string[size_string_size + 1];
memcpy(size_string, hdr->ar_size, size_string_size);
char* ps = size_string + size_string_size;
while (ps > size_string && ps[-1] == ' ')
--ps;
*ps = '\0';
errno = 0;
char* end;
*size = strtol(size_string, &end, 10);
if (*end != '\0'
|| *size < 0
|| (*size == LONG_MAX && errno == ERANGE))
long local_size;
if (!this->parse_decimal(hdr->ar_size, sizeof hdr->ar_size, &local_size))
{
go_error_at(this->location_, "%s: malformed archive header size at %lu",
this->filename_.c_str(), static_cast<unsigned long>(off));
return false;
}
*size = local_size;
*nested_off = 0;
if (hdr->ar_name[0] != '/')
@ -313,6 +574,7 @@ Archive_file::interpret_header(const Archive_header* hdr, off_t off,
}
else
{
char* end;
errno = 0;
long x = strtol(hdr->ar_name + 1, &end, 10);
long y = 0;
@ -352,7 +614,17 @@ Archive_file::get_file_and_offset(off_t off, const std::string& hdrname,
off_t nested_off, int* memfd, off_t* memoff,
std::string* memname)
{
if (!this->is_thin_archive_)
if (this->is_big_archive_)
{
*memfd = this->fd_;
*memoff = (off + sizeof(Archive_big_header) + hdrname.length()
+ sizeof(arfmag));
if ((*memoff & 1) != 0)
++*memoff;
*memname = this->filename_ + '(' + hdrname + ')';
return true;
}
else if (!this->is_thin_archive_)
{
*memfd = this->fd_;
*memoff = off + sizeof(Archive_header);
@ -399,7 +671,7 @@ Archive_file::get_file_and_offset(off_t off, const std::string& hdrname,
std::string nname;
off_t nsize;
off_t nnested_off;
if (!nfile->read_header(nested_off, &nname, &nsize, &nnested_off))
if (!nfile->read_header(nested_off, &nname, &nsize, &nnested_off, NULL))
return false;
return nfile->get_file_and_offset(nested_off, nname, nnested_off,
memfd, memoff, memname);
@ -453,11 +725,7 @@ class Archive_iterator
{
if (this->off_ == this->afile_->filesize())
return *this;
this->off_ += sizeof(Archive_header);
if (!this->afile_->is_thin_archive())
this->off_ += this->header_.size;
if ((this->off_ & 1) != 0)
++this->off_;
this->off_ = this->next_off_;
this->read_next_header();
return *this;
}
@ -486,6 +754,8 @@ class Archive_iterator
Archive_file* afile_;
// The current offset in the file.
off_t off_;
// The offset of the next member.
off_t next_off_;
// The current archive header.
Header header_;
};
@ -498,31 +768,16 @@ Archive_iterator::read_next_header()
off_t filesize = this->afile_->filesize();
while (true)
{
if (filesize - this->off_ < static_cast<off_t>(sizeof(Archive_header)))
{
if (filesize != this->off_)
{
go_error_at(this->afile_->location(),
"%s: short archive header at %lu",
this->afile_->filename().c_str(),
static_cast<unsigned long>(this->off_));
this->off_ = filesize;
}
this->header_.off = filesize;
return;
}
char buf[sizeof(Archive_header)];
if (!this->afile_->read(this->off_, sizeof(Archive_header), buf))
if (this->off_ == filesize)
{
this->header_.off = filesize;
return;
}
const Archive_header* hdr = reinterpret_cast<const Archive_header*>(buf);
if (!this->afile_->interpret_header(hdr, this->off_, &this->header_.name,
&this->header_.size,
&this->header_.nested_off))
if (!this->afile_->read_header(this->off_, &this->header_.name,
&this->header_.size,
&this->header_.nested_off,
&this->next_off_))
{
this->header_.off = filesize;
return;
@ -533,9 +788,7 @@ Archive_iterator::read_next_header()
if (!this->header_.name.empty() && this->header_.name != "/")
return;
this->off_ += sizeof(Archive_header) + this->header_.size;
if ((this->off_ & 1) != 0)
++this->off_;
this->off_ = this->next_off_;
}
}
@ -544,7 +797,7 @@ Archive_iterator::read_next_header()
Archive_iterator
archive_begin(Archive_file* afile)
{
return Archive_iterator(afile, sizeof(armag));
return Archive_iterator(afile, afile->first_member_offset());
}
// Final iterator.

View File

@ -220,11 +220,11 @@ DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice", P3(TYPE, SLICE, INT), R1(SLICE))
// Register roots (global variables) for the garbage collector.
DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "__go_register_gc_roots", P1(POINTER), R0())
DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "runtime.registerGCRoots", P1(POINTER), R0())
// Allocate memory.
DEF_GO_RUNTIME(NEW, "__go_new", P2(TYPE, UINTPTR), R1(POINTER))
DEF_GO_RUNTIME(NEW, "runtime.newobject", P1(TYPE), R1(POINTER))
// Start a new goroutine.
DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())
@ -315,6 +315,15 @@ DEF_GO_RUNTIME(IFACEEFACEEQ, "runtime.ifaceefaceeq", P2(IFACE, EFACE),
R1(BOOL))
// Set *dst = src where dst is a pointer to a pointer and src is a pointer.
DEF_GO_RUNTIME(WRITEBARRIERPTR, "runtime.writebarrierptr",
P2(POINTER, POINTER), R0())
// Set *dst = *src for an arbitrary type.
DEF_GO_RUNTIME(TYPEDMEMMOVE, "runtime.typedmemmove",
P3(TYPE, POINTER, POINTER), R0())
// Lock the printer (for print/println).
DEF_GO_RUNTIME(PRINTLOCK, "runtime.printlock", P0(), R0())

View File

@ -510,6 +510,10 @@ Temporary_statement::do_get_backend(Translate_context* context)
binit = init->get_backend(context);
}
if (binit != NULL)
binit = context->backend()->convert_expression(btype, binit,
this->location());
Bstatement* statement;
this->bvariable_ =
context->backend()->temporary_variable(bfunction, context->bblock(),

File diff suppressed because it is too large Load Diff

View File

@ -89,28 +89,6 @@ static const int RUNTIME_TYPE_KIND_DIRECT_IFACE = (1 << 5);
static const int RUNTIME_TYPE_KIND_GC_PROG = (1 << 6);
static const int RUNTIME_TYPE_KIND_NO_POINTERS = (1 << 7);
// GC instruction opcodes. These must match the values in libgo/runtime/mgc0.h.
enum GC_Opcode
{
GC_END = 0, // End of object, loop or subroutine.
GC_PTR, // A typed pointer.
GC_APTR, // Pointer to an arbitrary object.
GC_ARRAY_START, // Start an array with a fixed length.
GC_ARRAY_NEXT, // The next element of an array.
GC_CALL, // Call a subroutine.
GC_CHAN_PTR, // Go channel.
GC_STRING, // Go string.
GC_EFACE, // interface{}.
GC_IFACE, // interface{...}.
GC_SLICE, // Go slice.
GC_REGION, // A region/part of the current object.
GC_NUM_INSTR // Number of instruction opcodes
};
// The GC Stack Capacity must match the value in libgo/runtime/mgc0.h.
static const int GC_STACK_CAPACITY = 8;
// To build the complete list of methods for a named type we need to
// gather all methods from anonymous fields. Those methods may
// require an arbitrary set of indirections and field offsets. There
@ -944,6 +922,15 @@ class Type
Bexpression*
gc_symbol_pointer(Gogo* gogo);
// Return whether this type needs a garbage collection program.
// Sets *PTRSIZE and *PTRDATA.
bool
needs_gcprog(Gogo*, int64_t* ptrsize, int64_t* ptrdata);
// Return a ptrmask variable for this type.
Bvariable*
gc_ptrmask_var(Gogo*, int64_t ptrsize, int64_t ptrdata);
// Return the type reflection string for this type.
std::string
reflection(Gogo*) const;
@ -971,6 +958,20 @@ class Type
bool
backend_type_field_align(Gogo*, int64_t* palign);
// Determine the ptrdata size for the backend version of this type:
// the length of the prefix of the type that can contain a pointer
// value. If it can be determined, set *PPTRDATA to the value in
// bytes and return true. Otherwise, return false.
bool
backend_type_ptrdata(Gogo*, int64_t* pptrdata);
// Determine the ptrdata size that we are going to set in the type
// descriptor. This is normally the same as backend_type_ptrdata,
// but differs if we use a gcprog for an array. The arguments and
// results are as for backend_type_ptrdata.
bool
descriptor_ptrdata(Gogo*, int64_t* pptrdata);
// Whether the backend size is known.
bool
is_backend_type_size_known(Gogo*);
@ -1043,9 +1044,6 @@ class Type
virtual Expression*
do_type_descriptor(Gogo*, Named_type* name) = 0;
virtual void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int) = 0;
virtual void
do_reflection(Gogo*, std::string*) const = 0;
@ -1101,22 +1099,6 @@ class Type
type_descriptor_constructor(Gogo*, int runtime_type_kind, Named_type*,
const Methods*, bool only_value_methods);
// Generate the GC symbol for this TYPE. VALS is the data so far in this
// symbol; extra values will be appended in do_gc_symbol. OFFSET is the
// offset into the symbol where the GC data is located. STACK_SIZE is the
// size of the GC stack when dealing with array types.
static void
gc_symbol(Gogo*, Type* type, Expression_list** vals, Expression** offset,
int stack_size);
// Build a composite literal for the GC symbol of this type.
Expression*
gc_symbol_constructor(Gogo*);
// Advance the OFFSET of the GC symbol by the size of this type.
void
advance_gc_offset(Expression** offset);
// For the benefit of child class reflection string generation.
void
append_reflection(const Type* type, Gogo* gogo, std::string* ret) const
@ -1194,6 +1176,11 @@ class Type
static GC_symbol_vars gc_symbol_vars;
// Map ptrmask symbol names to the ptrmask variable.
typedef Unordered_map(std::string, Bvariable*) GC_gcbits_vars;
static GC_gcbits_vars gc_gcbits_vars;
// Build the GC symbol for this type.
void
make_gc_symbol_var(Gogo*);
@ -1210,6 +1197,11 @@ class Type
bool
type_descriptor_defined_elsewhere(Named_type* name, const Package** package);
// Make a composite literal for the garbage collection program for
// this type.
Expression*
gcprog_constructor(Gogo*, int64_t ptrsize, int64_t ptrdata);
// Build the hash and equality type functions for a type which needs
// specific functions.
void
@ -1605,10 +1597,6 @@ protected:
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression** offset, int)
{ this->advance_gc_offset(offset); }
void
do_mangled_name(Gogo*, std::string*) const;
@ -1695,10 +1683,6 @@ class Float_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression** offset, int)
{ this->advance_gc_offset(offset); }
void
do_mangled_name(Gogo*, std::string*) const;
@ -1777,10 +1761,6 @@ class Complex_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression** offset, int)
{ this->advance_gc_offset(offset); }
void
do_mangled_name(Gogo*, std::string*) const;
@ -1835,9 +1815,6 @@ class String_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string* ret) const;
@ -1993,9 +1970,6 @@ class Function_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -2119,9 +2093,6 @@ class Pointer_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -2441,9 +2412,6 @@ class Struct_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -2519,6 +2487,12 @@ class Array_type : public Type
length() const
{ return this->length_; }
// Store the length as an int64_t into *PLEN. Return false if the
// length can not be determined. This will assert if called for a
// slice.
bool
int_length(int64_t* plen);
// Whether this type is identical with T.
bool
is_identical(const Array_type* t, bool errors_are_identical) const;
@ -2583,10 +2557,7 @@ class Array_type : public Type
do_verify();
bool
do_has_pointer() const
{
return this->length_ == NULL || this->element_type_->has_pointer();
}
do_has_pointer() const;
bool
do_compare_is_identity(Gogo*);
@ -2613,9 +2584,6 @@ class Array_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -2632,12 +2600,6 @@ class Array_type : public Type
Expression*
slice_type_descriptor(Gogo*, Named_type*);
void
slice_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
array_gc_symbol(Gogo*, Expression_list**, Expression**, int);
// The type of elements of the array.
Type* element_type_;
// The number of elements. This may be NULL.
@ -2736,9 +2698,6 @@ class Map_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -2851,9 +2810,6 @@ class Channel_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -2998,9 +2954,6 @@ class Interface_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo*, Expression_list**, Expression**, int);
void
do_mangled_name(Gogo*, std::string*) const;
@ -3306,10 +3259,6 @@ class Named_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo* gogo, Expression_list** vals, Expression** offset,
int stack);
void
do_mangled_name(Gogo*, std::string* ret) const;
@ -3466,11 +3415,6 @@ class Forward_declaration_type : public Type
void
do_reflection(Gogo*, std::string*) const;
void
do_gc_symbol(Gogo* gogo, Expression_list** vals, Expression** offset,
int stack_size)
{ Type::gc_symbol(gogo, this->real_type(), vals, offset, stack_size); }
void
do_mangled_name(Gogo*, std::string* ret) const;

465
gcc/go/gofrontend/wb.cc Normal file
View File

@ -0,0 +1,465 @@
// wb.cc -- Add write barriers as needed.
// Copyright 2017 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 "go-system.h"
#include "go-c.h"
#include "go-diagnostics.h"
#include "operator.h"
#include "lex.h"
#include "types.h"
#include "expressions.h"
#include "statements.h"
#include "runtime.h"
#include "gogo.h"
// Mark variables whose addresses are taken. This has to be done
// before the write barrier pass and after the escape analysis pass.
// It would be nice to do this elsewhere but there isn't an obvious
// place.
class Mark_address_taken : public Traverse
{
public:
Mark_address_taken(Gogo* gogo)
: Traverse(traverse_expressions),
gogo_(gogo)
{ }
int
expression(Expression**);
private:
Gogo* gogo_;
};
// Mark variable addresses taken.
int
Mark_address_taken::expression(Expression** pexpr)
{
Expression* expr = *pexpr;
Unary_expression* ue = expr->unary_expression();
if (ue != NULL)
ue->check_operand_address_taken(this->gogo_);
return TRAVERSE_CONTINUE;
}
// Add write barriers to the IR. This are required by the concurrent
// garbage collector. A write barrier is needed for any write of a
// pointer into memory controlled by the garbage collector. Write
// barriers are not required for writes to local variables that live
// on the stack. Write barriers are only required when the runtime
// enables them, which can be checked using a run time check on
// runtime.writeBarrier.enabled.
//
// Essentially, for each assignment A = B, where A is or contains a
// pointer, and where A is not, or at any rate may not be, a stack
// variable, we rewrite it into
// if runtime.writeBarrier.enabled {
// typedmemmove(typeof(A), &A, &B)
// } else {
// A = B
// }
//
// The test of runtime.writeBarrier.Enabled is implemented by treating
// the variable as a *uint32, and testing *runtime.writeBarrier != 0.
// This is compatible with the definition in the runtime package.
//
// For types that are pointer shared (pointers, maps, chans, funcs),
// we replaced the call to typedmemmove with writebarrierptr(&A, B).
// As far as the GC is concerned, all pointers are the same, so it
// doesn't need the type descriptor.
//
// There are possible optimizations that are not implemented.
//
// runtime.writeBarrier can only change when the goroutine is
// preempted, which in practice means when a call is made into the
// runtime package, so we could optimize by only testing it once
// between function calls.
//
// A slice could be handled with a call to writebarrierptr plus two
// integer moves.
// Traverse the IR adding write barriers.
class Write_barriers : public Traverse
{
public:
Write_barriers(Gogo* gogo)
: Traverse(traverse_functions | traverse_variables | traverse_statements),
gogo_(gogo), function_(NULL)
{ }
int
function(Named_object*);
int
variable(Named_object*);
int
statement(Block*, size_t* pindex, Statement*);
private:
// General IR.
Gogo* gogo_;
// Current function.
Function* function_;
};
// Traverse a function. Just record it for later.
int
Write_barriers::function(Named_object* no)
{
go_assert(this->function_ == NULL);
this->function_ = no->func_value();
int t = this->function_->traverse(this);
this->function_ = NULL;
if (t == TRAVERSE_EXIT)
return t;
return TRAVERSE_SKIP_COMPONENTS;
}
// Insert write barriers for a global variable: ensure that variable
// initialization is handled correctly. This is rarely needed, since
// we currently don't enable background GC until after all global
// variables are initialized. But we do need this if an init function
// calls runtime.GC.
int
Write_barriers::variable(Named_object* no)
{
// We handle local variables in the variable declaration statement.
// We only have to handle global variables here.
if (!no->is_variable())
return TRAVERSE_CONTINUE;
Variable* var = no->var_value();
if (!var->is_global())
return TRAVERSE_CONTINUE;
// Nothing to do if there is no initializer.
Expression* init = var->init();
if (init == NULL)
return TRAVERSE_CONTINUE;
// Nothing to do for variables that do not contain any pointers.
if (!var->type()->has_pointer())
return TRAVERSE_CONTINUE;
// Nothing to do if the initializer is static.
init = Expression::make_cast(var->type(), init, var->location());
if (!var->has_pre_init() && init->is_static_initializer())
return TRAVERSE_CONTINUE;
// Otherwise change the initializer into a pre_init assignment
// statement with a write barrier.
// We can't check for a dependency of the variable on itself after
// we make this change, because the preinit statement will always
// depend on the variable (since it assigns to it). So check for a
// self-dependency now.
this->gogo_->check_self_dep(no);
// Replace the initializer.
Location loc = init->location();
Expression* ref = Expression::make_var_reference(no, loc);
ref->var_expression()->set_in_lvalue_pos();
Statement_inserter inserter(this->gogo_, var);
Statement* s = this->gogo_->assign_with_write_barrier(NULL, NULL, &inserter,
ref, init, loc);
var->add_preinit_statement(this->gogo_, s);
var->clear_init();
return TRAVERSE_CONTINUE;
}
// Insert write barriers for statements.
int
Write_barriers::statement(Block* block, size_t* pindex, Statement* s)
{
switch (s->classification())
{
default:
break;
case Statement::STATEMENT_VARIABLE_DECLARATION:
{
Variable_declaration_statement* vds =
s->variable_declaration_statement();
Named_object* no = vds->var();
Variable* var = no->var_value();
// We may need to emit a write barrier for the initialization
// of the variable.
// Nothing to do for a variable with no initializer.
Expression* init = var->init();
if (init == NULL)
break;
// Nothing to do if the variable is not in the heap. Only
// local variables get declaration statements, and local
// variables on the stack do not require write barriers.
if (!var->is_in_heap())
break;
// Nothing to do if the variable does not contain any pointers.
if (!var->type()->has_pointer())
break;
// Otherwise initialize the variable with a write barrier.
Function* function = this->function_;
Location loc = init->location();
Statement_inserter inserter(block, pindex);
// Insert the variable declaration statement with no
// initializer, so that the variable exists.
var->clear_init();
inserter.insert(s);
// Create a statement that initializes the variable with a
// write barrier.
Expression* ref = Expression::make_var_reference(no, loc);
Statement* assign = this->gogo_->assign_with_write_barrier(function,
block,
&inserter,
ref, init,
loc);
// Replace the old variable declaration statement with the new
// initialization.
block->replace_statement(*pindex, assign);
}
break;
case Statement::STATEMENT_ASSIGNMENT:
{
Assignment_statement* as = s->assignment_statement();
Expression* lhs = as->lhs();
Expression* rhs = as->rhs();
// We may need to emit a write barrier for the assignment.
if (!this->gogo_->assign_needs_write_barrier(lhs))
break;
// Change the assignment to use a write barrier.
Function* function = this->function_;
Location loc = as->location();
Statement_inserter inserter = Statement_inserter(block, pindex);
Statement* assign = this->gogo_->assign_with_write_barrier(function,
block,
&inserter,
lhs, rhs,
loc);
block->replace_statement(*pindex, assign);
}
break;
}
return TRAVERSE_CONTINUE;
}
// The write barrier pass.
void
Gogo::add_write_barriers()
{
Mark_address_taken mat(this);
this->traverse(&mat);
Write_barriers wb(this);
this->traverse(&wb);
}
// Return the runtime.writeBarrier variable.
Named_object*
Gogo::write_barrier_variable()
{
static Named_object* write_barrier_var;
if (write_barrier_var == NULL)
{
Location bloc = Linemap::predeclared_location();
// We pretend that writeBarrier is a uint32, so that we do a
// 32-bit load. That is what the gc toolchain does.
Type* uint32_type = Type::lookup_integer_type("uint32");
Variable* var = new Variable(uint32_type, NULL, true, false, false,
bloc);
bool add_to_globals;
Package* package = this->add_imported_package("runtime", "_", false,
"runtime", "runtime",
bloc, &add_to_globals);
write_barrier_var = Named_object::make_variable("writeBarrier",
package, var);
}
return write_barrier_var;
}
// Return whether an assignment that sets LHS needs a write barrier.
bool
Gogo::assign_needs_write_barrier(Expression* lhs)
{
// Nothing to do if the variable does not contain any pointers.
if (!lhs->type()->has_pointer())
return false;
// Nothing to do for an assignment to a temporary.
if (lhs->temporary_reference_expression() != NULL)
return false;
// Nothing to do for an assignment to a sink.
if (lhs->is_sink_expression())
return false;
// Nothing to do for an assignment to a local variable that is not
// on the heap.
Var_expression* ve = lhs->var_expression();
if (ve != NULL)
{
Named_object* no = ve->named_object();
if (no->is_variable())
{
Variable* var = no->var_value();
if (!var->is_global() && !var->is_in_heap())
return false;
}
else if (no->is_result_variable())
{
Result_variable* rvar = no->result_var_value();
if (!rvar->is_in_heap())
return false;
}
}
// Write barrier needed in other cases.
return true;
}
// Return a statement that sets LHS to RHS using a write barrier.
// ENCLOSING is the enclosing block.
Statement*
Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
Statement_inserter* inserter, Expression* lhs,
Expression* rhs, Location loc)
{
if (function != NULL
&& ((function->pragmas() & GOPRAGMA_NOWRITEBARRIER) != 0
|| (function->pragmas() & GOPRAGMA_NOWRITEBARRIERREC) != 0))
go_error_at(loc, "write barrier prohibited");
Type* type = lhs->type();
go_assert(type->has_pointer());
Expression* addr;
if (lhs->unary_expression() != NULL
&& lhs->unary_expression()->op() == OPERATOR_MULT)
addr = lhs->unary_expression()->operand();
else
{
addr = Expression::make_unary(OPERATOR_AND, lhs, loc);
addr->unary_expression()->set_does_not_escape();
}
Temporary_statement* lhs_temp = Statement::make_temporary(NULL, addr, loc);
inserter->insert(lhs_temp);
lhs = Expression::make_temporary_reference(lhs_temp, loc);
if (!Type::are_identical(type, rhs->type(), false, NULL)
&& rhs->type()->interface_type() != NULL
&& !rhs->is_variable())
{
// May need a temporary for interface conversion.
Temporary_statement* temp = Statement::make_temporary(NULL, rhs, loc);
inserter->insert(temp);
rhs = Expression::make_temporary_reference(temp, loc);
}
rhs = Expression::convert_for_assignment(this, type, rhs, loc);
Temporary_statement* rhs_temp = NULL;
if (!rhs->is_variable() && !rhs->is_constant())
{
rhs_temp = Statement::make_temporary(NULL, rhs, loc);
inserter->insert(rhs_temp);
rhs = Expression::make_temporary_reference(rhs_temp, loc);
}
Expression* indir = Expression::make_unary(OPERATOR_MULT, lhs, loc);
Statement* assign = Statement::make_assignment(indir, rhs, loc);
lhs = Expression::make_temporary_reference(lhs_temp, loc);
if (rhs_temp != NULL)
rhs = Expression::make_temporary_reference(rhs_temp, loc);
Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
lhs = Expression::make_unsafe_cast(unsafe_ptr_type, lhs, loc);
Expression* call;
switch (type->base()->classification())
{
default:
go_unreachable();
case Type::TYPE_ERROR:
return assign;
case Type::TYPE_POINTER:
case Type::TYPE_FUNCTION:
case Type::TYPE_MAP:
case Type::TYPE_CHANNEL:
// These types are all represented by a single pointer.
call = Runtime::make_call(Runtime::WRITEBARRIERPTR, loc, 2, lhs, rhs);
break;
case Type::TYPE_STRING:
case Type::TYPE_STRUCT:
case Type::TYPE_ARRAY:
case Type::TYPE_INTERFACE:
{
rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
rhs->unary_expression()->set_does_not_escape();
call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
Expression::make_type_descriptor(type, loc),
lhs, rhs);
}
break;
}
return this->check_write_barrier(enclosing, assign,
Statement::make_statement(call, false));
}
// Return a statement that tests whether write barriers are enabled
// and executes either the efficient code or the write barrier
// function call, depending.
Statement*
Gogo::check_write_barrier(Block* enclosing, Statement* without,
Statement* with)
{
Location loc = without->location();
Named_object* wb = this->write_barrier_variable();
Expression* ref = Expression::make_var_reference(wb, loc);
Expression* zero = Expression::make_integer_ul(0, ref->type(), loc);
Expression* cond = Expression::make_binary(OPERATOR_EQEQ, ref, zero, loc);
Block* then_block = new Block(enclosing, loc);
then_block->add_statement(without);
Block* else_block = new Block(enclosing, loc);
else_block->add_statement(with);
return Statement::make_if_statement(cond, then_block, else_block, loc);
}

View File

@ -1,6 +1,6 @@
// runoutput
// Copyright 2013 The Go Authors. All rights reserved.
// 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.
@ -19,10 +19,10 @@ var bout *bufio.Writer
func main() {
bout = bufio.NewWriter(os.Stdout)
fmt.Fprintf(bout, "%s", programTop)
fmt.Fprintf(bout, "func main() {\n")
index := []string{
"0",
"1",
@ -38,7 +38,7 @@ func main() {
"v10",
"v20",
}
parse := func(s string) (n int, isconst bool) {
if s == "vminus1" {
return -1, false
@ -69,7 +69,7 @@ func main() {
iconst && kconst && iv > kv,
iconst && base == "array" && iv > Cap,
jconst && base == "array" && jv > Cap,
kconst && base == "array" && kv > Cap:
kconst && base == "array" && kv > Cap:
continue
}
@ -82,7 +82,7 @@ func main() {
xlen = jv - iv
xcap = kv - iv
}
fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
}
}
}
@ -147,9 +147,13 @@ func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
println(desc, "=", base, len, cap, "want panic")
return
}
if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) {
if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) {
notOK()
println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
if cap == 0 {
println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap)
} else {
println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
}
}
}

View File

@ -46,8 +46,17 @@ AM_CFLAGS = -fexceptions -fnon-call-exceptions -fplan9-extensions \
-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
-I $(MULTIBUILDTOP)../../gcc/include
AM_LDFLAGS =
if USING_SPLIT_STACK
AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
AM_LDFLAGS += -XCClinker $(SPLIT_STACK)
endif
if LIBGO_IS_AIX
# Using an import file for libgo avoid requiring to use the -brtl flag
# when builing a go program
AM_LDFLAGS += -Wl,-bbigtoc -Wl,-bI:$(srcdir)/libgo.imp
EXTRA_libgo_la_DEPENDENCIES = libgo.imp
endif
# Multilib support.
@ -383,12 +392,6 @@ toolexeclibgounicode_DATA = \
unicode/utf16.gox \
unicode/utf8.gox
if HAVE_SYS_MMAN_H
runtime_mem_file = runtime/mem.c
else
runtime_mem_file = runtime/mem_posix_memalign.c
endif
if LIBGO_IS_RTEMS
rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
else
@ -419,6 +422,9 @@ else
if LIBGO_IS_NETBSD
runtime_getncpu_file = runtime/getncpu-bsd.c
else
if LIBGO_IS_AIX
runtime_getncpu_file = runtime/getncpu-aix.c
else
runtime_getncpu_file = runtime/getncpu-none.c
endif
endif
@ -426,11 +432,11 @@ endif
endif
endif
endif
endif
runtime_files = \
runtime/aeshash.c \
runtime/go-assert.c \
runtime/go-breakpoint.c \
runtime/go-caller.c \
runtime/go-callers.c \
runtime/go-cdiv.c \
@ -445,7 +451,6 @@ runtime_files = \
runtime/go-memmove.c \
runtime/go-nanotime.c \
runtime/go-now.c \
runtime/go-new.c \
runtime/go-nosys.c \
runtime/go-reflect-call.c \
runtime/go-runtime-error.c \
@ -453,53 +458,29 @@ runtime_files = \
runtime/go-signal.c \
runtime/go-strslice.c \
runtime/go-typedesc-equal.c \
runtime/go-unsafe-new.c \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
runtime/go-unsetenv.c \
runtime/go-unwind.c \
runtime/go-varargs.c \
runtime/env_posix.c \
runtime/heapdump.c \
runtime/mcache.c \
runtime/mcentral.c \
$(runtime_mem_file) \
runtime/mfixalloc.c \
runtime/mgc0.c \
runtime/mheap.c \
runtime/msize.c \
runtime/panic.c \
runtime/parfor.c \
runtime/print.c \
runtime/proc.c \
runtime/runtime_c.c \
runtime/stack.c \
runtime/thread.c \
$(runtime_thread_files) \
runtime/yield.c \
$(rtems_task_variable_add_file) \
malloc.c \
$(runtime_getncpu_file)
goc2c.$(OBJEXT): runtime/goc2c.c
$(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) $<
goc2c: goc2c.$(OBJEXT)
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ $<
malloc.c: $(srcdir)/runtime/malloc.goc goc2c
./goc2c $< > $@.tmp
mv -f $@.tmp $@
%.c: $(srcdir)/runtime/%.goc goc2c
./goc2c $< > $@.tmp
mv -f $@.tmp $@
version.go: s-version; @true
s-version: Makefile
rm -f version.go.tmp
echo "package sys" > version.go.tmp
echo 'const DefaultGoroot = "$(prefix)"' >> version.go.tmp
echo 'const TheVersion = "'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'"' >> version.go.tmp
echo 'const Goexperiment = ``' >> version.go.tmp
echo 'const GOARCH = "'$(GOARCH)'"' >> version.go.tmp
echo 'const GOOS = "'$(GOOS)'"' >> version.go.tmp
echo 'const GccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp
@ -550,7 +531,7 @@ s-version: Makefile
runtime_sysinfo.go: s-runtime_sysinfo; @true
s-runtime_sysinfo: $(srcdir)/mkrsysinfo.sh gen-sysinfo.go
$(SHELL) $(srcdir)/mkrsysinfo.sh
GOOS=$(GOOS) $(SHELL) $(srcdir)/mkrsysinfo.sh
$(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime_sysinfo.go runtime_sysinfo.go
$(STAMP) $@
@ -560,14 +541,23 @@ s-sigtab: $(srcdir)/mksigtab.sh gen-sysinfo.go
$(SHELL) $(srcdir)/mvifdiff.sh tmp-sigtab.go sigtab.go
$(STAMP) $@
# _Complex_lock and _Reader_lock are Go translations of some AIX system
# types and should not be exported back to C
# sigset conflicts with system type sigset on AIX, so we need to rename it
runtime.inc: s-runtime-inc; @true
s-runtime-inc: runtime.lo Makefile
rm -f runtime.inc.tmp2
grep -v "#define _" runtime.inc.tmp | grep -v "#define [cm][01234] " > runtime.inc.tmp2
rm -f runtime.inc.tmp2 runtime.inc.tmp3
grep -v "#define _" runtime.inc.tmp | grep -v "#define [cm][01234] " | grep -v "#define empty " > runtime.inc.tmp2
for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num; do \
grep "#define $$pattern" runtime.inc.tmp >> runtime.inc.tmp2; \
done
$(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp2 runtime.inc
for TYPE in _Complex_lock _Reader_lock; do \
sed -e '/struct '$${TYPE}' {/,/^}/s/^.*$$//' runtime.inc.tmp2 > runtime.inc.tmp3; \
mv runtime.inc.tmp3 runtime.inc.tmp2; \
done
sed -e 's/sigset/sigset_go/' runtime.inc.tmp2 > runtime.inc.tmp3
$(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp3 runtime.inc
rm -f runtime.inc.tmp2 runtime.inc.tmp3
$(STAMP) $@
noinst_DATA = zstdpkglist.go
@ -579,7 +569,7 @@ s-zstdpkglist: Makefile
echo 'package main' > zstdpkglist.go.tmp
echo "" >> zstdpkglist.go.tmp
echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's/\.lo /\": true,\n/g' | grep -v _c | sed 's/\.lo/\": true,/' | sed 's/^/\t\"/' | sort -u >> zstdpkglist.go.tmp
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
echo '}' >> zstdpkglist.go.tmp
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
$(STAMP) $@
@ -632,7 +622,7 @@ s-errno:
sysinfo.go: s-sysinfo; @true
s-sysinfo: $(srcdir)/mksysinfo.sh gen-sysinfo.go errno.i
$(SHELL) $(srcdir)/mksysinfo.sh
GOOS=$(GOOS) $(SHELL) $(srcdir)/mksysinfo.sh
$(SHELL) $(srcdir)/mvifdiff.sh tmp-sysinfo.go sysinfo.go
$(STAMP) $@
@ -923,8 +913,13 @@ BUILDPACKAGE = \
$(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//'` $($(subst -,_,$(subst .,_,$(subst /,_,$@)))_GOCFLAGS) -o $@ $$files
# How to build a .gox file from a .lo file.
# Matching .o file can either be in the same directory as the .lo (non-PIC
# object) or in the .libs directory (PIC object).
BUILDGOX = \
f=`echo $< | sed -e 's/.lo$$/.o/'`; \
f="$(basename $<).o"; \
if test ! -f $$f; then \
f="$(basename $(<D)/.libs/$(<F)).o"; \
fi; \
$(OBJCOPY) -j .go_export $$f $@.tmp; \
$(SHELL) $(srcdir)/mvifdiff.sh $@.tmp `echo $@ | sed -e 's/s-gox/gox/'`
@ -941,6 +936,8 @@ CHECK = \
export RUNTESTFLAGS; \
MAKE="$(MAKE)"; \
export MAKE; \
NM="$(NM)"; \
export NM; \
libgccdir=`${GOC} -print-libgcc-file-name | sed -e 's|/[^/]*$$||'`; \
LD_LIBRARY_PATH="`${PWD_COMMAND}`/.libs:$${libgccdir}:${LD_LIBRARY_PATH}"; \
LD_LIBRARY_PATH=`echo $${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
@ -1296,6 +1293,7 @@ TEST_PACKAGES = \
runtime/internal/sys/check \
runtime/pprof/check \
runtime/pprof/internal/protopprof/check \
runtime/trace/check \
sync/atomic/check \
text/scanner/check \
text/tabwriter/check \
@ -1407,7 +1405,12 @@ check-multi:
bench:
-@$(MAKE) -k $(TEST_PACKAGES) GOBENCH=.
MOSTLYCLEAN_FILES = libgo.head libgo.sum.sep libgo.log.sep
MOSTLYCLEANFILES = \
s-runtime_sysinfo s-sigtab s-runtime-inc s-zstdpkglist \
s-libcalls s-libcalls-list s-syscall_arch s-gen-sysinfo s-sysinfo \
s-errno s-epoll \
libgo.head libgo.sum.sep libgo.log.sep libgo.var \
libcalls-list runtime.inc runtime.inc.tmp2 runtime.inc.tmp3
mostlyclean-local:
find . -name '*.lo' -print | xargs $(LIBTOOL) --mode=clean rm -f
@ -1415,8 +1418,13 @@ mostlyclean-local:
find . -name '*-testsum' -print | xargs rm -f
find . -name '*-testlog' -print | xargs rm -f
CLEANFILES = *.go *.gox goc2c *.c s-version libgo.sum libgo.log
CLEANFILES = *.go *.c s-version libgo.sum libgo.log runtime.inc
clean-local:
find . -name '*.la' -print | xargs $(LIBTOOL) --mode=clean rm -f
find . -name '*.a' -print | xargs rm -f
find . -name '*.gox' -print | xargs rm -f
find . -name '*.s-gox' -print | xargs rm -f
distclean-local:
find . -name '*.lo.dep' -print | xargs rm -f

View File

@ -62,8 +62,13 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@GOC_IS_LLGO_TRUE@am__append_1 = libgo-llgo.la libgobegin-llgo.a
@GOC_IS_LLGO_FALSE@am__append_2 = libgo.la libgobegin.a
@USING_SPLIT_STACK_TRUE@am__append_1 = -XCClinker $(SPLIT_STACK)
# Using an import file for libgo avoid requiring to use the -brtl flag
# when builing a go program
@LIBGO_IS_AIX_TRUE@am__append_2 = -Wl,-bbigtoc -Wl,-bI:$(srcdir)/libgo.imp
@GOC_IS_LLGO_TRUE@am__append_3 = libgo-llgo.la libgobegin-llgo.a
@GOC_IS_LLGO_FALSE@am__append_4 = libgo.la libgobegin.a
subdir = .
DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
@ -178,40 +183,36 @@ am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3) \
$(am__DEPENDENCIES_3) $(am__DEPENDENCIES_3)
libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
@HAVE_SYS_MMAN_H_FALSE@am__objects_1 = mem_posix_memalign.lo
@HAVE_SYS_MMAN_H_TRUE@am__objects_1 = mem.lo
@LIBGO_IS_LINUX_FALSE@am__objects_2 = thread-sema.lo
@LIBGO_IS_LINUX_TRUE@am__objects_2 = thread-linux.lo
@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-none.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_4 = getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_4 = getncpu-solaris.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_4 = getncpu-irix.lo
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_4 = \
@LIBGO_IS_LINUX_FALSE@am__objects_1 = thread-sema.lo
@LIBGO_IS_LINUX_TRUE@am__objects_1 = thread-linux.lo
@LIBGO_IS_RTEMS_TRUE@am__objects_2 = rtems-task-variable-add.lo
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-none.lo
@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-aix.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = getncpu-bsd.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_3 = getncpu-solaris.lo
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_3 = getncpu-irix.lo
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_3 = \
@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ getncpu-bsd.lo
@LIBGO_IS_LINUX_TRUE@am__objects_4 = getncpu-linux.lo
am__objects_5 = aeshash.lo go-assert.lo go-breakpoint.lo go-caller.lo \
go-callers.lo go-cdiv.lo go-cgo.lo go-construct-map.lo \
go-ffi.lo go-fieldtrack.lo go-matherr.lo go-memclr.lo \
go-memcmp.lo go-memequal.lo go-memmove.lo go-nanotime.lo \
go-now.lo go-new.lo go-nosys.lo go-reflect-call.lo \
go-runtime-error.lo go-setenv.lo go-signal.lo go-strslice.lo \
go-typedesc-equal.lo go-unsafe-new.lo go-unsafe-newarray.lo \
@LIBGO_IS_LINUX_TRUE@am__objects_3 = getncpu-linux.lo
am__objects_4 = aeshash.lo go-assert.lo go-caller.lo go-callers.lo \
go-cdiv.lo go-cgo.lo go-construct-map.lo go-ffi.lo \
go-fieldtrack.lo go-matherr.lo go-memclr.lo go-memcmp.lo \
go-memequal.lo go-memmove.lo go-nanotime.lo go-now.lo \
go-nosys.lo go-reflect-call.lo go-runtime-error.lo \
go-setenv.lo go-signal.lo go-strslice.lo go-typedesc-equal.lo \
go-unsafe-pointer.lo go-unsetenv.lo go-unwind.lo go-varargs.lo \
env_posix.lo heapdump.lo mcache.lo mcentral.lo \
$(am__objects_1) mfixalloc.lo mgc0.lo mheap.lo msize.lo \
panic.lo parfor.lo print.lo proc.lo runtime_c.lo thread.lo \
$(am__objects_2) yield.lo $(am__objects_3) malloc.lo \
$(am__objects_4)
am_libgo_llgo_la_OBJECTS = $(am__objects_5)
env_posix.lo panic.lo print.lo proc.lo runtime_c.lo stack.lo \
thread.lo $(am__objects_1) yield.lo $(am__objects_2) \
$(am__objects_3)
am_libgo_llgo_la_OBJECTS = $(am__objects_4)
libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS)
libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@
@GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir)
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
am_libgo_la_OBJECTS = $(am__objects_5)
am_libgo_la_OBJECTS = $(am__objects_4)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgo_la_LDFLAGS) \
@ -463,7 +464,8 @@ AM_CFLAGS = -fexceptions -fnon-call-exceptions -fplan9-extensions \
-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
-I $(MULTIBUILDTOP)../../gcc/include
@USING_SPLIT_STACK_TRUE@AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
AM_LDFLAGS = $(am__append_1) $(am__append_2)
@LIBGO_IS_AIX_TRUE@EXTRA_libgo_la_DEPENDENCIES = libgo.imp
# Multilib support.
MAKEOVERRIDES =
@ -761,13 +763,12 @@ toolexeclibgounicode_DATA = \
unicode/utf16.gox \
unicode/utf8.gox
@HAVE_SYS_MMAN_H_FALSE@runtime_mem_file = runtime/mem_posix_memalign.c
@HAVE_SYS_MMAN_H_TRUE@runtime_mem_file = runtime/mem.c
@LIBGO_IS_RTEMS_FALSE@rtems_task_variable_add_file =
@LIBGO_IS_RTEMS_TRUE@rtems_task_variable_add_file = runtime/rtems-task-variable-add.c
@LIBGO_IS_LINUX_FALSE@runtime_thread_files = runtime/thread-sema.c
@LIBGO_IS_LINUX_TRUE@runtime_thread_files = runtime/thread-linux.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
@LIBGO_IS_AIX_FALSE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-none.c
@LIBGO_IS_AIX_TRUE@@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-aix.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@runtime_getncpu_file = runtime/getncpu-bsd.c
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@runtime_getncpu_file = runtime/getncpu-solaris.c
@ -777,7 +778,6 @@ toolexeclibgounicode_DATA = \
runtime_files = \
runtime/aeshash.c \
runtime/go-assert.c \
runtime/go-breakpoint.c \
runtime/go-caller.c \
runtime/go-callers.c \
runtime/go-cdiv.c \
@ -792,7 +792,6 @@ runtime_files = \
runtime/go-memmove.c \
runtime/go-nanotime.c \
runtime/go-now.c \
runtime/go-new.c \
runtime/go-nosys.c \
runtime/go-reflect-call.c \
runtime/go-runtime-error.c \
@ -800,31 +799,20 @@ runtime_files = \
runtime/go-signal.c \
runtime/go-strslice.c \
runtime/go-typedesc-equal.c \
runtime/go-unsafe-new.c \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
runtime/go-unsetenv.c \
runtime/go-unwind.c \
runtime/go-varargs.c \
runtime/env_posix.c \
runtime/heapdump.c \
runtime/mcache.c \
runtime/mcentral.c \
$(runtime_mem_file) \
runtime/mfixalloc.c \
runtime/mgc0.c \
runtime/mheap.c \
runtime/msize.c \
runtime/panic.c \
runtime/parfor.c \
runtime/print.c \
runtime/proc.c \
runtime/runtime_c.c \
runtime/stack.c \
runtime/thread.c \
$(runtime_thread_files) \
runtime/yield.c \
$(rtems_task_variable_add_file) \
malloc.c \
$(runtime_getncpu_file)
noinst_DATA = zstdpkglist.go
@ -1079,8 +1067,13 @@ BUILDPACKAGE = \
# How to build a .gox file from a .lo file.
# Matching .o file can either be in the same directory as the .lo (non-PIC
# object) or in the .libs directory (PIC object).
BUILDGOX = \
f=`echo $< | sed -e 's/.lo$$/.o/'`; \
f="$(basename $<).o"; \
if test ! -f $$f; then \
f="$(basename $(<D)/.libs/$(<F)).o"; \
fi; \
$(OBJCOPY) -j .go_export $$f $@.tmp; \
$(SHELL) $(srcdir)/mvifdiff.sh $@.tmp `echo $@ | sed -e 's/s-gox/gox/'`
@ -1097,6 +1090,8 @@ CHECK = \
export RUNTESTFLAGS; \
MAKE="$(MAKE)"; \
export MAKE; \
NM="$(NM)"; \
export NM; \
libgccdir=`${GOC} -print-libgcc-file-name | sed -e 's|/[^/]*$$||'`; \
LD_LIBRARY_PATH="`${PWD_COMMAND}`/.libs:$${libgccdir}:${LD_LIBRARY_PATH}"; \
LD_LIBRARY_PATH=`echo $${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
@ -1136,7 +1131,7 @@ CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
$(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \
$(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \
$(toolexeclibgounicode_DATA) $(am__append_1) $(am__append_2)
$(toolexeclibgounicode_DATA) $(am__append_3) $(am__append_4)
# Pass -ffp-contract=off, or 386-specific options, when building the
# math package. MATH_FLAG is defined in configure.ac.
@ -1329,6 +1324,7 @@ TEST_PACKAGES = \
runtime/internal/sys/check \
runtime/pprof/check \
runtime/pprof/internal/protopprof/check \
runtime/trace/check \
sync/atomic/check \
text/scanner/check \
text/tabwriter/check \
@ -1338,8 +1334,14 @@ TEST_PACKAGES = \
unicode/utf16/check \
unicode/utf8/check
MOSTLYCLEAN_FILES = libgo.head libgo.sum.sep libgo.log.sep
CLEANFILES = *.go *.gox goc2c *.c s-version libgo.sum libgo.log
MOSTLYCLEANFILES = \
s-runtime_sysinfo s-sigtab s-runtime-inc s-zstdpkglist \
s-libcalls s-libcalls-list s-syscall_arch s-gen-sysinfo s-sysinfo \
s-errno s-epoll \
libgo.head libgo.sum.sep libgo.log.sep libgo.var \
libcalls-list runtime.inc runtime.inc.tmp2 runtime.inc.tmp3
CLEANFILES = *.go *.c s-version libgo.sum libgo.log runtime.inc
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@ -1482,13 +1484,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aeshash.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env_posix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-aix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-bsd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-irix.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-none.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getncpu-solaris.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-assert.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-breakpoint.Plo@am__quote@
@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-cdiv.Plo@am__quote@
@ -1502,7 +1504,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-memequal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-memmove.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nanotime.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nosys.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-now.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-call.Plo@am__quote@
@ -1511,31 +1512,19 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strslice.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typedesc-equal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-new.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-newarray.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsetenv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-varargs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heapdump.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgobegin_a-go-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgobegin_llgo_a-go-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgolibbegin_a-go-libmain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcentral.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_posix_memalign.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfixalloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mgc0.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msize.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parfor.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtems-task-variable-add.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime_c.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-linux.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread-sema.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
@ -1618,13 +1607,6 @@ go-assert.lo: runtime/go-assert.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-assert.lo `test -f 'runtime/go-assert.c' || echo '$(srcdir)/'`runtime/go-assert.c
go-breakpoint.lo: runtime/go-breakpoint.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-breakpoint.lo -MD -MP -MF $(DEPDIR)/go-breakpoint.Tpo -c -o go-breakpoint.lo `test -f 'runtime/go-breakpoint.c' || echo '$(srcdir)/'`runtime/go-breakpoint.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-breakpoint.Tpo $(DEPDIR)/go-breakpoint.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-breakpoint.c' object='go-breakpoint.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-breakpoint.lo `test -f 'runtime/go-breakpoint.c' || echo '$(srcdir)/'`runtime/go-breakpoint.c
go-caller.lo: runtime/go-caller.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-caller.lo -MD -MP -MF $(DEPDIR)/go-caller.Tpo -c -o go-caller.lo `test -f 'runtime/go-caller.c' || echo '$(srcdir)/'`runtime/go-caller.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-caller.Tpo $(DEPDIR)/go-caller.Plo
@ -1723,13 +1705,6 @@ go-now.lo: runtime/go-now.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-now.lo `test -f 'runtime/go-now.c' || echo '$(srcdir)/'`runtime/go-now.c
go-new.lo: runtime/go-new.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-new.lo -MD -MP -MF $(DEPDIR)/go-new.Tpo -c -o go-new.lo `test -f 'runtime/go-new.c' || echo '$(srcdir)/'`runtime/go-new.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-new.Tpo $(DEPDIR)/go-new.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-new.c' object='go-new.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-new.lo `test -f 'runtime/go-new.c' || echo '$(srcdir)/'`runtime/go-new.c
go-nosys.lo: runtime/go-nosys.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-nosys.lo -MD -MP -MF $(DEPDIR)/go-nosys.Tpo -c -o go-nosys.lo `test -f 'runtime/go-nosys.c' || echo '$(srcdir)/'`runtime/go-nosys.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-nosys.Tpo $(DEPDIR)/go-nosys.Plo
@ -1779,20 +1754,6 @@ go-typedesc-equal.lo: runtime/go-typedesc-equal.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-typedesc-equal.lo `test -f 'runtime/go-typedesc-equal.c' || echo '$(srcdir)/'`runtime/go-typedesc-equal.c
go-unsafe-new.lo: runtime/go-unsafe-new.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-unsafe-new.lo -MD -MP -MF $(DEPDIR)/go-unsafe-new.Tpo -c -o go-unsafe-new.lo `test -f 'runtime/go-unsafe-new.c' || echo '$(srcdir)/'`runtime/go-unsafe-new.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unsafe-new.Tpo $(DEPDIR)/go-unsafe-new.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-unsafe-new.c' object='go-unsafe-new.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-unsafe-new.lo `test -f 'runtime/go-unsafe-new.c' || echo '$(srcdir)/'`runtime/go-unsafe-new.c
go-unsafe-newarray.lo: runtime/go-unsafe-newarray.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-unsafe-newarray.lo -MD -MP -MF $(DEPDIR)/go-unsafe-newarray.Tpo -c -o go-unsafe-newarray.lo `test -f 'runtime/go-unsafe-newarray.c' || echo '$(srcdir)/'`runtime/go-unsafe-newarray.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unsafe-newarray.Tpo $(DEPDIR)/go-unsafe-newarray.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-unsafe-newarray.c' object='go-unsafe-newarray.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-unsafe-newarray.lo `test -f 'runtime/go-unsafe-newarray.c' || echo '$(srcdir)/'`runtime/go-unsafe-newarray.c
go-unsafe-pointer.lo: runtime/go-unsafe-pointer.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-unsafe-pointer.lo -MD -MP -MF $(DEPDIR)/go-unsafe-pointer.Tpo -c -o go-unsafe-pointer.lo `test -f 'runtime/go-unsafe-pointer.c' || echo '$(srcdir)/'`runtime/go-unsafe-pointer.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unsafe-pointer.Tpo $(DEPDIR)/go-unsafe-pointer.Plo
@ -1828,69 +1789,6 @@ env_posix.lo: runtime/env_posix.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 env_posix.lo `test -f 'runtime/env_posix.c' || echo '$(srcdir)/'`runtime/env_posix.c
heapdump.lo: runtime/heapdump.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT heapdump.lo -MD -MP -MF $(DEPDIR)/heapdump.Tpo -c -o heapdump.lo `test -f 'runtime/heapdump.c' || echo '$(srcdir)/'`runtime/heapdump.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/heapdump.Tpo $(DEPDIR)/heapdump.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/heapdump.c' object='heapdump.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 heapdump.lo `test -f 'runtime/heapdump.c' || echo '$(srcdir)/'`runtime/heapdump.c
mcache.lo: runtime/mcache.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mcache.lo -MD -MP -MF $(DEPDIR)/mcache.Tpo -c -o mcache.lo `test -f 'runtime/mcache.c' || echo '$(srcdir)/'`runtime/mcache.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mcache.Tpo $(DEPDIR)/mcache.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mcache.c' object='mcache.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 mcache.lo `test -f 'runtime/mcache.c' || echo '$(srcdir)/'`runtime/mcache.c
mcentral.lo: runtime/mcentral.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mcentral.lo -MD -MP -MF $(DEPDIR)/mcentral.Tpo -c -o mcentral.lo `test -f 'runtime/mcentral.c' || echo '$(srcdir)/'`runtime/mcentral.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mcentral.Tpo $(DEPDIR)/mcentral.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mcentral.c' object='mcentral.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 mcentral.lo `test -f 'runtime/mcentral.c' || echo '$(srcdir)/'`runtime/mcentral.c
mem_posix_memalign.lo: runtime/mem_posix_memalign.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mem_posix_memalign.lo -MD -MP -MF $(DEPDIR)/mem_posix_memalign.Tpo -c -o mem_posix_memalign.lo `test -f 'runtime/mem_posix_memalign.c' || echo '$(srcdir)/'`runtime/mem_posix_memalign.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mem_posix_memalign.Tpo $(DEPDIR)/mem_posix_memalign.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mem_posix_memalign.c' object='mem_posix_memalign.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 mem_posix_memalign.lo `test -f 'runtime/mem_posix_memalign.c' || echo '$(srcdir)/'`runtime/mem_posix_memalign.c
mem.lo: runtime/mem.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mem.lo -MD -MP -MF $(DEPDIR)/mem.Tpo -c -o mem.lo `test -f 'runtime/mem.c' || echo '$(srcdir)/'`runtime/mem.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mem.Tpo $(DEPDIR)/mem.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mem.c' object='mem.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 mem.lo `test -f 'runtime/mem.c' || echo '$(srcdir)/'`runtime/mem.c
mfixalloc.lo: runtime/mfixalloc.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mfixalloc.lo -MD -MP -MF $(DEPDIR)/mfixalloc.Tpo -c -o mfixalloc.lo `test -f 'runtime/mfixalloc.c' || echo '$(srcdir)/'`runtime/mfixalloc.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mfixalloc.Tpo $(DEPDIR)/mfixalloc.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mfixalloc.c' object='mfixalloc.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 mfixalloc.lo `test -f 'runtime/mfixalloc.c' || echo '$(srcdir)/'`runtime/mfixalloc.c
mgc0.lo: runtime/mgc0.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mgc0.lo -MD -MP -MF $(DEPDIR)/mgc0.Tpo -c -o mgc0.lo `test -f 'runtime/mgc0.c' || echo '$(srcdir)/'`runtime/mgc0.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mgc0.Tpo $(DEPDIR)/mgc0.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mgc0.c' object='mgc0.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 mgc0.lo `test -f 'runtime/mgc0.c' || echo '$(srcdir)/'`runtime/mgc0.c
mheap.lo: runtime/mheap.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mheap.lo -MD -MP -MF $(DEPDIR)/mheap.Tpo -c -o mheap.lo `test -f 'runtime/mheap.c' || echo '$(srcdir)/'`runtime/mheap.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mheap.Tpo $(DEPDIR)/mheap.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mheap.c' object='mheap.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 mheap.lo `test -f 'runtime/mheap.c' || echo '$(srcdir)/'`runtime/mheap.c
msize.lo: runtime/msize.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msize.lo -MD -MP -MF $(DEPDIR)/msize.Tpo -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/msize.Tpo $(DEPDIR)/msize.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/msize.c' object='msize.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 msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
panic.lo: runtime/panic.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT panic.lo -MD -MP -MF $(DEPDIR)/panic.Tpo -c -o panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/panic.Tpo $(DEPDIR)/panic.Plo
@ -1898,13 +1796,6 @@ panic.lo: runtime/panic.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 panic.lo `test -f 'runtime/panic.c' || echo '$(srcdir)/'`runtime/panic.c
parfor.lo: runtime/parfor.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parfor.lo -MD -MP -MF $(DEPDIR)/parfor.Tpo -c -o parfor.lo `test -f 'runtime/parfor.c' || echo '$(srcdir)/'`runtime/parfor.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parfor.Tpo $(DEPDIR)/parfor.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/parfor.c' object='parfor.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 parfor.lo `test -f 'runtime/parfor.c' || echo '$(srcdir)/'`runtime/parfor.c
print.lo: runtime/print.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT print.lo -MD -MP -MF $(DEPDIR)/print.Tpo -c -o print.lo `test -f 'runtime/print.c' || echo '$(srcdir)/'`runtime/print.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/print.Tpo $(DEPDIR)/print.Plo
@ -1926,6 +1817,13 @@ runtime_c.lo: runtime/runtime_c.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 runtime_c.lo `test -f 'runtime/runtime_c.c' || echo '$(srcdir)/'`runtime/runtime_c.c
stack.lo: runtime/stack.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stack.lo -MD -MP -MF $(DEPDIR)/stack.Tpo -c -o stack.lo `test -f 'runtime/stack.c' || echo '$(srcdir)/'`runtime/stack.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/stack.Tpo $(DEPDIR)/stack.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/stack.c' object='stack.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 stack.lo `test -f 'runtime/stack.c' || echo '$(srcdir)/'`runtime/stack.c
thread.lo: runtime/thread.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.lo -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Plo
@ -1968,6 +1866,13 @@ getncpu-none.lo: runtime/getncpu-none.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 getncpu-none.lo `test -f 'runtime/getncpu-none.c' || echo '$(srcdir)/'`runtime/getncpu-none.c
getncpu-aix.lo: runtime/getncpu-aix.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-aix.lo -MD -MP -MF $(DEPDIR)/getncpu-aix.Tpo -c -o getncpu-aix.lo `test -f 'runtime/getncpu-aix.c' || echo '$(srcdir)/'`runtime/getncpu-aix.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/getncpu-aix.Tpo $(DEPDIR)/getncpu-aix.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/getncpu-aix.c' object='getncpu-aix.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 getncpu-aix.lo `test -f 'runtime/getncpu-aix.c' || echo '$(srcdir)/'`runtime/getncpu-aix.c
getncpu-bsd.lo: runtime/getncpu-bsd.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getncpu-bsd.lo -MD -MP -MF $(DEPDIR)/getncpu-bsd.Tpo -c -o getncpu-bsd.lo `test -f 'runtime/getncpu-bsd.c' || echo '$(srcdir)/'`runtime/getncpu-bsd.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/getncpu-bsd.Tpo $(DEPDIR)/getncpu-bsd.Plo
@ -2899,6 +2804,7 @@ install-strip:
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
@ -2921,7 +2827,7 @@ distclean: distclean-multi distclean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
distclean-hdr distclean-libtool distclean-local distclean-tags
dvi: dvi-recursive
@ -3049,15 +2955,15 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
clean-generic clean-libtool clean-local clean-multi \
clean-toolexeclibLIBRARIES clean-toolexeclibLTLIBRARIES ctags \
ctags-recursive distclean distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-multi distclean-tags \
dvi dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-multi \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip install-toolexeclibLIBRARIES \
install-toolexeclibLTLIBRARIES install-toolexeclibgoDATA \
install-toolexeclibgoarchiveDATA \
distclean-hdr distclean-libtool distclean-local \
distclean-multi distclean-tags dvi dvi-am html html-am info \
info-am install install-am install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-multi install-pdf install-pdf-am \
install-ps install-ps-am install-strip \
install-toolexeclibLIBRARIES install-toolexeclibLTLIBRARIES \
install-toolexeclibgoDATA install-toolexeclibgoarchiveDATA \
install-toolexeclibgocompressDATA \
install-toolexeclibgocontainerDATA \
install-toolexeclibgocryptoDATA \
@ -3118,26 +3024,13 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgounicodeDATA
goc2c.$(OBJEXT): runtime/goc2c.c
$(CC_FOR_BUILD) -c $(CFLAGS_FOR_BUILD) $<
goc2c: goc2c.$(OBJEXT)
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ $<
malloc.c: $(srcdir)/runtime/malloc.goc goc2c
./goc2c $< > $@.tmp
mv -f $@.tmp $@
%.c: $(srcdir)/runtime/%.goc goc2c
./goc2c $< > $@.tmp
mv -f $@.tmp $@
version.go: s-version; @true
s-version: Makefile
rm -f version.go.tmp
echo "package sys" > version.go.tmp
echo 'const DefaultGoroot = "$(prefix)"' >> version.go.tmp
echo 'const TheVersion = "'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'"' >> version.go.tmp
echo 'const Goexperiment = ``' >> version.go.tmp
echo 'const GOARCH = "'$(GOARCH)'"' >> version.go.tmp
echo 'const GOOS = "'$(GOOS)'"' >> version.go.tmp
echo 'const GccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp
@ -3188,7 +3081,7 @@ s-version: Makefile
runtime_sysinfo.go: s-runtime_sysinfo; @true
s-runtime_sysinfo: $(srcdir)/mkrsysinfo.sh gen-sysinfo.go
$(SHELL) $(srcdir)/mkrsysinfo.sh
GOOS=$(GOOS) $(SHELL) $(srcdir)/mkrsysinfo.sh
$(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime_sysinfo.go runtime_sysinfo.go
$(STAMP) $@
@ -3198,14 +3091,23 @@ s-sigtab: $(srcdir)/mksigtab.sh gen-sysinfo.go
$(SHELL) $(srcdir)/mvifdiff.sh tmp-sigtab.go sigtab.go
$(STAMP) $@
# _Complex_lock and _Reader_lock are Go translations of some AIX system
# types and should not be exported back to C
# sigset conflicts with system type sigset on AIX, so we need to rename it
runtime.inc: s-runtime-inc; @true
s-runtime-inc: runtime.lo Makefile
rm -f runtime.inc.tmp2
grep -v "#define _" runtime.inc.tmp | grep -v "#define [cm][01234] " > runtime.inc.tmp2
rm -f runtime.inc.tmp2 runtime.inc.tmp3
grep -v "#define _" runtime.inc.tmp | grep -v "#define [cm][01234] " | grep -v "#define empty " > runtime.inc.tmp2
for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num; do \
grep "#define $$pattern" runtime.inc.tmp >> runtime.inc.tmp2; \
done
$(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp2 runtime.inc
for TYPE in _Complex_lock _Reader_lock; do \
sed -e '/struct '$${TYPE}' {/,/^}/s/^.*$$//' runtime.inc.tmp2 > runtime.inc.tmp3; \
mv runtime.inc.tmp3 runtime.inc.tmp2; \
done
sed -e 's/sigset/sigset_go/' runtime.inc.tmp2 > runtime.inc.tmp3
$(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp3 runtime.inc
rm -f runtime.inc.tmp2 runtime.inc.tmp3
$(STAMP) $@
# Generate the list of go std packages that were included in libgo
@ -3215,7 +3117,7 @@ s-zstdpkglist: Makefile
echo 'package main' > zstdpkglist.go.tmp
echo "" >> zstdpkglist.go.tmp
echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's/\.lo /\": true,\n/g' | grep -v _c | sed 's/\.lo/\": true,/' | sed 's/^/\t\"/' | sort -u >> zstdpkglist.go.tmp
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
echo '}' >> zstdpkglist.go.tmp
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
$(STAMP) $@
@ -3258,7 +3160,7 @@ s-errno:
sysinfo.go: s-sysinfo; @true
s-sysinfo: $(srcdir)/mksysinfo.sh gen-sysinfo.go errno.i
$(SHELL) $(srcdir)/mksysinfo.sh
GOOS=$(GOOS) $(SHELL) $(srcdir)/mksysinfo.sh
$(SHELL) $(srcdir)/mvifdiff.sh tmp-sysinfo.go sysinfo.go
$(STAMP) $@
@ -3496,6 +3398,11 @@ mostlyclean-local:
clean-local:
find . -name '*.la' -print | xargs $(LIBTOOL) --mode=clean rm -f
find . -name '*.a' -print | xargs rm -f
find . -name '*.gox' -print | xargs rm -f
find . -name '*.s-gox' -print | xargs rm -f
distclean-local:
find . -name '*.lo.dep' -print | xargs rm -f
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

View File

@ -259,6 +259,9 @@
/* Define to 1 if you have the `sync_file_range' function. */
#undef HAVE_SYNC_FILE_RANGE
/* Define to 1 if you have the `syscall' function. */
#undef HAVE_SYSCALL
/* Define to 1 if you have the <syscall.h> header file. */
#undef HAVE_SYSCALL_H

32
libgo/configure vendored
View File

@ -646,6 +646,8 @@ ALLGOOS
GOOS
LIBGO_IS_BSD_FALSE
LIBGO_IS_BSD_TRUE
LIBGO_IS_AIX_FALSE
LIBGO_IS_AIX_TRUE
LIBGO_IS_SOLARIS_FALSE
LIBGO_IS_SOLARIS_TRUE
LIBGO_IS_RTEMS_FALSE
@ -4327,6 +4329,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
case ${host} in
*-*-aix*)
# static hash tables crashes on AIX when libgo is built with O2
CFLAGS="$CFLAGS -fno-section-anchors"
GOCFLAGS="$GOCFLAGS -fno-section-anchors"
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
@ -11104,7 +11114,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11107 "configure"
#line 11117 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11210,7 +11220,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11213 "configure"
#line 11223 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -13507,7 +13517,7 @@ go_include="-include"
# All known GOOS values. This is the union of all operating systems
# supported by the gofrontend and all operating systems supported by
# the gc toolchain.
ALLGOOS="android darwin dragonfly freebsd irix linux netbsd openbsd plan9 rtems solaris windows"
ALLGOOS="aix android darwin dragonfly freebsd irix linux netbsd openbsd plan9 rtems solaris windows"
is_darwin=no
is_freebsd=no
@ -13518,6 +13528,7 @@ is_openbsd=no
is_dragonfly=no
is_rtems=no
is_solaris=no
is_aix=no
GOOS=unknown
case ${host} in
*-*-darwin*) is_darwin=yes; GOOS=darwin ;;
@ -13529,6 +13540,7 @@ case ${host} in
*-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
*-*-aix*) is_aix=yes; GOOS=aix ;;
esac
if test $is_darwin = yes; then
LIBGO_IS_DARWIN_TRUE=
@ -13602,6 +13614,14 @@ else
LIBGO_IS_SOLARIS_FALSE=
fi
if test $is_aix = yes; then
LIBGO_IS_AIX_TRUE=
LIBGO_IS_AIX_FALSE='#'
else
LIBGO_IS_AIX_TRUE='#'
LIBGO_IS_AIX_FALSE=
fi
if test $is_darwin = yes -o $is_dragonfly = yes -o $is_freebsd = yes -o $is_netbsd = yes -o $is_openbsd = yes; then
LIBGO_IS_BSD_TRUE=
LIBGO_IS_BSD_FALSE='#'
@ -14868,7 +14888,7 @@ else
fi
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 open64 openat pipe2 removexattr renameat setxattr 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 open64 openat pipe2 removexattr renameat setxattr sync_file_range splice syscall 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"
@ -15753,6 +15773,10 @@ if test -z "${LIBGO_IS_SOLARIS_TRUE}" && test -z "${LIBGO_IS_SOLARIS_FALSE}"; th
as_fn_error "conditional \"LIBGO_IS_SOLARIS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${LIBGO_IS_AIX_TRUE}" && test -z "${LIBGO_IS_AIX_FALSE}"; then
as_fn_error "conditional \"LIBGO_IS_AIX\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${LIBGO_IS_BSD_TRUE}" && test -z "${LIBGO_IS_BSD_FALSE}"; then
as_fn_error "conditional \"LIBGO_IS_BSD\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5

View File

@ -31,6 +31,14 @@ m4_rename_force([glibgo_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
AC_SUBST(CFLAGS)
case ${host} in
*-*-aix*)
# static hash tables crashes on AIX when libgo is built with O2
CFLAGS="$CFLAGS -fno-section-anchors"
GOCFLAGS="$GOCFLAGS -fno-section-anchors"
;;
esac
AM_MAINTAINER_MODE
AC_PROG_LD
@ -146,7 +154,7 @@ AC_SUBST(go_include)
# All known GOOS values. This is the union of all operating systems
# supported by the gofrontend and all operating systems supported by
# the gc toolchain.
ALLGOOS="android darwin dragonfly freebsd irix linux netbsd openbsd plan9 rtems solaris windows"
ALLGOOS="aix android darwin dragonfly freebsd irix linux netbsd openbsd plan9 rtems solaris windows"
is_darwin=no
is_freebsd=no
@ -157,6 +165,7 @@ is_openbsd=no
is_dragonfly=no
is_rtems=no
is_solaris=no
is_aix=no
GOOS=unknown
case ${host} in
*-*-darwin*) is_darwin=yes; GOOS=darwin ;;
@ -168,6 +177,7 @@ case ${host} in
*-*-dragonfly*) is_dragonfly=yes; GOOS=dragonfly ;;
*-*-rtems*) is_rtems=yes; GOOS=rtems ;;
*-*-solaris2*) is_solaris=yes; GOOS=solaris ;;
*-*-aix*) is_aix=yes; GOOS=aix ;;
esac
AM_CONDITIONAL(LIBGO_IS_DARWIN, test $is_darwin = yes)
AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes)
@ -178,6 +188,7 @@ AM_CONDITIONAL(LIBGO_IS_OPENBSD, test $is_openbsd = yes)
AM_CONDITIONAL(LIBGO_IS_DRAGONFLY, test $is_dragonfly = yes)
AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes)
AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes)
AM_CONDITIONAL(LIBGO_IS_AIX, test $is_aix = yes)
AM_CONDITIONAL(LIBGO_IS_BSD, test $is_darwin = yes -o $is_dragonfly = yes -o $is_freebsd = yes -o $is_netbsd = yes -o $is_openbsd = yes)
AC_SUBST(GOOS)
AC_SUBST(ALLGOOS)
@ -601,7 +612,7 @@ AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv unsetenv dl_iterate_phd
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 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat open64 openat pipe2 removexattr renameat setxattr 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 open64 openat pipe2 removexattr renameat setxattr sync_file_range splice syscall tee unlinkat unshare utimensat)
AC_TYPE_OFF_T
AC_CHECK_TYPES([loff_t])

View File

@ -10,6 +10,7 @@ import (
"internal/testenv"
"math/rand"
"reflect"
"runtime"
"strings"
"testing"
"unicode"
@ -392,7 +393,11 @@ func TestIndexRune(t *testing.T) {
}
})
if allocs != 0 {
t.Errorf("expected no allocations, got %f", allocs)
if runtime.Compiler == "gccgo" {
t.Log("does not work on gccgo without better escape analysis")
} else {
t.Errorf("expected no allocations, got %f", allocs)
}
}
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package rand

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris
// Unix cryptographically secure pseudorandom number
// generator.

View File

@ -0,0 +1,8 @@
// Copyright 2017 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 x509
// Possible certificate files; stop after finding one.
var certFiles []string

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix dragonfly freebsd linux nacl netbsd openbsd solaris
package x509
@ -16,6 +16,7 @@ import (
var certDirectories = []string{
"/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
"/system/etc/security/cacerts", // Android
"/var/ssl/certs", // AIX
}
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {

View File

@ -4,5 +4,5 @@
package build
const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows zos "
const goosList = "aix android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows zos "
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be alpha m68k ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le mipso32 mipsn32 mipsn64 mipso64 ppc s390 s390x sparc sparc64 "

View File

@ -97,6 +97,9 @@ func satan(x float64) float64 {
func libc_atan(float64) float64
func Atan(x float64) float64 {
if x == 0 {
return x
}
return libc_atan(x)
}

View File

@ -126,6 +126,9 @@ package math
func libc_expm1(float64) float64
func Expm1(x float64) float64 {
if x == 0 {
return x
}
return libc_expm1(x)
}

View File

@ -97,6 +97,9 @@ package math
func libc_log1p(float64) float64
func Log1p(x float64) float64 {
if x == 0 {
return x
}
return libc_log1p(x)
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package mime

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
// Minimal RFC 6724 address selection.

13
libgo/go/net/cgo_aix.go Normal file
View File

@ -0,0 +1,13 @@
// 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.
// +build cgo,!netgo
package net
import (
"syscall"
)
const cgoAddrInfoFlags = syscall.AI_CANONNAME

View File

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build cgo,!netgo
// +build darwin linux,!android netbsd solaris
// +build aix darwin linux,!android netbsd solaris
package net

View File

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build cgo,!netgo
// +build darwin dragonfly freebsd netbsd openbsd
// +build aix darwin dragonfly freebsd netbsd openbsd
package net

View File

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build cgo,!netgo
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build cgo,!netgo
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
// Read system DNS config from /etc/resolv.conf

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd windows solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl
// +build aix nacl
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package socktest

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris nacl
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris nacl
// Read system port mappings from /etc/services

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin nacl netbsd openbsd
// +build aix darwin nacl netbsd openbsd
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build nacl solaris
// +build aix nacl solaris
package net

View File

@ -0,0 +1,34 @@
// Copyright 2017 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 net
import (
"os"
"syscall"
)
// This was copied from sockopt_linux.go
func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
// Allow both IP versions even if the OS default
// is otherwise. Note that some operating systems
// never admit this option.
syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
}
// Allow broadcast.
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
}
func setDefaultListenerSockopts(s int) error {
// Allow reuse of recently-used addresses.
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
}
func setDefaultMulticastSockopts(s int) error {
// Allow multicast UDP and raw IP datagram sockets to listen
// concurrently across multiple listeners.
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
package net

View File

@ -0,0 +1,15 @@
// Copyright 2017 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 net
import "syscall"
func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
return syscall.ENOPROTOOPT
}
func setIPv4MulticastLoopback(fd *netFD, v bool) error {
return syscall.ENOPROTOOPT
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd windows
// +build aix darwin dragonfly freebsd linux netbsd openbsd windows
package net

View File

@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that do not
// provide a fast path for setting SetNonblock and CloseOnExec.
// +build darwin dragonfly nacl netbsd openbsd solaris
// +build aix darwin dragonfly nacl netbsd openbsd solaris
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build freebsd linux netbsd
// +build aix freebsd linux netbsd
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package net

View File

@ -6,6 +6,7 @@ package os
import (
"io"
"runtime"
"sync/atomic"
"syscall"
"unsafe"
@ -81,6 +82,11 @@ func (file *File) readdirnames(n int) (names []string, err error) {
syscall.Entersyscall()
i := libc_readdir_r(file.dirinfo.dir, entryDirent, pr)
syscall.Exitsyscall()
// On AIX when readdir_r hits EOF it sets dirent to nil and returns 9.
// https://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.basetrf2/readdir_r.htm
if runtime.GOOS == "aix" && i == 9 && dirent == nil {
break
}
if i != 0 {
return names, NewSyscallError("readdir_r", i)
}

View File

@ -5,7 +5,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux solaris,386 solaris,sparc
// +build aix linux solaris,386 solaris,sparc
package os

View File

@ -5,6 +5,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !aix
// +build !linux
// +build !solaris !386
// +build !solaris !sparc

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package exec

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os

View File

@ -0,0 +1,104 @@
// Copyright 2017 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.
// +build aix
package os
// We query the working directory at init, to use it later to search for the
// executable file
// errWd will be checked later, if we need to use initWd
var initWd, errWd = Getwd()
func executable() (string, error) {
var err error
var exePath string
if len(Args) == 0 || Args[0] == "" {
return "", ErrNotExist
}
// Args[0] is an absolute path : this is the executable
if IsPathSeparator(Args[0][0]) {
exePath = Args[0]
} else {
for i := 1; i < len(Args[0]); i++ {
// Args[0] is a relative path : append current directory
if IsPathSeparator(Args[0][i]) {
if errWd != nil {
return "", errWd
}
exePath = initWd + string(PathSeparator) + Args[0]
break
}
}
}
if exePath != "" {
err = isExecutable(exePath)
if err == nil {
return exePath, nil
}
// File does not exist or is not executable,
// this is an unexpected situation !
return "", err
}
// Search for executable in $PATH
for _, dir := range splitPathList(Getenv("PATH")) {
if len(dir) == 0 {
continue
}
if !IsPathSeparator(dir[0]) {
if errWd != nil {
return "", errWd
}
dir = initWd + string(PathSeparator) + dir
}
exePath = dir + string(PathSeparator) + Args[0]
err = isExecutable(exePath)
if err == nil {
return exePath, nil
}
if err == ErrPermission {
return "", err
}
}
return "", ErrNotExist
}
// isExecutable returns an error if a given file is not an executable.
func isExecutable(path string) error {
stat, err := Stat(path)
if err != nil {
return err
}
mode := stat.Mode()
if !mode.IsRegular() {
return ErrPermission
}
if (mode & 0111) != 0 {
return nil
}
return ErrPermission
}
// splitPathList splits a path list.
// This is based on genSplit from strings/strings.go
func splitPathList(pathList string) []string {
n := 1
for i := 0; i < len(pathList); i++ {
if pathList[i] == PathListSeparator {
n++
}
}
start := 0
a := make([]string, n)
na := 0
for i := 0; i+1 <= len(pathList) && na+1 < n; i++ {
if pathList[i] == PathListSeparator {
a[na] = pathList[start:i]
na++
start = i + 1
}
}
a[na] = pathList[start:]
return a[:na+1]
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package os
@ -19,6 +19,10 @@ func Readlink(name string) (string, error) {
for len := 128; ; len *= 2 {
b := make([]byte, len)
n, e := fixCount(syscall.Readlink(fixLongPath(name), b))
// buffer too small
if e == syscall.ERANGE {
continue
}
if e != nil {
return "", &PathError{"readlink", name, e}
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd nacl netbsd openbsd solaris
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package signal

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
package signal

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !aix
// +build !darwin
// +build !freebsd
// +build !linux

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux openbsd solaristag
// +build aix linux openbsd solaristag
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package os

View File

@ -4,7 +4,7 @@
// For systems which only store the hostname in uname (Solaris).
// +build solaris irix rtems
// +build aix solaris irix rtems
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build dragonfly linux netbsd openbsd solaris
// +build aix dragonfly linux netbsd openbsd solaris
package os

View File

@ -0,0 +1,24 @@
// Copyright 2017 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 user
import "syscall"
// Declarations for the libc functions on AIX.
//extern _posix_getpwnam_r
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
//extern _posix_getpwuid_r
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int
//extern _posix_getgrnam_r
func libc_getgrnam_r(name *byte, grp *syscall.Group, buf *byte, buflen syscall.Size_t, result **syscall.Group) int
//extern _posix_getgrgid_r
func libc_getgrgid_r(gid syscall.Gid_t, grp *syscall.Group, buf *byte, buflen syscall.Size_t, result **syscall.Group) int
//extern getgrset
func libc_getgrset(user *byte) *byte

View File

@ -0,0 +1,11 @@
// Copyright 2017 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 user
import "fmt"
func listGroups(u *User) ([]string, error) {
return nil, fmt.Errorf("user: list groups for %s: not supported on AIX", u.Username)
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris
// +build aix darwin dragonfly freebsd !android,linux netbsd openbsd solaris
// +build cgo
package user

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build dragonfly nacl netbsd openbsd solaris
// +build aix dragonfly nacl netbsd openbsd solaris
package os

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package filepath

View File

@ -259,20 +259,21 @@ const (
// with a unique tag like `reflect:"array"` or `reflect:"ptr"`
// so that code cannot convert from, say, *arrayType to *ptrType.
type rtype struct {
kind uint8 // enumeration for C
align int8 // alignment of variable with this type
fieldAlign uint8 // alignment of struct field with this type
_ uint8 // unused/padding
size uintptr
hash uint32 // hash of type; avoids computation in hash tables
ptrdata uintptr // size of memory prefix holding all pointers
hash uint32 // hash of type; avoids computation in hash tables
kind uint8 // enumeration for C
align int8 // alignment of variable with this type
fieldAlign uint8 // alignment of struct field with this type
_ uint8 // unused/padding
hashfn func(unsafe.Pointer, uintptr) uintptr // hash function
equalfn func(unsafe.Pointer, unsafe.Pointer) bool // equality function
gc unsafe.Pointer // garbage collection data
string *string // string form; unnecessary but undeniably useful
*uncommonType // (relatively) uncommon fields
ptrToThis *rtype // type for pointer to this type, if used in binary or has methods
gcdata *byte // garbage collection data
string *string // string form; unnecessary but undeniably useful
*uncommonType // (relatively) uncommon fields
ptrToThis *rtype // type for pointer to this type, if used in binary or has methods
}
// Method on non-interface type
@ -382,24 +383,6 @@ type structType struct {
fields []structField // sorted by offset
}
// NOTE: These are copied from ../runtime/mgc0.h.
// They must be kept in sync.
const (
_GC_END = iota
_GC_PTR
_GC_APTR
_GC_ARRAY_START
_GC_ARRAY_NEXT
_GC_CALL
_GC_CHAN_PTR
_GC_STRING
_GC_EFACE
_GC_IFACE
_GC_SLICE
_GC_REGION
_GC_NUM_INSTR
)
/*
* The compiler knows the exact layout of all the data structures above.
* The compiler does not know about the data structures and methods below.
@ -1098,32 +1081,6 @@ var ptrMap struct {
m map[*rtype]*ptrType
}
// garbage collection bytecode program for pointer to memory without pointers.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
type ptrDataGC struct {
width uintptr // sizeof(ptr)
op uintptr // _GC_APTR
off uintptr // 0
end uintptr // _GC_END
}
var ptrDataGCProg = ptrDataGC{
width: unsafe.Sizeof((*byte)(nil)),
op: _GC_APTR,
off: 0,
end: _GC_END,
}
// garbage collection bytecode program for pointer to memory with pointers.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
type ptrGC struct {
width uintptr // sizeof(ptr)
op uintptr // _GC_PTR
off uintptr // 0
elemgc unsafe.Pointer // element gc type
end uintptr // _GC_END
}
// PtrTo returns the pointer type with element t.
// For example, if t represents type Foo, PtrTo(t) represents *Foo.
func PtrTo(t Type) Type {
@ -1189,18 +1146,6 @@ func (t *rtype) ptrTo() *rtype {
pp.ptrToThis = nil
pp.elem = t
if t.kind&kindNoPointers != 0 {
pp.gc = unsafe.Pointer(&ptrDataGCProg)
} else {
pp.gc = unsafe.Pointer(&ptrGC{
width: pp.size,
op: _GC_PTR,
off: 0,
elemgc: t.gc,
end: _GC_END,
})
}
q := canonicalize(&pp.rtype)
p = (*ptrType)(unsafe.Pointer(q.(*rtype)))
@ -1507,16 +1452,6 @@ func cachePut(k cacheKey, t *rtype) Type {
return t
}
// garbage collection bytecode program for chan.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
type chanGC struct {
width uintptr // sizeof(map)
op uintptr // _GC_CHAN_PTR
off uintptr // 0
typ *rtype // map type
end uintptr // _GC_END
}
// The funcLookupCache caches FuncOf lookups.
// FuncOf does not share the common lookupCache since cacheKey is not
// sufficient to represent functions unambiguously.
@ -1584,17 +1519,6 @@ func ChanOf(dir ChanDir, t Type) Type {
ch.uncommonType = nil
ch.ptrToThis = nil
ch.gc = unsafe.Pointer(&chanGC{
width: ch.size,
op: _GC_CHAN_PTR,
off: 0,
typ: &ch.rtype,
end: _GC_END,
})
// INCORRECT. Uncomment to check that TestChanOfGC fails when ch.gc is wrong.
// ch.gc = unsafe.Pointer(&badGC{width: ch.size, end: _GC_END})
return cachePut(ckey, &ch.rtype)
}
@ -1733,9 +1657,6 @@ func FuncOf(in, out []Type, variadic bool) Type {
ft.uncommonType = nil
ft.ptrToThis = nil
// TODO(cmang): Generate GC data for funcs.
ft.gc = unsafe.Pointer(&ptrDataGCProg)
funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype)
return toType(&ft.rtype)
@ -1859,8 +1780,8 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
// and it's easier to generate a pointer bitmap than a GC program.
// Note that since the key and value are known to be <= 128 bytes,
// they're guaranteed to have bitmaps instead of GC programs.
// var gcdata *byte
// var ptrdata uintptr
var gcdata *byte
var ptrdata uintptr
size := bucketSize
size = align(size, uintptr(ktyp.fieldAlign))
@ -1875,37 +1796,63 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
if maxAlign > ptrSize {
size = align(size, maxAlign)
size += align(ptrSize, maxAlign) - ptrSize
} else if maxAlign < ptrSize {
size = align(size, ptrSize)
maxAlign = ptrSize
}
ovoff := size
size += ptrSize
if maxAlign < ptrSize {
maxAlign = ptrSize
}
var gcPtr unsafe.Pointer
if kind != kindNoPointers {
gc := []uintptr{size}
base := bucketSize
base = align(base, uintptr(ktyp.fieldAlign))
nptr := size / ptrSize
mask := make([]byte, (nptr+7)/8)
psize := bucketSize
psize = align(psize, uintptr(ktyp.fieldAlign))
base := psize / ptrSize
if ktyp.kind&kindNoPointers == 0 {
gc = append(gc, _GC_ARRAY_START, base, bucketSize, ktyp.size)
gc = appendGCProgram(gc, ktyp, 0)
gc = append(gc, _GC_ARRAY_NEXT)
if ktyp.kind&kindGCProg != 0 {
panic("reflect: unexpected GC program in MapOf")
}
kmask := (*[16]byte)(unsafe.Pointer(ktyp.gcdata))
for i := uintptr(0); i < ktyp.size/ptrSize; i++ {
if (kmask[i/8]>>(i%8))&1 != 0 {
for j := uintptr(0); j < bucketSize; j++ {
word := base + j*ktyp.size/ptrSize + i
mask[word/8] |= 1 << (word % 8)
}
}
}
}
base += ktyp.size * bucketSize
base = align(base, uintptr(etyp.fieldAlign))
psize += bucketSize * ktyp.size
psize = align(psize, uintptr(etyp.fieldAlign))
base = psize / ptrSize
if etyp.kind&kindNoPointers == 0 {
gc = append(gc, _GC_ARRAY_START, base, bucketSize, etyp.size)
gc = appendGCProgram(gc, etyp, 0)
gc = append(gc, _GC_ARRAY_NEXT)
if etyp.kind&kindGCProg != 0 {
panic("reflect: unexpected GC program in MapOf")
}
emask := (*[16]byte)(unsafe.Pointer(etyp.gcdata))
for i := uintptr(0); i < etyp.size/ptrSize; i++ {
if (emask[i/8]>>(i%8))&1 != 0 {
for j := uintptr(0); j < bucketSize; j++ {
word := base + j*etyp.size/ptrSize + i
mask[word/8] |= 1 << (word % 8)
}
}
}
}
word := ovoff / ptrSize
mask[word/8] |= 1 << (word % 8)
gcdata = &mask[0]
ptrdata = (word + 1) * ptrSize
// overflow word must be last
if ptrdata != size {
panic("reflect: bad layout computation in MapOf")
}
gc = append(gc, _GC_APTR, ovoff, _GC_END)
gcPtr = unsafe.Pointer(&gc[0])
} else {
// No pointers in bucket.
gc := [...]uintptr{size, _GC_END}
gcPtr = unsafe.Pointer(&gc[0])
}
b := &rtype{
@ -1913,102 +1860,14 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
fieldAlign: uint8(maxAlign),
size: size,
kind: kind,
gc: gcPtr,
ptrdata: ptrdata,
gcdata: gcdata,
}
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
b.string = &s
return b
}
// Take the GC program for "t" and append it to the GC program "gc".
func appendGCProgram(gc []uintptr, t *rtype, offset uintptr) []uintptr {
p := t.gc
p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0))) // skip size
loop:
for {
var argcnt int
switch *(*uintptr)(p) {
case _GC_END:
// Note: _GC_END not included in append
break loop
case _GC_ARRAY_NEXT:
argcnt = 0
case _GC_APTR, _GC_STRING, _GC_EFACE, _GC_IFACE:
argcnt = 1
case _GC_PTR, _GC_CALL, _GC_CHAN_PTR, _GC_SLICE:
argcnt = 2
case _GC_ARRAY_START, _GC_REGION:
argcnt = 3
default:
panic("unknown GC program op for " + *t.string + ": " + strconv.FormatUint(*(*uint64)(p), 10))
}
for i := 0; i < argcnt+1; i++ {
v := *(*uintptr)(p)
if i == 1 {
v += offset
}
gc = append(gc, v)
p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(uintptr(0)))
}
}
return gc
}
func hMapOf(bucket *rtype) *rtype {
ptrsize := unsafe.Sizeof(uintptr(0))
// make gc program & compute hmap size
gc := make([]uintptr, 1) // first entry is size, filled in at the end
offset := unsafe.Sizeof(uint(0)) // count
offset += unsafe.Sizeof(uint32(0)) // flags
offset += unsafe.Sizeof(uint32(0)) // hash0
offset += unsafe.Sizeof(uint8(0)) // B
offset += unsafe.Sizeof(uint8(0)) // keysize
offset += unsafe.Sizeof(uint8(0)) // valuesize
offset = (offset + 1) / 2 * 2
offset += unsafe.Sizeof(uint16(0)) // bucketsize
offset = (offset + ptrsize - 1) / ptrsize * ptrsize
// gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // buckets
offset += ptrsize
// gc = append(gc, _GC_PTR, offset, uintptr(bucket.gc)) // oldbuckets
offset += ptrsize
offset += ptrsize // nevacuate
gc = append(gc, _GC_END)
gc[0] = offset
h := new(rtype)
h.size = offset
// h.gc = unsafe.Pointer(&gc[0])
s := "hmap(" + *bucket.string + ")"
h.string = &s
return h
}
// garbage collection bytecode program for slice of non-zero-length values.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
type sliceGC struct {
width uintptr // sizeof(slice)
op uintptr // _GC_SLICE
off uintptr // 0
elemgc unsafe.Pointer // element gc program
end uintptr // _GC_END
}
// garbage collection bytecode program for slice of zero-length values.
// See ../../cmd/gc/reflect.c:/^dgcsym1 and :/^dgcsym.
type sliceEmptyGC struct {
width uintptr // sizeof(slice)
op uintptr // _GC_APTR
off uintptr // 0
end uintptr // _GC_END
}
var sliceEmptyGCProg = sliceEmptyGC{
width: unsafe.Sizeof([]byte(nil)),
op: _GC_APTR,
off: 0,
end: _GC_END,
}
// SliceOf returns the slice type with element type t.
// For example, if t represents int, SliceOf(t) represents []int.
func SliceOf(t Type) Type {
@ -2037,21 +1896,6 @@ func SliceOf(t Type) Type {
slice.uncommonType = nil
slice.ptrToThis = nil
if typ.size == 0 {
slice.gc = unsafe.Pointer(&sliceEmptyGCProg)
} else {
slice.gc = unsafe.Pointer(&sliceGC{
width: slice.size,
op: _GC_SLICE,
off: 0,
elemgc: typ.gc,
end: _GC_END,
})
}
// INCORRECT. Uncomment to check that TestSliceOfOfGC fails when slice.gc is wrong.
// slice.gc = unsafe.Pointer(&badGC{width: slice.size, end: _GC_END})
return cachePut(ckey, &slice.rtype)
}
@ -2073,15 +1917,18 @@ var structLookupCache struct {
// This limitation may be lifted in a future version.
func StructOf(fields []StructField) Type {
var (
hash = uint32(0)
size uintptr
typalign int8
hash = uint32(0)
size uintptr
typalign int8
comparable = true
hashable = true
fs = make([]structField, len(fields))
repr = make([]byte, 0, 64)
fset = map[string]struct{}{} // fields' names
hasPtr = false // records whether at least one struct-field is a pointer
hasPtr = false // records whether at least one struct-field is a pointer
hasGCProg = false // records whether a struct-field type has a GCProg
)
lastzero := uintptr(0)
@ -2092,6 +1939,9 @@ func StructOf(fields []StructField) Type {
}
f := runtimeStructField(field)
ft := f.typ
if ft.kind&kindGCProg != 0 {
hasGCProg = true
}
if ft.pointers() {
hasPtr = true
}
@ -2156,6 +2006,9 @@ func StructOf(fields []StructField) Type {
repr = append(repr, ';')
}
comparable = comparable && (ft.equalfn != nil)
hashable = hashable && (ft.hashfn != nil)
f.offset = align(size, uintptr(ft.fieldAlign))
if int8(ft.fieldAlign) > typalign {
typalign = int8(ft.fieldAlign)
@ -2228,36 +2081,95 @@ func StructOf(fields []StructField) Type {
typ.fieldAlign = uint8(typalign)
if !hasPtr {
typ.kind |= kindNoPointers
gc := [...]uintptr{size, _GC_END}
typ.gc = unsafe.Pointer(&gc[0])
} else {
typ.kind &^= kindNoPointers
gc := []uintptr{size}
for _, ft := range fs {
gc = appendGCProgram(gc, ft.typ, ft.offset)
}
gc = append(gc, _GC_END)
typ.gc = unsafe.Pointer(&gc[0])
}
typ.hashfn = func(p unsafe.Pointer, seed uintptr) uintptr {
ret := seed
for _, ft := range typ.fields {
o := unsafe.Pointer(uintptr(p) + ft.offset)
ret = ft.typ.hashfn(o, ret)
}
return ret
}
typ.equalfn = func(p, q unsafe.Pointer) bool {
for _, ft := range typ.fields {
pi := unsafe.Pointer(uintptr(p) + ft.offset)
qi := unsafe.Pointer(uintptr(q) + ft.offset)
if !ft.typ.equalfn(pi, qi) {
return false
if hasGCProg {
lastPtrField := 0
for i, ft := range fs {
if ft.typ.pointers() {
lastPtrField = i
}
}
return true
prog := []byte{0, 0, 0, 0} // will be length of prog
for i, ft := range fs {
if i > lastPtrField {
// gcprog should not include anything for any field after
// the last field that contains pointer data
break
}
// FIXME(sbinet) handle padding, fields smaller than a word
elemGC := (*[1 << 30]byte)(unsafe.Pointer(ft.typ.gcdata))[:]
elemPtrs := ft.typ.ptrdata / ptrSize
switch {
case ft.typ.kind&kindGCProg == 0 && ft.typ.ptrdata != 0:
// Element is small with pointer mask; use as literal bits.
mask := elemGC
// Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes).
var n uintptr
for n := elemPtrs; n > 120; n -= 120 {
prog = append(prog, 120)
prog = append(prog, mask[:15]...)
mask = mask[15:]
}
prog = append(prog, byte(n))
prog = append(prog, mask[:(n+7)/8]...)
case ft.typ.kind&kindGCProg != 0:
// Element has GC program; emit one element.
elemProg := elemGC[4 : 4+*(*uint32)(unsafe.Pointer(&elemGC[0]))-1]
prog = append(prog, elemProg...)
}
// Pad from ptrdata to size.
elemWords := ft.typ.size / ptrSize
if elemPtrs < elemWords {
// Emit literal 0 bit, then repeat as needed.
prog = append(prog, 0x01, 0x00)
if elemPtrs+1 < elemWords {
prog = append(prog, 0x81)
prog = appendVarint(prog, elemWords-elemPtrs-1)
}
}
}
*(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
typ.kind |= kindGCProg
typ.gcdata = &prog[0]
} else {
typ.kind &^= kindGCProg
bv := new(bitVector)
addTypeBits(bv, 0, typ.common())
if len(bv.data) > 0 {
typ.gcdata = &bv.data[0]
}
}
typ.ptrdata = typeptrdata(typ.common())
if hashable {
typ.hashfn = func(p unsafe.Pointer, seed uintptr) uintptr {
o := seed
for _, ft := range typ.fields {
pi := unsafe.Pointer(uintptr(p) + ft.offset)
o = ft.typ.hashfn(pi, o)
}
return o
}
} else {
typ.hashfn = nil
}
if comparable {
typ.equalfn = func(p, q unsafe.Pointer) bool {
for _, ft := range typ.fields {
pi := unsafe.Pointer(uintptr(p) + ft.offset)
qi := unsafe.Pointer(uintptr(q) + ft.offset)
if !ft.typ.equalfn(pi, qi) {
return false
}
}
return true
}
} else {
typ.equalfn = nil
}
typ.kind &^= kindDirectIface
@ -2308,6 +2220,35 @@ func runtimeStructField(field StructField) structField {
}
}
// typeptrdata returns the length in bytes of the prefix of t
// containing pointer data. Anything after this offset is scalar data.
// keep in sync with ../cmd/compile/internal/gc/reflect.go
func typeptrdata(t *rtype) uintptr {
if !t.pointers() {
return 0
}
switch t.Kind() {
case Struct:
st := (*structType)(unsafe.Pointer(t))
// find the last field that has pointers.
field := 0
for i := range st.fields {
ft := st.fields[i].typ
if ft.pointers() {
field = i
}
}
f := st.fields[field]
return f.offset + f.typ.ptrdata
default:
panic("reflect.typeptrdata: unexpected type, " + t.String())
}
}
// See cmd/compile/internal/gc/reflect.go for derivation of constant.
const maxPtrmaskBytes = 2048
// ArrayOf returns the array type with the given count and element type.
// For example, if t represents int, ArrayOf(5, t) represents [5]int.
//
@ -2350,9 +2291,9 @@ func ArrayOf(count int, elem Type) Type {
panic("reflect.ArrayOf: array size would exceed virtual address space")
}
array.size = typ.size * uintptr(count)
// if count > 0 && typ.ptrdata != 0 {
// array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata
// }
if count > 0 && typ.ptrdata != 0 {
array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata
}
array.align = typ.align
array.fieldAlign = typ.fieldAlign
array.uncommonType = nil
@ -2364,41 +2305,111 @@ func ArrayOf(count int, elem Type) Type {
case typ.kind&kindNoPointers != 0 || array.size == 0:
// No pointers.
array.kind |= kindNoPointers
gc := [...]uintptr{array.size, _GC_END}
array.gc = unsafe.Pointer(&gc[0])
array.gcdata = nil
array.ptrdata = 0
case count == 1:
// In memory, 1-element array looks just like the element.
array.kind |= typ.kind & kindGCProg
array.gc = typ.gc
array.gcdata = typ.gcdata
array.ptrdata = typ.ptrdata
case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*ptrSize:
// Element is small with pointer mask; array is still small.
// Create direct pointer mask by turning each 1 bit in elem
// into count 1 bits in larger mask.
mask := make([]byte, (array.ptrdata/ptrSize+7)/8)
elemMask := (*[1 << 30]byte)(unsafe.Pointer(typ.gcdata))[:]
elemWords := typ.size / ptrSize
for j := uintptr(0); j < typ.ptrdata/ptrSize; j++ {
if (elemMask[j/8]>>(j%8))&1 != 0 {
for i := uintptr(0); i < array.len; i++ {
k := i*elemWords + j
mask[k/8] |= 1 << (k % 8)
}
}
}
array.gcdata = &mask[0]
default:
gc := []uintptr{array.size, _GC_ARRAY_START, 0, uintptr(count), typ.size}
gc = appendGCProgram(gc, typ, 0)
gc = append(gc, _GC_ARRAY_NEXT, _GC_END)
array.gc = unsafe.Pointer(&gc[0])
// Create program that emits one element
// and then repeats to make the array.
prog := []byte{0, 0, 0, 0} // will be length of prog
elemGC := (*[1 << 30]byte)(unsafe.Pointer(typ.gcdata))[:]
elemPtrs := typ.ptrdata / ptrSize
if typ.kind&kindGCProg == 0 {
// Element is small with pointer mask; use as literal bits.
mask := elemGC
// Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes).
var n uintptr
for n = elemPtrs; n > 120; n -= 120 {
prog = append(prog, 120)
prog = append(prog, mask[:15]...)
mask = mask[15:]
}
prog = append(prog, byte(n))
prog = append(prog, mask[:(n+7)/8]...)
} else {
// Element has GC program; emit one element.
elemProg := elemGC[4 : 4+*(*uint32)(unsafe.Pointer(&elemGC[0]))-1]
prog = append(prog, elemProg...)
}
// Pad from ptrdata to size.
elemWords := typ.size / ptrSize
if elemPtrs < elemWords {
// Emit literal 0 bit, then repeat as needed.
prog = append(prog, 0x01, 0x00)
if elemPtrs+1 < elemWords {
prog = append(prog, 0x81)
prog = appendVarint(prog, elemWords-elemPtrs-1)
}
}
// Repeat count-1 times.
if elemWords < 0x80 {
prog = append(prog, byte(elemWords|0x80))
} else {
prog = append(prog, 0x80)
prog = appendVarint(prog, elemWords)
}
prog = appendVarint(prog, uintptr(count)-1)
prog = append(prog, 0)
*(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
array.kind |= kindGCProg
array.gcdata = &prog[0]
array.ptrdata = array.size // overestimate but ok; must match program
}
array.kind &^= kindDirectIface
array.hashfn = func(p unsafe.Pointer, seed uintptr) uintptr {
ret := seed
for i := 0; i < count; i++ {
ret = typ.hashfn(p, ret)
p = unsafe.Pointer(uintptr(p) + typ.size)
esize := typ.size
if typ.equalfn == nil {
array.equalfn = nil
} else {
eequal := typ.equalfn
array.equalfn = func(p, q unsafe.Pointer) bool {
for i := 0; i < count; i++ {
pi := arrayAt(p, i, esize)
qi := arrayAt(q, i, esize)
if !eequal(pi, qi) {
return false
}
}
return true
}
return ret
}
array.equalfn = func(p1, p2 unsafe.Pointer) bool {
for i := 0; i < count; i++ {
if !typ.equalfn(p1, p2) {
return false
if typ.hashfn == nil {
array.hashfn = nil
} else {
ehash := typ.hashfn
array.hashfn = func(ptr unsafe.Pointer, seed uintptr) uintptr {
o := seed
for i := 0; i < count; i++ {
o = ehash(arrayAt(ptr, i, esize), o)
}
p1 = unsafe.Pointer(uintptr(p1) + typ.size)
p2 = unsafe.Pointer(uintptr(p2) + typ.size)
return o
}
return true
}
return cachePut(ckey, &array.rtype)

View File

@ -131,7 +131,7 @@ func c128hash(p unsafe.Pointer, h uintptr) uintptr {
return f64hash(unsafe.Pointer(&x[1]), f64hash(unsafe.Pointer(&x[0]), h))
}
func interhash(p unsafe.Pointer, h uintptr, size uintptr) uintptr {
func interhash(p unsafe.Pointer, h uintptr) uintptr {
a := (*iface)(p)
tab := a.tab
if tab == nil {
@ -199,10 +199,10 @@ func c128equal(p, q unsafe.Pointer) bool {
func strequal(p, q unsafe.Pointer) bool {
return *(*string)(p) == *(*string)(q)
}
func interequal(p, q unsafe.Pointer, size uintptr) bool {
func interequal(p, q unsafe.Pointer) bool {
return ifaceeq(*(*iface)(p), *(*iface)(q))
}
func nilinterequal(p, q unsafe.Pointer, size uintptr) bool {
func nilinterequal(p, q unsafe.Pointer) bool {
return efaceeq(*(*eface)(p), *(*eface)(q))
}
func efaceeq(x, y eface) bool {
@ -361,6 +361,34 @@ var _ = nilinterequal
var _ = pointerhash
var _ = pointerequal
// Testing adapters for hash quality tests (see hash_test.go)
func stringHash(s string, seed uintptr) uintptr {
return strhash(noescape(unsafe.Pointer(&s)), seed)
}
func bytesHash(b []byte, seed uintptr) uintptr {
s := (*slice)(unsafe.Pointer(&b))
return memhash(s.array, seed, uintptr(s.len))
}
func int32Hash(i uint32, seed uintptr) uintptr {
return memhash32(noescape(unsafe.Pointer(&i)), seed)
}
func int64Hash(i uint64, seed uintptr) uintptr {
return memhash64(noescape(unsafe.Pointer(&i)), seed)
}
func efaceHash(i interface{}, seed uintptr) uintptr {
return nilinterhash(noescape(unsafe.Pointer(&i)), seed)
}
func ifaceHash(i interface {
F()
}, seed uintptr) uintptr {
return interhash(noescape(unsafe.Pointer(&i)), seed)
}
const hashRandomBytes = sys.PtrSize / 4 * 64
// used in asm_{386,amd64}.s to seed the hash function

Some files were not shown because too many files have changed in this diff Show More