Implement executable memory allocation for Subzero on Unix.

Change-Id: I82b6a3f5336ca64dea30a8d9541fcf43c7ead81a
Reviewed-on: https://swiftshader-review.googlesource.com/8373
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index aacec93..ab4c109 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -30,9 +30,13 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_os_ostream.h"
 
+#if defined(_WIN32)
 #define WIN32_LEAN_AND_MEAN
 #define NOMINMAX
 #include <Windows.h>
+#else
+#include <sys/mman.h>
+#endif
 
 #include <mutex>
 #include <limits>
@@ -292,12 +296,20 @@
 
 		T *allocate(size_type n)
 		{
-			return (T*)VirtualAlloc(NULL, sizeof(T) * n, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+			#if defined(_WIN32)
+				return (T*)VirtualAlloc(NULL, sizeof(T) * n, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+			#else
+				return (T*)mmap(nullptr, sizeof(T) * n, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+			#endif
 		}
 
 		void deallocate(T *p, size_type n)
 		{
-			VirtualFree(p, 0, MEM_RELEASE);
+			#if defined(_WIN32)
+				VirtualFree(p, 0, MEM_RELEASE);
+			#else
+				munmap(p, sizeof(T) * n);
+			#endif
 		}
 	};
 
@@ -315,11 +327,13 @@
 
 		virtual ~ELFMemoryStreamer()
 		{
-			if(buffer.size() != 0)
-			{
-				DWORD exeProtection;
-				VirtualProtect(&buffer[0], buffer.size(), oldProtection, &exeProtection);
-			}
+			#if defined(_WIN32)
+				if(buffer.size() != 0)
+				{
+					DWORD exeProtection;
+					VirtualProtect(&buffer[0], buffer.size(), oldProtection, &exeProtection);
+				}
+			#endif
 		}
 
 		void write8(uint8_t Value) override
@@ -353,8 +367,13 @@
 		{
 			if(!entry)
 			{
-				VirtualProtect(&buffer[0], buffer.size(), PAGE_EXECUTE_READWRITE, &oldProtection);
-				position = std::numeric_limits<std::size_t>::max();  // Can't stream more data after this
+				#if defined(_WIN32)
+					VirtualProtect(&buffer[0], buffer.size(), PAGE_EXECUTE_READWRITE, &oldProtection);
+				#else
+					mprotect(&buffer[0], buffer.size(), PROT_READ | PROT_WRITE | PROT_EXEC);
+				#endif
+
+				position = std::numeric_limits<std::size_t>::max();   // Can't stream more data after this
 
 				entry = loadImage(&buffer[0]);
 			}
@@ -366,7 +385,10 @@
 		void *entry;
 		std::vector<uint8_t, ExecutableAllocator<uint8_t>> buffer;
 		std::size_t position;
+
+		#if defined(_WIN32)
 		DWORD oldProtection;
+		#endif
 	};
 
 	Nucleus::Nucleus()