1169689Skan/* mingw32 host-specific hook definitions. 2169689Skan Copyright (C) 2004 Free Software Foundation, Inc. 3169689Skan 4169689Skan This file is part of GCC. 5169689Skan 6169689Skan GCC is free software; you can redistribute it and/or modify it 7169689Skan under the terms of the GNU General Public License as published 8169689Skan by the Free Software Foundation; either version 2, or (at your 9169689Skan option) any later version. 10169689Skan 11169689Skan GCC is distributed in the hope that it will be useful, but WITHOUT 12169689Skan ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13169689Skan or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14169689Skan License for more details. 15169689Skan 16169689Skan You should have received a copy of the GNU General Public License 17169689Skan along with GCC; see the file COPYING. If not, write to the 18169689Skan Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 19169689Skan MA 02110-1301, USA. */ 20169689Skan 21169689Skan#include "config.h" 22169689Skan#include "system.h" 23169689Skan#include "coretypes.h" 24169689Skan#include "hosthooks.h" 25169689Skan#include "hosthooks-def.h" 26169689Skan#include "toplev.h" 27169689Skan#include "diagnostic.h" 28169689Skan 29169689Skan 30169689Skan#define WIN32_LEAN_AND_MEAN /* Not so important if we have windows.h.gch. */ 31169689Skan#include <windows.h> 32169689Skan 33169689Skanstatic void * mingw32_gt_pch_get_address (size_t, int); 34169689Skanstatic int mingw32_gt_pch_use_address (void *, size_t, int, size_t); 35169689Skanstatic size_t mingw32_gt_pch_alloc_granularity (void); 36169689Skan 37169689Skan#undef HOST_HOOKS_GT_PCH_GET_ADDRESS 38169689Skan#define HOST_HOOKS_GT_PCH_GET_ADDRESS mingw32_gt_pch_get_address 39169689Skan#undef HOST_HOOKS_GT_PCH_USE_ADDRESS 40169689Skan#define HOST_HOOKS_GT_PCH_USE_ADDRESS mingw32_gt_pch_use_address 41169689Skan#undef HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY 42169689Skan#define HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY mingw32_gt_pch_alloc_granularity 43169689Skan 44169689Skanstatic inline void w32_error(const char*, const char*, int, const char*); 45169689Skan 46169689Skan/* FIXME: Is this big enough? */ 47169689Skanstatic const size_t pch_VA_max_size = 128 * 1024 * 1024; 48169689Skan 49169689Skan/* Granularity for reserving address space. */ 50169689Skanstatic const size_t va_granularity = 0x10000; 51169689Skan 52169689Skan/* Print out the GetLastError() translation. */ 53169689Skanstatic inline void 54169689Skanw32_error (const char* function, const char* file, int line, 55169689Skan const char* my_msg) 56169689Skan{ 57169689Skan LPSTR w32_msgbuf; 58169689Skan FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER 59169689Skan | FORMAT_MESSAGE_FROM_SYSTEM 60169689Skan | FORMAT_MESSAGE_IGNORE_INSERTS 61169689Skan | FORMAT_MESSAGE_MAX_WIDTH_MASK, 62169689Skan NULL, GetLastError(), 63169689Skan MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 64169689Skan (LPSTR) &w32_msgbuf, 0, NULL); 65169689Skan fprintf(stderr, "internal error in %s, at %s:%d: %s: %s\n", 66169689Skan function, trim_filename (file), line, my_msg, w32_msgbuf); 67169689Skan LocalFree ((HLOCAL)w32_msgbuf); 68169689Skan} 69169689Skan 70169689Skan/* Granularity for reserving address space. */ 71169689Skanstatic size_t mingw32_gt_pch_alloc_granularity (void) 72169689Skan{ 73169689Skan return va_granularity; 74169689Skan} 75169689Skan 76169689Skan/* Identify an address that's likely to be free in a subsequent invocation 77169689Skan of the compiler. The area should be able to hold SIZE bytes. FD is an 78169689Skan open file descriptor if the host would like to probe with mmap. */ 79169689Skan 80169689Skanstatic void * 81169689Skanmingw32_gt_pch_get_address (size_t size, int fd ATTRIBUTE_UNUSED) 82169689Skan{ 83169689Skan void* res; 84169689Skan size = (size + va_granularity - 1) & ~(va_granularity - 1); 85169689Skan if (size > pch_VA_max_size) 86169689Skan return NULL; 87169689Skan 88169689Skan /* FIXME: We let system determine base by setting first arg to NULL. 89169689Skan Allocating at top of available address space avoids unnecessary 90169689Skan fragmentation of "ordinary" (malloc's) address space but may not be safe 91169689Skan with delayed load of system dll's. Preferred addresses for NT system 92169689Skan dlls is in 0x70000000 to 0x78000000 range. 93169689Skan If we allocate at bottom we need to reserve the address as early as possible 94169689Skan and at the same point in each invocation. */ 95169689Skan 96169689Skan res = VirtualAlloc (NULL, pch_VA_max_size, 97169689Skan MEM_RESERVE | MEM_TOP_DOWN, 98169689Skan PAGE_NOACCESS); 99169689Skan if (!res) 100169689Skan w32_error (__FUNCTION__, __FILE__, __LINE__, "VirtualAlloc"); 101169689Skan else 102169689Skan /* We do not need the address space for now, so free it. */ 103169689Skan VirtualFree (res, 0, MEM_RELEASE); 104169689Skan 105169689Skan return res; 106169689Skan} 107169689Skan 108169689Skan/* ADDR is an address returned by gt_pch_get_address. Attempt to allocate 109169689Skan SIZE bytes at the same address and load it with the data from FD at 110169689Skan OFFSET. Return -1 if we couldn't allocate memory at ADDR, return 0 111169689Skan if the memory is allocated but the data not loaded, return 1 if done. */ 112169689Skan 113169689Skanstatic int 114169689Skanmingw32_gt_pch_use_address (void *addr, size_t size, int fd, 115169689Skan size_t offset) 116169689Skan{ 117169689Skan void * mmap_addr; 118169689Skan static HANDLE mmap_handle; 119169689Skan 120169689Skan if (size == 0) 121169689Skan return 0; 122169689Skan 123169689Skan /* Offset must be also be a multiple of allocation granularity for 124169689Skan this to work. We can't change the offset. */ 125169689Skan if ((offset & (va_granularity - 1)) != 0 || size > pch_VA_max_size) 126169689Skan return -1; 127169689Skan 128169689Skan mmap_handle = CreateFileMapping ((HANDLE) _get_osfhandle (fd), 129169689Skan NULL, PAGE_WRITECOPY | SEC_COMMIT, 130169689Skan 0, 0, NULL); 131169689Skan if (mmap_handle == NULL) 132169689Skan { 133169689Skan w32_error (__FUNCTION__, __FILE__, __LINE__, "CreateFileMapping"); 134169689Skan return -1; 135169689Skan } 136169689Skan mmap_addr = MapViewOfFileEx (mmap_handle, FILE_MAP_COPY, 0, offset, 137169689Skan size, addr); 138169689Skan if (mmap_addr != addr) 139169689Skan { 140169689Skan w32_error (__FUNCTION__, __FILE__, __LINE__, "MapViewOfFileEx"); 141169689Skan CloseHandle(mmap_handle); 142169689Skan return -1; 143169689Skan } 144169689Skan 145169689Skan return 1; 146169689Skan} 147169689Skan 148169689Skanconst struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; 149