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