aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@codesourcery.com>2006-12-14 20:31:09 +0000
committerCarlos O'Donell <carlos@codesourcery.com>2006-12-14 20:31:09 +0000
commit046131376113d0755313b63bed7eeb45451fead4 (patch)
tree17139168a345b7d46a3e87b5843bb2ca7f234d45
parent0dcf6cf16c80da5f12f8dad96d71f585f08ee777 (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.csl61
-rw-r--r--gcc/c-pch.c9
-rw-r--r--gcc/config.gcc4
-rw-r--r--gcc/config.host1
-rw-r--r--gcc/config/i386/host-mingw32.c148
-rw-r--r--gcc/config/i386/winnt.c14
-rw-r--r--gcc/config/i386/x-mingw325
-rw-r--r--gcc/config/rs6000/host-darwin.c39
-rw-r--r--gcc/doc/hostconfig.texi51
-rw-r--r--gcc/ggc-common.c101
-rw-r--r--gcc/ggc.h3
-rw-r--r--gcc/hooks.c19
-rw-r--r--gcc/hooks.h2
-rw-r--r--gcc/hosthooks-def.h12
-rw-r--r--gcc/hosthooks.h8
-rw-r--r--gcc/toplev.c2
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);
}