From 09a07b3d2dc945c62af5d1b525a2a348cfc3ebff Mon Sep 17 00:00:00 2001
From: Iain Sandoe <iain@sandoe.co.uk>
Date: Mon, 6 Dec 2021 07:50:08 +0000
Subject: [PATCH] Darwin, PCH: Rework PCH hooks for relocatable implementation.

Now we have a relocatable PCH implementation we can revise the
hooks that find and use the mmapped memory.  Specifically, this
removes the extra checking and diagnostic output for cases that
were likely to fail in a non-relocatable scenario.

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>

gcc/ChangeLog:

	* config/host-darwin.c (SAFE_ALLOC_SIZE): Remove.
	(darwin_gt_pch_get_address): Rework for relocatable PCH.
	(darwin_gt_pch_use_address): Likewise.
---
 gcc/config/host-darwin.c | 89 +++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 51 deletions(-)

diff --git a/gcc/config/host-darwin.c b/gcc/config/host-darwin.c
index d3c2858c997..e5657fb6a28 100644
--- a/gcc/config/host-darwin.c
+++ b/gcc/config/host-darwin.c
@@ -33,29 +33,27 @@
    The spaces should all have 512Mb available c.f. PCH files for large
    C++ or Objective-C in the range of 150Mb for 64b hosts.
 
-   We also try to steer clear of places already used for sanitizers.  */
+   We also try to steer clear of places already used for sanitizers.
+
+   If the allocation fails at the 'ideal' address, we go with what the
+   kernel provides (there is more likelihood that we will need to relocate
+   on read in).  */
 
 #define PAGE_SZ 4096
 #if defined(__x86_64) && defined(__LP64__)
 # define TRY_EMPTY_VM_SPACE	0x180000000000ULL
-# define SAFE_ALLOC_SIZE	0x20000000
 #elif defined(__x86_64)
 # define TRY_EMPTY_VM_SPACE	0x00006fe00000ULL
-# define SAFE_ALLOC_SIZE	0x20000000
 #elif defined(__i386)
 # define TRY_EMPTY_VM_SPACE	0x00006fe00000ULL
-# define SAFE_ALLOC_SIZE	0x20000000
 #elif defined(__POWERPC__) && defined(__LP64__)
 # define TRY_EMPTY_VM_SPACE	0x180000000000ULL
-# define SAFE_ALLOC_SIZE	0x20000000
 #elif defined(__POWERPC__)
 # define TRY_EMPTY_VM_SPACE	0x00006fe00000ULL
-# define SAFE_ALLOC_SIZE	0x20000000
 #elif defined(__aarch64__)
 # undef PAGE_SZ
 # define PAGE_SZ 16384
 # define TRY_EMPTY_VM_SPACE	0x180000000000ULL
-# define SAFE_ALLOC_SIZE	0x20000000
 #else
 # error "unknown Darwin target"
 #endif
@@ -67,13 +65,7 @@
 void *
 darwin_gt_pch_get_address (size_t sz, int fd)
 {
-  if (sz > SAFE_ALLOC_SIZE)
-    {
-      error ("PCH memory request exceeds the available space");
-      return NULL;
-    }
-
-  /* Now try with the constraint that we really want this address...  */
+  /* First try with the constraint that we really want this address...  */
   void *addr = mmap ((void *)TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
 		     MAP_PRIVATE | MAP_FIXED, fd, 0);
 
@@ -86,47 +78,36 @@ darwin_gt_pch_get_address (size_t sz, int fd)
   if (addr == (void *) TRY_EMPTY_VM_SPACE)
     return addr;
 
-  warning (OPT_Winvalid_pch, "PCH memory [fixed at %p] is not available %m",
-	   (void *) TRY_EMPTY_VM_SPACE);
-
   /* OK try to find a space without the constraint.  */
   addr = mmap ((void *) TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
 	       MAP_PRIVATE, fd, 0);
 
-  /* If we failed this time, that means there is *no* large enough free
-     space.  */
-  if (addr == (void *) MAP_FAILED)
+  /* We return whatever the kernel gave us.  */
+  if (addr != (void *) MAP_FAILED)
     {
-      error ("no memory is available for PCH : %m");
-      return NULL;
+      /* Unmap the area before returning.  */
+      munmap (addr, sz);
+      return addr;
     }
 
-  /* Unmap the area before returning.  */
-  munmap (addr, sz);
-
-  /* If we got the exact area we requested, then that's great.  */
-  if (TRY_EMPTY_VM_SPACE && addr == (void *) TRY_EMPTY_VM_SPACE)
-    return addr;
-
-  warning (OPT_Winvalid_pch, "PCH memory at %p is not available",
-	  (void *) TRY_EMPTY_VM_SPACE);
-
-  /* Otherwise, we need to try again but put some buffer space first.  */
-  size_t buffer_size = 32 * 1024 * 1024;
+  /* Otherwise, try again but put some arbitrary buffer space first.  */
+  size_t buffer_size = 64 * 1024 * 1024;
   void *buffer = mmap (0, buffer_size, PROT_NONE,
 		       MAP_PRIVATE | MAP_ANON, -1, 0);
   addr = mmap ((void *)TRY_EMPTY_VM_SPACE, sz, PROT_READ | PROT_WRITE,
 		MAP_PRIVATE, fd, 0);
+
   if (buffer != (void *) MAP_FAILED)
     munmap (buffer, buffer_size);
 
+  /* If we failed this time, that means there is *no* large enough free
+     space.  */
   if (addr == (void *) MAP_FAILED)
     {
       error ("PCH memory not available %m");
       return NULL;
     }
 
-  warning (OPT_Winvalid_pch, "PCH memory at %p used instead", addr);
   munmap (addr, sz);
   return addr;
 }
