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:
MemorySanitizer(Module & M,MemorySanitizerOptions Options)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
insertModuleCtor(Module & M)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
getOptOrDefault(const cl::opt<T> & Opt,T Default)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
MemorySanitizerOptions(int TO,bool R,bool K,bool EagerChecks)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
run(Module & M,ModuleAnalysisManager & AM)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
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)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.
createPrivateConstGlobalForString(Module & M,StringRef Str)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
getOrInsertMsanMetadataFunction(Module & M,StringRef Name,ArgsTy...Args)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.
createKernelApi(Module & M,const TargetLibraryInfo & TLI)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
getOrInsertGlobal(Module & M,StringRef Name,Type * Ty)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.
createUserspaceApi(Module & M,const TargetLibraryInfo & TLI)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.
initializeCallbacks(Module & M,const TargetLibraryInfo & TLI)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
getKmsanShadowOriginAccessFn(bool isStore,int size)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.
initializeModule(Module & M)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
TypeSizeToSizeIndex(TypeSize TS)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:
NextNodeIRBuilder(Instruction * IP)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
ShadowOriginAndInsertPoint__anonb346f5430811::MemorySanitizerVisitor::ShadowOriginAndInsertPoint11550b57cec5SDimitry 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
MemorySanitizerVisitor__anonb346f5430811::MemorySanitizerVisitor11660b57cec5SDimitry 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
instrumentWithCalls__anonb346f5430811::MemorySanitizerVisitor1196bdd1243dSDimitry 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
isInPrologue__anonb346f5430811::MemorySanitizerVisitor1206e8d8bef9SDimitry 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.
updateOrigin__anonb346f5430811::MemorySanitizerVisitor12150b57cec5SDimitry 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
originToIntptr__anonb346f5430811::MemorySanitizerVisitor12210b57cec5SDimitry 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.
paintOrigin__anonb346f5430811::MemorySanitizerVisitor12320b57cec5SDimitry 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
storeOrigin__anonb346f5430811::MemorySanitizerVisitor12820b57cec5SDimitry 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
materializeStores__anonb346f5430811::MemorySanitizerVisitor1324bdd1243dSDimitry 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.
shouldDisambiguateWarningLocation__anonb346f5430811::MemorySanitizerVisitor1351bdd1243dSDimitry 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.
insertWarningFn__anonb346f5430811::MemorySanitizerVisitor13630b57cec5SDimitry 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
materializeOneCheck__anonb346f5430811::MemorySanitizerVisitor1395bdd1243dSDimitry 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
materializeInstructionChecks__anonb346f5430811::MemorySanitizerVisitor1424bdd1243dSDimitry 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
materializeChecks__anonb346f5430811::MemorySanitizerVisitor1476bdd1243dSDimitry 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
insertKmsanPrologue__anonb346f5430811::MemorySanitizerVisitor1501e8d8bef9SDimitry 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.
runOnFunction__anonb346f5430811::MemorySanitizerVisitor15250b57cec5SDimitry 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.
getShadowTy__anonb346f5430811::MemorySanitizerVisitor1575bdd1243dSDimitry Andric Type *getShadowTy(Value *V) { return getShadowTy(V->getType()); }
15760b57cec5SDimitry Andric
15770b57cec5SDimitry Andric /// Compute the shadow type that corresponds to a given Type.
getShadowTy__anonb346f5430811::MemorySanitizerVisitor15780b57cec5SDimitry 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
collapseStructShadow__anonb346f5430811::MemorySanitizerVisitor1609e8d8bef9SDimitry 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
collapseArrayShadow__anonb346f5430811::MemorySanitizerVisitor1629e8d8bef9SDimitry 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.
convertShadowToScalar__anonb346f5430811::MemorySanitizerVisitor1648e8d8bef9SDimitry 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
convertToBool__anonb346f5430811::MemorySanitizerVisitor1664e8d8bef9SDimitry 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
ptrToIntPtrType__anonb346f5430811::MemorySanitizerVisitor1674bdd1243dSDimitry 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
getPtrToShadowPtrType__anonb346f5430811::MemorySanitizerVisitor1683bdd1243dSDimitry 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
constToIntPtr__anonb346f5430811::MemorySanitizerVisitor1693bdd1243dSDimitry 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>>.
getShadowPtrOffset__anonb346f5430811::MemorySanitizerVisitor17090b57cec5SDimitry 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 *>
getShadowOriginPtrUserspace__anonb346f5430811::MemorySanitizerVisitor1730480093f4SDimitry 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>
createMetadataCall__anonb346f5430811::MemorySanitizerVisitor176606c3fb27SDimitry 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
getShadowOriginPtrKernelNoVec__anonb346f5430811::MemorySanitizerVisitor1777bdd1243dSDimitry 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>>.
getShadowOriginPtrKernel__anonb346f5430811::MemorySanitizerVisitor1807bdd1243dSDimitry 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
getShadowOriginPtr__anonb346f5430811::MemorySanitizerVisitor18400b57cec5SDimitry 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.
getShadowPtrForArgument__anonb346f5430811::MemorySanitizerVisitor18525f757f3fSDimitry 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.
getOriginPtrForArgument__anonb346f5430811::MemorySanitizerVisitor18605f757f3fSDimitry 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.
getShadowPtrForRetval__anonb346f5430811::MemorySanitizerVisitor18705f757f3fSDimitry 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.
getOriginPtrForRetval__anonb346f5430811::MemorySanitizerVisitor18755f757f3fSDimitry 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.
setShadow__anonb346f5430811::MemorySanitizerVisitor18810b57cec5SDimitry 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.
setOrigin__anonb346f5430811::MemorySanitizerVisitor18870b57cec5SDimitry 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
getCleanShadow__anonb346f5430811::MemorySanitizerVisitor18950b57cec5SDimitry 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).
getCleanShadow__anonb346f5430811::MemorySanitizerVisitor1906bdd1243dSDimitry Andric Constant *getCleanShadow(Value *V) { return getCleanShadow(V->getType()); }
19070b57cec5SDimitry Andric
19080b57cec5SDimitry Andric /// Create a dirty shadow of a given shadow type.
getPoisonedShadow__anonb346f5430811::MemorySanitizerVisitor19090b57cec5SDimitry 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.
getPoisonedShadow__anonb346f5430811::MemorySanitizerVisitor19280b57cec5SDimitry 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.
getCleanOrigin__anonb346f5430811::MemorySanitizerVisitor1936bdd1243dSDimitry 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).
getShadow__anonb346f5430811::MemorySanitizerVisitor19420b57cec5SDimitry 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.
getShadow__anonb346f5430811::MemorySanitizerVisitor20580b57cec5SDimitry 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.
getOrigin__anonb346f5430811::MemorySanitizerVisitor20630b57cec5SDimitry 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.
getOrigin__anonb346f5430811::MemorySanitizerVisitor20800b57cec5SDimitry 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.
insertShadowCheck__anonb346f5430811::MemorySanitizerVisitor20880b57cec5SDimitry 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.
insertShadowCheck__anonb346f5430811::MemorySanitizerVisitor21130b57cec5SDimitry 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
addReleaseOrdering__anonb346f5430811::MemorySanitizerVisitor21300b57cec5SDimitry 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
makeAddReleaseOrderingTable__anonb346f5430811::MemorySanitizerVisitor2147e8d8bef9SDimitry 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
addAcquireOrdering__anonb346f5430811::MemorySanitizerVisitor21640b57cec5SDimitry 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
makeAddAcquireOrderingTable__anonb346f5430811::MemorySanitizerVisitor2181e8d8bef9SDimitry 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;
visit__anonb346f5430811::MemorySanitizerVisitor22000b57cec5SDimitry 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.
visitLoadInst__anonb346f5430811::MemorySanitizerVisitor22210b57cec5SDimitry 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.
visitStoreInst__anonb346f5430811::MemorySanitizerVisitor22590b57cec5SDimitry 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
handleCASOrRMW__anonb346f5430811::MemorySanitizerVisitor22650b57cec5SDimitry 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
visitAtomicRMWInst__anonb346f5430811::MemorySanitizerVisitor22900b57cec5SDimitry Andric void visitAtomicRMWInst(AtomicRMWInst &I) {
22910b57cec5SDimitry Andric handleCASOrRMW(I);
22920b57cec5SDimitry Andric I.setOrdering(addReleaseOrdering(I.getOrdering()));
22930b57cec5SDimitry Andric }
22940b57cec5SDimitry Andric
visitAtomicCmpXchgInst__anonb346f5430811::MemorySanitizerVisitor22950b57cec5SDimitry Andric void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
22960b57cec5SDimitry Andric handleCASOrRMW(I);
22970b57cec5SDimitry Andric I.setSuccessOrdering(addReleaseOrdering(I.getSuccessOrdering()));
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric
23000b57cec5SDimitry Andric // Vector manipulation.
visitExtractElementInst__anonb346f5430811::MemorySanitizerVisitor23010b57cec5SDimitry 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
visitInsertElementInst__anonb346f5430811::MemorySanitizerVisitor23090b57cec5SDimitry 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
visitShuffleVectorInst__anonb346f5430811::MemorySanitizerVisitor23190b57cec5SDimitry 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.
visitSExtInst__anonb346f5430811::MemorySanitizerVisitor23290b57cec5SDimitry 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
visitZExtInst__anonb346f5430811::MemorySanitizerVisitor23350b57cec5SDimitry 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
visitTruncInst__anonb346f5430811::MemorySanitizerVisitor23410b57cec5SDimitry 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
visitBitCastInst__anonb346f5430811::MemorySanitizerVisitor23470b57cec5SDimitry 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
visitPtrToIntInst__anonb346f5430811::MemorySanitizerVisitor23590b57cec5SDimitry 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
visitIntToPtrInst__anonb346f5430811::MemorySanitizerVisitor23660b57cec5SDimitry 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
visitFPToSIInst__anonb346f5430811::MemorySanitizerVisitor23730b57cec5SDimitry Andric void visitFPToSIInst(CastInst &I) { handleShadowOr(I); }
visitFPToUIInst__anonb346f5430811::MemorySanitizerVisitor23740b57cec5SDimitry Andric void visitFPToUIInst(CastInst &I) { handleShadowOr(I); }
visitSIToFPInst__anonb346f5430811::MemorySanitizerVisitor23750b57cec5SDimitry Andric void visitSIToFPInst(CastInst &I) { handleShadowOr(I); }
visitUIToFPInst__anonb346f5430811::MemorySanitizerVisitor23760b57cec5SDimitry Andric void visitUIToFPInst(CastInst &I) { handleShadowOr(I); }
visitFPExtInst__anonb346f5430811::MemorySanitizerVisitor23770b57cec5SDimitry Andric void visitFPExtInst(CastInst &I) { handleShadowOr(I); }
visitFPTruncInst__anonb346f5430811::MemorySanitizerVisitor23780b57cec5SDimitry 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.
visitAnd__anonb346f5430811::MemorySanitizerVisitor23850b57cec5SDimitry 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
visitOr__anonb346f5430811::MemorySanitizerVisitor24070b57cec5SDimitry 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:
Combiner(MemorySanitizerVisitor * MSV,IRBuilder<> & IRB)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.
Add(Value * OpShadow,Value * OpOrigin)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.
Add(Value * V)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.
Done(Instruction * I)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.
DoneAndStoreOrigin(TypeSize TS,Value * OriginPtr)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.
setOriginForNaryOp__anonb346f5430811::MemorySanitizerVisitor25170b57cec5SDimitry 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
VectorOrPrimitiveTypeSizeInBits__anonb346f5430811::MemorySanitizerVisitor25270b57cec5SDimitry 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.
CreateShadowCast__anonb346f5430811::MemorySanitizerVisitor25370b57cec5SDimitry 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.
CreateAppToShadowCast__anonb346f5430811::MemorySanitizerVisitor25610b57cec5SDimitry 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.
handleShadowOr__anonb346f5430811::MemorySanitizerVisitor25720b57cec5SDimitry 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
visitFNeg__anonb346f5430811::MemorySanitizerVisitor25800b57cec5SDimitry 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.
handleMulByConstant__anonb346f5430811::MemorySanitizerVisitor25910b57cec5SDimitry 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
visitMul__anonb346f5430811::MemorySanitizerVisitor26260b57cec5SDimitry 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
visitFAdd__anonb346f5430811::MemorySanitizerVisitor26370b57cec5SDimitry Andric void visitFAdd(BinaryOperator &I) { handleShadowOr(I); }
visitFSub__anonb346f5430811::MemorySanitizerVisitor26380b57cec5SDimitry Andric void visitFSub(BinaryOperator &I) { handleShadowOr(I); }
visitFMul__anonb346f5430811::MemorySanitizerVisitor26390b57cec5SDimitry Andric void visitFMul(BinaryOperator &I) { handleShadowOr(I); }
visitAdd__anonb346f5430811::MemorySanitizerVisitor26400b57cec5SDimitry Andric void visitAdd(BinaryOperator &I) { handleShadowOr(I); }
visitSub__anonb346f5430811::MemorySanitizerVisitor26410b57cec5SDimitry Andric void visitSub(BinaryOperator &I) { handleShadowOr(I); }
visitXor__anonb346f5430811::MemorySanitizerVisitor26420b57cec5SDimitry Andric void visitXor(BinaryOperator &I) { handleShadowOr(I); }
26430b57cec5SDimitry Andric
handleIntegerDiv__anonb346f5430811::MemorySanitizerVisitor26440b57cec5SDimitry 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
visitUDiv__anonb346f5430811::MemorySanitizerVisitor26520b57cec5SDimitry Andric void visitUDiv(BinaryOperator &I) { handleIntegerDiv(I); }
visitSDiv__anonb346f5430811::MemorySanitizerVisitor26530b57cec5SDimitry Andric void visitSDiv(BinaryOperator &I) { handleIntegerDiv(I); }
visitURem__anonb346f5430811::MemorySanitizerVisitor26540b57cec5SDimitry Andric void visitURem(BinaryOperator &I) { handleIntegerDiv(I); }
visitSRem__anonb346f5430811::MemorySanitizerVisitor26550b57cec5SDimitry 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.
visitFDiv__anonb346f5430811::MemorySanitizerVisitor26590b57cec5SDimitry Andric void visitFDiv(BinaryOperator &I) { handleShadowOr(I); }
visitFRem__anonb346f5430811::MemorySanitizerVisitor26600b57cec5SDimitry 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.
handleEqualityComparison__anonb346f5430811::MemorySanitizerVisitor26660b57cec5SDimitry 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.
getLowestPossibleValue__anonb346f5430811::MemorySanitizerVisitor27020b57cec5SDimitry 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.
getHighestPossibleValue__anonb346f5430811::MemorySanitizerVisitor27190b57cec5SDimitry 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
handleRelationalComparisonExact__anonb346f5430811::MemorySanitizerVisitor27390b57cec5SDimitry 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().
handleSignedRelationalComparison__anonb346f5430811::MemorySanitizerVisitor27710b57cec5SDimitry 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
visitICmpInst__anonb346f5430811::MemorySanitizerVisitor28000b57cec5SDimitry 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
visitFCmpInst__anonb346f5430811::MemorySanitizerVisitor2829bdd1243dSDimitry Andric void visitFCmpInst(FCmpInst &I) { handleShadowOr(I); }
28300b57cec5SDimitry Andric
handleShift__anonb346f5430811::MemorySanitizerVisitor28310b57cec5SDimitry 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
visitShl__anonb346f5430811::MemorySanitizerVisitor28450b57cec5SDimitry Andric void visitShl(BinaryOperator &I) { handleShift(I); }
visitAShr__anonb346f5430811::MemorySanitizerVisitor28460b57cec5SDimitry Andric void visitAShr(BinaryOperator &I) { handleShift(I); }
visitLShr__anonb346f5430811::MemorySanitizerVisitor28470b57cec5SDimitry Andric void visitLShr(BinaryOperator &I) { handleShift(I); }
28480b57cec5SDimitry Andric
handleFunnelShift__anonb346f5430811::MemorySanitizerVisitor2849fe6060f1SDimitry 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.
visitMemMoveInst__anonb346f5430811::MemorySanitizerVisitor28760b57cec5SDimitry 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.
visitMemCpyInst__anonb346f5430811::MemorySanitizerVisitor28990b57cec5SDimitry 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.
visitMemSetInst__anonb346f5430811::MemorySanitizerVisitor29090b57cec5SDimitry 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
visitVAStartInst__anonb346f5430811::MemorySanitizerVisitor2919bdd1243dSDimitry Andric void visitVAStartInst(VAStartInst &I) { VAHelper->visitVAStartInst(I); }
29200b57cec5SDimitry Andric
visitVACopyInst__anonb346f5430811::MemorySanitizerVisitor2921bdd1243dSDimitry 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.
handleVectorStoreIntrinsic__anonb346f5430811::MemorySanitizerVisitor29270b57cec5SDimitry 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.
handleVectorLoadIntrinsic__anonb346f5430811::MemorySanitizerVisitor29520b57cec5SDimitry 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.
maybeHandleSimpleNomemIntrinsic__anonb346f5430811::MemorySanitizerVisitor29880b57cec5SDimitry 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.
handleUnknownIntrinsic__anonb346f5430811::MemorySanitizerVisitor30200b57cec5SDimitry 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
handleInvariantGroup__anonb346f5430811::MemorySanitizerVisitor30468bcb0991SDimitry Andric void handleInvariantGroup(IntrinsicInst &I) {
30478bcb0991SDimitry Andric setShadow(&I, getShadow(&I, 0));
30488bcb0991SDimitry Andric setOrigin(&I, getOrigin(&I, 0));
30498bcb0991SDimitry Andric }
30508bcb0991SDimitry Andric
handleLifetimeStart__anonb346f5430811::MemorySanitizerVisitor30510b57cec5SDimitry 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
handleBswap__anonb346f5430811::MemorySanitizerVisitor30600b57cec5SDimitry 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
handleCountZeroes__anonb346f5430811::MemorySanitizerVisitor3070bdd1243dSDimitry 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.
handleVectorConvertIntrinsic__anonb346f5430811::MemorySanitizerVisitor3106e8d8bef9SDimitry 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.
Lower64ShadowExtend__anonb346f5430811::MemorySanitizerVisitor31730b57cec5SDimitry 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.
LowerElementShadowExtend__anonb346f5430811::MemorySanitizerVisitor31830b57cec5SDimitry 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
VariableShadowExtend__anonb346f5430811::MemorySanitizerVisitor31890b57cec5SDimitry 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.
handleVectorShiftIntrinsic__anonb346f5430811::MemorySanitizerVisitor32030b57cec5SDimitry 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.
getMMXVectorTy__anonb346f5430811::MemorySanitizerVisitor32220b57cec5SDimitry 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.
getSignedPackIntrinsic__anonb346f5430811::MemorySanitizerVisitor32320b57cec5SDimitry 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.
handleVectorPackIntrinsic__anonb346f5430811::MemorySanitizerVisitor32680b57cec5SDimitry 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>`.
createDppMask__anonb346f5430811::MemorySanitizerVisitor3306*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.
findDppPoisonedOutput__anonb346f5430811::MemorySanitizerVisitor3317*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.
handleDppIntrinsic__anonb346f5430811::MemorySanitizerVisitor3343*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
convertBlendvToSelectMask__anonb346f5430811::MemorySanitizerVisitor3374*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)`.
handleBlendvIntrinsic__anonb346f5430811::MemorySanitizerVisitor3384*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.
handleVectorSadIntrinsic__anonb346f5430811::MemorySanitizerVisitor34060b57cec5SDimitry 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.
handleVectorPmaddIntrinsic__anonb346f5430811::MemorySanitizerVisitor34270b57cec5SDimitry 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.
handleVectorComparePackedIntrinsic__anonb346f5430811::MemorySanitizerVisitor34460b57cec5SDimitry 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.
handleVectorCompareScalarIntrinsic__anonb346f5430811::MemorySanitizerVisitor34610b57cec5SDimitry 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.
handleVectorReduceIntrinsic__anonb346f5430811::MemorySanitizerVisitor34735ffd83dbSDimitry 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.
handleVectorReduceOrIntrinsic__anonb346f5430811::MemorySanitizerVisitor34835ffd83dbSDimitry 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.
handleVectorReduceAndIntrinsic__anonb346f5430811::MemorySanitizerVisitor35015ffd83dbSDimitry 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
handleStmxcsr__anonb346f5430811::MemorySanitizerVisitor35150b57cec5SDimitry 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
handleLdmxcsr__anonb346f5430811::MemorySanitizerVisitor35280b57cec5SDimitry 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
handleMaskedExpandLoad__anonb346f5430811::MemorySanitizerVisitor3549bdd1243dSDimitry 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
handleMaskedCompressStore__anonb346f5430811::MemorySanitizerVisitor3580bdd1243dSDimitry 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
handleMaskedGather__anonb346f5430811::MemorySanitizerVisitor3602bdd1243dSDimitry 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
handleMaskedScatter__anonb346f5430811::MemorySanitizerVisitor3640bdd1243dSDimitry 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
handleMaskedStore__anonb346f5430811::MemorySanitizerVisitor3668bdd1243dSDimitry 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
handleMaskedLoad__anonb346f5430811::MemorySanitizerVisitor3698bdd1243dSDimitry 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))
handleBmiIntrinsic__anonb346f5430811::MemorySanitizerVisitor37440b57cec5SDimitry 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
getPclmulMask__anonb346f5430811::MemorySanitizerVisitor3760*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.
handlePclmulIntrinsic__anonb346f5430811::MemorySanitizerVisitor377613138422SDimitry 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
handleUnarySdSsIntrinsic__anonb346f5430811::MemorySanitizerVisitor379481ad6265SDimitry 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
handleVtestIntrinsic__anonb346f5430811::MemorySanitizerVisitor3811bdd1243dSDimitry 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
handleBinarySdSsIntrinsic__anonb346f5430811::MemorySanitizerVisitor382481ad6265SDimitry 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.
handleAbsIntrinsic__anonb346f5430811::MemorySanitizerVisitor3845e8d8bef9SDimitry 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
handleIsFpClass__anonb346f5430811::MemorySanitizerVisitor385506c3fb27SDimitry 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
handleArithmeticWithOverflow__anonb346f5430811::MemorySanitizerVisitor3862*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.
handleNEONVectorStoreIntrinsic__anonb346f5430811::MemorySanitizerVisitor3883*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
visitIntrinsicInst__anonb346f5430811::MemorySanitizerVisitor39410b57cec5SDimitry 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
visitLibAtomicLoad__anonb346f5430811::MemorySanitizerVisitor4294e8d8bef9SDimitry 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
visitLibAtomicStore__anonb346f5430811::MemorySanitizerVisitor4328e8d8bef9SDimitry 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
visitCallBase__anonb346f5430811::MemorySanitizerVisitor43495ffd83dbSDimitry 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
isAMustTailRetVal__anonb346f5430811::MemorySanitizerVisitor45550b57cec5SDimitry 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
visitReturnInst__anonb346f5430811::MemorySanitizerVisitor45650b57cec5SDimitry 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
visitPHINode__anonb346f5430811::MemorySanitizerVisitor45970b57cec5SDimitry 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
getLocalVarIdptr__anonb346f5430811::MemorySanitizerVisitor4613bdd1243dSDimitry 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
getLocalVarDescription__anonb346f5430811::MemorySanitizerVisitor46210b57cec5SDimitry Andric Value *getLocalVarDescription(AllocaInst &I) {
4622bdd1243dSDimitry Andric return createPrivateConstGlobalForString(*F.getParent(), I.getName());
46230b57cec5SDimitry Andric }
46240b57cec5SDimitry Andric
poisonAllocaUserspace__anonb346f5430811::MemorySanitizerVisitor46250b57cec5SDimitry 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
poisonAllocaKmsan__anonb346f5430811::MemorySanitizerVisitor46490b57cec5SDimitry 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
instrumentAlloca__anonb346f5430811::MemorySanitizerVisitor46580b57cec5SDimitry 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
visitAllocaInst__anonb346f5430811::MemorySanitizerVisitor46750b57cec5SDimitry 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
visitSelectInst__anonb346f5430811::MemorySanitizerVisitor46830b57cec5SDimitry 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
handleSelectLikeInst__anonb346f5430811::MemorySanitizerVisitor4692*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
visitLandingPadInst__anonb346f5430811::MemorySanitizerVisitor47390b57cec5SDimitry 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
visitCatchSwitchInst__anonb346f5430811::MemorySanitizerVisitor47460b57cec5SDimitry Andric void visitCatchSwitchInst(CatchSwitchInst &I) {
47470b57cec5SDimitry Andric setShadow(&I, getCleanShadow(&I));
47480b57cec5SDimitry Andric setOrigin(&I, getCleanOrigin());
47490b57cec5SDimitry Andric }
47500b57cec5SDimitry Andric
visitFuncletPadInst__anonb346f5430811::MemorySanitizerVisitor47510b57cec5SDimitry Andric void visitFuncletPadInst(FuncletPadInst &I) {
47520b57cec5SDimitry Andric setShadow(&I, getCleanShadow(&I));
47530b57cec5SDimitry Andric setOrigin(&I, getCleanOrigin());
47540b57cec5SDimitry Andric }
47550b57cec5SDimitry Andric
visitGetElementPtrInst__anonb346f5430811::MemorySanitizerVisitor4756bdd1243dSDimitry Andric void visitGetElementPtrInst(GetElementPtrInst &I) { handleShadowOr(I); }
47570b57cec5SDimitry Andric
visitExtractValueInst__anonb346f5430811::MemorySanitizerVisitor47580b57cec5SDimitry 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
visitInsertValueInst__anonb346f5430811::MemorySanitizerVisitor47700b57cec5SDimitry 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
dumpInst__anonb346f5430811::MemorySanitizerVisitor47830b57cec5SDimitry 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
visitResumeInst__anonb346f5430811::MemorySanitizerVisitor47920b57cec5SDimitry Andric void visitResumeInst(ResumeInst &I) {
47930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Resume: " << I << "\n");
47940b57cec5SDimitry Andric // Nothing to do here.
47950b57cec5SDimitry Andric }
47960b57cec5SDimitry Andric
visitCleanupReturnInst__anonb346f5430811::MemorySanitizerVisitor47970b57cec5SDimitry Andric void visitCleanupReturnInst(CleanupReturnInst &CRI) {
47980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "CleanupReturn: " << CRI << "\n");
47990b57cec5SDimitry Andric // Nothing to do here.
48000b57cec5SDimitry Andric }
48010b57cec5SDimitry Andric
visitCatchReturnInst__anonb346f5430811::MemorySanitizerVisitor48020b57cec5SDimitry Andric void visitCatchReturnInst(CatchReturnInst &CRI) {
48030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "CatchReturn: " << CRI << "\n");
48040b57cec5SDimitry Andric // Nothing to do here.
48050b57cec5SDimitry Andric }
48060b57cec5SDimitry Andric
instrumentAsmArgument__anonb346f5430811::MemorySanitizerVisitor480781ad6265SDimitry 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.
getNumOutputArgs__anonb346f5430811::MemorySanitizerVisitor48430b57cec5SDimitry 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
visitAsmInstruction__anonb346f5430811::MemorySanitizerVisitor48680b57cec5SDimitry 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
visitFreezeInst__anonb346f5430811::MemorySanitizerVisitor4912e8d8bef9SDimitry 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
visitInstruction__anonb346f5430811::MemorySanitizerVisitor49180b57cec5SDimitry 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
VarArgHelperBase__anonb346f5430811::VarArgHelperBase49405f757f3fSDimitry Andric VarArgHelperBase(Function &F, MemorySanitizer &MS,
49415f757f3fSDimitry Andric MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
49425f757f3fSDimitry Andric : F(F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
49435f757f3fSDimitry Andric
getShadowAddrForVAArgument__anonb346f5430811::VarArgHelperBase49445f757f3fSDimitry 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.
getShadowPtrForVAArgument__anonb346f5430811::VarArgHelperBase49505f757f3fSDimitry 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.
getShadowPtrForVAArgument__anonb346f5430811::VarArgHelperBase49595f757f3fSDimitry 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.
getOriginPtrForVAArgument__anonb346f5430811::VarArgHelperBase49685f757f3fSDimitry 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
CleanUnusedTLS__anonb346f5430811::VarArgHelperBase49785f757f3fSDimitry 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
unpoisonVAListTagForInst__anonb346f5430811::VarArgHelperBase49915f757f3fSDimitry 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
visitVAStartInst__anonb346f5430811::VarArgHelperBase50025f757f3fSDimitry 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
visitVACopyInst__anonb346f5430811::VarArgHelperBase50095f757f3fSDimitry 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
VarArgAMD64Helper__anonb346f5430811::VarArgAMD64Helper50320b57cec5SDimitry 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
classifyArgument__anonb346f5430811::VarArgAMD64Helper50460b57cec5SDimitry 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.
visitCallBase__anonb346f5430811::VarArgAMD64Helper50685ffd83dbSDimitry 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
finalizeInstrumentation__anonb346f5430811::VarArgAMD64Helper51690b57cec5SDimitry 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
VarArgMIPS64Helper__anonb346f5430811::VarArgMIPS64Helper52520b57cec5SDimitry Andric VarArgMIPS64Helper(Function &F, MemorySanitizer &MS,
5253bdd1243dSDimitry Andric MemorySanitizerVisitor &MSV)
52545f757f3fSDimitry Andric : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/8) {}
52550b57cec5SDimitry Andric
visitCallBase__anonb346f5430811::VarArgMIPS64Helper52565ffd83dbSDimitry 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
finalizeInstrumentation__anonb346f5430811::VarArgMIPS64Helper52840b57cec5SDimitry 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
VarArgAArch64Helper__anonb346f5430811::VarArgAArch64Helper53470b57cec5SDimitry 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.
classifyArgument__anonb346f5430811::VarArgAArch64Helper53525f757f3fSDimitry 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.
visitCallBase__anonb346f5430811::VarArgAArch64Helper53835ffd83dbSDimitry 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.
getVAField64__anonb346f5430811::VarArgAArch64Helper54370b57cec5SDimitry 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.
getVAField32__anonb346f5430811::VarArgAArch64Helper54460b57cec5SDimitry 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
finalizeInstrumentation__anonb346f5430811::VarArgAArch64Helper54550b57cec5SDimitry 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
VarArgPowerPC64Helper__anonb346f5430811::VarArgPowerPC64Helper55770b57cec5SDimitry Andric VarArgPowerPC64Helper(Function &F, MemorySanitizer &MS,
5578bdd1243dSDimitry Andric MemorySanitizerVisitor &MSV)
55795f757f3fSDimitry Andric : VarArgHelperBase(F, MS, MSV, /*VAListTagSize=*/8) {}
55800b57cec5SDimitry Andric
visitCallBase__anonb346f5430811::VarArgPowerPC64Helper55815ffd83dbSDimitry 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
finalizeInstrumentation__anonb346f5430811::VarArgPowerPC64Helper56670b57cec5SDimitry 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
VarArgSystemZHelper__anonb346f5430811::VarArgSystemZHelper57415ffd83dbSDimitry 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
classifyArgument__anonb346f5430811::VarArgSystemZHelper574606c3fb27SDimitry 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
getShadowExtension__anonb346f5430811::VarArgSystemZHelper57645ffd83dbSDimitry 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
visitCallBase__anonb346f5430811::VarArgSystemZHelper57835ffd83dbSDimitry 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
copyRegSaveArea__anonb346f5430811::VarArgSystemZHelper59045ffd83dbSDimitry 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.
copyOverflowArea__anonb346f5430811::VarArgSystemZHelper59315ffd83dbSDimitry 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
finalizeInstrumentation__anonb346f5430811::VarArgSystemZHelper59575ffd83dbSDimitry 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 {
VarArgNoOpHelper__anonb346f5430811::VarArgNoOpHelper60040b57cec5SDimitry Andric VarArgNoOpHelper(Function &F, MemorySanitizer &MS,
60050b57cec5SDimitry Andric MemorySanitizerVisitor &MSV) {}
60060b57cec5SDimitry Andric
visitCallBase__anonb346f5430811::VarArgNoOpHelper60075ffd83dbSDimitry Andric void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {}
60080b57cec5SDimitry Andric
visitVAStartInst__anonb346f5430811::VarArgNoOpHelper60090b57cec5SDimitry Andric void visitVAStartInst(VAStartInst &I) override {}
60100b57cec5SDimitry Andric
visitVACopyInst__anonb346f5430811::VarArgNoOpHelper60110b57cec5SDimitry Andric void visitVACopyInst(VACopyInst &I) override {}
60120b57cec5SDimitry Andric
finalizeInstrumentation__anonb346f5430811::VarArgNoOpHelper60130b57cec5SDimitry Andric void finalizeInstrumentation() override {}
60140b57cec5SDimitry Andric };
60150b57cec5SDimitry Andric
60160b57cec5SDimitry Andric } // end anonymous namespace
60170b57cec5SDimitry Andric
CreateVarArgHelper(Function & Func,MemorySanitizer & Msan,MemorySanitizerVisitor & Visitor)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
sanitizeFunction(Function & F,TargetLibraryInfo & TLI)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