aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/i386/host-mingw32.c
diff options
context:
space:
mode:
authorBen Cheng <bccheng@google.com>2014-03-25 22:37:19 -0700
committerBen Cheng <bccheng@google.com>2014-03-25 22:37:19 -0700
commit1bc5aee63eb72b341f506ad058502cd0361f0d10 (patch)
treec607e8252f3405424ff15bc2d00aa38dadbb2518 /gcc-4.9/gcc/config/i386/host-mingw32.c
parent283a0bf58fcf333c58a2a92c3ebbc41fb9eb1fdb (diff)
downloadtoolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.gz
toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.bz2
toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.zip
Initial checkin of GCC 4.9.0 from trunk (r208799).
Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba
Diffstat (limited to 'gcc-4.9/gcc/config/i386/host-mingw32.c')
-rw-r--r--gcc-4.9/gcc/config/i386/host-mingw32.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/config/i386/host-mingw32.c b/gcc-4.9/gcc/config/i386/host-mingw32.c
new file mode 100644
index 000000000..fc01ceb24
--- /dev/null
+++ b/gcc-4.9/gcc/config/i386/host-mingw32.c
@@ -0,0 +1,198 @@
+/* mingw32 host-specific hook definitions.
+ Copyright (C) 2004-2014 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 3, 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 COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+#include "diagnostic.h"
+
+
+#define WIN32_LEAN_AND_MEAN /* Not so important if we have windows.h.gch. */
+#include <windows.h>
+#include <stdlib.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 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)
+{
+ SYSTEM_INFO si;
+
+ GetSystemInfo (&si);
+ va_granularity = (size_t) si.dwAllocationGranularity;
+
+ 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;
+ HANDLE mmap_handle;
+
+ /* Apparently, MS Vista puts unnamed file mapping objects into Global
+ namespace when running an application in a Terminal Server
+ session. This causes failure since, by default, applications
+ don't get SeCreateGlobalPrivilege. We don't need global
+ memory sharing so explicitly put object into Local namespace.
+
+ If multiple concurrent GCC processes are using PCH functionality,
+ MapViewOfFileEx returns "Access Denied" error. So we ensure the
+ session-wide mapping name is unique by appending process ID. */
+
+#define OBJECT_NAME_FMT "Local\\MinGWGCCPCH-"
+
+ char* object_name = NULL;
+ /* However, the documentation for CreateFileMapping says that on NT4
+ and earlier, backslashes are invalid in object name. So, we need
+ to check if we are on Windows2000 or higher. */
+ OSVERSIONINFO version_info;
+ int r;
+
+ version_info.dwOSVersionInfoSize = sizeof (version_info);
+
+ 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;
+
+
+ /* Determine the version of Windows we are running on and use a
+ uniquely-named local object if running > 4. */
+ GetVersionEx (&version_info);
+ if (version_info.dwMajorVersion > 4)
+ {
+ char local_object_name [sizeof (OBJECT_NAME_FMT)
+ + sizeof (DWORD) * 2];
+ snprintf (local_object_name, sizeof (local_object_name),
+ OBJECT_NAME_FMT "%lx", GetCurrentProcessId());
+ object_name = local_object_name;
+ }
+ mmap_handle = CreateFileMappingA ((HANDLE) _get_osfhandle (fd), NULL,
+ PAGE_WRITECOPY | SEC_COMMIT, 0, 0,
+ object_name);
+
+ if (mmap_handle == NULL)
+ {
+ w32_error (__FUNCTION__, __FILE__, __LINE__, "CreateFileMapping");
+ return -1;
+ }
+
+ /* Retry five times, as here might occure a race with multiple gcc's
+ instances at same time. */
+ for (r = 0; r < 5; r++)
+ {
+ mmap_addr = MapViewOfFileEx (mmap_handle, FILE_MAP_COPY, 0, offset,
+ size, addr);
+ if (mmap_addr == addr)
+ break;
+ if (r != 4)
+ Sleep (500);
+ }
+
+ 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;