From 90aa6719a03ca37a01bf94240dbf02fb4b1eb3e0 Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Sat, 5 Jun 2004 07:28:27 +0000 Subject: toplev.c (init_asm_output): Add explicit 'b' to mode when opening asm_out_file. * 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. From-SVN: r82643 --- gcc/ChangeLog | 31 +++++++++ gcc/c-pch.c | 7 +- gcc/config.gcc | 4 ++ gcc/config.host | 1 + gcc/config/i386/host-mingw32.c | 148 +++++++++++++++++++++++++++++++++++++++++ gcc/config/i386/winnt.c | 14 ++-- gcc/config/i386/x-mingw32 | 5 ++ gcc/doc/hostconfig.texi | 7 ++ gcc/ggc-common.c | 19 ++++-- gcc/hosthooks-def.h | 7 +- gcc/hosthooks.h | 4 ++ gcc/toplev.c | 2 +- 12 files changed, 234 insertions(+), 15 deletions(-) create mode 100644 gcc/config/i386/host-mingw32.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 28e486c..4b1360a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2004-06-05 Danny Smith + + * 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-06-04 Bernardo Innocenti * config/m68k/m68k.h: Remove comments copied over from tm.texi. diff --git a/gcc/c-pch.c b/gcc/c-pch.c index 8e2e6f1..03cf3bf 100644 --- a/gcc/c-pch.c +++ b/gcc/c-pch.c @@ -194,7 +194,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); @@ -211,8 +210,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); diff --git a/gcc/config.gcc b/gcc/config.gcc index 67efab5..8bf7d0e 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1035,6 +1035,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 @@ -1047,6 +1048,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 if test x$enable_threads = xyes; then thread_file='win32' @@ -1063,6 +1065,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 @@ -1072,6 +1075,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 9734966..67a067c 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -143,6 +143,7 @@ case ${host} in host_xmake_file=i386/x-mingw32 host_exeext=.exe host_can_use_collect2=no + 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 0000000..0e3fdd7 --- /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 + +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 6196d32..0b51aa4 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -769,13 +769,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 @@ -788,7 +788,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; @@ -796,14 +796,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 @@ -816,7 +816,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; @@ -861,3 +861,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 04593aa..8b6a985 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/doc/hostconfig.texi b/gcc/doc/hostconfig.texi index c97b41b..a016e56 100644 --- a/gcc/doc/hostconfig.texi +++ b/gcc/doc/hostconfig.texi @@ -71,6 +71,13 @@ 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 4939cb6..cc0dc93 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -431,7 +431,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 (); @@ -481,14 +481,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; } @@ -612,6 +613,16 @@ default_gt_pch_use_address (void *base, size_t size, int fd ATTRIBUTE_UNUSED, return (addr == base) - 1; } +/* 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(); +} + #if HAVE_MMAP_FILE /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present. We temporarily allocate SIZE bytes, and let the kernel place the data diff --git a/gcc/hosthooks-def.h b/gcc/hosthooks-def.h index 81761f9..910f783 100644 --- a/gcc/hosthooks-def.h +++ b/gcc/hosthooks-def.h @@ -32,8 +32,12 @@ Boston, MA 02111-1307, USA. */ #define HOST_HOOKS_GT_PCH_USE_ADDRESS default_gt_pch_use_address #endif +#define HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY \ + default_gt_pch_alloc_granularity + extern void* default_gt_pch_get_address (size_t, int); extern int default_gt_pch_use_address (void *, size_t, int, size_t); +extern size_t default_gt_pch_alloc_granularity (void); extern void* mmap_gt_pch_get_address (size_t, int); extern int mmap_gt_pch_use_address (void *, size_t, int, size_t); @@ -41,7 +45,8 @@ extern int mmap_gt_pch_use_address (void *, size_t, int, size_t); #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 c8b7c0f..0ac89f5 100644 --- a/gcc/hosthooks.h +++ b/gcc/hosthooks.h @@ -36,6 +36,10 @@ struct host_hooks if the memory is allocated but the data not loaded, return 1 if done. */ int (*gt_pch_use_address) (void *addr, size_t size, int fd, size_t offset); + /* 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 afbdb5c..2741be5 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2039,7 +2039,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); } -- cgit v1.1