Fix MSAN LLVM jit false positives

Unpoison all buffers we store to.

Bug: b/140204746
Change-Id: I211d799b294932affe82cb310ed02d0c0ed5149a
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/40908
Tested-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Reactor/LLVMJIT.cpp b/src/Reactor/LLVMJIT.cpp
index 1718957..29c29e1 100644
--- a/src/Reactor/LLVMJIT.cpp
+++ b/src/Reactor/LLVMJIT.cpp
@@ -48,6 +48,7 @@
 #include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Verifier.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetOptions.h"
@@ -74,6 +75,10 @@
 extern "C" void _chkstk();
 #endif
 
+#if __has_feature(memory_sanitizer)
+#	include <sanitizer/msan_interface.h>
+#endif
+
 namespace {
 
 // Cache provides a simple, thread-safe key-value store.
@@ -549,6 +554,9 @@
 			functions.emplace("sync_fetch_and_umax_4", reinterpret_cast<void *>(F::sync_fetch_and_umax_4));
 			functions.emplace("sync_fetch_and_umin_4", reinterpret_cast<void *>(F::sync_fetch_and_umin_4));
 #endif
+#if __has_feature(memory_sanitizer)
+			functions.emplace("msan_unpoison", reinterpret_cast<void *>(__msan_unpoison));
+#endif
 		}
 	};
 
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index d3d021d..7d154b8 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -1049,6 +1049,22 @@
 			auto elTy = T(type);
 			ASSERT(V(ptr)->getType()->getContainedType(0) == elTy);
 
+#if __has_feature(memory_sanitizer)
+			// Mark all memory writes as initialized by calling __msan_unpoison
+			{
+				// void __msan_unpoison(const volatile void *a, size_t size)
+				auto voidTy = ::llvm::Type::getVoidTy(jit->context);
+				auto i8Ty = ::llvm::Type::getInt8Ty(jit->context);
+				auto voidPtrTy = i8Ty->getPointerTo();
+				auto sizetTy = ::llvm::IntegerType::get(jit->context, sizeof(size_t) * 8);
+				auto funcTy = ::llvm::FunctionType::get(voidTy, { voidPtrTy, sizetTy }, false);
+				auto func = jit->module->getOrInsertFunction("__msan_unpoison", funcTy);
+				auto size = jit->module->getDataLayout().getTypeStoreSize(elTy);
+				jit->builder->CreateCall(func, { jit->builder->CreatePointerCast(V(ptr), voidPtrTy),
+				                                 ::llvm::ConstantInt::get(sizetTy, size) });
+			}
+#endif
+
 			if(!atomic)
 			{
 				jit->builder->CreateAlignedStore(V(value), V(ptr), alignment, isVolatile);