@@ -147,9 +128,6 @@ darwin_gt_pch_use_address (void *&addr, size_t sz, int fd, size_t off)
     return -1;
 
   gcc_checking_assert (!(off % PAGE_SZ));
-  if (addr != (void *) TRY_EMPTY_VM_SPACE)
-    warning (OPT_Winvalid_pch, "PCH at %p does not use the default position",
-	     addr);
 
   /* Try to map the file with MAP_PRIVATE and FIXED.  */
   mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
@@ -159,25 +137,34 @@ darwin_gt_pch_use_address (void *&addr, size_t sz, int fd, size_t off)
   if (mapped_addr == addr)
     return 1;
 
-  warning (OPT_Winvalid_pch, "PCH private mmap of written position (%p)"
-	   " failed [errno %d] %m", addr, errno);
-
+  /* In theory, the only alternative to success for MAP_FIXED should be FAILED
+     however, there are some buggy earlier implementations that could return
+     an address.  */
   if (mapped_addr != (void *) MAP_FAILED)
     munmap (mapped_addr, sz);
 
-  /* Try to make an anonymous private mmap at the desired location.  */
+  /* Try to map the file with MAP_PRIVATE but let the kernel move it.  */
   mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
-		      MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, (off_t)0);
+		      MAP_PRIVATE, fd, (off_t) off);
 
-  if (mapped_addr != addr)
+  /* Hopefully, we succeed.  */
+  if (mapped_addr != (void *) MAP_FAILED)
     {
-      warning (OPT_Winvalid_pch, "PCH anon mmap at written position (%p)"
-	       " failed [errno %d] %m", addr, errno);
-      if (mapped_addr != (void *) MAP_FAILED)
-	    munmap (mapped_addr, sz);
-      return -1;
+      addr = mapped_addr;
+      return 1;
     }
 
+  /* Try to make an anonymous private mmap at the desired location in case
+     the problem is in mapping the file.  */
+  mapped_addr = mmap (addr, sz, PROT_READ | PROT_WRITE,
+		      MAP_PRIVATE | MAP_ANON, -1, (off_t)0);
+
+  /* If this fails, we are out of ideas (and maybe memory).  */
+  if (mapped_addr == (void *) MAP_FAILED)
+    return -1;
+
+  addr = mapped_addr;
+
   if (lseek (fd, off, SEEK_SET) == (off_t) -1)
     return -1;
 
@@ -185,10 +172,10 @@ darwin_gt_pch_use_address (void *&addr, size_t sz, int fd, size_t off)
     {
       ssize_t nbytes;
 
-      nbytes = read (fd, addr, MIN (sz, (size_t) -1 >> 1));
+      nbytes = read (fd, mapped_addr, MIN (sz, (size_t) -1 >> 1));
       if (nbytes <= 0)
 	return -1;
-      addr = (char *) addr + nbytes;
+      mapped_addr = (char *) mapped_addr + nbytes;
       sz -= nbytes;
     }
 
-- 
2.24.3 (Apple Git-128)

