On Darwin ARM, memory needs special handling to do JIT. This patch expands
this handling to work properly for modifying stub functions, relocations
back to entry points after JIT compilation, etc..


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57013 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/System/Unix/Memory.inc b/lib/System/Unix/Memory.inc
index cf0157d..646311d 100644
--- a/lib/System/Unix/Memory.inc
+++ b/lib/System/Unix/Memory.inc
@@ -76,7 +76,7 @@
                                 (vm_size_t)(pageSize*NumPages), 0,
                                 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
   if (KERN_SUCCESS != kr) {
-    MakeErrMsg(ErrMsg, "vm_protect max RWX failed\n");
+    MakeErrMsg(ErrMsg, "vm_protect max RX failed\n");
     return sys::MemoryBlock();
   }
 
@@ -103,3 +103,27 @@
   return false;
 }
 
+bool llvm::sys::Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) {
+#if defined(__APPLE__) && defined(__arm__)
+  if (M.Address == 0 || M.Size == 0) return false;
+  sys::Memory::InvalidateInstructionCache(M.Address, M.Size);
+  kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
+    (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE);
+  return KERN_SUCCESS == kr;
+#else
+  return true;
+#endif
+}
+
+bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) {
+#if defined(__APPLE__) && defined(__arm__)
+  if (M.Address == 0 || M.Size == 0) return false;
+  sys::Memory::InvalidateInstructionCache(M.Address, M.Size);
+  kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
+    (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
+  return KERN_SUCCESS == kr;
+#else
+  return false;
+#endif
+}
+