xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MemorySanitizer.cpp - detector of uninitialized reads --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file is a part of MemorySanitizer, a detector of uninitialized
110b57cec5SDimitry Andric /// reads.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric /// The algorithm of the tool is similar to Memcheck
14*0fca6ea1SDimitry Andric /// (https://static.usenix.org/event/usenix05/tech/general/full_papers/seward/seward_html/usenix2005.html)
15*0fca6ea1SDimitry Andric /// We associate a few shadow bits with every byte of the application memory,
16*0fca6ea1SDimitry Andric /// poison the shadow of the malloc-ed or alloca-ed memory, load the shadow,
17*0fca6ea1SDimitry Andric /// bits on every memory read, propagate the shadow bits through some of the
18*0fca6ea1SDimitry Andric /// arithmetic instruction (including MOV), store the shadow bits on every memory
190b57cec5SDimitry Andric /// write, report a bug on some other instructions (e.g. JMP) if the
200b57cec5SDimitry Andric /// associated shadow is poisoned.
210b57cec5SDimitry Andric ///
220b57cec5SDimitry Andric /// But there are differences too. The first and the major one:
230b57cec5SDimitry Andric /// compiler instrumentation instead of binary instrumentation. This
240b57cec5SDimitry Andric /// gives us much better register allocation, possible compiler
250b57cec5SDimitry Andric /// optimizations and a fast start-up. But this brings the major issue
260b57cec5SDimitry Andric /// as well: msan needs to see all program events, including system
270b57cec5SDimitry Andric /// calls and reads/writes in system libraries, so we either need to
280b57cec5SDimitry Andric /// compile *everything* with msan or use a binary translation
290b57cec5SDimitry Andric /// component (e.g. DynamoRIO) to instrument pre-built libraries.
300b57cec5SDimitry Andric /// Another difference from Memcheck is that we use 8 shadow bits per
310b57cec5SDimitry Andric /// byte of application memory and use a direct shadow mapping. This
320b57cec5SDimitry Andric /// greatly simplifies the instrumentation code and avoids races on
330b57cec5SDimitry Andric /// shadow updates (Memcheck is single-threaded so races are not a
340b57cec5SDimitry Andric /// concern there. Memcheck uses 2 shadow bits per byte with a slow
350b57cec5SDimitry Andric /// path storage that uses 8 bits per byte).
360b57cec5SDimitry Andric ///
370b57cec5SDimitry Andric /// The default value of shadow is 0, which means "clean" (not poisoned).
380b57cec5SDimitry Andric ///
390b57cec5SDimitry Andric /// Every module initializer should call __msan_init to ensure that the
400b57cec5SDimitry Andric /// shadow memory is ready. On error, __msan_warning is called. Since
410b57cec5SDimitry Andric /// parameters and return values may be passed via registers, we have a
420b57cec5SDimitry Andric /// specialized thread-local shadow for return values
430b57cec5SDimitry Andric /// (__msan_retval_tls) and parameters (__msan_param_tls).
440b57cec5SDimitry Andric ///
450b57cec5SDimitry Andric ///                           Origin tracking.
460b57cec5SDimitry Andric ///
470b57cec5SDimitry Andric /// MemorySanitizer can track origins (allocation points) of all uninitialized
480b57cec5SDimitry Andric /// values. This behavior is controlled with a flag (msan-track-origins) and is
490b57cec5SDimitry Andric /// disabled by default.
500b57cec5SDimitry Andric ///
510b57cec5SDimitry Andric /// Origins are 4-byte values created and interpreted by the runtime library.
520b57cec5SDimitry Andric /// They are stored in a second shadow mapping, one 4-byte value for 4 bytes
530b57cec5SDimitry Andric /// of application memory. Propagation of origins is basically a bunch of
540b57cec5SDimitry Andric /// "select" instructions that pick the origin of a dirty argument, if an
550b57cec5SDimitry Andric /// instruction has one.
560b57cec5SDimitry Andric ///
570b57cec5SDimitry Andric /// Every 4 aligned, consecutive bytes of application memory have one origin
580b57cec5SDimitry Andric /// value associated with them. If these bytes contain uninitialized data
590b57cec5SDimitry Andric /// coming from 2 different allocations, the last store wins. Because of this,
600b57cec5SDimitry Andric /// MemorySanitizer reports can show unrelated origins, but this is unlikely in
610b57cec5SDimitry Andric /// practice.
620b57cec5SDimitry Andric ///
630b57cec5SDimitry Andric /// Origins are meaningless for fully initialized values, so MemorySanitizer
640b57cec5SDimitry Andric /// avoids storing origin to memory when a fully initialized value is stored.
655ffd83dbSDimitry Andric /// This way it avoids needless overwriting origin of the 4-byte region on
660b57cec5SDimitry Andric /// a short (i.e. 1 byte) clean store, and it is also good for performance.
670b57cec5SDimitry Andric ///
680b57cec5SDimitry Andric ///                            Atomic handling.
690b57cec5SDimitry Andric ///
700b57cec5SDimitry Andric /// Ideally, every atomic store of application value should update the
710b57cec5SDimitry Andric /// corresponding shadow location in an atomic way. Unfortunately, atomic store
720b57cec5SDimitry Andric /// of two disjoint locations can not be done without severe slowdown.
730b57cec5SDimitry Andric ///
740b57cec5SDimitry Andric /// Therefore, we implement an approximation that may err on the safe side.
750b57cec5SDimitry Andric /// In this implementation, every atomically accessed location in the program
760b57cec5SDimitry Andric /// may only change from (partially) uninitialized to fully initialized, but
770b57cec5SDimitry Andric /// not the other way around. We load the shadow _after_ the application load,
780b57cec5SDimitry Andric /// and we store the shadow _before_ the app store. Also, we always store clean
790b57cec5SDimitry Andric /// shadow (if the application store is atomic). This way, if the store-load
800b57cec5SDimitry Andric /// pair constitutes a happens-before arc, shadow store and load are correctly
810b57cec5SDimitry Andric /// ordered such that the load will get either the value that was stored, or
820b57cec5SDimitry Andric /// some later value (which is always clean).
830b57cec5SDimitry Andric ///
840b57cec5SDimitry Andric /// This does not work very well with Compare-And-Swap (CAS) and
850b57cec5SDimitry Andric /// Read-Modify-Write (RMW) operations. To follow the above logic, CAS and RMW
860b57cec5SDimitry Andric /// must store the new shadow before the app operation, and load the shadow
870b57cec5SDimitry Andric /// after the app operation. Computers don't work this way. Current
880b57cec5SDimitry Andric /// implementation ignores the load aspect of CAS/RMW, always returning a clean
890b57cec5SDimitry Andric /// value. It implements the store part as a simple atomic store by storing a
900b57cec5SDimitry Andric /// clean shadow.
910b57cec5SDimitry Andric ///
920b57cec5SDimitry Andric ///                      Instrumenting inline assembly.
930b57cec5SDimitry Andric ///
940b57cec5SDimitry Andric /// For inline assembly code LLVM has little idea about which memory locations
950b57cec5SDimitry Andric /// become initialized depending on the arguments. It can be possible to figure
960b57cec5SDimitry Andric /// out which arguments are meant to point to inputs and outputs, but the
970b57cec5SDimitry Andric /// actual semantics can be only visible at runtime. In the Linux kernel it's
980b57cec5SDimitry Andric /// also possible that the arguments only indicate the offset for a base taken
990b57cec5SDimitry Andric /// from a segment register, so it's dangerous to treat any asm() arguments as
1000b57cec5SDimitry Andric /// pointers. We take a conservative approach generating calls to
1010b57cec5SDimitry Andric ///   __msan_instrument_asm_store(ptr, size)
1020b57cec5SDimitry Andric /// , which defer the memory unpoisoning to the runtime library.
1030b57cec5SDimitry Andric /// The latter can perform more complex address checks to figure out whether
1040b57cec5SDimitry Andric /// it's safe to touch the shadow memory.
1050b57cec5SDimitry Andric /// Like with atomic operations, we call __msan_instrument_asm_store() before
1060b57cec5SDimitry Andric /// the assembly call, so that changes to the shadow memory will be seen by
1070b57cec5SDimitry Andric /// other threads together with main memory initialization.
1080b57cec5SDimitry Andric ///
1090b57cec5SDimitry Andric ///                  KernelMemorySanitizer (KMSAN) implementation.
1100b57cec5SDimitry Andric ///
1110b57cec5SDimitry Andric /// The major differences between KMSAN and MSan instrumentation are:
1120b57cec5SDimitry Andric ///  - KMSAN always tracks the origins and implies msan-keep-going=true;
1130b57cec5SDimitry Andric ///  - KMSAN allocates shadow and origin memory for each page separately, so
1140b57cec5SDimitry Andric ///    there are no explicit accesses to shadow and origin in the
1150b57cec5SDimitry Andric ///    instrumentation.
1160b57cec5SDimitry Andric ///    Shadow and origin values for a particular X-byte memory location
1170b57cec5SDimitry Andric ///    (X=1,2,4,8) are accessed through pointers obtained via the
1180b57cec5SDimitry Andric ///      __msan_metadata_ptr_for_load_X(ptr)
1190b57cec5SDimitry Andric ///      __msan_metadata_ptr_for_store_X(ptr)
1200b57cec5SDimitry Andric ///    functions. The corresponding functions check that the X-byte accesses
1210b57cec5SDimitry Andric ///    are possible and returns the pointers to shadow and origin memory.
1220b57cec5SDimitry Andric ///    Arbitrary sized accesses are handled with:
1230b57cec5SDimitry Andric ///      __msan_metadata_ptr_for_load_n(ptr, size)
1240b57cec5SDimitry Andric ///      __msan_metadata_ptr_for_store_n(ptr, size);
12506c3fb27SDimitry Andric ///    Note that the sanitizer code has to deal with how shadow/origin pairs
12606c3fb27SDimitry Andric ///    returned by the these functions are represented in different ABIs. In
127*0fca6ea1SDimitry Andric ///    the X86_64 ABI they are returned in RDX:RAX, in PowerPC64 they are
128*0fca6ea1SDimitry Andric ///    returned in r3 and r4, and in the SystemZ ABI they are written to memory
129*0fca6ea1SDimitry Andric ///    pointed to by a hidden parameter.
1300b57cec5SDimitry Andric ///  - TLS variables are stored in a single per-task struct. A call to a
1310b57cec5SDimitry Andric ///    function __msan_get_context_state() returning a pointer to that struct
1320b57cec5SDimitry Andric ///    is inserted into every instrumented function before the entry block;
1330b57cec5SDimitry Andric ///  - __msan_warning() takes a 32-bit origin parameter;
1340b57cec5SDimitry Andric ///  - local variables are poisoned with __msan_poison_alloca() upon function
1350b57cec5SDimitry Andric ///    entry and unpoisoned with __msan_unpoison_alloca() before leaving the
1360b57cec5SDimitry Andric ///    function;
1370b57cec5SDimitry Andric ///  - the pass doesn't declare any global variables or add global constructors
1380b57cec5SDimitry Andric ///    to the translation unit.
1390b57cec5SDimitry Andric ///
1400b57cec5SDimitry Andric /// Also, KMSAN currently ignores uninitialized memory passed into inline asm
1410b57cec5SDimitry Andric /// calls, making sure we're on the safe side wrt. possible false positives.
1420b57cec5SDimitry Andric ///
143*0fca6ea1SDimitry Andric ///  KernelMemorySanitizer only supports X86_64, SystemZ and PowerPC64 at the
144*0fca6ea1SDimitry Andric ///  moment.
1450b57cec5SDimitry Andric ///
1465ffd83dbSDimitry Andric //
1475ffd83dbSDimitry Andric // FIXME: This sanitizer does not yet handle scalable vectors
1485ffd83dbSDimitry Andric //
1490b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
1520b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
1530b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
154bdd1243dSDimitry Andric #include "llvm/ADT/DenseMap.h"
1550b57cec5SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
156bdd1243dSDimitry Andric #include "llvm/ADT/SetVector.h"
157*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
1580b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
1590b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
1600b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
161bdd1243dSDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
1620b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
163e8d8bef9SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
1640b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
16506c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h"
1660b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
1670b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
1680b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
1690b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
1700b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
1710b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
1720b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
1730b57cec5SDimitry Andric #include "llvm/IR/Function.h"
1740b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
1750b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
1760b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
1770b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
1780b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h"
1790b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
1800b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
1810b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
1820b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
1830b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
184*0fca6ea1SDimitry Andric #include "llvm/IR/IntrinsicsAArch64.h"
185480093f4SDimitry Andric #include "llvm/IR/IntrinsicsX86.h"
1860b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h"
1870b57cec5SDimitry Andric #include "llvm/IR/Module.h"
1880b57cec5SDimitry Andric #include "llvm/IR/Type.h"
1890b57cec5SDimitry Andric #include "llvm/IR/Value.h"
1900b57cec5SDimitry Andric #include "llvm/IR/ValueMap.h"
1911fd87a68SDimitry Andric #include "llvm/Support/Alignment.h"
1920b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h"
1930b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
1940b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
1950b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
196bdd1243dSDimitry Andric #include "llvm/Support/DebugCounter.h"
1970b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1980b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
1990b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
20006c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
2010b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
2020b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
2030b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
2040b57cec5SDimitry Andric #include <algorithm>
2050b57cec5SDimitry Andric #include <cassert>
2060b57cec5SDimitry Andric #include <cstddef>
2070b57cec5SDimitry Andric #include <cstdint>
2080b57cec5SDimitry Andric #include <memory>
2090b57cec5SDimitry Andric #include <string>
2100b57cec5SDimitry Andric #include <tuple>
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric using namespace llvm;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric #define DEBUG_TYPE "msan"
2150b57cec5SDimitry Andric 
216bdd1243dSDimitry Andric DEBUG_COUNTER(DebugInsertCheck, "msan-insert-check",
217bdd1243dSDimitry Andric               "Controls which checks to insert");
218bdd1243dSDimitry Andric 
219*0fca6ea1SDimitry Andric DEBUG_COUNTER(DebugInstrumentInstruction, "msan-instrument-instruction",
220*0fca6ea1SDimitry Andric               "Controls which instruction to instrument");
221*0fca6ea1SDimitry Andric 
2220b57cec5SDimitry Andric static const unsigned kOriginSize = 4;
223480093f4SDimitry Andric static const Align kMinOriginAlignment = Align(4);
224480093f4SDimitry Andric static const Align kShadowTLSAlignment = Align(8);
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric // These constants must be kept in sync with the ones in msan.h.
2270b57cec5SDimitry Andric static const unsigned kParamTLSSize = 800;
2280b57cec5SDimitry Andric static const unsigned kRetvalTLSSize = 800;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric // Accesses sizes are powers of two: 1, 2, 4, 8.
2310b57cec5SDimitry Andric static const size_t kNumberOfAccessSizes = 4;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric /// Track origins of uninitialized values.
2340b57cec5SDimitry Andric ///
2350b57cec5SDimitry Andric /// Adds a section to MemorySanitizer report that points to the allocation
2360b57cec5SDimitry Andric /// (stack or heap) the uninitialized bits came from originally.
237bdd1243dSDimitry Andric static cl::opt<int> ClTrackOrigins(
238bdd1243dSDimitry Andric     "msan-track-origins",
239bdd1243dSDimitry Andric     cl::desc("Track origins (allocation sites) of poisoned memory"), cl::Hidden,
240bdd1243dSDimitry Andric     cl::init(0));
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric static cl::opt<bool> ClKeepGoing("msan-keep-going",
2430b57cec5SDimitry Andric                                  cl::desc("keep going after reporting a UMR"),
2440b57cec5SDimitry Andric                                  cl::Hidden, cl::init(false));
2450b57cec5SDimitry Andric 
246bdd1243dSDimitry Andric static cl::opt<bool>
247bdd1243dSDimitry Andric     ClPoisonStack("msan-poison-stack",
248bdd1243dSDimitry Andric                   cl::desc("poison uninitialized stack variables"), cl::Hidden,
249bdd1243dSDimitry Andric                   cl::init(true));
2500b57cec5SDimitry Andric 
251bdd1243dSDimitry Andric static cl::opt<bool> ClPoisonStackWithCall(
252bdd1243dSDimitry Andric     "msan-poison-stack-with-call",
253bdd1243dSDimitry Andric     cl::desc("poison uninitialized stack variables with a call"), cl::Hidden,
254bdd1243dSDimitry Andric     cl::init(false));
2550b57cec5SDimitry Andric 
256bdd1243dSDimitry Andric static cl::opt<int> ClPoisonStackPattern(
257bdd1243dSDimitry Andric     "msan-poison-stack-pattern",
2580b57cec5SDimitry Andric     cl::desc("poison uninitialized stack variables with the given pattern"),
2590b57cec5SDimitry Andric     cl::Hidden, cl::init(0xff));
2600b57cec5SDimitry Andric 
261bdd1243dSDimitry Andric static cl::opt<bool>
262bdd1243dSDimitry Andric     ClPrintStackNames("msan-print-stack-names",
263bdd1243dSDimitry Andric                       cl::desc("Print name of local stack variable"),
2640b57cec5SDimitry Andric                       cl::Hidden, cl::init(true));
2650b57cec5SDimitry Andric 
266bdd1243dSDimitry Andric static cl::opt<bool> ClPoisonUndef("msan-poison-undef",
267bdd1243dSDimitry Andric                                    cl::desc("poison undef temps"), cl::Hidden,
268bdd1243dSDimitry Andric                                    cl::init(true));
269bdd1243dSDimitry Andric 
270bdd1243dSDimitry Andric static cl::opt<bool>
271bdd1243dSDimitry Andric     ClHandleICmp("msan-handle-icmp",
2720b57cec5SDimitry Andric                  cl::desc("propagate shadow through ICmpEQ and ICmpNE"),
2730b57cec5SDimitry Andric                  cl::Hidden, cl::init(true));
2740b57cec5SDimitry Andric 
275bdd1243dSDimitry Andric static cl::opt<bool>
276bdd1243dSDimitry Andric     ClHandleICmpExact("msan-handle-icmp-exact",
2770b57cec5SDimitry Andric                       cl::desc("exact handling of relational integer ICmp"),
2780b57cec5SDimitry Andric                       cl::Hidden, cl::init(false));
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric static cl::opt<bool> ClHandleLifetimeIntrinsics(
2810b57cec5SDimitry Andric     "msan-handle-lifetime-intrinsics",
2820b57cec5SDimitry Andric     cl::desc(
2830b57cec5SDimitry Andric         "when possible, poison scoped variables at the beginning of the scope "
2840b57cec5SDimitry Andric         "(slower, but more precise)"),
2850b57cec5SDimitry Andric     cl::Hidden, cl::init(true));
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric // When compiling the Linux kernel, we sometimes see false positives related to
2880b57cec5SDimitry Andric // MSan being unable to understand that inline assembly calls may initialize
2890b57cec5SDimitry Andric // local variables.
2900b57cec5SDimitry Andric // This flag makes the compiler conservatively unpoison every memory location
2910b57cec5SDimitry Andric // passed into an assembly call. Note that this may cause false positives.
2920b57cec5SDimitry Andric // Because it's impossible to figure out the array sizes, we can only unpoison
2930b57cec5SDimitry Andric // the first sizeof(type) bytes for each type* pointer.
2940b57cec5SDimitry Andric static cl::opt<bool> ClHandleAsmConservative(
2950b57cec5SDimitry Andric     "msan-handle-asm-conservative",
2960b57cec5SDimitry Andric     cl::desc("conservative handling of inline assembly"), cl::Hidden,
2970b57cec5SDimitry Andric     cl::init(true));
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric // This flag controls whether we check the shadow of the address
3000b57cec5SDimitry Andric // operand of load or store. Such bugs are very rare, since load from
3010b57cec5SDimitry Andric // a garbage address typically results in SEGV, but still happen
3020b57cec5SDimitry Andric // (e.g. only lower bits of address are garbage, or the access happens
3030b57cec5SDimitry Andric // early at program startup where malloc-ed memory is more likely to
3040b57cec5SDimitry Andric // be zeroed. As of 2012-08-28 this flag adds 20% slowdown.
305bdd1243dSDimitry Andric static cl::opt<bool> ClCheckAccessAddress(
306bdd1243dSDimitry Andric     "msan-check-access-address",
3070b57cec5SDimitry Andric     cl::desc("report accesses through a pointer which has poisoned shadow"),
3080b57cec5SDimitry Andric     cl::Hidden, cl::init(true));
3090b57cec5SDimitry Andric 
3105ffd83dbSDimitry Andric static cl::opt<bool> ClEagerChecks(
3115ffd83dbSDimitry Andric     "msan-eager-checks",
3125ffd83dbSDimitry Andric     cl::desc("check arguments and return values at function call boundaries"),
3135ffd83dbSDimitry Andric     cl::Hidden, cl::init(false));
3145ffd83dbSDimitry Andric 
315bdd1243dSDimitry Andric static cl::opt<bool> ClDumpStrictInstructions(
316bdd1243dSDimitry Andric     "msan-dump-strict-instructions",
3170b57cec5SDimitry Andric     cl::desc("print out instructions with default strict semantics"),
3180b57cec5SDimitry Andric     cl::Hidden, cl::init(false));
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric static cl::opt<int> ClInstrumentationWithCallThreshold(
3210b57cec5SDimitry Andric     "msan-instrumentation-with-call-threshold",
3220b57cec5SDimitry Andric     cl::desc(
3230b57cec5SDimitry Andric         "If the function being instrumented requires more than "
3240b57cec5SDimitry Andric         "this number of checks and origin stores, use callbacks instead of "
3250b57cec5SDimitry Andric         "inline checks (-1 means never use callbacks)."),
3260b57cec5SDimitry Andric     cl::Hidden, cl::init(3500));
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric static cl::opt<bool>
3290b57cec5SDimitry Andric     ClEnableKmsan("msan-kernel",
3300b57cec5SDimitry Andric                   cl::desc("Enable KernelMemorySanitizer instrumentation"),
3310b57cec5SDimitry Andric                   cl::Hidden, cl::init(false));
3320b57cec5SDimitry Andric 
3330eae32dcSDimitry Andric static cl::opt<bool>
3340eae32dcSDimitry Andric     ClDisableChecks("msan-disable-checks",
3350eae32dcSDimitry Andric                     cl::desc("Apply no_sanitize to the whole file"), cl::Hidden,
3360eae32dcSDimitry Andric                     cl::init(false));
3370eae32dcSDimitry Andric 
338bdd1243dSDimitry Andric static cl::opt<bool>
339bdd1243dSDimitry Andric     ClCheckConstantShadow("msan-check-constant-shadow",
3400b57cec5SDimitry Andric                           cl::desc("Insert checks for constant shadow values"),
341bdd1243dSDimitry Andric                           cl::Hidden, cl::init(true));
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric // This is off by default because of a bug in gold:
3440b57cec5SDimitry Andric // https://sourceware.org/bugzilla/show_bug.cgi?id=19002
345bdd1243dSDimitry Andric static cl::opt<bool>
346bdd1243dSDimitry Andric     ClWithComdat("msan-with-comdat",
3470b57cec5SDimitry Andric                  cl::desc("Place MSan constructors in comdat sections"),
3480b57cec5SDimitry Andric                  cl::Hidden, cl::init(false));
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric // These options allow to specify custom memory map parameters
3510b57cec5SDimitry Andric // See MemoryMapParams for details.
3520b57cec5SDimitry Andric static cl::opt<uint64_t> ClAndMask("msan-and-mask",
3530b57cec5SDimitry Andric                                    cl::desc("Define custom MSan AndMask"),
3540b57cec5SDimitry Andric                                    cl::Hidden, cl::init(0));
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric static cl::opt<uint64_t> ClXorMask("msan-xor-mask",
3570b57cec5SDimitry Andric                                    cl::desc("Define custom MSan XorMask"),
3580b57cec5SDimitry Andric                                    cl::Hidden, cl::init(0));
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric static cl::opt<uint64_t> ClShadowBase("msan-shadow-base",
3610b57cec5SDimitry Andric                                       cl::desc("Define custom MSan ShadowBase"),
3620b57cec5SDimitry Andric                                       cl::Hidden, cl::init(0));
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric static cl::opt<uint64_t> ClOriginBase("msan-origin-base",
3650b57cec5SDimitry Andric                                       cl::desc("Define custom MSan OriginBase"),
3660b57cec5SDimitry Andric                                       cl::Hidden, cl::init(0));
3670b57cec5SDimitry Andric 
368bdd1243dSDimitry Andric static cl::opt<int>
369bdd1243dSDimitry Andric     ClDisambiguateWarning("msan-disambiguate-warning-threshold",
370bdd1243dSDimitry Andric                           cl::desc("Define threshold for number of checks per "
371bdd1243dSDimitry Andric                                    "debug location to force origin update."),
372bdd1243dSDimitry Andric                           cl::Hidden, cl::init(3));
373bdd1243dSDimitry Andric 
374e8d8bef9SDimitry Andric const char kMsanModuleCtorName[] = "msan.module_ctor";
375e8d8bef9SDimitry Andric const char kMsanInitName[] = "__msan_init";
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric namespace {
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric // Memory map parameters used in application-to-shadow address calculation.
3800b57cec5SDimitry Andric // Offset = (Addr & ~AndMask) ^ XorMask
3810b57cec5SDimitry Andric // Shadow = ShadowBase + Offset
3820b57cec5SDimitry Andric // Origin = OriginBase + Offset
3830b57cec5SDimitry Andric struct MemoryMapParams {
3840b57cec5SDimitry Andric   uint64_t AndMask;
3850b57cec5SDimitry Andric   uint64_t XorMask;
3860b57cec5SDimitry Andric   uint64_t ShadowBase;
3870b57cec5SDimitry Andric   uint64_t OriginBase;
3880b57cec5SDimitry Andric };
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric struct PlatformMemoryMapParams {
3910b57cec5SDimitry Andric   const MemoryMapParams *bits32;
3920b57cec5SDimitry Andric   const MemoryMapParams *bits64;
3930b57cec5SDimitry Andric };
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric } // end anonymous namespace
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric // i386 Linux
3980b57cec5SDimitry Andric static const MemoryMapParams Linux_I386_MemoryMapParams = {
3990b57cec5SDimitry Andric     0x000080000000, // AndMask
4000b57cec5SDimitry Andric     0,              // XorMask (not used)
4010b57cec5SDimitry Andric     0,              // ShadowBase (not used)
4020b57cec5SDimitry Andric     0x000040000000, // OriginBase
4030b57cec5SDimitry Andric };
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric // x86_64 Linux
4060b57cec5SDimitry Andric static const MemoryMapParams Linux_X86_64_MemoryMapParams = {
4070b57cec5SDimitry Andric     0,              // AndMask (not used)
4080b57cec5SDimitry Andric     0x500000000000, // XorMask
4090b57cec5SDimitry Andric     0,              // ShadowBase (not used)
4100b57cec5SDimitry Andric     0x100000000000, // OriginBase
4110b57cec5SDimitry Andric };
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric // mips64 Linux
4140b57cec5SDimitry Andric static const MemoryMapParams Linux_MIPS64_MemoryMapParams = {
4150b57cec5SDimitry Andric     0,              // AndMask (not used)
4160b57cec5SDimitry Andric     0x008000000000, // XorMask
4170b57cec5SDimitry Andric     0,              // ShadowBase (not used)
4180b57cec5SDimitry Andric     0x002000000000, // OriginBase
4190b57cec5SDimitry Andric };
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric // ppc64 Linux
4220b57cec5SDimitry Andric static const MemoryMapParams Linux_PowerPC64_MemoryMapParams = {
4230b57cec5SDimitry Andric     0xE00000000000, // AndMask
4240b57cec5SDimitry Andric     0x100000000000, // XorMask
4250b57cec5SDimitry Andric     0x080000000000, // ShadowBase
4260b57cec5SDimitry Andric     0x1C0000000000, // OriginBase
4270b57cec5SDimitry Andric };
4280b57cec5SDimitry Andric 
4295ffd83dbSDimitry Andric // s390x Linux
4305ffd83dbSDimitry Andric static const MemoryMapParams Linux_S390X_MemoryMapParams = {
4315ffd83dbSDimitry Andric     0xC00000000000, // AndMask
4325ffd83dbSDimitry Andric     0,              // XorMask (not used)
4335ffd83dbSDimitry Andric     0x080000000000, // ShadowBase
4345ffd83dbSDimitry Andric     0x1C0000000000, // OriginBase
4355ffd83dbSDimitry Andric };
4365ffd83dbSDimitry Andric 
4370b57cec5SDimitry Andric // aarch64 Linux
4380b57cec5SDimitry Andric static const MemoryMapParams Linux_AArch64_MemoryMapParams = {
4390b57cec5SDimitry Andric     0,               // AndMask (not used)
440bdd1243dSDimitry Andric     0x0B00000000000, // XorMask
4410b57cec5SDimitry Andric     0,               // ShadowBase (not used)
442bdd1243dSDimitry Andric     0x0200000000000, // OriginBase
4430b57cec5SDimitry Andric };
4440b57cec5SDimitry Andric 
44506c3fb27SDimitry Andric // loongarch64 Linux
44606c3fb27SDimitry Andric static const MemoryMapParams Linux_LoongArch64_MemoryMapParams = {
44706c3fb27SDimitry Andric     0,              // AndMask (not used)
44806c3fb27SDimitry Andric     0x500000000000, // XorMask
44906c3fb27SDimitry Andric     0,              // ShadowBase (not used)
45006c3fb27SDimitry Andric     0x100000000000, // OriginBase
45106c3fb27SDimitry Andric };
45206c3fb27SDimitry Andric 
453fcaf7f86SDimitry Andric // aarch64 FreeBSD
454fcaf7f86SDimitry Andric static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams = {
455fcaf7f86SDimitry Andric     0x1800000000000, // AndMask
456fcaf7f86SDimitry Andric     0x0400000000000, // XorMask
457fcaf7f86SDimitry Andric     0x0200000000000, // ShadowBase
458fcaf7f86SDimitry Andric     0x0700000000000, // OriginBase
459fcaf7f86SDimitry Andric };
460fcaf7f86SDimitry Andric 
4610b57cec5SDimitry Andric // i386 FreeBSD
4620b57cec5SDimitry Andric static const MemoryMapParams FreeBSD_I386_MemoryMapParams = {
4630b57cec5SDimitry Andric     0x000180000000, // AndMask
4640b57cec5SDimitry Andric     0x000040000000, // XorMask
4650b57cec5SDimitry Andric     0x000020000000, // ShadowBase
4660b57cec5SDimitry Andric     0x000700000000, // OriginBase
4670b57cec5SDimitry Andric };
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric // x86_64 FreeBSD
4700b57cec5SDimitry Andric static const MemoryMapParams FreeBSD_X86_64_MemoryMapParams = {
4710b57cec5SDimitry Andric     0xc00000000000, // AndMask
4720b57cec5SDimitry Andric     0x200000000000, // XorMask
4730b57cec5SDimitry Andric     0x100000000000, // ShadowBase
4740b57cec5SDimitry Andric     0x380000000000, // OriginBase
4750b57cec5SDimitry Andric };
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric // x86_64 NetBSD
4780b57cec5SDimitry Andric static const MemoryMapParams NetBSD_X86_64_MemoryMapParams = {
4790b57cec5SDimitry Andric     0,              // AndMask
4800b57cec5SDimitry Andric     0x500000000000, // XorMask
4810b57cec5SDimitry Andric     0,              // ShadowBase
4820b57cec5SDimitry Andric     0x100000000000, // OriginBase
4830b57cec5SDimitry Andric };
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric static const PlatformMemoryMapParams Linux_X86_MemoryMapParams = {
4860b57cec5SDimitry Andric     &Linux_I386_MemoryMapParams,
4870b57cec5SDimitry Andric     &Linux_X86_64_MemoryMapParams,
4880b57cec5SDimitry Andric };
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric static const PlatformMemoryMapParams Linux_MIPS_MemoryMapParams = {
4910b57cec5SDimitry Andric     nullptr,
4920b57cec5SDimitry Andric     &Linux_MIPS64_MemoryMapParams,
4930b57cec5SDimitry Andric };
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric static const PlatformMemoryMapParams Linux_PowerPC_MemoryMapParams = {
4960b57cec5SDimitry Andric     nullptr,
4970b57cec5SDimitry Andric     &Linux_PowerPC64_MemoryMapParams,
4980b57cec5SDimitry Andric };
4990b57cec5SDimitry Andric 
5005ffd83dbSDimitry Andric static const PlatformMemoryMapParams Linux_S390_MemoryMapParams = {
5015ffd83dbSDimitry Andric     nullptr,
5025ffd83dbSDimitry Andric     &Linux_S390X_MemoryMapParams,
5035ffd83dbSDimitry Andric };
5045ffd83dbSDimitry Andric 
5050b57cec5SDimitry Andric static const PlatformMemoryMapParams Linux_ARM_MemoryMapParams = {
5060b57cec5SDimitry Andric     nullptr,
5070b57cec5SDimitry Andric     &Linux_AArch64_MemoryMapParams,
5080b57cec5SDimitry Andric };
5090b57cec5SDimitry Andric 
51006c3fb27SDimitry Andric static const PlatformMemoryMapParams Linux_LoongArch_MemoryMapParams = {
51106c3fb27SDimitry Andric     nullptr,
51206c3fb27SDimitry Andric     &Linux_LoongArch64_MemoryMapParams,
51306c3fb27SDimitry Andric };
51406c3fb27SDimitry Andric 
515fcaf7f86SDimitry Andric static const PlatformMemoryMapParams FreeBSD_ARM_MemoryMapParams = {
516fcaf7f86SDimitry Andric     nullptr,
517fcaf7f86SDimitry Andric     &FreeBSD_AArch64_MemoryMapParams,
518fcaf7f86SDimitry Andric };
519fcaf7f86SDimitry Andric 
5200b57cec5SDimitry Andric static const PlatformMemoryMapParams FreeBSD_X86_MemoryMapParams = {
5210b57cec5SDimitry Andric     &FreeBSD_I386_MemoryMapParams,
5220b57cec5SDimitry Andric     &FreeBSD_X86_64_MemoryMapParams,
5230b57cec5SDimitry Andric };
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric static const PlatformMemoryMapParams NetBSD_X86_MemoryMapParams = {
5260b57cec5SDimitry Andric     nullptr,
5270b57cec5SDimitry Andric     &NetBSD_X86_64_MemoryMapParams,
5280b57cec5SDimitry Andric };
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric namespace {
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric /// Instrument functions of a module to detect uninitialized reads.
5330b57cec5SDimitry Andric ///
5340b57cec5SDimitry Andric /// Instantiating MemorySanitizer inserts the msan runtime library API function
5350b57cec5SDimitry Andric /// declarations into the module if they don't exist already. Instantiating
5360b57cec5SDimitry Andric /// ensures the __msan_init function is in the list of global constructors for
5370b57cec5SDimitry Andric /// the module.
5380b57cec5SDimitry Andric class MemorySanitizer {
5390b57cec5SDimitry Andric public:
5408bcb0991SDimitry Andric   MemorySanitizer(Module &M, MemorySanitizerOptions Options)
5418bcb0991SDimitry Andric       : CompileKernel(Options.Kernel), TrackOrigins(Options.TrackOrigins),
54204eeddc0SDimitry Andric         Recover(Options.Recover), EagerChecks(Options.EagerChecks) {
5430b57cec5SDimitry Andric     initializeModule(M);
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   // MSan cannot be moved or copied because of MapParams.
5470b57cec5SDimitry Andric   MemorySanitizer(MemorySanitizer &&) = delete;
5480b57cec5SDimitry Andric   MemorySanitizer &operator=(MemorySanitizer &&) = delete;
5490b57cec5SDimitry Andric   MemorySanitizer(const MemorySanitizer &) = delete;
5500b57cec5SDimitry Andric   MemorySanitizer &operator=(const MemorySanitizer &) = delete;
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   bool sanitizeFunction(Function &F, TargetLibraryInfo &TLI);
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric private:
5550b57cec5SDimitry Andric   friend struct MemorySanitizerVisitor;
5565f757f3fSDimitry Andric   friend struct VarArgHelperBase;
5570b57cec5SDimitry Andric   friend struct VarArgAMD64Helper;
5580b57cec5SDimitry Andric   friend struct VarArgMIPS64Helper;
5590b57cec5SDimitry Andric   friend struct VarArgAArch64Helper;
5600b57cec5SDimitry Andric   friend struct VarArgPowerPC64Helper;
5615ffd83dbSDimitry Andric   friend struct VarArgSystemZHelper;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   void initializeModule(Module &M);
564bdd1243dSDimitry Andric   void initializeCallbacks(Module &M, const TargetLibraryInfo &TLI);
565bdd1243dSDimitry Andric   void createKernelApi(Module &M, const TargetLibraryInfo &TLI);
566bdd1243dSDimitry Andric   void createUserspaceApi(Module &M, const TargetLibraryInfo &TLI);
5670b57cec5SDimitry Andric 
56806c3fb27SDimitry Andric   template <typename... ArgsTy>
56906c3fb27SDimitry Andric   FunctionCallee getOrInsertMsanMetadataFunction(Module &M, StringRef Name,
57006c3fb27SDimitry Andric                                                  ArgsTy... Args);
57106c3fb27SDimitry Andric 
5720b57cec5SDimitry Andric   /// True if we're compiling the Linux kernel.
5730b57cec5SDimitry Andric   bool CompileKernel;
5740b57cec5SDimitry Andric   /// Track origins (allocation points) of uninitialized values.
5750b57cec5SDimitry Andric   int TrackOrigins;
5760b57cec5SDimitry Andric   bool Recover;
57704eeddc0SDimitry Andric   bool EagerChecks;
5780b57cec5SDimitry Andric 
57906c3fb27SDimitry Andric   Triple TargetTriple;
5800b57cec5SDimitry Andric   LLVMContext *C;
5815f757f3fSDimitry Andric   Type *IntptrTy;  ///< Integer type with the size of a ptr in default AS.
5820b57cec5SDimitry Andric   Type *OriginTy;
5835f757f3fSDimitry Andric   PointerType *PtrTy; ///< Integer type with the size of a ptr in default AS.
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   // XxxTLS variables represent the per-thread state in MSan and per-task state
5860b57cec5SDimitry Andric   // in KMSAN.
5870b57cec5SDimitry Andric   // For the userspace these point to thread-local globals. In the kernel land
5880b57cec5SDimitry Andric   // they point to the members of a per-task struct obtained via a call to
5890b57cec5SDimitry Andric   // __msan_get_context_state().
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   /// Thread-local shadow storage for function parameters.
5920b57cec5SDimitry Andric   Value *ParamTLS;
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   /// Thread-local origin storage for function parameters.
5950b57cec5SDimitry Andric   Value *ParamOriginTLS;
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   /// Thread-local shadow storage for function return value.
5980b57cec5SDimitry Andric   Value *RetvalTLS;
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   /// Thread-local origin storage for function return value.
6010b57cec5SDimitry Andric   Value *RetvalOriginTLS;
6020b57cec5SDimitry Andric 
6035f757f3fSDimitry Andric   /// Thread-local shadow storage for in-register va_arg function.
6040b57cec5SDimitry Andric   Value *VAArgTLS;
6050b57cec5SDimitry Andric 
6065f757f3fSDimitry Andric   /// Thread-local shadow storage for in-register va_arg function.
6070b57cec5SDimitry Andric   Value *VAArgOriginTLS;
6080b57cec5SDimitry Andric 
6095f757f3fSDimitry Andric   /// Thread-local shadow storage for va_arg overflow area.
6100b57cec5SDimitry Andric   Value *VAArgOverflowSizeTLS;
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   /// Are the instrumentation callbacks set up?
6130b57cec5SDimitry Andric   bool CallbacksInitialized = false;
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   /// The run-time callback to print a warning.
6160b57cec5SDimitry Andric   FunctionCallee WarningFn;
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   // These arrays are indexed by log2(AccessSize).
6190b57cec5SDimitry Andric   FunctionCallee MaybeWarningFn[kNumberOfAccessSizes];
6200b57cec5SDimitry Andric   FunctionCallee MaybeStoreOriginFn[kNumberOfAccessSizes];
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   /// Run-time helper that generates a new origin value for a stack
6230b57cec5SDimitry Andric   /// allocation.
624bdd1243dSDimitry Andric   FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
625bdd1243dSDimitry Andric   // No description version
626bdd1243dSDimitry Andric   FunctionCallee MsanSetAllocaOriginNoDescriptionFn;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   /// Run-time helper that poisons stack on function entry.
6290b57cec5SDimitry Andric   FunctionCallee MsanPoisonStackFn;
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric   /// Run-time helper that records a store (or any event) of an
6320b57cec5SDimitry Andric   /// uninitialized value and returns an updated origin id encoding this info.
6330b57cec5SDimitry Andric   FunctionCallee MsanChainOriginFn;
6340b57cec5SDimitry Andric 
635e8d8bef9SDimitry Andric   /// Run-time helper that paints an origin over a region.
636e8d8bef9SDimitry Andric   FunctionCallee MsanSetOriginFn;
637e8d8bef9SDimitry Andric 
6380b57cec5SDimitry Andric   /// MSan runtime replacements for memmove, memcpy and memset.
6390b57cec5SDimitry Andric   FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   /// KMSAN callback for task-local function argument shadow.
6420b57cec5SDimitry Andric   StructType *MsanContextStateTy;
6430b57cec5SDimitry Andric   FunctionCallee MsanGetContextStateFn;
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   /// Functions for poisoning/unpoisoning local variables
6460b57cec5SDimitry Andric   FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;
6470b57cec5SDimitry Andric 
64806c3fb27SDimitry Andric   /// Pair of shadow/origin pointers.
64906c3fb27SDimitry Andric   Type *MsanMetadata;
65006c3fb27SDimitry Andric 
65106c3fb27SDimitry Andric   /// Each of the MsanMetadataPtrXxx functions returns a MsanMetadata.
6520b57cec5SDimitry Andric   FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;
6530b57cec5SDimitry Andric   FunctionCallee MsanMetadataPtrForLoad_1_8[4];
6540b57cec5SDimitry Andric   FunctionCallee MsanMetadataPtrForStore_1_8[4];
6550b57cec5SDimitry Andric   FunctionCallee MsanInstrumentAsmStoreFn;
6560b57cec5SDimitry Andric 
65706c3fb27SDimitry Andric   /// Storage for return values of the MsanMetadataPtrXxx functions.
65806c3fb27SDimitry Andric   Value *MsanMetadataAlloca;
65906c3fb27SDimitry Andric 
6600b57cec5SDimitry Andric   /// Helper to choose between different MsanMetadataPtrXxx().
6610b57cec5SDimitry Andric   FunctionCallee getKmsanShadowOriginAccessFn(bool isStore, int size);
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   /// Memory map parameters used in application-to-shadow calculation.
6640b57cec5SDimitry Andric   const MemoryMapParams *MapParams;
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   /// Custom memory map parameters used when -msan-shadow-base or
6670b57cec5SDimitry Andric   // -msan-origin-base is provided.
6680b57cec5SDimitry Andric   MemoryMapParams CustomMapParams;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   MDNode *ColdCallWeights;
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   /// Branch weights for origin store.
6730b57cec5SDimitry Andric   MDNode *OriginStoreWeights;
6740b57cec5SDimitry Andric };
6750b57cec5SDimitry Andric 
6768bcb0991SDimitry Andric void insertModuleCtor(Module &M) {
6778bcb0991SDimitry Andric   getOrCreateSanitizerCtorAndInitFunctions(
6788bcb0991SDimitry Andric       M, kMsanModuleCtorName, kMsanInitName,
6798bcb0991SDimitry Andric       /*InitArgTypes=*/{},
6808bcb0991SDimitry Andric       /*InitArgs=*/{},
6818bcb0991SDimitry Andric       // This callback is invoked when the functions are created the first
6828bcb0991SDimitry Andric       // time. Hook them into the global ctors list in that case:
6838bcb0991SDimitry Andric       [&](Function *Ctor, FunctionCallee) {
6848bcb0991SDimitry Andric         if (!ClWithComdat) {
6858bcb0991SDimitry Andric           appendToGlobalCtors(M, Ctor, 0);
6868bcb0991SDimitry Andric           return;
6878bcb0991SDimitry Andric         }
6888bcb0991SDimitry Andric         Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName);
6898bcb0991SDimitry Andric         Ctor->setComdat(MsanCtorComdat);
6908bcb0991SDimitry Andric         appendToGlobalCtors(M, Ctor, 0, Ctor);
6918bcb0991SDimitry Andric       });
6928bcb0991SDimitry Andric }
6938bcb0991SDimitry Andric 
6948bcb0991SDimitry Andric template <class T> T getOptOrDefault(const cl::opt<T> &Opt, T Default) {
6958bcb0991SDimitry Andric   return (Opt.getNumOccurrences() > 0) ? Opt : Default;
6968bcb0991SDimitry Andric }
6978bcb0991SDimitry Andric 
6980b57cec5SDimitry Andric } // end anonymous namespace
6990b57cec5SDimitry Andric 
70004eeddc0SDimitry Andric MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
70104eeddc0SDimitry Andric                                                bool EagerChecks)
7028bcb0991SDimitry Andric     : Kernel(getOptOrDefault(ClEnableKmsan, K)),
7038bcb0991SDimitry Andric       TrackOrigins(getOptOrDefault(ClTrackOrigins, Kernel ? 2 : TO)),
70404eeddc0SDimitry Andric       Recover(getOptOrDefault(ClKeepGoing, Kernel || R)),
70504eeddc0SDimitry Andric       EagerChecks(getOptOrDefault(ClEagerChecks, EagerChecks)) {}
7068bcb0991SDimitry Andric 
707bdd1243dSDimitry Andric PreservedAnalyses MemorySanitizerPass::run(Module &M,
708bdd1243dSDimitry Andric                                            ModuleAnalysisManager &AM) {
709bdd1243dSDimitry Andric   bool Modified = false;
710bdd1243dSDimitry Andric   if (!Options.Kernel) {
711bdd1243dSDimitry Andric     insertModuleCtor(M);
712bdd1243dSDimitry Andric     Modified = true;
7130b57cec5SDimitry Andric   }
7140b57cec5SDimitry Andric 
715bdd1243dSDimitry Andric   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
716bdd1243dSDimitry Andric   for (Function &F : M) {
717bdd1243dSDimitry Andric     if (F.empty())
718bdd1243dSDimitry Andric       continue;
719bdd1243dSDimitry Andric     MemorySanitizer Msan(*F.getParent(), Options);
720bdd1243dSDimitry Andric     Modified |=
721bdd1243dSDimitry Andric         Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
722bdd1243dSDimitry Andric   }
723bdd1243dSDimitry Andric 
724bdd1243dSDimitry Andric   if (!Modified)
7258bcb0991SDimitry Andric     return PreservedAnalyses::all();
726bdd1243dSDimitry Andric 
727bdd1243dSDimitry Andric   PreservedAnalyses PA = PreservedAnalyses::none();
728bdd1243dSDimitry Andric   // GlobalsAA is considered stateless and does not get invalidated unless
729bdd1243dSDimitry Andric   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
730bdd1243dSDimitry Andric   // make changes that require GlobalsAA to be invalidated.
731bdd1243dSDimitry Andric   PA.abandon<GlobalsAA>();
732bdd1243dSDimitry Andric   return PA;
7338bcb0991SDimitry Andric }
7348bcb0991SDimitry Andric 
735349cc55cSDimitry Andric void MemorySanitizerPass::printPipeline(
736349cc55cSDimitry Andric     raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
737349cc55cSDimitry Andric   static_cast<PassInfoMixin<MemorySanitizerPass> *>(this)->printPipeline(
738349cc55cSDimitry Andric       OS, MapClassName2PassName);
73906c3fb27SDimitry Andric   OS << '<';
740349cc55cSDimitry Andric   if (Options.Recover)
741349cc55cSDimitry Andric     OS << "recover;";
742349cc55cSDimitry Andric   if (Options.Kernel)
743349cc55cSDimitry Andric     OS << "kernel;";
74404eeddc0SDimitry Andric   if (Options.EagerChecks)
74504eeddc0SDimitry Andric     OS << "eager-checks;";
746349cc55cSDimitry Andric   OS << "track-origins=" << Options.TrackOrigins;
74706c3fb27SDimitry Andric   OS << '>';
748349cc55cSDimitry Andric }
749349cc55cSDimitry Andric 
7500b57cec5SDimitry Andric /// Create a non-const global initialized with the given string.
7510b57cec5SDimitry Andric ///
7520b57cec5SDimitry Andric /// Creates a writable global for Str so that we can pass it to the
7530b57cec5SDimitry Andric /// run-time lib. Runtime uses first 4 bytes of the string to store the
7540b57cec5SDimitry Andric /// frame ID, so the string needs to be mutable.
755bdd1243dSDimitry Andric static GlobalVariable *createPrivateConstGlobalForString(Module &M,
7560b57cec5SDimitry Andric                                                          StringRef Str) {
7570b57cec5SDimitry Andric   Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str);
758bdd1243dSDimitry Andric   return new GlobalVariable(M, StrConst->getType(), /*isConstant=*/true,
7590b57cec5SDimitry Andric                             GlobalValue::PrivateLinkage, StrConst, "");
7600b57cec5SDimitry Andric }
7610b57cec5SDimitry Andric 
76206c3fb27SDimitry Andric template <typename... ArgsTy>
76306c3fb27SDimitry Andric FunctionCallee
76406c3fb27SDimitry Andric MemorySanitizer::getOrInsertMsanMetadataFunction(Module &M, StringRef Name,
76506c3fb27SDimitry Andric                                                  ArgsTy... Args) {
76606c3fb27SDimitry Andric   if (TargetTriple.getArch() == Triple::systemz) {
76706c3fb27SDimitry Andric     // SystemZ ABI: shadow/origin pair is returned via a hidden parameter.
76806c3fb27SDimitry Andric     return M.getOrInsertFunction(Name, Type::getVoidTy(*C),
76906c3fb27SDimitry Andric                                  PointerType::get(MsanMetadata, 0),
77006c3fb27SDimitry Andric                                  std::forward<ArgsTy>(Args)...);
77106c3fb27SDimitry Andric   }
77206c3fb27SDimitry Andric 
77306c3fb27SDimitry Andric   return M.getOrInsertFunction(Name, MsanMetadata,
77406c3fb27SDimitry Andric                                std::forward<ArgsTy>(Args)...);
77506c3fb27SDimitry Andric }
77606c3fb27SDimitry Andric 
7770b57cec5SDimitry Andric /// Create KMSAN API callbacks.
778bdd1243dSDimitry Andric void MemorySanitizer::createKernelApi(Module &M, const TargetLibraryInfo &TLI) {
7790b57cec5SDimitry Andric   IRBuilder<> IRB(*C);
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   // These will be initialized in insertKmsanPrologue().
7820b57cec5SDimitry Andric   RetvalTLS = nullptr;
7830b57cec5SDimitry Andric   RetvalOriginTLS = nullptr;
7840b57cec5SDimitry Andric   ParamTLS = nullptr;
7850b57cec5SDimitry Andric   ParamOriginTLS = nullptr;
7860b57cec5SDimitry Andric   VAArgTLS = nullptr;
7870b57cec5SDimitry Andric   VAArgOriginTLS = nullptr;
7880b57cec5SDimitry Andric   VAArgOverflowSizeTLS = nullptr;
7890b57cec5SDimitry Andric 
790bdd1243dSDimitry Andric   WarningFn = M.getOrInsertFunction("__msan_warning",
791bdd1243dSDimitry Andric                                     TLI.getAttrList(C, {0}, /*Signed=*/false),
792bdd1243dSDimitry Andric                                     IRB.getVoidTy(), IRB.getInt32Ty());
793bdd1243dSDimitry Andric 
7940b57cec5SDimitry Andric   // Requests the per-task context state (kmsan_context_state*) from the
7950b57cec5SDimitry Andric   // runtime library.
7960b57cec5SDimitry Andric   MsanContextStateTy = StructType::get(
7970b57cec5SDimitry Andric       ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8),
7980b57cec5SDimitry Andric       ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8),
7990b57cec5SDimitry Andric       ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8),
8000b57cec5SDimitry Andric       ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), /* va_arg_origin */
8010b57cec5SDimitry Andric       IRB.getInt64Ty(), ArrayType::get(OriginTy, kParamTLSSize / 4), OriginTy,
8020b57cec5SDimitry Andric       OriginTy);
8030b57cec5SDimitry Andric   MsanGetContextStateFn = M.getOrInsertFunction(
8040b57cec5SDimitry Andric       "__msan_get_context_state", PointerType::get(MsanContextStateTy, 0));
8050b57cec5SDimitry Andric 
80606c3fb27SDimitry Andric   MsanMetadata = StructType::get(PointerType::get(IRB.getInt8Ty(), 0),
8070b57cec5SDimitry Andric                                  PointerType::get(IRB.getInt32Ty(), 0));
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric   for (int ind = 0, size = 1; ind < 4; ind++, size <<= 1) {
8100b57cec5SDimitry Andric     std::string name_load =
8110b57cec5SDimitry Andric         "__msan_metadata_ptr_for_load_" + std::to_string(size);
8120b57cec5SDimitry Andric     std::string name_store =
8130b57cec5SDimitry Andric         "__msan_metadata_ptr_for_store_" + std::to_string(size);
81406c3fb27SDimitry Andric     MsanMetadataPtrForLoad_1_8[ind] = getOrInsertMsanMetadataFunction(
81506c3fb27SDimitry Andric         M, name_load, PointerType::get(IRB.getInt8Ty(), 0));
81606c3fb27SDimitry Andric     MsanMetadataPtrForStore_1_8[ind] = getOrInsertMsanMetadataFunction(
81706c3fb27SDimitry Andric         M, name_store, PointerType::get(IRB.getInt8Ty(), 0));
8180b57cec5SDimitry Andric   }
8190b57cec5SDimitry Andric 
82006c3fb27SDimitry Andric   MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(
82106c3fb27SDimitry Andric       M, "__msan_metadata_ptr_for_load_n", PointerType::get(IRB.getInt8Ty(), 0),
82206c3fb27SDimitry Andric       IRB.getInt64Ty());
82306c3fb27SDimitry Andric   MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(
82406c3fb27SDimitry Andric       M, "__msan_metadata_ptr_for_store_n",
8250b57cec5SDimitry Andric       PointerType::get(IRB.getInt8Ty(), 0), IRB.getInt64Ty());
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   // Functions for poisoning and unpoisoning memory.
8285f757f3fSDimitry Andric   MsanPoisonAllocaFn = M.getOrInsertFunction(
8295f757f3fSDimitry Andric       "__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
8300b57cec5SDimitry Andric   MsanUnpoisonAllocaFn = M.getOrInsertFunction(
8315f757f3fSDimitry Andric       "__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric static Constant *getOrInsertGlobal(Module &M, StringRef Name, Type *Ty) {
8350b57cec5SDimitry Andric   return M.getOrInsertGlobal(Name, Ty, [&] {
8360b57cec5SDimitry Andric     return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
8370b57cec5SDimitry Andric                               nullptr, Name, nullptr,
8380b57cec5SDimitry Andric                               GlobalVariable::InitialExecTLSModel);
8390b57cec5SDimitry Andric   });
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric /// Insert declarations for userspace-specific functions and globals.
843bdd1243dSDimitry Andric void MemorySanitizer::createUserspaceApi(Module &M, const TargetLibraryInfo &TLI) {
8440b57cec5SDimitry Andric   IRBuilder<> IRB(*C);
8455ffd83dbSDimitry Andric 
8460b57cec5SDimitry Andric   // Create the callback.
8470b57cec5SDimitry Andric   // FIXME: this function should have "Cold" calling conv,
8480b57cec5SDimitry Andric   // which is not yet implemented.
849bdd1243dSDimitry Andric   if (TrackOrigins) {
8505ffd83dbSDimitry Andric     StringRef WarningFnName = Recover ? "__msan_warning_with_origin"
8515ffd83dbSDimitry Andric                                       : "__msan_warning_with_origin_noreturn";
852bdd1243dSDimitry Andric     WarningFn = M.getOrInsertFunction(WarningFnName,
853bdd1243dSDimitry Andric                                       TLI.getAttrList(C, {0}, /*Signed=*/false),
854bdd1243dSDimitry Andric                                       IRB.getVoidTy(), IRB.getInt32Ty());
855bdd1243dSDimitry Andric   } else {
856bdd1243dSDimitry Andric     StringRef WarningFnName =
857bdd1243dSDimitry Andric         Recover ? "__msan_warning" : "__msan_warning_noreturn";
858bdd1243dSDimitry Andric     WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
859bdd1243dSDimitry Andric   }
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric   // Create the global TLS variables.
8620b57cec5SDimitry Andric   RetvalTLS =
8630b57cec5SDimitry Andric       getOrInsertGlobal(M, "__msan_retval_tls",
8640b57cec5SDimitry Andric                         ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8));
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   RetvalOriginTLS = getOrInsertGlobal(M, "__msan_retval_origin_tls", OriginTy);
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric   ParamTLS =
8690b57cec5SDimitry Andric       getOrInsertGlobal(M, "__msan_param_tls",
8700b57cec5SDimitry Andric                         ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8));
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   ParamOriginTLS =
8730b57cec5SDimitry Andric       getOrInsertGlobal(M, "__msan_param_origin_tls",
8740b57cec5SDimitry Andric                         ArrayType::get(OriginTy, kParamTLSSize / 4));
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric   VAArgTLS =
8770b57cec5SDimitry Andric       getOrInsertGlobal(M, "__msan_va_arg_tls",
8780b57cec5SDimitry Andric                         ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8));
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric   VAArgOriginTLS =
8810b57cec5SDimitry Andric       getOrInsertGlobal(M, "__msan_va_arg_origin_tls",
8820b57cec5SDimitry Andric                         ArrayType::get(OriginTy, kParamTLSSize / 4));
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   VAArgOverflowSizeTLS =
8850b57cec5SDimitry Andric       getOrInsertGlobal(M, "__msan_va_arg_overflow_size_tls", IRB.getInt64Ty());
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
8880b57cec5SDimitry Andric        AccessSizeIndex++) {
8890b57cec5SDimitry Andric     unsigned AccessSize = 1 << AccessSizeIndex;
8900b57cec5SDimitry Andric     std::string FunctionName = "__msan_maybe_warning_" + itostr(AccessSize);
8910b57cec5SDimitry Andric     MaybeWarningFn[AccessSizeIndex] = M.getOrInsertFunction(
892bdd1243dSDimitry Andric         FunctionName, TLI.getAttrList(C, {0, 1}, /*Signed=*/false),
8935ffd83dbSDimitry Andric         IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric     FunctionName = "__msan_maybe_store_origin_" + itostr(AccessSize);
8960b57cec5SDimitry Andric     MaybeStoreOriginFn[AccessSizeIndex] = M.getOrInsertFunction(
897bdd1243dSDimitry Andric         FunctionName, TLI.getAttrList(C, {0, 2}, /*Signed=*/false),
8985f757f3fSDimitry Andric         IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,
8995ffd83dbSDimitry Andric         IRB.getInt32Ty());
9000b57cec5SDimitry Andric   }
9010b57cec5SDimitry Andric 
9025f757f3fSDimitry Andric   MsanSetAllocaOriginWithDescriptionFn =
9035f757f3fSDimitry Andric       M.getOrInsertFunction("__msan_set_alloca_origin_with_descr",
9045f757f3fSDimitry Andric                             IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);
9055f757f3fSDimitry Andric   MsanSetAllocaOriginNoDescriptionFn =
9065f757f3fSDimitry Andric       M.getOrInsertFunction("__msan_set_alloca_origin_no_descr",
9075f757f3fSDimitry Andric                             IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
9085f757f3fSDimitry Andric   MsanPoisonStackFn = M.getOrInsertFunction("__msan_poison_stack",
9095f757f3fSDimitry Andric                                             IRB.getVoidTy(), PtrTy, IntptrTy);
9100b57cec5SDimitry Andric }
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric /// Insert extern declaration of runtime-provided functions and globals.
913bdd1243dSDimitry Andric void MemorySanitizer::initializeCallbacks(Module &M, const TargetLibraryInfo &TLI) {
9140b57cec5SDimitry Andric   // Only do this once.
9150b57cec5SDimitry Andric   if (CallbacksInitialized)
9160b57cec5SDimitry Andric     return;
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   IRBuilder<> IRB(*C);
9190b57cec5SDimitry Andric   // Initialize callbacks that are common for kernel and userspace
9200b57cec5SDimitry Andric   // instrumentation.
9210b57cec5SDimitry Andric   MsanChainOriginFn = M.getOrInsertFunction(
922bdd1243dSDimitry Andric       "__msan_chain_origin",
923bdd1243dSDimitry Andric       TLI.getAttrList(C, {0}, /*Signed=*/false, /*Ret=*/true), IRB.getInt32Ty(),
924bdd1243dSDimitry Andric       IRB.getInt32Ty());
925bdd1243dSDimitry Andric   MsanSetOriginFn = M.getOrInsertFunction(
926bdd1243dSDimitry Andric       "__msan_set_origin", TLI.getAttrList(C, {2}, /*Signed=*/false),
9275f757f3fSDimitry Andric       IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
928bdd1243dSDimitry Andric   MemmoveFn =
9295f757f3fSDimitry Andric       M.getOrInsertFunction("__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
930bdd1243dSDimitry Andric   MemcpyFn =
9315f757f3fSDimitry Andric       M.getOrInsertFunction("__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
9325f757f3fSDimitry Andric   MemsetFn = M.getOrInsertFunction("__msan_memset",
9335f757f3fSDimitry Andric                                    TLI.getAttrList(C, {1}, /*Signed=*/true),
9345f757f3fSDimitry Andric                                    PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   MsanInstrumentAsmStoreFn =
9370b57cec5SDimitry Andric       M.getOrInsertFunction("__msan_instrument_asm_store", IRB.getVoidTy(),
9380b57cec5SDimitry Andric                             PointerType::get(IRB.getInt8Ty(), 0), IntptrTy);
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   if (CompileKernel) {
941bdd1243dSDimitry Andric     createKernelApi(M, TLI);
9420b57cec5SDimitry Andric   } else {
943bdd1243dSDimitry Andric     createUserspaceApi(M, TLI);
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric   CallbacksInitialized = true;
9460b57cec5SDimitry Andric }
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric FunctionCallee MemorySanitizer::getKmsanShadowOriginAccessFn(bool isStore,
9490b57cec5SDimitry Andric                                                              int size) {
9500b57cec5SDimitry Andric   FunctionCallee *Fns =
9510b57cec5SDimitry Andric       isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;
9520b57cec5SDimitry Andric   switch (size) {
9530b57cec5SDimitry Andric   case 1:
9540b57cec5SDimitry Andric     return Fns[0];
9550b57cec5SDimitry Andric   case 2:
9560b57cec5SDimitry Andric     return Fns[1];
9570b57cec5SDimitry Andric   case 4:
9580b57cec5SDimitry Andric     return Fns[2];
9590b57cec5SDimitry Andric   case 8:
9600b57cec5SDimitry Andric     return Fns[3];
9610b57cec5SDimitry Andric   default:
9620b57cec5SDimitry Andric     return nullptr;
9630b57cec5SDimitry Andric   }
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric /// Module-level initialization.
9670b57cec5SDimitry Andric ///
9680b57cec5SDimitry Andric /// inserts a call to __msan_init to the module's constructor list.
9690b57cec5SDimitry Andric void MemorySanitizer::initializeModule(Module &M) {
9700b57cec5SDimitry Andric   auto &DL = M.getDataLayout();
9710b57cec5SDimitry Andric 
97206c3fb27SDimitry Andric   TargetTriple = Triple(M.getTargetTriple());
97306c3fb27SDimitry Andric 
9740b57cec5SDimitry Andric   bool ShadowPassed = ClShadowBase.getNumOccurrences() > 0;
9750b57cec5SDimitry Andric   bool OriginPassed = ClOriginBase.getNumOccurrences() > 0;
9760b57cec5SDimitry Andric   // Check the overrides first
9770b57cec5SDimitry Andric   if (ShadowPassed || OriginPassed) {
9780b57cec5SDimitry Andric     CustomMapParams.AndMask = ClAndMask;
9790b57cec5SDimitry Andric     CustomMapParams.XorMask = ClXorMask;
9800b57cec5SDimitry Andric     CustomMapParams.ShadowBase = ClShadowBase;
9810b57cec5SDimitry Andric     CustomMapParams.OriginBase = ClOriginBase;
9820b57cec5SDimitry Andric     MapParams = &CustomMapParams;
9830b57cec5SDimitry Andric   } else {
9840b57cec5SDimitry Andric     switch (TargetTriple.getOS()) {
9850b57cec5SDimitry Andric     case Triple::FreeBSD:
9860b57cec5SDimitry Andric       switch (TargetTriple.getArch()) {
987fcaf7f86SDimitry Andric       case Triple::aarch64:
988fcaf7f86SDimitry Andric         MapParams = FreeBSD_ARM_MemoryMapParams.bits64;
989fcaf7f86SDimitry Andric         break;
9900b57cec5SDimitry Andric       case Triple::x86_64:
9910b57cec5SDimitry Andric         MapParams = FreeBSD_X86_MemoryMapParams.bits64;
9920b57cec5SDimitry Andric         break;
9930b57cec5SDimitry Andric       case Triple::x86:
9940b57cec5SDimitry Andric         MapParams = FreeBSD_X86_MemoryMapParams.bits32;
9950b57cec5SDimitry Andric         break;
9960b57cec5SDimitry Andric       default:
9970b57cec5SDimitry Andric         report_fatal_error("unsupported architecture");
9980b57cec5SDimitry Andric       }
9990b57cec5SDimitry Andric       break;
10000b57cec5SDimitry Andric     case Triple::NetBSD:
10010b57cec5SDimitry Andric       switch (TargetTriple.getArch()) {
10020b57cec5SDimitry Andric       case Triple::x86_64:
10030b57cec5SDimitry Andric         MapParams = NetBSD_X86_MemoryMapParams.bits64;
10040b57cec5SDimitry Andric         break;
10050b57cec5SDimitry Andric       default:
10060b57cec5SDimitry Andric         report_fatal_error("unsupported architecture");
10070b57cec5SDimitry Andric       }
10080b57cec5SDimitry Andric       break;
10090b57cec5SDimitry Andric     case Triple::Linux:
10100b57cec5SDimitry Andric       switch (TargetTriple.getArch()) {
10110b57cec5SDimitry Andric       case Triple::x86_64:
10120b57cec5SDimitry Andric         MapParams = Linux_X86_MemoryMapParams.bits64;
10130b57cec5SDimitry Andric         break;
10140b57cec5SDimitry Andric       case Triple::x86:
10150b57cec5SDimitry Andric         MapParams = Linux_X86_MemoryMapParams.bits32;
10160b57cec5SDimitry Andric         break;
10170b57cec5SDimitry Andric       case Triple::mips64:
10180b57cec5SDimitry Andric       case Triple::mips64el:
10190b57cec5SDimitry Andric         MapParams = Linux_MIPS_MemoryMapParams.bits64;
10200b57cec5SDimitry Andric         break;
10210b57cec5SDimitry Andric       case Triple::ppc64:
10220b57cec5SDimitry Andric       case Triple::ppc64le:
10230b57cec5SDimitry Andric         MapParams = Linux_PowerPC_MemoryMapParams.bits64;
10240b57cec5SDimitry Andric         break;
10255ffd83dbSDimitry Andric       case Triple::systemz:
10265ffd83dbSDimitry Andric         MapParams = Linux_S390_MemoryMapParams.bits64;
10275ffd83dbSDimitry Andric         break;
10280b57cec5SDimitry Andric       case Triple::aarch64:
10290b57cec5SDimitry Andric       case Triple::aarch64_be:
10300b57cec5SDimitry Andric         MapParams = Linux_ARM_MemoryMapParams.bits64;
10310b57cec5SDimitry Andric         break;
103206c3fb27SDimitry Andric       case Triple::loongarch64:
103306c3fb27SDimitry Andric         MapParams = Linux_LoongArch_MemoryMapParams.bits64;
103406c3fb27SDimitry Andric         break;
10350b57cec5SDimitry Andric       default:
10360b57cec5SDimitry Andric         report_fatal_error("unsupported architecture");
10370b57cec5SDimitry Andric       }
10380b57cec5SDimitry Andric       break;
10390b57cec5SDimitry Andric     default:
10400b57cec5SDimitry Andric       report_fatal_error("unsupported operating system");
10410b57cec5SDimitry Andric     }
10420b57cec5SDimitry Andric   }
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   C = &(M.getContext());
10450b57cec5SDimitry Andric   IRBuilder<> IRB(*C);
10460b57cec5SDimitry Andric   IntptrTy = IRB.getIntPtrTy(DL);
10470b57cec5SDimitry Andric   OriginTy = IRB.getInt32Ty();
10485f757f3fSDimitry Andric   PtrTy = IRB.getPtrTy();
10490b57cec5SDimitry Andric 
1050*0fca6ea1SDimitry Andric   ColdCallWeights = MDBuilder(*C).createUnlikelyBranchWeights();
1051*0fca6ea1SDimitry Andric   OriginStoreWeights = MDBuilder(*C).createUnlikelyBranchWeights();
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric   if (!CompileKernel) {
10540b57cec5SDimitry Andric     if (TrackOrigins)
10550b57cec5SDimitry Andric       M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] {
10560b57cec5SDimitry Andric         return new GlobalVariable(
10570b57cec5SDimitry Andric             M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
10580b57cec5SDimitry Andric             IRB.getInt32(TrackOrigins), "__msan_track_origins");
10590b57cec5SDimitry Andric       });
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric     if (Recover)
10620b57cec5SDimitry Andric       M.getOrInsertGlobal("__msan_keep_going", IRB.getInt32Ty(), [&] {
10630b57cec5SDimitry Andric         return new GlobalVariable(M, IRB.getInt32Ty(), true,
10640b57cec5SDimitry Andric                                   GlobalValue::WeakODRLinkage,
10650b57cec5SDimitry Andric                                   IRB.getInt32(Recover), "__msan_keep_going");
10660b57cec5SDimitry Andric       });
10670b57cec5SDimitry Andric   }
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric namespace {
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric /// A helper class that handles instrumentation of VarArg
10730b57cec5SDimitry Andric /// functions on a particular platform.
10740b57cec5SDimitry Andric ///
10750b57cec5SDimitry Andric /// Implementations are expected to insert the instrumentation
10760b57cec5SDimitry Andric /// necessary to propagate argument shadow through VarArg function
10770b57cec5SDimitry Andric /// calls. Visit* methods are called during an InstVisitor pass over
10780b57cec5SDimitry Andric /// the function, and should avoid creating new basic blocks. A new
10790b57cec5SDimitry Andric /// instance of this class is created for each instrumented function.
10800b57cec5SDimitry Andric struct VarArgHelper {
10810b57cec5SDimitry Andric   virtual ~VarArgHelper() = default;
10820b57cec5SDimitry Andric 
10835ffd83dbSDimitry Andric   /// Visit a CallBase.
10845ffd83dbSDimitry Andric   virtual void visitCallBase(CallBase &CB, IRBuilder<> &IRB) = 0;
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   /// Visit a va_start call.
10870b57cec5SDimitry Andric   virtual void visitVAStartInst(VAStartInst &I) = 0;
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric   /// Visit a va_copy call.
10900b57cec5SDimitry Andric   virtual void visitVACopyInst(VACopyInst &I) = 0;
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   /// Finalize function instrumentation.
10930b57cec5SDimitry Andric   ///
10940b57cec5SDimitry Andric   /// This method is called after visiting all interesting (see above)
10950b57cec5SDimitry Andric   /// instructions in a function.
10960b57cec5SDimitry Andric   virtual void finalizeInstrumentation() = 0;
10970b57cec5SDimitry Andric };
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric struct MemorySanitizerVisitor;
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric } // end anonymous namespace
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
11040b57cec5SDimitry Andric                                         MemorySanitizerVisitor &Visitor);
11050b57cec5SDimitry Andric 
110606c3fb27SDimitry Andric static unsigned TypeSizeToSizeIndex(TypeSize TS) {
110706c3fb27SDimitry Andric   if (TS.isScalable())
110806c3fb27SDimitry Andric     // Scalable types unconditionally take slowpaths.
110906c3fb27SDimitry Andric     return kNumberOfAccessSizes;
111006c3fb27SDimitry Andric   unsigned TypeSizeFixed = TS.getFixedValue();
111106c3fb27SDimitry Andric   if (TypeSizeFixed <= 8)
1112bdd1243dSDimitry Andric     return 0;
111306c3fb27SDimitry Andric   return Log2_32_Ceil((TypeSizeFixed + 7) / 8);
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric namespace {
11170b57cec5SDimitry Andric 
1118bdd1243dSDimitry Andric /// Helper class to attach debug information of the given instruction onto new
1119bdd1243dSDimitry Andric /// instructions inserted after.
1120bdd1243dSDimitry Andric class NextNodeIRBuilder : public IRBuilder<> {
1121bdd1243dSDimitry Andric public:
1122bdd1243dSDimitry Andric   explicit NextNodeIRBuilder(Instruction *IP) : IRBuilder<>(IP->getNextNode()) {
1123bdd1243dSDimitry Andric     SetCurrentDebugLocation(IP->getDebugLoc());
1124bdd1243dSDimitry Andric   }
1125bdd1243dSDimitry Andric };
1126bdd1243dSDimitry Andric 
11270b57cec5SDimitry Andric /// This class does all the work for a given function. Store and Load
11280b57cec5SDimitry Andric /// instructions store and load corresponding shadow and origin
11290b57cec5SDimitry Andric /// values. Most instructions propagate shadow from arguments to their
11300b57cec5SDimitry Andric /// return values. Certain instructions (most importantly, BranchInst)
11310b57cec5SDimitry Andric /// test their argument shadow and print reports (with a runtime call) if it's
11320b57cec5SDimitry Andric /// non-zero.
11330b57cec5SDimitry Andric struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
11340b57cec5SDimitry Andric   Function &F;
11350b57cec5SDimitry Andric   MemorySanitizer &MS;
11360b57cec5SDimitry Andric   SmallVector<PHINode *, 16> ShadowPHINodes, OriginPHINodes;
11370b57cec5SDimitry Andric   ValueMap<Value *, Value *> ShadowMap, OriginMap;
11380b57cec5SDimitry Andric   std::unique_ptr<VarArgHelper> VAHelper;
11390b57cec5SDimitry Andric   const TargetLibraryInfo *TLI;
1140e8d8bef9SDimitry Andric   Instruction *FnPrologueEnd;
1141*0fca6ea1SDimitry Andric   SmallVector<Instruction *, 16> Instructions;
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric   // The following flags disable parts of MSan instrumentation based on
11445ffd83dbSDimitry Andric   // exclusion list contents and command-line options.
11450b57cec5SDimitry Andric   bool InsertChecks;
11460b57cec5SDimitry Andric   bool PropagateShadow;
11470b57cec5SDimitry Andric   bool PoisonStack;
11480b57cec5SDimitry Andric   bool PoisonUndef;
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric   struct ShadowOriginAndInsertPoint {
11510b57cec5SDimitry Andric     Value *Shadow;
11520b57cec5SDimitry Andric     Value *Origin;
11530b57cec5SDimitry Andric     Instruction *OrigIns;
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric     ShadowOriginAndInsertPoint(Value *S, Value *O, Instruction *I)
11560b57cec5SDimitry Andric         : Shadow(S), Origin(O), OrigIns(I) {}
11570b57cec5SDimitry Andric   };
11580b57cec5SDimitry Andric   SmallVector<ShadowOriginAndInsertPoint, 16> InstrumentationList;
1159bdd1243dSDimitry Andric   DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
11600b57cec5SDimitry Andric   bool InstrumentLifetimeStart = ClHandleLifetimeIntrinsics;
1161bdd1243dSDimitry Andric   SmallSetVector<AllocaInst *, 16> AllocaSet;
11620b57cec5SDimitry Andric   SmallVector<std::pair<IntrinsicInst *, AllocaInst *>, 16> LifetimeStartList;
11630b57cec5SDimitry Andric   SmallVector<StoreInst *, 16> StoreList;
1164bdd1243dSDimitry Andric   int64_t SplittableBlocksCount = 0;
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric   MemorySanitizerVisitor(Function &F, MemorySanitizer &MS,
11670b57cec5SDimitry Andric                          const TargetLibraryInfo &TLI)
11680b57cec5SDimitry Andric       : F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)), TLI(&TLI) {
11690eae32dcSDimitry Andric     bool SanitizeFunction =
11700eae32dcSDimitry Andric         F.hasFnAttribute(Attribute::SanitizeMemory) && !ClDisableChecks;
11710b57cec5SDimitry Andric     InsertChecks = SanitizeFunction;
11720b57cec5SDimitry Andric     PropagateShadow = SanitizeFunction;
11730b57cec5SDimitry Andric     PoisonStack = SanitizeFunction && ClPoisonStack;
11740b57cec5SDimitry Andric     PoisonUndef = SanitizeFunction && ClPoisonUndef;
11750b57cec5SDimitry Andric 
1176e8d8bef9SDimitry Andric     // In the presence of unreachable blocks, we may see Phi nodes with
1177e8d8bef9SDimitry Andric     // incoming nodes from such blocks. Since InstVisitor skips unreachable
1178e8d8bef9SDimitry Andric     // blocks, such nodes will not have any shadow value associated with them.
1179e8d8bef9SDimitry Andric     // It's easier to remove unreachable blocks than deal with missing shadow.
1180e8d8bef9SDimitry Andric     removeUnreachableBlocks(F);
1181e8d8bef9SDimitry Andric 
1182bdd1243dSDimitry Andric     MS.initializeCallbacks(*F.getParent(), TLI);
1183e8d8bef9SDimitry Andric     FnPrologueEnd = IRBuilder<>(F.getEntryBlock().getFirstNonPHI())
1184e8d8bef9SDimitry Andric                         .CreateIntrinsic(Intrinsic::donothing, {}, {});
1185e8d8bef9SDimitry Andric 
1186e8d8bef9SDimitry Andric     if (MS.CompileKernel) {
1187e8d8bef9SDimitry Andric       IRBuilder<> IRB(FnPrologueEnd);
1188e8d8bef9SDimitry Andric       insertKmsanPrologue(IRB);
1189e8d8bef9SDimitry Andric     }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric     LLVM_DEBUG(if (!InsertChecks) dbgs()
11920b57cec5SDimitry Andric                << "MemorySanitizer is not inserting checks into '"
11930b57cec5SDimitry Andric                << F.getName() << "'\n");
11940b57cec5SDimitry Andric   }
11950b57cec5SDimitry Andric 
1196bdd1243dSDimitry Andric   bool instrumentWithCalls(Value *V) {
1197bdd1243dSDimitry Andric     // Constants likely will be eliminated by follow-up passes.
1198bdd1243dSDimitry Andric     if (isa<Constant>(V))
1199bdd1243dSDimitry Andric       return false;
1200bdd1243dSDimitry Andric 
1201bdd1243dSDimitry Andric     ++SplittableBlocksCount;
1202bdd1243dSDimitry Andric     return ClInstrumentationWithCallThreshold >= 0 &&
1203bdd1243dSDimitry Andric            SplittableBlocksCount > ClInstrumentationWithCallThreshold;
1204bdd1243dSDimitry Andric   }
1205bdd1243dSDimitry Andric 
1206e8d8bef9SDimitry Andric   bool isInPrologue(Instruction &I) {
1207e8d8bef9SDimitry Andric     return I.getParent() == FnPrologueEnd->getParent() &&
1208e8d8bef9SDimitry Andric            (&I == FnPrologueEnd || I.comesBefore(FnPrologueEnd));
1209e8d8bef9SDimitry Andric   }
1210e8d8bef9SDimitry Andric 
1211bdd1243dSDimitry Andric   // Creates a new origin and records the stack trace. In general we can call
1212bdd1243dSDimitry Andric   // this function for any origin manipulation we like. However it will cost
1213bdd1243dSDimitry Andric   // runtime resources. So use this wisely only if it can provide additional
1214bdd1243dSDimitry Andric   // information helpful to a user.
12150b57cec5SDimitry Andric   Value *updateOrigin(Value *V, IRBuilder<> &IRB) {
1216bdd1243dSDimitry Andric     if (MS.TrackOrigins <= 1)
1217bdd1243dSDimitry Andric       return V;
12180b57cec5SDimitry Andric     return IRB.CreateCall(MS.MsanChainOriginFn, V);
12190b57cec5SDimitry Andric   }
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric   Value *originToIntptr(IRBuilder<> &IRB, Value *Origin) {
1222*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
12230b57cec5SDimitry Andric     unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);
1224bdd1243dSDimitry Andric     if (IntptrSize == kOriginSize)
1225bdd1243dSDimitry Andric       return Origin;
12260b57cec5SDimitry Andric     assert(IntptrSize == kOriginSize * 2);
12270b57cec5SDimitry Andric     Origin = IRB.CreateIntCast(Origin, MS.IntptrTy, /* isSigned */ false);
12280b57cec5SDimitry Andric     return IRB.CreateOr(Origin, IRB.CreateShl(Origin, kOriginSize * 8));
12290b57cec5SDimitry Andric   }
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric   /// Fill memory range with the given origin value.
12320b57cec5SDimitry Andric   void paintOrigin(IRBuilder<> &IRB, Value *Origin, Value *OriginPtr,
123306c3fb27SDimitry Andric                    TypeSize TS, Align Alignment) {
1234*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
12355ffd83dbSDimitry Andric     const Align IntptrAlignment = DL.getABITypeAlign(MS.IntptrTy);
12360b57cec5SDimitry Andric     unsigned IntptrSize = DL.getTypeStoreSize(MS.IntptrTy);
12370b57cec5SDimitry Andric     assert(IntptrAlignment >= kMinOriginAlignment);
12380b57cec5SDimitry Andric     assert(IntptrSize >= kOriginSize);
12390b57cec5SDimitry Andric 
124006c3fb27SDimitry Andric     // Note: The loop based formation works for fixed length vectors too,
124106c3fb27SDimitry Andric     // however we prefer to unroll and specialize alignment below.
124206c3fb27SDimitry Andric     if (TS.isScalable()) {
1243*0fca6ea1SDimitry Andric       Value *Size = IRB.CreateTypeSize(MS.IntptrTy, TS);
1244*0fca6ea1SDimitry Andric       Value *RoundUp =
1245*0fca6ea1SDimitry Andric           IRB.CreateAdd(Size, ConstantInt::get(MS.IntptrTy, kOriginSize - 1));
1246*0fca6ea1SDimitry Andric       Value *End =
1247*0fca6ea1SDimitry Andric           IRB.CreateUDiv(RoundUp, ConstantInt::get(MS.IntptrTy, kOriginSize));
124806c3fb27SDimitry Andric       auto [InsertPt, Index] =
124906c3fb27SDimitry Andric         SplitBlockAndInsertSimpleForLoop(End, &*IRB.GetInsertPoint());
125006c3fb27SDimitry Andric       IRB.SetInsertPoint(InsertPt);
125106c3fb27SDimitry Andric 
125206c3fb27SDimitry Andric       Value *GEP = IRB.CreateGEP(MS.OriginTy, OriginPtr, Index);
125306c3fb27SDimitry Andric       IRB.CreateAlignedStore(Origin, GEP, kMinOriginAlignment);
125406c3fb27SDimitry Andric       return;
125506c3fb27SDimitry Andric     }
125606c3fb27SDimitry Andric 
125706c3fb27SDimitry Andric     unsigned Size = TS.getFixedValue();
125806c3fb27SDimitry Andric 
12590b57cec5SDimitry Andric     unsigned Ofs = 0;
1260480093f4SDimitry Andric     Align CurrentAlignment = Alignment;
12610b57cec5SDimitry Andric     if (Alignment >= IntptrAlignment && IntptrSize > kOriginSize) {
12620b57cec5SDimitry Andric       Value *IntptrOrigin = originToIntptr(IRB, Origin);
12630b57cec5SDimitry Andric       Value *IntptrOriginPtr =
12640b57cec5SDimitry Andric           IRB.CreatePointerCast(OriginPtr, PointerType::get(MS.IntptrTy, 0));
12650b57cec5SDimitry Andric       for (unsigned i = 0; i < Size / IntptrSize; ++i) {
12660b57cec5SDimitry Andric         Value *Ptr = i ? IRB.CreateConstGEP1_32(MS.IntptrTy, IntptrOriginPtr, i)
12670b57cec5SDimitry Andric                        : IntptrOriginPtr;
12685ffd83dbSDimitry Andric         IRB.CreateAlignedStore(IntptrOrigin, Ptr, CurrentAlignment);
12690b57cec5SDimitry Andric         Ofs += IntptrSize / kOriginSize;
12700b57cec5SDimitry Andric         CurrentAlignment = IntptrAlignment;
12710b57cec5SDimitry Andric       }
12720b57cec5SDimitry Andric     }
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric     for (unsigned i = Ofs; i < (Size + kOriginSize - 1) / kOriginSize; ++i) {
12750b57cec5SDimitry Andric       Value *GEP =
12760b57cec5SDimitry Andric           i ? IRB.CreateConstGEP1_32(MS.OriginTy, OriginPtr, i) : OriginPtr;
12775ffd83dbSDimitry Andric       IRB.CreateAlignedStore(Origin, GEP, CurrentAlignment);
12780b57cec5SDimitry Andric       CurrentAlignment = kMinOriginAlignment;
12790b57cec5SDimitry Andric     }
12800b57cec5SDimitry Andric   }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric   void storeOrigin(IRBuilder<> &IRB, Value *Addr, Value *Shadow, Value *Origin,
1283bdd1243dSDimitry Andric                    Value *OriginPtr, Align Alignment) {
1284*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
1285480093f4SDimitry Andric     const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);
128606c3fb27SDimitry Andric     TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());
1287*0fca6ea1SDimitry Andric     // ZExt cannot convert between vector and scalar
1288e8d8bef9SDimitry Andric     Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
1289480093f4SDimitry Andric     if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {
1290bdd1243dSDimitry Andric       if (!ClCheckConstantShadow || ConstantShadow->isZeroValue()) {
1291bdd1243dSDimitry Andric         // Origin is not needed: value is initialized or const shadow is
1292bdd1243dSDimitry Andric         // ignored.
1293bdd1243dSDimitry Andric         return;
1294bdd1243dSDimitry Andric       }
1295bdd1243dSDimitry Andric       if (llvm::isKnownNonZero(ConvertedShadow, DL)) {
1296bdd1243dSDimitry Andric         // Copy origin as the value is definitely uninitialized.
12970b57cec5SDimitry Andric         paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,
12980b57cec5SDimitry Andric                     OriginAlignment);
12990b57cec5SDimitry Andric         return;
13000b57cec5SDimitry Andric       }
1301bdd1243dSDimitry Andric       // Fallback to runtime check, which still can be optimized out later.
1302bdd1243dSDimitry Andric     }
13030b57cec5SDimitry Andric 
130406c3fb27SDimitry Andric     TypeSize TypeSizeInBits = DL.getTypeSizeInBits(ConvertedShadow->getType());
13050b57cec5SDimitry Andric     unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits);
1306bdd1243dSDimitry Andric     if (instrumentWithCalls(ConvertedShadow) &&
1307bdd1243dSDimitry Andric         SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) {
13080b57cec5SDimitry Andric       FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex];
1309e8d8bef9SDimitry Andric       Value *ConvertedShadow2 =
1310e8d8bef9SDimitry Andric           IRB.CreateZExt(ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex)));
13115f757f3fSDimitry Andric       CallBase *CB = IRB.CreateCall(Fn, {ConvertedShadow2, Addr, Origin});
1312fe6060f1SDimitry Andric       CB->addParamAttr(0, Attribute::ZExt);
1313fe6060f1SDimitry Andric       CB->addParamAttr(2, Attribute::ZExt);
13140b57cec5SDimitry Andric     } else {
1315e8d8bef9SDimitry Andric       Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp");
13160b57cec5SDimitry Andric       Instruction *CheckTerm = SplitBlockAndInsertIfThen(
13170b57cec5SDimitry Andric           Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights);
13180b57cec5SDimitry Andric       IRBuilder<> IRBNew(CheckTerm);
13190b57cec5SDimitry Andric       paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize,
13200b57cec5SDimitry Andric                   OriginAlignment);
13210b57cec5SDimitry Andric     }
13220b57cec5SDimitry Andric   }
13230b57cec5SDimitry Andric 
1324bdd1243dSDimitry Andric   void materializeStores() {
13250b57cec5SDimitry Andric     for (StoreInst *SI : StoreList) {
13260b57cec5SDimitry Andric       IRBuilder<> IRB(SI);
13270b57cec5SDimitry Andric       Value *Val = SI->getValueOperand();
13280b57cec5SDimitry Andric       Value *Addr = SI->getPointerOperand();
13290b57cec5SDimitry Andric       Value *Shadow = SI->isAtomic() ? getCleanShadow(Val) : getShadow(Val);
13300b57cec5SDimitry Andric       Value *ShadowPtr, *OriginPtr;
13310b57cec5SDimitry Andric       Type *ShadowTy = Shadow->getType();
13320eae32dcSDimitry Andric       const Align Alignment = SI->getAlign();
1333480093f4SDimitry Andric       const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);
13340b57cec5SDimitry Andric       std::tie(ShadowPtr, OriginPtr) =
13350b57cec5SDimitry Andric           getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ true);
13360b57cec5SDimitry Andric 
13375ffd83dbSDimitry Andric       StoreInst *NewSI = IRB.CreateAlignedStore(Shadow, ShadowPtr, Alignment);
13380b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "  STORE: " << *NewSI << "\n");
13390b57cec5SDimitry Andric       (void)NewSI;
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric       if (SI->isAtomic())
13420b57cec5SDimitry Andric         SI->setOrdering(addReleaseOrdering(SI->getOrdering()));
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric       if (MS.TrackOrigins && !SI->isAtomic())
13450b57cec5SDimitry Andric         storeOrigin(IRB, Addr, Shadow, getOrigin(Val), OriginPtr,
1346bdd1243dSDimitry Andric                     OriginAlignment);
13470b57cec5SDimitry Andric     }
13480b57cec5SDimitry Andric   }
13490b57cec5SDimitry Andric 
1350*0fca6ea1SDimitry Andric   // Returns true if Debug Location corresponds to multiple warnings.
1351bdd1243dSDimitry Andric   bool shouldDisambiguateWarningLocation(const DebugLoc &DebugLoc) {
1352bdd1243dSDimitry Andric     if (MS.TrackOrigins < 2)
1353bdd1243dSDimitry Andric       return false;
1354bdd1243dSDimitry Andric 
1355bdd1243dSDimitry Andric     if (LazyWarningDebugLocationCount.empty())
1356bdd1243dSDimitry Andric       for (const auto &I : InstrumentationList)
1357bdd1243dSDimitry Andric         ++LazyWarningDebugLocationCount[I.OrigIns->getDebugLoc()];
1358bdd1243dSDimitry Andric 
1359bdd1243dSDimitry Andric     return LazyWarningDebugLocationCount[DebugLoc] >= ClDisambiguateWarning;
1360bdd1243dSDimitry Andric   }
1361bdd1243dSDimitry Andric 
13620b57cec5SDimitry Andric   /// Helper function to insert a warning at IRB's current insert point.
13630b57cec5SDimitry Andric   void insertWarningFn(IRBuilder<> &IRB, Value *Origin) {
13640b57cec5SDimitry Andric     if (!Origin)
13650b57cec5SDimitry Andric       Origin = (Value *)IRB.getInt32(0);
13665ffd83dbSDimitry Andric     assert(Origin->getType()->isIntegerTy());
1367bdd1243dSDimitry Andric 
1368bdd1243dSDimitry Andric     if (shouldDisambiguateWarningLocation(IRB.getCurrentDebugLocation())) {
1369bdd1243dSDimitry Andric       // Try to create additional origin with debug info of the last origin
1370bdd1243dSDimitry Andric       // instruction. It may provide additional information to the user.
1371bdd1243dSDimitry Andric       if (Instruction *OI = dyn_cast_or_null<Instruction>(Origin)) {
1372bdd1243dSDimitry Andric         assert(MS.TrackOrigins);
1373bdd1243dSDimitry Andric         auto NewDebugLoc = OI->getDebugLoc();
1374bdd1243dSDimitry Andric         // Origin update with missing or the same debug location provides no
1375bdd1243dSDimitry Andric         // additional value.
1376bdd1243dSDimitry Andric         if (NewDebugLoc && NewDebugLoc != IRB.getCurrentDebugLocation()) {
1377bdd1243dSDimitry Andric           // Insert update just before the check, so we call runtime only just
1378bdd1243dSDimitry Andric           // before the report.
1379bdd1243dSDimitry Andric           IRBuilder<> IRBOrigin(&*IRB.GetInsertPoint());
1380bdd1243dSDimitry Andric           IRBOrigin.SetCurrentDebugLocation(NewDebugLoc);
1381bdd1243dSDimitry Andric           Origin = updateOrigin(Origin, IRBOrigin);
1382bdd1243dSDimitry Andric         }
1383bdd1243dSDimitry Andric       }
1384bdd1243dSDimitry Andric     }
1385bdd1243dSDimitry Andric 
1386bdd1243dSDimitry Andric     if (MS.CompileKernel || MS.TrackOrigins)
13875ffd83dbSDimitry Andric       IRB.CreateCall(MS.WarningFn, Origin)->setCannotMerge();
1388bdd1243dSDimitry Andric     else
1389bdd1243dSDimitry Andric       IRB.CreateCall(MS.WarningFn)->setCannotMerge();
13900b57cec5SDimitry Andric     // FIXME: Insert UnreachableInst if !MS.Recover?
13910b57cec5SDimitry Andric     // This may invalidate some of the following checks and needs to be done
13920b57cec5SDimitry Andric     // at the very end.
13930b57cec5SDimitry Andric   }
13940b57cec5SDimitry Andric 
1395bdd1243dSDimitry Andric   void materializeOneCheck(IRBuilder<> &IRB, Value *ConvertedShadow,
1396bdd1243dSDimitry Andric                            Value *Origin) {
1397*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
139806c3fb27SDimitry Andric     TypeSize TypeSizeInBits = DL.getTypeSizeInBits(ConvertedShadow->getType());
13990b57cec5SDimitry Andric     unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits);
1400bdd1243dSDimitry Andric     if (instrumentWithCalls(ConvertedShadow) &&
1401bdd1243dSDimitry Andric         SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) {
14020b57cec5SDimitry Andric       FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];
1403*0fca6ea1SDimitry Andric       // ZExt cannot convert between vector and scalar
1404*0fca6ea1SDimitry Andric       ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);
14050b57cec5SDimitry Andric       Value *ConvertedShadow2 =
14060b57cec5SDimitry Andric           IRB.CreateZExt(ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex)));
1407fe6060f1SDimitry Andric       CallBase *CB = IRB.CreateCall(
1408fe6060f1SDimitry Andric           Fn, {ConvertedShadow2,
1409fe6060f1SDimitry Andric                MS.TrackOrigins && Origin ? Origin : (Value *)IRB.getInt32(0)});
1410fe6060f1SDimitry Andric       CB->addParamAttr(0, Attribute::ZExt);
1411fe6060f1SDimitry Andric       CB->addParamAttr(1, Attribute::ZExt);
14120b57cec5SDimitry Andric     } else {
1413e8d8bef9SDimitry Andric       Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp");
14140b57cec5SDimitry Andric       Instruction *CheckTerm = SplitBlockAndInsertIfThen(
1415bdd1243dSDimitry Andric           Cmp, &*IRB.GetInsertPoint(),
14160b57cec5SDimitry Andric           /* Unreachable */ !MS.Recover, MS.ColdCallWeights);
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric       IRB.SetInsertPoint(CheckTerm);
14190b57cec5SDimitry Andric       insertWarningFn(IRB, Origin);
14200b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "  CHECK: " << *Cmp << "\n");
14210b57cec5SDimitry Andric     }
14220b57cec5SDimitry Andric   }
14230b57cec5SDimitry Andric 
1424bdd1243dSDimitry Andric   void materializeInstructionChecks(
1425bdd1243dSDimitry Andric       ArrayRef<ShadowOriginAndInsertPoint> InstructionChecks) {
1426*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
1427bdd1243dSDimitry Andric     // Disable combining in some cases. TrackOrigins checks each shadow to pick
1428bdd1243dSDimitry Andric     // correct origin.
1429bdd1243dSDimitry Andric     bool Combine = !MS.TrackOrigins;
1430bdd1243dSDimitry Andric     Instruction *Instruction = InstructionChecks.front().OrigIns;
1431bdd1243dSDimitry Andric     Value *Shadow = nullptr;
1432bdd1243dSDimitry Andric     for (const auto &ShadowData : InstructionChecks) {
1433bdd1243dSDimitry Andric       assert(ShadowData.OrigIns == Instruction);
1434bdd1243dSDimitry Andric       IRBuilder<> IRB(Instruction);
1435bdd1243dSDimitry Andric 
1436bdd1243dSDimitry Andric       Value *ConvertedShadow = ShadowData.Shadow;
1437bdd1243dSDimitry Andric 
1438bdd1243dSDimitry Andric       if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {
1439bdd1243dSDimitry Andric         if (!ClCheckConstantShadow || ConstantShadow->isZeroValue()) {
1440bdd1243dSDimitry Andric           // Skip, value is initialized or const shadow is ignored.
1441bdd1243dSDimitry Andric           continue;
14420b57cec5SDimitry Andric         }
1443bdd1243dSDimitry Andric         if (llvm::isKnownNonZero(ConvertedShadow, DL)) {
1444bdd1243dSDimitry Andric           // Report as the value is definitely uninitialized.
1445bdd1243dSDimitry Andric           insertWarningFn(IRB, ShadowData.Origin);
1446bdd1243dSDimitry Andric           if (!MS.Recover)
1447bdd1243dSDimitry Andric             return; // Always fail and stop here, not need to check the rest.
1448bdd1243dSDimitry Andric           // Skip entire instruction,
1449bdd1243dSDimitry Andric           continue;
1450bdd1243dSDimitry Andric         }
1451bdd1243dSDimitry Andric         // Fallback to runtime check, which still can be optimized out later.
1452bdd1243dSDimitry Andric       }
1453bdd1243dSDimitry Andric 
1454bdd1243dSDimitry Andric       if (!Combine) {
1455bdd1243dSDimitry Andric         materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin);
1456bdd1243dSDimitry Andric         continue;
1457bdd1243dSDimitry Andric       }
1458bdd1243dSDimitry Andric 
1459bdd1243dSDimitry Andric       if (!Shadow) {
1460bdd1243dSDimitry Andric         Shadow = ConvertedShadow;
1461bdd1243dSDimitry Andric         continue;
1462bdd1243dSDimitry Andric       }
1463bdd1243dSDimitry Andric 
1464bdd1243dSDimitry Andric       Shadow = convertToBool(Shadow, IRB, "_mscmp");
1465bdd1243dSDimitry Andric       ConvertedShadow = convertToBool(ConvertedShadow, IRB, "_mscmp");
1466bdd1243dSDimitry Andric       Shadow = IRB.CreateOr(Shadow, ConvertedShadow, "_msor");
1467bdd1243dSDimitry Andric     }
1468bdd1243dSDimitry Andric 
1469bdd1243dSDimitry Andric     if (Shadow) {
1470bdd1243dSDimitry Andric       assert(Combine);
1471bdd1243dSDimitry Andric       IRBuilder<> IRB(Instruction);
1472bdd1243dSDimitry Andric       materializeOneCheck(IRB, Shadow, nullptr);
1473bdd1243dSDimitry Andric     }
1474bdd1243dSDimitry Andric   }
1475bdd1243dSDimitry Andric 
1476bdd1243dSDimitry Andric   void materializeChecks() {
1477*0fca6ea1SDimitry Andric #ifndef NDEBUG
1478*0fca6ea1SDimitry Andric     // For assert below.
1479*0fca6ea1SDimitry Andric     SmallPtrSet<Instruction *, 16> Done;
1480*0fca6ea1SDimitry Andric #endif
1481bdd1243dSDimitry Andric 
1482bdd1243dSDimitry Andric     for (auto I = InstrumentationList.begin();
1483bdd1243dSDimitry Andric          I != InstrumentationList.end();) {
1484*0fca6ea1SDimitry Andric       auto OrigIns = I->OrigIns;
1485*0fca6ea1SDimitry Andric       // Checks are grouped by the original instruction. We call all
1486*0fca6ea1SDimitry Andric       // `insertShadowCheck` for an instruction at once.
1487*0fca6ea1SDimitry Andric       assert(Done.insert(OrigIns).second);
1488*0fca6ea1SDimitry Andric       auto J = std::find_if(I + 1, InstrumentationList.end(),
1489*0fca6ea1SDimitry Andric                             [OrigIns](const ShadowOriginAndInsertPoint &R) {
1490*0fca6ea1SDimitry Andric                               return OrigIns != R.OrigIns;
1491bdd1243dSDimitry Andric                             });
1492bdd1243dSDimitry Andric       // Process all checks of instruction at once.
1493bdd1243dSDimitry Andric       materializeInstructionChecks(ArrayRef<ShadowOriginAndInsertPoint>(I, J));
1494bdd1243dSDimitry Andric       I = J;
1495bdd1243dSDimitry Andric     }
1496bdd1243dSDimitry Andric 
14970b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "DONE:\n" << F);
14980b57cec5SDimitry Andric   }
14990b57cec5SDimitry Andric 
1500e8d8bef9SDimitry Andric   // Returns the last instruction in the new prologue
1501e8d8bef9SDimitry Andric   void insertKmsanPrologue(IRBuilder<> &IRB) {
15020b57cec5SDimitry Andric     Value *ContextState = IRB.CreateCall(MS.MsanGetContextStateFn, {});
15030b57cec5SDimitry Andric     Constant *Zero = IRB.getInt32(0);
15040b57cec5SDimitry Andric     MS.ParamTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15050b57cec5SDimitry Andric                                 {Zero, IRB.getInt32(0)}, "param_shadow");
15060b57cec5SDimitry Andric     MS.RetvalTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15070b57cec5SDimitry Andric                                  {Zero, IRB.getInt32(1)}, "retval_shadow");
15080b57cec5SDimitry Andric     MS.VAArgTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15090b57cec5SDimitry Andric                                 {Zero, IRB.getInt32(2)}, "va_arg_shadow");
15100b57cec5SDimitry Andric     MS.VAArgOriginTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15110b57cec5SDimitry Andric                                       {Zero, IRB.getInt32(3)}, "va_arg_origin");
15120b57cec5SDimitry Andric     MS.VAArgOverflowSizeTLS =
15130b57cec5SDimitry Andric         IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15140b57cec5SDimitry Andric                       {Zero, IRB.getInt32(4)}, "va_arg_overflow_size");
15150b57cec5SDimitry Andric     MS.ParamOriginTLS = IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15160b57cec5SDimitry Andric                                       {Zero, IRB.getInt32(5)}, "param_origin");
15170b57cec5SDimitry Andric     MS.RetvalOriginTLS =
15180b57cec5SDimitry Andric         IRB.CreateGEP(MS.MsanContextStateTy, ContextState,
15190b57cec5SDimitry Andric                       {Zero, IRB.getInt32(6)}, "retval_origin");
152006c3fb27SDimitry Andric     if (MS.TargetTriple.getArch() == Triple::systemz)
152106c3fb27SDimitry Andric       MS.MsanMetadataAlloca = IRB.CreateAlloca(MS.MsanMetadata, 0u);
15220b57cec5SDimitry Andric   }
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric   /// Add MemorySanitizer instrumentation to a function.
15250b57cec5SDimitry Andric   bool runOnFunction() {
15260b57cec5SDimitry Andric     // Iterate all BBs in depth-first order and create shadow instructions
15270b57cec5SDimitry Andric     // for all instructions (where applicable).
15280b57cec5SDimitry Andric     // For PHI nodes we create dummy shadow PHIs which will be finalized later.
1529e8d8bef9SDimitry Andric     for (BasicBlock *BB : depth_first(FnPrologueEnd->getParent()))
15300b57cec5SDimitry Andric       visit(*BB);
15310b57cec5SDimitry Andric 
1532*0fca6ea1SDimitry Andric     // `visit` above only collects instructions. Process them after iterating
1533*0fca6ea1SDimitry Andric     // CFG to avoid requirement on CFG transformations.
1534*0fca6ea1SDimitry Andric     for (Instruction *I : Instructions)
1535*0fca6ea1SDimitry Andric       InstVisitor<MemorySanitizerVisitor>::visit(*I);
1536*0fca6ea1SDimitry Andric 
15370b57cec5SDimitry Andric     // Finalize PHI nodes.
15380b57cec5SDimitry Andric     for (PHINode *PN : ShadowPHINodes) {
15390b57cec5SDimitry Andric       PHINode *PNS = cast<PHINode>(getShadow(PN));
15400b57cec5SDimitry Andric       PHINode *PNO = MS.TrackOrigins ? cast<PHINode>(getOrigin(PN)) : nullptr;
15410b57cec5SDimitry Andric       size_t NumValues = PN->getNumIncomingValues();
15420b57cec5SDimitry Andric       for (size_t v = 0; v < NumValues; v++) {
15430b57cec5SDimitry Andric         PNS->addIncoming(getShadow(PN, v), PN->getIncomingBlock(v));
1544bdd1243dSDimitry Andric         if (PNO)
1545bdd1243dSDimitry Andric           PNO->addIncoming(getOrigin(PN, v), PN->getIncomingBlock(v));
15460b57cec5SDimitry Andric       }
15470b57cec5SDimitry Andric     }
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric     VAHelper->finalizeInstrumentation();
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric     // Poison llvm.lifetime.start intrinsics, if we haven't fallen back to
15520b57cec5SDimitry Andric     // instrumenting only allocas.
15530b57cec5SDimitry Andric     if (InstrumentLifetimeStart) {
15540b57cec5SDimitry Andric       for (auto Item : LifetimeStartList) {
15550b57cec5SDimitry Andric         instrumentAlloca(*Item.second, Item.first);
1556bdd1243dSDimitry Andric         AllocaSet.remove(Item.second);
15570b57cec5SDimitry Andric       }
15580b57cec5SDimitry Andric     }
15590b57cec5SDimitry Andric     // Poison the allocas for which we didn't instrument the corresponding
15600b57cec5SDimitry Andric     // lifetime intrinsics.
15610b57cec5SDimitry Andric     for (AllocaInst *AI : AllocaSet)
15620b57cec5SDimitry Andric       instrumentAlloca(*AI);
15630b57cec5SDimitry Andric 
15640b57cec5SDimitry Andric     // Insert shadow value checks.
1565bdd1243dSDimitry Andric     materializeChecks();
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric     // Delayed instrumentation of StoreInst.
15680b57cec5SDimitry Andric     // This may not add new address checks.
1569bdd1243dSDimitry Andric     materializeStores();
15700b57cec5SDimitry Andric 
15710b57cec5SDimitry Andric     return true;
15720b57cec5SDimitry Andric   }
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric   /// Compute the shadow type that corresponds to a given Value.
1575bdd1243dSDimitry Andric   Type *getShadowTy(Value *V) { return getShadowTy(V->getType()); }
15760b57cec5SDimitry Andric 
15770b57cec5SDimitry Andric   /// Compute the shadow type that corresponds to a given Type.
15780b57cec5SDimitry Andric   Type *getShadowTy(Type *OrigTy) {
15790b57cec5SDimitry Andric     if (!OrigTy->isSized()) {
15800b57cec5SDimitry Andric       return nullptr;
15810b57cec5SDimitry Andric     }
15820b57cec5SDimitry Andric     // For integer type, shadow is the same as the original type.
15830b57cec5SDimitry Andric     // This may return weird-sized types like i1.
15840b57cec5SDimitry Andric     if (IntegerType *IT = dyn_cast<IntegerType>(OrigTy))
15850b57cec5SDimitry Andric       return IT;
1586*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
15870b57cec5SDimitry Andric     if (VectorType *VT = dyn_cast<VectorType>(OrigTy)) {
15880b57cec5SDimitry Andric       uint32_t EltSize = DL.getTypeSizeInBits(VT->getElementType());
158906c3fb27SDimitry Andric       return VectorType::get(IntegerType::get(*MS.C, EltSize),
159006c3fb27SDimitry Andric                              VT->getElementCount());
15910b57cec5SDimitry Andric     }
15920b57cec5SDimitry Andric     if (ArrayType *AT = dyn_cast<ArrayType>(OrigTy)) {
15930b57cec5SDimitry Andric       return ArrayType::get(getShadowTy(AT->getElementType()),
15940b57cec5SDimitry Andric                             AT->getNumElements());
15950b57cec5SDimitry Andric     }
15960b57cec5SDimitry Andric     if (StructType *ST = dyn_cast<StructType>(OrigTy)) {
15970b57cec5SDimitry Andric       SmallVector<Type *, 4> Elements;
15980b57cec5SDimitry Andric       for (unsigned i = 0, n = ST->getNumElements(); i < n; i++)
15990b57cec5SDimitry Andric         Elements.push_back(getShadowTy(ST->getElementType(i)));
16000b57cec5SDimitry Andric       StructType *Res = StructType::get(*MS.C, Elements, ST->isPacked());
16010b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "getShadowTy: " << *ST << " ===> " << *Res << "\n");
16020b57cec5SDimitry Andric       return Res;
16030b57cec5SDimitry Andric     }
16040b57cec5SDimitry Andric     uint32_t TypeSize = DL.getTypeSizeInBits(OrigTy);
16050b57cec5SDimitry Andric     return IntegerType::get(*MS.C, TypeSize);
16060b57cec5SDimitry Andric   }
16070b57cec5SDimitry Andric 
1608e8d8bef9SDimitry Andric   /// Extract combined shadow of struct elements as a bool
1609e8d8bef9SDimitry Andric   Value *collapseStructShadow(StructType *Struct, Value *Shadow,
1610e8d8bef9SDimitry Andric                               IRBuilder<> &IRB) {
1611e8d8bef9SDimitry Andric     Value *FalseVal = IRB.getIntN(/* width */ 1, /* value */ 0);
1612e8d8bef9SDimitry Andric     Value *Aggregator = FalseVal;
1613e8d8bef9SDimitry Andric 
1614e8d8bef9SDimitry Andric     for (unsigned Idx = 0; Idx < Struct->getNumElements(); Idx++) {
1615e8d8bef9SDimitry Andric       // Combine by ORing together each element's bool shadow
1616e8d8bef9SDimitry Andric       Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);
161706c3fb27SDimitry Andric       Value *ShadowBool = convertToBool(ShadowItem, IRB);
1618e8d8bef9SDimitry Andric 
1619e8d8bef9SDimitry Andric       if (Aggregator != FalseVal)
1620e8d8bef9SDimitry Andric         Aggregator = IRB.CreateOr(Aggregator, ShadowBool);
1621e8d8bef9SDimitry Andric       else
1622e8d8bef9SDimitry Andric         Aggregator = ShadowBool;
1623e8d8bef9SDimitry Andric     }
1624e8d8bef9SDimitry Andric 
1625e8d8bef9SDimitry Andric     return Aggregator;
1626e8d8bef9SDimitry Andric   }
1627e8d8bef9SDimitry Andric 
1628e8d8bef9SDimitry Andric   // Extract combined shadow of array elements
1629e8d8bef9SDimitry Andric   Value *collapseArrayShadow(ArrayType *Array, Value *Shadow,
1630e8d8bef9SDimitry Andric                              IRBuilder<> &IRB) {
1631e8d8bef9SDimitry Andric     if (!Array->getNumElements())
1632e8d8bef9SDimitry Andric       return IRB.getIntN(/* width */ 1, /* value */ 0);
1633e8d8bef9SDimitry Andric 
1634e8d8bef9SDimitry Andric     Value *FirstItem = IRB.CreateExtractValue(Shadow, 0);
1635e8d8bef9SDimitry Andric     Value *Aggregator = convertShadowToScalar(FirstItem, IRB);
1636e8d8bef9SDimitry Andric 
1637e8d8bef9SDimitry Andric     for (unsigned Idx = 1; Idx < Array->getNumElements(); Idx++) {
1638e8d8bef9SDimitry Andric       Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx);
1639e8d8bef9SDimitry Andric       Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);
1640e8d8bef9SDimitry Andric       Aggregator = IRB.CreateOr(Aggregator, ShadowInner);
1641e8d8bef9SDimitry Andric     }
1642e8d8bef9SDimitry Andric     return Aggregator;
1643e8d8bef9SDimitry Andric   }
1644e8d8bef9SDimitry Andric 
1645e8d8bef9SDimitry Andric   /// Convert a shadow value to it's flattened variant. The resulting
1646e8d8bef9SDimitry Andric   /// shadow may not necessarily have the same bit width as the input
1647e8d8bef9SDimitry Andric   /// value, but it will always be comparable to zero.
1648e8d8bef9SDimitry Andric   Value *convertShadowToScalar(Value *V, IRBuilder<> &IRB) {
1649e8d8bef9SDimitry Andric     if (StructType *Struct = dyn_cast<StructType>(V->getType()))
1650e8d8bef9SDimitry Andric       return collapseStructShadow(Struct, V, IRB);
1651e8d8bef9SDimitry Andric     if (ArrayType *Array = dyn_cast<ArrayType>(V->getType()))
1652e8d8bef9SDimitry Andric       return collapseArrayShadow(Array, V, IRB);
165306c3fb27SDimitry Andric     if (isa<VectorType>(V->getType())) {
165406c3fb27SDimitry Andric       if (isa<ScalableVectorType>(V->getType()))
165506c3fb27SDimitry Andric         return convertShadowToScalar(IRB.CreateOrReduce(V), IRB);
165606c3fb27SDimitry Andric       unsigned BitWidth =
165706c3fb27SDimitry Andric         V->getType()->getPrimitiveSizeInBits().getFixedValue();
165806c3fb27SDimitry Andric       return IRB.CreateBitCast(V, IntegerType::get(*MS.C, BitWidth));
165906c3fb27SDimitry Andric     }
1660bdd1243dSDimitry Andric     return V;
16610b57cec5SDimitry Andric   }
16620b57cec5SDimitry Andric 
1663e8d8bef9SDimitry Andric   // Convert a scalar value to an i1 by comparing with 0
1664e8d8bef9SDimitry Andric   Value *convertToBool(Value *V, IRBuilder<> &IRB, const Twine &name = "") {
1665e8d8bef9SDimitry Andric     Type *VTy = V->getType();
1666bdd1243dSDimitry Andric     if (!VTy->isIntegerTy())
1667bdd1243dSDimitry Andric       return convertToBool(convertShadowToScalar(V, IRB), IRB, name);
1668e8d8bef9SDimitry Andric     if (VTy->getIntegerBitWidth() == 1)
1669e8d8bef9SDimitry Andric       // Just converting a bool to a bool, so do nothing.
1670e8d8bef9SDimitry Andric       return V;
1671e8d8bef9SDimitry Andric     return IRB.CreateICmpNE(V, ConstantInt::get(VTy, 0), name);
1672e8d8bef9SDimitry Andric   }
1673e8d8bef9SDimitry Andric 
1674bdd1243dSDimitry Andric   Type *ptrToIntPtrType(Type *PtrTy) const {
167506c3fb27SDimitry Andric     if (VectorType *VectTy = dyn_cast<VectorType>(PtrTy)) {
167606c3fb27SDimitry Andric       return VectorType::get(ptrToIntPtrType(VectTy->getElementType()),
167706c3fb27SDimitry Andric                              VectTy->getElementCount());
1678bdd1243dSDimitry Andric     }
1679bdd1243dSDimitry Andric     assert(PtrTy->isIntOrPtrTy());
1680bdd1243dSDimitry Andric     return MS.IntptrTy;
1681bdd1243dSDimitry Andric   }
1682bdd1243dSDimitry Andric 
1683bdd1243dSDimitry Andric   Type *getPtrToShadowPtrType(Type *IntPtrTy, Type *ShadowTy) const {
168406c3fb27SDimitry Andric     if (VectorType *VectTy = dyn_cast<VectorType>(IntPtrTy)) {
168506c3fb27SDimitry Andric       return VectorType::get(
1686bdd1243dSDimitry Andric           getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
168706c3fb27SDimitry Andric           VectTy->getElementCount());
1688bdd1243dSDimitry Andric     }
1689bdd1243dSDimitry Andric     assert(IntPtrTy == MS.IntptrTy);
16905f757f3fSDimitry Andric     return PointerType::get(*MS.C, 0);
1691bdd1243dSDimitry Andric   }
1692bdd1243dSDimitry Andric 
1693bdd1243dSDimitry Andric   Constant *constToIntPtr(Type *IntPtrTy, uint64_t C) const {
169406c3fb27SDimitry Andric     if (VectorType *VectTy = dyn_cast<VectorType>(IntPtrTy)) {
169506c3fb27SDimitry Andric       return ConstantVector::getSplat(
169606c3fb27SDimitry Andric           VectTy->getElementCount(), constToIntPtr(VectTy->getElementType(), C));
1697bdd1243dSDimitry Andric     }
1698bdd1243dSDimitry Andric     assert(IntPtrTy == MS.IntptrTy);
1699bdd1243dSDimitry Andric     return ConstantInt::get(MS.IntptrTy, C);
1700bdd1243dSDimitry Andric   }
1701bdd1243dSDimitry Andric 
17020b57cec5SDimitry Andric   /// Compute the integer shadow offset that corresponds to a given
17030b57cec5SDimitry Andric   /// application address.
17040b57cec5SDimitry Andric   ///
17050b57cec5SDimitry Andric   /// Offset = (Addr & ~AndMask) ^ XorMask
1706bdd1243dSDimitry Andric   /// Addr can be a ptr or <N x ptr>. In both cases ShadowTy the shadow type of
1707bdd1243dSDimitry Andric   /// a single pointee.
1708bdd1243dSDimitry Andric   /// Returns <shadow_ptr, origin_ptr> or <<N x shadow_ptr>, <N x origin_ptr>>.
17090b57cec5SDimitry Andric   Value *getShadowPtrOffset(Value *Addr, IRBuilder<> &IRB) {
1710bdd1243dSDimitry Andric     Type *IntptrTy = ptrToIntPtrType(Addr->getType());
1711bdd1243dSDimitry Andric     Value *OffsetLong = IRB.CreatePointerCast(Addr, IntptrTy);
17120b57cec5SDimitry Andric 
1713bdd1243dSDimitry Andric     if (uint64_t AndMask = MS.MapParams->AndMask)
1714bdd1243dSDimitry Andric       OffsetLong = IRB.CreateAnd(OffsetLong, constToIntPtr(IntptrTy, ~AndMask));
17150b57cec5SDimitry Andric 
1716bdd1243dSDimitry Andric     if (uint64_t XorMask = MS.MapParams->XorMask)
1717bdd1243dSDimitry Andric       OffsetLong = IRB.CreateXor(OffsetLong, constToIntPtr(IntptrTy, XorMask));
17180b57cec5SDimitry Andric     return OffsetLong;
17190b57cec5SDimitry Andric   }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   /// Compute the shadow and origin addresses corresponding to a given
17220b57cec5SDimitry Andric   /// application address.
17230b57cec5SDimitry Andric   ///
17240b57cec5SDimitry Andric   /// Shadow = ShadowBase + Offset
17250b57cec5SDimitry Andric   /// Origin = (OriginBase + Offset) & ~3ULL
1726bdd1243dSDimitry Andric   /// Addr can be a ptr or <N x ptr>. In both cases ShadowTy the shadow type of
1727bdd1243dSDimitry Andric   /// a single pointee.
1728bdd1243dSDimitry Andric   /// Returns <shadow_ptr, origin_ptr> or <<N x shadow_ptr>, <N x origin_ptr>>.
1729480093f4SDimitry Andric   std::pair<Value *, Value *>
1730480093f4SDimitry Andric   getShadowOriginPtrUserspace(Value *Addr, IRBuilder<> &IRB, Type *ShadowTy,
1731480093f4SDimitry Andric                               MaybeAlign Alignment) {
1732cf675768SDimitry Andric     VectorType *VectTy = dyn_cast<VectorType>(Addr->getType());
1733cf675768SDimitry Andric     if (!VectTy) {
1734cf675768SDimitry Andric       assert(Addr->getType()->isPointerTy());
1735cf675768SDimitry Andric     } else {
1736cf675768SDimitry Andric       assert(VectTy->getElementType()->isPointerTy());
1737cf675768SDimitry Andric     }
1738bdd1243dSDimitry Andric     Type *IntptrTy = ptrToIntPtrType(Addr->getType());
17390b57cec5SDimitry Andric     Value *ShadowOffset = getShadowPtrOffset(Addr, IRB);
17400b57cec5SDimitry Andric     Value *ShadowLong = ShadowOffset;
1741bdd1243dSDimitry Andric     if (uint64_t ShadowBase = MS.MapParams->ShadowBase) {
17420b57cec5SDimitry Andric       ShadowLong =
1743bdd1243dSDimitry Andric           IRB.CreateAdd(ShadowLong, constToIntPtr(IntptrTy, ShadowBase));
17440b57cec5SDimitry Andric     }
1745bdd1243dSDimitry Andric     Value *ShadowPtr = IRB.CreateIntToPtr(
1746bdd1243dSDimitry Andric         ShadowLong, getPtrToShadowPtrType(IntptrTy, ShadowTy));
1747bdd1243dSDimitry Andric 
17480b57cec5SDimitry Andric     Value *OriginPtr = nullptr;
17490b57cec5SDimitry Andric     if (MS.TrackOrigins) {
17500b57cec5SDimitry Andric       Value *OriginLong = ShadowOffset;
17510b57cec5SDimitry Andric       uint64_t OriginBase = MS.MapParams->OriginBase;
17520b57cec5SDimitry Andric       if (OriginBase != 0)
1753bdd1243dSDimitry Andric         OriginLong =
1754bdd1243dSDimitry Andric             IRB.CreateAdd(OriginLong, constToIntPtr(IntptrTy, OriginBase));
1755480093f4SDimitry Andric       if (!Alignment || *Alignment < kMinOriginAlignment) {
1756480093f4SDimitry Andric         uint64_t Mask = kMinOriginAlignment.value() - 1;
1757bdd1243dSDimitry Andric         OriginLong = IRB.CreateAnd(OriginLong, constToIntPtr(IntptrTy, ~Mask));
17580b57cec5SDimitry Andric       }
1759bdd1243dSDimitry Andric       OriginPtr = IRB.CreateIntToPtr(
1760bdd1243dSDimitry Andric           OriginLong, getPtrToShadowPtrType(IntptrTy, MS.OriginTy));
17610b57cec5SDimitry Andric     }
17620b57cec5SDimitry Andric     return std::make_pair(ShadowPtr, OriginPtr);
17630b57cec5SDimitry Andric   }
17640b57cec5SDimitry Andric 
176506c3fb27SDimitry Andric   template <typename... ArgsTy>
176606c3fb27SDimitry Andric   Value *createMetadataCall(IRBuilder<> &IRB, FunctionCallee Callee,
176706c3fb27SDimitry Andric                             ArgsTy... Args) {
176806c3fb27SDimitry Andric     if (MS.TargetTriple.getArch() == Triple::systemz) {
176906c3fb27SDimitry Andric       IRB.CreateCall(Callee,
177006c3fb27SDimitry Andric                      {MS.MsanMetadataAlloca, std::forward<ArgsTy>(Args)...});
177106c3fb27SDimitry Andric       return IRB.CreateLoad(MS.MsanMetadata, MS.MsanMetadataAlloca);
177206c3fb27SDimitry Andric     }
177306c3fb27SDimitry Andric 
177406c3fb27SDimitry Andric     return IRB.CreateCall(Callee, {std::forward<ArgsTy>(Args)...});
177506c3fb27SDimitry Andric   }
177606c3fb27SDimitry Andric 
1777bdd1243dSDimitry Andric   std::pair<Value *, Value *> getShadowOriginPtrKernelNoVec(Value *Addr,
1778480093f4SDimitry Andric                                                             IRBuilder<> &IRB,
1779480093f4SDimitry Andric                                                             Type *ShadowTy,
1780480093f4SDimitry Andric                                                             bool isStore) {
17810b57cec5SDimitry Andric     Value *ShadowOriginPtrs;
1782*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
178306c3fb27SDimitry Andric     TypeSize Size = DL.getTypeStoreSize(ShadowTy);
17840b57cec5SDimitry Andric 
17850b57cec5SDimitry Andric     FunctionCallee Getter = MS.getKmsanShadowOriginAccessFn(isStore, Size);
17860b57cec5SDimitry Andric     Value *AddrCast =
17870b57cec5SDimitry Andric         IRB.CreatePointerCast(Addr, PointerType::get(IRB.getInt8Ty(), 0));
17880b57cec5SDimitry Andric     if (Getter) {
178906c3fb27SDimitry Andric       ShadowOriginPtrs = createMetadataCall(IRB, Getter, AddrCast);
17900b57cec5SDimitry Andric     } else {
17910b57cec5SDimitry Andric       Value *SizeVal = ConstantInt::get(MS.IntptrTy, Size);
179206c3fb27SDimitry Andric       ShadowOriginPtrs = createMetadataCall(
179306c3fb27SDimitry Andric           IRB,
179406c3fb27SDimitry Andric           isStore ? MS.MsanMetadataPtrForStoreN : MS.MsanMetadataPtrForLoadN,
179506c3fb27SDimitry Andric           AddrCast, SizeVal);
17960b57cec5SDimitry Andric     }
17970b57cec5SDimitry Andric     Value *ShadowPtr = IRB.CreateExtractValue(ShadowOriginPtrs, 0);
17980b57cec5SDimitry Andric     ShadowPtr = IRB.CreatePointerCast(ShadowPtr, PointerType::get(ShadowTy, 0));
17990b57cec5SDimitry Andric     Value *OriginPtr = IRB.CreateExtractValue(ShadowOriginPtrs, 1);
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric     return std::make_pair(ShadowPtr, OriginPtr);
18020b57cec5SDimitry Andric   }
18030b57cec5SDimitry Andric 
1804bdd1243dSDimitry Andric   /// Addr can be a ptr or <N x ptr>. In both cases ShadowTy the shadow type of
1805bdd1243dSDimitry Andric   /// a single pointee.
1806bdd1243dSDimitry Andric   /// Returns <shadow_ptr, origin_ptr> or <<N x shadow_ptr>, <N x origin_ptr>>.
1807bdd1243dSDimitry Andric   std::pair<Value *, Value *> getShadowOriginPtrKernel(Value *Addr,
1808bdd1243dSDimitry Andric                                                        IRBuilder<> &IRB,
1809bdd1243dSDimitry Andric                                                        Type *ShadowTy,
1810bdd1243dSDimitry Andric                                                        bool isStore) {
181106c3fb27SDimitry Andric     VectorType *VectTy = dyn_cast<VectorType>(Addr->getType());
1812bdd1243dSDimitry Andric     if (!VectTy) {
1813bdd1243dSDimitry Andric       assert(Addr->getType()->isPointerTy());
1814bdd1243dSDimitry Andric       return getShadowOriginPtrKernelNoVec(Addr, IRB, ShadowTy, isStore);
1815bdd1243dSDimitry Andric     }
1816bdd1243dSDimitry Andric 
1817bdd1243dSDimitry Andric     // TODO: Support callbacs with vectors of addresses.
181806c3fb27SDimitry Andric     unsigned NumElements = cast<FixedVectorType>(VectTy)->getNumElements();
1819bdd1243dSDimitry Andric     Value *ShadowPtrs = ConstantInt::getNullValue(
18205f757f3fSDimitry Andric         FixedVectorType::get(IRB.getPtrTy(), NumElements));
1821bdd1243dSDimitry Andric     Value *OriginPtrs = nullptr;
1822bdd1243dSDimitry Andric     if (MS.TrackOrigins)
1823bdd1243dSDimitry Andric       OriginPtrs = ConstantInt::getNullValue(
18245f757f3fSDimitry Andric           FixedVectorType::get(IRB.getPtrTy(), NumElements));
1825bdd1243dSDimitry Andric     for (unsigned i = 0; i < NumElements; ++i) {
1826bdd1243dSDimitry Andric       Value *OneAddr =
1827bdd1243dSDimitry Andric           IRB.CreateExtractElement(Addr, ConstantInt::get(IRB.getInt32Ty(), i));
1828bdd1243dSDimitry Andric       auto [ShadowPtr, OriginPtr] =
1829bdd1243dSDimitry Andric           getShadowOriginPtrKernelNoVec(OneAddr, IRB, ShadowTy, isStore);
1830bdd1243dSDimitry Andric 
1831bdd1243dSDimitry Andric       ShadowPtrs = IRB.CreateInsertElement(
1832bdd1243dSDimitry Andric           ShadowPtrs, ShadowPtr, ConstantInt::get(IRB.getInt32Ty(), i));
1833bdd1243dSDimitry Andric       if (MS.TrackOrigins)
1834bdd1243dSDimitry Andric         OriginPtrs = IRB.CreateInsertElement(
1835bdd1243dSDimitry Andric             OriginPtrs, OriginPtr, ConstantInt::get(IRB.getInt32Ty(), i));
1836bdd1243dSDimitry Andric     }
1837bdd1243dSDimitry Andric     return {ShadowPtrs, OriginPtrs};
1838bdd1243dSDimitry Andric   }
1839bdd1243dSDimitry Andric 
18400b57cec5SDimitry Andric   std::pair<Value *, Value *> getShadowOriginPtr(Value *Addr, IRBuilder<> &IRB,
18410b57cec5SDimitry Andric                                                  Type *ShadowTy,
1842480093f4SDimitry Andric                                                  MaybeAlign Alignment,
18430b57cec5SDimitry Andric                                                  bool isStore) {
18440b57cec5SDimitry Andric     if (MS.CompileKernel)
1845480093f4SDimitry Andric       return getShadowOriginPtrKernel(Addr, IRB, ShadowTy, isStore);
1846480093f4SDimitry Andric     return getShadowOriginPtrUserspace(Addr, IRB, ShadowTy, Alignment);
18470b57cec5SDimitry Andric   }
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric   /// Compute the shadow address for a given function argument.
18500b57cec5SDimitry Andric   ///
18510b57cec5SDimitry Andric   /// Shadow = ParamTLS+ArgOffset.
18525f757f3fSDimitry Andric   Value *getShadowPtrForArgument(IRBuilder<> &IRB, int ArgOffset) {
18530b57cec5SDimitry Andric     Value *Base = IRB.CreatePointerCast(MS.ParamTLS, MS.IntptrTy);
18540b57cec5SDimitry Andric     if (ArgOffset)
18550b57cec5SDimitry Andric       Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
18565f757f3fSDimitry Andric     return IRB.CreateIntToPtr(Base, IRB.getPtrTy(0), "_msarg");
18570b57cec5SDimitry Andric   }
18580b57cec5SDimitry Andric 
18590b57cec5SDimitry Andric   /// Compute the origin address for a given function argument.
18605f757f3fSDimitry Andric   Value *getOriginPtrForArgument(IRBuilder<> &IRB, int ArgOffset) {
18610b57cec5SDimitry Andric     if (!MS.TrackOrigins)
18620b57cec5SDimitry Andric       return nullptr;
18630b57cec5SDimitry Andric     Value *Base = IRB.CreatePointerCast(MS.ParamOriginTLS, MS.IntptrTy);
18640b57cec5SDimitry Andric     if (ArgOffset)
18650b57cec5SDimitry Andric       Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
18665f757f3fSDimitry Andric     return IRB.CreateIntToPtr(Base, IRB.getPtrTy(0), "_msarg_o");
18670b57cec5SDimitry Andric   }
18680b57cec5SDimitry Andric 
18690b57cec5SDimitry Andric   /// Compute the shadow address for a retval.
18705f757f3fSDimitry Andric   Value *getShadowPtrForRetval(IRBuilder<> &IRB) {
18715f757f3fSDimitry Andric     return IRB.CreatePointerCast(MS.RetvalTLS, IRB.getPtrTy(0), "_msret");
18720b57cec5SDimitry Andric   }
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   /// Compute the origin address for a retval.
18755f757f3fSDimitry Andric   Value *getOriginPtrForRetval() {
18760b57cec5SDimitry Andric     // We keep a single origin for the entire retval. Might be too optimistic.
18770b57cec5SDimitry Andric     return MS.RetvalOriginTLS;
18780b57cec5SDimitry Andric   }
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric   /// Set SV to be the shadow value for V.
18810b57cec5SDimitry Andric   void setShadow(Value *V, Value *SV) {
18820b57cec5SDimitry Andric     assert(!ShadowMap.count(V) && "Values may only have one shadow");
18830b57cec5SDimitry Andric     ShadowMap[V] = PropagateShadow ? SV : getCleanShadow(V);
18840b57cec5SDimitry Andric   }
18850b57cec5SDimitry Andric 
18860b57cec5SDimitry Andric   /// Set Origin to be the origin value for V.
18870b57cec5SDimitry Andric   void setOrigin(Value *V, Value *Origin) {
1888bdd1243dSDimitry Andric     if (!MS.TrackOrigins)
1889bdd1243dSDimitry Andric       return;
18900b57cec5SDimitry Andric     assert(!OriginMap.count(V) && "Values may only have one origin");
18910b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "ORIGIN: " << *V << "  ==> " << *Origin << "\n");
18920b57cec5SDimitry Andric     OriginMap[V] = Origin;
18930b57cec5SDimitry Andric   }
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   Constant *getCleanShadow(Type *OrigTy) {
18960b57cec5SDimitry Andric     Type *ShadowTy = getShadowTy(OrigTy);
18970b57cec5SDimitry Andric     if (!ShadowTy)
18980b57cec5SDimitry Andric       return nullptr;
18990b57cec5SDimitry Andric     return Constant::getNullValue(ShadowTy);
19000b57cec5SDimitry Andric   }
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric   /// Create a clean shadow value for a given value.
19030b57cec5SDimitry Andric   ///
19040b57cec5SDimitry Andric   /// Clean shadow (all zeroes) means all bits of the value are defined
19050b57cec5SDimitry Andric   /// (initialized).
1906bdd1243dSDimitry Andric   Constant *getCleanShadow(Value *V) { return getCleanShadow(V->getType()); }
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric   /// Create a dirty shadow of a given shadow type.
19090b57cec5SDimitry Andric   Constant *getPoisonedShadow(Type *ShadowTy) {
19100b57cec5SDimitry Andric     assert(ShadowTy);
19110b57cec5SDimitry Andric     if (isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy))
19120b57cec5SDimitry Andric       return Constant::getAllOnesValue(ShadowTy);
19130b57cec5SDimitry Andric     if (ArrayType *AT = dyn_cast<ArrayType>(ShadowTy)) {
19140b57cec5SDimitry Andric       SmallVector<Constant *, 4> Vals(AT->getNumElements(),
19150b57cec5SDimitry Andric                                       getPoisonedShadow(AT->getElementType()));
19160b57cec5SDimitry Andric       return ConstantArray::get(AT, Vals);
19170b57cec5SDimitry Andric     }
19180b57cec5SDimitry Andric     if (StructType *ST = dyn_cast<StructType>(ShadowTy)) {
19190b57cec5SDimitry Andric       SmallVector<Constant *, 4> Vals;
19200b57cec5SDimitry Andric       for (unsigned i = 0, n = ST->getNumElements(); i < n; i++)
19210b57cec5SDimitry Andric         Vals.push_back(getPoisonedShadow(ST->getElementType(i)));
19220b57cec5SDimitry Andric       return ConstantStruct::get(ST, Vals);
19230b57cec5SDimitry Andric     }
19240b57cec5SDimitry Andric     llvm_unreachable("Unexpected shadow type");
19250b57cec5SDimitry Andric   }
19260b57cec5SDimitry Andric 
19270b57cec5SDimitry Andric   /// Create a dirty shadow for a given value.
19280b57cec5SDimitry Andric   Constant *getPoisonedShadow(Value *V) {
19290b57cec5SDimitry Andric     Type *ShadowTy = getShadowTy(V);
19300b57cec5SDimitry Andric     if (!ShadowTy)
19310b57cec5SDimitry Andric       return nullptr;
19320b57cec5SDimitry Andric     return getPoisonedShadow(ShadowTy);
19330b57cec5SDimitry Andric   }
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric   /// Create a clean (zero) origin.
1936bdd1243dSDimitry Andric   Value *getCleanOrigin() { return Constant::getNullValue(MS.OriginTy); }
19370b57cec5SDimitry Andric 
19380b57cec5SDimitry Andric   /// Get the shadow value for a given Value.
19390b57cec5SDimitry Andric   ///
19400b57cec5SDimitry Andric   /// This function either returns the value set earlier with setShadow,
19410b57cec5SDimitry Andric   /// or extracts if from ParamTLS (for function arguments).
19420b57cec5SDimitry Andric   Value *getShadow(Value *V) {
19430b57cec5SDimitry Andric     if (Instruction *I = dyn_cast<Instruction>(V)) {
194481ad6265SDimitry Andric       if (!PropagateShadow || I->getMetadata(LLVMContext::MD_nosanitize))
19450b57cec5SDimitry Andric         return getCleanShadow(V);
19460b57cec5SDimitry Andric       // For instructions the shadow is already stored in the map.
19470b57cec5SDimitry Andric       Value *Shadow = ShadowMap[V];
19480b57cec5SDimitry Andric       if (!Shadow) {
19490b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "No shadow: " << *V << "\n" << *(I->getParent()));
19500b57cec5SDimitry Andric         (void)I;
19510b57cec5SDimitry Andric         assert(Shadow && "No shadow for a value");
19520b57cec5SDimitry Andric       }
19530b57cec5SDimitry Andric       return Shadow;
19540b57cec5SDimitry Andric     }
19550b57cec5SDimitry Andric     if (UndefValue *U = dyn_cast<UndefValue>(V)) {
195604eeddc0SDimitry Andric       Value *AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
195704eeddc0SDimitry Andric                                                         : getCleanShadow(V);
19580b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Undef: " << *U << " ==> " << *AllOnes << "\n");
19590b57cec5SDimitry Andric       (void)U;
19600b57cec5SDimitry Andric       return AllOnes;
19610b57cec5SDimitry Andric     }
19620b57cec5SDimitry Andric     if (Argument *A = dyn_cast<Argument>(V)) {
19630b57cec5SDimitry Andric       // For arguments we compute the shadow on demand and store it in the map.
196481ad6265SDimitry Andric       Value *&ShadowPtr = ShadowMap[V];
196581ad6265SDimitry Andric       if (ShadowPtr)
196681ad6265SDimitry Andric         return ShadowPtr;
19670b57cec5SDimitry Andric       Function *F = A->getParent();
1968e8d8bef9SDimitry Andric       IRBuilder<> EntryIRB(FnPrologueEnd);
19690b57cec5SDimitry Andric       unsigned ArgOffset = 0;
1970*0fca6ea1SDimitry Andric       const DataLayout &DL = F->getDataLayout();
19710b57cec5SDimitry Andric       for (auto &FArg : F->args()) {
1972*0fca6ea1SDimitry Andric         if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
1973*0fca6ea1SDimitry Andric           LLVM_DEBUG(dbgs() << (FArg.getType()->isScalableTy()
1974*0fca6ea1SDimitry Andric                                     ? "vscale not fully supported\n"
1975*0fca6ea1SDimitry Andric                                     : "Arg is not sized\n"));
1976*0fca6ea1SDimitry Andric           if (A == &FArg) {
1977*0fca6ea1SDimitry Andric             ShadowPtr = getCleanShadow(V);
1978*0fca6ea1SDimitry Andric             setOrigin(A, getCleanOrigin());
1979*0fca6ea1SDimitry Andric             break;
1980*0fca6ea1SDimitry Andric           }
19810b57cec5SDimitry Andric           continue;
19820b57cec5SDimitry Andric         }
19835ffd83dbSDimitry Andric 
198404eeddc0SDimitry Andric         unsigned Size = FArg.hasByValAttr()
19855ffd83dbSDimitry Andric                             ? DL.getTypeAllocSize(FArg.getParamByValType())
19860b57cec5SDimitry Andric                             : DL.getTypeAllocSize(FArg.getType());
19875ffd83dbSDimitry Andric 
19880b57cec5SDimitry Andric         if (A == &FArg) {
19890b57cec5SDimitry Andric           bool Overflow = ArgOffset + Size > kParamTLSSize;
199004eeddc0SDimitry Andric           if (FArg.hasByValAttr()) {
19910b57cec5SDimitry Andric             // ByVal pointer itself has clean shadow. We copy the actual
19920b57cec5SDimitry Andric             // argument shadow to the underlying memory.
19930b57cec5SDimitry Andric             // Figure out maximal valid memcpy alignment.
1994480093f4SDimitry Andric             const Align ArgAlign = DL.getValueOrABITypeAlignment(
1995bdd1243dSDimitry Andric                 FArg.getParamAlign(), FArg.getParamByValType());
19961fd87a68SDimitry Andric             Value *CpShadowPtr, *CpOriginPtr;
19971fd87a68SDimitry Andric             std::tie(CpShadowPtr, CpOriginPtr) =
19980b57cec5SDimitry Andric                 getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,
19991fd87a68SDimitry Andric                                    /*isStore*/ true);
200004eeddc0SDimitry Andric             if (!PropagateShadow || Overflow) {
20010b57cec5SDimitry Andric               // ParamTLS overflow.
20020b57cec5SDimitry Andric               EntryIRB.CreateMemSet(
20030b57cec5SDimitry Andric                   CpShadowPtr, Constant::getNullValue(EntryIRB.getInt8Ty()),
20040b57cec5SDimitry Andric                   Size, ArgAlign);
20050b57cec5SDimitry Andric             } else {
20065f757f3fSDimitry Andric               Value *Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2007480093f4SDimitry Andric               const Align CopyAlign = std::min(ArgAlign, kShadowTLSAlignment);
20080b57cec5SDimitry Andric               Value *Cpy = EntryIRB.CreateMemCpy(CpShadowPtr, CopyAlign, Base,
20090b57cec5SDimitry Andric                                                  CopyAlign, Size);
20100b57cec5SDimitry Andric               LLVM_DEBUG(dbgs() << "  ByValCpy: " << *Cpy << "\n");
20110b57cec5SDimitry Andric               (void)Cpy;
20121fd87a68SDimitry Andric 
20131fd87a68SDimitry Andric               if (MS.TrackOrigins) {
20141fd87a68SDimitry Andric                 Value *OriginPtr =
20155f757f3fSDimitry Andric                     getOriginPtrForArgument(EntryIRB, ArgOffset);
20161fd87a68SDimitry Andric                 // FIXME: OriginSize should be:
20171fd87a68SDimitry Andric                 // alignTo(V % kMinOriginAlignment + Size, kMinOriginAlignment)
20181fd87a68SDimitry Andric                 unsigned OriginSize = alignTo(Size, kMinOriginAlignment);
20191fd87a68SDimitry Andric                 EntryIRB.CreateMemCpy(
20201fd87a68SDimitry Andric                     CpOriginPtr,
20211fd87a68SDimitry Andric                     /* by getShadowOriginPtr */ kMinOriginAlignment, OriginPtr,
20221fd87a68SDimitry Andric                     /* by origin_tls[ArgOffset] */ kMinOriginAlignment,
20231fd87a68SDimitry Andric                     OriginSize);
20241fd87a68SDimitry Andric               }
20250b57cec5SDimitry Andric             }
202604eeddc0SDimitry Andric           }
202704eeddc0SDimitry Andric 
202804eeddc0SDimitry Andric           if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||
202904eeddc0SDimitry Andric               (MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {
203081ad6265SDimitry Andric             ShadowPtr = getCleanShadow(V);
203104eeddc0SDimitry Andric             setOrigin(A, getCleanOrigin());
20320b57cec5SDimitry Andric           } else {
20335ffd83dbSDimitry Andric             // Shadow over TLS
20345f757f3fSDimitry Andric             Value *Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
203581ad6265SDimitry Andric             ShadowPtr = EntryIRB.CreateAlignedLoad(getShadowTy(&FArg), Base,
20365ffd83dbSDimitry Andric                                                    kShadowTLSAlignment);
203704eeddc0SDimitry Andric             if (MS.TrackOrigins) {
203804eeddc0SDimitry Andric               Value *OriginPtr =
20395f757f3fSDimitry Andric                   getOriginPtrForArgument(EntryIRB, ArgOffset);
204004eeddc0SDimitry Andric               setOrigin(A, EntryIRB.CreateLoad(MS.OriginTy, OriginPtr));
20410b57cec5SDimitry Andric             }
20420b57cec5SDimitry Andric           }
20430b57cec5SDimitry Andric           LLVM_DEBUG(dbgs()
204481ad6265SDimitry Andric                      << "  ARG:    " << FArg << " ==> " << *ShadowPtr << "\n");
2045e8d8bef9SDimitry Andric           break;
20460b57cec5SDimitry Andric         }
20475ffd83dbSDimitry Andric 
20480b57cec5SDimitry Andric         ArgOffset += alignTo(Size, kShadowTLSAlignment);
20490b57cec5SDimitry Andric       }
205081ad6265SDimitry Andric       assert(ShadowPtr && "Could not find shadow for an argument");
205181ad6265SDimitry Andric       return ShadowPtr;
20520b57cec5SDimitry Andric     }
20530b57cec5SDimitry Andric     // For everything else the shadow is zero.
20540b57cec5SDimitry Andric     return getCleanShadow(V);
20550b57cec5SDimitry Andric   }
20560b57cec5SDimitry Andric 
20570b57cec5SDimitry Andric   /// Get the shadow for i-th argument of the instruction I.
20580b57cec5SDimitry Andric   Value *getShadow(Instruction *I, int i) {
20590b57cec5SDimitry Andric     return getShadow(I->getOperand(i));
20600b57cec5SDimitry Andric   }
20610b57cec5SDimitry Andric 
20620b57cec5SDimitry Andric   /// Get the origin for a value.
20630b57cec5SDimitry Andric   Value *getOrigin(Value *V) {
2064bdd1243dSDimitry Andric     if (!MS.TrackOrigins)
2065bdd1243dSDimitry Andric       return nullptr;
2066bdd1243dSDimitry Andric     if (!PropagateShadow || isa<Constant>(V) || isa<InlineAsm>(V))
2067bdd1243dSDimitry Andric       return getCleanOrigin();
20680b57cec5SDimitry Andric     assert((isa<Instruction>(V) || isa<Argument>(V)) &&
20690b57cec5SDimitry Andric            "Unexpected value type in getOrigin()");
20700b57cec5SDimitry Andric     if (Instruction *I = dyn_cast<Instruction>(V)) {
207181ad6265SDimitry Andric       if (I->getMetadata(LLVMContext::MD_nosanitize))
20720b57cec5SDimitry Andric         return getCleanOrigin();
20730b57cec5SDimitry Andric     }
20740b57cec5SDimitry Andric     Value *Origin = OriginMap[V];
20750b57cec5SDimitry Andric     assert(Origin && "Missing origin");
20760b57cec5SDimitry Andric     return Origin;
20770b57cec5SDimitry Andric   }
20780b57cec5SDimitry Andric 
20790b57cec5SDimitry Andric   /// Get the origin for i-th argument of the instruction I.
20800b57cec5SDimitry Andric   Value *getOrigin(Instruction *I, int i) {
20810b57cec5SDimitry Andric     return getOrigin(I->getOperand(i));
20820b57cec5SDimitry Andric   }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric   /// Remember the place where a shadow check should be inserted.
20850b57cec5SDimitry Andric   ///
20860b57cec5SDimitry Andric   /// This location will be later instrumented with a check that will print a
20870b57cec5SDimitry Andric   /// UMR warning in runtime if the shadow value is not 0.
20880b57cec5SDimitry Andric   void insertShadowCheck(Value *Shadow, Value *Origin, Instruction *OrigIns) {
20890b57cec5SDimitry Andric     assert(Shadow);
2090bdd1243dSDimitry Andric     if (!InsertChecks)
2091bdd1243dSDimitry Andric       return;
2092bdd1243dSDimitry Andric 
2093bdd1243dSDimitry Andric     if (!DebugCounter::shouldExecute(DebugInsertCheck)) {
2094bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "Skipping check of " << *Shadow << " before "
2095bdd1243dSDimitry Andric                         << *OrigIns << "\n");
2096bdd1243dSDimitry Andric       return;
2097bdd1243dSDimitry Andric     }
20980b57cec5SDimitry Andric #ifndef NDEBUG
20990b57cec5SDimitry Andric     Type *ShadowTy = Shadow->getType();
2100e8d8bef9SDimitry Andric     assert((isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy) ||
2101e8d8bef9SDimitry Andric             isa<StructType>(ShadowTy) || isa<ArrayType>(ShadowTy)) &&
2102e8d8bef9SDimitry Andric            "Can only insert checks for integer, vector, and aggregate shadow "
2103e8d8bef9SDimitry Andric            "types");
21040b57cec5SDimitry Andric #endif
21050b57cec5SDimitry Andric     InstrumentationList.push_back(
21060b57cec5SDimitry Andric         ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
21070b57cec5SDimitry Andric   }
21080b57cec5SDimitry Andric 
21090b57cec5SDimitry Andric   /// Remember the place where a shadow check should be inserted.
21100b57cec5SDimitry Andric   ///
21110b57cec5SDimitry Andric   /// This location will be later instrumented with a check that will print a
21120b57cec5SDimitry Andric   /// UMR warning in runtime if the value is not fully defined.
21130b57cec5SDimitry Andric   void insertShadowCheck(Value *Val, Instruction *OrigIns) {
21140b57cec5SDimitry Andric     assert(Val);
21150b57cec5SDimitry Andric     Value *Shadow, *Origin;
21160b57cec5SDimitry Andric     if (ClCheckConstantShadow) {
21170b57cec5SDimitry Andric       Shadow = getShadow(Val);
2118bdd1243dSDimitry Andric       if (!Shadow)
2119bdd1243dSDimitry Andric         return;
21200b57cec5SDimitry Andric       Origin = getOrigin(Val);
21210b57cec5SDimitry Andric     } else {
21220b57cec5SDimitry Andric       Shadow = dyn_cast_or_null<Instruction>(getShadow(Val));
2123bdd1243dSDimitry Andric       if (!Shadow)
2124bdd1243dSDimitry Andric         return;
21250b57cec5SDimitry Andric       Origin = dyn_cast_or_null<Instruction>(getOrigin(Val));
21260b57cec5SDimitry Andric     }
21270b57cec5SDimitry Andric     insertShadowCheck(Shadow, Origin, OrigIns);
21280b57cec5SDimitry Andric   }
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric   AtomicOrdering addReleaseOrdering(AtomicOrdering a) {
21310b57cec5SDimitry Andric     switch (a) {
21320b57cec5SDimitry Andric     case AtomicOrdering::NotAtomic:
21330b57cec5SDimitry Andric       return AtomicOrdering::NotAtomic;
21340b57cec5SDimitry Andric     case AtomicOrdering::Unordered:
21350b57cec5SDimitry Andric     case AtomicOrdering::Monotonic:
21360b57cec5SDimitry Andric     case AtomicOrdering::Release:
21370b57cec5SDimitry Andric       return AtomicOrdering::Release;
21380b57cec5SDimitry Andric     case AtomicOrdering::Acquire:
21390b57cec5SDimitry Andric     case AtomicOrdering::AcquireRelease:
21400b57cec5SDimitry Andric       return AtomicOrdering::AcquireRelease;
21410b57cec5SDimitry Andric     case AtomicOrdering::SequentiallyConsistent:
21420b57cec5SDimitry Andric       return AtomicOrdering::SequentiallyConsistent;
21430b57cec5SDimitry Andric     }
21440b57cec5SDimitry Andric     llvm_unreachable("Unknown ordering");
21450b57cec5SDimitry Andric   }
21460b57cec5SDimitry Andric 
2147e8d8bef9SDimitry Andric   Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
2148e8d8bef9SDimitry Andric     constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2149e8d8bef9SDimitry Andric     uint32_t OrderingTable[NumOrderings] = {};
2150e8d8bef9SDimitry Andric 
2151e8d8bef9SDimitry Andric     OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2152e8d8bef9SDimitry Andric         OrderingTable[(int)AtomicOrderingCABI::release] =
2153e8d8bef9SDimitry Andric             (int)AtomicOrderingCABI::release;
2154e8d8bef9SDimitry Andric     OrderingTable[(int)AtomicOrderingCABI::consume] =
2155e8d8bef9SDimitry Andric         OrderingTable[(int)AtomicOrderingCABI::acquire] =
2156e8d8bef9SDimitry Andric             OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
2157e8d8bef9SDimitry Andric                 (int)AtomicOrderingCABI::acq_rel;
2158e8d8bef9SDimitry Andric     OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2159e8d8bef9SDimitry Andric         (int)AtomicOrderingCABI::seq_cst;
2160e8d8bef9SDimitry Andric 
2161*0fca6ea1SDimitry Andric     return ConstantDataVector::get(IRB.getContext(), OrderingTable);
2162e8d8bef9SDimitry Andric   }
2163e8d8bef9SDimitry Andric 
21640b57cec5SDimitry Andric   AtomicOrdering addAcquireOrdering(AtomicOrdering a) {
21650b57cec5SDimitry Andric     switch (a) {
21660b57cec5SDimitry Andric     case AtomicOrdering::NotAtomic:
21670b57cec5SDimitry Andric       return AtomicOrdering::NotAtomic;
21680b57cec5SDimitry Andric     case AtomicOrdering::Unordered:
21690b57cec5SDimitry Andric     case AtomicOrdering::Monotonic:
21700b57cec5SDimitry Andric     case AtomicOrdering::Acquire:
21710b57cec5SDimitry Andric       return AtomicOrdering::Acquire;
21720b57cec5SDimitry Andric     case AtomicOrdering::Release:
21730b57cec5SDimitry Andric     case AtomicOrdering::AcquireRelease:
21740b57cec5SDimitry Andric       return AtomicOrdering::AcquireRelease;
21750b57cec5SDimitry Andric     case AtomicOrdering::SequentiallyConsistent:
21760b57cec5SDimitry Andric       return AtomicOrdering::SequentiallyConsistent;
21770b57cec5SDimitry Andric     }
21780b57cec5SDimitry Andric     llvm_unreachable("Unknown ordering");
21790b57cec5SDimitry Andric   }
21800b57cec5SDimitry Andric 
2181e8d8bef9SDimitry Andric   Value *makeAddAcquireOrderingTable(IRBuilder<> &IRB) {
2182e8d8bef9SDimitry Andric     constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2183e8d8bef9SDimitry Andric     uint32_t OrderingTable[NumOrderings] = {};
2184e8d8bef9SDimitry Andric 
2185e8d8bef9SDimitry Andric     OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2186e8d8bef9SDimitry Andric         OrderingTable[(int)AtomicOrderingCABI::acquire] =
2187e8d8bef9SDimitry Andric             OrderingTable[(int)AtomicOrderingCABI::consume] =
2188e8d8bef9SDimitry Andric                 (int)AtomicOrderingCABI::acquire;
2189e8d8bef9SDimitry Andric     OrderingTable[(int)AtomicOrderingCABI::release] =
2190e8d8bef9SDimitry Andric         OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
2191e8d8bef9SDimitry Andric             (int)AtomicOrderingCABI::acq_rel;
2192e8d8bef9SDimitry Andric     OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2193e8d8bef9SDimitry Andric         (int)AtomicOrderingCABI::seq_cst;
2194e8d8bef9SDimitry Andric 
2195*0fca6ea1SDimitry Andric     return ConstantDataVector::get(IRB.getContext(), OrderingTable);
2196e8d8bef9SDimitry Andric   }
2197e8d8bef9SDimitry Andric 
21980b57cec5SDimitry Andric   // ------------------- Visitors.
21990b57cec5SDimitry Andric   using InstVisitor<MemorySanitizerVisitor>::visit;
22000b57cec5SDimitry Andric   void visit(Instruction &I) {
220181ad6265SDimitry Andric     if (I.getMetadata(LLVMContext::MD_nosanitize))
2202e8d8bef9SDimitry Andric       return;
2203e8d8bef9SDimitry Andric     // Don't want to visit if we're in the prologue
2204e8d8bef9SDimitry Andric     if (isInPrologue(I))
2205e8d8bef9SDimitry Andric       return;
2206*0fca6ea1SDimitry Andric     if (!DebugCounter::shouldExecute(DebugInstrumentInstruction)) {
2207*0fca6ea1SDimitry Andric       LLVM_DEBUG(dbgs() << "Skipping instruction: " << I << "\n");
2208*0fca6ea1SDimitry Andric       // We still need to set the shadow and origin to clean values.
2209*0fca6ea1SDimitry Andric       setShadow(&I, getCleanShadow(&I));
2210*0fca6ea1SDimitry Andric       setOrigin(&I, getCleanOrigin());
2211*0fca6ea1SDimitry Andric       return;
2212*0fca6ea1SDimitry Andric     }
2213*0fca6ea1SDimitry Andric 
2214*0fca6ea1SDimitry Andric     Instructions.push_back(&I);
22150b57cec5SDimitry Andric   }
22160b57cec5SDimitry Andric 
22170b57cec5SDimitry Andric   /// Instrument LoadInst
22180b57cec5SDimitry Andric   ///
22190b57cec5SDimitry Andric   /// Loads the corresponding shadow and (optionally) origin.
22200b57cec5SDimitry Andric   /// Optionally, checks that the load address is fully defined.
22210b57cec5SDimitry Andric   void visitLoadInst(LoadInst &I) {
22220b57cec5SDimitry Andric     assert(I.getType()->isSized() && "Load type must have size");
222381ad6265SDimitry Andric     assert(!I.getMetadata(LLVMContext::MD_nosanitize));
2224bdd1243dSDimitry Andric     NextNodeIRBuilder IRB(&I);
22250b57cec5SDimitry Andric     Type *ShadowTy = getShadowTy(&I);
22260b57cec5SDimitry Andric     Value *Addr = I.getPointerOperand();
2227480093f4SDimitry Andric     Value *ShadowPtr = nullptr, *OriginPtr = nullptr;
222881ad6265SDimitry Andric     const Align Alignment = I.getAlign();
22290b57cec5SDimitry Andric     if (PropagateShadow) {
22300b57cec5SDimitry Andric       std::tie(ShadowPtr, OriginPtr) =
22310b57cec5SDimitry Andric           getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ false);
22325ffd83dbSDimitry Andric       setShadow(&I,
22335ffd83dbSDimitry Andric                 IRB.CreateAlignedLoad(ShadowTy, ShadowPtr, Alignment, "_msld"));
22340b57cec5SDimitry Andric     } else {
22350b57cec5SDimitry Andric       setShadow(&I, getCleanShadow(&I));
22360b57cec5SDimitry Andric     }
22370b57cec5SDimitry Andric 
22380b57cec5SDimitry Andric     if (ClCheckAccessAddress)
22390b57cec5SDimitry Andric       insertShadowCheck(I.getPointerOperand(), &I);
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric     if (I.isAtomic())
22420b57cec5SDimitry Andric       I.setOrdering(addAcquireOrdering(I.getOrdering()));
22430b57cec5SDimitry Andric 
22440b57cec5SDimitry Andric     if (MS.TrackOrigins) {
22450b57cec5SDimitry Andric       if (PropagateShadow) {
2246480093f4SDimitry Andric         const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);
22475ffd83dbSDimitry Andric         setOrigin(
22485ffd83dbSDimitry Andric             &I, IRB.CreateAlignedLoad(MS.OriginTy, OriginPtr, OriginAlignment));
22490b57cec5SDimitry Andric       } else {
22500b57cec5SDimitry Andric         setOrigin(&I, getCleanOrigin());
22510b57cec5SDimitry Andric       }
22520b57cec5SDimitry Andric     }
22530b57cec5SDimitry Andric   }
22540b57cec5SDimitry Andric 
22550b57cec5SDimitry Andric   /// Instrument StoreInst
22560b57cec5SDimitry Andric   ///
22570b57cec5SDimitry Andric   /// Stores the corresponding shadow and (optionally) origin.
22580b57cec5SDimitry Andric   /// Optionally, checks that the store address is fully defined.
22590b57cec5SDimitry Andric   void visitStoreInst(StoreInst &I) {
22600b57cec5SDimitry Andric     StoreList.push_back(&I);
22610b57cec5SDimitry Andric     if (ClCheckAccessAddress)
22620b57cec5SDimitry Andric       insertShadowCheck(I.getPointerOperand(), &I);
22630b57cec5SDimitry Andric   }
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric   void handleCASOrRMW(Instruction &I) {
22660b57cec5SDimitry Andric     assert(isa<AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I));
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
22690b57cec5SDimitry Andric     Value *Addr = I.getOperand(0);
2270fe6060f1SDimitry Andric     Value *Val = I.getOperand(1);
2271bdd1243dSDimitry Andric     Value *ShadowPtr = getShadowOriginPtr(Addr, IRB, getShadowTy(Val), Align(1),
2272480093f4SDimitry Andric                                           /*isStore*/ true)
22730b57cec5SDimitry Andric                            .first;
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric     if (ClCheckAccessAddress)
22760b57cec5SDimitry Andric       insertShadowCheck(Addr, &I);
22770b57cec5SDimitry Andric 
22780b57cec5SDimitry Andric     // Only test the conditional argument of cmpxchg instruction.
22790b57cec5SDimitry Andric     // The other argument can potentially be uninitialized, but we can not
22800b57cec5SDimitry Andric     // detect this situation reliably without possible false positives.
22810b57cec5SDimitry Andric     if (isa<AtomicCmpXchgInst>(I))
2282fe6060f1SDimitry Andric       insertShadowCheck(Val, &I);
22830b57cec5SDimitry Andric 
2284fe6060f1SDimitry Andric     IRB.CreateStore(getCleanShadow(Val), ShadowPtr);
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
22870b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
22880b57cec5SDimitry Andric   }
22890b57cec5SDimitry Andric 
22900b57cec5SDimitry Andric   void visitAtomicRMWInst(AtomicRMWInst &I) {
22910b57cec5SDimitry Andric     handleCASOrRMW(I);
22920b57cec5SDimitry Andric     I.setOrdering(addReleaseOrdering(I.getOrdering()));
22930b57cec5SDimitry Andric   }
22940b57cec5SDimitry Andric 
22950b57cec5SDimitry Andric   void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
22960b57cec5SDimitry Andric     handleCASOrRMW(I);
22970b57cec5SDimitry Andric     I.setSuccessOrdering(addReleaseOrdering(I.getSuccessOrdering()));
22980b57cec5SDimitry Andric   }
22990b57cec5SDimitry Andric 
23000b57cec5SDimitry Andric   // Vector manipulation.
23010b57cec5SDimitry Andric   void visitExtractElementInst(ExtractElementInst &I) {
23020b57cec5SDimitry Andric     insertShadowCheck(I.getOperand(1), &I);
23030b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23040b57cec5SDimitry Andric     setShadow(&I, IRB.CreateExtractElement(getShadow(&I, 0), I.getOperand(1),
23050b57cec5SDimitry Andric                                            "_msprop"));
23060b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23070b57cec5SDimitry Andric   }
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric   void visitInsertElementInst(InsertElementInst &I) {
23100b57cec5SDimitry Andric     insertShadowCheck(I.getOperand(2), &I);
23110b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
2312bdd1243dSDimitry Andric     auto *Shadow0 = getShadow(&I, 0);
2313bdd1243dSDimitry Andric     auto *Shadow1 = getShadow(&I, 1);
2314bdd1243dSDimitry Andric     setShadow(&I, IRB.CreateInsertElement(Shadow0, Shadow1, I.getOperand(2),
2315bdd1243dSDimitry Andric                                           "_msprop"));
23160b57cec5SDimitry Andric     setOriginForNaryOp(I);
23170b57cec5SDimitry Andric   }
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric   void visitShuffleVectorInst(ShuffleVectorInst &I) {
23200b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
2321bdd1243dSDimitry Andric     auto *Shadow0 = getShadow(&I, 0);
2322bdd1243dSDimitry Andric     auto *Shadow1 = getShadow(&I, 1);
2323bdd1243dSDimitry Andric     setShadow(&I, IRB.CreateShuffleVector(Shadow0, Shadow1, I.getShuffleMask(),
2324bdd1243dSDimitry Andric                                           "_msprop"));
23250b57cec5SDimitry Andric     setOriginForNaryOp(I);
23260b57cec5SDimitry Andric   }
23270b57cec5SDimitry Andric 
23280b57cec5SDimitry Andric   // Casts.
23290b57cec5SDimitry Andric   void visitSExtInst(SExtInst &I) {
23300b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23310b57cec5SDimitry Andric     setShadow(&I, IRB.CreateSExt(getShadow(&I, 0), I.getType(), "_msprop"));
23320b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23330b57cec5SDimitry Andric   }
23340b57cec5SDimitry Andric 
23350b57cec5SDimitry Andric   void visitZExtInst(ZExtInst &I) {
23360b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23370b57cec5SDimitry Andric     setShadow(&I, IRB.CreateZExt(getShadow(&I, 0), I.getType(), "_msprop"));
23380b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23390b57cec5SDimitry Andric   }
23400b57cec5SDimitry Andric 
23410b57cec5SDimitry Andric   void visitTruncInst(TruncInst &I) {
23420b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23430b57cec5SDimitry Andric     setShadow(&I, IRB.CreateTrunc(getShadow(&I, 0), I.getType(), "_msprop"));
23440b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23450b57cec5SDimitry Andric   }
23460b57cec5SDimitry Andric 
23470b57cec5SDimitry Andric   void visitBitCastInst(BitCastInst &I) {
23480b57cec5SDimitry Andric     // Special case: if this is the bitcast (there is exactly 1 allowed) between
23490b57cec5SDimitry Andric     // a musttail call and a ret, don't instrument. New instructions are not
23500b57cec5SDimitry Andric     // allowed after a musttail call.
23510b57cec5SDimitry Andric     if (auto *CI = dyn_cast<CallInst>(I.getOperand(0)))
23520b57cec5SDimitry Andric       if (CI->isMustTailCall())
23530b57cec5SDimitry Andric         return;
23540b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23550b57cec5SDimitry Andric     setShadow(&I, IRB.CreateBitCast(getShadow(&I, 0), getShadowTy(&I)));
23560b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23570b57cec5SDimitry Andric   }
23580b57cec5SDimitry Andric 
23590b57cec5SDimitry Andric   void visitPtrToIntInst(PtrToIntInst &I) {
23600b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23610b57cec5SDimitry Andric     setShadow(&I, IRB.CreateIntCast(getShadow(&I, 0), getShadowTy(&I), false,
23620b57cec5SDimitry Andric                                     "_msprop_ptrtoint"));
23630b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23640b57cec5SDimitry Andric   }
23650b57cec5SDimitry Andric 
23660b57cec5SDimitry Andric   void visitIntToPtrInst(IntToPtrInst &I) {
23670b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23680b57cec5SDimitry Andric     setShadow(&I, IRB.CreateIntCast(getShadow(&I, 0), getShadowTy(&I), false,
23690b57cec5SDimitry Andric                                     "_msprop_inttoptr"));
23700b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
23710b57cec5SDimitry Andric   }
23720b57cec5SDimitry Andric 
23730b57cec5SDimitry Andric   void visitFPToSIInst(CastInst &I) { handleShadowOr(I); }
23740b57cec5SDimitry Andric   void visitFPToUIInst(CastInst &I) { handleShadowOr(I); }
23750b57cec5SDimitry Andric   void visitSIToFPInst(CastInst &I) { handleShadowOr(I); }
23760b57cec5SDimitry Andric   void visitUIToFPInst(CastInst &I) { handleShadowOr(I); }
23770b57cec5SDimitry Andric   void visitFPExtInst(CastInst &I) { handleShadowOr(I); }
23780b57cec5SDimitry Andric   void visitFPTruncInst(CastInst &I) { handleShadowOr(I); }
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric   /// Propagate shadow for bitwise AND.
23810b57cec5SDimitry Andric   ///
23820b57cec5SDimitry Andric   /// This code is exact, i.e. if, for example, a bit in the left argument
23830b57cec5SDimitry Andric   /// is defined and 0, then neither the value not definedness of the
23840b57cec5SDimitry Andric   /// corresponding bit in B don't affect the resulting shadow.
23850b57cec5SDimitry Andric   void visitAnd(BinaryOperator &I) {
23860b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
23870b57cec5SDimitry Andric     //  "And" of 0 and a poisoned value results in unpoisoned value.
23880b57cec5SDimitry Andric     //  1&1 => 1;     0&1 => 0;     p&1 => p;
23890b57cec5SDimitry Andric     //  1&0 => 0;     0&0 => 0;     p&0 => 0;
23900b57cec5SDimitry Andric     //  1&p => p;     0&p => 0;     p&p => p;
23910b57cec5SDimitry Andric     //  S = (S1 & S2) | (V1 & S2) | (S1 & V2)
23920b57cec5SDimitry Andric     Value *S1 = getShadow(&I, 0);
23930b57cec5SDimitry Andric     Value *S2 = getShadow(&I, 1);
23940b57cec5SDimitry Andric     Value *V1 = I.getOperand(0);
23950b57cec5SDimitry Andric     Value *V2 = I.getOperand(1);
23960b57cec5SDimitry Andric     if (V1->getType() != S1->getType()) {
23970b57cec5SDimitry Andric       V1 = IRB.CreateIntCast(V1, S1->getType(), false);
23980b57cec5SDimitry Andric       V2 = IRB.CreateIntCast(V2, S2->getType(), false);
23990b57cec5SDimitry Andric     }
24000b57cec5SDimitry Andric     Value *S1S2 = IRB.CreateAnd(S1, S2);
24010b57cec5SDimitry Andric     Value *V1S2 = IRB.CreateAnd(V1, S2);
24020b57cec5SDimitry Andric     Value *S1V2 = IRB.CreateAnd(S1, V2);
24030b57cec5SDimitry Andric     setShadow(&I, IRB.CreateOr({S1S2, V1S2, S1V2}));
24040b57cec5SDimitry Andric     setOriginForNaryOp(I);
24050b57cec5SDimitry Andric   }
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric   void visitOr(BinaryOperator &I) {
24080b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
24090b57cec5SDimitry Andric     //  "Or" of 1 and a poisoned value results in unpoisoned value.
24100b57cec5SDimitry Andric     //  1|1 => 1;     0|1 => 1;     p|1 => 1;
24110b57cec5SDimitry Andric     //  1|0 => 1;     0|0 => 0;     p|0 => p;
24120b57cec5SDimitry Andric     //  1|p => 1;     0|p => p;     p|p => p;
24130b57cec5SDimitry Andric     //  S = (S1 & S2) | (~V1 & S2) | (S1 & ~V2)
24140b57cec5SDimitry Andric     Value *S1 = getShadow(&I, 0);
24150b57cec5SDimitry Andric     Value *S2 = getShadow(&I, 1);
24160b57cec5SDimitry Andric     Value *V1 = IRB.CreateNot(I.getOperand(0));
24170b57cec5SDimitry Andric     Value *V2 = IRB.CreateNot(I.getOperand(1));
24180b57cec5SDimitry Andric     if (V1->getType() != S1->getType()) {
24190b57cec5SDimitry Andric       V1 = IRB.CreateIntCast(V1, S1->getType(), false);
24200b57cec5SDimitry Andric       V2 = IRB.CreateIntCast(V2, S2->getType(), false);
24210b57cec5SDimitry Andric     }
24220b57cec5SDimitry Andric     Value *S1S2 = IRB.CreateAnd(S1, S2);
24230b57cec5SDimitry Andric     Value *V1S2 = IRB.CreateAnd(V1, S2);
24240b57cec5SDimitry Andric     Value *S1V2 = IRB.CreateAnd(S1, V2);
24250b57cec5SDimitry Andric     setShadow(&I, IRB.CreateOr({S1S2, V1S2, S1V2}));
24260b57cec5SDimitry Andric     setOriginForNaryOp(I);
24270b57cec5SDimitry Andric   }
24280b57cec5SDimitry Andric 
24290b57cec5SDimitry Andric   /// Default propagation of shadow and/or origin.
24300b57cec5SDimitry Andric   ///
24310b57cec5SDimitry Andric   /// This class implements the general case of shadow propagation, used in all
24320b57cec5SDimitry Andric   /// cases where we don't know and/or don't care about what the operation
24330b57cec5SDimitry Andric   /// actually does. It converts all input shadow values to a common type
24340b57cec5SDimitry Andric   /// (extending or truncating as necessary), and bitwise OR's them.
24350b57cec5SDimitry Andric   ///
24360b57cec5SDimitry Andric   /// This is much cheaper than inserting checks (i.e. requiring inputs to be
24370b57cec5SDimitry Andric   /// fully initialized), and less prone to false positives.
24380b57cec5SDimitry Andric   ///
24390b57cec5SDimitry Andric   /// This class also implements the general case of origin propagation. For a
24400b57cec5SDimitry Andric   /// Nary operation, result origin is set to the origin of an argument that is
24410b57cec5SDimitry Andric   /// not entirely initialized. If there is more than one such arguments, the
24420b57cec5SDimitry Andric   /// rightmost of them is picked. It does not matter which one is picked if all
24430b57cec5SDimitry Andric   /// arguments are initialized.
2444bdd1243dSDimitry Andric   template <bool CombineShadow> class Combiner {
24450b57cec5SDimitry Andric     Value *Shadow = nullptr;
24460b57cec5SDimitry Andric     Value *Origin = nullptr;
24470b57cec5SDimitry Andric     IRBuilder<> &IRB;
24480b57cec5SDimitry Andric     MemorySanitizerVisitor *MSV;
24490b57cec5SDimitry Andric 
24500b57cec5SDimitry Andric   public:
24510b57cec5SDimitry Andric     Combiner(MemorySanitizerVisitor *MSV, IRBuilder<> &IRB)
24520b57cec5SDimitry Andric         : IRB(IRB), MSV(MSV) {}
24530b57cec5SDimitry Andric 
24540b57cec5SDimitry Andric     /// Add a pair of shadow and origin values to the mix.
24550b57cec5SDimitry Andric     Combiner &Add(Value *OpShadow, Value *OpOrigin) {
24560b57cec5SDimitry Andric       if (CombineShadow) {
24570b57cec5SDimitry Andric         assert(OpShadow);
24580b57cec5SDimitry Andric         if (!Shadow)
24590b57cec5SDimitry Andric           Shadow = OpShadow;
24600b57cec5SDimitry Andric         else {
24610b57cec5SDimitry Andric           OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
24620b57cec5SDimitry Andric           Shadow = IRB.CreateOr(Shadow, OpShadow, "_msprop");
24630b57cec5SDimitry Andric         }
24640b57cec5SDimitry Andric       }
24650b57cec5SDimitry Andric 
24660b57cec5SDimitry Andric       if (MSV->MS.TrackOrigins) {
24670b57cec5SDimitry Andric         assert(OpOrigin);
24680b57cec5SDimitry Andric         if (!Origin) {
24690b57cec5SDimitry Andric           Origin = OpOrigin;
24700b57cec5SDimitry Andric         } else {
24710b57cec5SDimitry Andric           Constant *ConstOrigin = dyn_cast<Constant>(OpOrigin);
24720b57cec5SDimitry Andric           // No point in adding something that might result in 0 origin value.
24730b57cec5SDimitry Andric           if (!ConstOrigin || !ConstOrigin->isNullValue()) {
247406c3fb27SDimitry Andric             Value *Cond = MSV->convertToBool(OpShadow, IRB);
24750b57cec5SDimitry Andric             Origin = IRB.CreateSelect(Cond, OpOrigin, Origin);
24760b57cec5SDimitry Andric           }
24770b57cec5SDimitry Andric         }
24780b57cec5SDimitry Andric       }
24790b57cec5SDimitry Andric       return *this;
24800b57cec5SDimitry Andric     }
24810b57cec5SDimitry Andric 
24820b57cec5SDimitry Andric     /// Add an application value to the mix.
24830b57cec5SDimitry Andric     Combiner &Add(Value *V) {
24840b57cec5SDimitry Andric       Value *OpShadow = MSV->getShadow(V);
24850b57cec5SDimitry Andric       Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) : nullptr;
24860b57cec5SDimitry Andric       return Add(OpShadow, OpOrigin);
24870b57cec5SDimitry Andric     }
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric     /// Set the current combined values as the given instruction's shadow
24900b57cec5SDimitry Andric     /// and origin.
24910b57cec5SDimitry Andric     void Done(Instruction *I) {
24920b57cec5SDimitry Andric       if (CombineShadow) {
24930b57cec5SDimitry Andric         assert(Shadow);
24940b57cec5SDimitry Andric         Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(I));
24950b57cec5SDimitry Andric         MSV->setShadow(I, Shadow);
24960b57cec5SDimitry Andric       }
24970b57cec5SDimitry Andric       if (MSV->MS.TrackOrigins) {
24980b57cec5SDimitry Andric         assert(Origin);
24990b57cec5SDimitry Andric         MSV->setOrigin(I, Origin);
25000b57cec5SDimitry Andric       }
25010b57cec5SDimitry Andric     }
2502*0fca6ea1SDimitry Andric 
2503*0fca6ea1SDimitry Andric     /// Store the current combined value at the specified origin
2504*0fca6ea1SDimitry Andric     /// location.
2505*0fca6ea1SDimitry Andric     void DoneAndStoreOrigin(TypeSize TS, Value *OriginPtr) {
2506*0fca6ea1SDimitry Andric       if (MSV->MS.TrackOrigins) {
2507*0fca6ea1SDimitry Andric         assert(Origin);
2508*0fca6ea1SDimitry Andric         MSV->paintOrigin(IRB, Origin, OriginPtr, TS, kMinOriginAlignment);
2509*0fca6ea1SDimitry Andric       }
2510*0fca6ea1SDimitry Andric     }
25110b57cec5SDimitry Andric   };
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric   using ShadowAndOriginCombiner = Combiner<true>;
25140b57cec5SDimitry Andric   using OriginCombiner = Combiner<false>;
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric   /// Propagate origin for arbitrary operation.
25170b57cec5SDimitry Andric   void setOriginForNaryOp(Instruction &I) {
2518bdd1243dSDimitry Andric     if (!MS.TrackOrigins)
2519bdd1243dSDimitry Andric       return;
25200b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
25210b57cec5SDimitry Andric     OriginCombiner OC(this, IRB);
2522fe6060f1SDimitry Andric     for (Use &Op : I.operands())
2523fe6060f1SDimitry Andric       OC.Add(Op.get());
25240b57cec5SDimitry Andric     OC.Done(&I);
25250b57cec5SDimitry Andric   }
25260b57cec5SDimitry Andric 
25270b57cec5SDimitry Andric   size_t VectorOrPrimitiveTypeSizeInBits(Type *Ty) {
25280b57cec5SDimitry Andric     assert(!(Ty->isVectorTy() && Ty->getScalarType()->isPointerTy()) &&
25290b57cec5SDimitry Andric            "Vector of pointers is not a valid shadow type");
25305ffd83dbSDimitry Andric     return Ty->isVectorTy() ? cast<FixedVectorType>(Ty)->getNumElements() *
25315ffd83dbSDimitry Andric                                   Ty->getScalarSizeInBits()
25325ffd83dbSDimitry Andric                             : Ty->getPrimitiveSizeInBits();
25330b57cec5SDimitry Andric   }
25340b57cec5SDimitry Andric 
25350b57cec5SDimitry Andric   /// Cast between two shadow types, extending or truncating as
25360b57cec5SDimitry Andric   /// necessary.
25370b57cec5SDimitry Andric   Value *CreateShadowCast(IRBuilder<> &IRB, Value *V, Type *dstTy,
25380b57cec5SDimitry Andric                           bool Signed = false) {
25390b57cec5SDimitry Andric     Type *srcTy = V->getType();
2540*0fca6ea1SDimitry Andric     if (srcTy == dstTy)
2541*0fca6ea1SDimitry Andric       return V;
25420b57cec5SDimitry Andric     size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
25430b57cec5SDimitry Andric     size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
25440b57cec5SDimitry Andric     if (srcSizeInBits > 1 && dstSizeInBits == 1)
25450b57cec5SDimitry Andric       return IRB.CreateICmpNE(V, getCleanShadow(V));
25460b57cec5SDimitry Andric 
25470b57cec5SDimitry Andric     if (dstTy->isIntegerTy() && srcTy->isIntegerTy())
25480b57cec5SDimitry Andric       return IRB.CreateIntCast(V, dstTy, Signed);
25490b57cec5SDimitry Andric     if (dstTy->isVectorTy() && srcTy->isVectorTy() &&
255006c3fb27SDimitry Andric         cast<VectorType>(dstTy)->getElementCount() ==
255106c3fb27SDimitry Andric             cast<VectorType>(srcTy)->getElementCount())
25520b57cec5SDimitry Andric       return IRB.CreateIntCast(V, dstTy, Signed);
25530b57cec5SDimitry Andric     Value *V1 = IRB.CreateBitCast(V, Type::getIntNTy(*MS.C, srcSizeInBits));
25540b57cec5SDimitry Andric     Value *V2 =
25550b57cec5SDimitry Andric         IRB.CreateIntCast(V1, Type::getIntNTy(*MS.C, dstSizeInBits), Signed);
25560b57cec5SDimitry Andric     return IRB.CreateBitCast(V2, dstTy);
25570b57cec5SDimitry Andric     // TODO: handle struct types.
25580b57cec5SDimitry Andric   }
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric   /// Cast an application value to the type of its own shadow.
25610b57cec5SDimitry Andric   Value *CreateAppToShadowCast(IRBuilder<> &IRB, Value *V) {
25620b57cec5SDimitry Andric     Type *ShadowTy = getShadowTy(V);
25630b57cec5SDimitry Andric     if (V->getType() == ShadowTy)
25640b57cec5SDimitry Andric       return V;
25650b57cec5SDimitry Andric     if (V->getType()->isPtrOrPtrVectorTy())
25660b57cec5SDimitry Andric       return IRB.CreatePtrToInt(V, ShadowTy);
25670b57cec5SDimitry Andric     else
25680b57cec5SDimitry Andric       return IRB.CreateBitCast(V, ShadowTy);
25690b57cec5SDimitry Andric   }
25700b57cec5SDimitry Andric 
25710b57cec5SDimitry Andric   /// Propagate shadow for arbitrary operation.
25720b57cec5SDimitry Andric   void handleShadowOr(Instruction &I) {
25730b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
25740b57cec5SDimitry Andric     ShadowAndOriginCombiner SC(this, IRB);
2575fe6060f1SDimitry Andric     for (Use &Op : I.operands())
2576fe6060f1SDimitry Andric       SC.Add(Op.get());
25770b57cec5SDimitry Andric     SC.Done(&I);
25780b57cec5SDimitry Andric   }
25790b57cec5SDimitry Andric 
25800b57cec5SDimitry Andric   void visitFNeg(UnaryOperator &I) { handleShadowOr(I); }
25810b57cec5SDimitry Andric 
25820b57cec5SDimitry Andric   // Handle multiplication by constant.
25830b57cec5SDimitry Andric   //
25840b57cec5SDimitry Andric   // Handle a special case of multiplication by constant that may have one or
25850b57cec5SDimitry Andric   // more zeros in the lower bits. This makes corresponding number of lower bits
25860b57cec5SDimitry Andric   // of the result zero as well. We model it by shifting the other operand
25870b57cec5SDimitry Andric   // shadow left by the required number of bits. Effectively, we transform
25880b57cec5SDimitry Andric   // (X * (A * 2**B)) to ((X << B) * A) and instrument (X << B) as (Sx << B).
25890b57cec5SDimitry Andric   // We use multiplication by 2**N instead of shift to cover the case of
25900b57cec5SDimitry Andric   // multiplication by 0, which may occur in some elements of a vector operand.
25910b57cec5SDimitry Andric   void handleMulByConstant(BinaryOperator &I, Constant *ConstArg,
25920b57cec5SDimitry Andric                            Value *OtherArg) {
25930b57cec5SDimitry Andric     Constant *ShadowMul;
25940b57cec5SDimitry Andric     Type *Ty = ConstArg->getType();
25955ffd83dbSDimitry Andric     if (auto *VTy = dyn_cast<VectorType>(Ty)) {
25965ffd83dbSDimitry Andric       unsigned NumElements = cast<FixedVectorType>(VTy)->getNumElements();
25975ffd83dbSDimitry Andric       Type *EltTy = VTy->getElementType();
25980b57cec5SDimitry Andric       SmallVector<Constant *, 16> Elements;
25990b57cec5SDimitry Andric       for (unsigned Idx = 0; Idx < NumElements; ++Idx) {
26000b57cec5SDimitry Andric         if (ConstantInt *Elt =
26010b57cec5SDimitry Andric                 dyn_cast<ConstantInt>(ConstArg->getAggregateElement(Idx))) {
26020b57cec5SDimitry Andric           const APInt &V = Elt->getValue();
260306c3fb27SDimitry Andric           APInt V2 = APInt(V.getBitWidth(), 1) << V.countr_zero();
26040b57cec5SDimitry Andric           Elements.push_back(ConstantInt::get(EltTy, V2));
26050b57cec5SDimitry Andric         } else {
26060b57cec5SDimitry Andric           Elements.push_back(ConstantInt::get(EltTy, 1));
26070b57cec5SDimitry Andric         }
26080b57cec5SDimitry Andric       }
26090b57cec5SDimitry Andric       ShadowMul = ConstantVector::get(Elements);
26100b57cec5SDimitry Andric     } else {
26110b57cec5SDimitry Andric       if (ConstantInt *Elt = dyn_cast<ConstantInt>(ConstArg)) {
26120b57cec5SDimitry Andric         const APInt &V = Elt->getValue();
261306c3fb27SDimitry Andric         APInt V2 = APInt(V.getBitWidth(), 1) << V.countr_zero();
26140b57cec5SDimitry Andric         ShadowMul = ConstantInt::get(Ty, V2);
26150b57cec5SDimitry Andric       } else {
26160b57cec5SDimitry Andric         ShadowMul = ConstantInt::get(Ty, 1);
26170b57cec5SDimitry Andric       }
26180b57cec5SDimitry Andric     }
26190b57cec5SDimitry Andric 
26200b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
26210b57cec5SDimitry Andric     setShadow(&I,
26220b57cec5SDimitry Andric               IRB.CreateMul(getShadow(OtherArg), ShadowMul, "msprop_mul_cst"));
26230b57cec5SDimitry Andric     setOrigin(&I, getOrigin(OtherArg));
26240b57cec5SDimitry Andric   }
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   void visitMul(BinaryOperator &I) {
26270b57cec5SDimitry Andric     Constant *constOp0 = dyn_cast<Constant>(I.getOperand(0));
26280b57cec5SDimitry Andric     Constant *constOp1 = dyn_cast<Constant>(I.getOperand(1));
26290b57cec5SDimitry Andric     if (constOp0 && !constOp1)
26300b57cec5SDimitry Andric       handleMulByConstant(I, constOp0, I.getOperand(1));
26310b57cec5SDimitry Andric     else if (constOp1 && !constOp0)
26320b57cec5SDimitry Andric       handleMulByConstant(I, constOp1, I.getOperand(0));
26330b57cec5SDimitry Andric     else
26340b57cec5SDimitry Andric       handleShadowOr(I);
26350b57cec5SDimitry Andric   }
26360b57cec5SDimitry Andric 
26370b57cec5SDimitry Andric   void visitFAdd(BinaryOperator &I) { handleShadowOr(I); }
26380b57cec5SDimitry Andric   void visitFSub(BinaryOperator &I) { handleShadowOr(I); }
26390b57cec5SDimitry Andric   void visitFMul(BinaryOperator &I) { handleShadowOr(I); }
26400b57cec5SDimitry Andric   void visitAdd(BinaryOperator &I) { handleShadowOr(I); }
26410b57cec5SDimitry Andric   void visitSub(BinaryOperator &I) { handleShadowOr(I); }
26420b57cec5SDimitry Andric   void visitXor(BinaryOperator &I) { handleShadowOr(I); }
26430b57cec5SDimitry Andric 
26440b57cec5SDimitry Andric   void handleIntegerDiv(Instruction &I) {
26450b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
26460b57cec5SDimitry Andric     // Strict on the second argument.
26470b57cec5SDimitry Andric     insertShadowCheck(I.getOperand(1), &I);
26480b57cec5SDimitry Andric     setShadow(&I, getShadow(&I, 0));
26490b57cec5SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
26500b57cec5SDimitry Andric   }
26510b57cec5SDimitry Andric 
26520b57cec5SDimitry Andric   void visitUDiv(BinaryOperator &I) { handleIntegerDiv(I); }
26530b57cec5SDimitry Andric   void visitSDiv(BinaryOperator &I) { handleIntegerDiv(I); }
26540b57cec5SDimitry Andric   void visitURem(BinaryOperator &I) { handleIntegerDiv(I); }
26550b57cec5SDimitry Andric   void visitSRem(BinaryOperator &I) { handleIntegerDiv(I); }
26560b57cec5SDimitry Andric 
26570b57cec5SDimitry Andric   // Floating point division is side-effect free. We can not require that the
26580b57cec5SDimitry Andric   // divisor is fully initialized and must propagate shadow. See PR37523.
26590b57cec5SDimitry Andric   void visitFDiv(BinaryOperator &I) { handleShadowOr(I); }
26600b57cec5SDimitry Andric   void visitFRem(BinaryOperator &I) { handleShadowOr(I); }
26610b57cec5SDimitry Andric 
26620b57cec5SDimitry Andric   /// Instrument == and != comparisons.
26630b57cec5SDimitry Andric   ///
26640b57cec5SDimitry Andric   /// Sometimes the comparison result is known even if some of the bits of the
26650b57cec5SDimitry Andric   /// arguments are not.
26660b57cec5SDimitry Andric   void handleEqualityComparison(ICmpInst &I) {
26670b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
26680b57cec5SDimitry Andric     Value *A = I.getOperand(0);
26690b57cec5SDimitry Andric     Value *B = I.getOperand(1);
26700b57cec5SDimitry Andric     Value *Sa = getShadow(A);
26710b57cec5SDimitry Andric     Value *Sb = getShadow(B);
26720b57cec5SDimitry Andric 
26730b57cec5SDimitry Andric     // Get rid of pointers and vectors of pointers.
26740b57cec5SDimitry Andric     // For ints (and vectors of ints), types of A and Sa match,
26750b57cec5SDimitry Andric     // and this is a no-op.
26760b57cec5SDimitry Andric     A = IRB.CreatePointerCast(A, Sa->getType());
26770b57cec5SDimitry Andric     B = IRB.CreatePointerCast(B, Sb->getType());
26780b57cec5SDimitry Andric 
26790b57cec5SDimitry Andric     // A == B  <==>  (C = A^B) == 0
26800b57cec5SDimitry Andric     // A != B  <==>  (C = A^B) != 0
26810b57cec5SDimitry Andric     // Sc = Sa | Sb
26820b57cec5SDimitry Andric     Value *C = IRB.CreateXor(A, B);
26830b57cec5SDimitry Andric     Value *Sc = IRB.CreateOr(Sa, Sb);
26840b57cec5SDimitry Andric     // Now dealing with i = (C == 0) comparison (or C != 0, does not matter now)
26850b57cec5SDimitry Andric     // Result is defined if one of the following is true
26860b57cec5SDimitry Andric     // * there is a defined 1 bit in C
26870b57cec5SDimitry Andric     // * C is fully defined
26880b57cec5SDimitry Andric     // Si = !(C & ~Sc) && Sc
26890b57cec5SDimitry Andric     Value *Zero = Constant::getNullValue(Sc->getType());
26900b57cec5SDimitry Andric     Value *MinusOne = Constant::getAllOnesValue(Sc->getType());
2691bdd1243dSDimitry Andric     Value *LHS = IRB.CreateICmpNE(Sc, Zero);
2692bdd1243dSDimitry Andric     Value *RHS =
2693bdd1243dSDimitry Andric         IRB.CreateICmpEQ(IRB.CreateAnd(IRB.CreateXor(Sc, MinusOne), C), Zero);
2694bdd1243dSDimitry Andric     Value *Si = IRB.CreateAnd(LHS, RHS);
26950b57cec5SDimitry Andric     Si->setName("_msprop_icmp");
26960b57cec5SDimitry Andric     setShadow(&I, Si);
26970b57cec5SDimitry Andric     setOriginForNaryOp(I);
26980b57cec5SDimitry Andric   }
26990b57cec5SDimitry Andric 
27000b57cec5SDimitry Andric   /// Build the lowest possible value of V, taking into account V's
27010b57cec5SDimitry Andric   ///        uninitialized bits.
27020b57cec5SDimitry Andric   Value *getLowestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,
27030b57cec5SDimitry Andric                                 bool isSigned) {
27040b57cec5SDimitry Andric     if (isSigned) {
27050b57cec5SDimitry Andric       // Split shadow into sign bit and other bits.
27060b57cec5SDimitry Andric       Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);
27070b57cec5SDimitry Andric       Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);
27080b57cec5SDimitry Andric       // Maximise the undefined shadow bit, minimize other undefined bits.
2709bdd1243dSDimitry Andric       return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaOtherBits)),
2710bdd1243dSDimitry Andric                           SaSignBit);
27110b57cec5SDimitry Andric     } else {
27120b57cec5SDimitry Andric       // Minimize undefined bits.
27130b57cec5SDimitry Andric       return IRB.CreateAnd(A, IRB.CreateNot(Sa));
27140b57cec5SDimitry Andric     }
27150b57cec5SDimitry Andric   }
27160b57cec5SDimitry Andric 
27170b57cec5SDimitry Andric   /// Build the highest possible value of V, taking into account V's
27180b57cec5SDimitry Andric   ///        uninitialized bits.
27190b57cec5SDimitry Andric   Value *getHighestPossibleValue(IRBuilder<> &IRB, Value *A, Value *Sa,
27200b57cec5SDimitry Andric                                  bool isSigned) {
27210b57cec5SDimitry Andric     if (isSigned) {
27220b57cec5SDimitry Andric       // Split shadow into sign bit and other bits.
27230b57cec5SDimitry Andric       Value *SaOtherBits = IRB.CreateLShr(IRB.CreateShl(Sa, 1), 1);
27240b57cec5SDimitry Andric       Value *SaSignBit = IRB.CreateXor(Sa, SaOtherBits);
27250b57cec5SDimitry Andric       // Minimise the undefined shadow bit, maximise other undefined bits.
2726bdd1243dSDimitry Andric       return IRB.CreateOr(IRB.CreateAnd(A, IRB.CreateNot(SaSignBit)),
2727bdd1243dSDimitry Andric                           SaOtherBits);
27280b57cec5SDimitry Andric     } else {
27290b57cec5SDimitry Andric       // Maximize undefined bits.
27300b57cec5SDimitry Andric       return IRB.CreateOr(A, Sa);
27310b57cec5SDimitry Andric     }
27320b57cec5SDimitry Andric   }
27330b57cec5SDimitry Andric 
27340b57cec5SDimitry Andric   /// Instrument relational comparisons.
27350b57cec5SDimitry Andric   ///
27360b57cec5SDimitry Andric   /// This function does exact shadow propagation for all relational
27370b57cec5SDimitry Andric   /// comparisons of integers, pointers and vectors of those.
27380b57cec5SDimitry Andric   /// FIXME: output seems suboptimal when one of the operands is a constant
27390b57cec5SDimitry Andric   void handleRelationalComparisonExact(ICmpInst &I) {
27400b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
27410b57cec5SDimitry Andric     Value *A = I.getOperand(0);
27420b57cec5SDimitry Andric     Value *B = I.getOperand(1);
27430b57cec5SDimitry Andric     Value *Sa = getShadow(A);
27440b57cec5SDimitry Andric     Value *Sb = getShadow(B);
27450b57cec5SDimitry Andric 
27460b57cec5SDimitry Andric     // Get rid of pointers and vectors of pointers.
27470b57cec5SDimitry Andric     // For ints (and vectors of ints), types of A and Sa match,
27480b57cec5SDimitry Andric     // and this is a no-op.
27490b57cec5SDimitry Andric     A = IRB.CreatePointerCast(A, Sa->getType());
27500b57cec5SDimitry Andric     B = IRB.CreatePointerCast(B, Sb->getType());
27510b57cec5SDimitry Andric 
27520b57cec5SDimitry Andric     // Let [a0, a1] be the interval of possible values of A, taking into account
27530b57cec5SDimitry Andric     // its undefined bits. Let [b0, b1] be the interval of possible values of B.
27540b57cec5SDimitry Andric     // Then (A cmp B) is defined iff (a0 cmp b1) == (a1 cmp b0).
27550b57cec5SDimitry Andric     bool IsSigned = I.isSigned();
27560b57cec5SDimitry Andric     Value *S1 = IRB.CreateICmp(I.getPredicate(),
27570b57cec5SDimitry Andric                                getLowestPossibleValue(IRB, A, Sa, IsSigned),
27580b57cec5SDimitry Andric                                getHighestPossibleValue(IRB, B, Sb, IsSigned));
27590b57cec5SDimitry Andric     Value *S2 = IRB.CreateICmp(I.getPredicate(),
27600b57cec5SDimitry Andric                                getHighestPossibleValue(IRB, A, Sa, IsSigned),
27610b57cec5SDimitry Andric                                getLowestPossibleValue(IRB, B, Sb, IsSigned));
27620b57cec5SDimitry Andric     Value *Si = IRB.CreateXor(S1, S2);
27630b57cec5SDimitry Andric     setShadow(&I, Si);
27640b57cec5SDimitry Andric     setOriginForNaryOp(I);
27650b57cec5SDimitry Andric   }
27660b57cec5SDimitry Andric 
27670b57cec5SDimitry Andric   /// Instrument signed relational comparisons.
27680b57cec5SDimitry Andric   ///
27690b57cec5SDimitry Andric   /// Handle sign bit tests: x<0, x>=0, x<=-1, x>-1 by propagating the highest
27700b57cec5SDimitry Andric   /// bit of the shadow. Everything else is delegated to handleShadowOr().
27710b57cec5SDimitry Andric   void handleSignedRelationalComparison(ICmpInst &I) {
27720b57cec5SDimitry Andric     Constant *constOp;
27730b57cec5SDimitry Andric     Value *op = nullptr;
27740b57cec5SDimitry Andric     CmpInst::Predicate pre;
27750b57cec5SDimitry Andric     if ((constOp = dyn_cast<Constant>(I.getOperand(1)))) {
27760b57cec5SDimitry Andric       op = I.getOperand(0);
27770b57cec5SDimitry Andric       pre = I.getPredicate();
27780b57cec5SDimitry Andric     } else if ((constOp = dyn_cast<Constant>(I.getOperand(0)))) {
27790b57cec5SDimitry Andric       op = I.getOperand(1);
27800b57cec5SDimitry Andric       pre = I.getSwappedPredicate();
27810b57cec5SDimitry Andric     } else {
27820b57cec5SDimitry Andric       handleShadowOr(I);
27830b57cec5SDimitry Andric       return;
27840b57cec5SDimitry Andric     }
27850b57cec5SDimitry Andric 
27860b57cec5SDimitry Andric     if ((constOp->isNullValue() &&
27870b57cec5SDimitry Andric          (pre == CmpInst::ICMP_SLT || pre == CmpInst::ICMP_SGE)) ||
27880b57cec5SDimitry Andric         (constOp->isAllOnesValue() &&
27890b57cec5SDimitry Andric          (pre == CmpInst::ICMP_SGT || pre == CmpInst::ICMP_SLE))) {
27900b57cec5SDimitry Andric       IRBuilder<> IRB(&I);
27910b57cec5SDimitry Andric       Value *Shadow = IRB.CreateICmpSLT(getShadow(op), getCleanShadow(op),
27920b57cec5SDimitry Andric                                         "_msprop_icmp_s");
27930b57cec5SDimitry Andric       setShadow(&I, Shadow);
27940b57cec5SDimitry Andric       setOrigin(&I, getOrigin(op));
27950b57cec5SDimitry Andric     } else {
27960b57cec5SDimitry Andric       handleShadowOr(I);
27970b57cec5SDimitry Andric     }
27980b57cec5SDimitry Andric   }
27990b57cec5SDimitry Andric 
28000b57cec5SDimitry Andric   void visitICmpInst(ICmpInst &I) {
28010b57cec5SDimitry Andric     if (!ClHandleICmp) {
28020b57cec5SDimitry Andric       handleShadowOr(I);
28030b57cec5SDimitry Andric       return;
28040b57cec5SDimitry Andric     }
28050b57cec5SDimitry Andric     if (I.isEquality()) {
28060b57cec5SDimitry Andric       handleEqualityComparison(I);
28070b57cec5SDimitry Andric       return;
28080b57cec5SDimitry Andric     }
28090b57cec5SDimitry Andric 
28100b57cec5SDimitry Andric     assert(I.isRelational());
28110b57cec5SDimitry Andric     if (ClHandleICmpExact) {
28120b57cec5SDimitry Andric       handleRelationalComparisonExact(I);
28130b57cec5SDimitry Andric       return;
28140b57cec5SDimitry Andric     }
28150b57cec5SDimitry Andric     if (I.isSigned()) {
28160b57cec5SDimitry Andric       handleSignedRelationalComparison(I);
28170b57cec5SDimitry Andric       return;
28180b57cec5SDimitry Andric     }
28190b57cec5SDimitry Andric 
28200b57cec5SDimitry Andric     assert(I.isUnsigned());
28210b57cec5SDimitry Andric     if ((isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
28220b57cec5SDimitry Andric       handleRelationalComparisonExact(I);
28230b57cec5SDimitry Andric       return;
28240b57cec5SDimitry Andric     }
28250b57cec5SDimitry Andric 
28260b57cec5SDimitry Andric     handleShadowOr(I);
28270b57cec5SDimitry Andric   }
28280b57cec5SDimitry Andric 
2829bdd1243dSDimitry Andric   void visitFCmpInst(FCmpInst &I) { handleShadowOr(I); }
28300b57cec5SDimitry Andric 
28310b57cec5SDimitry Andric   void handleShift(BinaryOperator &I) {
28320b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
28330b57cec5SDimitry Andric     // If any of the S2 bits are poisoned, the whole thing is poisoned.
28340b57cec5SDimitry Andric     // Otherwise perform the same shift on S1.
28350b57cec5SDimitry Andric     Value *S1 = getShadow(&I, 0);
28360b57cec5SDimitry Andric     Value *S2 = getShadow(&I, 1);
2837bdd1243dSDimitry Andric     Value *S2Conv =
2838bdd1243dSDimitry Andric         IRB.CreateSExt(IRB.CreateICmpNE(S2, getCleanShadow(S2)), S2->getType());
28390b57cec5SDimitry Andric     Value *V2 = I.getOperand(1);
28400b57cec5SDimitry Andric     Value *Shift = IRB.CreateBinOp(I.getOpcode(), S1, V2);
28410b57cec5SDimitry Andric     setShadow(&I, IRB.CreateOr(Shift, S2Conv));
28420b57cec5SDimitry Andric     setOriginForNaryOp(I);
28430b57cec5SDimitry Andric   }
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric   void visitShl(BinaryOperator &I) { handleShift(I); }
28460b57cec5SDimitry Andric   void visitAShr(BinaryOperator &I) { handleShift(I); }
28470b57cec5SDimitry Andric   void visitLShr(BinaryOperator &I) { handleShift(I); }
28480b57cec5SDimitry Andric 
2849fe6060f1SDimitry Andric   void handleFunnelShift(IntrinsicInst &I) {
2850fe6060f1SDimitry Andric     IRBuilder<> IRB(&I);
2851fe6060f1SDimitry Andric     // If any of the S2 bits are poisoned, the whole thing is poisoned.
2852fe6060f1SDimitry Andric     // Otherwise perform the same shift on S0 and S1.
2853fe6060f1SDimitry Andric     Value *S0 = getShadow(&I, 0);
2854fe6060f1SDimitry Andric     Value *S1 = getShadow(&I, 1);
2855fe6060f1SDimitry Andric     Value *S2 = getShadow(&I, 2);
2856fe6060f1SDimitry Andric     Value *S2Conv =
2857fe6060f1SDimitry Andric         IRB.CreateSExt(IRB.CreateICmpNE(S2, getCleanShadow(S2)), S2->getType());
2858fe6060f1SDimitry Andric     Value *V2 = I.getOperand(2);
2859fe6060f1SDimitry Andric     Function *Intrin = Intrinsic::getDeclaration(
2860fe6060f1SDimitry Andric         I.getModule(), I.getIntrinsicID(), S2Conv->getType());
2861fe6060f1SDimitry Andric     Value *Shift = IRB.CreateCall(Intrin, {S0, S1, V2});
2862fe6060f1SDimitry Andric     setShadow(&I, IRB.CreateOr(Shift, S2Conv));
2863fe6060f1SDimitry Andric     setOriginForNaryOp(I);
2864fe6060f1SDimitry Andric   }
2865fe6060f1SDimitry Andric 
28660b57cec5SDimitry Andric   /// Instrument llvm.memmove
28670b57cec5SDimitry Andric   ///
28680b57cec5SDimitry Andric   /// At this point we don't know if llvm.memmove will be inlined or not.
28690b57cec5SDimitry Andric   /// If we don't instrument it and it gets inlined,
28700b57cec5SDimitry Andric   /// our interceptor will not kick in and we will lose the memmove.
28710b57cec5SDimitry Andric   /// If we instrument the call here, but it does not get inlined,
28720b57cec5SDimitry Andric   /// we will memove the shadow twice: which is bad in case
28730b57cec5SDimitry Andric   /// of overlapping regions. So, we simply lower the intrinsic to a call.
28740b57cec5SDimitry Andric   ///
28750b57cec5SDimitry Andric   /// Similar situation exists for memcpy and memset.
28760b57cec5SDimitry Andric   void visitMemMoveInst(MemMoveInst &I) {
287781ad6265SDimitry Andric     getShadow(I.getArgOperand(1)); // Ensure shadow initialized
28780b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
28795f757f3fSDimitry Andric     IRB.CreateCall(MS.MemmoveFn,
28805f757f3fSDimitry Andric                    {I.getArgOperand(0), I.getArgOperand(1),
28810b57cec5SDimitry Andric                     IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
28820b57cec5SDimitry Andric     I.eraseFromParent();
28830b57cec5SDimitry Andric   }
28840b57cec5SDimitry Andric 
2885bdd1243dSDimitry Andric   /// Instrument memcpy
2886bdd1243dSDimitry Andric   ///
2887bdd1243dSDimitry Andric   /// Similar to memmove: avoid copying shadow twice. This is somewhat
2888bdd1243dSDimitry Andric   /// unfortunate as it may slowdown small constant memcpys.
2889bdd1243dSDimitry Andric   /// FIXME: consider doing manual inline for small constant sizes and proper
2890bdd1243dSDimitry Andric   /// alignment.
2891bdd1243dSDimitry Andric   ///
2892bdd1243dSDimitry Andric   /// Note: This also handles memcpy.inline, which promises no calls to external
2893bdd1243dSDimitry Andric   /// functions as an optimization. However, with instrumentation enabled this
2894bdd1243dSDimitry Andric   /// is difficult to promise; additionally, we know that the MSan runtime
2895bdd1243dSDimitry Andric   /// exists and provides __msan_memcpy(). Therefore, we assume that with
2896bdd1243dSDimitry Andric   /// instrumentation it's safe to turn memcpy.inline into a call to
2897bdd1243dSDimitry Andric   /// __msan_memcpy(). Should this be wrong, such as when implementing memcpy()
2898bdd1243dSDimitry Andric   /// itself, instrumentation should be disabled with the no_sanitize attribute.
28990b57cec5SDimitry Andric   void visitMemCpyInst(MemCpyInst &I) {
290081ad6265SDimitry Andric     getShadow(I.getArgOperand(1)); // Ensure shadow initialized
29010b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
29025f757f3fSDimitry Andric     IRB.CreateCall(MS.MemcpyFn,
29035f757f3fSDimitry Andric                    {I.getArgOperand(0), I.getArgOperand(1),
29040b57cec5SDimitry Andric                     IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
29050b57cec5SDimitry Andric     I.eraseFromParent();
29060b57cec5SDimitry Andric   }
29070b57cec5SDimitry Andric 
29080b57cec5SDimitry Andric   // Same as memcpy.
29090b57cec5SDimitry Andric   void visitMemSetInst(MemSetInst &I) {
29100b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
29110b57cec5SDimitry Andric     IRB.CreateCall(
29120b57cec5SDimitry Andric         MS.MemsetFn,
29135f757f3fSDimitry Andric         {I.getArgOperand(0),
29140b57cec5SDimitry Andric          IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
29150b57cec5SDimitry Andric          IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
29160b57cec5SDimitry Andric     I.eraseFromParent();
29170b57cec5SDimitry Andric   }
29180b57cec5SDimitry Andric 
2919bdd1243dSDimitry Andric   void visitVAStartInst(VAStartInst &I) { VAHelper->visitVAStartInst(I); }
29200b57cec5SDimitry Andric 
2921bdd1243dSDimitry Andric   void visitVACopyInst(VACopyInst &I) { VAHelper->visitVACopyInst(I); }
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric   /// Handle vector store-like intrinsics.
29240b57cec5SDimitry Andric   ///
29250b57cec5SDimitry Andric   /// Instrument intrinsics that look like a simple SIMD store: writes memory,
29260b57cec5SDimitry Andric   /// has 1 pointer argument and 1 vector argument, returns void.
29270b57cec5SDimitry Andric   bool handleVectorStoreIntrinsic(IntrinsicInst &I) {
29280b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
29290b57cec5SDimitry Andric     Value *Addr = I.getArgOperand(0);
29300b57cec5SDimitry Andric     Value *Shadow = getShadow(&I, 1);
29310b57cec5SDimitry Andric     Value *ShadowPtr, *OriginPtr;
29320b57cec5SDimitry Andric 
29330b57cec5SDimitry Andric     // We don't know the pointer alignment (could be unaligned SSE store!).
29340b57cec5SDimitry Andric     // Have to assume to worst case.
29350b57cec5SDimitry Andric     std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
29365ffd83dbSDimitry Andric         Addr, IRB, Shadow->getType(), Align(1), /*isStore*/ true);
29375ffd83dbSDimitry Andric     IRB.CreateAlignedStore(Shadow, ShadowPtr, Align(1));
29380b57cec5SDimitry Andric 
29390b57cec5SDimitry Andric     if (ClCheckAccessAddress)
29400b57cec5SDimitry Andric       insertShadowCheck(Addr, &I);
29410b57cec5SDimitry Andric 
29420b57cec5SDimitry Andric     // FIXME: factor out common code from materializeStores
2943bdd1243dSDimitry Andric     if (MS.TrackOrigins)
2944bdd1243dSDimitry Andric       IRB.CreateStore(getOrigin(&I, 1), OriginPtr);
29450b57cec5SDimitry Andric     return true;
29460b57cec5SDimitry Andric   }
29470b57cec5SDimitry Andric 
29480b57cec5SDimitry Andric   /// Handle vector load-like intrinsics.
29490b57cec5SDimitry Andric   ///
29500b57cec5SDimitry Andric   /// Instrument intrinsics that look like a simple SIMD load: reads memory,
29510b57cec5SDimitry Andric   /// has 1 pointer argument, returns a vector.
29520b57cec5SDimitry Andric   bool handleVectorLoadIntrinsic(IntrinsicInst &I) {
29530b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
29540b57cec5SDimitry Andric     Value *Addr = I.getArgOperand(0);
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric     Type *ShadowTy = getShadowTy(&I);
2957480093f4SDimitry Andric     Value *ShadowPtr = nullptr, *OriginPtr = nullptr;
29580b57cec5SDimitry Andric     if (PropagateShadow) {
29590b57cec5SDimitry Andric       // We don't know the pointer alignment (could be unaligned SSE load!).
29600b57cec5SDimitry Andric       // Have to assume to worst case.
29615ffd83dbSDimitry Andric       const Align Alignment = Align(1);
29620b57cec5SDimitry Andric       std::tie(ShadowPtr, OriginPtr) =
29630b57cec5SDimitry Andric           getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment, /*isStore*/ false);
29645ffd83dbSDimitry Andric       setShadow(&I,
29655ffd83dbSDimitry Andric                 IRB.CreateAlignedLoad(ShadowTy, ShadowPtr, Alignment, "_msld"));
29660b57cec5SDimitry Andric     } else {
29670b57cec5SDimitry Andric       setShadow(&I, getCleanShadow(&I));
29680b57cec5SDimitry Andric     }
29690b57cec5SDimitry Andric 
29700b57cec5SDimitry Andric     if (ClCheckAccessAddress)
29710b57cec5SDimitry Andric       insertShadowCheck(Addr, &I);
29720b57cec5SDimitry Andric 
29730b57cec5SDimitry Andric     if (MS.TrackOrigins) {
29740b57cec5SDimitry Andric       if (PropagateShadow)
29750b57cec5SDimitry Andric         setOrigin(&I, IRB.CreateLoad(MS.OriginTy, OriginPtr));
29760b57cec5SDimitry Andric       else
29770b57cec5SDimitry Andric         setOrigin(&I, getCleanOrigin());
29780b57cec5SDimitry Andric     }
29790b57cec5SDimitry Andric     return true;
29800b57cec5SDimitry Andric   }
29810b57cec5SDimitry Andric 
29820b57cec5SDimitry Andric   /// Handle (SIMD arithmetic)-like intrinsics.
29830b57cec5SDimitry Andric   ///
29840b57cec5SDimitry Andric   /// Instrument intrinsics with any number of arguments of the same type,
29850b57cec5SDimitry Andric   /// equal to the return type. The type should be simple (no aggregates or
29860b57cec5SDimitry Andric   /// pointers; vectors are fine).
29870b57cec5SDimitry Andric   /// Caller guarantees that this intrinsic does not access memory.
29880b57cec5SDimitry Andric   bool maybeHandleSimpleNomemIntrinsic(IntrinsicInst &I) {
29890b57cec5SDimitry Andric     Type *RetTy = I.getType();
2990bdd1243dSDimitry Andric     if (!(RetTy->isIntOrIntVectorTy() || RetTy->isFPOrFPVectorTy() ||
29910b57cec5SDimitry Andric           RetTy->isX86_MMXTy()))
29920b57cec5SDimitry Andric       return false;
29930b57cec5SDimitry Andric 
2994349cc55cSDimitry Andric     unsigned NumArgOperands = I.arg_size();
29950b57cec5SDimitry Andric     for (unsigned i = 0; i < NumArgOperands; ++i) {
29960b57cec5SDimitry Andric       Type *Ty = I.getArgOperand(i)->getType();
29970b57cec5SDimitry Andric       if (Ty != RetTy)
29980b57cec5SDimitry Andric         return false;
29990b57cec5SDimitry Andric     }
30000b57cec5SDimitry Andric 
30010b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
30020b57cec5SDimitry Andric     ShadowAndOriginCombiner SC(this, IRB);
30030b57cec5SDimitry Andric     for (unsigned i = 0; i < NumArgOperands; ++i)
30040b57cec5SDimitry Andric       SC.Add(I.getArgOperand(i));
30050b57cec5SDimitry Andric     SC.Done(&I);
30060b57cec5SDimitry Andric 
30070b57cec5SDimitry Andric     return true;
30080b57cec5SDimitry Andric   }
30090b57cec5SDimitry Andric 
30100b57cec5SDimitry Andric   /// Heuristically instrument unknown intrinsics.
30110b57cec5SDimitry Andric   ///
30120b57cec5SDimitry Andric   /// The main purpose of this code is to do something reasonable with all
30130b57cec5SDimitry Andric   /// random intrinsics we might encounter, most importantly - SIMD intrinsics.
30140b57cec5SDimitry Andric   /// We recognize several classes of intrinsics by their argument types and
30155ffd83dbSDimitry Andric   /// ModRefBehaviour and apply special instrumentation when we are reasonably
30160b57cec5SDimitry Andric   /// sure that we know what the intrinsic does.
30170b57cec5SDimitry Andric   ///
30180b57cec5SDimitry Andric   /// We special-case intrinsics where this approach fails. See llvm.bswap
30190b57cec5SDimitry Andric   /// handling as an example of that.
30200b57cec5SDimitry Andric   bool handleUnknownIntrinsic(IntrinsicInst &I) {
3021349cc55cSDimitry Andric     unsigned NumArgOperands = I.arg_size();
30220b57cec5SDimitry Andric     if (NumArgOperands == 0)
30230b57cec5SDimitry Andric       return false;
30240b57cec5SDimitry Andric 
3025bdd1243dSDimitry Andric     if (NumArgOperands == 2 && I.getArgOperand(0)->getType()->isPointerTy() &&
30260b57cec5SDimitry Andric         I.getArgOperand(1)->getType()->isVectorTy() &&
3027bdd1243dSDimitry Andric         I.getType()->isVoidTy() && !I.onlyReadsMemory()) {
30280b57cec5SDimitry Andric       // This looks like a vector store.
30290b57cec5SDimitry Andric       return handleVectorStoreIntrinsic(I);
30300b57cec5SDimitry Andric     }
30310b57cec5SDimitry Andric 
3032bdd1243dSDimitry Andric     if (NumArgOperands == 1 && I.getArgOperand(0)->getType()->isPointerTy() &&
3033bdd1243dSDimitry Andric         I.getType()->isVectorTy() && I.onlyReadsMemory()) {
30340b57cec5SDimitry Andric       // This looks like a vector load.
30350b57cec5SDimitry Andric       return handleVectorLoadIntrinsic(I);
30360b57cec5SDimitry Andric     }
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric     if (I.doesNotAccessMemory())
30390b57cec5SDimitry Andric       if (maybeHandleSimpleNomemIntrinsic(I))
30400b57cec5SDimitry Andric         return true;
30410b57cec5SDimitry Andric 
30420b57cec5SDimitry Andric     // FIXME: detect and handle SSE maskstore/maskload
30430b57cec5SDimitry Andric     return false;
30440b57cec5SDimitry Andric   }
30450b57cec5SDimitry Andric 
30468bcb0991SDimitry Andric   void handleInvariantGroup(IntrinsicInst &I) {
30478bcb0991SDimitry Andric     setShadow(&I, getShadow(&I, 0));
30488bcb0991SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
30498bcb0991SDimitry Andric   }
30508bcb0991SDimitry Andric 
30510b57cec5SDimitry Andric   void handleLifetimeStart(IntrinsicInst &I) {
30520b57cec5SDimitry Andric     if (!PoisonStack)
30530b57cec5SDimitry Andric       return;
3054e8d8bef9SDimitry Andric     AllocaInst *AI = llvm::findAllocaForValue(I.getArgOperand(1));
30550b57cec5SDimitry Andric     if (!AI)
30560b57cec5SDimitry Andric       InstrumentLifetimeStart = false;
30570b57cec5SDimitry Andric     LifetimeStartList.push_back(std::make_pair(&I, AI));
30580b57cec5SDimitry Andric   }
30590b57cec5SDimitry Andric 
30600b57cec5SDimitry Andric   void handleBswap(IntrinsicInst &I) {
30610b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
30620b57cec5SDimitry Andric     Value *Op = I.getArgOperand(0);
30630b57cec5SDimitry Andric     Type *OpType = Op->getType();
30640b57cec5SDimitry Andric     Function *BswapFunc = Intrinsic::getDeclaration(
3065bdd1243dSDimitry Andric         F.getParent(), Intrinsic::bswap, ArrayRef(&OpType, 1));
30660b57cec5SDimitry Andric     setShadow(&I, IRB.CreateCall(BswapFunc, getShadow(Op)));
30670b57cec5SDimitry Andric     setOrigin(&I, getOrigin(Op));
30680b57cec5SDimitry Andric   }
30690b57cec5SDimitry Andric 
3070bdd1243dSDimitry Andric   void handleCountZeroes(IntrinsicInst &I) {
3071bdd1243dSDimitry Andric     IRBuilder<> IRB(&I);
3072bdd1243dSDimitry Andric     Value *Src = I.getArgOperand(0);
3073bdd1243dSDimitry Andric 
3074bdd1243dSDimitry Andric     // Set the Output shadow based on input Shadow
3075bdd1243dSDimitry Andric     Value *BoolShadow = IRB.CreateIsNotNull(getShadow(Src), "_mscz_bs");
3076bdd1243dSDimitry Andric 
3077bdd1243dSDimitry Andric     // If zero poison is requested, mix in with the shadow
3078bdd1243dSDimitry Andric     Constant *IsZeroPoison = cast<Constant>(I.getOperand(1));
3079bdd1243dSDimitry Andric     if (!IsZeroPoison->isZeroValue()) {
3080bdd1243dSDimitry Andric       Value *BoolZeroPoison = IRB.CreateIsNull(Src, "_mscz_bzp");
3081bdd1243dSDimitry Andric       BoolShadow = IRB.CreateOr(BoolShadow, BoolZeroPoison, "_mscz_bs");
3082bdd1243dSDimitry Andric     }
3083bdd1243dSDimitry Andric 
3084bdd1243dSDimitry Andric     Value *OutputShadow =
3085bdd1243dSDimitry Andric         IRB.CreateSExt(BoolShadow, getShadowTy(Src), "_mscz_os");
3086bdd1243dSDimitry Andric 
3087bdd1243dSDimitry Andric     setShadow(&I, OutputShadow);
3088bdd1243dSDimitry Andric     setOriginForNaryOp(I);
3089bdd1243dSDimitry Andric   }
3090bdd1243dSDimitry Andric 
30915ffd83dbSDimitry Andric   // Instrument vector convert intrinsic.
30920b57cec5SDimitry Andric   //
30930b57cec5SDimitry Andric   // This function instruments intrinsics like cvtsi2ss:
30940b57cec5SDimitry Andric   // %Out = int_xxx_cvtyyy(%ConvertOp)
30950b57cec5SDimitry Andric   // or
30960b57cec5SDimitry Andric   // %Out = int_xxx_cvtyyy(%CopyOp, %ConvertOp)
30970b57cec5SDimitry Andric   // Intrinsic converts \p NumUsedElements elements of \p ConvertOp to the same
30980b57cec5SDimitry Andric   // number \p Out elements, and (if has 2 arguments) copies the rest of the
30990b57cec5SDimitry Andric   // elements from \p CopyOp.
31000b57cec5SDimitry Andric   // In most cases conversion involves floating-point value which may trigger a
31010b57cec5SDimitry Andric   // hardware exception when not fully initialized. For this reason we require
31020b57cec5SDimitry Andric   // \p ConvertOp[0:NumUsedElements] to be fully initialized and trap otherwise.
31030b57cec5SDimitry Andric   // We copy the shadow of \p CopyOp[NumUsedElements:] to \p
31040b57cec5SDimitry Andric   // Out[NumUsedElements:]. This means that intrinsics without \p CopyOp always
31050b57cec5SDimitry Andric   // return a fully initialized value.
3106e8d8bef9SDimitry Andric   void handleVectorConvertIntrinsic(IntrinsicInst &I, int NumUsedElements,
3107e8d8bef9SDimitry Andric                                     bool HasRoundingMode = false) {
31080b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
31090b57cec5SDimitry Andric     Value *CopyOp, *ConvertOp;
31100b57cec5SDimitry Andric 
3111e8d8bef9SDimitry Andric     assert((!HasRoundingMode ||
3112349cc55cSDimitry Andric             isa<ConstantInt>(I.getArgOperand(I.arg_size() - 1))) &&
3113e8d8bef9SDimitry Andric            "Invalid rounding mode");
3114e8d8bef9SDimitry Andric 
3115349cc55cSDimitry Andric     switch (I.arg_size() - HasRoundingMode) {
31160b57cec5SDimitry Andric     case 2:
31170b57cec5SDimitry Andric       CopyOp = I.getArgOperand(0);
31180b57cec5SDimitry Andric       ConvertOp = I.getArgOperand(1);
31190b57cec5SDimitry Andric       break;
31200b57cec5SDimitry Andric     case 1:
31210b57cec5SDimitry Andric       ConvertOp = I.getArgOperand(0);
31220b57cec5SDimitry Andric       CopyOp = nullptr;
31230b57cec5SDimitry Andric       break;
31240b57cec5SDimitry Andric     default:
31250b57cec5SDimitry Andric       llvm_unreachable("Cvt intrinsic with unsupported number of arguments.");
31260b57cec5SDimitry Andric     }
31270b57cec5SDimitry Andric 
31280b57cec5SDimitry Andric     // The first *NumUsedElements* elements of ConvertOp are converted to the
31290b57cec5SDimitry Andric     // same number of output elements. The rest of the output is copied from
31300b57cec5SDimitry Andric     // CopyOp, or (if not available) filled with zeroes.
31310b57cec5SDimitry Andric     // Combine shadow for elements of ConvertOp that are used in this operation,
31320b57cec5SDimitry Andric     // and insert a check.
31330b57cec5SDimitry Andric     // FIXME: consider propagating shadow of ConvertOp, at least in the case of
31340b57cec5SDimitry Andric     // int->any conversion.
31350b57cec5SDimitry Andric     Value *ConvertShadow = getShadow(ConvertOp);
31360b57cec5SDimitry Andric     Value *AggShadow = nullptr;
31370b57cec5SDimitry Andric     if (ConvertOp->getType()->isVectorTy()) {
31380b57cec5SDimitry Andric       AggShadow = IRB.CreateExtractElement(
31390b57cec5SDimitry Andric           ConvertShadow, ConstantInt::get(IRB.getInt32Ty(), 0));
31400b57cec5SDimitry Andric       for (int i = 1; i < NumUsedElements; ++i) {
31410b57cec5SDimitry Andric         Value *MoreShadow = IRB.CreateExtractElement(
31420b57cec5SDimitry Andric             ConvertShadow, ConstantInt::get(IRB.getInt32Ty(), i));
31430b57cec5SDimitry Andric         AggShadow = IRB.CreateOr(AggShadow, MoreShadow);
31440b57cec5SDimitry Andric       }
31450b57cec5SDimitry Andric     } else {
31460b57cec5SDimitry Andric       AggShadow = ConvertShadow;
31470b57cec5SDimitry Andric     }
31480b57cec5SDimitry Andric     assert(AggShadow->getType()->isIntegerTy());
31490b57cec5SDimitry Andric     insertShadowCheck(AggShadow, getOrigin(ConvertOp), &I);
31500b57cec5SDimitry Andric 
31510b57cec5SDimitry Andric     // Build result shadow by zero-filling parts of CopyOp shadow that come from
31520b57cec5SDimitry Andric     // ConvertOp.
31530b57cec5SDimitry Andric     if (CopyOp) {
31540b57cec5SDimitry Andric       assert(CopyOp->getType() == I.getType());
31550b57cec5SDimitry Andric       assert(CopyOp->getType()->isVectorTy());
31560b57cec5SDimitry Andric       Value *ResultShadow = getShadow(CopyOp);
31575ffd83dbSDimitry Andric       Type *EltTy = cast<VectorType>(ResultShadow->getType())->getElementType();
31580b57cec5SDimitry Andric       for (int i = 0; i < NumUsedElements; ++i) {
31590b57cec5SDimitry Andric         ResultShadow = IRB.CreateInsertElement(
31600b57cec5SDimitry Andric             ResultShadow, ConstantInt::getNullValue(EltTy),
31610b57cec5SDimitry Andric             ConstantInt::get(IRB.getInt32Ty(), i));
31620b57cec5SDimitry Andric       }
31630b57cec5SDimitry Andric       setShadow(&I, ResultShadow);
31640b57cec5SDimitry Andric       setOrigin(&I, getOrigin(CopyOp));
31650b57cec5SDimitry Andric     } else {
31660b57cec5SDimitry Andric       setShadow(&I, getCleanShadow(&I));
31670b57cec5SDimitry Andric       setOrigin(&I, getCleanOrigin());
31680b57cec5SDimitry Andric     }
31690b57cec5SDimitry Andric   }
31700b57cec5SDimitry Andric 
31710b57cec5SDimitry Andric   // Given a scalar or vector, extract lower 64 bits (or less), and return all
31720b57cec5SDimitry Andric   // zeroes if it is zero, and all ones otherwise.
31730b57cec5SDimitry Andric   Value *Lower64ShadowExtend(IRBuilder<> &IRB, Value *S, Type *T) {
31740b57cec5SDimitry Andric     if (S->getType()->isVectorTy())
31750b57cec5SDimitry Andric       S = CreateShadowCast(IRB, S, IRB.getInt64Ty(), /* Signed */ true);
31760b57cec5SDimitry Andric     assert(S->getType()->getPrimitiveSizeInBits() <= 64);
31770b57cec5SDimitry Andric     Value *S2 = IRB.CreateICmpNE(S, getCleanShadow(S));
31780b57cec5SDimitry Andric     return CreateShadowCast(IRB, S2, T, /* Signed */ true);
31790b57cec5SDimitry Andric   }
31800b57cec5SDimitry Andric 
31810b57cec5SDimitry Andric   // Given a vector, extract its first element, and return all
31820b57cec5SDimitry Andric   // zeroes if it is zero, and all ones otherwise.
31830b57cec5SDimitry Andric   Value *LowerElementShadowExtend(IRBuilder<> &IRB, Value *S, Type *T) {
31840b57cec5SDimitry Andric     Value *S1 = IRB.CreateExtractElement(S, (uint64_t)0);
31850b57cec5SDimitry Andric     Value *S2 = IRB.CreateICmpNE(S1, getCleanShadow(S1));
31860b57cec5SDimitry Andric     return CreateShadowCast(IRB, S2, T, /* Signed */ true);
31870b57cec5SDimitry Andric   }
31880b57cec5SDimitry Andric 
31890b57cec5SDimitry Andric   Value *VariableShadowExtend(IRBuilder<> &IRB, Value *S) {
31900b57cec5SDimitry Andric     Type *T = S->getType();
31910b57cec5SDimitry Andric     assert(T->isVectorTy());
31920b57cec5SDimitry Andric     Value *S2 = IRB.CreateICmpNE(S, getCleanShadow(S));
31930b57cec5SDimitry Andric     return IRB.CreateSExt(S2, T);
31940b57cec5SDimitry Andric   }
31950b57cec5SDimitry Andric 
31965ffd83dbSDimitry Andric   // Instrument vector shift intrinsic.
31970b57cec5SDimitry Andric   //
31980b57cec5SDimitry Andric   // This function instruments intrinsics like int_x86_avx2_psll_w.
31990b57cec5SDimitry Andric   // Intrinsic shifts %In by %ShiftSize bits.
32000b57cec5SDimitry Andric   // %ShiftSize may be a vector. In that case the lower 64 bits determine shift
32010b57cec5SDimitry Andric   // size, and the rest is ignored. Behavior is defined even if shift size is
32020b57cec5SDimitry Andric   // greater than register (or field) width.
32030b57cec5SDimitry Andric   void handleVectorShiftIntrinsic(IntrinsicInst &I, bool Variable) {
3204349cc55cSDimitry Andric     assert(I.arg_size() == 2);
32050b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
32060b57cec5SDimitry Andric     // If any of the S2 bits are poisoned, the whole thing is poisoned.
32070b57cec5SDimitry Andric     // Otherwise perform the same shift on S1.
32080b57cec5SDimitry Andric     Value *S1 = getShadow(&I, 0);
32090b57cec5SDimitry Andric     Value *S2 = getShadow(&I, 1);
32100b57cec5SDimitry Andric     Value *S2Conv = Variable ? VariableShadowExtend(IRB, S2)
32110b57cec5SDimitry Andric                              : Lower64ShadowExtend(IRB, S2, getShadowTy(&I));
32120b57cec5SDimitry Andric     Value *V1 = I.getOperand(0);
32130b57cec5SDimitry Andric     Value *V2 = I.getOperand(1);
32145ffd83dbSDimitry Andric     Value *Shift = IRB.CreateCall(I.getFunctionType(), I.getCalledOperand(),
32150b57cec5SDimitry Andric                                   {IRB.CreateBitCast(S1, V1->getType()), V2});
32160b57cec5SDimitry Andric     Shift = IRB.CreateBitCast(Shift, getShadowTy(&I));
32170b57cec5SDimitry Andric     setShadow(&I, IRB.CreateOr(Shift, S2Conv));
32180b57cec5SDimitry Andric     setOriginForNaryOp(I);
32190b57cec5SDimitry Andric   }
32200b57cec5SDimitry Andric 
32210b57cec5SDimitry Andric   // Get an X86_MMX-sized vector type.
32220b57cec5SDimitry Andric   Type *getMMXVectorTy(unsigned EltSizeInBits) {
32230b57cec5SDimitry Andric     const unsigned X86_MMXSizeInBits = 64;
32240b57cec5SDimitry Andric     assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
32250b57cec5SDimitry Andric            "Illegal MMX vector element size");
32265ffd83dbSDimitry Andric     return FixedVectorType::get(IntegerType::get(*MS.C, EltSizeInBits),
32270b57cec5SDimitry Andric                                 X86_MMXSizeInBits / EltSizeInBits);
32280b57cec5SDimitry Andric   }
32290b57cec5SDimitry Andric 
32300b57cec5SDimitry Andric   // Returns a signed counterpart for an (un)signed-saturate-and-pack
32310b57cec5SDimitry Andric   // intrinsic.
32320b57cec5SDimitry Andric   Intrinsic::ID getSignedPackIntrinsic(Intrinsic::ID id) {
32330b57cec5SDimitry Andric     switch (id) {
32340b57cec5SDimitry Andric     case Intrinsic::x86_sse2_packsswb_128:
32350b57cec5SDimitry Andric     case Intrinsic::x86_sse2_packuswb_128:
32360b57cec5SDimitry Andric       return Intrinsic::x86_sse2_packsswb_128;
32370b57cec5SDimitry Andric 
32380b57cec5SDimitry Andric     case Intrinsic::x86_sse2_packssdw_128:
32390b57cec5SDimitry Andric     case Intrinsic::x86_sse41_packusdw:
32400b57cec5SDimitry Andric       return Intrinsic::x86_sse2_packssdw_128;
32410b57cec5SDimitry Andric 
32420b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packsswb:
32430b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packuswb:
32440b57cec5SDimitry Andric       return Intrinsic::x86_avx2_packsswb;
32450b57cec5SDimitry Andric 
32460b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packssdw:
32470b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packusdw:
32480b57cec5SDimitry Andric       return Intrinsic::x86_avx2_packssdw;
32490b57cec5SDimitry Andric 
32500b57cec5SDimitry Andric     case Intrinsic::x86_mmx_packsswb:
32510b57cec5SDimitry Andric     case Intrinsic::x86_mmx_packuswb:
32520b57cec5SDimitry Andric       return Intrinsic::x86_mmx_packsswb;
32530b57cec5SDimitry Andric 
32540b57cec5SDimitry Andric     case Intrinsic::x86_mmx_packssdw:
32550b57cec5SDimitry Andric       return Intrinsic::x86_mmx_packssdw;
32560b57cec5SDimitry Andric     default:
32570b57cec5SDimitry Andric       llvm_unreachable("unexpected intrinsic id");
32580b57cec5SDimitry Andric     }
32590b57cec5SDimitry Andric   }
32600b57cec5SDimitry Andric 
32615ffd83dbSDimitry Andric   // Instrument vector pack intrinsic.
32620b57cec5SDimitry Andric   //
32630b57cec5SDimitry Andric   // This function instruments intrinsics like x86_mmx_packsswb, that
32640b57cec5SDimitry Andric   // packs elements of 2 input vectors into half as many bits with saturation.
32650b57cec5SDimitry Andric   // Shadow is propagated with the signed variant of the same intrinsic applied
32660b57cec5SDimitry Andric   // to sext(Sa != zeroinitializer), sext(Sb != zeroinitializer).
32670b57cec5SDimitry Andric   // EltSizeInBits is used only for x86mmx arguments.
32680b57cec5SDimitry Andric   void handleVectorPackIntrinsic(IntrinsicInst &I, unsigned EltSizeInBits = 0) {
3269349cc55cSDimitry Andric     assert(I.arg_size() == 2);
32700b57cec5SDimitry Andric     bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy();
32710b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
32720b57cec5SDimitry Andric     Value *S1 = getShadow(&I, 0);
32730b57cec5SDimitry Andric     Value *S2 = getShadow(&I, 1);
32740b57cec5SDimitry Andric     assert(isX86_MMX || S1->getType()->isVectorTy());
32750b57cec5SDimitry Andric 
32760b57cec5SDimitry Andric     // SExt and ICmpNE below must apply to individual elements of input vectors.
32770b57cec5SDimitry Andric     // In case of x86mmx arguments, cast them to appropriate vector types and
32780b57cec5SDimitry Andric     // back.
32790b57cec5SDimitry Andric     Type *T = isX86_MMX ? getMMXVectorTy(EltSizeInBits) : S1->getType();
32800b57cec5SDimitry Andric     if (isX86_MMX) {
32810b57cec5SDimitry Andric       S1 = IRB.CreateBitCast(S1, T);
32820b57cec5SDimitry Andric       S2 = IRB.CreateBitCast(S2, T);
32830b57cec5SDimitry Andric     }
3284bdd1243dSDimitry Andric     Value *S1_ext =
3285bdd1243dSDimitry Andric         IRB.CreateSExt(IRB.CreateICmpNE(S1, Constant::getNullValue(T)), T);
3286bdd1243dSDimitry Andric     Value *S2_ext =
3287bdd1243dSDimitry Andric         IRB.CreateSExt(IRB.CreateICmpNE(S2, Constant::getNullValue(T)), T);
32880b57cec5SDimitry Andric     if (isX86_MMX) {
32890b57cec5SDimitry Andric       Type *X86_MMXTy = Type::getX86_MMXTy(*MS.C);
32900b57cec5SDimitry Andric       S1_ext = IRB.CreateBitCast(S1_ext, X86_MMXTy);
32910b57cec5SDimitry Andric       S2_ext = IRB.CreateBitCast(S2_ext, X86_MMXTy);
32920b57cec5SDimitry Andric     }
32930b57cec5SDimitry Andric 
32940b57cec5SDimitry Andric     Function *ShadowFn = Intrinsic::getDeclaration(
32950b57cec5SDimitry Andric         F.getParent(), getSignedPackIntrinsic(I.getIntrinsicID()));
32960b57cec5SDimitry Andric 
32970b57cec5SDimitry Andric     Value *S =
32980b57cec5SDimitry Andric         IRB.CreateCall(ShadowFn, {S1_ext, S2_ext}, "_msprop_vector_pack");
3299bdd1243dSDimitry Andric     if (isX86_MMX)
3300bdd1243dSDimitry Andric       S = IRB.CreateBitCast(S, getShadowTy(&I));
33010b57cec5SDimitry Andric     setShadow(&I, S);
33020b57cec5SDimitry Andric     setOriginForNaryOp(I);
33030b57cec5SDimitry Andric   }
33040b57cec5SDimitry Andric 
3305*0fca6ea1SDimitry Andric   // Convert `Mask` into `<n x i1>`.
3306*0fca6ea1SDimitry Andric   Constant *createDppMask(unsigned Width, unsigned Mask) {
3307*0fca6ea1SDimitry Andric     SmallVector<Constant *, 4> R(Width);
3308*0fca6ea1SDimitry Andric     for (auto &M : R) {
3309*0fca6ea1SDimitry Andric       M = ConstantInt::getBool(F.getContext(), Mask & 1);
3310*0fca6ea1SDimitry Andric       Mask >>= 1;
3311*0fca6ea1SDimitry Andric     }
3312*0fca6ea1SDimitry Andric     return ConstantVector::get(R);
3313*0fca6ea1SDimitry Andric   }
3314*0fca6ea1SDimitry Andric 
3315*0fca6ea1SDimitry Andric   // Calculate output shadow as array of booleans `<n x i1>`, assuming if any
3316*0fca6ea1SDimitry Andric   // arg is poisoned, entire dot product is poisoned.
3317*0fca6ea1SDimitry Andric   Value *findDppPoisonedOutput(IRBuilder<> &IRB, Value *S, unsigned SrcMask,
3318*0fca6ea1SDimitry Andric                                unsigned DstMask) {
3319*0fca6ea1SDimitry Andric     const unsigned Width =
3320*0fca6ea1SDimitry Andric         cast<FixedVectorType>(S->getType())->getNumElements();
3321*0fca6ea1SDimitry Andric 
3322*0fca6ea1SDimitry Andric     S = IRB.CreateSelect(createDppMask(Width, SrcMask), S,
3323*0fca6ea1SDimitry Andric                          Constant::getNullValue(S->getType()));
3324*0fca6ea1SDimitry Andric     Value *SElem = IRB.CreateOrReduce(S);
3325*0fca6ea1SDimitry Andric     Value *IsClean = IRB.CreateIsNull(SElem, "_msdpp");
3326*0fca6ea1SDimitry Andric     Value *DstMaskV = createDppMask(Width, DstMask);
3327*0fca6ea1SDimitry Andric 
3328*0fca6ea1SDimitry Andric     return IRB.CreateSelect(
3329*0fca6ea1SDimitry Andric         IsClean, Constant::getNullValue(DstMaskV->getType()), DstMaskV);
3330*0fca6ea1SDimitry Andric   }
3331*0fca6ea1SDimitry Andric 
3332*0fca6ea1SDimitry Andric   // See `Intel Intrinsics Guide` for `_dp_p*` instructions.
3333*0fca6ea1SDimitry Andric   //
3334*0fca6ea1SDimitry Andric   // 2 and 4 element versions produce single scalar of dot product, and then
3335*0fca6ea1SDimitry Andric   // puts it into elements of output vector, selected by 4 lowest bits of the
3336*0fca6ea1SDimitry Andric   // mask. Top 4 bits of the mask control which elements of input to use for dot
3337*0fca6ea1SDimitry Andric   // product.
3338*0fca6ea1SDimitry Andric   //
3339*0fca6ea1SDimitry Andric   // 8 element version mask still has only 4 bit for input, and 4 bit for output
3340*0fca6ea1SDimitry Andric   // mask. According to the spec it just operates as 4 element version on first
3341*0fca6ea1SDimitry Andric   // 4 elements of inputs and output, and then on last 4 elements of inputs and
3342*0fca6ea1SDimitry Andric   // output.
3343*0fca6ea1SDimitry Andric   void handleDppIntrinsic(IntrinsicInst &I) {
3344*0fca6ea1SDimitry Andric     IRBuilder<> IRB(&I);
3345*0fca6ea1SDimitry Andric 
3346*0fca6ea1SDimitry Andric     Value *S0 = getShadow(&I, 0);
3347*0fca6ea1SDimitry Andric     Value *S1 = getShadow(&I, 1);
3348*0fca6ea1SDimitry Andric     Value *S = IRB.CreateOr(S0, S1);
3349*0fca6ea1SDimitry Andric 
3350*0fca6ea1SDimitry Andric     const unsigned Width =
3351*0fca6ea1SDimitry Andric         cast<FixedVectorType>(S->getType())->getNumElements();
3352*0fca6ea1SDimitry Andric     assert(Width == 2 || Width == 4 || Width == 8);
3353*0fca6ea1SDimitry Andric 
3354*0fca6ea1SDimitry Andric     const unsigned Mask = cast<ConstantInt>(I.getArgOperand(2))->getZExtValue();
3355*0fca6ea1SDimitry Andric     const unsigned SrcMask = Mask >> 4;
3356*0fca6ea1SDimitry Andric     const unsigned DstMask = Mask & 0xf;
3357*0fca6ea1SDimitry Andric 
3358*0fca6ea1SDimitry Andric     // Calculate shadow as `<n x i1>`.
3359*0fca6ea1SDimitry Andric     Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
3360*0fca6ea1SDimitry Andric     if (Width == 8) {
3361*0fca6ea1SDimitry Andric       // First 4 elements of shadow are already calculated. `makeDppShadow`
3362*0fca6ea1SDimitry Andric       // operats on 32 bit masks, so we can just shift masks, and repeat.
3363*0fca6ea1SDimitry Andric       SI1 = IRB.CreateOr(
3364*0fca6ea1SDimitry Andric           SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
3365*0fca6ea1SDimitry Andric     }
3366*0fca6ea1SDimitry Andric     // Extend to real size of shadow, poisoning either all or none bits of an
3367*0fca6ea1SDimitry Andric     // element.
3368*0fca6ea1SDimitry Andric     S = IRB.CreateSExt(SI1, S->getType(), "_msdpp");
3369*0fca6ea1SDimitry Andric 
3370*0fca6ea1SDimitry Andric     setShadow(&I, S);
3371*0fca6ea1SDimitry Andric     setOriginForNaryOp(I);
3372*0fca6ea1SDimitry Andric   }
3373*0fca6ea1SDimitry Andric 
3374*0fca6ea1SDimitry Andric   Value *convertBlendvToSelectMask(IRBuilder<> &IRB, Value *C) {
3375*0fca6ea1SDimitry Andric     C = CreateAppToShadowCast(IRB, C);
3376*0fca6ea1SDimitry Andric     FixedVectorType *FVT = cast<FixedVectorType>(C->getType());
3377*0fca6ea1SDimitry Andric     unsigned ElSize = FVT->getElementType()->getPrimitiveSizeInBits();
3378*0fca6ea1SDimitry Andric     C = IRB.CreateAShr(C, ElSize - 1);
3379*0fca6ea1SDimitry Andric     FVT = FixedVectorType::get(IRB.getInt1Ty(), FVT->getNumElements());
3380*0fca6ea1SDimitry Andric     return IRB.CreateTrunc(C, FVT);
3381*0fca6ea1SDimitry Andric   }
3382*0fca6ea1SDimitry Andric 
3383*0fca6ea1SDimitry Andric   // `blendv(f, t, c)` is effectively `select(c[top_bit], t, f)`.
3384*0fca6ea1SDimitry Andric   void handleBlendvIntrinsic(IntrinsicInst &I) {
3385*0fca6ea1SDimitry Andric     Value *C = I.getOperand(2);
3386*0fca6ea1SDimitry Andric     Value *T = I.getOperand(1);
3387*0fca6ea1SDimitry Andric     Value *F = I.getOperand(0);
3388*0fca6ea1SDimitry Andric 
3389*0fca6ea1SDimitry Andric     Value *Sc = getShadow(&I, 2);
3390*0fca6ea1SDimitry Andric     Value *Oc = MS.TrackOrigins ? getOrigin(C) : nullptr;
3391*0fca6ea1SDimitry Andric 
3392*0fca6ea1SDimitry Andric     {
3393*0fca6ea1SDimitry Andric       IRBuilder<> IRB(&I);
3394*0fca6ea1SDimitry Andric       // Extract top bit from condition and its shadow.
3395*0fca6ea1SDimitry Andric       C = convertBlendvToSelectMask(IRB, C);
3396*0fca6ea1SDimitry Andric       Sc = convertBlendvToSelectMask(IRB, Sc);
3397*0fca6ea1SDimitry Andric 
3398*0fca6ea1SDimitry Andric       setShadow(C, Sc);
3399*0fca6ea1SDimitry Andric       setOrigin(C, Oc);
3400*0fca6ea1SDimitry Andric     }
3401*0fca6ea1SDimitry Andric 
3402*0fca6ea1SDimitry Andric     handleSelectLikeInst(I, C, T, F);
3403*0fca6ea1SDimitry Andric   }
3404*0fca6ea1SDimitry Andric 
34055ffd83dbSDimitry Andric   // Instrument sum-of-absolute-differences intrinsic.
34060b57cec5SDimitry Andric   void handleVectorSadIntrinsic(IntrinsicInst &I) {
34070b57cec5SDimitry Andric     const unsigned SignificantBitsPerResultElement = 16;
34080b57cec5SDimitry Andric     bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy();
34090b57cec5SDimitry Andric     Type *ResTy = isX86_MMX ? IntegerType::get(*MS.C, 64) : I.getType();
34100b57cec5SDimitry Andric     unsigned ZeroBitsPerResultElement =
34110b57cec5SDimitry Andric         ResTy->getScalarSizeInBits() - SignificantBitsPerResultElement;
34120b57cec5SDimitry Andric 
34130b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
3414bdd1243dSDimitry Andric     auto *Shadow0 = getShadow(&I, 0);
3415bdd1243dSDimitry Andric     auto *Shadow1 = getShadow(&I, 1);
3416bdd1243dSDimitry Andric     Value *S = IRB.CreateOr(Shadow0, Shadow1);
34170b57cec5SDimitry Andric     S = IRB.CreateBitCast(S, ResTy);
34180b57cec5SDimitry Andric     S = IRB.CreateSExt(IRB.CreateICmpNE(S, Constant::getNullValue(ResTy)),
34190b57cec5SDimitry Andric                        ResTy);
34200b57cec5SDimitry Andric     S = IRB.CreateLShr(S, ZeroBitsPerResultElement);
34210b57cec5SDimitry Andric     S = IRB.CreateBitCast(S, getShadowTy(&I));
34220b57cec5SDimitry Andric     setShadow(&I, S);
34230b57cec5SDimitry Andric     setOriginForNaryOp(I);
34240b57cec5SDimitry Andric   }
34250b57cec5SDimitry Andric 
34260b57cec5SDimitry Andric   // Instrument multiply-add intrinsic.
34270b57cec5SDimitry Andric   void handleVectorPmaddIntrinsic(IntrinsicInst &I,
34280b57cec5SDimitry Andric                                   unsigned EltSizeInBits = 0) {
34290b57cec5SDimitry Andric     bool isX86_MMX = I.getOperand(0)->getType()->isX86_MMXTy();
34300b57cec5SDimitry Andric     Type *ResTy = isX86_MMX ? getMMXVectorTy(EltSizeInBits * 2) : I.getType();
34310b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
3432bdd1243dSDimitry Andric     auto *Shadow0 = getShadow(&I, 0);
3433bdd1243dSDimitry Andric     auto *Shadow1 = getShadow(&I, 1);
3434bdd1243dSDimitry Andric     Value *S = IRB.CreateOr(Shadow0, Shadow1);
34350b57cec5SDimitry Andric     S = IRB.CreateBitCast(S, ResTy);
34360b57cec5SDimitry Andric     S = IRB.CreateSExt(IRB.CreateICmpNE(S, Constant::getNullValue(ResTy)),
34370b57cec5SDimitry Andric                        ResTy);
34380b57cec5SDimitry Andric     S = IRB.CreateBitCast(S, getShadowTy(&I));
34390b57cec5SDimitry Andric     setShadow(&I, S);
34400b57cec5SDimitry Andric     setOriginForNaryOp(I);
34410b57cec5SDimitry Andric   }
34420b57cec5SDimitry Andric 
34430b57cec5SDimitry Andric   // Instrument compare-packed intrinsic.
34440b57cec5SDimitry Andric   // Basically, an or followed by sext(icmp ne 0) to end up with all-zeros or
34450b57cec5SDimitry Andric   // all-ones shadow.
34460b57cec5SDimitry Andric   void handleVectorComparePackedIntrinsic(IntrinsicInst &I) {
34470b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
34480b57cec5SDimitry Andric     Type *ResTy = getShadowTy(&I);
3449bdd1243dSDimitry Andric     auto *Shadow0 = getShadow(&I, 0);
3450bdd1243dSDimitry Andric     auto *Shadow1 = getShadow(&I, 1);
3451bdd1243dSDimitry Andric     Value *S0 = IRB.CreateOr(Shadow0, Shadow1);
34520b57cec5SDimitry Andric     Value *S = IRB.CreateSExt(
34530b57cec5SDimitry Andric         IRB.CreateICmpNE(S0, Constant::getNullValue(ResTy)), ResTy);
34540b57cec5SDimitry Andric     setShadow(&I, S);
34550b57cec5SDimitry Andric     setOriginForNaryOp(I);
34560b57cec5SDimitry Andric   }
34570b57cec5SDimitry Andric 
34580b57cec5SDimitry Andric   // Instrument compare-scalar intrinsic.
34590b57cec5SDimitry Andric   // This handles both cmp* intrinsics which return the result in the first
34600b57cec5SDimitry Andric   // element of a vector, and comi* which return the result as i32.
34610b57cec5SDimitry Andric   void handleVectorCompareScalarIntrinsic(IntrinsicInst &I) {
34620b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
3463bdd1243dSDimitry Andric     auto *Shadow0 = getShadow(&I, 0);
3464bdd1243dSDimitry Andric     auto *Shadow1 = getShadow(&I, 1);
3465bdd1243dSDimitry Andric     Value *S0 = IRB.CreateOr(Shadow0, Shadow1);
34660b57cec5SDimitry Andric     Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&I));
34670b57cec5SDimitry Andric     setShadow(&I, S);
34680b57cec5SDimitry Andric     setOriginForNaryOp(I);
34690b57cec5SDimitry Andric   }
34700b57cec5SDimitry Andric 
34715ffd83dbSDimitry Andric   // Instrument generic vector reduction intrinsics
34725ffd83dbSDimitry Andric   // by ORing together all their fields.
34735ffd83dbSDimitry Andric   void handleVectorReduceIntrinsic(IntrinsicInst &I) {
34745ffd83dbSDimitry Andric     IRBuilder<> IRB(&I);
34755ffd83dbSDimitry Andric     Value *S = IRB.CreateOrReduce(getShadow(&I, 0));
34765ffd83dbSDimitry Andric     setShadow(&I, S);
34775ffd83dbSDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
34785ffd83dbSDimitry Andric   }
34795ffd83dbSDimitry Andric 
3480e8d8bef9SDimitry Andric   // Instrument vector.reduce.or intrinsic.
34815ffd83dbSDimitry Andric   // Valid (non-poisoned) set bits in the operand pull low the
34825ffd83dbSDimitry Andric   // corresponding shadow bits.
34835ffd83dbSDimitry Andric   void handleVectorReduceOrIntrinsic(IntrinsicInst &I) {
34845ffd83dbSDimitry Andric     IRBuilder<> IRB(&I);
34855ffd83dbSDimitry Andric     Value *OperandShadow = getShadow(&I, 0);
34865ffd83dbSDimitry Andric     Value *OperandUnsetBits = IRB.CreateNot(I.getOperand(0));
34875ffd83dbSDimitry Andric     Value *OperandUnsetOrPoison = IRB.CreateOr(OperandUnsetBits, OperandShadow);
34885ffd83dbSDimitry Andric     // Bit N is clean if any field's bit N is 1 and unpoison
34895ffd83dbSDimitry Andric     Value *OutShadowMask = IRB.CreateAndReduce(OperandUnsetOrPoison);
34905ffd83dbSDimitry Andric     // Otherwise, it is clean if every field's bit N is unpoison
34915ffd83dbSDimitry Andric     Value *OrShadow = IRB.CreateOrReduce(OperandShadow);
34925ffd83dbSDimitry Andric     Value *S = IRB.CreateAnd(OutShadowMask, OrShadow);
34935ffd83dbSDimitry Andric 
34945ffd83dbSDimitry Andric     setShadow(&I, S);
34955ffd83dbSDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
34965ffd83dbSDimitry Andric   }
34975ffd83dbSDimitry Andric 
3498e8d8bef9SDimitry Andric   // Instrument vector.reduce.and intrinsic.
34995ffd83dbSDimitry Andric   // Valid (non-poisoned) unset bits in the operand pull down the
35005ffd83dbSDimitry Andric   // corresponding shadow bits.
35015ffd83dbSDimitry Andric   void handleVectorReduceAndIntrinsic(IntrinsicInst &I) {
35025ffd83dbSDimitry Andric     IRBuilder<> IRB(&I);
35035ffd83dbSDimitry Andric     Value *OperandShadow = getShadow(&I, 0);
35045ffd83dbSDimitry Andric     Value *OperandSetOrPoison = IRB.CreateOr(I.getOperand(0), OperandShadow);
35055ffd83dbSDimitry Andric     // Bit N is clean if any field's bit N is 0 and unpoison
35065ffd83dbSDimitry Andric     Value *OutShadowMask = IRB.CreateAndReduce(OperandSetOrPoison);
35075ffd83dbSDimitry Andric     // Otherwise, it is clean if every field's bit N is unpoison
35085ffd83dbSDimitry Andric     Value *OrShadow = IRB.CreateOrReduce(OperandShadow);
35095ffd83dbSDimitry Andric     Value *S = IRB.CreateAnd(OutShadowMask, OrShadow);
35105ffd83dbSDimitry Andric 
35115ffd83dbSDimitry Andric     setShadow(&I, S);
35125ffd83dbSDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
35135ffd83dbSDimitry Andric   }
35145ffd83dbSDimitry Andric 
35150b57cec5SDimitry Andric   void handleStmxcsr(IntrinsicInst &I) {
35160b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
35170b57cec5SDimitry Andric     Value *Addr = I.getArgOperand(0);
35180b57cec5SDimitry Andric     Type *Ty = IRB.getInt32Ty();
35190b57cec5SDimitry Andric     Value *ShadowPtr =
35205ffd83dbSDimitry Andric         getShadowOriginPtr(Addr, IRB, Ty, Align(1), /*isStore*/ true).first;
35210b57cec5SDimitry Andric 
35225f757f3fSDimitry Andric     IRB.CreateStore(getCleanShadow(Ty), ShadowPtr);
35230b57cec5SDimitry Andric 
35240b57cec5SDimitry Andric     if (ClCheckAccessAddress)
35250b57cec5SDimitry Andric       insertShadowCheck(Addr, &I);
35260b57cec5SDimitry Andric   }
35270b57cec5SDimitry Andric 
35280b57cec5SDimitry Andric   void handleLdmxcsr(IntrinsicInst &I) {
3529bdd1243dSDimitry Andric     if (!InsertChecks)
3530bdd1243dSDimitry Andric       return;
35310b57cec5SDimitry Andric 
35320b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
35330b57cec5SDimitry Andric     Value *Addr = I.getArgOperand(0);
35340b57cec5SDimitry Andric     Type *Ty = IRB.getInt32Ty();
35355ffd83dbSDimitry Andric     const Align Alignment = Align(1);
35360b57cec5SDimitry Andric     Value *ShadowPtr, *OriginPtr;
35370b57cec5SDimitry Andric     std::tie(ShadowPtr, OriginPtr) =
35380b57cec5SDimitry Andric         getShadowOriginPtr(Addr, IRB, Ty, Alignment, /*isStore*/ false);
35390b57cec5SDimitry Andric 
35400b57cec5SDimitry Andric     if (ClCheckAccessAddress)
35410b57cec5SDimitry Andric       insertShadowCheck(Addr, &I);
35420b57cec5SDimitry Andric 
35435ffd83dbSDimitry Andric     Value *Shadow = IRB.CreateAlignedLoad(Ty, ShadowPtr, Alignment, "_ldmxcsr");
35440b57cec5SDimitry Andric     Value *Origin = MS.TrackOrigins ? IRB.CreateLoad(MS.OriginTy, OriginPtr)
35450b57cec5SDimitry Andric                                     : getCleanOrigin();
35460b57cec5SDimitry Andric     insertShadowCheck(Shadow, Origin, &I);
35470b57cec5SDimitry Andric   }
35480b57cec5SDimitry Andric 
3549bdd1243dSDimitry Andric   void handleMaskedExpandLoad(IntrinsicInst &I) {
35500b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
3551bdd1243dSDimitry Andric     Value *Ptr = I.getArgOperand(0);
3552bdd1243dSDimitry Andric     Value *Mask = I.getArgOperand(1);
3553bdd1243dSDimitry Andric     Value *PassThru = I.getArgOperand(2);
35540b57cec5SDimitry Andric 
35550b57cec5SDimitry Andric     if (ClCheckAccessAddress) {
3556bdd1243dSDimitry Andric       insertShadowCheck(Ptr, &I);
35570b57cec5SDimitry Andric       insertShadowCheck(Mask, &I);
35580b57cec5SDimitry Andric     }
35590b57cec5SDimitry Andric 
3560bdd1243dSDimitry Andric     if (!PropagateShadow) {
3561bdd1243dSDimitry Andric       setShadow(&I, getCleanShadow(&I));
3562bdd1243dSDimitry Andric       setOrigin(&I, getCleanOrigin());
3563bdd1243dSDimitry Andric       return;
35640b57cec5SDimitry Andric     }
35650b57cec5SDimitry Andric 
3566bdd1243dSDimitry Andric     Type *ShadowTy = getShadowTy(&I);
356706c3fb27SDimitry Andric     Type *ElementShadowTy = cast<VectorType>(ShadowTy)->getElementType();
3568bdd1243dSDimitry Andric     auto [ShadowPtr, OriginPtr] =
3569bdd1243dSDimitry Andric         getShadowOriginPtr(Ptr, IRB, ElementShadowTy, {}, /*isStore*/ false);
3570bdd1243dSDimitry Andric 
3571bdd1243dSDimitry Andric     Value *Shadow = IRB.CreateMaskedExpandLoad(
3572bdd1243dSDimitry Andric         ShadowTy, ShadowPtr, Mask, getShadow(PassThru), "_msmaskedexpload");
3573bdd1243dSDimitry Andric 
3574bdd1243dSDimitry Andric     setShadow(&I, Shadow);
3575bdd1243dSDimitry Andric 
3576bdd1243dSDimitry Andric     // TODO: Store origins.
3577bdd1243dSDimitry Andric     setOrigin(&I, getCleanOrigin());
3578bdd1243dSDimitry Andric   }
3579bdd1243dSDimitry Andric 
3580bdd1243dSDimitry Andric   void handleMaskedCompressStore(IntrinsicInst &I) {
35810b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
3582bdd1243dSDimitry Andric     Value *Values = I.getArgOperand(0);
3583bdd1243dSDimitry Andric     Value *Ptr = I.getArgOperand(1);
3584bdd1243dSDimitry Andric     Value *Mask = I.getArgOperand(2);
3585bdd1243dSDimitry Andric 
3586bdd1243dSDimitry Andric     if (ClCheckAccessAddress) {
3587bdd1243dSDimitry Andric       insertShadowCheck(Ptr, &I);
3588bdd1243dSDimitry Andric       insertShadowCheck(Mask, &I);
3589bdd1243dSDimitry Andric     }
3590bdd1243dSDimitry Andric 
3591bdd1243dSDimitry Andric     Value *Shadow = getShadow(Values);
3592bdd1243dSDimitry Andric     Type *ElementShadowTy =
359306c3fb27SDimitry Andric         getShadowTy(cast<VectorType>(Values->getType())->getElementType());
3594bdd1243dSDimitry Andric     auto [ShadowPtr, OriginPtrs] =
3595bdd1243dSDimitry Andric         getShadowOriginPtr(Ptr, IRB, ElementShadowTy, {}, /*isStore*/ true);
3596bdd1243dSDimitry Andric 
3597bdd1243dSDimitry Andric     IRB.CreateMaskedCompressStore(Shadow, ShadowPtr, Mask);
3598bdd1243dSDimitry Andric 
3599bdd1243dSDimitry Andric     // TODO: Store origins.
3600bdd1243dSDimitry Andric   }
3601bdd1243dSDimitry Andric 
3602bdd1243dSDimitry Andric   void handleMaskedGather(IntrinsicInst &I) {
3603bdd1243dSDimitry Andric     IRBuilder<> IRB(&I);
3604bdd1243dSDimitry Andric     Value *Ptrs = I.getArgOperand(0);
36055ffd83dbSDimitry Andric     const Align Alignment(
3606480093f4SDimitry Andric         cast<ConstantInt>(I.getArgOperand(1))->getZExtValue());
36070b57cec5SDimitry Andric     Value *Mask = I.getArgOperand(2);
36080b57cec5SDimitry Andric     Value *PassThru = I.getArgOperand(3);
36090b57cec5SDimitry Andric 
3610bdd1243dSDimitry Andric     Type *PtrsShadowTy = getShadowTy(Ptrs);
3611bdd1243dSDimitry Andric     if (ClCheckAccessAddress) {
3612bdd1243dSDimitry Andric       insertShadowCheck(Mask, &I);
3613bdd1243dSDimitry Andric       Value *MaskedPtrShadow = IRB.CreateSelect(
3614bdd1243dSDimitry Andric           Mask, getShadow(Ptrs), Constant::getNullValue((PtrsShadowTy)),
3615bdd1243dSDimitry Andric           "_msmaskedptrs");
3616bdd1243dSDimitry Andric       insertShadowCheck(MaskedPtrShadow, getOrigin(Ptrs), &I);
36170b57cec5SDimitry Andric     }
36180b57cec5SDimitry Andric 
3619bdd1243dSDimitry Andric     if (!PropagateShadow) {
3620bdd1243dSDimitry Andric       setShadow(&I, getCleanShadow(&I));
3621bdd1243dSDimitry Andric       setOrigin(&I, getCleanOrigin());
3622bdd1243dSDimitry Andric       return;
3623bdd1243dSDimitry Andric     }
3624bdd1243dSDimitry Andric 
3625bdd1243dSDimitry Andric     Type *ShadowTy = getShadowTy(&I);
362606c3fb27SDimitry Andric     Type *ElementShadowTy = cast<VectorType>(ShadowTy)->getElementType();
3627bdd1243dSDimitry Andric     auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
3628bdd1243dSDimitry Andric         Ptrs, IRB, ElementShadowTy, Alignment, /*isStore*/ false);
3629bdd1243dSDimitry Andric 
3630bdd1243dSDimitry Andric     Value *Shadow =
3631bdd1243dSDimitry Andric         IRB.CreateMaskedGather(ShadowTy, ShadowPtrs, Alignment, Mask,
3632bdd1243dSDimitry Andric                                getShadow(PassThru), "_msmaskedgather");
3633bdd1243dSDimitry Andric 
3634bdd1243dSDimitry Andric     setShadow(&I, Shadow);
3635bdd1243dSDimitry Andric 
3636bdd1243dSDimitry Andric     // TODO: Store origins.
3637bdd1243dSDimitry Andric     setOrigin(&I, getCleanOrigin());
3638bdd1243dSDimitry Andric   }
3639bdd1243dSDimitry Andric 
3640bdd1243dSDimitry Andric   void handleMaskedScatter(IntrinsicInst &I) {
3641bdd1243dSDimitry Andric     IRBuilder<> IRB(&I);
3642bdd1243dSDimitry Andric     Value *Values = I.getArgOperand(0);
3643bdd1243dSDimitry Andric     Value *Ptrs = I.getArgOperand(1);
3644bdd1243dSDimitry Andric     const Align Alignment(
3645bdd1243dSDimitry Andric         cast<ConstantInt>(I.getArgOperand(2))->getZExtValue());
3646bdd1243dSDimitry Andric     Value *Mask = I.getArgOperand(3);
3647bdd1243dSDimitry Andric 
3648bdd1243dSDimitry Andric     Type *PtrsShadowTy = getShadowTy(Ptrs);
36490b57cec5SDimitry Andric     if (ClCheckAccessAddress) {
3650bdd1243dSDimitry Andric       insertShadowCheck(Mask, &I);
3651bdd1243dSDimitry Andric       Value *MaskedPtrShadow = IRB.CreateSelect(
3652bdd1243dSDimitry Andric           Mask, getShadow(Ptrs), Constant::getNullValue((PtrsShadowTy)),
3653bdd1243dSDimitry Andric           "_msmaskedptrs");
3654bdd1243dSDimitry Andric       insertShadowCheck(MaskedPtrShadow, getOrigin(Ptrs), &I);
3655bdd1243dSDimitry Andric     }
3656bdd1243dSDimitry Andric 
3657bdd1243dSDimitry Andric     Value *Shadow = getShadow(Values);
3658bdd1243dSDimitry Andric     Type *ElementShadowTy =
365906c3fb27SDimitry Andric         getShadowTy(cast<VectorType>(Values->getType())->getElementType());
3660bdd1243dSDimitry Andric     auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
3661bdd1243dSDimitry Andric         Ptrs, IRB, ElementShadowTy, Alignment, /*isStore*/ true);
3662bdd1243dSDimitry Andric 
3663bdd1243dSDimitry Andric     IRB.CreateMaskedScatter(Shadow, ShadowPtrs, Alignment, Mask);
3664bdd1243dSDimitry Andric 
3665bdd1243dSDimitry Andric     // TODO: Store origin.
3666bdd1243dSDimitry Andric   }
3667bdd1243dSDimitry Andric 
3668bdd1243dSDimitry Andric   void handleMaskedStore(IntrinsicInst &I) {
3669bdd1243dSDimitry Andric     IRBuilder<> IRB(&I);
3670bdd1243dSDimitry Andric     Value *V = I.getArgOperand(0);
3671bdd1243dSDimitry Andric     Value *Ptr = I.getArgOperand(1);
3672bdd1243dSDimitry Andric     const Align Alignment(
3673bdd1243dSDimitry Andric         cast<ConstantInt>(I.getArgOperand(2))->getZExtValue());
3674bdd1243dSDimitry Andric     Value *Mask = I.getArgOperand(3);
3675bdd1243dSDimitry Andric     Value *Shadow = getShadow(V);
3676bdd1243dSDimitry Andric 
3677bdd1243dSDimitry Andric     if (ClCheckAccessAddress) {
3678bdd1243dSDimitry Andric       insertShadowCheck(Ptr, &I);
36790b57cec5SDimitry Andric       insertShadowCheck(Mask, &I);
36800b57cec5SDimitry Andric     }
36810b57cec5SDimitry Andric 
3682bdd1243dSDimitry Andric     Value *ShadowPtr;
3683bdd1243dSDimitry Andric     Value *OriginPtr;
3684bdd1243dSDimitry Andric     std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3685bdd1243dSDimitry Andric         Ptr, IRB, Shadow->getType(), Alignment, /*isStore*/ true);
3686bdd1243dSDimitry Andric 
3687bdd1243dSDimitry Andric     IRB.CreateMaskedStore(Shadow, ShadowPtr, Alignment, Mask);
3688bdd1243dSDimitry Andric 
3689bdd1243dSDimitry Andric     if (!MS.TrackOrigins)
3690bdd1243dSDimitry Andric       return;
3691bdd1243dSDimitry Andric 
3692*0fca6ea1SDimitry Andric     auto &DL = F.getDataLayout();
3693bdd1243dSDimitry Andric     paintOrigin(IRB, getOrigin(V), OriginPtr,
3694bdd1243dSDimitry Andric                 DL.getTypeStoreSize(Shadow->getType()),
3695bdd1243dSDimitry Andric                 std::max(Alignment, kMinOriginAlignment));
3696bdd1243dSDimitry Andric   }
3697bdd1243dSDimitry Andric 
3698bdd1243dSDimitry Andric   void handleMaskedLoad(IntrinsicInst &I) {
3699bdd1243dSDimitry Andric     IRBuilder<> IRB(&I);
3700bdd1243dSDimitry Andric     Value *Ptr = I.getArgOperand(0);
3701bdd1243dSDimitry Andric     const Align Alignment(
3702bdd1243dSDimitry Andric         cast<ConstantInt>(I.getArgOperand(1))->getZExtValue());
3703bdd1243dSDimitry Andric     Value *Mask = I.getArgOperand(2);
3704bdd1243dSDimitry Andric     Value *PassThru = I.getArgOperand(3);
3705bdd1243dSDimitry Andric 
3706bdd1243dSDimitry Andric     if (ClCheckAccessAddress) {
3707bdd1243dSDimitry Andric       insertShadowCheck(Ptr, &I);
3708bdd1243dSDimitry Andric       insertShadowCheck(Mask, &I);
3709bdd1243dSDimitry Andric     }
3710bdd1243dSDimitry Andric 
3711bdd1243dSDimitry Andric     if (!PropagateShadow) {
3712bdd1243dSDimitry Andric       setShadow(&I, getCleanShadow(&I));
3713bdd1243dSDimitry Andric       setOrigin(&I, getCleanOrigin());
3714bdd1243dSDimitry Andric       return;
3715bdd1243dSDimitry Andric     }
3716bdd1243dSDimitry Andric 
3717bdd1243dSDimitry Andric     Type *ShadowTy = getShadowTy(&I);
3718bdd1243dSDimitry Andric     Value *ShadowPtr, *OriginPtr;
3719bdd1243dSDimitry Andric     std::tie(ShadowPtr, OriginPtr) =
3720bdd1243dSDimitry Andric         getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment, /*isStore*/ false);
3721bdd1243dSDimitry Andric     setShadow(&I, IRB.CreateMaskedLoad(ShadowTy, ShadowPtr, Alignment, Mask,
3722bdd1243dSDimitry Andric                                        getShadow(PassThru), "_msmaskedld"));
3723bdd1243dSDimitry Andric 
3724bdd1243dSDimitry Andric     if (!MS.TrackOrigins)
3725bdd1243dSDimitry Andric       return;
3726bdd1243dSDimitry Andric 
37270b57cec5SDimitry Andric     // Choose between PassThru's and the loaded value's origins.
37280b57cec5SDimitry Andric     Value *MaskedPassThruShadow = IRB.CreateAnd(
37290b57cec5SDimitry Andric         getShadow(PassThru), IRB.CreateSExt(IRB.CreateNeg(Mask), ShadowTy));
37300b57cec5SDimitry Andric 
373106c3fb27SDimitry Andric     Value *NotNull = convertToBool(MaskedPassThruShadow, IRB, "_mscmp");
37320b57cec5SDimitry Andric 
3733bdd1243dSDimitry Andric     Value *PtrOrigin = IRB.CreateLoad(MS.OriginTy, OriginPtr);
3734bdd1243dSDimitry Andric     Value *Origin = IRB.CreateSelect(NotNull, getOrigin(PassThru), PtrOrigin);
37350b57cec5SDimitry Andric 
37360b57cec5SDimitry Andric     setOrigin(&I, Origin);
37370b57cec5SDimitry Andric   }
37380b57cec5SDimitry Andric 
37390b57cec5SDimitry Andric   // Instrument BMI / BMI2 intrinsics.
37400b57cec5SDimitry Andric   // All of these intrinsics are Z = I(X, Y)
3741bdd1243dSDimitry Andric   // where the types of all operands and the result match, and are either i32 or
3742bdd1243dSDimitry Andric   // i64. The following instrumentation happens to work for all of them:
37430b57cec5SDimitry Andric   //   Sz = I(Sx, Y) | (sext (Sy != 0))
37440b57cec5SDimitry Andric   void handleBmiIntrinsic(IntrinsicInst &I) {
37450b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
37460b57cec5SDimitry Andric     Type *ShadowTy = getShadowTy(&I);
37470b57cec5SDimitry Andric 
37480b57cec5SDimitry Andric     // If any bit of the mask operand is poisoned, then the whole thing is.
37490b57cec5SDimitry Andric     Value *SMask = getShadow(&I, 1);
37500b57cec5SDimitry Andric     SMask = IRB.CreateSExt(IRB.CreateICmpNE(SMask, getCleanShadow(ShadowTy)),
37510b57cec5SDimitry Andric                            ShadowTy);
37520b57cec5SDimitry Andric     // Apply the same intrinsic to the shadow of the first operand.
37530b57cec5SDimitry Andric     Value *S = IRB.CreateCall(I.getCalledFunction(),
37540b57cec5SDimitry Andric                               {getShadow(&I, 0), I.getOperand(1)});
37550b57cec5SDimitry Andric     S = IRB.CreateOr(SMask, S);
37560b57cec5SDimitry Andric     setShadow(&I, S);
37570b57cec5SDimitry Andric     setOriginForNaryOp(I);
37580b57cec5SDimitry Andric   }
37590b57cec5SDimitry Andric 
3760*0fca6ea1SDimitry Andric   static SmallVector<int, 8> getPclmulMask(unsigned Width, bool OddElements) {
37615ffd83dbSDimitry Andric     SmallVector<int, 8> Mask;
376213138422SDimitry Andric     for (unsigned X = OddElements ? 1 : 0; X < Width; X += 2) {
37635ffd83dbSDimitry Andric       Mask.append(2, X);
376413138422SDimitry Andric     }
37655ffd83dbSDimitry Andric     return Mask;
376613138422SDimitry Andric   }
376713138422SDimitry Andric 
376813138422SDimitry Andric   // Instrument pclmul intrinsics.
376913138422SDimitry Andric   // These intrinsics operate either on odd or on even elements of the input
377013138422SDimitry Andric   // vectors, depending on the constant in the 3rd argument, ignoring the rest.
377113138422SDimitry Andric   // Replace the unused elements with copies of the used ones, ex:
377213138422SDimitry Andric   //   (0, 1, 2, 3) -> (0, 0, 2, 2) (even case)
377313138422SDimitry Andric   // or
377413138422SDimitry Andric   //   (0, 1, 2, 3) -> (1, 1, 3, 3) (odd case)
377513138422SDimitry Andric   // and then apply the usual shadow combining logic.
377613138422SDimitry Andric   void handlePclmulIntrinsic(IntrinsicInst &I) {
377713138422SDimitry Andric     IRBuilder<> IRB(&I);
37785ffd83dbSDimitry Andric     unsigned Width =
37795ffd83dbSDimitry Andric         cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements();
378013138422SDimitry Andric     assert(isa<ConstantInt>(I.getArgOperand(2)) &&
378113138422SDimitry Andric            "pclmul 3rd operand must be a constant");
378213138422SDimitry Andric     unsigned Imm = cast<ConstantInt>(I.getArgOperand(2))->getZExtValue();
3783e8d8bef9SDimitry Andric     Value *Shuf0 = IRB.CreateShuffleVector(getShadow(&I, 0),
37845ffd83dbSDimitry Andric                                            getPclmulMask(Width, Imm & 0x01));
3785e8d8bef9SDimitry Andric     Value *Shuf1 = IRB.CreateShuffleVector(getShadow(&I, 1),
37865ffd83dbSDimitry Andric                                            getPclmulMask(Width, Imm & 0x10));
378713138422SDimitry Andric     ShadowAndOriginCombiner SOC(this, IRB);
378813138422SDimitry Andric     SOC.Add(Shuf0, getOrigin(&I, 0));
378913138422SDimitry Andric     SOC.Add(Shuf1, getOrigin(&I, 1));
379013138422SDimitry Andric     SOC.Done(&I);
379113138422SDimitry Andric   }
379213138422SDimitry Andric 
379381ad6265SDimitry Andric   // Instrument _mm_*_sd|ss intrinsics
379481ad6265SDimitry Andric   void handleUnarySdSsIntrinsic(IntrinsicInst &I) {
37955ffd83dbSDimitry Andric     IRBuilder<> IRB(&I);
379681ad6265SDimitry Andric     unsigned Width =
379781ad6265SDimitry Andric         cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements();
37985ffd83dbSDimitry Andric     Value *First = getShadow(&I, 0);
37995ffd83dbSDimitry Andric     Value *Second = getShadow(&I, 1);
380081ad6265SDimitry Andric     // First element of second operand, remaining elements of first operand
380181ad6265SDimitry Andric     SmallVector<int, 16> Mask;
380281ad6265SDimitry Andric     Mask.push_back(Width);
380381ad6265SDimitry Andric     for (unsigned i = 1; i < Width; i++)
380481ad6265SDimitry Andric       Mask.push_back(i);
380581ad6265SDimitry Andric     Value *Shadow = IRB.CreateShuffleVector(First, Second, Mask);
38065ffd83dbSDimitry Andric 
38075ffd83dbSDimitry Andric     setShadow(&I, Shadow);
38085ffd83dbSDimitry Andric     setOriginForNaryOp(I);
38095ffd83dbSDimitry Andric   }
38105ffd83dbSDimitry Andric 
3811bdd1243dSDimitry Andric   void handleVtestIntrinsic(IntrinsicInst &I) {
3812bdd1243dSDimitry Andric     IRBuilder<> IRB(&I);
3813bdd1243dSDimitry Andric     Value *Shadow0 = getShadow(&I, 0);
3814bdd1243dSDimitry Andric     Value *Shadow1 = getShadow(&I, 1);
3815bdd1243dSDimitry Andric     Value *Or = IRB.CreateOr(Shadow0, Shadow1);
3816bdd1243dSDimitry Andric     Value *NZ = IRB.CreateICmpNE(Or, Constant::getNullValue(Or->getType()));
3817bdd1243dSDimitry Andric     Value *Scalar = convertShadowToScalar(NZ, IRB);
3818bdd1243dSDimitry Andric     Value *Shadow = IRB.CreateZExt(Scalar, getShadowTy(&I));
3819bdd1243dSDimitry Andric 
3820bdd1243dSDimitry Andric     setShadow(&I, Shadow);
3821bdd1243dSDimitry Andric     setOriginForNaryOp(I);
3822bdd1243dSDimitry Andric   }
3823bdd1243dSDimitry Andric 
382481ad6265SDimitry Andric   void handleBinarySdSsIntrinsic(IntrinsicInst &I) {
38255ffd83dbSDimitry Andric     IRBuilder<> IRB(&I);
382681ad6265SDimitry Andric     unsigned Width =
382781ad6265SDimitry Andric         cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements();
38285ffd83dbSDimitry Andric     Value *First = getShadow(&I, 0);
38295ffd83dbSDimitry Andric     Value *Second = getShadow(&I, 1);
38305ffd83dbSDimitry Andric     Value *OrShadow = IRB.CreateOr(First, Second);
383181ad6265SDimitry Andric     // First element of both OR'd together, remaining elements of first operand
383281ad6265SDimitry Andric     SmallVector<int, 16> Mask;
383381ad6265SDimitry Andric     Mask.push_back(Width);
383481ad6265SDimitry Andric     for (unsigned i = 1; i < Width; i++)
383581ad6265SDimitry Andric       Mask.push_back(i);
383681ad6265SDimitry Andric     Value *Shadow = IRB.CreateShuffleVector(First, OrShadow, Mask);
38375ffd83dbSDimitry Andric 
38385ffd83dbSDimitry Andric     setShadow(&I, Shadow);
38395ffd83dbSDimitry Andric     setOriginForNaryOp(I);
38405ffd83dbSDimitry Andric   }
38415ffd83dbSDimitry Andric 
3842e8d8bef9SDimitry Andric   // Instrument abs intrinsic.
3843e8d8bef9SDimitry Andric   // handleUnknownIntrinsic can't handle it because of the last
3844e8d8bef9SDimitry Andric   // is_int_min_poison argument which does not match the result type.
3845e8d8bef9SDimitry Andric   void handleAbsIntrinsic(IntrinsicInst &I) {
3846e8d8bef9SDimitry Andric     assert(I.getType()->isIntOrIntVectorTy());
3847e8d8bef9SDimitry Andric     assert(I.getArgOperand(0)->getType() == I.getType());
3848e8d8bef9SDimitry Andric 
3849e8d8bef9SDimitry Andric     // FIXME: Handle is_int_min_poison.
3850e8d8bef9SDimitry Andric     IRBuilder<> IRB(&I);
3851e8d8bef9SDimitry Andric     setShadow(&I, getShadow(&I, 0));
3852e8d8bef9SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
3853e8d8bef9SDimitry Andric   }
3854e8d8bef9SDimitry Andric 
385506c3fb27SDimitry Andric   void handleIsFpClass(IntrinsicInst &I) {
385606c3fb27SDimitry Andric     IRBuilder<> IRB(&I);
385706c3fb27SDimitry Andric     Value *Shadow = getShadow(&I, 0);
385806c3fb27SDimitry Andric     setShadow(&I, IRB.CreateICmpNE(Shadow, getCleanShadow(Shadow)));
385906c3fb27SDimitry Andric     setOrigin(&I, getOrigin(&I, 0));
386006c3fb27SDimitry Andric   }
386106c3fb27SDimitry Andric 
3862*0fca6ea1SDimitry Andric   void handleArithmeticWithOverflow(IntrinsicInst &I) {
3863*0fca6ea1SDimitry Andric     IRBuilder<> IRB(&I);
3864*0fca6ea1SDimitry Andric     Value *Shadow0 = getShadow(&I, 0);
3865*0fca6ea1SDimitry Andric     Value *Shadow1 = getShadow(&I, 1);
3866*0fca6ea1SDimitry Andric     Value *ShadowElt0 = IRB.CreateOr(Shadow0, Shadow1);
3867*0fca6ea1SDimitry Andric     Value *ShadowElt1 =
3868*0fca6ea1SDimitry Andric         IRB.CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
3869*0fca6ea1SDimitry Andric 
3870*0fca6ea1SDimitry Andric     Value *Shadow = PoisonValue::get(getShadowTy(&I));
3871*0fca6ea1SDimitry Andric     Shadow = IRB.CreateInsertValue(Shadow, ShadowElt0, 0);
3872*0fca6ea1SDimitry Andric     Shadow = IRB.CreateInsertValue(Shadow, ShadowElt1, 1);
3873*0fca6ea1SDimitry Andric 
3874*0fca6ea1SDimitry Andric     setShadow(&I, Shadow);
3875*0fca6ea1SDimitry Andric     setOriginForNaryOp(I);
3876*0fca6ea1SDimitry Andric   }
3877*0fca6ea1SDimitry Andric 
3878*0fca6ea1SDimitry Andric   /// Handle Arm NEON vector store intrinsics (vst{2,3,4}).
3879*0fca6ea1SDimitry Andric   ///
3880*0fca6ea1SDimitry Andric   /// Arm NEON vector store intrinsics have the output address (pointer) as the
3881*0fca6ea1SDimitry Andric   /// last argument, with the initial arguments being the inputs. They return
3882*0fca6ea1SDimitry Andric   /// void.
3883*0fca6ea1SDimitry Andric   void handleNEONVectorStoreIntrinsic(IntrinsicInst &I) {
3884*0fca6ea1SDimitry Andric     IRBuilder<> IRB(&I);
3885*0fca6ea1SDimitry Andric 
3886*0fca6ea1SDimitry Andric     // Don't use getNumOperands() because it includes the callee
3887*0fca6ea1SDimitry Andric     int numArgOperands = I.arg_size();
3888*0fca6ea1SDimitry Andric     assert(numArgOperands >= 1);
3889*0fca6ea1SDimitry Andric 
3890*0fca6ea1SDimitry Andric     // The last arg operand is the output
3891*0fca6ea1SDimitry Andric     Value *Addr = I.getArgOperand(numArgOperands - 1);
3892*0fca6ea1SDimitry Andric     assert(Addr->getType()->isPointerTy());
3893*0fca6ea1SDimitry Andric 
3894*0fca6ea1SDimitry Andric     if (ClCheckAccessAddress)
3895*0fca6ea1SDimitry Andric       insertShadowCheck(Addr, &I);
3896*0fca6ea1SDimitry Andric 
3897*0fca6ea1SDimitry Andric     // Every arg operand, other than the last one, is an input vector
3898*0fca6ea1SDimitry Andric     IntrinsicInst *ShadowI = cast<IntrinsicInst>(I.clone());
3899*0fca6ea1SDimitry Andric     for (int i = 0; i < numArgOperands - 1; i++) {
3900*0fca6ea1SDimitry Andric       assert(isa<FixedVectorType>(I.getArgOperand(i)->getType()));
3901*0fca6ea1SDimitry Andric       ShadowI->setArgOperand(i, getShadow(&I, i));
3902*0fca6ea1SDimitry Andric     }
3903*0fca6ea1SDimitry Andric 
3904*0fca6ea1SDimitry Andric     // MSan's GetShadowTy assumes the LHS is the type we want the shadow for
3905*0fca6ea1SDimitry Andric     // e.g., for:
3906*0fca6ea1SDimitry Andric     //     [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to i128
3907*0fca6ea1SDimitry Andric     // we know the type of the output (and its shadow) is <16 x i8>.
3908*0fca6ea1SDimitry Andric     //
3909*0fca6ea1SDimitry Andric     // Arm NEON VST is unusual because the last argument is the output address:
3910*0fca6ea1SDimitry Andric     //     define void @st2_16b(<16 x i8> %A, <16 x i8> %B, ptr %P) {
3911*0fca6ea1SDimitry Andric     //         call void @llvm.aarch64.neon.st2.v16i8.p0
3912*0fca6ea1SDimitry Andric     //                   (<16 x i8> [[A]], <16 x i8> [[B]], ptr [[P]])
3913*0fca6ea1SDimitry Andric     // and we have no type information about P's operand. We must manually
3914*0fca6ea1SDimitry Andric     // compute the type (<16 x i8> x 2).
3915*0fca6ea1SDimitry Andric     FixedVectorType *OutputVectorTy = FixedVectorType::get(
3916*0fca6ea1SDimitry Andric         cast<FixedVectorType>(I.getArgOperand(0)->getType())->getElementType(),
3917*0fca6ea1SDimitry Andric         cast<FixedVectorType>(I.getArgOperand(0)->getType())->getNumElements() *
3918*0fca6ea1SDimitry Andric             (numArgOperands - 1));
3919*0fca6ea1SDimitry Andric     Type *ShadowTy = getShadowTy(OutputVectorTy);
3920*0fca6ea1SDimitry Andric     Value *ShadowPtr, *OriginPtr;
3921*0fca6ea1SDimitry Andric     // AArch64 NEON does not need alignment (unless OS requires it)
3922*0fca6ea1SDimitry Andric     std::tie(ShadowPtr, OriginPtr) =
3923*0fca6ea1SDimitry Andric         getShadowOriginPtr(Addr, IRB, ShadowTy, Align(1), /*isStore*/ true);
3924*0fca6ea1SDimitry Andric     ShadowI->setArgOperand(numArgOperands - 1, ShadowPtr);
3925*0fca6ea1SDimitry Andric     ShadowI->insertAfter(&I);
3926*0fca6ea1SDimitry Andric 
3927*0fca6ea1SDimitry Andric     if (MS.TrackOrigins) {
3928*0fca6ea1SDimitry Andric       // TODO: if we modelled the vst* instruction more precisely, we could
3929*0fca6ea1SDimitry Andric       // more accurately track the origins (e.g., if both inputs are
3930*0fca6ea1SDimitry Andric       // uninitialized for vst2, we currently blame the second input, even
3931*0fca6ea1SDimitry Andric       // though part of the output depends only on the first input).
3932*0fca6ea1SDimitry Andric       OriginCombiner OC(this, IRB);
3933*0fca6ea1SDimitry Andric       for (int i = 0; i < numArgOperands - 1; i++)
3934*0fca6ea1SDimitry Andric         OC.Add(I.getArgOperand(i));
3935*0fca6ea1SDimitry Andric 
3936*0fca6ea1SDimitry Andric       const DataLayout &DL = F.getDataLayout();
3937*0fca6ea1SDimitry Andric       OC.DoneAndStoreOrigin(DL.getTypeStoreSize(OutputVectorTy), OriginPtr);
3938*0fca6ea1SDimitry Andric     }
3939*0fca6ea1SDimitry Andric   }
3940*0fca6ea1SDimitry Andric 
39410b57cec5SDimitry Andric   void visitIntrinsicInst(IntrinsicInst &I) {
39420b57cec5SDimitry Andric     switch (I.getIntrinsicID()) {
3943*0fca6ea1SDimitry Andric     case Intrinsic::uadd_with_overflow:
3944*0fca6ea1SDimitry Andric     case Intrinsic::sadd_with_overflow:
3945*0fca6ea1SDimitry Andric     case Intrinsic::usub_with_overflow:
3946*0fca6ea1SDimitry Andric     case Intrinsic::ssub_with_overflow:
3947*0fca6ea1SDimitry Andric     case Intrinsic::umul_with_overflow:
3948*0fca6ea1SDimitry Andric     case Intrinsic::smul_with_overflow:
3949*0fca6ea1SDimitry Andric       handleArithmeticWithOverflow(I);
3950*0fca6ea1SDimitry Andric       break;
3951e8d8bef9SDimitry Andric     case Intrinsic::abs:
3952e8d8bef9SDimitry Andric       handleAbsIntrinsic(I);
3953e8d8bef9SDimitry Andric       break;
395406c3fb27SDimitry Andric     case Intrinsic::is_fpclass:
395506c3fb27SDimitry Andric       handleIsFpClass(I);
395606c3fb27SDimitry Andric       break;
39570b57cec5SDimitry Andric     case Intrinsic::lifetime_start:
39580b57cec5SDimitry Andric       handleLifetimeStart(I);
39590b57cec5SDimitry Andric       break;
39608bcb0991SDimitry Andric     case Intrinsic::launder_invariant_group:
39618bcb0991SDimitry Andric     case Intrinsic::strip_invariant_group:
39628bcb0991SDimitry Andric       handleInvariantGroup(I);
39638bcb0991SDimitry Andric       break;
39640b57cec5SDimitry Andric     case Intrinsic::bswap:
39650b57cec5SDimitry Andric       handleBswap(I);
39660b57cec5SDimitry Andric       break;
3967bdd1243dSDimitry Andric     case Intrinsic::ctlz:
3968bdd1243dSDimitry Andric     case Intrinsic::cttz:
3969bdd1243dSDimitry Andric       handleCountZeroes(I);
3970bdd1243dSDimitry Andric       break;
3971bdd1243dSDimitry Andric     case Intrinsic::masked_compressstore:
3972bdd1243dSDimitry Andric       handleMaskedCompressStore(I);
3973bdd1243dSDimitry Andric       break;
3974bdd1243dSDimitry Andric     case Intrinsic::masked_expandload:
3975bdd1243dSDimitry Andric       handleMaskedExpandLoad(I);
3976bdd1243dSDimitry Andric       break;
3977bdd1243dSDimitry Andric     case Intrinsic::masked_gather:
3978bdd1243dSDimitry Andric       handleMaskedGather(I);
3979bdd1243dSDimitry Andric       break;
3980bdd1243dSDimitry Andric     case Intrinsic::masked_scatter:
3981bdd1243dSDimitry Andric       handleMaskedScatter(I);
3982bdd1243dSDimitry Andric       break;
39830b57cec5SDimitry Andric     case Intrinsic::masked_store:
39840b57cec5SDimitry Andric       handleMaskedStore(I);
39850b57cec5SDimitry Andric       break;
39860b57cec5SDimitry Andric     case Intrinsic::masked_load:
39870b57cec5SDimitry Andric       handleMaskedLoad(I);
39880b57cec5SDimitry Andric       break;
3989e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_and:
39905ffd83dbSDimitry Andric       handleVectorReduceAndIntrinsic(I);
39915ffd83dbSDimitry Andric       break;
3992e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_or:
39935ffd83dbSDimitry Andric       handleVectorReduceOrIntrinsic(I);
39945ffd83dbSDimitry Andric       break;
3995e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_add:
3996e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_xor:
3997e8d8bef9SDimitry Andric     case Intrinsic::vector_reduce_mul:
39985ffd83dbSDimitry Andric       handleVectorReduceIntrinsic(I);
39995ffd83dbSDimitry Andric       break;
40000b57cec5SDimitry Andric     case Intrinsic::x86_sse_stmxcsr:
40010b57cec5SDimitry Andric       handleStmxcsr(I);
40020b57cec5SDimitry Andric       break;
40030b57cec5SDimitry Andric     case Intrinsic::x86_sse_ldmxcsr:
40040b57cec5SDimitry Andric       handleLdmxcsr(I);
40050b57cec5SDimitry Andric       break;
40060b57cec5SDimitry Andric     case Intrinsic::x86_avx512_vcvtsd2usi64:
40070b57cec5SDimitry Andric     case Intrinsic::x86_avx512_vcvtsd2usi32:
40080b57cec5SDimitry Andric     case Intrinsic::x86_avx512_vcvtss2usi64:
40090b57cec5SDimitry Andric     case Intrinsic::x86_avx512_vcvtss2usi32:
40100b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvttss2usi64:
40110b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvttss2usi:
40120b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvttsd2usi64:
40130b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvttsd2usi:
40140b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvtusi2ss:
40150b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvtusi642sd:
40160b57cec5SDimitry Andric     case Intrinsic::x86_avx512_cvtusi642ss:
4017e8d8bef9SDimitry Andric       handleVectorConvertIntrinsic(I, 1, true);
4018e8d8bef9SDimitry Andric       break;
40190b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cvtsd2si64:
40200b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cvtsd2si:
40210b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cvtsd2ss:
40220b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cvttsd2si64:
40230b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cvttsd2si:
40240b57cec5SDimitry Andric     case Intrinsic::x86_sse_cvtss2si64:
40250b57cec5SDimitry Andric     case Intrinsic::x86_sse_cvtss2si:
40260b57cec5SDimitry Andric     case Intrinsic::x86_sse_cvttss2si64:
40270b57cec5SDimitry Andric     case Intrinsic::x86_sse_cvttss2si:
40280b57cec5SDimitry Andric       handleVectorConvertIntrinsic(I, 1);
40290b57cec5SDimitry Andric       break;
40300b57cec5SDimitry Andric     case Intrinsic::x86_sse_cvtps2pi:
40310b57cec5SDimitry Andric     case Intrinsic::x86_sse_cvttps2pi:
40320b57cec5SDimitry Andric       handleVectorConvertIntrinsic(I, 2);
40330b57cec5SDimitry Andric       break;
40340b57cec5SDimitry Andric 
40350b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psll_w_512:
40360b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psll_d_512:
40370b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psll_q_512:
40380b57cec5SDimitry Andric     case Intrinsic::x86_avx512_pslli_w_512:
40390b57cec5SDimitry Andric     case Intrinsic::x86_avx512_pslli_d_512:
40400b57cec5SDimitry Andric     case Intrinsic::x86_avx512_pslli_q_512:
40410b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrl_w_512:
40420b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrl_d_512:
40430b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrl_q_512:
40440b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psra_w_512:
40450b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psra_d_512:
40460b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psra_q_512:
40470b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrli_w_512:
40480b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrli_d_512:
40490b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrli_q_512:
40500b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrai_w_512:
40510b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrai_d_512:
40520b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrai_q_512:
40530b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psra_q_256:
40540b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psra_q_128:
40550b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrai_q_256:
40560b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrai_q_128:
40570b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psll_w:
40580b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psll_d:
40590b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psll_q:
40600b57cec5SDimitry Andric     case Intrinsic::x86_avx2_pslli_w:
40610b57cec5SDimitry Andric     case Intrinsic::x86_avx2_pslli_d:
40620b57cec5SDimitry Andric     case Intrinsic::x86_avx2_pslli_q:
40630b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrl_w:
40640b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrl_d:
40650b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrl_q:
40660b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psra_w:
40670b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psra_d:
40680b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrli_w:
40690b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrli_d:
40700b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrli_q:
40710b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrai_w:
40720b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrai_d:
40730b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psll_w:
40740b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psll_d:
40750b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psll_q:
40760b57cec5SDimitry Andric     case Intrinsic::x86_sse2_pslli_w:
40770b57cec5SDimitry Andric     case Intrinsic::x86_sse2_pslli_d:
40780b57cec5SDimitry Andric     case Intrinsic::x86_sse2_pslli_q:
40790b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrl_w:
40800b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrl_d:
40810b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrl_q:
40820b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psra_w:
40830b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psra_d:
40840b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrli_w:
40850b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrli_d:
40860b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrli_q:
40870b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrai_w:
40880b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psrai_d:
40890b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psll_w:
40900b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psll_d:
40910b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psll_q:
40920b57cec5SDimitry Andric     case Intrinsic::x86_mmx_pslli_w:
40930b57cec5SDimitry Andric     case Intrinsic::x86_mmx_pslli_d:
40940b57cec5SDimitry Andric     case Intrinsic::x86_mmx_pslli_q:
40950b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrl_w:
40960b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrl_d:
40970b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrl_q:
40980b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psra_w:
40990b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psra_d:
41000b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrli_w:
41010b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrli_d:
41020b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrli_q:
41030b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrai_w:
41040b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psrai_d:
41050b57cec5SDimitry Andric       handleVectorShiftIntrinsic(I, /* Variable */ false);
41060b57cec5SDimitry Andric       break;
41070b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psllv_d:
41080b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psllv_d_256:
41090b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psllv_d_512:
41100b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psllv_q:
41110b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psllv_q_256:
41120b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psllv_q_512:
41130b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrlv_d:
41140b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrlv_d_256:
41150b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrlv_d_512:
41160b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrlv_q:
41170b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrlv_q_256:
41180b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrlv_q_512:
41190b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrav_d:
41200b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psrav_d_256:
41210b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrav_d_512:
41220b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrav_q_128:
41230b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrav_q_256:
41240b57cec5SDimitry Andric     case Intrinsic::x86_avx512_psrav_q_512:
41250b57cec5SDimitry Andric       handleVectorShiftIntrinsic(I, /* Variable */ true);
41260b57cec5SDimitry Andric       break;
41270b57cec5SDimitry Andric 
41280b57cec5SDimitry Andric     case Intrinsic::x86_sse2_packsswb_128:
41290b57cec5SDimitry Andric     case Intrinsic::x86_sse2_packssdw_128:
41300b57cec5SDimitry Andric     case Intrinsic::x86_sse2_packuswb_128:
41310b57cec5SDimitry Andric     case Intrinsic::x86_sse41_packusdw:
41320b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packsswb:
41330b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packssdw:
41340b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packuswb:
41350b57cec5SDimitry Andric     case Intrinsic::x86_avx2_packusdw:
41360b57cec5SDimitry Andric       handleVectorPackIntrinsic(I);
41370b57cec5SDimitry Andric       break;
41380b57cec5SDimitry Andric 
4139*0fca6ea1SDimitry Andric     case Intrinsic::x86_sse41_pblendvb:
4140*0fca6ea1SDimitry Andric     case Intrinsic::x86_sse41_blendvpd:
4141*0fca6ea1SDimitry Andric     case Intrinsic::x86_sse41_blendvps:
4142*0fca6ea1SDimitry Andric     case Intrinsic::x86_avx_blendv_pd_256:
4143*0fca6ea1SDimitry Andric     case Intrinsic::x86_avx_blendv_ps_256:
4144*0fca6ea1SDimitry Andric     case Intrinsic::x86_avx2_pblendvb:
4145*0fca6ea1SDimitry Andric       handleBlendvIntrinsic(I);
4146*0fca6ea1SDimitry Andric       break;
4147*0fca6ea1SDimitry Andric 
4148*0fca6ea1SDimitry Andric     case Intrinsic::x86_avx_dp_ps_256:
4149*0fca6ea1SDimitry Andric     case Intrinsic::x86_sse41_dppd:
4150*0fca6ea1SDimitry Andric     case Intrinsic::x86_sse41_dpps:
4151*0fca6ea1SDimitry Andric       handleDppIntrinsic(I);
4152*0fca6ea1SDimitry Andric       break;
4153*0fca6ea1SDimitry Andric 
41540b57cec5SDimitry Andric     case Intrinsic::x86_mmx_packsswb:
41550b57cec5SDimitry Andric     case Intrinsic::x86_mmx_packuswb:
41560b57cec5SDimitry Andric       handleVectorPackIntrinsic(I, 16);
41570b57cec5SDimitry Andric       break;
41580b57cec5SDimitry Andric 
41590b57cec5SDimitry Andric     case Intrinsic::x86_mmx_packssdw:
41600b57cec5SDimitry Andric       handleVectorPackIntrinsic(I, 32);
41610b57cec5SDimitry Andric       break;
41620b57cec5SDimitry Andric 
41630b57cec5SDimitry Andric     case Intrinsic::x86_mmx_psad_bw:
41640b57cec5SDimitry Andric     case Intrinsic::x86_sse2_psad_bw:
41650b57cec5SDimitry Andric     case Intrinsic::x86_avx2_psad_bw:
41660b57cec5SDimitry Andric       handleVectorSadIntrinsic(I);
41670b57cec5SDimitry Andric       break;
41680b57cec5SDimitry Andric 
41690b57cec5SDimitry Andric     case Intrinsic::x86_sse2_pmadd_wd:
41700b57cec5SDimitry Andric     case Intrinsic::x86_avx2_pmadd_wd:
41710b57cec5SDimitry Andric     case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
41720b57cec5SDimitry Andric     case Intrinsic::x86_avx2_pmadd_ub_sw:
41730b57cec5SDimitry Andric       handleVectorPmaddIntrinsic(I);
41740b57cec5SDimitry Andric       break;
41750b57cec5SDimitry Andric 
41760b57cec5SDimitry Andric     case Intrinsic::x86_ssse3_pmadd_ub_sw:
41770b57cec5SDimitry Andric       handleVectorPmaddIntrinsic(I, 8);
41780b57cec5SDimitry Andric       break;
41790b57cec5SDimitry Andric 
41800b57cec5SDimitry Andric     case Intrinsic::x86_mmx_pmadd_wd:
41810b57cec5SDimitry Andric       handleVectorPmaddIntrinsic(I, 16);
41820b57cec5SDimitry Andric       break;
41830b57cec5SDimitry Andric 
41840b57cec5SDimitry Andric     case Intrinsic::x86_sse_cmp_ss:
41850b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cmp_sd:
41860b57cec5SDimitry Andric     case Intrinsic::x86_sse_comieq_ss:
41870b57cec5SDimitry Andric     case Intrinsic::x86_sse_comilt_ss:
41880b57cec5SDimitry Andric     case Intrinsic::x86_sse_comile_ss:
41890b57cec5SDimitry Andric     case Intrinsic::x86_sse_comigt_ss:
41900b57cec5SDimitry Andric     case Intrinsic::x86_sse_comige_ss:
41910b57cec5SDimitry Andric     case Intrinsic::x86_sse_comineq_ss:
41920b57cec5SDimitry Andric     case Intrinsic::x86_sse_ucomieq_ss:
41930b57cec5SDimitry Andric     case Intrinsic::x86_sse_ucomilt_ss:
41940b57cec5SDimitry Andric     case Intrinsic::x86_sse_ucomile_ss:
41950b57cec5SDimitry Andric     case Intrinsic::x86_sse_ucomigt_ss:
41960b57cec5SDimitry Andric     case Intrinsic::x86_sse_ucomige_ss:
41970b57cec5SDimitry Andric     case Intrinsic::x86_sse_ucomineq_ss:
41980b57cec5SDimitry Andric     case Intrinsic::x86_sse2_comieq_sd:
41990b57cec5SDimitry Andric     case Intrinsic::x86_sse2_comilt_sd:
42000b57cec5SDimitry Andric     case Intrinsic::x86_sse2_comile_sd:
42010b57cec5SDimitry Andric     case Intrinsic::x86_sse2_comigt_sd:
42020b57cec5SDimitry Andric     case Intrinsic::x86_sse2_comige_sd:
42030b57cec5SDimitry Andric     case Intrinsic::x86_sse2_comineq_sd:
42040b57cec5SDimitry Andric     case Intrinsic::x86_sse2_ucomieq_sd:
42050b57cec5SDimitry Andric     case Intrinsic::x86_sse2_ucomilt_sd:
42060b57cec5SDimitry Andric     case Intrinsic::x86_sse2_ucomile_sd:
42070b57cec5SDimitry Andric     case Intrinsic::x86_sse2_ucomigt_sd:
42080b57cec5SDimitry Andric     case Intrinsic::x86_sse2_ucomige_sd:
42090b57cec5SDimitry Andric     case Intrinsic::x86_sse2_ucomineq_sd:
42100b57cec5SDimitry Andric       handleVectorCompareScalarIntrinsic(I);
42110b57cec5SDimitry Andric       break;
42120b57cec5SDimitry Andric 
4213bdd1243dSDimitry Andric     case Intrinsic::x86_avx_cmp_pd_256:
4214bdd1243dSDimitry Andric     case Intrinsic::x86_avx_cmp_ps_256:
42150b57cec5SDimitry Andric     case Intrinsic::x86_sse2_cmp_pd:
4216bdd1243dSDimitry Andric     case Intrinsic::x86_sse_cmp_ps:
42170b57cec5SDimitry Andric       handleVectorComparePackedIntrinsic(I);
42180b57cec5SDimitry Andric       break;
42190b57cec5SDimitry Andric 
42200b57cec5SDimitry Andric     case Intrinsic::x86_bmi_bextr_32:
42210b57cec5SDimitry Andric     case Intrinsic::x86_bmi_bextr_64:
42220b57cec5SDimitry Andric     case Intrinsic::x86_bmi_bzhi_32:
42230b57cec5SDimitry Andric     case Intrinsic::x86_bmi_bzhi_64:
42240b57cec5SDimitry Andric     case Intrinsic::x86_bmi_pdep_32:
42250b57cec5SDimitry Andric     case Intrinsic::x86_bmi_pdep_64:
42260b57cec5SDimitry Andric     case Intrinsic::x86_bmi_pext_32:
42270b57cec5SDimitry Andric     case Intrinsic::x86_bmi_pext_64:
42280b57cec5SDimitry Andric       handleBmiIntrinsic(I);
42290b57cec5SDimitry Andric       break;
42300b57cec5SDimitry Andric 
423113138422SDimitry Andric     case Intrinsic::x86_pclmulqdq:
423213138422SDimitry Andric     case Intrinsic::x86_pclmulqdq_256:
423313138422SDimitry Andric     case Intrinsic::x86_pclmulqdq_512:
423413138422SDimitry Andric       handlePclmulIntrinsic(I);
423513138422SDimitry Andric       break;
423613138422SDimitry Andric 
42375ffd83dbSDimitry Andric     case Intrinsic::x86_sse41_round_sd:
423881ad6265SDimitry Andric     case Intrinsic::x86_sse41_round_ss:
423981ad6265SDimitry Andric       handleUnarySdSsIntrinsic(I);
42405ffd83dbSDimitry Andric       break;
42415ffd83dbSDimitry Andric     case Intrinsic::x86_sse2_max_sd:
424281ad6265SDimitry Andric     case Intrinsic::x86_sse_max_ss:
42435ffd83dbSDimitry Andric     case Intrinsic::x86_sse2_min_sd:
424481ad6265SDimitry Andric     case Intrinsic::x86_sse_min_ss:
424581ad6265SDimitry Andric       handleBinarySdSsIntrinsic(I);
42465ffd83dbSDimitry Andric       break;
42475ffd83dbSDimitry Andric 
4248bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestc_pd:
4249bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestc_pd_256:
4250bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestc_ps:
4251bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestc_ps_256:
4252bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestnzc_pd:
4253bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestnzc_pd_256:
4254bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestnzc_ps:
4255bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestnzc_ps_256:
4256bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestz_pd:
4257bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestz_pd_256:
4258bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestz_ps:
4259bdd1243dSDimitry Andric     case Intrinsic::x86_avx_vtestz_ps_256:
4260bdd1243dSDimitry Andric     case Intrinsic::x86_avx_ptestc_256:
4261bdd1243dSDimitry Andric     case Intrinsic::x86_avx_ptestnzc_256:
4262bdd1243dSDimitry Andric     case Intrinsic::x86_avx_ptestz_256:
4263bdd1243dSDimitry Andric     case Intrinsic::x86_sse41_ptestc:
4264bdd1243dSDimitry Andric     case Intrinsic::x86_sse41_ptestnzc:
4265bdd1243dSDimitry Andric     case Intrinsic::x86_sse41_ptestz:
4266bdd1243dSDimitry Andric       handleVtestIntrinsic(I);
4267bdd1243dSDimitry Andric       break;
4268bdd1243dSDimitry Andric 
4269fe6060f1SDimitry Andric     case Intrinsic::fshl:
4270fe6060f1SDimitry Andric     case Intrinsic::fshr:
4271fe6060f1SDimitry Andric       handleFunnelShift(I);
4272fe6060f1SDimitry Andric       break;
4273fe6060f1SDimitry Andric 
42740b57cec5SDimitry Andric     case Intrinsic::is_constant:
42750b57cec5SDimitry Andric       // The result of llvm.is.constant() is always defined.
42760b57cec5SDimitry Andric       setShadow(&I, getCleanShadow(&I));
42770b57cec5SDimitry Andric       setOrigin(&I, getCleanOrigin());
42780b57cec5SDimitry Andric       break;
42790b57cec5SDimitry Andric 
4280*0fca6ea1SDimitry Andric     case Intrinsic::aarch64_neon_st2:
4281*0fca6ea1SDimitry Andric     case Intrinsic::aarch64_neon_st3:
4282*0fca6ea1SDimitry Andric     case Intrinsic::aarch64_neon_st4: {
4283*0fca6ea1SDimitry Andric       handleNEONVectorStoreIntrinsic(I);
4284*0fca6ea1SDimitry Andric       break;
4285*0fca6ea1SDimitry Andric     }
4286*0fca6ea1SDimitry Andric 
42870b57cec5SDimitry Andric     default:
42880b57cec5SDimitry Andric       if (!handleUnknownIntrinsic(I))
42890b57cec5SDimitry Andric         visitInstruction(I);
42900b57cec5SDimitry Andric       break;
42910b57cec5SDimitry Andric     }
42920b57cec5SDimitry Andric   }
42930b57cec5SDimitry Andric 
4294e8d8bef9SDimitry Andric   void visitLibAtomicLoad(CallBase &CB) {
4295e8d8bef9SDimitry Andric     // Since we use getNextNode here, we can't have CB terminate the BB.
4296e8d8bef9SDimitry Andric     assert(isa<CallInst>(CB));
4297e8d8bef9SDimitry Andric 
4298e8d8bef9SDimitry Andric     IRBuilder<> IRB(&CB);
4299e8d8bef9SDimitry Andric     Value *Size = CB.getArgOperand(0);
4300e8d8bef9SDimitry Andric     Value *SrcPtr = CB.getArgOperand(1);
4301e8d8bef9SDimitry Andric     Value *DstPtr = CB.getArgOperand(2);
4302e8d8bef9SDimitry Andric     Value *Ordering = CB.getArgOperand(3);
4303e8d8bef9SDimitry Andric     // Convert the call to have at least Acquire ordering to make sure
4304e8d8bef9SDimitry Andric     // the shadow operations aren't reordered before it.
4305e8d8bef9SDimitry Andric     Value *NewOrdering =
4306e8d8bef9SDimitry Andric         IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering);
4307e8d8bef9SDimitry Andric     CB.setArgOperand(3, NewOrdering);
4308e8d8bef9SDimitry Andric 
4309bdd1243dSDimitry Andric     NextNodeIRBuilder NextIRB(&CB);
4310e8d8bef9SDimitry Andric     Value *SrcShadowPtr, *SrcOriginPtr;
4311e8d8bef9SDimitry Andric     std::tie(SrcShadowPtr, SrcOriginPtr) =
4312e8d8bef9SDimitry Andric         getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(), Align(1),
4313e8d8bef9SDimitry Andric                            /*isStore*/ false);
4314e8d8bef9SDimitry Andric     Value *DstShadowPtr =
4315e8d8bef9SDimitry Andric         getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(), Align(1),
4316e8d8bef9SDimitry Andric                            /*isStore*/ true)
4317e8d8bef9SDimitry Andric             .first;
4318e8d8bef9SDimitry Andric 
4319e8d8bef9SDimitry Andric     NextIRB.CreateMemCpy(DstShadowPtr, Align(1), SrcShadowPtr, Align(1), Size);
4320e8d8bef9SDimitry Andric     if (MS.TrackOrigins) {
4321e8d8bef9SDimitry Andric       Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
4322e8d8bef9SDimitry Andric                                                    kMinOriginAlignment);
4323e8d8bef9SDimitry Andric       Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
4324e8d8bef9SDimitry Andric       NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
4325e8d8bef9SDimitry Andric     }
4326e8d8bef9SDimitry Andric   }
4327e8d8bef9SDimitry Andric 
4328e8d8bef9SDimitry Andric   void visitLibAtomicStore(CallBase &CB) {
4329e8d8bef9SDimitry Andric     IRBuilder<> IRB(&CB);
4330e8d8bef9SDimitry Andric     Value *Size = CB.getArgOperand(0);
4331e8d8bef9SDimitry Andric     Value *DstPtr = CB.getArgOperand(2);
4332e8d8bef9SDimitry Andric     Value *Ordering = CB.getArgOperand(3);
4333e8d8bef9SDimitry Andric     // Convert the call to have at least Release ordering to make sure
4334e8d8bef9SDimitry Andric     // the shadow operations aren't reordered after it.
4335e8d8bef9SDimitry Andric     Value *NewOrdering =
4336e8d8bef9SDimitry Andric         IRB.CreateExtractElement(makeAddReleaseOrderingTable(IRB), Ordering);
4337e8d8bef9SDimitry Andric     CB.setArgOperand(3, NewOrdering);
4338e8d8bef9SDimitry Andric 
4339e8d8bef9SDimitry Andric     Value *DstShadowPtr =
4340e8d8bef9SDimitry Andric         getShadowOriginPtr(DstPtr, IRB, IRB.getInt8Ty(), Align(1),
4341e8d8bef9SDimitry Andric                            /*isStore*/ true)
4342e8d8bef9SDimitry Andric             .first;
4343e8d8bef9SDimitry Andric 
4344e8d8bef9SDimitry Andric     // Atomic store always paints clean shadow/origin. See file header.
4345e8d8bef9SDimitry Andric     IRB.CreateMemSet(DstShadowPtr, getCleanShadow(IRB.getInt8Ty()), Size,
4346e8d8bef9SDimitry Andric                      Align(1));
4347e8d8bef9SDimitry Andric   }
4348e8d8bef9SDimitry Andric 
43495ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB) {
435081ad6265SDimitry Andric     assert(!CB.getMetadata(LLVMContext::MD_nosanitize));
43515ffd83dbSDimitry Andric     if (CB.isInlineAsm()) {
43520b57cec5SDimitry Andric       // For inline asm (either a call to asm function, or callbr instruction),
43530b57cec5SDimitry Andric       // do the usual thing: check argument shadow and mark all outputs as
43540b57cec5SDimitry Andric       // clean. Note that any side effects of the inline asm that are not
43550b57cec5SDimitry Andric       // immediately visible in its constraints are not handled.
4356*0fca6ea1SDimitry Andric       if (ClHandleAsmConservative)
43575ffd83dbSDimitry Andric         visitAsmInstruction(CB);
43580b57cec5SDimitry Andric       else
43595ffd83dbSDimitry Andric         visitInstruction(CB);
43600b57cec5SDimitry Andric       return;
43610b57cec5SDimitry Andric     }
4362e8d8bef9SDimitry Andric     LibFunc LF;
4363e8d8bef9SDimitry Andric     if (TLI->getLibFunc(CB, LF)) {
4364e8d8bef9SDimitry Andric       // libatomic.a functions need to have special handling because there isn't
4365e8d8bef9SDimitry Andric       // a good way to intercept them or compile the library with
4366e8d8bef9SDimitry Andric       // instrumentation.
4367e8d8bef9SDimitry Andric       switch (LF) {
4368e8d8bef9SDimitry Andric       case LibFunc_atomic_load:
4369e8d8bef9SDimitry Andric         if (!isa<CallInst>(CB)) {
4370e8d8bef9SDimitry Andric           llvm::errs() << "MSAN -- cannot instrument invoke of libatomic load."
4371e8d8bef9SDimitry Andric                           "Ignoring!\n";
4372e8d8bef9SDimitry Andric           break;
4373e8d8bef9SDimitry Andric         }
4374e8d8bef9SDimitry Andric         visitLibAtomicLoad(CB);
4375e8d8bef9SDimitry Andric         return;
4376e8d8bef9SDimitry Andric       case LibFunc_atomic_store:
4377e8d8bef9SDimitry Andric         visitLibAtomicStore(CB);
4378e8d8bef9SDimitry Andric         return;
4379e8d8bef9SDimitry Andric       default:
4380e8d8bef9SDimitry Andric         break;
4381e8d8bef9SDimitry Andric       }
4382e8d8bef9SDimitry Andric     }
4383e8d8bef9SDimitry Andric 
43845ffd83dbSDimitry Andric     if (auto *Call = dyn_cast<CallInst>(&CB)) {
43855ffd83dbSDimitry Andric       assert(!isa<IntrinsicInst>(Call) && "intrinsics are handled elsewhere");
43860b57cec5SDimitry Andric 
43870b57cec5SDimitry Andric       // We are going to insert code that relies on the fact that the callee
43880b57cec5SDimitry Andric       // will become a non-readonly function after it is instrumented by us. To
43890b57cec5SDimitry Andric       // prevent this code from being optimized out, mark that function
43900b57cec5SDimitry Andric       // non-readonly in advance.
4391bdd1243dSDimitry Andric       // TODO: We can likely do better than dropping memory() completely here.
439204eeddc0SDimitry Andric       AttributeMask B;
4393bdd1243dSDimitry Andric       B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
4394e8d8bef9SDimitry Andric 
4395349cc55cSDimitry Andric       Call->removeFnAttrs(B);
4396e8d8bef9SDimitry Andric       if (Function *Func = Call->getCalledFunction()) {
4397349cc55cSDimitry Andric         Func->removeFnAttrs(B);
43980b57cec5SDimitry Andric       }
43990b57cec5SDimitry Andric 
44000b57cec5SDimitry Andric       maybeMarkSanitizerLibraryCallNoBuiltin(Call, TLI);
44010b57cec5SDimitry Andric     }
44025ffd83dbSDimitry Andric     IRBuilder<> IRB(&CB);
440304eeddc0SDimitry Andric     bool MayCheckCall = MS.EagerChecks;
4404e8d8bef9SDimitry Andric     if (Function *Func = CB.getCalledFunction()) {
4405e8d8bef9SDimitry Andric       // __sanitizer_unaligned_{load,store} functions may be called by users
4406e8d8bef9SDimitry Andric       // and always expects shadows in the TLS. So don't check them.
44075f757f3fSDimitry Andric       MayCheckCall &= !Func->getName().starts_with("__sanitizer_unaligned_");
4408e8d8bef9SDimitry Andric     }
44090b57cec5SDimitry Andric 
44100b57cec5SDimitry Andric     unsigned ArgOffset = 0;
44115ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "  CallSite: " << CB << "\n");
4412bdd1243dSDimitry Andric     for (const auto &[i, A] : llvm::enumerate(CB.args())) {
44130b57cec5SDimitry Andric       if (!A->getType()->isSized()) {
44145ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "Arg " << i << " is not sized: " << CB << "\n");
44150b57cec5SDimitry Andric         continue;
44160b57cec5SDimitry Andric       }
4417*0fca6ea1SDimitry Andric 
4418*0fca6ea1SDimitry Andric       if (A->getType()->isScalableTy()) {
4419*0fca6ea1SDimitry Andric         LLVM_DEBUG(dbgs() << "Arg  " << i << " is vscale: " << CB << "\n");
4420*0fca6ea1SDimitry Andric         // Handle as noundef, but don't reserve tls slots.
4421*0fca6ea1SDimitry Andric         insertShadowCheck(A, &CB);
4422*0fca6ea1SDimitry Andric         continue;
4423*0fca6ea1SDimitry Andric       }
4424*0fca6ea1SDimitry Andric 
44250b57cec5SDimitry Andric       unsigned Size = 0;
4426*0fca6ea1SDimitry Andric       const DataLayout &DL = F.getDataLayout();
44275ffd83dbSDimitry Andric 
44285ffd83dbSDimitry Andric       bool ByVal = CB.paramHasAttr(i, Attribute::ByVal);
44295ffd83dbSDimitry Andric       bool NoUndef = CB.paramHasAttr(i, Attribute::NoUndef);
4430e8d8bef9SDimitry Andric       bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
44315ffd83dbSDimitry Andric 
44325ffd83dbSDimitry Andric       if (EagerCheck) {
44335ffd83dbSDimitry Andric         insertShadowCheck(A, &CB);
4434349cc55cSDimitry Andric         Size = DL.getTypeAllocSize(A->getType());
4435349cc55cSDimitry Andric       } else {
443604eeddc0SDimitry Andric         Value *Store = nullptr;
443704eeddc0SDimitry Andric         // Compute the Shadow for arg even if it is ByVal, because
443804eeddc0SDimitry Andric         // in that case getShadow() will copy the actual arg shadow to
443904eeddc0SDimitry Andric         // __msan_param_tls.
444004eeddc0SDimitry Andric         Value *ArgShadow = getShadow(A);
44415f757f3fSDimitry Andric         Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
444204eeddc0SDimitry Andric         LLVM_DEBUG(dbgs() << "  Arg#" << i << ": " << *A
444304eeddc0SDimitry Andric                           << " Shadow: " << *ArgShadow << "\n");
44445ffd83dbSDimitry Andric         if (ByVal) {
44455ffd83dbSDimitry Andric           // ByVal requires some special handling as it's too big for a single
44465ffd83dbSDimitry Andric           // load
44470b57cec5SDimitry Andric           assert(A->getType()->isPointerTy() &&
44480b57cec5SDimitry Andric                  "ByVal argument is not a pointer!");
44495ffd83dbSDimitry Andric           Size = DL.getTypeAllocSize(CB.getParamByValType(i));
4450349cc55cSDimitry Andric           if (ArgOffset + Size > kParamTLSSize)
4451349cc55cSDimitry Andric             break;
44525ffd83dbSDimitry Andric           const MaybeAlign ParamAlignment(CB.getParamAlign(i));
4453bdd1243dSDimitry Andric           MaybeAlign Alignment = std::nullopt;
4454480093f4SDimitry Andric           if (ParamAlignment)
4455480093f4SDimitry Andric             Alignment = std::min(*ParamAlignment, kShadowTLSAlignment);
44561fd87a68SDimitry Andric           Value *AShadowPtr, *AOriginPtr;
44571fd87a68SDimitry Andric           std::tie(AShadowPtr, AOriginPtr) =
44580b57cec5SDimitry Andric               getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), Alignment,
44591fd87a68SDimitry Andric                                  /*isStore*/ false);
446004eeddc0SDimitry Andric           if (!PropagateShadow) {
446104eeddc0SDimitry Andric             Store = IRB.CreateMemSet(ArgShadowBase,
446204eeddc0SDimitry Andric                                      Constant::getNullValue(IRB.getInt8Ty()),
446304eeddc0SDimitry Andric                                      Size, Alignment);
446404eeddc0SDimitry Andric           } else {
44650b57cec5SDimitry Andric             Store = IRB.CreateMemCpy(ArgShadowBase, Alignment, AShadowPtr,
44660b57cec5SDimitry Andric                                      Alignment, Size);
44671fd87a68SDimitry Andric             if (MS.TrackOrigins) {
44685f757f3fSDimitry Andric               Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
44691fd87a68SDimitry Andric               // FIXME: OriginSize should be:
44701fd87a68SDimitry Andric               // alignTo(A % kMinOriginAlignment + Size, kMinOriginAlignment)
44711fd87a68SDimitry Andric               unsigned OriginSize = alignTo(Size, kMinOriginAlignment);
44721fd87a68SDimitry Andric               IRB.CreateMemCpy(
44731fd87a68SDimitry Andric                   ArgOriginBase,
44741fd87a68SDimitry Andric                   /* by origin_tls[ArgOffset] */ kMinOriginAlignment,
44751fd87a68SDimitry Andric                   AOriginPtr,
44761fd87a68SDimitry Andric                   /* by getShadowOriginPtr */ kMinOriginAlignment, OriginSize);
44771fd87a68SDimitry Andric             }
447804eeddc0SDimitry Andric           }
44790b57cec5SDimitry Andric         } else {
4480349cc55cSDimitry Andric           // Any other parameters mean we need bit-grained tracking of uninit
4481349cc55cSDimitry Andric           // data
44820b57cec5SDimitry Andric           Size = DL.getTypeAllocSize(A->getType());
4483349cc55cSDimitry Andric           if (ArgOffset + Size > kParamTLSSize)
4484349cc55cSDimitry Andric             break;
44850b57cec5SDimitry Andric           Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase,
44865ffd83dbSDimitry Andric                                          kShadowTLSAlignment);
44870b57cec5SDimitry Andric           Constant *Cst = dyn_cast<Constant>(ArgShadow);
44881fd87a68SDimitry Andric           if (MS.TrackOrigins && !(Cst && Cst->isNullValue())) {
44890b57cec5SDimitry Andric             IRB.CreateStore(getOrigin(A),
44905f757f3fSDimitry Andric                             getOriginPtrForArgument(IRB, ArgOffset));
44911fd87a68SDimitry Andric           }
44921fd87a68SDimitry Andric         }
44930b57cec5SDimitry Andric         (void)Store;
4494349cc55cSDimitry Andric         assert(Store != nullptr);
44950b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "  Param:" << *Store << "\n");
4496349cc55cSDimitry Andric       }
4497349cc55cSDimitry Andric       assert(Size != 0);
4498e8d8bef9SDimitry Andric       ArgOffset += alignTo(Size, kShadowTLSAlignment);
44990b57cec5SDimitry Andric     }
45000b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  done with call args\n");
45010b57cec5SDimitry Andric 
45025ffd83dbSDimitry Andric     FunctionType *FT = CB.getFunctionType();
45030b57cec5SDimitry Andric     if (FT->isVarArg()) {
45045ffd83dbSDimitry Andric       VAHelper->visitCallBase(CB, IRB);
45050b57cec5SDimitry Andric     }
45060b57cec5SDimitry Andric 
45070b57cec5SDimitry Andric     // Now, get the shadow for the RetVal.
45085ffd83dbSDimitry Andric     if (!CB.getType()->isSized())
45095ffd83dbSDimitry Andric       return;
45100b57cec5SDimitry Andric     // Don't emit the epilogue for musttail call returns.
45115ffd83dbSDimitry Andric     if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
45125ffd83dbSDimitry Andric       return;
45135ffd83dbSDimitry Andric 
4514e8d8bef9SDimitry Andric     if (MayCheckCall && CB.hasRetAttr(Attribute::NoUndef)) {
45155ffd83dbSDimitry Andric       setShadow(&CB, getCleanShadow(&CB));
45165ffd83dbSDimitry Andric       setOrigin(&CB, getCleanOrigin());
45175ffd83dbSDimitry Andric       return;
45185ffd83dbSDimitry Andric     }
45195ffd83dbSDimitry Andric 
45205ffd83dbSDimitry Andric     IRBuilder<> IRBBefore(&CB);
45210b57cec5SDimitry Andric     // Until we have full dynamic coverage, make sure the retval shadow is 0.
45225f757f3fSDimitry Andric     Value *Base = getShadowPtrForRetval(IRBBefore);
45235ffd83dbSDimitry Andric     IRBBefore.CreateAlignedStore(getCleanShadow(&CB), Base,
45245ffd83dbSDimitry Andric                                  kShadowTLSAlignment);
45250b57cec5SDimitry Andric     BasicBlock::iterator NextInsn;
45265ffd83dbSDimitry Andric     if (isa<CallInst>(CB)) {
45275ffd83dbSDimitry Andric       NextInsn = ++CB.getIterator();
45285ffd83dbSDimitry Andric       assert(NextInsn != CB.getParent()->end());
45290b57cec5SDimitry Andric     } else {
45305ffd83dbSDimitry Andric       BasicBlock *NormalDest = cast<InvokeInst>(CB).getNormalDest();
45310b57cec5SDimitry Andric       if (!NormalDest->getSinglePredecessor()) {
45320b57cec5SDimitry Andric         // FIXME: this case is tricky, so we are just conservative here.
45330b57cec5SDimitry Andric         // Perhaps we need to split the edge between this BB and NormalDest,
45340b57cec5SDimitry Andric         // but a naive attempt to use SplitEdge leads to a crash.
45355ffd83dbSDimitry Andric         setShadow(&CB, getCleanShadow(&CB));
45365ffd83dbSDimitry Andric         setOrigin(&CB, getCleanOrigin());
45370b57cec5SDimitry Andric         return;
45380b57cec5SDimitry Andric       }
4539bdd1243dSDimitry Andric       // FIXME: NextInsn is likely in a basic block that has not been visited
4540bdd1243dSDimitry Andric       // yet. Anything inserted there will be instrumented by MSan later!
45410b57cec5SDimitry Andric       NextInsn = NormalDest->getFirstInsertionPt();
45420b57cec5SDimitry Andric       assert(NextInsn != NormalDest->end() &&
45430b57cec5SDimitry Andric              "Could not find insertion point for retval shadow load");
45440b57cec5SDimitry Andric     }
45450b57cec5SDimitry Andric     IRBuilder<> IRBAfter(&*NextInsn);
45460b57cec5SDimitry Andric     Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
45475f757f3fSDimitry Andric         getShadowTy(&CB), getShadowPtrForRetval(IRBAfter),
45485ffd83dbSDimitry Andric         kShadowTLSAlignment, "_msret");
45495ffd83dbSDimitry Andric     setShadow(&CB, RetvalShadow);
45500b57cec5SDimitry Andric     if (MS.TrackOrigins)
45515ffd83dbSDimitry Andric       setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy,
45525f757f3fSDimitry Andric                                          getOriginPtrForRetval()));
45530b57cec5SDimitry Andric   }
45540b57cec5SDimitry Andric 
45550b57cec5SDimitry Andric   bool isAMustTailRetVal(Value *RetVal) {
45560b57cec5SDimitry Andric     if (auto *I = dyn_cast<BitCastInst>(RetVal)) {
45570b57cec5SDimitry Andric       RetVal = I->getOperand(0);
45580b57cec5SDimitry Andric     }
45590b57cec5SDimitry Andric     if (auto *I = dyn_cast<CallInst>(RetVal)) {
45600b57cec5SDimitry Andric       return I->isMustTailCall();
45610b57cec5SDimitry Andric     }
45620b57cec5SDimitry Andric     return false;
45630b57cec5SDimitry Andric   }
45640b57cec5SDimitry Andric 
45650b57cec5SDimitry Andric   void visitReturnInst(ReturnInst &I) {
45660b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
45670b57cec5SDimitry Andric     Value *RetVal = I.getReturnValue();
4568bdd1243dSDimitry Andric     if (!RetVal)
4569bdd1243dSDimitry Andric       return;
45700b57cec5SDimitry Andric     // Don't emit the epilogue for musttail call returns.
4571bdd1243dSDimitry Andric     if (isAMustTailRetVal(RetVal))
4572bdd1243dSDimitry Andric       return;
45735f757f3fSDimitry Andric     Value *ShadowPtr = getShadowPtrForRetval(IRB);
4574bdd1243dSDimitry Andric     bool HasNoUndef = F.hasRetAttribute(Attribute::NoUndef);
457504eeddc0SDimitry Andric     bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
45765ffd83dbSDimitry Andric     // FIXME: Consider using SpecialCaseList to specify a list of functions that
45775ffd83dbSDimitry Andric     // must always return fully initialized values. For now, we hardcode "main".
457804eeddc0SDimitry Andric     bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (F.getName() == "main");
45795ffd83dbSDimitry Andric 
45800b57cec5SDimitry Andric     Value *Shadow = getShadow(RetVal);
45815ffd83dbSDimitry Andric     bool StoreOrigin = true;
45825ffd83dbSDimitry Andric     if (EagerCheck) {
45835ffd83dbSDimitry Andric       insertShadowCheck(RetVal, &I);
45845ffd83dbSDimitry Andric       Shadow = getCleanShadow(RetVal);
45855ffd83dbSDimitry Andric       StoreOrigin = false;
45865ffd83dbSDimitry Andric     }
45875ffd83dbSDimitry Andric 
45885ffd83dbSDimitry Andric     // The caller may still expect information passed over TLS if we pass our
45895ffd83dbSDimitry Andric     // check
45905ffd83dbSDimitry Andric     if (StoreShadow) {
45915ffd83dbSDimitry Andric       IRB.CreateAlignedStore(Shadow, ShadowPtr, kShadowTLSAlignment);
45925ffd83dbSDimitry Andric       if (MS.TrackOrigins && StoreOrigin)
45935f757f3fSDimitry Andric         IRB.CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
45940b57cec5SDimitry Andric     }
45950b57cec5SDimitry Andric   }
45960b57cec5SDimitry Andric 
45970b57cec5SDimitry Andric   void visitPHINode(PHINode &I) {
45980b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
45990b57cec5SDimitry Andric     if (!PropagateShadow) {
46000b57cec5SDimitry Andric       setShadow(&I, getCleanShadow(&I));
46010b57cec5SDimitry Andric       setOrigin(&I, getCleanOrigin());
46020b57cec5SDimitry Andric       return;
46030b57cec5SDimitry Andric     }
46040b57cec5SDimitry Andric 
46050b57cec5SDimitry Andric     ShadowPHINodes.push_back(&I);
46060b57cec5SDimitry Andric     setShadow(&I, IRB.CreatePHI(getShadowTy(&I), I.getNumIncomingValues(),
46070b57cec5SDimitry Andric                                 "_msphi_s"));
46080b57cec5SDimitry Andric     if (MS.TrackOrigins)
4609bdd1243dSDimitry Andric       setOrigin(
4610bdd1243dSDimitry Andric           &I, IRB.CreatePHI(MS.OriginTy, I.getNumIncomingValues(), "_msphi_o"));
4611bdd1243dSDimitry Andric   }
4612bdd1243dSDimitry Andric 
4613bdd1243dSDimitry Andric   Value *getLocalVarIdptr(AllocaInst &I) {
4614bdd1243dSDimitry Andric     ConstantInt *IntConst =
4615bdd1243dSDimitry Andric         ConstantInt::get(Type::getInt32Ty((*F.getParent()).getContext()), 0);
4616bdd1243dSDimitry Andric     return new GlobalVariable(*F.getParent(), IntConst->getType(),
4617bdd1243dSDimitry Andric                               /*isConstant=*/false, GlobalValue::PrivateLinkage,
4618bdd1243dSDimitry Andric                               IntConst);
46190b57cec5SDimitry Andric   }
46200b57cec5SDimitry Andric 
46210b57cec5SDimitry Andric   Value *getLocalVarDescription(AllocaInst &I) {
4622bdd1243dSDimitry Andric     return createPrivateConstGlobalForString(*F.getParent(), I.getName());
46230b57cec5SDimitry Andric   }
46240b57cec5SDimitry Andric 
46250b57cec5SDimitry Andric   void poisonAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {
46260b57cec5SDimitry Andric     if (PoisonStack && ClPoisonStackWithCall) {
46275f757f3fSDimitry Andric       IRB.CreateCall(MS.MsanPoisonStackFn, {&I, Len});
46280b57cec5SDimitry Andric     } else {
46290b57cec5SDimitry Andric       Value *ShadowBase, *OriginBase;
4630480093f4SDimitry Andric       std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
46315ffd83dbSDimitry Andric           &I, IRB, IRB.getInt8Ty(), Align(1), /*isStore*/ true);
46320b57cec5SDimitry Andric 
46330b57cec5SDimitry Andric       Value *PoisonValue = IRB.getInt8(PoisonStack ? ClPoisonStackPattern : 0);
46340eae32dcSDimitry Andric       IRB.CreateMemSet(ShadowBase, PoisonValue, Len, I.getAlign());
46350b57cec5SDimitry Andric     }
46360b57cec5SDimitry Andric 
46370b57cec5SDimitry Andric     if (PoisonStack && MS.TrackOrigins) {
4638bdd1243dSDimitry Andric       Value *Idptr = getLocalVarIdptr(I);
4639bdd1243dSDimitry Andric       if (ClPrintStackNames) {
46400b57cec5SDimitry Andric         Value *Descr = getLocalVarDescription(I);
4641bdd1243dSDimitry Andric         IRB.CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
46425f757f3fSDimitry Andric                        {&I, Len, Idptr, Descr});
4643bdd1243dSDimitry Andric       } else {
46445f757f3fSDimitry Andric         IRB.CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
4645bdd1243dSDimitry Andric       }
46460b57cec5SDimitry Andric     }
46470b57cec5SDimitry Andric   }
46480b57cec5SDimitry Andric 
46490b57cec5SDimitry Andric   void poisonAllocaKmsan(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {
46500b57cec5SDimitry Andric     Value *Descr = getLocalVarDescription(I);
46510b57cec5SDimitry Andric     if (PoisonStack) {
46525f757f3fSDimitry Andric       IRB.CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
46530b57cec5SDimitry Andric     } else {
46545f757f3fSDimitry Andric       IRB.CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
46550b57cec5SDimitry Andric     }
46560b57cec5SDimitry Andric   }
46570b57cec5SDimitry Andric 
46580b57cec5SDimitry Andric   void instrumentAlloca(AllocaInst &I, Instruction *InsPoint = nullptr) {
46590b57cec5SDimitry Andric     if (!InsPoint)
46600b57cec5SDimitry Andric       InsPoint = &I;
4661bdd1243dSDimitry Andric     NextNodeIRBuilder IRB(InsPoint);
4662*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
4663*0fca6ea1SDimitry Andric     TypeSize TS = DL.getTypeAllocSize(I.getAllocatedType());
4664*0fca6ea1SDimitry Andric     Value *Len = IRB.CreateTypeSize(MS.IntptrTy, TS);
46650b57cec5SDimitry Andric     if (I.isArrayAllocation())
4666bdd1243dSDimitry Andric       Len = IRB.CreateMul(Len,
4667bdd1243dSDimitry Andric                           IRB.CreateZExtOrTrunc(I.getArraySize(), MS.IntptrTy));
46680b57cec5SDimitry Andric 
46690b57cec5SDimitry Andric     if (MS.CompileKernel)
46700b57cec5SDimitry Andric       poisonAllocaKmsan(I, IRB, Len);
46710b57cec5SDimitry Andric     else
46720b57cec5SDimitry Andric       poisonAllocaUserspace(I, IRB, Len);
46730b57cec5SDimitry Andric   }
46740b57cec5SDimitry Andric 
46750b57cec5SDimitry Andric   void visitAllocaInst(AllocaInst &I) {
46760b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
46770b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
46780b57cec5SDimitry Andric     // We'll get to this alloca later unless it's poisoned at the corresponding
46790b57cec5SDimitry Andric     // llvm.lifetime.start.
46800b57cec5SDimitry Andric     AllocaSet.insert(&I);
46810b57cec5SDimitry Andric   }
46820b57cec5SDimitry Andric 
46830b57cec5SDimitry Andric   void visitSelectInst(SelectInst &I) {
46840b57cec5SDimitry Andric     // a = select b, c, d
46850b57cec5SDimitry Andric     Value *B = I.getCondition();
46860b57cec5SDimitry Andric     Value *C = I.getTrueValue();
46870b57cec5SDimitry Andric     Value *D = I.getFalseValue();
4688*0fca6ea1SDimitry Andric 
4689*0fca6ea1SDimitry Andric     handleSelectLikeInst(I, B, C, D);
4690*0fca6ea1SDimitry Andric   }
4691*0fca6ea1SDimitry Andric 
4692*0fca6ea1SDimitry Andric   void handleSelectLikeInst(Instruction &I, Value *B, Value *C, Value *D) {
4693*0fca6ea1SDimitry Andric     IRBuilder<> IRB(&I);
4694*0fca6ea1SDimitry Andric 
46950b57cec5SDimitry Andric     Value *Sb = getShadow(B);
46960b57cec5SDimitry Andric     Value *Sc = getShadow(C);
46970b57cec5SDimitry Andric     Value *Sd = getShadow(D);
46980b57cec5SDimitry Andric 
4699*0fca6ea1SDimitry Andric     Value *Ob = MS.TrackOrigins ? getOrigin(B) : nullptr;
4700*0fca6ea1SDimitry Andric     Value *Oc = MS.TrackOrigins ? getOrigin(C) : nullptr;
4701*0fca6ea1SDimitry Andric     Value *Od = MS.TrackOrigins ? getOrigin(D) : nullptr;
4702*0fca6ea1SDimitry Andric 
47030b57cec5SDimitry Andric     // Result shadow if condition shadow is 0.
47040b57cec5SDimitry Andric     Value *Sa0 = IRB.CreateSelect(B, Sc, Sd);
47050b57cec5SDimitry Andric     Value *Sa1;
47060b57cec5SDimitry Andric     if (I.getType()->isAggregateType()) {
47070b57cec5SDimitry Andric       // To avoid "sign extending" i1 to an arbitrary aggregate type, we just do
47080b57cec5SDimitry Andric       // an extra "select". This results in much more compact IR.
47090b57cec5SDimitry Andric       // Sa = select Sb, poisoned, (select b, Sc, Sd)
47100b57cec5SDimitry Andric       Sa1 = getPoisonedShadow(getShadowTy(I.getType()));
47110b57cec5SDimitry Andric     } else {
47120b57cec5SDimitry Andric       // Sa = select Sb, [ (c^d) | Sc | Sd ], [ b ? Sc : Sd ]
47130b57cec5SDimitry Andric       // If Sb (condition is poisoned), look for bits in c and d that are equal
47140b57cec5SDimitry Andric       // and both unpoisoned.
47150b57cec5SDimitry Andric       // If !Sb (condition is unpoisoned), simply pick one of Sc and Sd.
47160b57cec5SDimitry Andric 
47170b57cec5SDimitry Andric       // Cast arguments to shadow-compatible type.
47180b57cec5SDimitry Andric       C = CreateAppToShadowCast(IRB, C);
47190b57cec5SDimitry Andric       D = CreateAppToShadowCast(IRB, D);
47200b57cec5SDimitry Andric 
47210b57cec5SDimitry Andric       // Result shadow if condition shadow is 1.
47220b57cec5SDimitry Andric       Sa1 = IRB.CreateOr({IRB.CreateXor(C, D), Sc, Sd});
47230b57cec5SDimitry Andric     }
47240b57cec5SDimitry Andric     Value *Sa = IRB.CreateSelect(Sb, Sa1, Sa0, "_msprop_select");
47250b57cec5SDimitry Andric     setShadow(&I, Sa);
47260b57cec5SDimitry Andric     if (MS.TrackOrigins) {
47270b57cec5SDimitry Andric       // Origins are always i32, so any vector conditions must be flattened.
47280b57cec5SDimitry Andric       // FIXME: consider tracking vector origins for app vectors?
47290b57cec5SDimitry Andric       if (B->getType()->isVectorTy()) {
473006c3fb27SDimitry Andric         B = convertToBool(B, IRB);
473106c3fb27SDimitry Andric         Sb = convertToBool(Sb, IRB);
47320b57cec5SDimitry Andric       }
47330b57cec5SDimitry Andric       // a = select b, c, d
47340b57cec5SDimitry Andric       // Oa = Sb ? Ob : (b ? Oc : Od)
4735*0fca6ea1SDimitry Andric       setOrigin(&I, IRB.CreateSelect(Sb, Ob, IRB.CreateSelect(B, Oc, Od)));
47360b57cec5SDimitry Andric     }
47370b57cec5SDimitry Andric   }
47380b57cec5SDimitry Andric 
47390b57cec5SDimitry Andric   void visitLandingPadInst(LandingPadInst &I) {
47400b57cec5SDimitry Andric     // Do nothing.
47410b57cec5SDimitry Andric     // See https://github.com/google/sanitizers/issues/504
47420b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
47430b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
47440b57cec5SDimitry Andric   }
47450b57cec5SDimitry Andric 
47460b57cec5SDimitry Andric   void visitCatchSwitchInst(CatchSwitchInst &I) {
47470b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
47480b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
47490b57cec5SDimitry Andric   }
47500b57cec5SDimitry Andric 
47510b57cec5SDimitry Andric   void visitFuncletPadInst(FuncletPadInst &I) {
47520b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
47530b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
47540b57cec5SDimitry Andric   }
47550b57cec5SDimitry Andric 
4756bdd1243dSDimitry Andric   void visitGetElementPtrInst(GetElementPtrInst &I) { handleShadowOr(I); }
47570b57cec5SDimitry Andric 
47580b57cec5SDimitry Andric   void visitExtractValueInst(ExtractValueInst &I) {
47590b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
47600b57cec5SDimitry Andric     Value *Agg = I.getAggregateOperand();
47610b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "ExtractValue:  " << I << "\n");
47620b57cec5SDimitry Andric     Value *AggShadow = getShadow(Agg);
47630b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "   AggShadow:  " << *AggShadow << "\n");
47640b57cec5SDimitry Andric     Value *ResShadow = IRB.CreateExtractValue(AggShadow, I.getIndices());
47650b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "   ResShadow:  " << *ResShadow << "\n");
47660b57cec5SDimitry Andric     setShadow(&I, ResShadow);
47670b57cec5SDimitry Andric     setOriginForNaryOp(I);
47680b57cec5SDimitry Andric   }
47690b57cec5SDimitry Andric 
47700b57cec5SDimitry Andric   void visitInsertValueInst(InsertValueInst &I) {
47710b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
47720b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "InsertValue:  " << I << "\n");
47730b57cec5SDimitry Andric     Value *AggShadow = getShadow(I.getAggregateOperand());
47740b57cec5SDimitry Andric     Value *InsShadow = getShadow(I.getInsertedValueOperand());
47750b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "   AggShadow:  " << *AggShadow << "\n");
47760b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "   InsShadow:  " << *InsShadow << "\n");
47770b57cec5SDimitry Andric     Value *Res = IRB.CreateInsertValue(AggShadow, InsShadow, I.getIndices());
47780b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "   Res:        " << *Res << "\n");
47790b57cec5SDimitry Andric     setShadow(&I, Res);
47800b57cec5SDimitry Andric     setOriginForNaryOp(I);
47810b57cec5SDimitry Andric   }
47820b57cec5SDimitry Andric 
47830b57cec5SDimitry Andric   void dumpInst(Instruction &I) {
47840b57cec5SDimitry Andric     if (CallInst *CI = dyn_cast<CallInst>(&I)) {
47850b57cec5SDimitry Andric       errs() << "ZZZ call " << CI->getCalledFunction()->getName() << "\n";
47860b57cec5SDimitry Andric     } else {
47870b57cec5SDimitry Andric       errs() << "ZZZ " << I.getOpcodeName() << "\n";
47880b57cec5SDimitry Andric     }
47890b57cec5SDimitry Andric     errs() << "QQQ " << I << "\n";
47900b57cec5SDimitry Andric   }
47910b57cec5SDimitry Andric 
47920b57cec5SDimitry Andric   void visitResumeInst(ResumeInst &I) {
47930b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Resume: " << I << "\n");
47940b57cec5SDimitry Andric     // Nothing to do here.
47950b57cec5SDimitry Andric   }
47960b57cec5SDimitry Andric 
47970b57cec5SDimitry Andric   void visitCleanupReturnInst(CleanupReturnInst &CRI) {
47980b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "CleanupReturn: " << CRI << "\n");
47990b57cec5SDimitry Andric     // Nothing to do here.
48000b57cec5SDimitry Andric   }
48010b57cec5SDimitry Andric 
48020b57cec5SDimitry Andric   void visitCatchReturnInst(CatchReturnInst &CRI) {
48030b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "CatchReturn: " << CRI << "\n");
48040b57cec5SDimitry Andric     // Nothing to do here.
48050b57cec5SDimitry Andric   }
48060b57cec5SDimitry Andric 
480781ad6265SDimitry Andric   void instrumentAsmArgument(Value *Operand, Type *ElemTy, Instruction &I,
480881ad6265SDimitry Andric                              IRBuilder<> &IRB, const DataLayout &DL,
480981ad6265SDimitry Andric                              bool isOutput) {
48100b57cec5SDimitry Andric     // For each assembly argument, we check its value for being initialized.
48110b57cec5SDimitry Andric     // If the argument is a pointer, we assume it points to a single element
48120b57cec5SDimitry Andric     // of the corresponding type (or to a 8-byte word, if the type is unsized).
48130b57cec5SDimitry Andric     // Each such pointer is instrumented with a call to the runtime library.
48140b57cec5SDimitry Andric     Type *OpType = Operand->getType();
48150b57cec5SDimitry Andric     // Check the operand value itself.
48160b57cec5SDimitry Andric     insertShadowCheck(Operand, &I);
48170b57cec5SDimitry Andric     if (!OpType->isPointerTy() || !isOutput) {
48180b57cec5SDimitry Andric       assert(!isOutput);
48190b57cec5SDimitry Andric       return;
48200b57cec5SDimitry Andric     }
482181ad6265SDimitry Andric     if (!ElemTy->isSized())
48220b57cec5SDimitry Andric       return;
4823*0fca6ea1SDimitry Andric     auto Size = DL.getTypeStoreSize(ElemTy);
4824*0fca6ea1SDimitry Andric     Value *SizeVal = IRB.CreateTypeSize(MS.IntptrTy, Size);
48257a6dacacSDimitry Andric     if (MS.CompileKernel) {
48265f757f3fSDimitry Andric       IRB.CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
48277a6dacacSDimitry Andric     } else {
48287a6dacacSDimitry Andric       // ElemTy, derived from elementtype(), does not encode the alignment of
48297a6dacacSDimitry Andric       // the pointer. Conservatively assume that the shadow memory is unaligned.
4830*0fca6ea1SDimitry Andric       // When Size is large, avoid StoreInst as it would expand to many
4831*0fca6ea1SDimitry Andric       // instructions.
48327a6dacacSDimitry Andric       auto [ShadowPtr, _] =
48337a6dacacSDimitry Andric           getShadowOriginPtrUserspace(Operand, IRB, IRB.getInt8Ty(), Align(1));
4834*0fca6ea1SDimitry Andric       if (Size <= 32)
48357a6dacacSDimitry Andric         IRB.CreateAlignedStore(getCleanShadow(ElemTy), ShadowPtr, Align(1));
4836*0fca6ea1SDimitry Andric       else
4837*0fca6ea1SDimitry Andric         IRB.CreateMemSet(ShadowPtr, ConstantInt::getNullValue(IRB.getInt8Ty()),
4838*0fca6ea1SDimitry Andric                          SizeVal, Align(1));
48397a6dacacSDimitry Andric     }
48400b57cec5SDimitry Andric   }
48410b57cec5SDimitry Andric 
48420b57cec5SDimitry Andric   /// Get the number of output arguments returned by pointers.
48430b57cec5SDimitry Andric   int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
48440b57cec5SDimitry Andric     int NumRetOutputs = 0;
48450b57cec5SDimitry Andric     int NumOutputs = 0;
48468bcb0991SDimitry Andric     Type *RetTy = cast<Value>(CB)->getType();
48470b57cec5SDimitry Andric     if (!RetTy->isVoidTy()) {
48480b57cec5SDimitry Andric       // Register outputs are returned via the CallInst return value.
48498bcb0991SDimitry Andric       auto *ST = dyn_cast<StructType>(RetTy);
48500b57cec5SDimitry Andric       if (ST)
48510b57cec5SDimitry Andric         NumRetOutputs = ST->getNumElements();
48520b57cec5SDimitry Andric       else
48530b57cec5SDimitry Andric         NumRetOutputs = 1;
48540b57cec5SDimitry Andric     }
48550b57cec5SDimitry Andric     InlineAsm::ConstraintInfoVector Constraints = IA->ParseConstraints();
4856fe6060f1SDimitry Andric     for (const InlineAsm::ConstraintInfo &Info : Constraints) {
48570b57cec5SDimitry Andric       switch (Info.Type) {
48580b57cec5SDimitry Andric       case InlineAsm::isOutput:
48590b57cec5SDimitry Andric         NumOutputs++;
48600b57cec5SDimitry Andric         break;
48610b57cec5SDimitry Andric       default:
48620b57cec5SDimitry Andric         break;
48630b57cec5SDimitry Andric       }
48640b57cec5SDimitry Andric     }
48650b57cec5SDimitry Andric     return NumOutputs - NumRetOutputs;
48660b57cec5SDimitry Andric   }
48670b57cec5SDimitry Andric 
48680b57cec5SDimitry Andric   void visitAsmInstruction(Instruction &I) {
48690b57cec5SDimitry Andric     // Conservative inline assembly handling: check for poisoned shadow of
48700b57cec5SDimitry Andric     // asm() arguments, then unpoison the result and all the memory locations
48710b57cec5SDimitry Andric     // pointed to by those arguments.
48720b57cec5SDimitry Andric     // An inline asm() statement in C++ contains lists of input and output
48730b57cec5SDimitry Andric     // arguments used by the assembly code. These are mapped to operands of the
48740b57cec5SDimitry Andric     // CallInst as follows:
48750b57cec5SDimitry Andric     //  - nR register outputs ("=r) are returned by value in a single structure
48760b57cec5SDimitry Andric     //  (SSA value of the CallInst);
48770b57cec5SDimitry Andric     //  - nO other outputs ("=m" and others) are returned by pointer as first
48780b57cec5SDimitry Andric     // nO operands of the CallInst;
48790b57cec5SDimitry Andric     //  - nI inputs ("r", "m" and others) are passed to CallInst as the
48800b57cec5SDimitry Andric     // remaining nI operands.
48810b57cec5SDimitry Andric     // The total number of asm() arguments in the source is nR+nO+nI, and the
48820b57cec5SDimitry Andric     // corresponding CallInst has nO+nI+1 operands (the last operand is the
48830b57cec5SDimitry Andric     // function to be called).
4884*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
48858bcb0991SDimitry Andric     CallBase *CB = cast<CallBase>(&I);
48860b57cec5SDimitry Andric     IRBuilder<> IRB(&I);
48875ffd83dbSDimitry Andric     InlineAsm *IA = cast<InlineAsm>(CB->getCalledOperand());
48880b57cec5SDimitry Andric     int OutputArgs = getNumOutputArgs(IA, CB);
48890b57cec5SDimitry Andric     // The last operand of a CallInst is the function itself.
48900b57cec5SDimitry Andric     int NumOperands = CB->getNumOperands() - 1;
48910b57cec5SDimitry Andric 
48920b57cec5SDimitry Andric     // Check input arguments. Doing so before unpoisoning output arguments, so
48930b57cec5SDimitry Andric     // that we won't overwrite uninit values before checking them.
48940b57cec5SDimitry Andric     for (int i = OutputArgs; i < NumOperands; i++) {
48950b57cec5SDimitry Andric       Value *Operand = CB->getOperand(i);
489681ad6265SDimitry Andric       instrumentAsmArgument(Operand, CB->getParamElementType(i), I, IRB, DL,
489781ad6265SDimitry Andric                             /*isOutput*/ false);
48980b57cec5SDimitry Andric     }
48990b57cec5SDimitry Andric     // Unpoison output arguments. This must happen before the actual InlineAsm
49000b57cec5SDimitry Andric     // call, so that the shadow for memory published in the asm() statement
49010b57cec5SDimitry Andric     // remains valid.
49020b57cec5SDimitry Andric     for (int i = 0; i < OutputArgs; i++) {
49030b57cec5SDimitry Andric       Value *Operand = CB->getOperand(i);
490481ad6265SDimitry Andric       instrumentAsmArgument(Operand, CB->getParamElementType(i), I, IRB, DL,
490581ad6265SDimitry Andric                             /*isOutput*/ true);
49060b57cec5SDimitry Andric     }
49070b57cec5SDimitry Andric 
49080b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
49090b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
49100b57cec5SDimitry Andric   }
49110b57cec5SDimitry Andric 
4912e8d8bef9SDimitry Andric   void visitFreezeInst(FreezeInst &I) {
4913e8d8bef9SDimitry Andric     // Freeze always returns a fully defined value.
4914e8d8bef9SDimitry Andric     setShadow(&I, getCleanShadow(&I));
4915e8d8bef9SDimitry Andric     setOrigin(&I, getCleanOrigin());
4916e8d8bef9SDimitry Andric   }
4917e8d8bef9SDimitry Andric 
49180b57cec5SDimitry Andric   void visitInstruction(Instruction &I) {
49190b57cec5SDimitry Andric     // Everything else: stop propagating and check for poisoned shadow.
49200b57cec5SDimitry Andric     if (ClDumpStrictInstructions)
49210b57cec5SDimitry Andric       dumpInst(I);
49220b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "DEFAULT: " << I << "\n");
49230b57cec5SDimitry Andric     for (size_t i = 0, n = I.getNumOperands(); i < n; i++) {
49240b57cec5SDimitry Andric       Value *Operand = I.getOperand(i);
49250b57cec5SDimitry Andric       if (Operand->getType()->isSized())
49260b57cec5SDimitry Andric         insertShadowCheck(Operand, &I);
49270b57cec5SDimitry Andric     }
49280b57cec5SDimitry Andric     setShadow(&I, getCleanShadow(&I));
49290b57cec5SDimitry Andric     setOrigin(&I, getCleanOrigin());
49300b57cec5SDimitry Andric   }
49310b57cec5SDimitry Andric };
49320b57cec5SDimitry Andric 
49335f757f3fSDimitry Andric struct VarArgHelperBase : public VarArgHelper {
49345f757f3fSDimitry Andric   Function &F;
49355f757f3fSDimitry Andric   MemorySanitizer &MS;
49365f757f3fSDimitry Andric   MemorySanitizerVisitor &MSV;
49375f757f3fSDimitry Andric   SmallVector<CallInst *, 16> VAStartInstrumentationList;
49385f757f3fSDimitry Andric   const unsigned VAListTagSize;
49395f757f3fSDimitry Andric 
49405f757f3fSDimitry Andric   VarArgHelperBase(Function &F, MemorySanitizer &MS,
49415f757f3fSDimitry Andric                    MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
49425f757f3fSDimitry Andric       : F(F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
49435f757f3fSDimitry Andric 
49445f757f3fSDimitry Andric   Value *getShadowAddrForVAArgument(IRBuilder<> &IRB, unsigned ArgOffset) {
49455f757f3fSDimitry Andric     Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
49465f757f3fSDimitry Andric     return IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
49475f757f3fSDimitry Andric   }
49485f757f3fSDimitry Andric 
49495f757f3fSDimitry Andric   /// Compute the shadow address for a given va_arg.
49505f757f3fSDimitry Andric   Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
49515f757f3fSDimitry Andric                                    unsigned ArgOffset) {
49525f757f3fSDimitry Andric     Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy);
49535f757f3fSDimitry Andric     Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
49545f757f3fSDimitry Andric     return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0),
49555f757f3fSDimitry Andric                               "_msarg_va_s");
49565f757f3fSDimitry Andric   }
49575f757f3fSDimitry Andric 
49585f757f3fSDimitry Andric   /// Compute the shadow address for a given va_arg.
49595f757f3fSDimitry Andric   Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB,
49605f757f3fSDimitry Andric                                    unsigned ArgOffset, unsigned ArgSize) {
49615f757f3fSDimitry Andric     // Make sure we don't overflow __msan_va_arg_tls.
49625f757f3fSDimitry Andric     if (ArgOffset + ArgSize > kParamTLSSize)
49635f757f3fSDimitry Andric       return nullptr;
49645f757f3fSDimitry Andric     return getShadowPtrForVAArgument(Ty, IRB, ArgOffset);
49655f757f3fSDimitry Andric   }
49665f757f3fSDimitry Andric 
49675f757f3fSDimitry Andric   /// Compute the origin address for a given va_arg.
49685f757f3fSDimitry Andric   Value *getOriginPtrForVAArgument(IRBuilder<> &IRB, int ArgOffset) {
49695f757f3fSDimitry Andric     Value *Base = IRB.CreatePointerCast(MS.VAArgOriginTLS, MS.IntptrTy);
49705f757f3fSDimitry Andric     // getOriginPtrForVAArgument() is always called after
49715f757f3fSDimitry Andric     // getShadowPtrForVAArgument(), so __msan_va_arg_origin_tls can never
49725f757f3fSDimitry Andric     // overflow.
49735f757f3fSDimitry Andric     Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
49745f757f3fSDimitry Andric     return IRB.CreateIntToPtr(Base, PointerType::get(MS.OriginTy, 0),
49755f757f3fSDimitry Andric                               "_msarg_va_o");
49765f757f3fSDimitry Andric   }
49775f757f3fSDimitry Andric 
49785f757f3fSDimitry Andric   void CleanUnusedTLS(IRBuilder<> &IRB, Value *ShadowBase,
49795f757f3fSDimitry Andric                       unsigned BaseOffset) {
49805f757f3fSDimitry Andric     // The tails of __msan_va_arg_tls is not large enough to fit full
49815f757f3fSDimitry Andric     // value shadow, but it will be copied to backup anyway. Make it
49825f757f3fSDimitry Andric     // clean.
49835f757f3fSDimitry Andric     if (BaseOffset >= kParamTLSSize)
49845f757f3fSDimitry Andric       return;
49855f757f3fSDimitry Andric     Value *TailSize =
49865f757f3fSDimitry Andric         ConstantInt::getSigned(IRB.getInt32Ty(), kParamTLSSize - BaseOffset);
49875f757f3fSDimitry Andric     IRB.CreateMemSet(ShadowBase, ConstantInt::getNullValue(IRB.getInt8Ty()),
49885f757f3fSDimitry Andric                      TailSize, Align(8));
49895f757f3fSDimitry Andric   }
49905f757f3fSDimitry Andric 
49915f757f3fSDimitry Andric   void unpoisonVAListTagForInst(IntrinsicInst &I) {
49925f757f3fSDimitry Andric     IRBuilder<> IRB(&I);
49935f757f3fSDimitry Andric     Value *VAListTag = I.getArgOperand(0);
49945f757f3fSDimitry Andric     const Align Alignment = Align(8);
49955f757f3fSDimitry Andric     auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
49965f757f3fSDimitry Andric         VAListTag, IRB, IRB.getInt8Ty(), Alignment, /*isStore*/ true);
49975f757f3fSDimitry Andric     // Unpoison the whole __va_list_tag.
49985f757f3fSDimitry Andric     IRB.CreateMemSet(ShadowPtr, Constant::getNullValue(IRB.getInt8Ty()),
49995f757f3fSDimitry Andric                      VAListTagSize, Alignment, false);
50005f757f3fSDimitry Andric   }
50015f757f3fSDimitry Andric 
50025f757f3fSDimitry Andric   void visitVAStartInst(VAStartInst &I) override {
50035f757f3fSDimitry Andric     if (F.getCallingConv() == CallingConv::Win64)
50045f757f3fSDimitry Andric       return;
50055f757f3fSDimitry Andric     VAStartInstrumentationList.push_back(&I);
50065f757f3fSDimitry Andric     unpoisonVAListTagForInst(I);
50075f757f3fSDimitry Andric   }
50085f757f3fSDimitry Andric 
50095f757f3fSDimitry Andric   void visitVACopyInst(VACopyInst &I) override {
50105f757f3fSDimitry Andric     if (F.getCallingConv() == CallingConv::Win64)
50115f757f3fSDimitry Andric       return;
50125f757f3fSDimitry Andric     unpoisonVAListTagForInst(I);
50135f757f3fSDimitry Andric   }
50145f757f3fSDimitry Andric };
50155f757f3fSDimitry Andric 
50160b57cec5SDimitry Andric /// AMD64-specific implementation of VarArgHelper.
50175f757f3fSDimitry Andric struct VarArgAMD64Helper : public VarArgHelperBase {
50180b57cec5SDimitry Andric   // An unfortunate workaround for asymmetric lowering of va_arg stuff.
50195ffd83dbSDimitry Andric   // See a comment in visitCallBase for more details.
50200b57cec5SDimitry Andric   static const unsigned AMD64GpEndOffset = 48; // AMD64 ABI Draft 0.99.6 p3.5.7
50210b57cec5SDimitry Andric   static const unsigned AMD64FpEndOffsetSSE = 176;
50220b57cec5SDimitry Andric   // If SSE is disabled, fp_offset in va_list is zero.
50230b57cec5SDimitry Andric   static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
50240b57cec5SDimitry Andric 
50250b57cec5SDimitry Andric   unsigned AMD64FpEndOffset;
502606c3fb27SDimitry Andric   AllocaInst *VAArgTLSCopy = nullptr;
502706c3fb27SDimitry Andric   AllocaInst *VAArgTLSOriginCopy = nullptr;
50280b57cec5SDimitry Andric   Value *VAArgOverflowSize = nullptr;
50290b57cec5SDimitry Andric 
50300b57cec5SDimitry Andric   enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
50310b57cec5SDimitry Andric 
50320b57cec5SDimitry Andric   VarArgAMD64Helper(Function &F, MemorySanitizer &MS,
50330b57cec5SDimitry Andric                     MemorySanitizerVisitor &MSV)
50345f757f3fSDimitry Andric       : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/24) {
50350b57cec5SDimitry Andric     AMD64FpEndOffset = AMD64FpEndOffsetSSE;
5036349cc55cSDimitry Andric     for (const auto &Attr : F.getAttributes().getFnAttrs()) {
50370b57cec5SDimitry Andric       if (Attr.isStringAttribute() &&
50380b57cec5SDimitry Andric           (Attr.getKindAsString() == "target-features")) {
50390b57cec5SDimitry Andric         if (Attr.getValueAsString().contains("-sse"))
50400b57cec5SDimitry Andric           AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
50410b57cec5SDimitry Andric         break;
50420b57cec5SDimitry Andric       }
50430b57cec5SDimitry Andric     }
50440b57cec5SDimitry Andric   }
50450b57cec5SDimitry Andric 
50460b57cec5SDimitry Andric   ArgKind classifyArgument(Value *arg) {
50470b57cec5SDimitry Andric     // A very rough approximation of X86_64 argument classification rules.
50480b57cec5SDimitry Andric     Type *T = arg->getType();
50495f757f3fSDimitry Andric     if (T->isX86_FP80Ty())
50505f757f3fSDimitry Andric       return AK_Memory;
50510b57cec5SDimitry Andric     if (T->isFPOrFPVectorTy() || T->isX86_MMXTy())
50520b57cec5SDimitry Andric       return AK_FloatingPoint;
50530b57cec5SDimitry Andric     if (T->isIntegerTy() && T->getPrimitiveSizeInBits() <= 64)
50540b57cec5SDimitry Andric       return AK_GeneralPurpose;
50550b57cec5SDimitry Andric     if (T->isPointerTy())
50560b57cec5SDimitry Andric       return AK_GeneralPurpose;
50570b57cec5SDimitry Andric     return AK_Memory;
50580b57cec5SDimitry Andric   }
50590b57cec5SDimitry Andric 
50600b57cec5SDimitry Andric   // For VarArg functions, store the argument shadow in an ABI-specific format
50610b57cec5SDimitry Andric   // that corresponds to va_list layout.
50620b57cec5SDimitry Andric   // We do this because Clang lowers va_arg in the frontend, and this pass
50630b57cec5SDimitry Andric   // only sees the low level code that deals with va_list internals.
50640b57cec5SDimitry Andric   // A much easier alternative (provided that Clang emits va_arg instructions)
50650b57cec5SDimitry Andric   // would have been to associate each live instance of va_list with a copy of
50660b57cec5SDimitry Andric   // MSanParamTLS, and extract shadow on va_arg() call in the argument list
50670b57cec5SDimitry Andric   // order.
50685ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
50690b57cec5SDimitry Andric     unsigned GpOffset = 0;
50700b57cec5SDimitry Andric     unsigned FpOffset = AMD64GpEndOffset;
50710b57cec5SDimitry Andric     unsigned OverflowOffset = AMD64FpEndOffset;
5072*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
50735f757f3fSDimitry Andric 
5074bdd1243dSDimitry Andric     for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {
50755ffd83dbSDimitry Andric       bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();
50765ffd83dbSDimitry Andric       bool IsByVal = CB.paramHasAttr(ArgNo, Attribute::ByVal);
50770b57cec5SDimitry Andric       if (IsByVal) {
50780b57cec5SDimitry Andric         // ByVal arguments always go to the overflow area.
50790b57cec5SDimitry Andric         // Fixed arguments passed through the overflow area will be stepped
50800b57cec5SDimitry Andric         // over by va_start, so don't count them towards the offset.
50810b57cec5SDimitry Andric         if (IsFixed)
50820b57cec5SDimitry Andric           continue;
50830b57cec5SDimitry Andric         assert(A->getType()->isPointerTy());
50845ffd83dbSDimitry Andric         Type *RealTy = CB.getParamByValType(ArgNo);
50850b57cec5SDimitry Andric         uint64_t ArgSize = DL.getTypeAllocSize(RealTy);
50865f757f3fSDimitry Andric         uint64_t AlignedSize = alignTo(ArgSize, 8);
50875f757f3fSDimitry Andric         unsigned BaseOffset = OverflowOffset;
50885f757f3fSDimitry Andric         Value *ShadowBase =
50895f757f3fSDimitry Andric             getShadowPtrForVAArgument(RealTy, IRB, OverflowOffset);
50900b57cec5SDimitry Andric         Value *OriginBase = nullptr;
50910b57cec5SDimitry Andric         if (MS.TrackOrigins)
50925f757f3fSDimitry Andric           OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
50935f757f3fSDimitry Andric         OverflowOffset += AlignedSize;
50945f757f3fSDimitry Andric 
50955f757f3fSDimitry Andric         if (OverflowOffset > kParamTLSSize) {
50965f757f3fSDimitry Andric           CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
50975f757f3fSDimitry Andric           continue; // We have no space to copy shadow there.
50985f757f3fSDimitry Andric         }
50995f757f3fSDimitry Andric 
51000b57cec5SDimitry Andric         Value *ShadowPtr, *OriginPtr;
51010b57cec5SDimitry Andric         std::tie(ShadowPtr, OriginPtr) =
51020b57cec5SDimitry Andric             MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), kShadowTLSAlignment,
51030b57cec5SDimitry Andric                                    /*isStore*/ false);
51040b57cec5SDimitry Andric         IRB.CreateMemCpy(ShadowBase, kShadowTLSAlignment, ShadowPtr,
51050b57cec5SDimitry Andric                          kShadowTLSAlignment, ArgSize);
51060b57cec5SDimitry Andric         if (MS.TrackOrigins)
51070b57cec5SDimitry Andric           IRB.CreateMemCpy(OriginBase, kShadowTLSAlignment, OriginPtr,
51080b57cec5SDimitry Andric                            kShadowTLSAlignment, ArgSize);
51090b57cec5SDimitry Andric       } else {
51100b57cec5SDimitry Andric         ArgKind AK = classifyArgument(A);
51110b57cec5SDimitry Andric         if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
51120b57cec5SDimitry Andric           AK = AK_Memory;
51130b57cec5SDimitry Andric         if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
51140b57cec5SDimitry Andric           AK = AK_Memory;
51150b57cec5SDimitry Andric         Value *ShadowBase, *OriginBase = nullptr;
51160b57cec5SDimitry Andric         switch (AK) {
51170b57cec5SDimitry Andric         case AK_GeneralPurpose:
51185f757f3fSDimitry Andric           ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, GpOffset);
51190b57cec5SDimitry Andric           if (MS.TrackOrigins)
51205f757f3fSDimitry Andric             OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
51210b57cec5SDimitry Andric           GpOffset += 8;
51225f757f3fSDimitry Andric           assert(GpOffset <= kParamTLSSize);
51230b57cec5SDimitry Andric           break;
51240b57cec5SDimitry Andric         case AK_FloatingPoint:
51255f757f3fSDimitry Andric           ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, FpOffset);
51260b57cec5SDimitry Andric           if (MS.TrackOrigins)
51275f757f3fSDimitry Andric             OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
51280b57cec5SDimitry Andric           FpOffset += 16;
51295f757f3fSDimitry Andric           assert(FpOffset <= kParamTLSSize);
51300b57cec5SDimitry Andric           break;
51310b57cec5SDimitry Andric         case AK_Memory:
51320b57cec5SDimitry Andric           if (IsFixed)
51330b57cec5SDimitry Andric             continue;
51340b57cec5SDimitry Andric           uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
51355f757f3fSDimitry Andric           uint64_t AlignedSize = alignTo(ArgSize, 8);
51365f757f3fSDimitry Andric           unsigned BaseOffset = OverflowOffset;
51370b57cec5SDimitry Andric           ShadowBase =
51385f757f3fSDimitry Andric               getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset);
51395f757f3fSDimitry Andric           if (MS.TrackOrigins) {
51405f757f3fSDimitry Andric             OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
51415f757f3fSDimitry Andric           }
51425f757f3fSDimitry Andric           OverflowOffset += AlignedSize;
51435f757f3fSDimitry Andric           if (OverflowOffset > kParamTLSSize) {
51445f757f3fSDimitry Andric             // We have no space to copy shadow there.
51455f757f3fSDimitry Andric             CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
51465f757f3fSDimitry Andric             continue;
51475f757f3fSDimitry Andric           }
51480b57cec5SDimitry Andric         }
51490b57cec5SDimitry Andric         // Take fixed arguments into account for GpOffset and FpOffset,
51500b57cec5SDimitry Andric         // but don't actually store shadows for them.
51510b57cec5SDimitry Andric         // TODO(glider): don't call get*PtrForVAArgument() for them.
51520b57cec5SDimitry Andric         if (IsFixed)
51530b57cec5SDimitry Andric           continue;
51540b57cec5SDimitry Andric         Value *Shadow = MSV.getShadow(A);
51555ffd83dbSDimitry Andric         IRB.CreateAlignedStore(Shadow, ShadowBase, kShadowTLSAlignment);
51560b57cec5SDimitry Andric         if (MS.TrackOrigins) {
51570b57cec5SDimitry Andric           Value *Origin = MSV.getOrigin(A);
515806c3fb27SDimitry Andric           TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());
51590b57cec5SDimitry Andric           MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
51600b57cec5SDimitry Andric                           std::max(kShadowTLSAlignment, kMinOriginAlignment));
51610b57cec5SDimitry Andric         }
51620b57cec5SDimitry Andric       }
51630b57cec5SDimitry Andric     }
51640b57cec5SDimitry Andric     Constant *OverflowSize =
51650b57cec5SDimitry Andric         ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
51660b57cec5SDimitry Andric     IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
51670b57cec5SDimitry Andric   }
51680b57cec5SDimitry Andric 
51690b57cec5SDimitry Andric   void finalizeInstrumentation() override {
51700b57cec5SDimitry Andric     assert(!VAArgOverflowSize && !VAArgTLSCopy &&
51710b57cec5SDimitry Andric            "finalizeInstrumentation called twice");
51720b57cec5SDimitry Andric     if (!VAStartInstrumentationList.empty()) {
51730b57cec5SDimitry Andric       // If there is a va_start in this function, make a backup copy of
51740b57cec5SDimitry Andric       // va_arg_tls somewhere in the function entry block.
5175e8d8bef9SDimitry Andric       IRBuilder<> IRB(MSV.FnPrologueEnd);
51760b57cec5SDimitry Andric       VAArgOverflowSize =
51770b57cec5SDimitry Andric           IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);
5178bdd1243dSDimitry Andric       Value *CopySize = IRB.CreateAdd(
5179bdd1243dSDimitry Andric           ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
51800b57cec5SDimitry Andric       VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
518106c3fb27SDimitry Andric       VAArgTLSCopy->setAlignment(kShadowTLSAlignment);
518206c3fb27SDimitry Andric       IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),
518306c3fb27SDimitry Andric                        CopySize, kShadowTLSAlignment, false);
518406c3fb27SDimitry Andric 
518506c3fb27SDimitry Andric       Value *SrcSize = IRB.CreateBinaryIntrinsic(
518606c3fb27SDimitry Andric           Intrinsic::umin, CopySize,
518706c3fb27SDimitry Andric           ConstantInt::get(MS.IntptrTy, kParamTLSSize));
518806c3fb27SDimitry Andric       IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
518906c3fb27SDimitry Andric                        kShadowTLSAlignment, SrcSize);
51900b57cec5SDimitry Andric       if (MS.TrackOrigins) {
51910b57cec5SDimitry Andric         VAArgTLSOriginCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
519206c3fb27SDimitry Andric         VAArgTLSOriginCopy->setAlignment(kShadowTLSAlignment);
519306c3fb27SDimitry Andric         IRB.CreateMemCpy(VAArgTLSOriginCopy, kShadowTLSAlignment,
519406c3fb27SDimitry Andric                          MS.VAArgOriginTLS, kShadowTLSAlignment, SrcSize);
51950b57cec5SDimitry Andric       }
51960b57cec5SDimitry Andric     }
51970b57cec5SDimitry Andric 
51980b57cec5SDimitry Andric     // Instrument va_start.
51990b57cec5SDimitry Andric     // Copy va_list shadow from the backup copy of the TLS contents.
5200*0fca6ea1SDimitry Andric     for (CallInst *OrigInst : VAStartInstrumentationList) {
5201bdd1243dSDimitry Andric       NextNodeIRBuilder IRB(OrigInst);
52020b57cec5SDimitry Andric       Value *VAListTag = OrigInst->getArgOperand(0);
52030b57cec5SDimitry Andric 
52045f757f3fSDimitry Andric       Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*
52050b57cec5SDimitry Andric       Value *RegSaveAreaPtrPtr = IRB.CreateIntToPtr(
52060b57cec5SDimitry Andric           IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
52070b57cec5SDimitry Andric                         ConstantInt::get(MS.IntptrTy, 16)),
52080b57cec5SDimitry Andric           PointerType::get(RegSaveAreaPtrTy, 0));
52090b57cec5SDimitry Andric       Value *RegSaveAreaPtr =
52100b57cec5SDimitry Andric           IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
52110b57cec5SDimitry Andric       Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
5212480093f4SDimitry Andric       const Align Alignment = Align(16);
52130b57cec5SDimitry Andric       std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
52140b57cec5SDimitry Andric           MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),
52150b57cec5SDimitry Andric                                  Alignment, /*isStore*/ true);
52160b57cec5SDimitry Andric       IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
52170b57cec5SDimitry Andric                        AMD64FpEndOffset);
52180b57cec5SDimitry Andric       if (MS.TrackOrigins)
52190b57cec5SDimitry Andric         IRB.CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
52200b57cec5SDimitry Andric                          Alignment, AMD64FpEndOffset);
52215f757f3fSDimitry Andric       Type *OverflowArgAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*
52220b57cec5SDimitry Andric       Value *OverflowArgAreaPtrPtr = IRB.CreateIntToPtr(
52230b57cec5SDimitry Andric           IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
52240b57cec5SDimitry Andric                         ConstantInt::get(MS.IntptrTy, 8)),
52250b57cec5SDimitry Andric           PointerType::get(OverflowArgAreaPtrTy, 0));
52260b57cec5SDimitry Andric       Value *OverflowArgAreaPtr =
52270b57cec5SDimitry Andric           IRB.CreateLoad(OverflowArgAreaPtrTy, OverflowArgAreaPtrPtr);
52280b57cec5SDimitry Andric       Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
52290b57cec5SDimitry Andric       std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
52300b57cec5SDimitry Andric           MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.getInt8Ty(),
52310b57cec5SDimitry Andric                                  Alignment, /*isStore*/ true);
52320b57cec5SDimitry Andric       Value *SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSCopy,
52330b57cec5SDimitry Andric                                              AMD64FpEndOffset);
52340b57cec5SDimitry Andric       IRB.CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
52350b57cec5SDimitry Andric                        VAArgOverflowSize);
52360b57cec5SDimitry Andric       if (MS.TrackOrigins) {
52370b57cec5SDimitry Andric         SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSOriginCopy,
52380b57cec5SDimitry Andric                                         AMD64FpEndOffset);
52390b57cec5SDimitry Andric         IRB.CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
52400b57cec5SDimitry Andric                          VAArgOverflowSize);
52410b57cec5SDimitry Andric       }
52420b57cec5SDimitry Andric     }
52430b57cec5SDimitry Andric   }
52440b57cec5SDimitry Andric };
52450b57cec5SDimitry Andric 
52460b57cec5SDimitry Andric /// MIPS64-specific implementation of VarArgHelper.
52475f757f3fSDimitry Andric /// NOTE: This is also used for LoongArch64.
52485f757f3fSDimitry Andric struct VarArgMIPS64Helper : public VarArgHelperBase {
524906c3fb27SDimitry Andric   AllocaInst *VAArgTLSCopy = nullptr;
52500b57cec5SDimitry Andric   Value *VAArgSize = nullptr;
52510b57cec5SDimitry Andric 
52520b57cec5SDimitry Andric   VarArgMIPS64Helper(Function &F, MemorySanitizer &MS,
5253bdd1243dSDimitry Andric                      MemorySanitizerVisitor &MSV)
52545f757f3fSDimitry Andric       : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/8) {}
52550b57cec5SDimitry Andric 
52565ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
52570b57cec5SDimitry Andric     unsigned VAArgOffset = 0;
5258*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
5259bdd1243dSDimitry Andric     for (Value *A :
5260bdd1243dSDimitry Andric          llvm::drop_begin(CB.args(), CB.getFunctionType()->getNumParams())) {
52610b57cec5SDimitry Andric       Triple TargetTriple(F.getParent()->getTargetTriple());
52620b57cec5SDimitry Andric       Value *Base;
52630b57cec5SDimitry Andric       uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
52640b57cec5SDimitry Andric       if (TargetTriple.getArch() == Triple::mips64) {
5265bdd1243dSDimitry Andric         // Adjusting the shadow for argument with size < 8 to match the
5266bdd1243dSDimitry Andric         // placement of bits in big endian system
52670b57cec5SDimitry Andric         if (ArgSize < 8)
52680b57cec5SDimitry Andric           VAArgOffset += (8 - ArgSize);
52690b57cec5SDimitry Andric       }
52700b57cec5SDimitry Andric       Base = getShadowPtrForVAArgument(A->getType(), IRB, VAArgOffset, ArgSize);
52710b57cec5SDimitry Andric       VAArgOffset += ArgSize;
52720b57cec5SDimitry Andric       VAArgOffset = alignTo(VAArgOffset, 8);
52730b57cec5SDimitry Andric       if (!Base)
52740b57cec5SDimitry Andric         continue;
52755ffd83dbSDimitry Andric       IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
52760b57cec5SDimitry Andric     }
52770b57cec5SDimitry Andric 
52780b57cec5SDimitry Andric     Constant *TotalVAArgSize = ConstantInt::get(IRB.getInt64Ty(), VAArgOffset);
52790b57cec5SDimitry Andric     // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
52800b57cec5SDimitry Andric     // a new class member i.e. it is the total size of all VarArgs.
52810b57cec5SDimitry Andric     IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
52820b57cec5SDimitry Andric   }
52830b57cec5SDimitry Andric 
52840b57cec5SDimitry Andric   void finalizeInstrumentation() override {
52850b57cec5SDimitry Andric     assert(!VAArgSize && !VAArgTLSCopy &&
52860b57cec5SDimitry Andric            "finalizeInstrumentation called twice");
5287e8d8bef9SDimitry Andric     IRBuilder<> IRB(MSV.FnPrologueEnd);
52880b57cec5SDimitry Andric     VAArgSize = IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);
5289bdd1243dSDimitry Andric     Value *CopySize =
5290bdd1243dSDimitry Andric         IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0), VAArgSize);
52910b57cec5SDimitry Andric 
52920b57cec5SDimitry Andric     if (!VAStartInstrumentationList.empty()) {
52930b57cec5SDimitry Andric       // If there is a va_start in this function, make a backup copy of
52940b57cec5SDimitry Andric       // va_arg_tls somewhere in the function entry block.
52950b57cec5SDimitry Andric       VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
529606c3fb27SDimitry Andric       VAArgTLSCopy->setAlignment(kShadowTLSAlignment);
529706c3fb27SDimitry Andric       IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),
529806c3fb27SDimitry Andric                        CopySize, kShadowTLSAlignment, false);
529906c3fb27SDimitry Andric 
530006c3fb27SDimitry Andric       Value *SrcSize = IRB.CreateBinaryIntrinsic(
530106c3fb27SDimitry Andric           Intrinsic::umin, CopySize,
530206c3fb27SDimitry Andric           ConstantInt::get(MS.IntptrTy, kParamTLSSize));
530306c3fb27SDimitry Andric       IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
530406c3fb27SDimitry Andric                        kShadowTLSAlignment, SrcSize);
53050b57cec5SDimitry Andric     }
53060b57cec5SDimitry Andric 
53070b57cec5SDimitry Andric     // Instrument va_start.
53080b57cec5SDimitry Andric     // Copy va_list shadow from the backup copy of the TLS contents.
5309*0fca6ea1SDimitry Andric     for (CallInst *OrigInst : VAStartInstrumentationList) {
5310bdd1243dSDimitry Andric       NextNodeIRBuilder IRB(OrigInst);
53110b57cec5SDimitry Andric       Value *VAListTag = OrigInst->getArgOperand(0);
53125f757f3fSDimitry Andric       Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*
53130b57cec5SDimitry Andric       Value *RegSaveAreaPtrPtr =
53140b57cec5SDimitry Andric           IRB.CreateIntToPtr(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
53150b57cec5SDimitry Andric                              PointerType::get(RegSaveAreaPtrTy, 0));
53160b57cec5SDimitry Andric       Value *RegSaveAreaPtr =
53170b57cec5SDimitry Andric           IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
53180b57cec5SDimitry Andric       Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
5319480093f4SDimitry Andric       const Align Alignment = Align(8);
53200b57cec5SDimitry Andric       std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
53210b57cec5SDimitry Andric           MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),
53220b57cec5SDimitry Andric                                  Alignment, /*isStore*/ true);
53230b57cec5SDimitry Andric       IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
53240b57cec5SDimitry Andric                        CopySize);
53250b57cec5SDimitry Andric     }
53260b57cec5SDimitry Andric   }
53270b57cec5SDimitry Andric };
53280b57cec5SDimitry Andric 
53290b57cec5SDimitry Andric /// AArch64-specific implementation of VarArgHelper.
53305f757f3fSDimitry Andric struct VarArgAArch64Helper : public VarArgHelperBase {
53310b57cec5SDimitry Andric   static const unsigned kAArch64GrArgSize = 64;
53320b57cec5SDimitry Andric   static const unsigned kAArch64VrArgSize = 128;
53330b57cec5SDimitry Andric 
53340b57cec5SDimitry Andric   static const unsigned AArch64GrBegOffset = 0;
53350b57cec5SDimitry Andric   static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
53360b57cec5SDimitry Andric   // Make VR space aligned to 16 bytes.
53370b57cec5SDimitry Andric   static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
5338bdd1243dSDimitry Andric   static const unsigned AArch64VrEndOffset =
5339bdd1243dSDimitry Andric       AArch64VrBegOffset + kAArch64VrArgSize;
53400b57cec5SDimitry Andric   static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
53410b57cec5SDimitry Andric 
534206c3fb27SDimitry Andric   AllocaInst *VAArgTLSCopy = nullptr;
53430b57cec5SDimitry Andric   Value *VAArgOverflowSize = nullptr;
53440b57cec5SDimitry Andric 
53450b57cec5SDimitry Andric   enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
53460b57cec5SDimitry Andric 
53470b57cec5SDimitry Andric   VarArgAArch64Helper(Function &F, MemorySanitizer &MS,
5348bdd1243dSDimitry Andric                       MemorySanitizerVisitor &MSV)
53495f757f3fSDimitry Andric       : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/32) {}
53500b57cec5SDimitry Andric 
53515f757f3fSDimitry Andric   // A very rough approximation of aarch64 argument classification rules.
53525f757f3fSDimitry Andric   std::pair<ArgKind, uint64_t> classifyArgument(Type *T) {
53535f757f3fSDimitry Andric     if (T->isIntOrPtrTy() && T->getPrimitiveSizeInBits() <= 64)
53545f757f3fSDimitry Andric       return {AK_GeneralPurpose, 1};
53555f757f3fSDimitry Andric     if (T->isFloatingPointTy() && T->getPrimitiveSizeInBits() <= 128)
53565f757f3fSDimitry Andric       return {AK_FloatingPoint, 1};
53575f757f3fSDimitry Andric 
53585f757f3fSDimitry Andric     if (T->isArrayTy()) {
53595f757f3fSDimitry Andric       auto R = classifyArgument(T->getArrayElementType());
53605f757f3fSDimitry Andric       R.second *= T->getScalarType()->getArrayNumElements();
53615f757f3fSDimitry Andric       return R;
53625f757f3fSDimitry Andric     }
53635f757f3fSDimitry Andric 
53645f757f3fSDimitry Andric     if (const FixedVectorType *FV = dyn_cast<FixedVectorType>(T)) {
53655f757f3fSDimitry Andric       auto R = classifyArgument(FV->getScalarType());
53665f757f3fSDimitry Andric       R.second *= FV->getNumElements();
53675f757f3fSDimitry Andric       return R;
53685f757f3fSDimitry Andric     }
53695f757f3fSDimitry Andric 
53705f757f3fSDimitry Andric     LLVM_DEBUG(errs() << "Unknown vararg type: " << *T << "\n");
53715f757f3fSDimitry Andric     return {AK_Memory, 0};
53720b57cec5SDimitry Andric   }
53730b57cec5SDimitry Andric 
53740b57cec5SDimitry Andric   // The instrumentation stores the argument shadow in a non ABI-specific
53750b57cec5SDimitry Andric   // format because it does not know which argument is named (since Clang,
53760b57cec5SDimitry Andric   // like x86_64 case, lowers the va_args in the frontend and this pass only
53770b57cec5SDimitry Andric   // sees the low level code that deals with va_list internals).
53780b57cec5SDimitry Andric   // The first seven GR registers are saved in the first 56 bytes of the
53795f757f3fSDimitry Andric   // va_arg tls arra, followed by the first 8 FP/SIMD registers, and then
53800b57cec5SDimitry Andric   // the remaining arguments.
53810b57cec5SDimitry Andric   // Using constant offset within the va_arg TLS array allows fast copy
53820b57cec5SDimitry Andric   // in the finalize instrumentation.
53835ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
53840b57cec5SDimitry Andric     unsigned GrOffset = AArch64GrBegOffset;
53850b57cec5SDimitry Andric     unsigned VrOffset = AArch64VrBegOffset;
53860b57cec5SDimitry Andric     unsigned OverflowOffset = AArch64VAEndOffset;
53870b57cec5SDimitry Andric 
5388*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
5389bdd1243dSDimitry Andric     for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {
53905ffd83dbSDimitry Andric       bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();
53915f757f3fSDimitry Andric       auto [AK, RegNum] = classifyArgument(A->getType());
53925f757f3fSDimitry Andric       if (AK == AK_GeneralPurpose &&
53935f757f3fSDimitry Andric           (GrOffset + RegNum * 8) > AArch64GrEndOffset)
53940b57cec5SDimitry Andric         AK = AK_Memory;
53955f757f3fSDimitry Andric       if (AK == AK_FloatingPoint &&
53965f757f3fSDimitry Andric           (VrOffset + RegNum * 16) > AArch64VrEndOffset)
53970b57cec5SDimitry Andric         AK = AK_Memory;
53980b57cec5SDimitry Andric       Value *Base;
53990b57cec5SDimitry Andric       switch (AK) {
54000b57cec5SDimitry Andric       case AK_GeneralPurpose:
54015f757f3fSDimitry Andric         Base = getShadowPtrForVAArgument(A->getType(), IRB, GrOffset);
54025f757f3fSDimitry Andric         GrOffset += 8 * RegNum;
54030b57cec5SDimitry Andric         break;
54040b57cec5SDimitry Andric       case AK_FloatingPoint:
54055f757f3fSDimitry Andric         Base = getShadowPtrForVAArgument(A->getType(), IRB, VrOffset);
54065f757f3fSDimitry Andric         VrOffset += 16 * RegNum;
54070b57cec5SDimitry Andric         break;
54080b57cec5SDimitry Andric       case AK_Memory:
54090b57cec5SDimitry Andric         // Don't count fixed arguments in the overflow area - va_start will
54100b57cec5SDimitry Andric         // skip right over them.
54110b57cec5SDimitry Andric         if (IsFixed)
54120b57cec5SDimitry Andric           continue;
54130b57cec5SDimitry Andric         uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
54145f757f3fSDimitry Andric         uint64_t AlignedSize = alignTo(ArgSize, 8);
54155f757f3fSDimitry Andric         unsigned BaseOffset = OverflowOffset;
54165f757f3fSDimitry Andric         Base = getShadowPtrForVAArgument(A->getType(), IRB, BaseOffset);
54175f757f3fSDimitry Andric         OverflowOffset += AlignedSize;
54185f757f3fSDimitry Andric         if (OverflowOffset > kParamTLSSize) {
54195f757f3fSDimitry Andric           // We have no space to copy shadow there.
54205f757f3fSDimitry Andric           CleanUnusedTLS(IRB, Base, BaseOffset);
54215f757f3fSDimitry Andric           continue;
54225f757f3fSDimitry Andric         }
54230b57cec5SDimitry Andric         break;
54240b57cec5SDimitry Andric       }
54250b57cec5SDimitry Andric       // Count Gp/Vr fixed arguments to their respective offsets, but don't
54260b57cec5SDimitry Andric       // bother to actually store a shadow.
54270b57cec5SDimitry Andric       if (IsFixed)
54280b57cec5SDimitry Andric         continue;
54295ffd83dbSDimitry Andric       IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
54300b57cec5SDimitry Andric     }
54310b57cec5SDimitry Andric     Constant *OverflowSize =
54320b57cec5SDimitry Andric         ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
54330b57cec5SDimitry Andric     IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
54340b57cec5SDimitry Andric   }
54350b57cec5SDimitry Andric 
54360b57cec5SDimitry Andric   // Retrieve a va_list field of 'void*' size.
54370b57cec5SDimitry Andric   Value *getVAField64(IRBuilder<> &IRB, Value *VAListTag, int offset) {
5438bdd1243dSDimitry Andric     Value *SaveAreaPtrPtr = IRB.CreateIntToPtr(
54390b57cec5SDimitry Andric         IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
54400b57cec5SDimitry Andric                       ConstantInt::get(MS.IntptrTy, offset)),
54415f757f3fSDimitry Andric         PointerType::get(*MS.C, 0));
54420b57cec5SDimitry Andric     return IRB.CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
54430b57cec5SDimitry Andric   }
54440b57cec5SDimitry Andric 
54450b57cec5SDimitry Andric   // Retrieve a va_list field of 'int' size.
54460b57cec5SDimitry Andric   Value *getVAField32(IRBuilder<> &IRB, Value *VAListTag, int offset) {
5447bdd1243dSDimitry Andric     Value *SaveAreaPtr = IRB.CreateIntToPtr(
54480b57cec5SDimitry Andric         IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
54490b57cec5SDimitry Andric                       ConstantInt::get(MS.IntptrTy, offset)),
54505f757f3fSDimitry Andric         PointerType::get(*MS.C, 0));
54510b57cec5SDimitry Andric     Value *SaveArea32 = IRB.CreateLoad(IRB.getInt32Ty(), SaveAreaPtr);
54520b57cec5SDimitry Andric     return IRB.CreateSExt(SaveArea32, MS.IntptrTy);
54530b57cec5SDimitry Andric   }
54540b57cec5SDimitry Andric 
54550b57cec5SDimitry Andric   void finalizeInstrumentation() override {
54560b57cec5SDimitry Andric     assert(!VAArgOverflowSize && !VAArgTLSCopy &&
54570b57cec5SDimitry Andric            "finalizeInstrumentation called twice");
54580b57cec5SDimitry Andric     if (!VAStartInstrumentationList.empty()) {
54590b57cec5SDimitry Andric       // If there is a va_start in this function, make a backup copy of
54600b57cec5SDimitry Andric       // va_arg_tls somewhere in the function entry block.
5461e8d8bef9SDimitry Andric       IRBuilder<> IRB(MSV.FnPrologueEnd);
54620b57cec5SDimitry Andric       VAArgOverflowSize =
54630b57cec5SDimitry Andric           IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);
5464bdd1243dSDimitry Andric       Value *CopySize = IRB.CreateAdd(
5465bdd1243dSDimitry Andric           ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
54660b57cec5SDimitry Andric       VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
546706c3fb27SDimitry Andric       VAArgTLSCopy->setAlignment(kShadowTLSAlignment);
546806c3fb27SDimitry Andric       IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),
546906c3fb27SDimitry Andric                        CopySize, kShadowTLSAlignment, false);
547006c3fb27SDimitry Andric 
547106c3fb27SDimitry Andric       Value *SrcSize = IRB.CreateBinaryIntrinsic(
547206c3fb27SDimitry Andric           Intrinsic::umin, CopySize,
547306c3fb27SDimitry Andric           ConstantInt::get(MS.IntptrTy, kParamTLSSize));
547406c3fb27SDimitry Andric       IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
547506c3fb27SDimitry Andric                        kShadowTLSAlignment, SrcSize);
54760b57cec5SDimitry Andric     }
54770b57cec5SDimitry Andric 
54780b57cec5SDimitry Andric     Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
54790b57cec5SDimitry Andric     Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
54800b57cec5SDimitry Andric 
54810b57cec5SDimitry Andric     // Instrument va_start, copy va_list shadow from the backup copy of
54820b57cec5SDimitry Andric     // the TLS contents.
5483*0fca6ea1SDimitry Andric     for (CallInst *OrigInst : VAStartInstrumentationList) {
5484bdd1243dSDimitry Andric       NextNodeIRBuilder IRB(OrigInst);
54850b57cec5SDimitry Andric 
54860b57cec5SDimitry Andric       Value *VAListTag = OrigInst->getArgOperand(0);
54870b57cec5SDimitry Andric 
54880b57cec5SDimitry Andric       // The variadic ABI for AArch64 creates two areas to save the incoming
54890b57cec5SDimitry Andric       // argument registers (one for 64-bit general register xn-x7 and another
54900b57cec5SDimitry Andric       // for 128-bit FP/SIMD vn-v7).
54910b57cec5SDimitry Andric       // We need then to propagate the shadow arguments on both regions
54920b57cec5SDimitry Andric       // 'va::__gr_top + va::__gr_offs' and 'va::__vr_top + va::__vr_offs'.
54935ffd83dbSDimitry Andric       // The remaining arguments are saved on shadow for 'va::stack'.
54940b57cec5SDimitry Andric       // One caveat is it requires only to propagate the non-named arguments,
54950b57cec5SDimitry Andric       // however on the call site instrumentation 'all' the arguments are
54960b57cec5SDimitry Andric       // saved. So to copy the shadow values from the va_arg TLS array
54970b57cec5SDimitry Andric       // we need to adjust the offset for both GR and VR fields based on
54980b57cec5SDimitry Andric       // the __{gr,vr}_offs value (since they are stores based on incoming
54990b57cec5SDimitry Andric       // named arguments).
55005f757f3fSDimitry Andric       Type *RegSaveAreaPtrTy = IRB.getPtrTy();
55010b57cec5SDimitry Andric 
55020b57cec5SDimitry Andric       // Read the stack pointer from the va_list.
5503cf675768SDimitry Andric       Value *StackSaveAreaPtr =
5504cf675768SDimitry Andric           IRB.CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
55050b57cec5SDimitry Andric 
55060b57cec5SDimitry Andric       // Read both the __gr_top and __gr_off and add them up.
55070b57cec5SDimitry Andric       Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
55080b57cec5SDimitry Andric       Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
55090b57cec5SDimitry Andric 
5510cf675768SDimitry Andric       Value *GrRegSaveAreaPtr = IRB.CreateIntToPtr(
5511cf675768SDimitry Andric           IRB.CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
55120b57cec5SDimitry Andric 
55130b57cec5SDimitry Andric       // Read both the __vr_top and __vr_off and add them up.
55140b57cec5SDimitry Andric       Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
55150b57cec5SDimitry Andric       Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
55160b57cec5SDimitry Andric 
5517cf675768SDimitry Andric       Value *VrRegSaveAreaPtr = IRB.CreateIntToPtr(
5518cf675768SDimitry Andric           IRB.CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
55190b57cec5SDimitry Andric 
55200b57cec5SDimitry Andric       // It does not know how many named arguments is being used and, on the
55210b57cec5SDimitry Andric       // callsite all the arguments were saved.  Since __gr_off is defined as
55220b57cec5SDimitry Andric       // '0 - ((8 - named_gr) * 8)', the idea is to just propagate the variadic
55230b57cec5SDimitry Andric       // argument by ignoring the bytes of shadow from named arguments.
55240b57cec5SDimitry Andric       Value *GrRegSaveAreaShadowPtrOff =
55250b57cec5SDimitry Andric           IRB.CreateAdd(GrArgSize, GrOffSaveArea);
55260b57cec5SDimitry Andric 
55270b57cec5SDimitry Andric       Value *GrRegSaveAreaShadowPtr =
55280b57cec5SDimitry Andric           MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.getInt8Ty(),
5529480093f4SDimitry Andric                                  Align(8), /*isStore*/ true)
55300b57cec5SDimitry Andric               .first;
55310b57cec5SDimitry Andric 
55327a6dacacSDimitry Andric       Value *GrSrcPtr =
55337a6dacacSDimitry Andric           IRB.CreateInBoundsPtrAdd(VAArgTLSCopy, GrRegSaveAreaShadowPtrOff);
55340b57cec5SDimitry Andric       Value *GrCopySize = IRB.CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
55350b57cec5SDimitry Andric 
5536480093f4SDimitry Andric       IRB.CreateMemCpy(GrRegSaveAreaShadowPtr, Align(8), GrSrcPtr, Align(8),
5537480093f4SDimitry Andric                        GrCopySize);
55380b57cec5SDimitry Andric 
55390b57cec5SDimitry Andric       // Again, but for FP/SIMD values.
55400b57cec5SDimitry Andric       Value *VrRegSaveAreaShadowPtrOff =
55410b57cec5SDimitry Andric           IRB.CreateAdd(VrArgSize, VrOffSaveArea);
55420b57cec5SDimitry Andric 
55430b57cec5SDimitry Andric       Value *VrRegSaveAreaShadowPtr =
55440b57cec5SDimitry Andric           MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.getInt8Ty(),
5545480093f4SDimitry Andric                                  Align(8), /*isStore*/ true)
55460b57cec5SDimitry Andric               .first;
55470b57cec5SDimitry Andric 
55487a6dacacSDimitry Andric       Value *VrSrcPtr = IRB.CreateInBoundsPtrAdd(
55497a6dacacSDimitry Andric           IRB.CreateInBoundsPtrAdd(VAArgTLSCopy,
55500b57cec5SDimitry Andric                                    IRB.getInt32(AArch64VrBegOffset)),
55510b57cec5SDimitry Andric           VrRegSaveAreaShadowPtrOff);
55520b57cec5SDimitry Andric       Value *VrCopySize = IRB.CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
55530b57cec5SDimitry Andric 
5554480093f4SDimitry Andric       IRB.CreateMemCpy(VrRegSaveAreaShadowPtr, Align(8), VrSrcPtr, Align(8),
5555480093f4SDimitry Andric                        VrCopySize);
55560b57cec5SDimitry Andric 
55570b57cec5SDimitry Andric       // And finally for remaining arguments.
55580b57cec5SDimitry Andric       Value *StackSaveAreaShadowPtr =
55590b57cec5SDimitry Andric           MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.getInt8Ty(),
5560480093f4SDimitry Andric                                  Align(16), /*isStore*/ true)
55610b57cec5SDimitry Andric               .first;
55620b57cec5SDimitry Andric 
55637a6dacacSDimitry Andric       Value *StackSrcPtr = IRB.CreateInBoundsPtrAdd(
55647a6dacacSDimitry Andric           VAArgTLSCopy, IRB.getInt32(AArch64VAEndOffset));
55650b57cec5SDimitry Andric 
5566480093f4SDimitry Andric       IRB.CreateMemCpy(StackSaveAreaShadowPtr, Align(16), StackSrcPtr,
5567480093f4SDimitry Andric                        Align(16), VAArgOverflowSize);
55680b57cec5SDimitry Andric     }
55690b57cec5SDimitry Andric   }
55700b57cec5SDimitry Andric };
55710b57cec5SDimitry Andric 
55720b57cec5SDimitry Andric /// PowerPC64-specific implementation of VarArgHelper.
55735f757f3fSDimitry Andric struct VarArgPowerPC64Helper : public VarArgHelperBase {
557406c3fb27SDimitry Andric   AllocaInst *VAArgTLSCopy = nullptr;
55750b57cec5SDimitry Andric   Value *VAArgSize = nullptr;
55760b57cec5SDimitry Andric 
55770b57cec5SDimitry Andric   VarArgPowerPC64Helper(Function &F, MemorySanitizer &MS,
5578bdd1243dSDimitry Andric                         MemorySanitizerVisitor &MSV)
55795f757f3fSDimitry Andric       : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/8) {}
55800b57cec5SDimitry Andric 
55815ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
55820b57cec5SDimitry Andric     // For PowerPC, we need to deal with alignment of stack arguments -
55830b57cec5SDimitry Andric     // they are mostly aligned to 8 bytes, but vectors and i128 arrays
55840b57cec5SDimitry Andric     // are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,
5585e8d8bef9SDimitry Andric     // For that reason, we compute current offset from stack pointer (which is
5586e8d8bef9SDimitry Andric     // always properly aligned), and offset for the first vararg, then subtract
5587e8d8bef9SDimitry Andric     // them.
55880b57cec5SDimitry Andric     unsigned VAArgBase;
55890b57cec5SDimitry Andric     Triple TargetTriple(F.getParent()->getTargetTriple());
55900b57cec5SDimitry Andric     // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
55910b57cec5SDimitry Andric     // and 32 bytes for ABIv2.  This is usually determined by target
55925ffd83dbSDimitry Andric     // endianness, but in theory could be overridden by function attribute.
55930b57cec5SDimitry Andric     if (TargetTriple.getArch() == Triple::ppc64)
55940b57cec5SDimitry Andric       VAArgBase = 48;
55950b57cec5SDimitry Andric     else
55960b57cec5SDimitry Andric       VAArgBase = 32;
55970b57cec5SDimitry Andric     unsigned VAArgOffset = VAArgBase;
5598*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
5599bdd1243dSDimitry Andric     for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {
56005ffd83dbSDimitry Andric       bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();
56015ffd83dbSDimitry Andric       bool IsByVal = CB.paramHasAttr(ArgNo, Attribute::ByVal);
56020b57cec5SDimitry Andric       if (IsByVal) {
56030b57cec5SDimitry Andric         assert(A->getType()->isPointerTy());
56045ffd83dbSDimitry Andric         Type *RealTy = CB.getParamByValType(ArgNo);
56050b57cec5SDimitry Andric         uint64_t ArgSize = DL.getTypeAllocSize(RealTy);
560681ad6265SDimitry Andric         Align ArgAlign = CB.getParamAlign(ArgNo).value_or(Align(8));
560781ad6265SDimitry Andric         if (ArgAlign < 8)
56085ffd83dbSDimitry Andric           ArgAlign = Align(8);
56090b57cec5SDimitry Andric         VAArgOffset = alignTo(VAArgOffset, ArgAlign);
56100b57cec5SDimitry Andric         if (!IsFixed) {
56110b57cec5SDimitry Andric           Value *Base = getShadowPtrForVAArgument(
56120b57cec5SDimitry Andric               RealTy, IRB, VAArgOffset - VAArgBase, ArgSize);
56130b57cec5SDimitry Andric           if (Base) {
56140b57cec5SDimitry Andric             Value *AShadowPtr, *AOriginPtr;
56150b57cec5SDimitry Andric             std::tie(AShadowPtr, AOriginPtr) =
56160b57cec5SDimitry Andric                 MSV.getShadowOriginPtr(A, IRB, IRB.getInt8Ty(),
56170b57cec5SDimitry Andric                                        kShadowTLSAlignment, /*isStore*/ false);
56180b57cec5SDimitry Andric 
56190b57cec5SDimitry Andric             IRB.CreateMemCpy(Base, kShadowTLSAlignment, AShadowPtr,
56200b57cec5SDimitry Andric                              kShadowTLSAlignment, ArgSize);
56210b57cec5SDimitry Andric           }
56220b57cec5SDimitry Andric         }
562381ad6265SDimitry Andric         VAArgOffset += alignTo(ArgSize, Align(8));
56240b57cec5SDimitry Andric       } else {
56250b57cec5SDimitry Andric         Value *Base;
56260b57cec5SDimitry Andric         uint64_t ArgSize = DL.getTypeAllocSize(A->getType());
562781ad6265SDimitry Andric         Align ArgAlign = Align(8);
56280b57cec5SDimitry Andric         if (A->getType()->isArrayTy()) {
56290b57cec5SDimitry Andric           // Arrays are aligned to element size, except for long double
56300b57cec5SDimitry Andric           // arrays, which are aligned to 8 bytes.
56310b57cec5SDimitry Andric           Type *ElementTy = A->getType()->getArrayElementType();
56320b57cec5SDimitry Andric           if (!ElementTy->isPPC_FP128Ty())
563381ad6265SDimitry Andric             ArgAlign = Align(DL.getTypeAllocSize(ElementTy));
56340b57cec5SDimitry Andric         } else if (A->getType()->isVectorTy()) {
56350b57cec5SDimitry Andric           // Vectors are naturally aligned.
563681ad6265SDimitry Andric           ArgAlign = Align(ArgSize);
56370b57cec5SDimitry Andric         }
56380b57cec5SDimitry Andric         if (ArgAlign < 8)
563981ad6265SDimitry Andric           ArgAlign = Align(8);
56400b57cec5SDimitry Andric         VAArgOffset = alignTo(VAArgOffset, ArgAlign);
56410b57cec5SDimitry Andric         if (DL.isBigEndian()) {
564281ad6265SDimitry Andric           // Adjusting the shadow for argument with size < 8 to match the
564381ad6265SDimitry Andric           // placement of bits in big endian system
56440b57cec5SDimitry Andric           if (ArgSize < 8)
56450b57cec5SDimitry Andric             VAArgOffset += (8 - ArgSize);
56460b57cec5SDimitry Andric         }
56470b57cec5SDimitry Andric         if (!IsFixed) {
56480b57cec5SDimitry Andric           Base = getShadowPtrForVAArgument(A->getType(), IRB,
56490b57cec5SDimitry Andric                                            VAArgOffset - VAArgBase, ArgSize);
56500b57cec5SDimitry Andric           if (Base)
56515ffd83dbSDimitry Andric             IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment);
56520b57cec5SDimitry Andric         }
56530b57cec5SDimitry Andric         VAArgOffset += ArgSize;
565481ad6265SDimitry Andric         VAArgOffset = alignTo(VAArgOffset, Align(8));
56550b57cec5SDimitry Andric       }
56560b57cec5SDimitry Andric       if (IsFixed)
56570b57cec5SDimitry Andric         VAArgBase = VAArgOffset;
56580b57cec5SDimitry Andric     }
56590b57cec5SDimitry Andric 
5660bdd1243dSDimitry Andric     Constant *TotalVAArgSize =
5661bdd1243dSDimitry Andric         ConstantInt::get(IRB.getInt64Ty(), VAArgOffset - VAArgBase);
56620b57cec5SDimitry Andric     // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
56630b57cec5SDimitry Andric     // a new class member i.e. it is the total size of all VarArgs.
56640b57cec5SDimitry Andric     IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
56650b57cec5SDimitry Andric   }
56660b57cec5SDimitry Andric 
56670b57cec5SDimitry Andric   void finalizeInstrumentation() override {
56680b57cec5SDimitry Andric     assert(!VAArgSize && !VAArgTLSCopy &&
56690b57cec5SDimitry Andric            "finalizeInstrumentation called twice");
5670e8d8bef9SDimitry Andric     IRBuilder<> IRB(MSV.FnPrologueEnd);
56710b57cec5SDimitry Andric     VAArgSize = IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);
5672bdd1243dSDimitry Andric     Value *CopySize =
5673bdd1243dSDimitry Andric         IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0), VAArgSize);
56740b57cec5SDimitry Andric 
56750b57cec5SDimitry Andric     if (!VAStartInstrumentationList.empty()) {
56760b57cec5SDimitry Andric       // If there is a va_start in this function, make a backup copy of
56770b57cec5SDimitry Andric       // va_arg_tls somewhere in the function entry block.
567806c3fb27SDimitry Andric 
56790b57cec5SDimitry Andric       VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
568006c3fb27SDimitry Andric       VAArgTLSCopy->setAlignment(kShadowTLSAlignment);
568106c3fb27SDimitry Andric       IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),
568206c3fb27SDimitry Andric                        CopySize, kShadowTLSAlignment, false);
568306c3fb27SDimitry Andric 
568406c3fb27SDimitry Andric       Value *SrcSize = IRB.CreateBinaryIntrinsic(
568506c3fb27SDimitry Andric           Intrinsic::umin, CopySize,
568606c3fb27SDimitry Andric           ConstantInt::get(MS.IntptrTy, kParamTLSSize));
568706c3fb27SDimitry Andric       IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
568806c3fb27SDimitry Andric                        kShadowTLSAlignment, SrcSize);
56890b57cec5SDimitry Andric     }
56900b57cec5SDimitry Andric 
56910b57cec5SDimitry Andric     // Instrument va_start.
56920b57cec5SDimitry Andric     // Copy va_list shadow from the backup copy of the TLS contents.
5693*0fca6ea1SDimitry Andric     for (CallInst *OrigInst : VAStartInstrumentationList) {
5694bdd1243dSDimitry Andric       NextNodeIRBuilder IRB(OrigInst);
56950b57cec5SDimitry Andric       Value *VAListTag = OrigInst->getArgOperand(0);
56965f757f3fSDimitry Andric       Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*
56970b57cec5SDimitry Andric       Value *RegSaveAreaPtrPtr =
56980b57cec5SDimitry Andric           IRB.CreateIntToPtr(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
56990b57cec5SDimitry Andric                              PointerType::get(RegSaveAreaPtrTy, 0));
57000b57cec5SDimitry Andric       Value *RegSaveAreaPtr =
57010b57cec5SDimitry Andric           IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
57020b57cec5SDimitry Andric       Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
5703480093f4SDimitry Andric       const Align Alignment = Align(8);
57040b57cec5SDimitry Andric       std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
57050b57cec5SDimitry Andric           MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(),
57060b57cec5SDimitry Andric                                  Alignment, /*isStore*/ true);
57070b57cec5SDimitry Andric       IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
57080b57cec5SDimitry Andric                        CopySize);
57090b57cec5SDimitry Andric     }
57100b57cec5SDimitry Andric   }
57110b57cec5SDimitry Andric };
57120b57cec5SDimitry Andric 
57135ffd83dbSDimitry Andric /// SystemZ-specific implementation of VarArgHelper.
57145f757f3fSDimitry Andric struct VarArgSystemZHelper : public VarArgHelperBase {
57155ffd83dbSDimitry Andric   static const unsigned SystemZGpOffset = 16;
57165ffd83dbSDimitry Andric   static const unsigned SystemZGpEndOffset = 56;
57175ffd83dbSDimitry Andric   static const unsigned SystemZFpOffset = 128;
57185ffd83dbSDimitry Andric   static const unsigned SystemZFpEndOffset = 160;
57195ffd83dbSDimitry Andric   static const unsigned SystemZMaxVrArgs = 8;
57205ffd83dbSDimitry Andric   static const unsigned SystemZRegSaveAreaSize = 160;
57215ffd83dbSDimitry Andric   static const unsigned SystemZOverflowOffset = 160;
57225ffd83dbSDimitry Andric   static const unsigned SystemZVAListTagSize = 32;
57235ffd83dbSDimitry Andric   static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
57245ffd83dbSDimitry Andric   static const unsigned SystemZRegSaveAreaPtrOffset = 24;
57255ffd83dbSDimitry Andric 
572606c3fb27SDimitry Andric   bool IsSoftFloatABI;
572706c3fb27SDimitry Andric   AllocaInst *VAArgTLSCopy = nullptr;
572806c3fb27SDimitry Andric   AllocaInst *VAArgTLSOriginCopy = nullptr;
57295ffd83dbSDimitry Andric   Value *VAArgOverflowSize = nullptr;
57305ffd83dbSDimitry Andric 
57315ffd83dbSDimitry Andric   enum class ArgKind {
57325ffd83dbSDimitry Andric     GeneralPurpose,
57335ffd83dbSDimitry Andric     FloatingPoint,
57345ffd83dbSDimitry Andric     Vector,
57355ffd83dbSDimitry Andric     Memory,
57365ffd83dbSDimitry Andric     Indirect,
57375ffd83dbSDimitry Andric   };
57385ffd83dbSDimitry Andric 
57395ffd83dbSDimitry Andric   enum class ShadowExtension { None, Zero, Sign };
57405ffd83dbSDimitry Andric 
57415ffd83dbSDimitry Andric   VarArgSystemZHelper(Function &F, MemorySanitizer &MS,
57425ffd83dbSDimitry Andric                       MemorySanitizerVisitor &MSV)
57435f757f3fSDimitry Andric       : VarArgHelperBase(F, MS, MSV, SystemZVAListTagSize),
574406c3fb27SDimitry Andric         IsSoftFloatABI(F.getFnAttribute("use-soft-float").getValueAsBool()) {}
57455ffd83dbSDimitry Andric 
574606c3fb27SDimitry Andric   ArgKind classifyArgument(Type *T) {
57475ffd83dbSDimitry Andric     // T is a SystemZABIInfo::classifyArgumentType() output, and there are
57485ffd83dbSDimitry Andric     // only a few possibilities of what it can be. In particular, enums, single
57495ffd83dbSDimitry Andric     // element structs and large types have already been taken care of.
57505ffd83dbSDimitry Andric 
57515ffd83dbSDimitry Andric     // Some i128 and fp128 arguments are converted to pointers only in the
57525ffd83dbSDimitry Andric     // back end.
57535ffd83dbSDimitry Andric     if (T->isIntegerTy(128) || T->isFP128Ty())
57545ffd83dbSDimitry Andric       return ArgKind::Indirect;
57555ffd83dbSDimitry Andric     if (T->isFloatingPointTy())
57565ffd83dbSDimitry Andric       return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
57575ffd83dbSDimitry Andric     if (T->isIntegerTy() || T->isPointerTy())
57585ffd83dbSDimitry Andric       return ArgKind::GeneralPurpose;
57595ffd83dbSDimitry Andric     if (T->isVectorTy())
57605ffd83dbSDimitry Andric       return ArgKind::Vector;
57615ffd83dbSDimitry Andric     return ArgKind::Memory;
57625ffd83dbSDimitry Andric   }
57635ffd83dbSDimitry Andric 
57645ffd83dbSDimitry Andric   ShadowExtension getShadowExtension(const CallBase &CB, unsigned ArgNo) {
57655ffd83dbSDimitry Andric     // ABI says: "One of the simple integer types no more than 64 bits wide.
57665ffd83dbSDimitry Andric     // ... If such an argument is shorter than 64 bits, replace it by a full
57675ffd83dbSDimitry Andric     // 64-bit integer representing the same number, using sign or zero
57685ffd83dbSDimitry Andric     // extension". Shadow for an integer argument has the same type as the
57695ffd83dbSDimitry Andric     // argument itself, so it can be sign or zero extended as well.
57705ffd83dbSDimitry Andric     bool ZExt = CB.paramHasAttr(ArgNo, Attribute::ZExt);
57715ffd83dbSDimitry Andric     bool SExt = CB.paramHasAttr(ArgNo, Attribute::SExt);
57725ffd83dbSDimitry Andric     if (ZExt) {
57735ffd83dbSDimitry Andric       assert(!SExt);
57745ffd83dbSDimitry Andric       return ShadowExtension::Zero;
57755ffd83dbSDimitry Andric     }
57765ffd83dbSDimitry Andric     if (SExt) {
57775ffd83dbSDimitry Andric       assert(!ZExt);
57785ffd83dbSDimitry Andric       return ShadowExtension::Sign;
57795ffd83dbSDimitry Andric     }
57805ffd83dbSDimitry Andric     return ShadowExtension::None;
57815ffd83dbSDimitry Andric   }
57825ffd83dbSDimitry Andric 
57835ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
57845ffd83dbSDimitry Andric     unsigned GpOffset = SystemZGpOffset;
57855ffd83dbSDimitry Andric     unsigned FpOffset = SystemZFpOffset;
57865ffd83dbSDimitry Andric     unsigned VrIndex = 0;
57875ffd83dbSDimitry Andric     unsigned OverflowOffset = SystemZOverflowOffset;
5788*0fca6ea1SDimitry Andric     const DataLayout &DL = F.getDataLayout();
5789bdd1243dSDimitry Andric     for (const auto &[ArgNo, A] : llvm::enumerate(CB.args())) {
57905ffd83dbSDimitry Andric       bool IsFixed = ArgNo < CB.getFunctionType()->getNumParams();
57915ffd83dbSDimitry Andric       // SystemZABIInfo does not produce ByVal parameters.
57925ffd83dbSDimitry Andric       assert(!CB.paramHasAttr(ArgNo, Attribute::ByVal));
57935ffd83dbSDimitry Andric       Type *T = A->getType();
579406c3fb27SDimitry Andric       ArgKind AK = classifyArgument(T);
57955ffd83dbSDimitry Andric       if (AK == ArgKind::Indirect) {
57965ffd83dbSDimitry Andric         T = PointerType::get(T, 0);
57975ffd83dbSDimitry Andric         AK = ArgKind::GeneralPurpose;
57985ffd83dbSDimitry Andric       }
57995ffd83dbSDimitry Andric       if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
58005ffd83dbSDimitry Andric         AK = ArgKind::Memory;
58015ffd83dbSDimitry Andric       if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
58025ffd83dbSDimitry Andric         AK = ArgKind::Memory;
58035ffd83dbSDimitry Andric       if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
58045ffd83dbSDimitry Andric         AK = ArgKind::Memory;
58055ffd83dbSDimitry Andric       Value *ShadowBase = nullptr;
58065ffd83dbSDimitry Andric       Value *OriginBase = nullptr;
58075ffd83dbSDimitry Andric       ShadowExtension SE = ShadowExtension::None;
58085ffd83dbSDimitry Andric       switch (AK) {
58095ffd83dbSDimitry Andric       case ArgKind::GeneralPurpose: {
58105ffd83dbSDimitry Andric         // Always keep track of GpOffset, but store shadow only for varargs.
58115ffd83dbSDimitry Andric         uint64_t ArgSize = 8;
58125ffd83dbSDimitry Andric         if (GpOffset + ArgSize <= kParamTLSSize) {
58135ffd83dbSDimitry Andric           if (!IsFixed) {
58145ffd83dbSDimitry Andric             SE = getShadowExtension(CB, ArgNo);
58155ffd83dbSDimitry Andric             uint64_t GapSize = 0;
58165ffd83dbSDimitry Andric             if (SE == ShadowExtension::None) {
58175ffd83dbSDimitry Andric               uint64_t ArgAllocSize = DL.getTypeAllocSize(T);
58185ffd83dbSDimitry Andric               assert(ArgAllocSize <= ArgSize);
58195ffd83dbSDimitry Andric               GapSize = ArgSize - ArgAllocSize;
58205ffd83dbSDimitry Andric             }
58215ffd83dbSDimitry Andric             ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
58225ffd83dbSDimitry Andric             if (MS.TrackOrigins)
58235ffd83dbSDimitry Andric               OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
58245ffd83dbSDimitry Andric           }
58255ffd83dbSDimitry Andric           GpOffset += ArgSize;
58265ffd83dbSDimitry Andric         } else {
58275ffd83dbSDimitry Andric           GpOffset = kParamTLSSize;
58285ffd83dbSDimitry Andric         }
58295ffd83dbSDimitry Andric         break;
58305ffd83dbSDimitry Andric       }
58315ffd83dbSDimitry Andric       case ArgKind::FloatingPoint: {
58325ffd83dbSDimitry Andric         // Always keep track of FpOffset, but store shadow only for varargs.
58335ffd83dbSDimitry Andric         uint64_t ArgSize = 8;
58345ffd83dbSDimitry Andric         if (FpOffset + ArgSize <= kParamTLSSize) {
58355ffd83dbSDimitry Andric           if (!IsFixed) {
58365ffd83dbSDimitry Andric             // PoP says: "A short floating-point datum requires only the
58375ffd83dbSDimitry Andric             // left-most 32 bit positions of a floating-point register".
58385ffd83dbSDimitry Andric             // Therefore, in contrast to AK_GeneralPurpose and AK_Memory,
58395ffd83dbSDimitry Andric             // don't extend shadow and don't mind the gap.
58405ffd83dbSDimitry Andric             ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
58415ffd83dbSDimitry Andric             if (MS.TrackOrigins)
58425ffd83dbSDimitry Andric               OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
58435ffd83dbSDimitry Andric           }
58445ffd83dbSDimitry Andric           FpOffset += ArgSize;
58455ffd83dbSDimitry Andric         } else {
58465ffd83dbSDimitry Andric           FpOffset = kParamTLSSize;
58475ffd83dbSDimitry Andric         }
58485ffd83dbSDimitry Andric         break;
58495ffd83dbSDimitry Andric       }
58505ffd83dbSDimitry Andric       case ArgKind::Vector: {
58515ffd83dbSDimitry Andric         // Keep track of VrIndex. No need to store shadow, since vector varargs
58525ffd83dbSDimitry Andric         // go through AK_Memory.
58535ffd83dbSDimitry Andric         assert(IsFixed);
58545ffd83dbSDimitry Andric         VrIndex++;
58555ffd83dbSDimitry Andric         break;
58565ffd83dbSDimitry Andric       }
58575ffd83dbSDimitry Andric       case ArgKind::Memory: {
58585ffd83dbSDimitry Andric         // Keep track of OverflowOffset and store shadow only for varargs.
58595ffd83dbSDimitry Andric         // Ignore fixed args, since we need to copy only the vararg portion of
58605ffd83dbSDimitry Andric         // the overflow area shadow.
58615ffd83dbSDimitry Andric         if (!IsFixed) {
58625ffd83dbSDimitry Andric           uint64_t ArgAllocSize = DL.getTypeAllocSize(T);
58635ffd83dbSDimitry Andric           uint64_t ArgSize = alignTo(ArgAllocSize, 8);
58645ffd83dbSDimitry Andric           if (OverflowOffset + ArgSize <= kParamTLSSize) {
58655ffd83dbSDimitry Andric             SE = getShadowExtension(CB, ArgNo);
58665ffd83dbSDimitry Andric             uint64_t GapSize =
58675ffd83dbSDimitry Andric                 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
58685ffd83dbSDimitry Andric             ShadowBase =
58695ffd83dbSDimitry Andric                 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
58705ffd83dbSDimitry Andric             if (MS.TrackOrigins)
58715ffd83dbSDimitry Andric               OriginBase =
58725ffd83dbSDimitry Andric                   getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
58735ffd83dbSDimitry Andric             OverflowOffset += ArgSize;
58745ffd83dbSDimitry Andric           } else {
58755ffd83dbSDimitry Andric             OverflowOffset = kParamTLSSize;
58765ffd83dbSDimitry Andric           }
58775ffd83dbSDimitry Andric         }
58785ffd83dbSDimitry Andric         break;
58795ffd83dbSDimitry Andric       }
58805ffd83dbSDimitry Andric       case ArgKind::Indirect:
58815ffd83dbSDimitry Andric         llvm_unreachable("Indirect must be converted to GeneralPurpose");
58825ffd83dbSDimitry Andric       }
58835ffd83dbSDimitry Andric       if (ShadowBase == nullptr)
58845ffd83dbSDimitry Andric         continue;
58855ffd83dbSDimitry Andric       Value *Shadow = MSV.getShadow(A);
58865ffd83dbSDimitry Andric       if (SE != ShadowExtension::None)
58875ffd83dbSDimitry Andric         Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.getInt64Ty(),
58885ffd83dbSDimitry Andric                                       /*Signed*/ SE == ShadowExtension::Sign);
58895ffd83dbSDimitry Andric       ShadowBase = IRB.CreateIntToPtr(
58905ffd83dbSDimitry Andric           ShadowBase, PointerType::get(Shadow->getType(), 0), "_msarg_va_s");
58915ffd83dbSDimitry Andric       IRB.CreateStore(Shadow, ShadowBase);
58925ffd83dbSDimitry Andric       if (MS.TrackOrigins) {
58935ffd83dbSDimitry Andric         Value *Origin = MSV.getOrigin(A);
589406c3fb27SDimitry Andric         TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());
58955ffd83dbSDimitry Andric         MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
58965ffd83dbSDimitry Andric                         kMinOriginAlignment);
58975ffd83dbSDimitry Andric       }
58985ffd83dbSDimitry Andric     }
58995ffd83dbSDimitry Andric     Constant *OverflowSize = ConstantInt::get(
59005ffd83dbSDimitry Andric         IRB.getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
59015ffd83dbSDimitry Andric     IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
59025ffd83dbSDimitry Andric   }
59035ffd83dbSDimitry Andric 
59045ffd83dbSDimitry Andric   void copyRegSaveArea(IRBuilder<> &IRB, Value *VAListTag) {
59055f757f3fSDimitry Andric     Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*
59065ffd83dbSDimitry Andric     Value *RegSaveAreaPtrPtr = IRB.CreateIntToPtr(
59075ffd83dbSDimitry Andric         IRB.CreateAdd(
59085ffd83dbSDimitry Andric             IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
59095ffd83dbSDimitry Andric             ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
59105ffd83dbSDimitry Andric         PointerType::get(RegSaveAreaPtrTy, 0));
59115ffd83dbSDimitry Andric     Value *RegSaveAreaPtr = IRB.CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
59125ffd83dbSDimitry Andric     Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
59135ffd83dbSDimitry Andric     const Align Alignment = Align(8);
59145ffd83dbSDimitry Andric     std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
59155ffd83dbSDimitry Andric         MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.getInt8Ty(), Alignment,
59165ffd83dbSDimitry Andric                                /*isStore*/ true);
59175ffd83dbSDimitry Andric     // TODO(iii): copy only fragments filled by visitCallBase()
591806c3fb27SDimitry Andric     // TODO(iii): support packed-stack && !use-soft-float
591906c3fb27SDimitry Andric     // For use-soft-float functions, it is enough to copy just the GPRs.
592006c3fb27SDimitry Andric     unsigned RegSaveAreaSize =
592106c3fb27SDimitry Andric         IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
59225ffd83dbSDimitry Andric     IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
592306c3fb27SDimitry Andric                      RegSaveAreaSize);
59245ffd83dbSDimitry Andric     if (MS.TrackOrigins)
59255ffd83dbSDimitry Andric       IRB.CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
592606c3fb27SDimitry Andric                        Alignment, RegSaveAreaSize);
59275ffd83dbSDimitry Andric   }
59285ffd83dbSDimitry Andric 
59295f757f3fSDimitry Andric   // FIXME: This implementation limits OverflowOffset to kParamTLSSize, so we
59305f757f3fSDimitry Andric   // don't know real overflow size and can't clear shadow beyond kParamTLSSize.
59315ffd83dbSDimitry Andric   void copyOverflowArea(IRBuilder<> &IRB, Value *VAListTag) {
59325f757f3fSDimitry Andric     Type *OverflowArgAreaPtrTy = PointerType::getUnqual(*MS.C); // i64*
59335ffd83dbSDimitry Andric     Value *OverflowArgAreaPtrPtr = IRB.CreateIntToPtr(
59345ffd83dbSDimitry Andric         IRB.CreateAdd(
59355ffd83dbSDimitry Andric             IRB.CreatePtrToInt(VAListTag, MS.IntptrTy),
59365ffd83dbSDimitry Andric             ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
59375ffd83dbSDimitry Andric         PointerType::get(OverflowArgAreaPtrTy, 0));
59385ffd83dbSDimitry Andric     Value *OverflowArgAreaPtr =
59395ffd83dbSDimitry Andric         IRB.CreateLoad(OverflowArgAreaPtrTy, OverflowArgAreaPtrPtr);
59405ffd83dbSDimitry Andric     Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
59415ffd83dbSDimitry Andric     const Align Alignment = Align(8);
59425ffd83dbSDimitry Andric     std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
59435ffd83dbSDimitry Andric         MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.getInt8Ty(),
59445ffd83dbSDimitry Andric                                Alignment, /*isStore*/ true);
59455ffd83dbSDimitry Andric     Value *SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSCopy,
59465ffd83dbSDimitry Andric                                            SystemZOverflowOffset);
59475ffd83dbSDimitry Andric     IRB.CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
59485ffd83dbSDimitry Andric                      VAArgOverflowSize);
59495ffd83dbSDimitry Andric     if (MS.TrackOrigins) {
59505ffd83dbSDimitry Andric       SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSOriginCopy,
59515ffd83dbSDimitry Andric                                       SystemZOverflowOffset);
59525ffd83dbSDimitry Andric       IRB.CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
59535ffd83dbSDimitry Andric                        VAArgOverflowSize);
59545ffd83dbSDimitry Andric     }
59555ffd83dbSDimitry Andric   }
59565ffd83dbSDimitry Andric 
59575ffd83dbSDimitry Andric   void finalizeInstrumentation() override {
59585ffd83dbSDimitry Andric     assert(!VAArgOverflowSize && !VAArgTLSCopy &&
59595ffd83dbSDimitry Andric            "finalizeInstrumentation called twice");
59605ffd83dbSDimitry Andric     if (!VAStartInstrumentationList.empty()) {
59615ffd83dbSDimitry Andric       // If there is a va_start in this function, make a backup copy of
59625ffd83dbSDimitry Andric       // va_arg_tls somewhere in the function entry block.
5963e8d8bef9SDimitry Andric       IRBuilder<> IRB(MSV.FnPrologueEnd);
59645ffd83dbSDimitry Andric       VAArgOverflowSize =
59655ffd83dbSDimitry Andric           IRB.CreateLoad(IRB.getInt64Ty(), MS.VAArgOverflowSizeTLS);
59665ffd83dbSDimitry Andric       Value *CopySize =
59675ffd83dbSDimitry Andric           IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
59685ffd83dbSDimitry Andric                         VAArgOverflowSize);
59695ffd83dbSDimitry Andric       VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
597006c3fb27SDimitry Andric       VAArgTLSCopy->setAlignment(kShadowTLSAlignment);
597106c3fb27SDimitry Andric       IRB.CreateMemSet(VAArgTLSCopy, Constant::getNullValue(IRB.getInt8Ty()),
597206c3fb27SDimitry Andric                        CopySize, kShadowTLSAlignment, false);
597306c3fb27SDimitry Andric 
597406c3fb27SDimitry Andric       Value *SrcSize = IRB.CreateBinaryIntrinsic(
597506c3fb27SDimitry Andric           Intrinsic::umin, CopySize,
597606c3fb27SDimitry Andric           ConstantInt::get(MS.IntptrTy, kParamTLSSize));
597706c3fb27SDimitry Andric       IRB.CreateMemCpy(VAArgTLSCopy, kShadowTLSAlignment, MS.VAArgTLS,
597806c3fb27SDimitry Andric                        kShadowTLSAlignment, SrcSize);
59795ffd83dbSDimitry Andric       if (MS.TrackOrigins) {
59805ffd83dbSDimitry Andric         VAArgTLSOriginCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
598106c3fb27SDimitry Andric         VAArgTLSOriginCopy->setAlignment(kShadowTLSAlignment);
598206c3fb27SDimitry Andric         IRB.CreateMemCpy(VAArgTLSOriginCopy, kShadowTLSAlignment,
598306c3fb27SDimitry Andric                          MS.VAArgOriginTLS, kShadowTLSAlignment, SrcSize);
59845ffd83dbSDimitry Andric       }
59855ffd83dbSDimitry Andric     }
59865ffd83dbSDimitry Andric 
59875ffd83dbSDimitry Andric     // Instrument va_start.
59885ffd83dbSDimitry Andric     // Copy va_list shadow from the backup copy of the TLS contents.
5989*0fca6ea1SDimitry Andric     for (CallInst *OrigInst : VAStartInstrumentationList) {
5990bdd1243dSDimitry Andric       NextNodeIRBuilder IRB(OrigInst);
59915ffd83dbSDimitry Andric       Value *VAListTag = OrigInst->getArgOperand(0);
59925ffd83dbSDimitry Andric       copyRegSaveArea(IRB, VAListTag);
59935ffd83dbSDimitry Andric       copyOverflowArea(IRB, VAListTag);
59945ffd83dbSDimitry Andric     }
59955ffd83dbSDimitry Andric   }
59965ffd83dbSDimitry Andric };
59975ffd83dbSDimitry Andric 
59985f757f3fSDimitry Andric // Loongarch64 is not a MIPS, but the current vargs calling convention matches
59995f757f3fSDimitry Andric // the MIPS.
60005f757f3fSDimitry Andric using VarArgLoongArch64Helper = VarArgMIPS64Helper;
60015f757f3fSDimitry Andric 
60020b57cec5SDimitry Andric /// A no-op implementation of VarArgHelper.
60030b57cec5SDimitry Andric struct VarArgNoOpHelper : public VarArgHelper {
60040b57cec5SDimitry Andric   VarArgNoOpHelper(Function &F, MemorySanitizer &MS,
60050b57cec5SDimitry Andric                    MemorySanitizerVisitor &MSV) {}
60060b57cec5SDimitry Andric 
60075ffd83dbSDimitry Andric   void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {}
60080b57cec5SDimitry Andric 
60090b57cec5SDimitry Andric   void visitVAStartInst(VAStartInst &I) override {}
60100b57cec5SDimitry Andric 
60110b57cec5SDimitry Andric   void visitVACopyInst(VACopyInst &I) override {}
60120b57cec5SDimitry Andric 
60130b57cec5SDimitry Andric   void finalizeInstrumentation() override {}
60140b57cec5SDimitry Andric };
60150b57cec5SDimitry Andric 
60160b57cec5SDimitry Andric } // end anonymous namespace
60170b57cec5SDimitry Andric 
60180b57cec5SDimitry Andric static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
60190b57cec5SDimitry Andric                                         MemorySanitizerVisitor &Visitor) {
60200b57cec5SDimitry Andric   // VarArg handling is only implemented on AMD64. False positives are possible
60210b57cec5SDimitry Andric   // on other platforms.
60220b57cec5SDimitry Andric   Triple TargetTriple(Func.getParent()->getTargetTriple());
60230b57cec5SDimitry Andric   if (TargetTriple.getArch() == Triple::x86_64)
60240b57cec5SDimitry Andric     return new VarArgAMD64Helper(Func, Msan, Visitor);
60250b57cec5SDimitry Andric   else if (TargetTriple.isMIPS64())
60260b57cec5SDimitry Andric     return new VarArgMIPS64Helper(Func, Msan, Visitor);
60270b57cec5SDimitry Andric   else if (TargetTriple.getArch() == Triple::aarch64)
60280b57cec5SDimitry Andric     return new VarArgAArch64Helper(Func, Msan, Visitor);
60290b57cec5SDimitry Andric   else if (TargetTriple.getArch() == Triple::ppc64 ||
60300b57cec5SDimitry Andric            TargetTriple.getArch() == Triple::ppc64le)
60310b57cec5SDimitry Andric     return new VarArgPowerPC64Helper(Func, Msan, Visitor);
60325ffd83dbSDimitry Andric   else if (TargetTriple.getArch() == Triple::systemz)
60335ffd83dbSDimitry Andric     return new VarArgSystemZHelper(Func, Msan, Visitor);
60345f757f3fSDimitry Andric   else if (TargetTriple.isLoongArch64())
60355f757f3fSDimitry Andric     return new VarArgLoongArch64Helper(Func, Msan, Visitor);
60360b57cec5SDimitry Andric   else
60370b57cec5SDimitry Andric     return new VarArgNoOpHelper(Func, Msan, Visitor);
60380b57cec5SDimitry Andric }
60390b57cec5SDimitry Andric 
60400b57cec5SDimitry Andric bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) {
60418bcb0991SDimitry Andric   if (!CompileKernel && F.getName() == kMsanModuleCtorName)
60420b57cec5SDimitry Andric     return false;
60438bcb0991SDimitry Andric 
6044349cc55cSDimitry Andric   if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
6045349cc55cSDimitry Andric     return false;
6046349cc55cSDimitry Andric 
60470b57cec5SDimitry Andric   MemorySanitizerVisitor Visitor(F, *this, TLI);
60480b57cec5SDimitry Andric 
6049bdd1243dSDimitry Andric   // Clear out memory attributes.
605004eeddc0SDimitry Andric   AttributeMask B;
6051bdd1243dSDimitry Andric   B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
6052349cc55cSDimitry Andric   F.removeFnAttrs(B);
60530b57cec5SDimitry Andric 
60540b57cec5SDimitry Andric   return Visitor.runOnFunction();
60550b57cec5SDimitry Andric }
6056