diff options
author | Carlos O'Donell <carlos@codesourcery.com> | 2006-12-14 20:31:09 +0000 |
---|---|---|
committer | Carlos O'Donell <carlos@codesourcery.com> | 2006-12-14 20:31:09 +0000 |
commit | 046131376113d0755313b63bed7eeb45451fead4 (patch) | |
tree | 17139168a345b7d46a3e87b5843bb2ca7f234d45 | |
parent | 0dcf6cf16c80da5f12f8dad96d71f585f08ee777 (diff) |
The following backport from mainline fixes PCH on i686-mingw32. It csl/sourcerygxx/3.4.4-32csl-gxxpro-3_4-branch
implements PCH on i686-mingw32 using CreateFileMapping and
MapViewOfFileEX.
There were 3 patches in this timeframe, one from Ian Taylor, one from
Richard Henderson, and one from Danny Smith. I am backporting the two
simpler changes. Richard's patch rewrites much of the PCH handling and
it is too risky. Instead I have cherry-picked the important pieces of
Richards patch which allow Danny's patch to work correctly.
The hook HOST_HOOKS_GT_PCH_USE_ADDRESS now returns 1, 0, or -1 on
successfully mapped file, did nothing, and failed.
On mailine a return of 0 means "I mapped memory but didn't load the
file". No target uses this return to mean that. So I used 0 to
mean "use the default behaviour." The documentation is changed to
indicate this.
The default host hook for gt_pch_get_address returns zero, and maintains
the same semantics as before e.g. it attempts an MMAP at a fixed address.
Relocation of a PCH is not permitted, so we use fatal_error if we detect
relocation is needed. We also remove all the old code which tries to
relocate and issues a sorry().
In review, the old behaviour is kept for all targets *except*
i686-mingw32 and darwin. These targets have been augmented based on the
new behaviour of HOST_HOOKS_GT_PCH_USE_ADDRESS.
2006-12-13 Carlos O'Donell <carlos@codesourcery.com>
gcc/
* hooks.c (hook_int_voidp_size_t_voidp_size_t_int_0): New function.
(hook_voidp_size_t_int_null): Likewise.
* hooks.h: Add new declarations.
* ggc.h: Likewise.
* hosthooks-def.h (HOST_HOOKS_GT_PCH_USE_ADDRESS): Default to
hook_int_voidp_size_t_voidp_size_t_int_0.
(HOST_HOOKS_GT_PCH_GET_ADDRESS): Default to
hook_voidp_size_t_int_null.
* gcc/doc/hostconfig.texi (HOST_HOOKS_GT_PCH_USE_ADDRESS): Adjust
documentation with respect to returning zero.
Backport from mainline:
gcc/
2004-06-05 Danny Smith <dannysmith@users.sourceforge.net>
* toplev.c (init_asm_output): Add explicit 'b' to mode when
opening asm_out_file.
* c-pch.c (c_common_write_pch): Remove unnecessary fflush before
reading asm_out_file. Replace fflush after reading asm_out_file
with fseek.
* hosthooks-def.h (HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY): Define
default and add to HOST_HOOKS_INITIALIZER.
* hosthooks.h (gt_pch_alloc_granularity): Declare hook function.
* ggc-common.c (default_gt_pch_alloc_granularity): New function.
(gt_pch_save): Use host_hooks.gt_pch_alloc_granularity
to set mmi.offset padding.
* config.gcc (i[34567]86-*-mingw32*): Set target_gtfiles to
$(srcdir)/config/i386/winnt.c.
(i[34567]86-*-pe | i[34567]86-*-cygwin*): Likewise.
(i[34567]86-*-uwin*): Likewise.
*i[34567]86-*-interix3*): Likewise.
* config.host (i[34567]86-*-mingw32*): Set out_host_hook_obj.
* config/i386/host-mingw32.c: New file.
* config/i386/x-mingw32: Add rule for host-mingw32.o.
* config/i386/winnt.c: (struct extern_list) Tag as GTY.
(extern_head): Likewise.
(struct export_list) Likewise.
(export_head): Likewise.
(i386_pe_record_external_function): Use ggc_alloc.
(i386_pe_record_exported_symbol): Likewise.
Include "gt-winnt.h" at end.
* doc/hostconfig.texi: Document
HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY.
2004-03-10 Richard Henderson <rth@redhat.com>
* c-pch.c (c_common_no_more_pch): Update for gt_pch_use_address
extra arguments.
* hosthooks.h (struct host_hooks): Update gt_pch_get_address
and gt_pch_use_address.
* doc/hostconfig.texi: Update docs.
* config/rs6000/host-darwin.c (darwin_rs6000_gt_pch_get_address):
Update for changed definition.
(darwin_rs6000_gt_pch_use_address): Likewise.
2004-03-04 Ian Lance Taylor <ian@wasabisystems.com>
* ggc-common.c (gt_pch_restore): Don't unmap addr unless we are
going to call mmap again. Read the file into the right place.
Give a fatal error if we have to relocate.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/csl-gxxpro-3_4-branch@119868 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | ChangeLog.csl | 61 | ||||
-rw-r--r-- | gcc/c-pch.c | 9 | ||||
-rw-r--r-- | gcc/config.gcc | 4 | ||||
-rw-r--r-- | gcc/config.host | 1 | ||||
-rw-r--r-- | gcc/config/i386/host-mingw32.c | 148 | ||||
-rw-r--r-- | gcc/config/i386/winnt.c | 14 | ||||
-rw-r--r-- | gcc/config/i386/x-mingw32 | 5 | ||||
-rw-r--r-- | gcc/config/rs6000/host-darwin.c | 39 | ||||
-rw-r--r-- | gcc/doc/hostconfig.texi | 51 | ||||
-rw-r--r-- | gcc/ggc-common.c | 101 | ||||
-rw-r--r-- | gcc/ggc.h | 3 | ||||
-rw-r--r-- | gcc/hooks.c | 19 | ||||
-rw-r--r-- | gcc/hooks.h | 2 | ||||
-rw-r--r-- | gcc/hosthooks-def.h | 12 | ||||
-rw-r--r-- | gcc/hosthooks.h | 8 | ||||
-rw-r--r-- | gcc/toplev.c | 2 |
16 files changed, 371 insertions, 108 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl index dc6ced6cae1..36bb969b135 100644 --- a/ChangeLog.csl +++ b/ChangeLog.csl @@ -1,3 +1,64 @@ +2006-12-13 Carlos O'Donell <carlos@codesourcery.com> + + gcc/ + * hooks.c (hook_int_voidp_size_t_voidp_size_t_int_0): New function. + (hook_voidp_size_t_int_null): Likewise. + * hooks.h: Add new declarations. + * ggc.h: Likewise. + * hosthooks-def.h (HOST_HOOKS_GT_PCH_USE_ADDRESS): Default to + hook_int_voidp_size_t_voidp_size_t_int_0. + (HOST_HOOKS_GT_PCH_GET_ADDRESS): Default to + hook_voidp_size_t_int_null. + * gcc/doc/hostconfig.texi (HOST_HOOKS_GT_PCH_USE_ADDRESS): Adjust + documentation with respect to returning zero. + + Backport from mainline: + gcc/ + 2004-06-05 Danny Smith <dannysmith@users.sourceforge.net> + * toplev.c (init_asm_output): Add explicit 'b' to mode when + opening asm_out_file. + * c-pch.c (c_common_write_pch): Remove unnecessary fflush before + reading asm_out_file. Replace fflush after reading asm_out_file + with fseek. + * hosthooks-def.h (HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY): Define + default and add to HOST_HOOKS_INITIALIZER. + * hosthooks.h (gt_pch_alloc_granularity): Declare hook function. + * ggc-common.c (default_gt_pch_alloc_granularity): New function. + (gt_pch_save): Use host_hooks.gt_pch_alloc_granularity + to set mmi.offset padding. + * config.gcc (i[34567]86-*-mingw32*): Set target_gtfiles to + $(srcdir)/config/i386/winnt.c. + (i[34567]86-*-pe | i[34567]86-*-cygwin*): Likewise. + (i[34567]86-*-uwin*): Likewise. + *i[34567]86-*-interix3*): Likewise. + * config.host (i[34567]86-*-mingw32*): Set out_host_hook_obj. + * config/i386/host-mingw32.c: New file. + * config/i386/x-mingw32: Add rule for host-mingw32.o. + * config/i386/winnt.c: (struct extern_list) Tag as GTY. + (extern_head): Likewise. + (struct export_list) Likewise. + (export_head): Likewise. + (i386_pe_record_external_function): Use ggc_alloc. + (i386_pe_record_exported_symbol): Likewise. + Include "gt-winnt.h" at end. + * doc/hostconfig.texi: Document + HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY. + + 2004-03-10 Richard Henderson <rth@redhat.com> + * c-pch.c (c_common_no_more_pch): Update for gt_pch_use_address + extra arguments. + * hosthooks.h (struct host_hooks): Update gt_pch_get_address + and gt_pch_use_address. + * doc/hostconfig.texi: Update docs. + * config/rs6000/host-darwin.c (darwin_rs6000_gt_pch_get_address): + Update for changed definition. + (darwin_rs6000_gt_pch_use_address): Likewise. + + 2004-03-04 Ian Lance Taylor <ian@wasabisystems.com> + * ggc-common.c (gt_pch_restore): Don't unmap addr unless we are + going to call mmap again. Read the file into the right place. + Give a fatal error if we have to relocate. + 2006-07-28 Carlos O'Donell <carlos@codesourcery.com> * gcc/config/mips/elf.h (MAX_OFILE_ALIGNMENT): Set to (65536*8). diff --git a/gcc/c-pch.c b/gcc/c-pch.c index 8e4b6024359..163682a25e9 100644 --- a/gcc/c-pch.c +++ b/gcc/c-pch.c @@ -181,7 +181,6 @@ c_common_write_pch (void) fatal_error ("can't write %s: %m", pch_file); buf = xmalloc (16384); - fflush (asm_out_file); if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0) fatal_error ("can't seek in %s: %m", asm_file_name); @@ -198,8 +197,10 @@ c_common_write_pch (void) written += size; } free (buf); - /* asm_out_file can be written afterwards, so must be flushed first. */ - fflush (asm_out_file); + /* asm_out_file can be written afterwards, so fseek to clear + _IOREAD flag. */ + if (fseek (asm_out_file, 0, SEEK_END) != 0) + fatal_error ("can't seek in %s: %m", asm_file_name); gt_pch_save (pch_outfile); cpp_write_pch_state (parse_in, pch_outfile); @@ -428,6 +429,6 @@ c_common_no_more_pch (void) if (cpp_get_callbacks (parse_in)->valid_pch) { cpp_get_callbacks (parse_in)->valid_pch = NULL; - host_hooks.gt_pch_use_address (NULL, 0); + host_hooks.gt_pch_use_address (NULL, 0, -1, 0); } } diff --git a/gcc/config.gcc b/gcc/config.gcc index 43d632c6f0d..cfd15c14359 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1197,6 +1197,7 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h" xm_file=i386/xm-cygwin.h tmake_file="i386/t-cygwin i386/t-cygming" + target_gtfiles="\$(srcdir)/config/i386/winnt.c" extra_objs=winnt.o c_target_objs=cygwin2.o cxx_target_objs=cygwin2.o @@ -1209,6 +1210,7 @@ i[34567]86-*-mingw32*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h" xm_file=i386/xm-mingw32.h tmake_file="i386/t-cygming i386/t-mingw32" + target_gtfiles="\$(srcdir)/config/i386/winnt.c" extra_objs=winnt.o extra_parts="crtbegin.o crtend.o" if test x$enable_threads = xyes; then @@ -1226,6 +1228,7 @@ i[34567]86-*-uwin*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygwin.h i386/uwin.h" tmake_file="i386/t-cygwin i386/t-uwin" extra_objs=winnt.o + target_gtfiles="\$(srcdir)/config/i386/winnt.c" if test x$enable_threads = xyes; then thread_file='win32' fi @@ -1235,6 +1238,7 @@ i[34567]86-*-interix3*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/i386-interix.h i386/i386-interix3.h interix.h interix3.h" tmake_file="i386/t-interix" extra_objs=winnt.o + target_gtfiles="\$(srcdir)/config/i386/winnt.c" if test x$enable_threads = xyes ; then thread_file='posix' fi diff --git a/gcc/config.host b/gcc/config.host index fa6bced73db..fbec42aa3d3 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -135,6 +135,7 @@ case ${host} in host_xm_file=i386/xm-mingw32.h host_xmake_file=i386/x-mingw32 host_exeext=.exe + out_host_hook_obj=host-mingw32.o ;; i[34567]86-*-uwin*) echo "*** UWIN may not be used as a host platform because" diff --git a/gcc/config/i386/host-mingw32.c b/gcc/config/i386/host-mingw32.c new file mode 100644 index 00000000000..0e3fdd7caf1 --- /dev/null +++ b/gcc/config/i386/host-mingw32.c @@ -0,0 +1,148 @@ +/* mingw32 host-specific hook definitions. + Copyright (C) 2004 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "hosthooks.h" +#include "hosthooks-def.h" +#include "toplev.h" +#include "diagnostic.h" + + +#define WIN32_LEAN_AND_MEAN /* Not so important if we have windows.h.gch. */ +#include <windows.h> + +static void * mingw32_gt_pch_get_address (size_t, int); +static int mingw32_gt_pch_use_address (void *, size_t, int, size_t); +static size_t mingw32_gt_pch_alloc_granularity (void); + +#undef HOST_HOOKS_GT_PCH_GET_ADDRESS +#define HOST_HOOKS_GT_PCH_GET_ADDRESS mingw32_gt_pch_get_address +#undef HOST_HOOKS_GT_PCH_USE_ADDRESS +#define HOST_HOOKS_GT_PCH_USE_ADDRESS mingw32_gt_pch_use_address +#undef HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY +#define HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY mingw32_gt_pch_alloc_granularity + +static inline void w32_error(const char*, const char*, int, const char*); + +/* FIXME: Is this big enough? */ +static const size_t pch_VA_max_size = 128 * 1024 * 1024; + +/* Granularity for reserving address space. */ +static const size_t va_granularity = 0x10000; + +/* Print out the GetLastError() translation. */ +static inline void +w32_error (const char* function, const char* file, int line, + const char* my_msg) +{ + LPSTR w32_msgbuf; + FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS + | FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR) &w32_msgbuf, 0, NULL); + fprintf(stderr, "internal error in %s, at %s:%d: %s: %s\n", + function, trim_filename (file), line, my_msg, w32_msgbuf); + LocalFree ((HLOCAL)w32_msgbuf); +} + +/* Granularity for reserving address space. */ +static size_t mingw32_gt_pch_alloc_granularity (void) +{ + return va_granularity; +} + +/* Identify an address that's likely to be free in a subsequent invocation + of the compiler. The area should be able to hold SIZE bytes. FD is an + open file descriptor if the host would like to probe with mmap. */ + +static void * +mingw32_gt_pch_get_address (size_t size, int fd ATTRIBUTE_UNUSED) +{ + void* res; + size = (size + va_granularity - 1) & ~(va_granularity - 1); + if (size > pch_VA_max_size) + return NULL; + + /* FIXME: We let system determine base by setting first arg to NULL. + Allocating at top of available address space avoids unnecessary + fragmentation of "ordinary" (malloc's) address space but may not be safe + with delayed load of system dll's. Preferred addresses for NT system + dlls is in 0x70000000 to 0x78000000 range. + If we allocate at bottom we need to reserve the address as early as possible + and at the same point in each invocation. */ + + res = VirtualAlloc (NULL, pch_VA_max_size, + MEM_RESERVE | MEM_TOP_DOWN, + PAGE_NOACCESS); + if (!res) + w32_error (__FUNCTION__, __FILE__, __LINE__, "VirtualAlloc"); + else + /* We do not need the address space for now, so free it. */ + VirtualFree (res, 0, MEM_RELEASE); + + return res; +} + +/* ADDR is an address returned by gt_pch_get_address. Attempt to allocate + SIZE bytes at the same address and load it with the data from FD at + OFFSET. Return -1 if we couldn't allocate memory at ADDR, return 0 + if the memory is allocated but the data not loaded, return 1 if done. */ + +static int +mingw32_gt_pch_use_address (void *addr, size_t size, int fd, + size_t offset) +{ + void * mmap_addr; + static HANDLE mmap_handle; + + if (size == 0) + return 0; + + /* Offset must be also be a multiple of allocation granularity for + this to work. We can't change the offset. */ + if ((offset & (va_granularity - 1)) != 0 || size > pch_VA_max_size) + return -1; + + mmap_handle = CreateFileMapping ((HANDLE) _get_osfhandle (fd), + NULL, PAGE_WRITECOPY | SEC_COMMIT, + 0, 0, NULL); + if (mmap_handle == NULL) + { + w32_error (__FUNCTION__, __FILE__, __LINE__, "CreateFileMapping"); + return -1; + } + mmap_addr = MapViewOfFileEx (mmap_handle, FILE_MAP_COPY, 0, offset, + size, addr); + if (mmap_addr != addr) + { + w32_error (__FUNCTION__, __FILE__, __LINE__, "MapViewOfFileEx"); + CloseHandle(mmap_handle); + return -1; + } + + return 1; +} + +const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index ec513b497af..e4d67466d9f 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -691,13 +691,13 @@ i386_pe_declare_function_type (FILE *file, const char *name, int public) /* Keep a list of external functions. */ -struct extern_list +struct extern_list GTY(()) { struct extern_list *next; const char *name; }; -static struct extern_list *extern_head; +static GTY(()) struct extern_list *extern_head; /* Assemble an external function reference. We need to keep a list of these, so that we can output the function types at the end of the @@ -710,7 +710,7 @@ i386_pe_record_external_function (const char *name) { struct extern_list *p; - p = (struct extern_list *) xmalloc (sizeof *p); + p = (struct extern_list *) ggc_alloc (sizeof *p); p->next = extern_head; p->name = name; extern_head = p; @@ -718,14 +718,14 @@ i386_pe_record_external_function (const char *name) /* Keep a list of exported symbols. */ -struct export_list +struct export_list GTY(()) { struct export_list *next; const char *name; int is_data; /* used to type tag exported symbols. */ }; -static struct export_list *export_head; +static GTY(()) struct export_list *export_head; /* Assemble an export symbol entry. We need to keep a list of these, so that we can output the export list at the end of the @@ -738,7 +738,7 @@ i386_pe_record_exported_symbol (const char *name, int is_data) { struct export_list *p; - p = (struct export_list *) xmalloc (sizeof *p); + p = (struct export_list *) ggc_alloc (sizeof *p); p->next = export_head; p->name = name; p->is_data = is_data; @@ -783,3 +783,5 @@ i386_pe_file_end (void) } } } + +#include "gt-winnt.h" diff --git a/gcc/config/i386/x-mingw32 b/gcc/config/i386/x-mingw32 index 04593aa727f..8b6a98565ef 100644 --- a/gcc/config/i386/x-mingw32 +++ b/gcc/config/i386/x-mingw32 @@ -2,3 +2,8 @@ # Make local_includedir relative to EXEC_PREFIX # local_includedir=$(libsubdir)/$(unlibsubdir)/..`echo $(exec_prefix) | sed -e 's|^$(prefix)||' -e 's|/[^/]*|/..|g'`/include + +host-mingw32.o : $(srcdir)/config/i386/host-mingw32.c $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h hosthooks.h hosthooks-def.h toplev.h diagnostic.h + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/i386/host-mingw32.c diff --git a/gcc/config/rs6000/host-darwin.c b/gcc/config/rs6000/host-darwin.c index 7e8055690e4..8922d0c7fb9 100644 --- a/gcc/config/rs6000/host-darwin.c +++ b/gcc/config/rs6000/host-darwin.c @@ -152,7 +152,7 @@ static char pch_address_space[1024*1024*1024] __attribute__((aligned (4096))); /* Return the address of the PCH address space, if the PCH will fit in it. */ static void * -darwin_rs6000_gt_pch_get_address (size_t sz) +darwin_rs6000_gt_pch_get_address (size_t sz, int fd ATTRIBUTE_UNUSED) { if (sz <= sizeof (pch_address_space)) return pch_address_space; @@ -163,27 +163,40 @@ darwin_rs6000_gt_pch_get_address (size_t sz) /* Check ADDR and SZ for validity, and deallocate (using munmap) that part of pch_address_space beyond SZ. */ -static bool -darwin_rs6000_gt_pch_use_address (void *addr, size_t sz) +static int +darwin_rs6000_gt_pch_use_address (void *addr, size_t sz, int fd, size_t offset) { const size_t pagesize = getpagesize(); - bool result; - - if ((size_t)pch_address_space % pagesize != 0 - || sizeof (pch_address_space) % pagesize != 0) - abort (); - - result = (addr == pch_address_space && sz <= sizeof (pch_address_space)); - if (! result) + void *mmap_result; + int ret; + + gcc_assert ((size_t)pch_address_space % pagesize == 0 + && sizeof (pch_address_space) % pagesize == 0); + + ret = (addr == pch_address_space && sz <= sizeof (pch_address_space)); + if (! ret) sz = 0; /* Round the size to a whole page size. Normally this is a no-op. */ sz = (sz + pagesize - 1) / pagesize * pagesize; if (munmap (pch_address_space + sz, sizeof (pch_address_space) - sz) != 0) - fatal_error ("couldn't unmap pch_address_space: %m\n"); + fatal_error ("couldn't unmap pch_address_space: %m"); + + if (ret) + { + mmap_result = mmap (addr, sz, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, + fd, off); + + /* The file might not be mmap-able. */ + ret = mmap_result != (void *) MAP_FAILED; + + /* Sanity check for broken MAP_FIXED. */ + gcc_assert (!ret || mmap_result == addr); + } - return result; + return ret; } const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; diff --git a/gcc/doc/hostconfig.texi b/gcc/doc/hostconfig.texi index 3a00f8858b6..27a2c597547 100644 --- a/gcc/doc/hostconfig.texi +++ b/gcc/doc/hostconfig.texi @@ -42,39 +42,42 @@ This host hook is used to set up handling for extra signals. The most common thing to do in this hook is to detect stack overflow. @end deftypefn -@deftypefn {Host Hook} void * HOST_HOOKS_GT_PCH_GET_ADDRESS (size_t @var{size}) -This host hook returns the address of some space in which a PCH may be -loaded with @samp{HOST_HOOKS_PCH_LOAD_PCH}. The space will need to -have @var{size} bytes. If insufficient space is available, -@samp{NULL} may be returned; the PCH machinery will try to find a -suitable address using a heuristic. - -The memory does not have to be available now. In fact, usually -@samp{HOST_HOOKS_PCH_LOAD_PCH} will already have been called. The memory -need only be available in future invocations of GCC. +@deftypefn {Host Hook} void * HOST_HOOKS_GT_PCH_GET_ADDRESS (size_t @var{size}, int @var{fd}) +This host hook returns the address of some space that is likely to be +free in some subsequent invocation of the compiler. We intend to load +the PCH data at this address such that the data need not be relocated. +The area should be able to hold @var{size} bytes. If the host uses +@code{mmap}, @var{fd} is an open file descriptor that can be used for +probing. @end deftypefn -@deftypefn {Host Hook} bool HOST_HOOKS_GT_PCH_USE_ADDRESS (size_t @var{size}, void * @var{address}) -This host hook is called when a PCH file is about to be loaded. If -@var{address} is the address that would have been returned by -@samp{HOST_HOOKS_PCH_MEMORY_ADDRESS}, and @var{size} is smaller than -the maximum than @samp{HOST_HOOKS_PCH_MEMORY_ADDRESS} would have -accepted, return true, otherwise return false. +@deftypefn {Host Hook} int HOST_HOOKS_GT_PCH_USE_ADDRESS (void * @var{address}, size_t @var{size}, int @var{fd}, size_t @var{offset}) +This host hook is called when a PCH file is about to be loaded. +We want to load @var{size} bytes from @var{fd} at @var{offset} +into memory at @var{address}. The given address will be the result of +a previous invocation of @code{HOST_HOOKS_GT_PCH_GET_ADDRESS}. +Return @minus{}1 if we couldn't allocate @var{size} bytes at @var{address}. +Return 0 if you want PCH to do the work. Return 1 if the hook has +performed everything. -In addition, free any address space reserved that isn't needed to hold -@var{size} bytes (whether or not true is returned). The PCH machinery will -use @samp{mmap} with @samp{MAP_FIXED} to load the PCH if @samp{HAVE_MMAP_FILE}, -or will use @samp{fread} otherwise. - -If no PCH will be loaded, this hook may be called with @var{size} -zero, in which case all reserved address space should be freed. +If the implementation uses reserved address space, free any reserved +space beyond @var{size}, regardless of the return value. If no PCH will +be loaded, this hook may be called with @var{size} zero, in which case +all reserved address space should be freed. Do not try to handle values of @var{address} that could not have been -returned by this executable; just return false. Such values usually +returned by this executable; just return @minus{}1. Such values usually indicate an out-of-date PCH file (built by some other GCC executable), and such a PCH file won't work. @end deftypefn +@deftypefn {Host Hook} size_t HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY (void); +This host hook returns the alignment required for allocating virtual +memory. Usually this is the same as getpagesize, but on some hosts the +alignment for reserving memory differs from the pagesize for committing +memory. +@end deftypefn + @node Filesystem @section Host Filesystem @cindex configuration file diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index ecd6624487c..57392388936 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -31,6 +31,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "params.h" #include "hosthooks.h" +#include <unistd.h> /* Required for getpagesize(). */ + #ifdef HAVE_SYS_RESOURCE_H # include <sys/resource.h> #endif @@ -417,6 +419,16 @@ struct mmap_info void *preferred_base; }; +/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS. Return the + alignment required for allocating virtual memory. Usually this is the + same as pagesize. */ + +size_t +default_gt_pch_alloc_granularity (void) +{ + return getpagesize(); +} + /* Write out the state of the compiler to F. */ void @@ -429,7 +441,7 @@ gt_pch_save (FILE *f) char *this_object = NULL; size_t this_object_size = 0; struct mmap_info mmi; - size_t page_size = getpagesize(); + const size_t mmap_offset_alignment = host_hooks.gt_pch_alloc_granularity(); gt_pch_save_stringpool (); @@ -458,7 +470,7 @@ gt_pch_save (FILE *f) and on the rest it's a lot of work to do better. (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and HOST_HOOKS_GT_PCH_USE_ADDRESS.) */ - mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size); + mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (state.f)); #if HAVE_MMAP_FILE if (mmi.preferred_base == NULL) @@ -492,14 +504,15 @@ gt_pch_save (FILE *f) ggc_pch_prepare_write (state.d, state.f); - /* Pad the PCH file so that the mmapped area starts on a page boundary. */ + /* Pad the PCH file so that the mmapped area starts on an allocation + granularity (usually page) boundary. */ { long o; o = ftell (state.f) + sizeof (mmi); if (o == -1) fatal_error ("can't get position in PCH file: %m"); - mmi.offset = page_size - o % page_size; - if (mmi.offset == page_size) + mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment; + if (mmi.offset == mmap_offset_alignment) mmi.offset = 0; mmi.offset += o; } @@ -548,6 +561,7 @@ gt_pch_restore (FILE *f) struct mmap_info mmi; void *addr; bool needs_read; + int result; /* Delete any deletable objects. This makes ggc_pch_read much faster, as it can be sure that no GCable objects remain other @@ -580,28 +594,16 @@ gt_pch_restore (FILE *f) if (fread (&mmi, sizeof (mmi), 1, f) != 1) fatal_error ("can't read PCH file: %m"); - if (host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size)) - { -#if HAVE_MMAP_FILE - void *mmap_result; - - mmap_result = mmap (mmi.preferred_base, mmi.size, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, - fileno (f), mmi.offset); + /* Set the default value of addr. */ + addr = mmi.preferred_base; + result = host_hooks.gt_pch_use_address (addr, mmi.size, fileno(f), + mmi.offset); - /* The file might not be mmap-able. */ - needs_read = mmap_result == (void *) MAP_FAILED; - - /* Sanity check for broken MAP_FIXED. */ - if (! needs_read && mmap_result != mmi.preferred_base) - abort (); -#else - needs_read = true; -#endif - addr = mmi.preferred_base; - } - else + if (result == 0) { + /* Default hook for gt_pch_use_address returns 0. + This if case is used by all targets, and mingw32 + if a failure occurs in gt_pch_use_address. */ #if HAVE_MMAP_FILE addr = mmap (mmi.preferred_base, mmi.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, @@ -613,9 +615,6 @@ gt_pch_restore (FILE *f) size_t page_size = getpagesize(); char one_byte; - if (addr != (void *) MAP_FAILED) - munmap (addr, mmi.size); - /* We really want to be mapped at mmi.preferred_base so we're going to resort to MAP_FIXED. But before, make sure that we can do so without destroying a @@ -632,25 +631,40 @@ gt_pch_restore (FILE *f) break; if (i >= mmi.size) - addr = mmap (mmi.preferred_base, mmi.size, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, - fileno (f), mmi.offset); + { + if (addr != (void *) MAP_FAILED) + munmap (addr, mmi.size); + + addr = mmap (mmi.preferred_base, mmi.size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, + fileno (f), mmi.offset); + } } #endif /* HAVE_MINCORE */ needs_read = addr == (void *) MAP_FAILED; #else /* HAVE_MMAP_FILE */ + + /* Mingw32 targets do all the work in gt_pch_use_address. + Should that fail we fallback to using xmalloc to setup + addr and attempt to read the file via needs_read. */ needs_read = true; #endif /* HAVE_MMAP_FILE */ + /* In all probability this will fail, since + addr != mmi.preferred_base. This is a last ditch attempt. */ if (needs_read) addr = xmalloc (mmi.size); } + /* PCH files cannot be relocated. */ + if (result == -1 || addr != mmi.preferred_base) + fatal_error ("had to relocate PCH"); + if (needs_read) { if (fseek (f, mmi.offset, SEEK_SET) != 0 - || fread (&mmi, mmi.size, 1, f) != 1) + || fread (addr, mmi.size, 1, f) != 1) fatal_error ("can't read PCH file: %m"); } else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0) @@ -658,29 +672,6 @@ gt_pch_restore (FILE *f) ggc_pch_read (f, addr); - if (addr != mmi.preferred_base) - { - for (rt = gt_ggc_rtab; *rt; rt++) - for (rti = *rt; rti->base != NULL; rti++) - for (i = 0; i < rti->nelt; i++) - { - char **ptr = (char **)((char *)rti->base + rti->stride * i); - if (*ptr != NULL) - *ptr += (size_t)addr - (size_t)mmi.preferred_base; - } - - for (rt = gt_pch_cache_rtab; *rt; rt++) - for (rti = *rt; rti->base != NULL; rti++) - for (i = 0; i < rti->nelt; i++) - { - char **ptr = (char **)((char *)rti->base + rti->stride * i); - if (*ptr != NULL) - *ptr += (size_t)addr - (size_t)mmi.preferred_base; - } - - sorry ("had to relocate PCH"); - } - gt_pch_restore_stringpool (); } diff --git a/gcc/ggc.h b/gcc/ggc.h index 8add2da33ba..4877ca059eb 100644 --- a/gcc/ggc.h +++ b/gcc/ggc.h @@ -261,6 +261,9 @@ extern size_t ggc_get_size (const void *); /* Write out all GCed objects to F. */ extern void gt_pch_save (FILE *f); +/* Default hook for granularity. */ +extern size_t default_gt_pch_alloc_granularity (void); + /* Read objects previously saved with gt_pch_save from F. */ extern void gt_pch_restore (FILE *f); diff --git a/gcc/hooks.c b/gcc/hooks.c index 271074957e9..1b2735fb91e 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -241,3 +241,22 @@ hook_constcharptr_tree_null (tree t ATTRIBUTE_UNUSED) { return NULL; } + +/* Generic hook that takes void, size_t, void, size_t, and return zero. */ +int +hook_int_voidp_size_t_voidp_size_t_int_0 (void * a ATTRIBUTE_UNUSED, + size_t b ATTRIBUTE_UNUSED, + void * c ATTRIBUTE_UNUSED, + size_t d ATTRIBUTE_UNUSED) +{ + return 0; +} + +/* Generic hook that takes size_t and int, and returns NULL. */ +void * +hook_voidp_size_t_int_null (size_t a ATTRIBUTE_UNUSED, + int b ATTRIBUTE_UNUSED) +{ + return NULL; +} + diff --git a/gcc/hooks.h b/gcc/hooks.h index 6f88563dc96..dad072f7a12 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -61,5 +61,7 @@ extern rtx hook_rtx_rtx_null (rtx); extern rtx hook_rtx_tree_int_null (tree, int); extern void * hook_voidp_size_t_null (size_t); extern bool hook_bool_voidp_size_t_false (void *, size_t); +extern int hook_int_voidp_size_t_voidp_size_t_int_0 (void *, size_t, void *, size_t); +extern void * hook_voidp_size_t_int_null (size_t, int); extern const char *hook_constcharptr_tree_null (tree); #endif diff --git a/gcc/hosthooks-def.h b/gcc/hosthooks-def.h index b1a41e72988..9c864024438 100644 --- a/gcc/hosthooks-def.h +++ b/gcc/hosthooks-def.h @@ -24,14 +24,20 @@ Boston, MA 02111-1307, USA. */ #include "hooks.h" #define HOST_HOOKS_EXTRA_SIGNALS hook_void_void -#define HOST_HOOKS_GT_PCH_GET_ADDRESS hook_voidp_size_t_null -#define HOST_HOOKS_GT_PCH_USE_ADDRESS hook_bool_voidp_size_t_false +#define HOST_HOOKS_GT_PCH_GET_ADDRESS hook_voidp_size_t_int_null +#define HOST_HOOKS_GT_PCH_USE_ADDRESS hook_int_voidp_size_t_voidp_size_t_int_0 + +#define HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY \ + default_gt_pch_alloc_granularity + +extern size_t default_gt_pch_alloc_granularity (void); /* The structure is defined in hosthooks.h. */ #define HOST_HOOKS_INITIALIZER { \ HOST_HOOKS_EXTRA_SIGNALS, \ HOST_HOOKS_GT_PCH_GET_ADDRESS, \ - HOST_HOOKS_GT_PCH_USE_ADDRESS \ + HOST_HOOKS_GT_PCH_USE_ADDRESS, \ + HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY \ } #endif /* GCC_HOST_HOOKS_DEF_H */ diff --git a/gcc/hosthooks.h b/gcc/hosthooks.h index bbc28f69d4d..da2b25ed28a 100644 --- a/gcc/hosthooks.h +++ b/gcc/hosthooks.h @@ -25,8 +25,12 @@ struct host_hooks { void (*extra_signals) (void); - void * (*gt_pch_get_address) (size_t); - bool (*gt_pch_use_address) (void *, size_t); + void * (*gt_pch_get_address) (size_t, int); + int (*gt_pch_use_address) (void *, size_t, FILE *, size_t); + + /* Return the alignment required for allocating virtual memory. Usually + this is the same as pagesize. */ + size_t (*gt_pch_alloc_granularity) (void); /* Whenever you add entries here, make sure you adjust hosthooks-def.h. */ }; diff --git a/gcc/toplev.c b/gcc/toplev.c index eb706fa3b6c..d9563770489 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -4039,7 +4039,7 @@ init_asm_output (const char *name) if (!strcmp (asm_file_name, "-")) asm_out_file = stdout; else - asm_out_file = fopen (asm_file_name, "w+"); + asm_out_file = fopen (asm_file_name, "w+b"); if (asm_out_file == 0) fatal_error ("can't open %s for writing: %m", asm_file_name); } |