Support MSAN with Subzero JIT compiled code.

MemorySanitizer doesn't automatically work with dynamically generated
code or inline assembly, since it can't instrument it to know what
memory it touches. We can help it by marking all the memory that is
written to by Reactor with the Subzero back-end as initialized by
calling __msan_unpoison.

Note that writes to memory don't guarantee proper initialization. It
could be copying or writing other uninitialized values.

See also https://sites.google.com/a/chromium.org/dev/developers/testing/memorysanitizer

Bug chromium:860533

Change-Id: Idf64e43c6ab9b8f71f64723fc7e3653f6ea2fb30
Reviewed-on: https://swiftshader-review.googlesource.com/19789
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Common/Memory.cpp b/src/Common/Memory.cpp
index 938223e..45fef40 100644
--- a/src/Common/Memory.cpp
+++ b/src/Common/Memory.cpp
@@ -234,9 +234,9 @@
 
 void clear(uint16_t *memory, uint16_t element, size_t count)
 {
-	#if defined(_MSC_VER) && defined(__x86__)
+	#if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
 		__stosw(memory, element, count);
-	#elif defined(__GNUC__) && defined(__x86__)
+	#elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
 		__asm__("rep stosw" : : "D"(memory), "a"(element), "c"(count));
 	#else
 		for(size_t i = 0; i < count; i++)
@@ -248,9 +248,9 @@
 
 void clear(uint32_t *memory, uint32_t element, size_t count)
 {
-	#if defined(_MSC_VER) && defined(__x86__)
+	#if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
 		__stosd((unsigned long*)memory, element, count);
-	#elif defined(__GNUC__) && defined(__x86__)
+	#elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
 		__asm__("rep stosl" : : "D"(memory), "a"(element), "c"(count));
 	#else
 		for(size_t i = 0; i < count; i++)
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 66099ec..e499496 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -26,6 +26,11 @@
 
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_os_ostream.h"
+#include "llvm/Support/Compiler.h"
+
+#if __has_feature(memory_sanitizer)
+#include <sanitizer/msan_interface.h>
+#endif
 
 #if defined(_WIN32)
 #ifndef WIN32_LEAN_AND_MEAN
@@ -894,6 +899,17 @@
 
 	Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int align)
 	{
+		#if __has_feature(memory_sanitizer)
+			// Mark all (non-stack) memory writes as initialized by calling __msan_unpoison
+			if(align != 0)
+			{
+				auto call = Ice::InstCall::create(::function, 2, nullptr, ::context->getConstantInt64(reinterpret_cast<intptr_t>(__msan_unpoison)), false);
+				call->addArg(ptr);
+				call->addArg(::context->getConstantInt64(typeSize(type)));
+				::basicBlock->appendInst(call);
+			}
+		#endif
+
 		int valueType = (int)reinterpret_cast<intptr_t>(type);
 
 		if((valueType & EmulatedBits) && (align != 0))   // Narrow vector not stored on stack.
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index c5417d9..4245cd4 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -141,13 +141,10 @@
 			return;
 		}
 
-		// The memory sanitizer doesn't work with JIT compiled code
-		#if !defined(MEMORY_SANITIZER)
-			if(blitReactor(source, sourceRect, dest, destRect, options))
-			{
-				return;
-			}
-		#endif
+		if(blitReactor(source, sourceRect, dest, destRect, options))
+		{
+			return;
+		}
 
 		SliceRectF sRect = sourceRect;
 		SliceRect dRect = destRect;