184#include "llvm/IR/IntrinsicsAArch64.h"
185#include "llvm/IR/IntrinsicsX86.h"
216#define DEBUG_TYPE "msan"
219 "Controls which checks to insert");
222 "Controls which instruction to instrument");
241 "msan-track-origins",
246 cl::desc(
"keep going after reporting a UMR"),
255 "msan-poison-stack-with-call",
260 "msan-poison-stack-pattern",
261 cl::desc(
"poison uninitialized stack variables with the given pattern"),
266 cl::desc(
"Print name of local stack variable"),
271 cl::desc(
"Poison fully undef temporary values. "
272 "Partially undefined constant vectors "
273 "are unaffected by this flag (see "
274 "-msan-poison-undef-vectors)."),
278 "msan-poison-undef-vectors",
279 cl::desc(
"Precisely poison partially undefined constant vectors. "
280 "If false (legacy behavior), the entire vector is "
281 "considered fully initialized, which may lead to false "
282 "negatives. Fully undefined constant vectors are "
283 "unaffected by this flag (see -msan-poison-undef)."),
287 "msan-precise-disjoint-or",
288 cl::desc(
"Precisely poison disjoint OR. If false (legacy behavior), "
289 "disjointedness is ignored (i.e., 1|1 is initialized)."),
294 cl::desc(
"propagate shadow through ICmpEQ and ICmpNE"),
299 cl::desc(
"exact handling of relational integer ICmp"),
303 "msan-switch-precision",
304 cl::desc(
"Controls the number of cases considered by MSan for LLVM switch "
305 "instructions. 0 means no UUMs detected. Higher values lead to "
306 "fewer false negatives but may impact compiler and/or "
307 "application performance. N.B. LLVM switch instructions do not "
308 "correspond exactly to C++ switch statements."),
312 "msan-handle-lifetime-intrinsics",
314 "when possible, poison scoped variables at the beginning of the scope "
315 "(slower, but more precise)"),
326 "msan-handle-asm-conservative",
337 "msan-check-access-address",
338 cl::desc(
"report accesses through a pointer which has poisoned shadow"),
343 cl::desc(
"check arguments and return values at function call boundaries"),
347 "msan-dump-strict-instructions",
348 cl::desc(
"print out instructions with default strict semantics i.e.,"
349 "check that all the inputs are fully initialized, and mark "
350 "the output as fully initialized. These semantics are applied "
351 "to instructions that could not be handled explicitly nor "
360 "msan-dump-heuristic-instructions",
361 cl::desc(
"Prints 'unknown' instructions that were handled heuristically. "
362 "Use -msan-dump-strict-instructions to print instructions that "
363 "could not be handled explicitly nor heuristically."),
367 "msan-instrumentation-with-call-threshold",
369 "If the function being instrumented requires more than "
370 "this number of checks and origin stores, use callbacks instead of "
371 "inline checks (-1 means never use callbacks)."),
376 cl::desc(
"Enable KernelMemorySanitizer instrumentation"),
386 cl::desc(
"Insert checks for constant shadow values"),
393 cl::desc(
"Place MSan constructors in comdat sections"),
399 cl::desc(
"Define custom MSan AndMask"),
403 cl::desc(
"Define custom MSan XorMask"),
407 cl::desc(
"Define custom MSan ShadowBase"),
411 cl::desc(
"Define custom MSan OriginBase"),
416 cl::desc(
"Define threshold for number of checks per "
417 "debug location to force origin update."),
429struct MemoryMapParams {
436struct PlatformMemoryMapParams {
437 const MemoryMapParams *bits32;
438 const MemoryMapParams *bits64;
615class MemorySanitizer {
624 MemorySanitizer(MemorySanitizer &&) =
delete;
625 MemorySanitizer &operator=(MemorySanitizer &&) =
delete;
626 MemorySanitizer(
const MemorySanitizer &) =
delete;
627 MemorySanitizer &operator=(
const MemorySanitizer &) =
delete;
629 bool sanitizeFunction(Function &
F, TargetLibraryInfo &TLI);
632 friend struct MemorySanitizerVisitor;
633 friend struct VarArgHelperBase;
634 friend struct VarArgAMD64Helper;
635 friend struct VarArgAArch64Helper;
636 friend struct VarArgPowerPC64Helper;
637 friend struct VarArgPowerPC32Helper;
638 friend struct VarArgSystemZHelper;
639 friend struct VarArgI386Helper;
640 friend struct VarArgGenericHelper;
642 void initializeModule(
Module &M);
643 void initializeCallbacks(
Module &M,
const TargetLibraryInfo &TLI);
644 void createKernelApi(
Module &M,
const TargetLibraryInfo &TLI);
645 void createUserspaceApi(
Module &M,
const TargetLibraryInfo &TLI);
647 template <
typename... ArgsTy>
648 FunctionCallee getOrInsertMsanMetadataFunction(
Module &M, StringRef Name,
674 Value *ParamOriginTLS;
680 Value *RetvalOriginTLS;
686 Value *VAArgOriginTLS;
689 Value *VAArgOverflowSizeTLS;
692 bool CallbacksInitialized =
false;
695 FunctionCallee WarningFn;
699 FunctionCallee MaybeWarningVarSizeFn;
704 FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
706 FunctionCallee MsanSetAllocaOriginNoDescriptionFn;
709 FunctionCallee MsanPoisonStackFn;
713 FunctionCallee MsanChainOriginFn;
716 FunctionCallee MsanSetOriginFn;
719 FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
722 StructType *MsanContextStateTy;
723 FunctionCallee MsanGetContextStateFn;
726 FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;
732 FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;
733 FunctionCallee MsanMetadataPtrForLoad_1_8[4];
734 FunctionCallee MsanMetadataPtrForStore_1_8[4];
735 FunctionCallee MsanInstrumentAsmStoreFn;
738 Value *MsanMetadataAlloca;
741 FunctionCallee getKmsanShadowOriginAccessFn(
bool isStore,
int size);
744 const MemoryMapParams *MapParams;
748 MemoryMapParams CustomMapParams;
750 MDNode *ColdCallWeights;
753 MDNode *OriginStoreWeights;
756void insertModuleCtor(
Module &M) {
793 if (!Options.Kernel) {
802 MemorySanitizer Msan(*
F.getParent(), Options);
821 OS, MapClassName2PassName);
827 if (Options.EagerChecks)
828 OS <<
"eager-checks;";
829 OS <<
"track-origins=" << Options.TrackOrigins;
845template <
typename... ArgsTy>
847MemorySanitizer::getOrInsertMsanMetadataFunction(
Module &M,
StringRef Name,
852 std::forward<ArgsTy>(Args)...);
855 return M.getOrInsertFunction(Name, MsanMetadata,
856 std::forward<ArgsTy>(Args)...);
865 RetvalOriginTLS =
nullptr;
867 ParamOriginTLS =
nullptr;
869 VAArgOriginTLS =
nullptr;
870 VAArgOverflowSizeTLS =
nullptr;
872 WarningFn =
M.getOrInsertFunction(
"__msan_warning",
874 IRB.getVoidTy(), IRB.getInt32Ty());
885 MsanGetContextStateFn =
886 M.getOrInsertFunction(
"__msan_get_context_state", PtrTy);
890 for (
int ind = 0,
size = 1; ind < 4; ind++,
size <<= 1) {
891 std::string name_load =
892 "__msan_metadata_ptr_for_load_" + std::to_string(
size);
893 std::string name_store =
894 "__msan_metadata_ptr_for_store_" + std::to_string(
size);
895 MsanMetadataPtrForLoad_1_8[ind] =
896 getOrInsertMsanMetadataFunction(M, name_load, PtrTy);
897 MsanMetadataPtrForStore_1_8[ind] =
898 getOrInsertMsanMetadataFunction(M, name_store, PtrTy);
901 MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(
902 M,
"__msan_metadata_ptr_for_load_n", PtrTy, IntptrTy);
903 MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(
904 M,
"__msan_metadata_ptr_for_store_n", PtrTy, IntptrTy);
907 MsanPoisonAllocaFn =
M.getOrInsertFunction(
908 "__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
909 MsanUnpoisonAllocaFn =
M.getOrInsertFunction(
910 "__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);
914 return M.getOrInsertGlobal(Name, Ty, [&] {
916 nullptr, Name,
nullptr,
922void MemorySanitizer::createUserspaceApi(
Module &M,
930 StringRef WarningFnName = Recover ?
"__msan_warning_with_origin"
931 :
"__msan_warning_with_origin_noreturn";
932 WarningFn =
M.getOrInsertFunction(WarningFnName,
934 IRB.getVoidTy(), IRB.getInt32Ty());
937 Recover ?
"__msan_warning" :
"__msan_warning_noreturn";
938 WarningFn =
M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
965 IRB.getIntPtrTy(
M.getDataLayout()));
969 unsigned AccessSize = 1 << AccessSizeIndex;
970 std::string FunctionName =
"__msan_maybe_warning_" +
itostr(AccessSize);
971 MaybeWarningFn[AccessSizeIndex] =
M.getOrInsertFunction(
973 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());
974 MaybeWarningVarSizeFn =
M.getOrInsertFunction(
975 "__msan_maybe_warning_N", TLI.
getAttrList(
C, {},
false),
976 IRB.getVoidTy(), PtrTy, IRB.getInt64Ty(), IRB.getInt32Ty());
977 FunctionName =
"__msan_maybe_store_origin_" +
itostr(AccessSize);
978 MaybeStoreOriginFn[AccessSizeIndex] =
M.getOrInsertFunction(
980 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,
984 MsanSetAllocaOriginWithDescriptionFn =
985 M.getOrInsertFunction(
"__msan_set_alloca_origin_with_descr",
986 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);
987 MsanSetAllocaOriginNoDescriptionFn =
988 M.getOrInsertFunction(
"__msan_set_alloca_origin_no_descr",
989 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
990 MsanPoisonStackFn =
M.getOrInsertFunction(
"__msan_poison_stack",
991 IRB.getVoidTy(), PtrTy, IntptrTy);
995void MemorySanitizer::initializeCallbacks(
Module &M,
998 if (CallbacksInitialized)
1004 MsanChainOriginFn =
M.getOrInsertFunction(
1005 "__msan_chain_origin",
1006 TLI.
getAttrList(
C, {0},
false,
true), IRB.getInt32Ty(),
1008 MsanSetOriginFn =
M.getOrInsertFunction(
1010 IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
1012 M.getOrInsertFunction(
"__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
1014 M.getOrInsertFunction(
"__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
1015 MemsetFn =
M.getOrInsertFunction(
"__msan_memset",
1017 PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
1019 MsanInstrumentAsmStoreFn =
M.getOrInsertFunction(
1020 "__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
1022 if (CompileKernel) {
1023 createKernelApi(M, TLI);
1025 createUserspaceApi(M, TLI);
1027 CallbacksInitialized =
true;
1033 isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;
1051void MemorySanitizer::initializeModule(
Module &M) {
1052 auto &
DL =
M.getDataLayout();
1054 TargetTriple =
M.getTargetTriple();
1056 bool ShadowPassed =
ClShadowBase.getNumOccurrences() > 0;
1057 bool OriginPassed =
ClOriginBase.getNumOccurrences() > 0;
1059 if (ShadowPassed || OriginPassed) {
1064 MapParams = &CustomMapParams;
1066 switch (TargetTriple.getOS()) {
1068 switch (TargetTriple.getArch()) {
1083 switch (TargetTriple.getArch()) {
1092 switch (TargetTriple.getArch()) {
1129 C = &(
M.getContext());
1131 IntptrTy = IRB.getIntPtrTy(
DL);
1132 OriginTy = IRB.getInt32Ty();
1133 PtrTy = IRB.getPtrTy();
1138 if (!CompileKernel) {
1140 M.getOrInsertGlobal(
"__msan_track_origins", IRB.getInt32Ty(), [&] {
1141 return new GlobalVariable(
1142 M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
1143 IRB.getInt32(TrackOrigins),
"__msan_track_origins");
1147 M.getOrInsertGlobal(
"__msan_keep_going", IRB.getInt32Ty(), [&] {
1148 return new GlobalVariable(M, IRB.getInt32Ty(), true,
1149 GlobalValue::WeakODRLinkage,
1150 IRB.getInt32(Recover),
"__msan_keep_going");
1165struct VarArgHelper {
1166 virtual ~VarArgHelper() =
default;
1169 virtual void visitCallBase(CallBase &CB,
IRBuilder<> &IRB) = 0;
1172 virtual void visitVAStartInst(VAStartInst &
I) = 0;
1175 virtual void visitVACopyInst(VACopyInst &
I) = 0;
1181 virtual void finalizeInstrumentation() = 0;
1184struct MemorySanitizerVisitor;
1189 MemorySanitizerVisitor &Visitor);
1196 if (TypeSizeFixed <= 8)
1205class NextNodeIRBuilder :
public IRBuilder<> {
1218struct MemorySanitizerVisitor :
public InstVisitor<MemorySanitizerVisitor> {
1220 MemorySanitizer &MS;
1222 ValueMap<Value *, Value *> ShadowMap, OriginMap;
1223 std::unique_ptr<VarArgHelper> VAHelper;
1224 const TargetLibraryInfo *TLI;
1231 bool PropagateShadow;
1234 bool PoisonUndefVectors;
1236 struct ShadowOriginAndInsertPoint {
1241 ShadowOriginAndInsertPoint(
Value *S,
Value *O, Instruction *
I)
1242 : Shadow(S), Origin(
O), OrigIns(
I) {}
1245 DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
1246 SmallSetVector<AllocaInst *, 16> AllocaSet;
1249 int64_t SplittableBlocksCount = 0;
1251 MemorySanitizerVisitor(Function &
F, MemorySanitizer &MS,
1252 const TargetLibraryInfo &TLI)
1254 bool SanitizeFunction =
1256 InsertChecks = SanitizeFunction;
1257 PropagateShadow = SanitizeFunction;
1268 MS.initializeCallbacks(*
F.getParent(), TLI);
1270 IRBuilder<>(&
F.getEntryBlock(),
F.getEntryBlock().getFirstNonPHIIt())
1271 .CreateIntrinsicWithoutFolding(Intrinsic::donothing, {});
1273 if (MS.CompileKernel) {
1275 insertKmsanPrologue(IRB);
1279 <<
"MemorySanitizer is not inserting checks into '"
1280 <<
F.getName() <<
"'\n");
1283 bool instrumentWithCalls(
Value *V) {
1287 ++SplittableBlocksCount;
1292 bool isInPrologue(Instruction &
I) {
1293 return I.getParent() == FnPrologueEnd->
getParent() &&
1302 if (MS.TrackOrigins <= 1)
1304 return IRB.
CreateCall(MS.MsanChainOriginFn, V);
1308 const DataLayout &
DL =
F.getDataLayout();
1309 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1319 TypeSize TS, Align Alignment) {
1320 const DataLayout &
DL =
F.getDataLayout();
1321 const Align IntptrAlignment =
DL.getABITypeAlign(MS.IntptrTy);
1322 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1334 auto [InsertPt,
Index] =
1346 Align CurrentAlignment = Alignment;
1347 if (Alignment >= IntptrAlignment && IntptrSize >
kOriginSize) {
1348 Value *IntptrOrigin = originToIntptr(IRB, Origin);
1350 for (
unsigned i = 0; i <
Size / IntptrSize; ++i) {
1355 CurrentAlignment = IntptrAlignment;
1368 Value *OriginPtr, Align Alignment) {
1369 const DataLayout &
DL =
F.getDataLayout();
1371 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
1373 Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
1382 paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,
1389 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1391 if (instrumentWithCalls(ConvertedShadow) &&
1393 FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex];
1394 Value *ConvertedShadow2 =
1396 CallBase *CB = IRB.
CreateCall(Fn, {ConvertedShadow2, Addr, Origin});
1400 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1404 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize,
1409 void materializeStores() {
1410 for (StoreInst *SI : StoreList) {
1412 Value *Val =
SI->getValueOperand();
1413 Value *Addr =
SI->getPointerOperand();
1414 Value *Shadow =
SI->isAtomic() ? getCleanShadow(Val) : getShadow(Val);
1415 Value *ShadowPtr, *OriginPtr;
1417 const Align Alignment =
SI->getAlign();
1419 std::tie(ShadowPtr, OriginPtr) =
1420 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
true);
1422 [[maybe_unused]] StoreInst *NewSI =
1429 if (MS.TrackOrigins && !
SI->isAtomic())
1430 storeOrigin(IRB, Addr, Shadow, getOrigin(Val), OriginPtr,
1437 if (MS.TrackOrigins < 2)
1440 if (LazyWarningDebugLocationCount.
empty())
1441 for (
const auto &
I : InstrumentationList)
1442 ++LazyWarningDebugLocationCount[
I.OrigIns->getDebugLoc()];
1458 auto NewDebugLoc = OI->getDebugLoc();
1465 IRBOrigin.SetCurrentDebugLocation(NewDebugLoc);
1466 Origin = updateOrigin(Origin, IRBOrigin);
1471 if (MS.CompileKernel || MS.TrackOrigins)
1482 const DataLayout &
DL =
F.getDataLayout();
1483 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1485 if (instrumentWithCalls(ConvertedShadow) && !MS.CompileKernel) {
1487 ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);
1488 Value *ConvertedShadow2 =
1492 FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];
1496 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1500 FunctionCallee Fn = MS.MaybeWarningVarSizeFn;
1503 unsigned ShadowSize =
DL.getTypeAllocSize(ConvertedShadow2->
getType());
1506 {ShadowAlloca, ConstantInt::get(IRB.
getInt64Ty(), ShadowSize),
1507 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1512 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1515 !MS.Recover, MS.ColdCallWeights);
1518 insertWarningFn(IRB, Origin);
1523 void materializeInstructionChecks(
1525 const DataLayout &
DL =
F.getDataLayout();
1528 bool Combine = !MS.TrackOrigins;
1530 Value *Shadow =
nullptr;
1531 for (
const auto &ShadowData : InstructionChecks) {
1532 assert(ShadowData.OrigIns == Instruction);
1535 Value *ConvertedShadow = ShadowData.Shadow;
1544 insertWarningFn(IRB, ShadowData.Origin);
1554 materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin);
1559 Shadow = ConvertedShadow;
1563 Shadow = convertToBool(Shadow, IRB,
"_mscmp");
1564 ConvertedShadow = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1565 Shadow = IRB.
CreateOr(Shadow, ConvertedShadow,
"_msor");
1571 materializeOneCheck(IRB, Shadow,
nullptr);
1575 static bool isAArch64SVCount(
Type *Ty) {
1577 return TTy->
getName() ==
"aarch64.svcount";
1583 static bool isScalableNonVectorType(
Type *Ty) {
1584 if (!isAArch64SVCount(Ty))
1585 LLVM_DEBUG(
dbgs() <<
"isScalableNonVectorType: Unexpected type " << *Ty
1591 void materializeChecks() {
1594 SmallPtrSet<Instruction *, 16>
Done;
1597 for (
auto I = InstrumentationList.begin();
1598 I != InstrumentationList.end();) {
1599 auto OrigIns =
I->OrigIns;
1603 auto J = std::find_if(
I + 1, InstrumentationList.end(),
1604 [OrigIns](
const ShadowOriginAndInsertPoint &R) {
1605 return OrigIns != R.OrigIns;
1619 MS.ParamTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1620 {Zero, IRB.getInt32(0)},
"param_shadow");
1621 MS.RetvalTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1622 {Zero, IRB.getInt32(1)},
"retval_shadow");
1623 MS.VAArgTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1624 {Zero, IRB.getInt32(2)},
"va_arg_shadow");
1625 MS.VAArgOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1626 {Zero, IRB.getInt32(3)},
"va_arg_origin");
1627 MS.VAArgOverflowSizeTLS =
1628 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1629 {Zero, IRB.getInt32(4)},
"va_arg_overflow_size");
1630 MS.ParamOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1631 {Zero, IRB.getInt32(5)},
"param_origin");
1632 MS.RetvalOriginTLS =
1633 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1634 {Zero, IRB.getInt32(6)},
"retval_origin");
1636 MS.MsanMetadataAlloca = IRB.
CreateAlloca(MS.MsanMetadata, 0u);
1649 for (Instruction *
I : Instructions)
1653 for (PHINode *PN : ShadowPHINodes) {
1655 PHINode *PNO = MS.TrackOrigins ?
cast<PHINode>(getOrigin(PN)) : nullptr;
1656 size_t NumValues = PN->getNumIncomingValues();
1657 for (
size_t v = 0;
v < NumValues;
v++) {
1658 PNS->
addIncoming(getShadow(PN, v), PN->getIncomingBlock(v));
1660 PNO->
addIncoming(getOrigin(PN, v), PN->getIncomingBlock(v));
1664 VAHelper->finalizeInstrumentation();
1669 for (
auto Item : LifetimeStartList) {
1670 instrumentAlloca(*Item.second, Item.first);
1671 AllocaSet.
remove(Item.second);
1676 for (AllocaInst *AI : AllocaSet)
1677 instrumentAlloca(*AI);
1680 materializeChecks();
1684 materializeStores();
1690 Type *getShadowTy(
Value *V) {
return getShadowTy(
V->getType()); }
1701 const DataLayout &
DL =
F.getDataLayout();
1703 uint32_t EltSize =
DL.getTypeSizeInBits(VT->getElementType());
1705 VT->getElementCount());
1708 return ArrayType::get(getShadowTy(AT->getElementType()),
1709 AT->getNumElements());
1713 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
1714 Elements.push_back(getShadowTy(
ST->getElementType(i)));
1716 LLVM_DEBUG(
dbgs() <<
"getShadowTy: " << *ST <<
" ===> " << *Res <<
"\n");
1719 if (isScalableNonVectorType(OrigTy)) {
1720 LLVM_DEBUG(
dbgs() <<
"getShadowTy: Scalable non-vector type: " << *OrigTy
1725 uint32_t TypeSize =
DL.getTypeSizeInBits(OrigTy);
1730 Value *collapseStructShadow(StructType *Struct,
Value *Shadow,
1735 for (
unsigned Idx = 0; Idx <
Struct->getNumElements(); Idx++) {
1738 Value *ShadowBool = convertToBool(ShadowItem, IRB);
1740 if (Aggregator != FalseVal)
1741 Aggregator = IRB.
CreateOr(Aggregator, ShadowBool);
1743 Aggregator = ShadowBool;
1750 Value *collapseArrayShadow(ArrayType *Array,
Value *Shadow,
1752 if (!
Array->getNumElements())
1756 Value *Aggregator = convertShadowToScalar(FirstItem, IRB);
1758 for (
unsigned Idx = 1; Idx <
Array->getNumElements(); Idx++) {
1760 Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);
1761 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1771 return collapseStructShadow(Struct, V, IRB);
1773 return collapseArrayShadow(Array, V, IRB);
1778 V->getType()->getPrimitiveSizeInBits().getFixedValue();
1786 Type *VTy =
V->getType();
1788 return convertToBool(convertShadowToScalar(V, IRB), IRB,
name);
1795 Type *ptrToIntPtrType(
Type *PtrTy)
const {
1797 return VectorType::get(ptrToIntPtrType(VectTy->getElementType()),
1798 VectTy->getElementCount());
1804 Type *getPtrToShadowPtrType(
Type *IntPtrTy,
Type *ShadowTy)
const {
1806 return VectorType::get(
1807 getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
1808 VectTy->getElementCount());
1810 assert(IntPtrTy == MS.IntptrTy);
1817 VectTy->getElementCount(),
1818 constToIntPtr(VectTy->getElementType(),
C));
1820 assert(IntPtrTy == MS.IntptrTy);
1823 return ConstantInt::get(MS.IntptrTy,
C,
false,
1837 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1840 if (uint64_t AndMask = MS.MapParams->AndMask)
1841 OffsetLong = IRB.
CreateAnd(OffsetLong, constToIntPtr(IntptrTy, ~AndMask));
1843 if (uint64_t XorMask = MS.MapParams->XorMask)
1844 OffsetLong = IRB.
CreateXor(OffsetLong, constToIntPtr(IntptrTy, XorMask));
1856 std::pair<Value *, Value *>
1858 MaybeAlign Alignment) {
1863 assert(VectTy->getElementType()->isPointerTy());
1865 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1866 Value *ShadowOffset = getShadowPtrOffset(Addr, IRB);
1867 Value *ShadowLong = ShadowOffset;
1868 if (uint64_t ShadowBase = MS.MapParams->ShadowBase) {
1870 IRB.
CreateAdd(ShadowLong, constToIntPtr(IntptrTy, ShadowBase));
1873 ShadowLong, getPtrToShadowPtrType(IntptrTy, ShadowTy));
1875 Value *OriginPtr =
nullptr;
1876 if (MS.TrackOrigins) {
1877 Value *OriginLong = ShadowOffset;
1878 uint64_t OriginBase = MS.MapParams->OriginBase;
1879 if (OriginBase != 0)
1881 IRB.
CreateAdd(OriginLong, constToIntPtr(IntptrTy, OriginBase));
1884 OriginLong = IRB.
CreateAnd(OriginLong, constToIntPtr(IntptrTy, ~Mask));
1887 OriginLong, getPtrToShadowPtrType(IntptrTy, MS.OriginTy));
1889 return std::make_pair(ShadowPtr, OriginPtr);
1892 template <
typename... ArgsTy>
1897 {MS.MsanMetadataAlloca, std::forward<ArgsTy>(Args)...});
1898 return IRB.
CreateLoad(MS.MsanMetadata, MS.MsanMetadataAlloca);
1901 return IRB.
CreateCall(Callee, {std::forward<ArgsTy>(Args)...});
1904 std::pair<Value *, Value *> getShadowOriginPtrKernelNoVec(
Value *Addr,
1908 Value *ShadowOriginPtrs;
1909 const DataLayout &
DL =
F.getDataLayout();
1910 TypeSize
Size =
DL.getTypeStoreSize(ShadowTy);
1912 FunctionCallee Getter = MS.getKmsanShadowOriginAccessFn(
isStore,
Size);
1915 ShadowOriginPtrs = createMetadataCall(IRB, Getter, AddrCast);
1917 Value *SizeVal = ConstantInt::get(MS.IntptrTy,
Size);
1918 ShadowOriginPtrs = createMetadataCall(
1920 isStore ? MS.MsanMetadataPtrForStoreN : MS.MsanMetadataPtrForLoadN,
1927 return std::make_pair(ShadowPtr, OriginPtr);
1933 std::pair<Value *, Value *> getShadowOriginPtrKernel(
Value *Addr,
1940 return getShadowOriginPtrKernelNoVec(Addr, IRB, ShadowTy,
isStore);
1945 Value *ShadowPtrs = ConstantInt::getNullValue(
1947 Value *OriginPtrs =
nullptr;
1948 if (MS.TrackOrigins)
1949 OriginPtrs = ConstantInt::getNullValue(
1951 for (
unsigned i = 0; i < NumElements; ++i) {
1954 auto [ShadowPtr, OriginPtr] =
1955 getShadowOriginPtrKernelNoVec(OneAddr, IRB, ShadowTy,
isStore);
1958 ShadowPtrs, ShadowPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1959 if (MS.TrackOrigins)
1961 OriginPtrs, OriginPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1963 return {ShadowPtrs, OriginPtrs};
1966 std::pair<Value *, Value *> getShadowOriginPtr(
Value *Addr,
IRBuilder<> &IRB,
1968 MaybeAlign Alignment,
1970 if (MS.CompileKernel)
1971 return getShadowOriginPtrKernel(Addr, IRB, ShadowTy,
isStore);
1972 return getShadowOriginPtrUserspace(Addr, IRB, ShadowTy, Alignment);
1980 ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg");
1985 if (!MS.TrackOrigins)
1988 ConstantInt::get(MS.IntptrTy, ArgOffset),
1998 Value *getOriginPtrForRetval() {
2000 return MS.RetvalOriginTLS;
2005 assert(!ShadowMap.
count(V) &&
"Values may only have one shadow");
2006 ShadowMap[
V] = PropagateShadow ? SV : getCleanShadow(V);
2011 if (!MS.TrackOrigins)
2013 assert(!OriginMap.
count(V) &&
"Values may only have one origin");
2014 LLVM_DEBUG(
dbgs() <<
"ORIGIN: " << *V <<
" ==> " << *Origin <<
"\n");
2015 OriginMap[
V] = Origin;
2019 Type *ShadowTy = getShadowTy(OrigTy);
2029 Constant *getCleanShadow(
Value *V) {
return getCleanShadow(
V->getType()); }
2037 SmallVector<Constant *, 4> Vals(AT->getNumElements(),
2038 getPoisonedShadow(AT->getElementType()));
2042 SmallVector<Constant *, 4> Vals;
2043 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
2044 Vals.
push_back(getPoisonedShadow(
ST->getElementType(i)));
2052 Type *ShadowTy = getShadowTy(V);
2055 return getPoisonedShadow(ShadowTy);
2067 if (!PropagateShadow ||
I->getMetadata(LLVMContext::MD_nosanitize))
2068 return getCleanShadow(V);
2070 Value *Shadow = ShadowMap[
V];
2072 LLVM_DEBUG(
dbgs() <<
"No shadow: " << *V <<
"\n" << *(
I->getParent()));
2073 assert(Shadow &&
"No shadow for a value");
2080 Value *
AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
2081 : getCleanShadow(V);
2087 Value *&ShadowPtr = ShadowMap[
V];
2092 unsigned ArgOffset = 0;
2093 const DataLayout &
DL =
F->getDataLayout();
2094 for (
auto &FArg :
F->args()) {
2095 if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
2097 ?
"vscale not fully supported\n"
2098 :
"Arg is not sized\n"));
2100 ShadowPtr = getCleanShadow(V);
2101 setOrigin(
A, getCleanOrigin());
2107 unsigned Size = FArg.hasByValAttr()
2108 ?
DL.getTypeAllocSize(FArg.getParamByValType())
2109 :
DL.getTypeAllocSize(FArg.getType());
2113 if (FArg.hasByValAttr()) {
2117 const Align ArgAlign =
DL.getValueOrABITypeAlignment(
2118 FArg.getParamAlign(), FArg.getParamByValType());
2119 Value *CpShadowPtr, *CpOriginPtr;
2120 std::tie(CpShadowPtr, CpOriginPtr) =
2121 getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,
2123 if (!PropagateShadow || Overflow) {
2125 EntryIRB.CreateMemSet(
2129 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2131 [[maybe_unused]]
Value *Cpy = EntryIRB.CreateMemCpy(
2132 CpShadowPtr, CopyAlign,
Base, CopyAlign,
Size);
2135 if (MS.TrackOrigins) {
2136 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2140 EntryIRB.CreateMemCpy(
2149 if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||
2150 (MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {
2151 ShadowPtr = getCleanShadow(V);
2152 setOrigin(
A, getCleanOrigin());
2155 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2156 ShadowPtr = EntryIRB.CreateAlignedLoad(getShadowTy(&FArg),
Base,
2158 if (MS.TrackOrigins) {
2159 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2160 setOrigin(
A, EntryIRB.CreateLoad(MS.OriginTy, OriginPtr));
2164 <<
" ARG: " << FArg <<
" ==> " << *ShadowPtr <<
"\n");
2170 assert(ShadowPtr &&
"Could not find shadow for an argument");
2177 cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
2178 PoisonUndefVectors) {
2181 for (
unsigned i = 0; i != NumElems; ++i) {
2184 : getCleanShadow(Elem);
2188 LLVM_DEBUG(
dbgs() <<
"Partial undef constant vector: " << *V <<
" ==> "
2189 << *ShadowConstant <<
"\n");
2191 return ShadowConstant;
2197 return getCleanShadow(V);
2201 Value *getShadow(Instruction *
I,
int i) {
2202 return getShadow(
I->getOperand(i));
2207 if (!MS.TrackOrigins)
2210 return getCleanOrigin();
2212 "Unexpected value type in getOrigin()");
2214 if (
I->getMetadata(LLVMContext::MD_nosanitize))
2215 return getCleanOrigin();
2217 Value *Origin = OriginMap[
V];
2218 assert(Origin &&
"Missing origin");
2223 Value *getOrigin(Instruction *
I,
int i) {
2224 return getOrigin(
I->getOperand(i));
2231 void insertCheckShadow(
Value *Shadow,
Value *Origin, Instruction *OrigIns) {
2237 LLVM_DEBUG(
dbgs() <<
"Skipping check of " << *Shadow <<
" before "
2238 << *OrigIns <<
"\n");
2243 if (isScalableNonVectorType(ShadowTy)) {
2244 LLVM_DEBUG(
dbgs() <<
"Skipping check of scalable non-vector " << *Shadow
2245 <<
" before " << *OrigIns <<
"\n");
2251 "Can only insert checks for integer, vector, and aggregate shadow "
2254 InstrumentationList.push_back(
2255 ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
2263 void insertCheckShadowOf(
Value *Val, Instruction *OrigIns) {
2265 Value *Shadow, *Origin;
2267 Shadow = getShadow(Val);
2270 Origin = getOrigin(Val);
2277 insertCheckShadow(Shadow, Origin, OrigIns);
2282 case AtomicOrdering::NotAtomic:
2283 return AtomicOrdering::NotAtomic;
2284 case AtomicOrdering::Unordered:
2285 case AtomicOrdering::Monotonic:
2286 case AtomicOrdering::Release:
2287 return AtomicOrdering::Release;
2288 case AtomicOrdering::Acquire:
2289 case AtomicOrdering::AcquireRelease:
2290 return AtomicOrdering::AcquireRelease;
2291 case AtomicOrdering::SequentiallyConsistent:
2292 return AtomicOrdering::SequentiallyConsistent;
2298 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2299 uint32_t OrderingTable[NumOrderings] = {};
2301 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2302 OrderingTable[(
int)AtomicOrderingCABI::release] =
2303 (int)AtomicOrderingCABI::release;
2304 OrderingTable[(int)AtomicOrderingCABI::consume] =
2305 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2306 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
2307 (
int)AtomicOrderingCABI::acq_rel;
2308 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2309 (
int)AtomicOrderingCABI::seq_cst;
2316 case AtomicOrdering::NotAtomic:
2317 return AtomicOrdering::NotAtomic;
2318 case AtomicOrdering::Unordered:
2319 case AtomicOrdering::Monotonic:
2320 case AtomicOrdering::Acquire:
2321 return AtomicOrdering::Acquire;
2322 case AtomicOrdering::Release:
2323 case AtomicOrdering::AcquireRelease:
2324 return AtomicOrdering::AcquireRelease;
2325 case AtomicOrdering::SequentiallyConsistent:
2326 return AtomicOrdering::SequentiallyConsistent;
2332 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2333 uint32_t OrderingTable[NumOrderings] = {};
2335 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2336 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2337 OrderingTable[(int)AtomicOrderingCABI::consume] =
2338 (
int)AtomicOrderingCABI::acquire;
2339 OrderingTable[(int)AtomicOrderingCABI::release] =
2340 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
2341 (int)AtomicOrderingCABI::acq_rel;
2342 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2343 (
int)AtomicOrderingCABI::seq_cst;
2349 using InstVisitor<MemorySanitizerVisitor>
::visit;
2350 void visit(Instruction &
I) {
2351 if (
I.getMetadata(LLVMContext::MD_nosanitize))
2354 if (isInPrologue(
I))
2359 setShadow(&
I, getCleanShadow(&
I));
2360 setOrigin(&
I, getCleanOrigin());
2371 void visitLoadInst(LoadInst &
I) {
2372 assert(
I.getType()->isSized() &&
"Load type must have size");
2373 assert(!
I.getMetadata(LLVMContext::MD_nosanitize));
2374 NextNodeIRBuilder IRB(&
I);
2375 Type *ShadowTy = getShadowTy(&
I);
2376 Value *Addr =
I.getPointerOperand();
2377 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
2378 const Align Alignment =
I.getAlign();
2379 if (PropagateShadow) {
2380 std::tie(ShadowPtr, OriginPtr) =
2381 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
2385 setShadow(&
I, getCleanShadow(&
I));
2389 insertCheckShadowOf(
I.getPointerOperand(), &
I);
2394 if (MS.TrackOrigins) {
2395 if (PropagateShadow) {
2400 setOrigin(&
I, getCleanOrigin());
2409 void visitStoreInst(StoreInst &
I) {
2410 StoreList.push_back(&
I);
2412 insertCheckShadowOf(
I.getPointerOperand(), &
I);
2415 void handleCASOrRMW(Instruction &
I) {
2419 Value *Addr =
I.getOperand(0);
2420 Value *Val =
I.getOperand(1);
2421 Value *ShadowPtr = getShadowOriginPtr(Addr, IRB, getShadowTy(Val),
Align(1),
2426 insertCheckShadowOf(Addr, &
I);
2432 insertCheckShadowOf(Val, &
I);
2436 setShadow(&
I, getCleanShadow(&
I));
2437 setOrigin(&
I, getCleanOrigin());
2440 void visitAtomicRMWInst(AtomicRMWInst &
I) {
2445 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2507 void visitSwitchInst(SwitchInst &SI) {
2510 Value *Val =
SI.getCondition();
2511 Value *ShadowVal = getShadow(Val);
2523 Value *ShadowCases =
nullptr;
2524 for (
auto Case :
SI.cases()) {
2525 if (casesToConsider <= 0)
2528 Value *Comparator = Case.getCaseValue();
2531 Value *ComparisonShadow = propagateEqualityComparison(
2532 IRB, Val, Comparator, ShadowVal, getShadow(Comparator));
2535 ShadowCases = IRB.
CreateOr(ShadowCases, ComparisonShadow);
2537 ShadowCases = ComparisonShadow;
2543 insertCheckShadow(ShadowCases, getOrigin(Val), &SI);
2547 void visitExtractElementInst(ExtractElementInst &
I) {
2548 insertCheckShadowOf(
I.getOperand(1), &
I);
2552 setOrigin(&
I, getOrigin(&
I, 0));
2555 void visitInsertElementInst(InsertElementInst &
I) {
2556 insertCheckShadowOf(
I.getOperand(2), &
I);
2558 auto *Shadow0 = getShadow(&
I, 0);
2559 auto *Shadow1 = getShadow(&
I, 1);
2562 setOriginForNaryOp(
I);
2565 void visitShuffleVectorInst(ShuffleVectorInst &
I) {
2567 auto *Shadow0 = getShadow(&
I, 0);
2568 auto *Shadow1 = getShadow(&
I, 1);
2571 setOriginForNaryOp(
I);
2575 void visitSExtInst(SExtInst &
I) {
2577 setShadow(&
I, IRB.
CreateSExt(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2578 setOrigin(&
I, getOrigin(&
I, 0));
2581 void visitZExtInst(ZExtInst &
I) {
2583 setShadow(&
I, IRB.
CreateZExt(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2584 setOrigin(&
I, getOrigin(&
I, 0));
2587 void visitTruncInst(TruncInst &
I) {
2589 setShadow(&
I, IRB.
CreateTrunc(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2590 setOrigin(&
I, getOrigin(&
I, 0));
2593 void visitBitCastInst(BitCastInst &
I) {
2598 if (CI->isMustTailCall())
2602 setOrigin(&
I, getOrigin(&
I, 0));
2605 void visitPtrToIntInst(PtrToIntInst &
I) {
2608 "_msprop_ptrtoint"));
2609 setOrigin(&
I, getOrigin(&
I, 0));
2612 void visitIntToPtrInst(IntToPtrInst &
I) {
2615 "_msprop_inttoptr"));
2616 setOrigin(&
I, getOrigin(&
I, 0));
2637 void handleGenericVectorConvertIntrinsic(Instruction &
I,
bool FixedPoint) {
2638 [[maybe_unused]]
unsigned NumArgs =
I.getNumOperands();
2640 NumArgs = CI->arg_size();
2644 Value *Precision =
I.getOperand(1);
2645 insertCheckShadowOf(Precision, &
I);
2651 Value *S0 = getShadow(&
I, 0);
2660 setShadow(&
I, OutShadow);
2661 setOriginForNaryOp(
I);
2664 void visitFPToSIInst(CastInst &
I) {
2665 handleGenericVectorConvertIntrinsic(
I,
false);
2667 void visitFPToUIInst(CastInst &
I) {
2668 handleGenericVectorConvertIntrinsic(
I,
false);
2670 void visitSIToFPInst(CastInst &
I) {
2671 handleGenericVectorConvertIntrinsic(
I,
false);
2673 void visitUIToFPInst(CastInst &
I) {
2674 handleGenericVectorConvertIntrinsic(
I,
false);
2676 void visitFPExtInst(CastInst &
I) { handleShadowOr(
I); }
2677 void visitFPTruncInst(CastInst &
I) { handleShadowOr(
I); }
2697 assert(
V1->getType()->isIntOrIntVectorTy());
2708 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2712 void visitAnd(BinaryOperator &
I) {
2715 Value *V2 =
I.getOperand(1);
2717 Value *S2 = getShadow(&
I, 1);
2719 Value *OutShadow = handleBitwiseAnd(IRB,
V1, V2,
S1, S2);
2721 setShadow(&
I, OutShadow);
2722 setOriginForNaryOp(
I);
2725 void visitOr(BinaryOperator &
I) {
2738 Value *S2 = getShadow(&
I, 1);
2740 Value *V2 =
I.getOperand(1);
2744 assert(
V1->getType()->isIntOrIntVectorTy());
2764 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2768 setOriginForNaryOp(
I);
2786 template <
bool CombineShadow>
class Combiner {
2787 Value *Shadow =
nullptr;
2788 Value *Origin =
nullptr;
2790 MemorySanitizerVisitor *MSV;
2793 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2794 : IRB(IRB), MSV(MSV) {}
2798 if (CombineShadow) {
2803 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2804 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2808 if (MSV->MS.TrackOrigins) {
2815 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2816 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2826 Value *OpShadow = MSV->getShadow(V);
2827 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2828 return Add(OpShadow, OpOrigin);
2833 void Done(Instruction *
I) {
2834 if (CombineShadow) {
2836 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2837 MSV->setShadow(
I, Shadow);
2839 if (MSV->MS.TrackOrigins) {
2841 MSV->setOrigin(
I, Origin);
2847 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2848 if (MSV->MS.TrackOrigins) {
2855 using ShadowAndOriginCombiner = Combiner<true>;
2856 using OriginCombiner = Combiner<false>;
2859 void setOriginForNaryOp(Instruction &
I) {
2860 if (!MS.TrackOrigins)
2863 OriginCombiner OC(
this, IRB);
2864 for (Use &
Op :
I.operands())
2869 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2871 "Vector of pointers is not a valid shadow type");
2881 Type *srcTy =
V->getType();
2884 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2885 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2886 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2904 Type *ShadowTy = getShadowTy(V);
2905 if (
V->getType() == ShadowTy)
2907 if (
V->getType()->isPtrOrPtrVectorTy())
2914 void handleShadowOr(Instruction &
I) {
2916 ShadowAndOriginCombiner SC(
this, IRB);
2917 for (Use &
Op :
I.operands())
2944 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2945 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2950 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2956 assert(NumElems % (ReductionFactor * Shards) == 0);
2961 for (
unsigned i = 0; i < ReductionFactor; i++) {
2962 SmallVector<int, 16>
Mask;
2964 for (
unsigned j = 0;
j < Shards;
j++) {
2965 unsigned Offset = NumElems / Shards *
j;
2967 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2971 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2996 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
2997 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2999 assert(
I.getType()->isVectorTy());
3000 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3002 [[maybe_unused]] FixedVectorType *ParamType =
3006 [[maybe_unused]] FixedVectorType *
ReturnType =
3014 Value *FirstArgShadow = getShadow(&
I, 0);
3015 Value *SecondArgShadow =
nullptr;
3016 if (
I.arg_size() == 2)
3017 SecondArgShadow = getShadow(&
I, 1);
3019 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3020 FirstArgShadow, SecondArgShadow);
3022 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3024 setShadow(&
I, OrShadow);
3025 setOriginForNaryOp(
I);
3035 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
3036 int ReinterpretElemWidth) {
3037 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3039 assert(
I.getType()->isVectorTy());
3040 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3042 FixedVectorType *ParamType =
3047 [[maybe_unused]] FixedVectorType *
ReturnType =
3054 FixedVectorType *ReinterpretShadowTy =
nullptr;
3062 Value *FirstArgShadow = getShadow(&
I, 0);
3063 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3073 Value *SecondArgShadow =
nullptr;
3074 if (
I.arg_size() == 2) {
3075 SecondArgShadow = getShadow(&
I, 1);
3076 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3079 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3080 FirstArgShadow, SecondArgShadow);
3082 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3084 setShadow(&
I, OrShadow);
3085 setOriginForNaryOp(
I);
3088 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3099 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3105 Type *EltTy = VTy->getElementType();
3107 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3108 if (ConstantInt *Elt =
3110 const APInt &
V = Elt->getValue();
3111 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3112 Elements.push_back(ConstantInt::get(EltTy, V2));
3114 Elements.push_back(ConstantInt::get(EltTy, 1));
3120 const APInt &
V = Elt->getValue();
3121 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3122 ShadowMul = ConstantInt::get(Ty, V2);
3124 ShadowMul = ConstantInt::get(Ty, 1);
3130 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3131 setOrigin(&
I, getOrigin(OtherArg));
3134 void visitMul(BinaryOperator &
I) {
3137 if (constOp0 && !constOp1)
3138 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3139 else if (constOp1 && !constOp0)
3140 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3145 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3146 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3147 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3148 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3149 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3150 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3152 void handleIntegerDiv(Instruction &
I) {
3155 insertCheckShadowOf(
I.getOperand(1), &
I);
3156 setShadow(&
I, getShadow(&
I, 0));
3157 setOrigin(&
I, getOrigin(&
I, 0));
3160 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3161 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3162 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3163 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3167 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3168 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3174 void handleEqualityComparison(ICmpInst &
I) {
3178 Value *Sa = getShadow(
A);
3179 Value *Sb = getShadow(
B);
3181 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3184 setOriginForNaryOp(
I);
3192 void handleRelationalComparisonExact(ICmpInst &
I) {
3196 Value *Sa = getShadow(
A);
3197 Value *Sb = getShadow(
B);
3208 bool IsSigned =
I.isSigned();
3210 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3220 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3225 return std::make_pair(Min, Max);
3228 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3229 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3235 setOriginForNaryOp(
I);
3242 void handleSignedRelationalComparison(ICmpInst &
I) {
3247 op =
I.getOperand(0);
3248 pre =
I.getPredicate();
3250 op =
I.getOperand(1);
3251 pre =
I.getSwappedPredicate();
3264 setShadow(&
I, Shadow);
3265 setOrigin(&
I, getOrigin(
op));
3271 void visitICmpInst(ICmpInst &
I) {
3276 if (
I.isEquality()) {
3277 handleEqualityComparison(
I);
3283 handleRelationalComparisonExact(
I);
3287 handleSignedRelationalComparison(
I);
3293 handleRelationalComparisonExact(
I);
3300 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3302 void handleShift(BinaryOperator &
I) {
3307 Value *S2 = getShadow(&
I, 1);
3310 Value *V2 =
I.getOperand(1);
3312 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3313 setOriginForNaryOp(
I);
3316 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3317 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3318 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3320 void handleFunnelShift(IntrinsicInst &
I) {
3324 Value *S0 = getShadow(&
I, 0);
3326 Value *S2 = getShadow(&
I, 2);
3329 Value *V2 =
I.getOperand(2);
3332 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3333 setOriginForNaryOp(
I);
3341 void handleGenericBitManipulation(IntrinsicInst &
I) {
3343 Type *ShadowTy = getShadowTy(&
I);
3346 Value *SMask = getShadow(&
I, 1);
3351 if (Function *Func =
I.getCalledFunction())
3352 S = IRB.
CreateCall(Func, {getShadow(&
I, 0),
I.getOperand(1)});
3355 {getShadow(&I, 0), I.getOperand(1)});
3358 setOriginForNaryOp(
I);
3371 void visitMemMoveInst(MemMoveInst &
I) {
3372 getShadow(
I.getArgOperand(1));
3375 {I.getArgOperand(0), I.getArgOperand(1),
3376 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3394 void visitMemCpyInst(MemCpyInst &
I) {
3395 getShadow(
I.getArgOperand(1));
3398 {I.getArgOperand(0), I.getArgOperand(1),
3399 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3404 void visitMemSetInst(MemSetInst &
I) {
3408 {I.getArgOperand(0),
3409 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3410 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3414 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3416 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3422 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3426 Value *Addr =
I.getArgOperand(0);
3427 Value *Shadow = getShadow(&
I, 1);
3428 Value *ShadowPtr, *OriginPtr;
3432 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3437 insertCheckShadowOf(Addr, &
I);
3440 if (MS.TrackOrigins)
3449 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3453 Value *Addr =
I.getArgOperand(0);
3455 Type *ShadowTy = getShadowTy(&
I);
3456 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3457 if (PropagateShadow) {
3461 std::tie(ShadowPtr, OriginPtr) =
3462 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3466 setShadow(&
I, getCleanShadow(&
I));
3470 insertCheckShadowOf(Addr, &
I);
3472 if (MS.TrackOrigins) {
3473 if (PropagateShadow)
3474 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3476 setOrigin(&
I, getCleanOrigin());
3496 [[maybe_unused]]
bool
3497 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3498 unsigned int trailingFlags) {
3499 Type *RetTy =
I.getType();
3503 unsigned NumArgOperands =
I.arg_size();
3504 assert(NumArgOperands >= trailingFlags);
3505 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3506 Type *Ty =
I.getArgOperand(i)->getType();
3512 ShadowAndOriginCombiner SC(
this, IRB);
3513 for (
unsigned i = 0; i < NumArgOperands; ++i)
3514 SC.Add(
I.getArgOperand(i));
3531 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3532 unsigned NumArgOperands =
I.arg_size();
3533 if (NumArgOperands == 0)
3536 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3537 I.getArgOperand(1)->getType()->isVectorTy() &&
3538 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3540 return handleVectorStoreIntrinsic(
I);
3543 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3544 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3546 return handleVectorLoadIntrinsic(
I);
3549 if (
I.doesNotAccessMemory())
3550 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3558 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3559 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3561 dumpInst(
I,
"Heuristic");
3563 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3570 void handleInvariantGroup(IntrinsicInst &
I) {
3571 setShadow(&
I, getShadow(&
I, 0));
3572 setOrigin(&
I, getOrigin(&
I, 0));
3575 void handleLifetimeStart(IntrinsicInst &
I) {
3580 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3583 void handleBswap(IntrinsicInst &
I) {
3586 Type *OpType =
Op->getType();
3589 setOrigin(&
I, getOrigin(
Op));
3610 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3612 Value *Src =
I.getArgOperand(0);
3613 Value *SrcShadow = getShadow(Src);
3617 I.getType(),
I.getIntrinsicID(), {Src, False});
3619 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3622 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3624 Value *NotAllZeroShadow =
3626 Value *OutputShadow =
3627 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3633 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3636 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3638 setShadow(&
I, OutputShadow);
3639 setOriginForNaryOp(
I);
3648 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3668 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3673 Value *FullShadow = getCleanShadow(&
I);
3674 unsigned ShadowNumElems =
3676 unsigned FullShadowNumElems =
3679 assert((ShadowNumElems == FullShadowNumElems) ||
3680 (ShadowNumElems * 2 == FullShadowNumElems));
3682 if (ShadowNumElems == FullShadowNumElems) {
3683 FullShadow = Shadow;
3687 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3712 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3713 bool HasRoundingMode) {
3714 if (HasRoundingMode) {
3722 Value *Src =
I.getArgOperand(0);
3723 assert(Src->getType()->isVectorTy());
3727 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3730 Value *S0 = getShadow(&
I, 0);
3742 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3744 setShadow(&
I, FullShadow);
3745 setOriginForNaryOp(
I);
3766 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3767 bool HasRoundingMode =
false) {
3769 Value *CopyOp, *ConvertOp;
3771 assert((!HasRoundingMode ||
3773 "Invalid rounding mode");
3775 switch (
I.arg_size() - HasRoundingMode) {
3777 CopyOp =
I.getArgOperand(0);
3778 ConvertOp =
I.getArgOperand(1);
3781 ConvertOp =
I.getArgOperand(0);
3795 Value *ConvertShadow = getShadow(ConvertOp);
3796 Value *AggShadow =
nullptr;
3799 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3800 for (
int i = 1; i < NumUsedElements; ++i) {
3802 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3803 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3806 AggShadow = ConvertShadow;
3809 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3816 Value *ResultShadow = getShadow(CopyOp);
3818 for (
int i = 0; i < NumUsedElements; ++i) {
3820 ResultShadow, ConstantInt::getNullValue(EltTy),
3823 setShadow(&
I, ResultShadow);
3824 setOrigin(&
I, getOrigin(CopyOp));
3826 setShadow(&
I, getCleanShadow(&
I));
3827 setOrigin(&
I, getCleanOrigin());
3835 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3838 return CreateShadowCast(IRB, S2,
T,
true);
3846 return CreateShadowCast(IRB, S2,
T,
true);
3863 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3869 Value *S2 = getShadow(&
I, 1);
3871 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3873 Value *V2 =
I.getOperand(1);
3875 {IRB.CreateBitCast(S1, V1->getType()), V2});
3877 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3878 setOriginForNaryOp(
I);
3883 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3884 unsigned X86_MMXSizeInBits = 64) {
3885 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3886 "Illegal MMX vector element size");
3888 X86_MMXSizeInBits / EltSizeInBits);
3895 case Intrinsic::x86_sse2_packsswb_128:
3896 case Intrinsic::x86_sse2_packuswb_128:
3897 return Intrinsic::x86_sse2_packsswb_128;
3899 case Intrinsic::x86_sse2_packssdw_128:
3900 case Intrinsic::x86_sse41_packusdw:
3901 return Intrinsic::x86_sse2_packssdw_128;
3903 case Intrinsic::x86_avx2_packsswb:
3904 case Intrinsic::x86_avx2_packuswb:
3905 return Intrinsic::x86_avx2_packsswb;
3907 case Intrinsic::x86_avx2_packssdw:
3908 case Intrinsic::x86_avx2_packusdw:
3909 return Intrinsic::x86_avx2_packssdw;
3911 case Intrinsic::x86_mmx_packsswb:
3912 case Intrinsic::x86_mmx_packuswb:
3913 return Intrinsic::x86_mmx_packsswb;
3915 case Intrinsic::x86_mmx_packssdw:
3916 return Intrinsic::x86_mmx_packssdw;
3918 case Intrinsic::x86_avx512_packssdw_512:
3919 case Intrinsic::x86_avx512_packusdw_512:
3920 return Intrinsic::x86_avx512_packssdw_512;
3922 case Intrinsic::x86_avx512_packsswb_512:
3923 case Intrinsic::x86_avx512_packuswb_512:
3924 return Intrinsic::x86_avx512_packsswb_512;
3940 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3941 unsigned MMXEltSizeInBits = 0) {
3945 Value *S2 = getShadow(&
I, 1);
3946 assert(
S1->getType()->isVectorTy());
3952 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3953 if (MMXEltSizeInBits) {
3961 if (MMXEltSizeInBits) {
3967 {S1_ext, S2_ext},
nullptr,
3968 "_msprop_vector_pack");
3969 if (MMXEltSizeInBits)
3972 setOriginForNaryOp(
I);
3976 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3977 SmallVector<Constant *, 4>
R(Width);
3989 const unsigned Width =
3996 Value *DstMaskV = createDppMask(Width, DstMask);
4013 void handleDppIntrinsic(IntrinsicInst &
I) {
4016 Value *S0 = getShadow(&
I, 0);
4020 const unsigned Width =
4022 assert(Width == 2 || Width == 4 || Width == 8);
4025 const unsigned SrcMask =
Mask >> 4;
4026 const unsigned DstMask =
Mask & 0xf;
4029 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
4034 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4041 setOriginForNaryOp(
I);
4045 C = CreateAppToShadowCast(IRB,
C);
4054 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4059 Value *Sc = getShadow(&
I, 2);
4060 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4065 C = convertBlendvToSelectMask(IRB,
C);
4066 Sc = convertBlendvToSelectMask(IRB, Sc);
4072 handleSelectLikeInst(
I,
C,
T,
F);
4076 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4077 const unsigned SignificantBitsPerResultElement = 16;
4079 unsigned ZeroBitsPerResultElement =
4083 auto *Shadow0 = getShadow(&
I, 0);
4084 auto *Shadow1 = getShadow(&
I, 1);
4089 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4092 setOriginForNaryOp(
I);
4116 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4117 unsigned ReductionFactor,
4119 unsigned EltSizeInBits,
4123 [[maybe_unused]] FixedVectorType *
ReturnType =
4128 Value *Va =
nullptr;
4129 Value *Vb =
nullptr;
4130 Value *Sa =
nullptr;
4131 Value *Sb =
nullptr;
4133 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4134 if (
I.arg_size() == 2) {
4137 Va =
I.getOperand(0);
4138 Vb =
I.getOperand(1);
4140 Sa = getShadow(&
I, 0);
4141 Sb = getShadow(&
I, 1);
4142 }
else if (
I.arg_size() == 3) {
4144 Va =
I.getOperand(1);
4145 Vb =
I.getOperand(2);
4147 Sa = getShadow(&
I, 1);
4148 Sb = getShadow(&
I, 2);
4165 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4167 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4177 if (
I.arg_size() == 3) {
4178 [[maybe_unused]]
auto *AccumulatorType =
4180 assert(AccumulatorType == ReturnType);
4183 FixedVectorType *ImplicitReturnType =
4186 if (EltSizeInBits) {
4188 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4200 ReturnType->getNumElements() * ReductionFactor);
4217 VaInt = CreateAppToShadowCast(IRB, Va);
4218 VbInt = CreateAppToShadowCast(IRB, Vb);
4225 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4247 ImplicitReturnType);
4252 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4255 if (
I.arg_size() == 3)
4256 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4258 setShadow(&
I, OutShadow);
4259 setOriginForNaryOp(
I);
4276 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4277 bool PredicateAsOperand) {
4278 if (PredicateAsOperand) {
4280 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4288 Type *ResTy = getShadowTy(&
I);
4289 auto *Shadow0 = getShadow(&
I, 0);
4290 auto *Shadow1 = getShadow(&
I, 1);
4295 setOriginForNaryOp(
I);
4301 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4303 auto *Shadow0 = getShadow(&
I, 0);
4304 auto *Shadow1 = getShadow(&
I, 1);
4306 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4308 setOriginForNaryOp(
I);
4317 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4322 if (AllowShadowCast)
4323 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4327 setOriginForNaryOp(
I);
4337 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4341 Value *Shadow0 = getShadow(&
I, 0);
4347 setOriginForNaryOp(
I);
4353 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4357 Value *OperandShadow = getShadow(&
I, 0);
4359 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4367 setOrigin(&
I, getOrigin(&
I, 0));
4373 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4377 Value *OperandShadow = getShadow(&
I, 0);
4378 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4386 setOrigin(&
I, getOrigin(&
I, 0));
4389 void handleStmxcsr(IntrinsicInst &
I) {
4391 Value *Addr =
I.getArgOperand(0);
4394 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4399 insertCheckShadowOf(Addr, &
I);
4402 void handleLdmxcsr(IntrinsicInst &
I) {
4407 Value *Addr =
I.getArgOperand(0);
4410 Value *ShadowPtr, *OriginPtr;
4411 std::tie(ShadowPtr, OriginPtr) =
4412 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4415 insertCheckShadowOf(Addr, &
I);
4418 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4420 insertCheckShadow(Shadow, Origin, &
I);
4423 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4425 Value *Ptr =
I.getArgOperand(0);
4426 MaybeAlign
Align =
I.getParamAlign(0);
4428 Value *PassThru =
I.getArgOperand(2);
4431 insertCheckShadowOf(Ptr, &
I);
4432 insertCheckShadowOf(Mask, &
I);
4435 if (!PropagateShadow) {
4436 setShadow(&
I, getCleanShadow(&
I));
4437 setOrigin(&
I, getCleanOrigin());
4441 Type *ShadowTy = getShadowTy(&
I);
4443 auto [ShadowPtr, OriginPtr] =
4444 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4448 getShadow(PassThru),
"_msmaskedexpload");
4450 setShadow(&
I, Shadow);
4453 setOrigin(&
I, getCleanOrigin());
4456 void handleMaskedCompressStore(IntrinsicInst &
I) {
4458 Value *Values =
I.getArgOperand(0);
4459 Value *Ptr =
I.getArgOperand(1);
4460 MaybeAlign
Align =
I.getParamAlign(1);
4464 insertCheckShadowOf(Ptr, &
I);
4465 insertCheckShadowOf(Mask, &
I);
4468 Value *Shadow = getShadow(Values);
4469 Type *ElementShadowTy =
4471 auto [ShadowPtr, OriginPtrs] =
4472 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4479 void handleMaskedGather(IntrinsicInst &
I) {
4481 Value *Ptrs =
I.getArgOperand(0);
4482 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4484 Value *PassThru =
I.getArgOperand(2);
4486 Type *PtrsShadowTy = getShadowTy(Ptrs);
4488 insertCheckShadowOf(Mask, &
I);
4492 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4495 if (!PropagateShadow) {
4496 setShadow(&
I, getCleanShadow(&
I));
4497 setOrigin(&
I, getCleanOrigin());
4501 Type *ShadowTy = getShadowTy(&
I);
4503 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4504 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4508 getShadow(PassThru),
"_msmaskedgather");
4510 setShadow(&
I, Shadow);
4513 setOrigin(&
I, getCleanOrigin());
4516 void handleMaskedScatter(IntrinsicInst &
I) {
4518 Value *Values =
I.getArgOperand(0);
4519 Value *Ptrs =
I.getArgOperand(1);
4520 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4523 Type *PtrsShadowTy = getShadowTy(Ptrs);
4525 insertCheckShadowOf(Mask, &
I);
4529 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4532 Value *Shadow = getShadow(Values);
4533 Type *ElementShadowTy =
4535 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4536 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4547 void handleMaskedStore(IntrinsicInst &
I) {
4549 Value *
V =
I.getArgOperand(0);
4550 Value *Ptr =
I.getArgOperand(1);
4551 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4553 Value *Shadow = getShadow(V);
4556 insertCheckShadowOf(Ptr, &
I);
4557 insertCheckShadowOf(Mask, &
I);
4562 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4563 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4567 if (!MS.TrackOrigins)
4570 auto &
DL =
F.getDataLayout();
4571 paintOrigin(IRB, getOrigin(V), OriginPtr,
4580 void handleMaskedLoad(IntrinsicInst &
I) {
4582 Value *Ptr =
I.getArgOperand(0);
4583 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4585 Value *PassThru =
I.getArgOperand(2);
4588 insertCheckShadowOf(Ptr, &
I);
4589 insertCheckShadowOf(Mask, &
I);
4592 if (!PropagateShadow) {
4593 setShadow(&
I, getCleanShadow(&
I));
4594 setOrigin(&
I, getCleanOrigin());
4598 Type *ShadowTy = getShadowTy(&
I);
4599 Value *ShadowPtr, *OriginPtr;
4600 std::tie(ShadowPtr, OriginPtr) =
4601 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4603 getShadow(PassThru),
"_msmaskedld"));
4605 if (!MS.TrackOrigins)
4612 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4617 setOrigin(&
I, Origin);
4633 void handleAVXMaskedStore(IntrinsicInst &
I) {
4638 Value *Dst =
I.getArgOperand(0);
4639 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4644 Value *Src =
I.getArgOperand(2);
4649 Value *SrcShadow = getShadow(Src);
4652 insertCheckShadowOf(Dst, &
I);
4653 insertCheckShadowOf(Mask, &
I);
4656 Value *DstShadowPtr;
4657 Value *DstOriginPtr;
4658 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4659 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4661 SmallVector<Value *, 2> ShadowArgs;
4662 ShadowArgs.
append(1, DstShadowPtr);
4663 ShadowArgs.
append(1, Mask);
4671 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
4674 if (!MS.TrackOrigins)
4678 auto &
DL =
F.getDataLayout();
4679 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4680 DL.getTypeStoreSize(SrcShadow->
getType()),
4699 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4704 Value *Src =
I.getArgOperand(0);
4705 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4713 insertCheckShadowOf(Mask, &
I);
4716 Type *SrcShadowTy = getShadowTy(Src);
4717 Value *SrcShadowPtr, *SrcOriginPtr;
4718 std::tie(SrcShadowPtr, SrcOriginPtr) =
4719 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4721 SmallVector<Value *, 2> ShadowArgs;
4722 ShadowArgs.
append(1, SrcShadowPtr);
4723 ShadowArgs.
append(1, Mask);
4726 I.getType(),
I.getIntrinsicID(), ShadowArgs);
4732 if (!MS.TrackOrigins)
4739 setOrigin(&
I, PtrSrcOrigin);
4748 assert(isFixedIntVector(Idx));
4749 auto IdxVectorSize =
4757 auto *IdxShadow = getShadow(Idx);
4762 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4767 void handleAVXVpermilvar(IntrinsicInst &
I) {
4769 Value *Shadow = getShadow(&
I, 0);
4770 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4774 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4776 I.getType(),
I.getIntrinsicID(), {Shadow, I.getArgOperand(1)});
4779 setOriginForNaryOp(
I);
4784 void handleAVXVpermi2var(IntrinsicInst &
I) {
4789 [[maybe_unused]]
auto ArgVectorSize =
4792 ->getNumElements() == ArgVectorSize);
4794 ->getNumElements() == ArgVectorSize);
4795 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4796 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4797 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4799 Value *AShadow = getShadow(&
I, 0);
4800 Value *Idx =
I.getArgOperand(1);
4801 Value *BShadow = getShadow(&
I, 2);
4803 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4807 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4808 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4810 I.getType(),
I.getIntrinsicID(), {AShadow, Idx, BShadow});
4812 setOriginForNaryOp(
I);
4815 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4819 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4823 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4824 return isFixedIntVectorTy(
V->getType());
4827 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4828 return isFixedFPVectorTy(
V->getType());
4850 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4855 Value *WriteThrough;
4859 WriteThrough =
I.getOperand(2);
4860 Mask =
I.getOperand(3);
4863 WriteThrough =
I.getOperand(1);
4864 Mask =
I.getOperand(2);
4869 assert(isFixedIntVector(WriteThrough));
4871 unsigned ANumElements =
4873 [[maybe_unused]]
unsigned WriteThruNumElements =
4875 assert(ANumElements == WriteThruNumElements ||
4876 ANumElements * 2 == WriteThruNumElements);
4879 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4880 assert(ANumElements == MaskNumElements ||
4881 ANumElements * 2 == MaskNumElements);
4883 assert(WriteThruNumElements == MaskNumElements);
4887 insertCheckShadowOf(Mask, &
I);
4897 Value *AShadow = getShadow(
A);
4898 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4900 if (ANumElements * 2 == MaskNumElements) {
4912 "_ms_mask_bitcast");
4922 getShadowTy(&
I),
"_ms_a_shadow");
4924 Value *WriteThroughShadow = getShadow(WriteThrough);
4926 "_ms_writethru_select");
4928 setShadow(&
I, Shadow);
4929 setOriginForNaryOp(
I);
4932 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4933 SmallVector<int, 8>
Mask;
4934 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4948 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4953 "pclmul 3rd operand must be a constant");
4956 getPclmulMask(Width, Imm & 0x01));
4958 getPclmulMask(Width, Imm & 0x10));
4959 ShadowAndOriginCombiner SOC(
this, IRB);
4960 SOC.Add(Shuf0, getOrigin(&
I, 0));
4961 SOC.Add(Shuf1, getOrigin(&
I, 1));
4966 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4971 Value *Second = getShadow(&
I, 1);
4973 SmallVector<int, 16>
Mask;
4974 Mask.push_back(Width);
4975 for (
unsigned i = 1; i < Width; i++)
4979 setShadow(&
I, Shadow);
4980 setOriginForNaryOp(
I);
4983 void handleVtestIntrinsic(IntrinsicInst &
I) {
4985 Value *Shadow0 = getShadow(&
I, 0);
4986 Value *Shadow1 = getShadow(&
I, 1);
4992 setShadow(&
I, Shadow);
4993 setOriginForNaryOp(
I);
4996 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
5001 Value *Second = getShadow(&
I, 1);
5004 SmallVector<int, 16>
Mask;
5005 Mask.push_back(Width);
5006 for (
unsigned i = 1; i < Width; i++)
5010 setShadow(&
I, Shadow);
5011 setOriginForNaryOp(
I);
5017 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
5018 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5023 ShadowAndOriginCombiner SC(
this, IRB);
5024 SC.Add(
I.getArgOperand(0));
5032 void handleAbsIntrinsic(IntrinsicInst &
I) {
5034 Value *Src =
I.getArgOperand(0);
5035 Value *IsIntMinPoison =
I.getArgOperand(1);
5037 assert(
I.getType()->isIntOrIntVectorTy());
5039 assert(Src->getType() ==
I.getType());
5045 Value *SrcShadow = getShadow(Src);
5049 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5052 Value *PoisonedShadow = getPoisonedShadow(Src);
5053 Value *PoisonedIfIntMinShadow =
5056 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5058 setShadow(&
I, Shadow);
5059 setOrigin(&
I, getOrigin(&
I, 0));
5062 void handleIsFpClass(IntrinsicInst &
I) {
5064 Value *Shadow = getShadow(&
I, 0);
5065 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5066 setOrigin(&
I, getOrigin(&
I, 0));
5069 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5071 Value *Shadow0 = getShadow(&
I, 0);
5072 Value *Shadow1 = getShadow(&
I, 1);
5075 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5081 setShadow(&
I, Shadow);
5082 setOriginForNaryOp(
I);
5088 Value *Shadow = getShadow(V);
5110 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5115 Value *WriteThrough =
I.getOperand(1);
5119 assert(isFixedIntVector(WriteThrough));
5121 unsigned ANumElements =
5123 unsigned OutputNumElements =
5125 assert(ANumElements == OutputNumElements ||
5126 ANumElements * 2 == OutputNumElements);
5136 insertCheckShadowOf(Mask, &
I);
5139 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5140 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5141 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5152 if (ANumElements != OutputNumElements) {
5154 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5161 Value *AShadow = getShadow(
A);
5165 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5175 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5176 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5178 Value *WriteThroughShadow = getShadow(WriteThrough);
5181 setShadow(&
I, Shadow);
5182 setOriginForNaryOp(
I);
5216 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5217 SmallVector<unsigned, 4> DataIndices,
5218 unsigned WriteThruIndex,
5219 unsigned MaskIndex) {
5222 unsigned NumArgs =
I.arg_size();
5224 assert(WriteThruIndex < NumArgs);
5225 assert(MaskIndex < NumArgs);
5226 assert(WriteThruIndex != MaskIndex);
5227 Value *WriteThru =
I.getOperand(WriteThruIndex);
5229 unsigned OutputNumElements =
5234 bool isData[16] = {
false};
5236 for (
unsigned i : DataIndices) {
5238 assert(i != WriteThruIndex);
5245 [[maybe_unused]]
unsigned ANumElements =
5247 assert(ANumElements == OutputNumElements);
5252 assert(isFixedFPVector(WriteThru));
5254 for (
unsigned i = 0; i < NumArgs; ++i) {
5255 if (!isData[i] && i != WriteThruIndex) {
5258 assert(
I.getOperand(i)->getType()->isIntegerTy());
5259 insertCheckShadowOf(
I.getOperand(i), &
I);
5264 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5265 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5266 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5273 Value *DataShadow =
nullptr;
5274 for (
unsigned i : DataIndices) {
5277 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5279 DataShadow = getShadow(
A);
5287 Value *WriteThruShadow = getShadow(WriteThru);
5290 setShadow(&
I, Shadow);
5292 setOriginForNaryOp(
I);
5302 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5308 Value *WriteThrough =
I.getOperand(2);
5315 insertCheckShadowOf(Mask, &
I);
5319 unsigned NumElements =
5321 assert(NumElements == 8);
5322 assert(
A->getType() ==
B->getType());
5324 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5327 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5328 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5330 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5332 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5339 Value *AShadow = getShadow(
A);
5340 Value *DstLowerShadow =
5341 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5343 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5346 setShadow(&
I, DstShadow);
5347 setOriginForNaryOp(
I);
5377 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5388 ->getScalarSizeInBits() == 8);
5390 assert(
A->getType() ==
X->getType());
5392 assert(
B->getType()->isIntegerTy());
5393 assert(
B->getType()->getScalarSizeInBits() == 8);
5395 assert(
I.getType() ==
A->getType());
5397 Value *AShadow = getShadow(
A);
5398 Value *XShadow = getShadow(
X);
5399 Value *BZeroShadow = getCleanShadow(
B);
5402 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5404 {X, AShadow, BZeroShadow});
5406 {XShadow, A, BZeroShadow});
5409 Value *BShadow = getShadow(
B);
5410 Value *BBroadcastShadow = getCleanShadow(AShadow);
5415 for (
unsigned i = 0; i < NumElements; i++)
5419 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5420 setOriginForNaryOp(
I);
5434 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5435 unsigned int numArgs =
I.arg_size();
5438 assert(
I.getType()->isStructTy());
5448 assert(4 <= numArgs && numArgs <= 6);
5462 for (
unsigned int i = 0; i < numArgs - 2; i++)
5463 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5466 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5470 insertCheckShadowOf(LaneNumber, &
I);
5473 Value *Src =
I.getArgOperand(numArgs - 1);
5474 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5476 Type *SrcShadowTy = getShadowTy(Src);
5477 auto [SrcShadowPtr, SrcOriginPtr] =
5478 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5485 getShadowTy(&
I),
I.getIntrinsicID(), ShadowArgs);
5488 if (!MS.TrackOrigins)
5492 setOrigin(&
I, PtrSrcOrigin);
5509 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5513 int numArgOperands =
I.arg_size();
5516 assert(numArgOperands >= 1);
5517 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5519 int skipTrailingOperands = 1;
5522 insertCheckShadowOf(Addr, &
I);
5526 skipTrailingOperands++;
5527 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5529 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5532 SmallVector<Value *, 8> ShadowArgs;
5534 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5536 Value *Shadow = getShadow(&
I, i);
5537 ShadowArgs.
append(1, Shadow);
5554 (numArgOperands - skipTrailingOperands));
5555 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5559 I.getArgOperand(numArgOperands - skipTrailingOperands));
5561 Value *OutputShadowPtr, *OutputOriginPtr;
5563 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5564 Addr, IRB, OutputShadowTy,
Align(1),
true);
5565 ShadowArgs.
append(1, OutputShadowPtr);
5568 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
5571 if (MS.TrackOrigins) {
5579 OriginCombiner OC(
this, IRB);
5580 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5581 OC.Add(
I.getArgOperand(i));
5583 const DataLayout &
DL =
F.getDataLayout();
5584 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5617 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5621 Value *
R =
I.getArgOperand(0);
5622 Value *
A =
I.getArgOperand(1);
5623 Value *
B =
I.getArgOperand(2);
5625 assert(
I.getType() ==
R->getType());
5650 Value *ShadowR = getShadow(&
I, 0);
5651 Value *ShadowA = getShadow(&
I, 1);
5652 Value *ShadowB = getShadow(&
I, 2);
5670 {getCleanShadow(RTy), ShadowA, ShadowB});
5696 {RZeros, ShadowA, ShadowB});
5710 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5711 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5713 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5715 setOriginForNaryOp(
I);
5740 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5742 unsigned int trailingVerbatimArgs) {
5745 assert(trailingVerbatimArgs <
I.arg_size());
5747 SmallVector<Value *, 8> ShadowArgs;
5749 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5750 Value *Shadow = getShadow(&
I, i);
5758 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5760 Value *Arg =
I.getArgOperand(i);
5765 Value *CombinedShadow = CI;
5768 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5771 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5772 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5777 setOriginForNaryOp(
I);
5783 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5789 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5790 switch (
I.getIntrinsicID()) {
5791 case Intrinsic::uadd_with_overflow:
5792 case Intrinsic::sadd_with_overflow:
5793 case Intrinsic::usub_with_overflow:
5794 case Intrinsic::ssub_with_overflow:
5795 case Intrinsic::umul_with_overflow:
5796 case Intrinsic::smul_with_overflow:
5797 handleArithmeticWithOverflow(
I);
5799 case Intrinsic::abs:
5800 handleAbsIntrinsic(
I);
5802 case Intrinsic::bitreverse:
5803 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5806 case Intrinsic::is_fpclass:
5809 case Intrinsic::lifetime_start:
5810 handleLifetimeStart(
I);
5812 case Intrinsic::launder_invariant_group:
5813 case Intrinsic::strip_invariant_group:
5814 handleInvariantGroup(
I);
5816 case Intrinsic::bswap:
5819 case Intrinsic::ctlz:
5820 case Intrinsic::cttz:
5821 handleCountLeadingTrailingZeros(
I);
5823 case Intrinsic::masked_compressstore:
5824 handleMaskedCompressStore(
I);
5826 case Intrinsic::masked_expandload:
5827 handleMaskedExpandLoad(
I);
5829 case Intrinsic::masked_gather:
5830 handleMaskedGather(
I);
5832 case Intrinsic::masked_scatter:
5833 handleMaskedScatter(
I);
5835 case Intrinsic::masked_store:
5836 handleMaskedStore(
I);
5838 case Intrinsic::masked_load:
5839 handleMaskedLoad(
I);
5841 case Intrinsic::vector_reduce_and:
5842 handleVectorReduceAndIntrinsic(
I);
5844 case Intrinsic::vector_reduce_or:
5845 handleVectorReduceOrIntrinsic(
I);
5848 case Intrinsic::vector_reduce_add:
5849 case Intrinsic::vector_reduce_xor:
5850 case Intrinsic::vector_reduce_mul:
5853 case Intrinsic::vector_reduce_smax:
5854 case Intrinsic::vector_reduce_smin:
5855 case Intrinsic::vector_reduce_umax:
5856 case Intrinsic::vector_reduce_umin:
5859 case Intrinsic::vector_reduce_fmax:
5860 case Intrinsic::vector_reduce_fmin:
5861 handleVectorReduceIntrinsic(
I,
false);
5864 case Intrinsic::vector_reduce_fadd:
5865 case Intrinsic::vector_reduce_fmul:
5866 handleVectorReduceWithStarterIntrinsic(
I);
5869 case Intrinsic::scmp:
5870 case Intrinsic::ucmp: {
5875 case Intrinsic::fshl:
5876 case Intrinsic::fshr:
5877 handleFunnelShift(
I);
5880 case Intrinsic::pdep:
5881 case Intrinsic::pext:
5882 handleGenericBitManipulation(
I);
5885 case Intrinsic::is_constant:
5887 setShadow(&
I, getCleanShadow(&
I));
5888 setOrigin(&
I, getCleanOrigin());
5895 case Intrinsic::fptosi_sat:
5896 case Intrinsic::fptoui_sat:
5897 handleGenericVectorConvertIntrinsic(
I,
false);
5907 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
5908 switch (
I.getIntrinsicID()) {
5909 case Intrinsic::x86_sse_stmxcsr:
5912 case Intrinsic::x86_sse_ldmxcsr:
5919 case Intrinsic::x86_avx512_vcvtsd2usi64:
5920 case Intrinsic::x86_avx512_vcvtsd2usi32:
5921 case Intrinsic::x86_avx512_vcvtss2usi64:
5922 case Intrinsic::x86_avx512_vcvtss2usi32:
5923 case Intrinsic::x86_avx512_cvttss2usi64:
5924 case Intrinsic::x86_avx512_cvttss2usi:
5925 case Intrinsic::x86_avx512_cvttsd2usi64:
5926 case Intrinsic::x86_avx512_cvttsd2usi:
5927 case Intrinsic::x86_avx512_cvtusi2ss:
5928 case Intrinsic::x86_avx512_cvtusi642sd:
5929 case Intrinsic::x86_avx512_cvtusi642ss:
5930 handleSSEVectorConvertIntrinsic(
I, 1,
true);
5932 case Intrinsic::x86_sse2_cvtsd2si64:
5933 case Intrinsic::x86_sse2_cvtsd2si:
5934 case Intrinsic::x86_sse2_cvtsd2ss:
5935 case Intrinsic::x86_sse2_cvttsd2si64:
5936 case Intrinsic::x86_sse2_cvttsd2si:
5937 case Intrinsic::x86_sse_cvtss2si64:
5938 case Intrinsic::x86_sse_cvtss2si:
5939 case Intrinsic::x86_sse_cvttss2si64:
5940 case Intrinsic::x86_sse_cvttss2si:
5941 handleSSEVectorConvertIntrinsic(
I, 1);
5943 case Intrinsic::x86_sse_cvtps2pi:
5944 case Intrinsic::x86_sse_cvttps2pi:
5945 handleSSEVectorConvertIntrinsic(
I, 2);
5953 case Intrinsic::x86_vcvtps2ph_128:
5954 case Intrinsic::x86_vcvtps2ph_256: {
5955 handleSSEVectorConvertIntrinsicByProp(
I,
true);
5964 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
5965 handleAVX512VectorConvertFPToInt(
I,
false);
5970 case Intrinsic::x86_sse2_cvtpd2ps:
5971 case Intrinsic::x86_sse2_cvtps2dq:
5972 case Intrinsic::x86_sse2_cvtpd2dq:
5973 case Intrinsic::x86_sse2_cvttps2dq:
5974 case Intrinsic::x86_sse2_cvttpd2dq:
5975 case Intrinsic::x86_avx_cvt_pd2_ps_256:
5976 case Intrinsic::x86_avx_cvt_ps2dq_256:
5977 case Intrinsic::x86_avx_cvt_pd2dq_256:
5978 case Intrinsic::x86_avx_cvtt_ps2dq_256:
5979 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
5980 handleSSEVectorConvertIntrinsicByProp(
I,
false);
5991 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
5992 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
5993 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
5994 handleAVX512VectorConvertFPToInt(
I,
true);
5998 case Intrinsic::x86_avx512_psll_w_512:
5999 case Intrinsic::x86_avx512_psll_d_512:
6000 case Intrinsic::x86_avx512_psll_q_512:
6001 case Intrinsic::x86_avx512_pslli_w_512:
6002 case Intrinsic::x86_avx512_pslli_d_512:
6003 case Intrinsic::x86_avx512_pslli_q_512:
6004 case Intrinsic::x86_avx512_psrl_w_512:
6005 case Intrinsic::x86_avx512_psrl_d_512:
6006 case Intrinsic::x86_avx512_psrl_q_512:
6007 case Intrinsic::x86_avx512_psra_w_512:
6008 case Intrinsic::x86_avx512_psra_d_512:
6009 case Intrinsic::x86_avx512_psra_q_512:
6010 case Intrinsic::x86_avx512_psrli_w_512:
6011 case Intrinsic::x86_avx512_psrli_d_512:
6012 case Intrinsic::x86_avx512_psrli_q_512:
6013 case Intrinsic::x86_avx512_psrai_w_512:
6014 case Intrinsic::x86_avx512_psrai_d_512:
6015 case Intrinsic::x86_avx512_psrai_q_512:
6016 case Intrinsic::x86_avx512_psra_q_256:
6017 case Intrinsic::x86_avx512_psra_q_128:
6018 case Intrinsic::x86_avx512_psrai_q_256:
6019 case Intrinsic::x86_avx512_psrai_q_128:
6020 case Intrinsic::x86_avx2_psll_w:
6021 case Intrinsic::x86_avx2_psll_d:
6022 case Intrinsic::x86_avx2_psll_q:
6023 case Intrinsic::x86_avx2_pslli_w:
6024 case Intrinsic::x86_avx2_pslli_d:
6025 case Intrinsic::x86_avx2_pslli_q:
6026 case Intrinsic::x86_avx2_psrl_w:
6027 case Intrinsic::x86_avx2_psrl_d:
6028 case Intrinsic::x86_avx2_psrl_q:
6029 case Intrinsic::x86_avx2_psra_w:
6030 case Intrinsic::x86_avx2_psra_d:
6031 case Intrinsic::x86_avx2_psrli_w:
6032 case Intrinsic::x86_avx2_psrli_d:
6033 case Intrinsic::x86_avx2_psrli_q:
6034 case Intrinsic::x86_avx2_psrai_w:
6035 case Intrinsic::x86_avx2_psrai_d:
6036 case Intrinsic::x86_sse2_psll_w:
6037 case Intrinsic::x86_sse2_psll_d:
6038 case Intrinsic::x86_sse2_psll_q:
6039 case Intrinsic::x86_sse2_pslli_w:
6040 case Intrinsic::x86_sse2_pslli_d:
6041 case Intrinsic::x86_sse2_pslli_q:
6042 case Intrinsic::x86_sse2_psrl_w:
6043 case Intrinsic::x86_sse2_psrl_d:
6044 case Intrinsic::x86_sse2_psrl_q:
6045 case Intrinsic::x86_sse2_psra_w:
6046 case Intrinsic::x86_sse2_psra_d:
6047 case Intrinsic::x86_sse2_psrli_w:
6048 case Intrinsic::x86_sse2_psrli_d:
6049 case Intrinsic::x86_sse2_psrli_q:
6050 case Intrinsic::x86_sse2_psrai_w:
6051 case Intrinsic::x86_sse2_psrai_d:
6052 case Intrinsic::x86_mmx_psll_w:
6053 case Intrinsic::x86_mmx_psll_d:
6054 case Intrinsic::x86_mmx_psll_q:
6055 case Intrinsic::x86_mmx_pslli_w:
6056 case Intrinsic::x86_mmx_pslli_d:
6057 case Intrinsic::x86_mmx_pslli_q:
6058 case Intrinsic::x86_mmx_psrl_w:
6059 case Intrinsic::x86_mmx_psrl_d:
6060 case Intrinsic::x86_mmx_psrl_q:
6061 case Intrinsic::x86_mmx_psra_w:
6062 case Intrinsic::x86_mmx_psra_d:
6063 case Intrinsic::x86_mmx_psrli_w:
6064 case Intrinsic::x86_mmx_psrli_d:
6065 case Intrinsic::x86_mmx_psrli_q:
6066 case Intrinsic::x86_mmx_psrai_w:
6067 case Intrinsic::x86_mmx_psrai_d:
6068 handleVectorShiftIntrinsic(
I,
false);
6070 case Intrinsic::x86_avx2_psllv_d:
6071 case Intrinsic::x86_avx2_psllv_d_256:
6072 case Intrinsic::x86_avx512_psllv_d_512:
6073 case Intrinsic::x86_avx2_psllv_q:
6074 case Intrinsic::x86_avx2_psllv_q_256:
6075 case Intrinsic::x86_avx512_psllv_q_512:
6076 case Intrinsic::x86_avx2_psrlv_d:
6077 case Intrinsic::x86_avx2_psrlv_d_256:
6078 case Intrinsic::x86_avx512_psrlv_d_512:
6079 case Intrinsic::x86_avx2_psrlv_q:
6080 case Intrinsic::x86_avx2_psrlv_q_256:
6081 case Intrinsic::x86_avx512_psrlv_q_512:
6082 case Intrinsic::x86_avx2_psrav_d:
6083 case Intrinsic::x86_avx2_psrav_d_256:
6084 case Intrinsic::x86_avx512_psrav_d_512:
6085 case Intrinsic::x86_avx512_psrav_q_128:
6086 case Intrinsic::x86_avx512_psrav_q_256:
6087 case Intrinsic::x86_avx512_psrav_q_512:
6088 handleVectorShiftIntrinsic(
I,
true);
6092 case Intrinsic::x86_sse2_packsswb_128:
6093 case Intrinsic::x86_sse2_packssdw_128:
6094 case Intrinsic::x86_sse2_packuswb_128:
6095 case Intrinsic::x86_sse41_packusdw:
6096 case Intrinsic::x86_avx2_packsswb:
6097 case Intrinsic::x86_avx2_packssdw:
6098 case Intrinsic::x86_avx2_packuswb:
6099 case Intrinsic::x86_avx2_packusdw:
6105 case Intrinsic::x86_avx512_packsswb_512:
6106 case Intrinsic::x86_avx512_packssdw_512:
6107 case Intrinsic::x86_avx512_packuswb_512:
6108 case Intrinsic::x86_avx512_packusdw_512:
6109 handleVectorPackIntrinsic(
I);
6112 case Intrinsic::x86_sse41_pblendvb:
6113 case Intrinsic::x86_sse41_blendvpd:
6114 case Intrinsic::x86_sse41_blendvps:
6115 case Intrinsic::x86_avx_blendv_pd_256:
6116 case Intrinsic::x86_avx_blendv_ps_256:
6117 case Intrinsic::x86_avx2_pblendvb:
6118 handleBlendvIntrinsic(
I);
6121 case Intrinsic::x86_avx_dp_ps_256:
6122 case Intrinsic::x86_sse41_dppd:
6123 case Intrinsic::x86_sse41_dpps:
6124 handleDppIntrinsic(
I);
6127 case Intrinsic::x86_mmx_packsswb:
6128 case Intrinsic::x86_mmx_packuswb:
6129 handleVectorPackIntrinsic(
I, 16);
6132 case Intrinsic::x86_mmx_packssdw:
6133 handleVectorPackIntrinsic(
I, 32);
6136 case Intrinsic::x86_mmx_psad_bw:
6137 handleVectorSadIntrinsic(
I,
true);
6139 case Intrinsic::x86_sse2_psad_bw:
6140 case Intrinsic::x86_avx2_psad_bw:
6141 handleVectorSadIntrinsic(
I);
6167 case Intrinsic::x86_sse2_pmadd_wd:
6168 case Intrinsic::x86_avx2_pmadd_wd:
6169 case Intrinsic::x86_avx512_pmaddw_d_512:
6170 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6171 case Intrinsic::x86_avx2_pmadd_ub_sw:
6172 case Intrinsic::x86_avx512_pmaddubs_w_512:
6173 handleVectorDotProductIntrinsic(
I, 2,
6180 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6181 handleVectorDotProductIntrinsic(
I, 2,
6188 case Intrinsic::x86_mmx_pmadd_wd:
6189 handleVectorDotProductIntrinsic(
I, 2,
6198 case Intrinsic::aarch64_neon_bfmlalt:
6199 handleVectorDotProductIntrinsic(
I, 2,
6207 case Intrinsic::aarch64_neon_bfmlalb:
6208 handleVectorDotProductIntrinsic(
I, 2,
6306 case Intrinsic::x86_avx512_vpdpbusd_128:
6307 case Intrinsic::x86_avx512_vpdpbusd_256:
6308 case Intrinsic::x86_avx512_vpdpbusd_512:
6309 case Intrinsic::x86_avx512_vpdpbusds_128:
6310 case Intrinsic::x86_avx512_vpdpbusds_256:
6311 case Intrinsic::x86_avx512_vpdpbusds_512:
6312 case Intrinsic::x86_avx2_vpdpbssd_128:
6313 case Intrinsic::x86_avx2_vpdpbssd_256:
6314 case Intrinsic::x86_avx10_vpdpbssd_512:
6315 case Intrinsic::x86_avx2_vpdpbssds_128:
6316 case Intrinsic::x86_avx2_vpdpbssds_256:
6317 case Intrinsic::x86_avx10_vpdpbssds_512:
6318 case Intrinsic::x86_avx2_vpdpbsud_128:
6319 case Intrinsic::x86_avx2_vpdpbsud_256:
6320 case Intrinsic::x86_avx10_vpdpbsud_512:
6321 case Intrinsic::x86_avx2_vpdpbsuds_128:
6322 case Intrinsic::x86_avx2_vpdpbsuds_256:
6323 case Intrinsic::x86_avx10_vpdpbsuds_512:
6324 case Intrinsic::x86_avx2_vpdpbuud_128:
6325 case Intrinsic::x86_avx2_vpdpbuud_256:
6326 case Intrinsic::x86_avx10_vpdpbuud_512:
6327 case Intrinsic::x86_avx2_vpdpbuuds_128:
6328 case Intrinsic::x86_avx2_vpdpbuuds_256:
6329 case Intrinsic::x86_avx10_vpdpbuuds_512:
6330 handleVectorDotProductIntrinsic(
I, 4,
6428 case Intrinsic::x86_avx512_vpdpwssd_128:
6429 case Intrinsic::x86_avx512_vpdpwssd_256:
6430 case Intrinsic::x86_avx512_vpdpwssd_512:
6431 case Intrinsic::x86_avx512_vpdpwssds_128:
6432 case Intrinsic::x86_avx512_vpdpwssds_256:
6433 case Intrinsic::x86_avx512_vpdpwssds_512:
6434 case Intrinsic::x86_avx2_vpdpwsud_128:
6435 case Intrinsic::x86_avx2_vpdpwsud_256:
6436 case Intrinsic::x86_avx10_vpdpwsud_512:
6437 case Intrinsic::x86_avx2_vpdpwsuds_128:
6438 case Intrinsic::x86_avx2_vpdpwsuds_256:
6439 case Intrinsic::x86_avx10_vpdpwsuds_512:
6440 case Intrinsic::x86_avx2_vpdpwusd_128:
6441 case Intrinsic::x86_avx2_vpdpwusd_256:
6442 case Intrinsic::x86_avx10_vpdpwusd_512:
6443 case Intrinsic::x86_avx2_vpdpwusds_128:
6444 case Intrinsic::x86_avx2_vpdpwusds_256:
6445 case Intrinsic::x86_avx10_vpdpwusds_512:
6446 case Intrinsic::x86_avx2_vpdpwuud_128:
6447 case Intrinsic::x86_avx2_vpdpwuud_256:
6448 case Intrinsic::x86_avx10_vpdpwuud_512:
6449 case Intrinsic::x86_avx2_vpdpwuuds_128:
6450 case Intrinsic::x86_avx2_vpdpwuuds_256:
6451 case Intrinsic::x86_avx10_vpdpwuuds_512:
6452 handleVectorDotProductIntrinsic(
I, 2,
6466 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6467 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6468 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6469 handleVectorDotProductIntrinsic(
I, 2,
6475 case Intrinsic::x86_sse_cmp_ss:
6476 case Intrinsic::x86_sse2_cmp_sd:
6477 case Intrinsic::x86_sse_comieq_ss:
6478 case Intrinsic::x86_sse_comilt_ss:
6479 case Intrinsic::x86_sse_comile_ss:
6480 case Intrinsic::x86_sse_comigt_ss:
6481 case Intrinsic::x86_sse_comige_ss:
6482 case Intrinsic::x86_sse_comineq_ss:
6483 case Intrinsic::x86_sse_ucomieq_ss:
6484 case Intrinsic::x86_sse_ucomilt_ss:
6485 case Intrinsic::x86_sse_ucomile_ss:
6486 case Intrinsic::x86_sse_ucomigt_ss:
6487 case Intrinsic::x86_sse_ucomige_ss:
6488 case Intrinsic::x86_sse_ucomineq_ss:
6489 case Intrinsic::x86_sse2_comieq_sd:
6490 case Intrinsic::x86_sse2_comilt_sd:
6491 case Intrinsic::x86_sse2_comile_sd:
6492 case Intrinsic::x86_sse2_comigt_sd:
6493 case Intrinsic::x86_sse2_comige_sd:
6494 case Intrinsic::x86_sse2_comineq_sd:
6495 case Intrinsic::x86_sse2_ucomieq_sd:
6496 case Intrinsic::x86_sse2_ucomilt_sd:
6497 case Intrinsic::x86_sse2_ucomile_sd:
6498 case Intrinsic::x86_sse2_ucomigt_sd:
6499 case Intrinsic::x86_sse2_ucomige_sd:
6500 case Intrinsic::x86_sse2_ucomineq_sd:
6501 handleVectorCompareScalarIntrinsic(
I);
6504 case Intrinsic::x86_avx_cmp_pd_256:
6505 case Intrinsic::x86_avx_cmp_ps_256:
6506 case Intrinsic::x86_sse2_cmp_pd:
6507 case Intrinsic::x86_sse_cmp_ps:
6508 handleVectorComparePackedIntrinsic(
I,
true);
6511 case Intrinsic::x86_bmi_bextr_32:
6512 case Intrinsic::x86_bmi_bextr_64:
6513 case Intrinsic::x86_bmi_bzhi_32:
6514 case Intrinsic::x86_bmi_bzhi_64:
6515 handleGenericBitManipulation(
I);
6518 case Intrinsic::x86_pclmulqdq:
6519 case Intrinsic::x86_pclmulqdq_256:
6520 case Intrinsic::x86_pclmulqdq_512:
6521 handlePclmulIntrinsic(
I);
6524 case Intrinsic::x86_avx_round_pd_256:
6525 case Intrinsic::x86_avx_round_ps_256:
6526 case Intrinsic::x86_sse41_round_pd:
6527 case Intrinsic::x86_sse41_round_ps:
6528 handleRoundPdPsIntrinsic(
I);
6531 case Intrinsic::x86_sse41_round_sd:
6532 case Intrinsic::x86_sse41_round_ss:
6533 handleUnarySdSsIntrinsic(
I);
6536 case Intrinsic::x86_sse2_max_sd:
6537 case Intrinsic::x86_sse_max_ss:
6538 case Intrinsic::x86_sse2_min_sd:
6539 case Intrinsic::x86_sse_min_ss:
6540 handleBinarySdSsIntrinsic(
I);
6543 case Intrinsic::x86_avx_vtestc_pd:
6544 case Intrinsic::x86_avx_vtestc_pd_256:
6545 case Intrinsic::x86_avx_vtestc_ps:
6546 case Intrinsic::x86_avx_vtestc_ps_256:
6547 case Intrinsic::x86_avx_vtestnzc_pd:
6548 case Intrinsic::x86_avx_vtestnzc_pd_256:
6549 case Intrinsic::x86_avx_vtestnzc_ps:
6550 case Intrinsic::x86_avx_vtestnzc_ps_256:
6551 case Intrinsic::x86_avx_vtestz_pd:
6552 case Intrinsic::x86_avx_vtestz_pd_256:
6553 case Intrinsic::x86_avx_vtestz_ps:
6554 case Intrinsic::x86_avx_vtestz_ps_256:
6555 case Intrinsic::x86_avx_ptestc_256:
6556 case Intrinsic::x86_avx_ptestnzc_256:
6557 case Intrinsic::x86_avx_ptestz_256:
6558 case Intrinsic::x86_sse41_ptestc:
6559 case Intrinsic::x86_sse41_ptestnzc:
6560 case Intrinsic::x86_sse41_ptestz:
6561 handleVtestIntrinsic(
I);
6565 case Intrinsic::x86_ssse3_phadd_w:
6566 case Intrinsic::x86_ssse3_phadd_w_128:
6567 case Intrinsic::x86_ssse3_phsub_w:
6568 case Intrinsic::x86_ssse3_phsub_w_128:
6569 handlePairwiseShadowOrIntrinsic(
I, 1,
6573 case Intrinsic::x86_avx2_phadd_w:
6574 case Intrinsic::x86_avx2_phsub_w:
6575 handlePairwiseShadowOrIntrinsic(
I, 2,
6580 case Intrinsic::x86_ssse3_phadd_d:
6581 case Intrinsic::x86_ssse3_phadd_d_128:
6582 case Intrinsic::x86_ssse3_phsub_d:
6583 case Intrinsic::x86_ssse3_phsub_d_128:
6584 handlePairwiseShadowOrIntrinsic(
I, 1,
6588 case Intrinsic::x86_avx2_phadd_d:
6589 case Intrinsic::x86_avx2_phsub_d:
6590 handlePairwiseShadowOrIntrinsic(
I, 2,
6595 case Intrinsic::x86_ssse3_phadd_sw:
6596 case Intrinsic::x86_ssse3_phadd_sw_128:
6597 case Intrinsic::x86_ssse3_phsub_sw:
6598 case Intrinsic::x86_ssse3_phsub_sw_128:
6599 handlePairwiseShadowOrIntrinsic(
I, 1,
6603 case Intrinsic::x86_avx2_phadd_sw:
6604 case Intrinsic::x86_avx2_phsub_sw:
6605 handlePairwiseShadowOrIntrinsic(
I, 2,
6610 case Intrinsic::x86_sse3_hadd_ps:
6611 case Intrinsic::x86_sse3_hadd_pd:
6612 case Intrinsic::x86_sse3_hsub_ps:
6613 case Intrinsic::x86_sse3_hsub_pd:
6614 handlePairwiseShadowOrIntrinsic(
I, 1);
6617 case Intrinsic::x86_avx_hadd_pd_256:
6618 case Intrinsic::x86_avx_hadd_ps_256:
6619 case Intrinsic::x86_avx_hsub_pd_256:
6620 case Intrinsic::x86_avx_hsub_ps_256:
6621 handlePairwiseShadowOrIntrinsic(
I, 2);
6624 case Intrinsic::x86_avx_maskstore_ps:
6625 case Intrinsic::x86_avx_maskstore_pd:
6626 case Intrinsic::x86_avx_maskstore_ps_256:
6627 case Intrinsic::x86_avx_maskstore_pd_256:
6628 case Intrinsic::x86_avx2_maskstore_d:
6629 case Intrinsic::x86_avx2_maskstore_q:
6630 case Intrinsic::x86_avx2_maskstore_d_256:
6631 case Intrinsic::x86_avx2_maskstore_q_256: {
6632 handleAVXMaskedStore(
I);
6636 case Intrinsic::x86_avx_maskload_ps:
6637 case Intrinsic::x86_avx_maskload_pd:
6638 case Intrinsic::x86_avx_maskload_ps_256:
6639 case Intrinsic::x86_avx_maskload_pd_256:
6640 case Intrinsic::x86_avx2_maskload_d:
6641 case Intrinsic::x86_avx2_maskload_q:
6642 case Intrinsic::x86_avx2_maskload_d_256:
6643 case Intrinsic::x86_avx2_maskload_q_256: {
6644 handleAVXMaskedLoad(
I);
6649 case Intrinsic::x86_avx512fp16_add_ph_512:
6650 case Intrinsic::x86_avx512fp16_sub_ph_512:
6651 case Intrinsic::x86_avx512fp16_mul_ph_512:
6652 case Intrinsic::x86_avx512fp16_div_ph_512:
6653 case Intrinsic::x86_avx512fp16_max_ph_512:
6654 case Intrinsic::x86_avx512fp16_min_ph_512:
6655 case Intrinsic::x86_avx512_min_ps_512:
6656 case Intrinsic::x86_avx512_min_pd_512:
6657 case Intrinsic::x86_avx512_max_ps_512:
6658 case Intrinsic::x86_avx512_max_pd_512: {
6663 [[maybe_unused]]
bool Success =
6664 maybeHandleSimpleNomemIntrinsic(
I, 1);
6669 case Intrinsic::x86_avx_vpermilvar_pd:
6670 case Intrinsic::x86_avx_vpermilvar_pd_256:
6671 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6672 case Intrinsic::x86_avx_vpermilvar_ps:
6673 case Intrinsic::x86_avx_vpermilvar_ps_256:
6674 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6675 handleAVXVpermilvar(
I);
6679 case Intrinsic::x86_avx512_vpermi2var_d_128:
6680 case Intrinsic::x86_avx512_vpermi2var_d_256:
6681 case Intrinsic::x86_avx512_vpermi2var_d_512:
6682 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6683 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6684 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6685 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6686 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6687 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6688 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6689 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6690 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6691 case Intrinsic::x86_avx512_vpermi2var_q_128:
6692 case Intrinsic::x86_avx512_vpermi2var_q_256:
6693 case Intrinsic::x86_avx512_vpermi2var_q_512:
6694 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6695 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6696 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6697 handleAVXVpermi2var(
I);
6711 case Intrinsic::x86_avx2_pshuf_b:
6712 case Intrinsic::x86_sse_pshuf_w:
6713 case Intrinsic::x86_ssse3_pshuf_b_128:
6714 case Intrinsic::x86_ssse3_pshuf_b:
6715 case Intrinsic::x86_avx512_pshuf_b_512:
6716 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6722 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6723 case Intrinsic::x86_avx512_mask_pmov_db_128:
6724 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6725 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6726 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6727 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6728 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6729 case Intrinsic::x86_avx512_mask_pmov_db_256:
6730 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6731 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6732 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6733 case Intrinsic::x86_avx512_mask_pmov_db_512:
6734 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6735 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6738 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6746 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6747 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6748 handleIntrinsicByApplyingToShadow(
I,
6749 Intrinsic::x86_avx512_mask_pmov_dw_512,
6754 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6755 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6756 handleIntrinsicByApplyingToShadow(
I,
6757 Intrinsic::x86_avx512_mask_pmov_dw_256,
6761 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6762 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6763 handleIntrinsicByApplyingToShadow(
I,
6764 Intrinsic::x86_avx512_mask_pmov_dw_128,
6768 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6769 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6770 handleIntrinsicByApplyingToShadow(
I,
6771 Intrinsic::x86_avx512_mask_pmov_db_512,
6776 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6777 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6778 handleIntrinsicByApplyingToShadow(
I,
6779 Intrinsic::x86_avx512_mask_pmov_db_256,
6783 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6784 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6785 handleIntrinsicByApplyingToShadow(
I,
6786 Intrinsic::x86_avx512_mask_pmov_db_128,
6790 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6791 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6792 handleIntrinsicByApplyingToShadow(
I,
6793 Intrinsic::x86_avx512_mask_pmov_qb_512,
6798 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6799 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6800 handleIntrinsicByApplyingToShadow(
I,
6801 Intrinsic::x86_avx512_mask_pmov_qb_256,
6805 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6806 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6807 handleIntrinsicByApplyingToShadow(
I,
6808 Intrinsic::x86_avx512_mask_pmov_qb_128,
6812 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6813 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6814 handleIntrinsicByApplyingToShadow(
I,
6815 Intrinsic::x86_avx512_mask_pmov_qw_512,
6820 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6821 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6822 handleIntrinsicByApplyingToShadow(
I,
6823 Intrinsic::x86_avx512_mask_pmov_qw_256,
6827 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6828 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6829 handleIntrinsicByApplyingToShadow(
I,
6830 Intrinsic::x86_avx512_mask_pmov_qw_128,
6834 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6835 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6836 handleIntrinsicByApplyingToShadow(
I,
6837 Intrinsic::x86_avx512_mask_pmov_qd_128,
6841 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6842 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6843 handleIntrinsicByApplyingToShadow(
I,
6844 Intrinsic::x86_avx512_mask_pmov_wb_128,
6848 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6849 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6850 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6851 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6852 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6853 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6854 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6855 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6859 handleAVX512VectorDownConvert(
I);
6899 case Intrinsic::x86_avx512_rsqrt14_ps_512:
6900 case Intrinsic::x86_avx512_rsqrt14_ps_256:
6901 case Intrinsic::x86_avx512_rsqrt14_ps_128:
6902 case Intrinsic::x86_avx512_rsqrt14_pd_512:
6903 case Intrinsic::x86_avx512_rsqrt14_pd_256:
6904 case Intrinsic::x86_avx512_rsqrt14_pd_128:
6905 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
6906 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
6907 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
6908 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
6909 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
6910 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
6911 handleAVX512VectorGenericMaskedFP(
I, {0},
6952 case Intrinsic::x86_avx512_rcp14_ps_512:
6953 case Intrinsic::x86_avx512_rcp14_ps_256:
6954 case Intrinsic::x86_avx512_rcp14_ps_128:
6955 case Intrinsic::x86_avx512_rcp14_pd_512:
6956 case Intrinsic::x86_avx512_rcp14_pd_256:
6957 case Intrinsic::x86_avx512_rcp14_pd_128:
6958 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
6959 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
6960 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
6961 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
6962 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
6963 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
6964 handleAVX512VectorGenericMaskedFP(
I, {0},
7009 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
7010 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
7011 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
7012 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
7013 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
7014 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
7015 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
7016 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
7017 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
7018 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
7019 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
7020 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
7021 handleAVX512VectorGenericMaskedFP(
I, {0},
7057 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7058 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7059 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7060 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7061 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7062 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7063 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7064 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7065 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7069 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7089 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7090 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7091 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7092 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7093 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7094 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7095 visitGenericScalarHalfwordInst(
I);
7100 case Intrinsic::x86_vgf2p8affineqb_128:
7101 case Intrinsic::x86_vgf2p8affineqb_256:
7102 case Intrinsic::x86_vgf2p8affineqb_512:
7103 handleAVXGF2P8Affine(
I);
7113 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7114 switch (
I.getIntrinsicID()) {
7118 case Intrinsic::aarch64_neon_rshrn:
7119 case Intrinsic::aarch64_neon_sqrshl:
7120 case Intrinsic::aarch64_neon_sqrshrn:
7121 case Intrinsic::aarch64_neon_sqrshrun:
7122 case Intrinsic::aarch64_neon_sqshl:
7123 case Intrinsic::aarch64_neon_sqshlu:
7124 case Intrinsic::aarch64_neon_sqshrn:
7125 case Intrinsic::aarch64_neon_sqshrun:
7126 case Intrinsic::aarch64_neon_srshl:
7127 case Intrinsic::aarch64_neon_sshl:
7128 case Intrinsic::aarch64_neon_uqrshl:
7129 case Intrinsic::aarch64_neon_uqrshrn:
7130 case Intrinsic::aarch64_neon_uqshl:
7131 case Intrinsic::aarch64_neon_uqshrn:
7132 case Intrinsic::aarch64_neon_urshl:
7133 case Intrinsic::aarch64_neon_ushl:
7134 handleVectorShiftIntrinsic(
I,
false);
7147 case Intrinsic::aarch64_neon_vsli:
7148 case Intrinsic::aarch64_neon_vsri:
7149 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7155 case Intrinsic::aarch64_neon_fmaxp:
7156 case Intrinsic::aarch64_neon_fminp:
7158 case Intrinsic::aarch64_neon_fmaxnmp:
7159 case Intrinsic::aarch64_neon_fminnmp:
7161 case Intrinsic::aarch64_neon_smaxp:
7162 case Intrinsic::aarch64_neon_sminp:
7163 case Intrinsic::aarch64_neon_umaxp:
7164 case Intrinsic::aarch64_neon_uminp:
7166 case Intrinsic::aarch64_neon_addp:
7168 case Intrinsic::aarch64_neon_faddp:
7170 case Intrinsic::aarch64_neon_saddlp:
7171 case Intrinsic::aarch64_neon_uaddlp: {
7172 handlePairwiseShadowOrIntrinsic(
I, 1);
7177 case Intrinsic::aarch64_neon_fcvtas:
7178 case Intrinsic::aarch64_neon_fcvtau:
7180 case Intrinsic::aarch64_neon_fcvtms:
7181 case Intrinsic::aarch64_neon_fcvtmu:
7183 case Intrinsic::aarch64_neon_fcvtns:
7184 case Intrinsic::aarch64_neon_fcvtnu:
7186 case Intrinsic::aarch64_neon_fcvtps:
7187 case Intrinsic::aarch64_neon_fcvtpu:
7189 case Intrinsic::aarch64_neon_fcvtzs:
7190 case Intrinsic::aarch64_neon_fcvtzu:
7192 case Intrinsic::aarch64_neon_fcvtxn:
7193 handleGenericVectorConvertIntrinsic(
I,
false);
7197 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7198 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7199 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7200 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7201 handleGenericVectorConvertIntrinsic(
I,
true);
7210 case Intrinsic::aarch64_neon_faddv:
7211 case Intrinsic::aarch64_neon_saddv:
7212 case Intrinsic::aarch64_neon_uaddv:
7215 case Intrinsic::aarch64_neon_smaxv:
7216 case Intrinsic::aarch64_neon_sminv:
7217 case Intrinsic::aarch64_neon_umaxv:
7218 case Intrinsic::aarch64_neon_uminv:
7222 case Intrinsic::aarch64_neon_fmaxv:
7223 case Intrinsic::aarch64_neon_fminv:
7224 case Intrinsic::aarch64_neon_fmaxnmv:
7225 case Intrinsic::aarch64_neon_fminnmv:
7227 case Intrinsic::aarch64_neon_saddlv:
7228 case Intrinsic::aarch64_neon_uaddlv:
7229 handleVectorReduceIntrinsic(
I,
true);
7232 case Intrinsic::aarch64_neon_ld1x2:
7233 case Intrinsic::aarch64_neon_ld1x3:
7234 case Intrinsic::aarch64_neon_ld1x4:
7235 case Intrinsic::aarch64_neon_ld2:
7236 case Intrinsic::aarch64_neon_ld3:
7237 case Intrinsic::aarch64_neon_ld4:
7238 case Intrinsic::aarch64_neon_ld2r:
7239 case Intrinsic::aarch64_neon_ld3r:
7240 case Intrinsic::aarch64_neon_ld4r: {
7241 handleNEONVectorLoad(
I,
false);
7245 case Intrinsic::aarch64_neon_ld2lane:
7246 case Intrinsic::aarch64_neon_ld3lane:
7247 case Intrinsic::aarch64_neon_ld4lane: {
7248 handleNEONVectorLoad(
I,
true);
7253 case Intrinsic::aarch64_neon_sqxtn:
7254 case Intrinsic::aarch64_neon_sqxtun:
7255 case Intrinsic::aarch64_neon_uqxtn:
7262 case Intrinsic::aarch64_neon_st1x2:
7263 case Intrinsic::aarch64_neon_st1x3:
7264 case Intrinsic::aarch64_neon_st1x4:
7265 case Intrinsic::aarch64_neon_st2:
7266 case Intrinsic::aarch64_neon_st3:
7267 case Intrinsic::aarch64_neon_st4: {
7268 handleNEONVectorStoreIntrinsic(
I,
false);
7272 case Intrinsic::aarch64_neon_st2lane:
7273 case Intrinsic::aarch64_neon_st3lane:
7274 case Intrinsic::aarch64_neon_st4lane: {
7275 handleNEONVectorStoreIntrinsic(
I,
true);
7288 case Intrinsic::aarch64_neon_tbl1:
7289 case Intrinsic::aarch64_neon_tbl2:
7290 case Intrinsic::aarch64_neon_tbl3:
7291 case Intrinsic::aarch64_neon_tbl4:
7292 case Intrinsic::aarch64_neon_tbx1:
7293 case Intrinsic::aarch64_neon_tbx2:
7294 case Intrinsic::aarch64_neon_tbx3:
7295 case Intrinsic::aarch64_neon_tbx4: {
7297 handleIntrinsicByApplyingToShadow(
7298 I,
I.getIntrinsicID(),
7303 case Intrinsic::aarch64_neon_fmulx:
7304 case Intrinsic::aarch64_neon_pmul:
7305 case Intrinsic::aarch64_neon_pmull:
7306 case Intrinsic::aarch64_neon_smull:
7307 case Intrinsic::aarch64_neon_pmull64:
7308 case Intrinsic::aarch64_neon_umull: {
7309 handleNEONVectorMultiplyIntrinsic(
I);
7313 case Intrinsic::aarch64_neon_smmla:
7314 case Intrinsic::aarch64_neon_ummla:
7315 case Intrinsic::aarch64_neon_usmmla:
7316 case Intrinsic::aarch64_neon_bfmmla:
7317 handleNEONMatrixMultiply(
I);
7324 case Intrinsic::aarch64_neon_sdot:
7325 case Intrinsic::aarch64_neon_udot:
7326 case Intrinsic::aarch64_neon_usdot:
7327 handleVectorDotProductIntrinsic(
I, 4,
7337 case Intrinsic::aarch64_neon_bfdot:
7338 handleVectorDotProductIntrinsic(
I, 2,
7345 case Intrinsic::aarch64_neon_facge:
7346 case Intrinsic::aarch64_neon_facgt:
7347 handleVectorComparePackedIntrinsic(
I,
false);
7357 void visitIntrinsicInst(IntrinsicInst &
I) {
7358 if (maybeHandleCrossPlatformIntrinsic(
I))
7361 if (maybeHandleX86SIMDIntrinsic(
I))
7364 if (maybeHandleArmSIMDIntrinsic(
I))
7367 if (maybeHandleUnknownIntrinsic(
I))
7370 visitInstruction(
I);
7373 void visitLibAtomicLoad(CallBase &CB) {
7384 Value *NewOrdering =
7388 NextNodeIRBuilder NextIRB(&CB);
7389 Value *SrcShadowPtr, *SrcOriginPtr;
7390 std::tie(SrcShadowPtr, SrcOriginPtr) =
7391 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7393 Value *DstShadowPtr =
7394 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7398 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7399 if (MS.TrackOrigins) {
7400 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7402 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7403 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7407 void visitLibAtomicStore(CallBase &CB) {
7414 Value *NewOrdering =
7418 Value *DstShadowPtr =
7428 void visitCallBase(CallBase &CB) {
7436 visitAsmInstruction(CB);
7438 visitInstruction(CB);
7447 case LibFunc_atomic_load:
7449 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7453 visitLibAtomicLoad(CB);
7455 case LibFunc_atomic_store:
7456 visitLibAtomicStore(CB);
7472 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7476 Func->removeFnAttrs(
B);
7482 bool MayCheckCall = MS.EagerChecks;
7486 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7489 unsigned ArgOffset = 0;
7492 if (!
A->getType()->isSized()) {
7493 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7497 if (
A->getType()->isScalableTy()) {
7498 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7500 insertCheckShadowOf(
A, &CB);
7505 const DataLayout &
DL =
F.getDataLayout();
7509 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7512 insertCheckShadowOf(
A, &CB);
7513 Size =
DL.getTypeAllocSize(
A->getType());
7519 Value *ArgShadow = getShadow(
A);
7520 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7522 <<
" Shadow: " << *ArgShadow <<
"\n");
7526 assert(
A->getType()->isPointerTy() &&
7527 "ByVal argument is not a pointer!");
7532 MaybeAlign Alignment = std::nullopt;
7535 Value *AShadowPtr, *AOriginPtr;
7536 std::tie(AShadowPtr, AOriginPtr) =
7537 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7539 if (!PropagateShadow) {
7546 if (MS.TrackOrigins) {
7547 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7561 Size =
DL.getTypeAllocSize(
A->getType());
7567 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7569 getOriginPtrForArgument(IRB, ArgOffset));
7572 assert(Store !=
nullptr);
7581 if (FT->isVarArg()) {
7582 VAHelper->visitCallBase(CB, IRB);
7592 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7593 setShadow(&CB, getCleanShadow(&CB));
7594 setOrigin(&CB, getCleanOrigin());
7600 Value *
Base = getShadowPtrForRetval(IRBBefore);
7601 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7613 setShadow(&CB, getCleanShadow(&CB));
7614 setOrigin(&CB, getCleanOrigin());
7621 "Could not find insertion point for retval shadow load");
7624 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7627 setShadow(&CB, RetvalShadow);
7628 if (MS.TrackOrigins)
7629 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7634 RetVal =
I->getOperand(0);
7637 return I->isMustTailCall();
7642 void visitReturnInst(ReturnInst &
I) {
7644 Value *RetVal =
I.getReturnValue();
7650 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7651 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7652 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7655 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7657 Value *Shadow = getShadow(RetVal);
7658 bool StoreOrigin =
true;
7660 insertCheckShadowOf(RetVal, &
I);
7661 Shadow = getCleanShadow(RetVal);
7662 StoreOrigin =
false;
7669 if (MS.TrackOrigins && StoreOrigin)
7670 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7674 void visitPHINode(PHINode &
I) {
7676 if (!PropagateShadow) {
7677 setShadow(&
I, getCleanShadow(&
I));
7678 setOrigin(&
I, getCleanOrigin());
7682 ShadowPHINodes.push_back(&
I);
7683 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7685 if (MS.TrackOrigins)
7687 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7690 Value *getLocalVarIdptr(AllocaInst &
I) {
7691 ConstantInt *IntConst =
7692 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7693 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7698 Value *getLocalVarDescription(AllocaInst &
I) {
7704 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7706 Value *ShadowBase, *OriginBase;
7707 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7711 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7714 if (PoisonStack && MS.TrackOrigins) {
7715 Value *Idptr = getLocalVarIdptr(
I);
7717 Value *Descr = getLocalVarDescription(
I);
7718 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7719 {&I, Len, Idptr, Descr});
7721 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7727 Value *Descr = getLocalVarDescription(
I);
7729 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7731 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7735 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7738 NextNodeIRBuilder IRB(InsPoint);
7741 if (MS.CompileKernel)
7742 poisonAllocaKmsan(
I, IRB, Len);
7744 poisonAllocaUserspace(
I, IRB, Len);
7747 void visitAllocaInst(AllocaInst &
I) {
7748 setShadow(&
I, getCleanShadow(&
I));
7749 setOrigin(&
I, getCleanOrigin());
7755 void visitSelectInst(SelectInst &
I) {
7761 handleSelectLikeInst(
I,
B,
C,
D);
7767 Value *Sb = getShadow(
B);
7768 Value *Sc = getShadow(
C);
7769 Value *Sd = getShadow(
D);
7771 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7772 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7773 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7778 if (
I.getType()->isAggregateType()) {
7782 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7783 }
else if (isScalableNonVectorType(
I.getType())) {
7791 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7799 C = CreateAppToShadowCast(IRB,
C);
7800 D = CreateAppToShadowCast(IRB,
D);
7807 if (MS.TrackOrigins) {
7810 if (
B->getType()->isVectorTy()) {
7811 B = convertToBool(
B, IRB);
7812 Sb = convertToBool(Sb, IRB);
7820 void visitLandingPadInst(LandingPadInst &
I) {
7823 setShadow(&
I, getCleanShadow(&
I));
7824 setOrigin(&
I, getCleanOrigin());
7827 void visitCatchSwitchInst(CatchSwitchInst &
I) {
7828 setShadow(&
I, getCleanShadow(&
I));
7829 setOrigin(&
I, getCleanOrigin());
7832 void visitFuncletPadInst(FuncletPadInst &
I) {
7833 setShadow(&
I, getCleanShadow(&
I));
7834 setOrigin(&
I, getCleanOrigin());
7837 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
7839 void visitExtractValueInst(ExtractValueInst &
I) {
7841 Value *Agg =
I.getAggregateOperand();
7843 Value *AggShadow = getShadow(Agg);
7847 setShadow(&
I, ResShadow);
7848 setOriginForNaryOp(
I);
7851 void visitInsertValueInst(InsertValueInst &
I) {
7854 Value *AggShadow = getShadow(
I.getAggregateOperand());
7855 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
7861 setOriginForNaryOp(
I);
7864 void dumpInst(Instruction &
I,
const Twine &Prefix) {
7871 << CI->getCalledFunction()->
getName() <<
"\n";
7873 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
7880 unsigned NumOperands =
I.getNumOperands();
7882 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
7894 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
7895 <<
I.getOpcodeName() <<
"(";
7897 for (
size_t i = 0; i < NumOperands; i++) {
7915 void visitResumeInst(ResumeInst &
I) {
7920 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
7925 void visitCatchReturnInst(CatchReturnInst &CRI) {
7930 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
7939 insertCheckShadowOf(Operand, &
I);
7946 auto Size =
DL.getTypeStoreSize(ElemTy);
7948 if (MS.CompileKernel) {
7949 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
7955 auto [ShadowPtr,
_] =
7956 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
7966 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
7967 int NumRetOutputs = 0;
7974 NumRetOutputs =
ST->getNumElements();
7979 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
7980 switch (
Info.Type) {
7988 return NumOutputs - NumRetOutputs;
7991 void visitAsmInstruction(Instruction &
I) {
8007 const DataLayout &
DL =
F.getDataLayout();
8011 int OutputArgs = getNumOutputArgs(IA, CB);
8017 for (
int i = OutputArgs; i < NumOperands; i++) {
8025 for (
int i = 0; i < OutputArgs; i++) {
8031 setShadow(&
I, getCleanShadow(&
I));
8032 setOrigin(&
I, getCleanOrigin());
8035 void visitFreezeInst(FreezeInst &
I) {
8037 setShadow(&
I, getCleanShadow(&
I));
8038 setOrigin(&
I, getCleanOrigin());
8041 void visitInstruction(Instruction &
I) {
8044 dumpInst(
I,
"Strict");
8046 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8047 Value *Operand =
I.getOperand(i);
8049 insertCheckShadowOf(Operand, &
I);
8051 setShadow(&
I, getCleanShadow(&
I));
8052 setOrigin(&
I, getCleanOrigin());
8056struct VarArgHelperBase :
public VarArgHelper {
8058 MemorySanitizer &MS;
8059 MemorySanitizerVisitor &MSV;
8061 const unsigned VAListTagSize;
8063 VarArgHelperBase(Function &
F, MemorySanitizer &MS,
8064 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8065 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8069 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8075 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8084 return getShadowPtrForVAArgument(IRB, ArgOffset);
8093 ConstantInt::get(MS.IntptrTy, ArgOffset),
8098 unsigned BaseOffset) {
8107 TailSize,
Align(8));
8110 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8112 Value *VAListTag =
I.getArgOperand(0);
8114 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8115 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8118 VAListTagSize, Alignment,
false);
8121 void visitVAStartInst(VAStartInst &
I)
override {
8122 if (
F.getCallingConv() == CallingConv::Win64)
8125 unpoisonVAListTagForInst(
I);
8128 void visitVACopyInst(VACopyInst &
I)
override {
8129 if (
F.getCallingConv() == CallingConv::Win64)
8131 unpoisonVAListTagForInst(
I);
8136struct VarArgAMD64Helper :
public VarArgHelperBase {
8139 static const unsigned AMD64GpEndOffset = 48;
8140 static const unsigned AMD64FpEndOffsetSSE = 176;
8142 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8144 unsigned AMD64FpEndOffset;
8145 AllocaInst *VAArgTLSCopy =
nullptr;
8146 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8147 Value *VAArgOverflowSize =
nullptr;
8149 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8151 VarArgAMD64Helper(Function &
F, MemorySanitizer &MS,
8152 MemorySanitizerVisitor &MSV)
8153 : VarArgHelperBase(
F, MS, MSV, 24) {
8154 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8155 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8156 if (Attr.isStringAttribute() &&
8157 (Attr.getKindAsString() ==
"target-features")) {
8158 if (Attr.getValueAsString().contains(
"-sse"))
8159 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8165 ArgKind classifyArgument(
Value *arg) {
8168 if (
T->isX86_FP80Ty())
8170 if (
T->isFPOrFPVectorTy())
8171 return AK_FloatingPoint;
8172 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8173 return AK_GeneralPurpose;
8174 if (
T->isPointerTy())
8175 return AK_GeneralPurpose;
8187 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8188 unsigned GpOffset = 0;
8189 unsigned FpOffset = AMD64GpEndOffset;
8190 unsigned OverflowOffset = AMD64FpEndOffset;
8191 const DataLayout &
DL =
F.getDataLayout();
8195 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8202 assert(
A->getType()->isPointerTy());
8204 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8205 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8206 unsigned BaseOffset = OverflowOffset;
8207 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8208 Value *OriginBase =
nullptr;
8209 if (MS.TrackOrigins)
8210 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8211 OverflowOffset += AlignedSize;
8214 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8218 Value *ShadowPtr, *OriginPtr;
8219 std::tie(ShadowPtr, OriginPtr) =
8224 if (MS.TrackOrigins)
8228 ArgKind AK = classifyArgument(
A);
8229 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8231 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8233 Value *ShadowBase, *OriginBase =
nullptr;
8235 case AK_GeneralPurpose:
8236 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8237 if (MS.TrackOrigins)
8238 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8242 case AK_FloatingPoint:
8243 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8244 if (MS.TrackOrigins)
8245 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8252 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8253 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8254 unsigned BaseOffset = OverflowOffset;
8255 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8256 if (MS.TrackOrigins) {
8257 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8259 OverflowOffset += AlignedSize;
8262 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8271 Value *Shadow = MSV.getShadow(
A);
8273 if (MS.TrackOrigins) {
8274 Value *Origin = MSV.getOrigin(
A);
8275 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8276 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8282 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8283 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8286 void finalizeInstrumentation()
override {
8287 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8288 "finalizeInstrumentation called twice");
8289 if (!VAStartInstrumentationList.
empty()) {
8296 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8297 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8303 Intrinsic::umin, CopySize,
8307 if (MS.TrackOrigins) {
8308 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8317 for (CallInst *OrigInst : VAStartInstrumentationList) {
8318 NextNodeIRBuilder IRB(OrigInst);
8319 Value *VAListTag = OrigInst->getArgOperand(0);
8321 Value *RegSaveAreaPtrPtr =
8322 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8324 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8326 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8327 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8329 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8331 if (MS.TrackOrigins)
8332 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8333 Alignment, AMD64FpEndOffset);
8334 Value *OverflowArgAreaPtrPtr =
8335 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8336 Value *OverflowArgAreaPtr =
8337 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8338 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8339 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8340 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8344 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8346 if (MS.TrackOrigins) {
8349 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8357struct VarArgAArch64Helper :
public VarArgHelperBase {
8358 static const unsigned kAArch64GrArgSize = 64;
8359 static const unsigned kAArch64VrArgSize = 128;
8361 static const unsigned AArch64GrBegOffset = 0;
8362 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8364 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8365 static const unsigned AArch64VrEndOffset =
8366 AArch64VrBegOffset + kAArch64VrArgSize;
8367 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8369 AllocaInst *VAArgTLSCopy =
nullptr;
8370 Value *VAArgOverflowSize =
nullptr;
8372 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8374 VarArgAArch64Helper(Function &
F, MemorySanitizer &MS,
8375 MemorySanitizerVisitor &MSV)
8376 : VarArgHelperBase(
F, MS, MSV, 32) {}
8379 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8380 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8381 return {AK_GeneralPurpose, 1};
8382 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8383 return {AK_FloatingPoint, 1};
8385 if (
T->isArrayTy()) {
8386 auto R = classifyArgument(
T->getArrayElementType());
8387 R.second *=
T->getScalarType()->getArrayNumElements();
8392 auto R = classifyArgument(FV->getScalarType());
8393 R.second *= FV->getNumElements();
8398 return {AK_Memory, 0};
8410 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8411 unsigned GrOffset = AArch64GrBegOffset;
8412 unsigned VrOffset = AArch64VrBegOffset;
8413 unsigned OverflowOffset = AArch64VAEndOffset;
8415 const DataLayout &
DL =
F.getDataLayout();
8418 auto [AK, RegNum] = classifyArgument(
A->getType());
8419 if (AK == AK_GeneralPurpose &&
8420 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8422 if (AK == AK_FloatingPoint &&
8423 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8427 case AK_GeneralPurpose:
8428 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8429 GrOffset += 8 * RegNum;
8431 case AK_FloatingPoint:
8432 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8433 VrOffset += 16 * RegNum;
8440 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8441 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8442 unsigned BaseOffset = OverflowOffset;
8443 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8444 OverflowOffset += AlignedSize;
8447 CleanUnusedTLS(IRB,
Base, BaseOffset);
8459 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8460 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8465 Value *SaveAreaPtrPtr =
8466 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8467 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8472 Value *SaveAreaPtr =
8473 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8475 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8478 void finalizeInstrumentation()
override {
8479 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8480 "finalizeInstrumentation called twice");
8481 if (!VAStartInstrumentationList.empty()) {
8488 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8489 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8495 Intrinsic::umin, CopySize,
8501 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8502 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8506 for (CallInst *OrigInst : VAStartInstrumentationList) {
8507 NextNodeIRBuilder IRB(OrigInst);
8509 Value *VAListTag = OrigInst->getArgOperand(0);
8526 Value *StackSaveAreaPtr =
8527 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8530 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8531 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8534 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8537 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8538 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8541 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8547 Value *GrRegSaveAreaShadowPtrOff =
8548 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8550 Value *GrRegSaveAreaShadowPtr =
8551 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8557 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8563 Value *VrRegSaveAreaShadowPtrOff =
8564 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8566 Value *VrRegSaveAreaShadowPtr =
8567 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8574 VrRegSaveAreaShadowPtrOff);
8575 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8581 Value *StackSaveAreaShadowPtr =
8582 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8587 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8590 Align(16), VAArgOverflowSize);
8596struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8597 AllocaInst *VAArgTLSCopy =
nullptr;
8598 Value *VAArgSize =
nullptr;
8600 VarArgPowerPC64Helper(Function &
F, MemorySanitizer &MS,
8601 MemorySanitizerVisitor &MSV)
8602 : VarArgHelperBase(
F, MS, MSV, 8) {}
8604 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8612 Triple TargetTriple(
F.getParent()->getTargetTriple());
8616 if (TargetTriple.isPPC64ELFv2ABI())
8620 unsigned VAArgOffset = VAArgBase;
8621 const DataLayout &
DL =
F.getDataLayout();
8624 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8626 assert(
A->getType()->isPointerTy());
8628 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8631 ArgAlign =
Align(8);
8632 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8635 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8637 Value *AShadowPtr, *AOriginPtr;
8638 std::tie(AShadowPtr, AOriginPtr) =
8639 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8649 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8651 if (
A->getType()->isArrayTy()) {
8654 Type *ElementTy =
A->getType()->getArrayElementType();
8656 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8657 }
else if (
A->getType()->isVectorTy()) {
8659 ArgAlign =
Align(ArgSize);
8662 ArgAlign =
Align(8);
8663 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8664 if (
DL.isBigEndian()) {
8668 VAArgOffset += (8 - ArgSize);
8672 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8676 VAArgOffset += ArgSize;
8680 VAArgBase = VAArgOffset;
8684 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8687 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8690 void finalizeInstrumentation()
override {
8691 assert(!VAArgSize && !VAArgTLSCopy &&
8692 "finalizeInstrumentation called twice");
8695 Value *CopySize = VAArgSize;
8697 if (!VAStartInstrumentationList.empty()) {
8701 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8707 Intrinsic::umin, CopySize,
8715 for (CallInst *OrigInst : VAStartInstrumentationList) {
8716 NextNodeIRBuilder IRB(OrigInst);
8717 Value *VAListTag = OrigInst->getArgOperand(0);
8720 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8723 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8724 const DataLayout &
DL =
F.getDataLayout();
8725 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8727 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8728 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8730 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8737struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8738 AllocaInst *VAArgTLSCopy =
nullptr;
8739 Value *VAArgSize =
nullptr;
8741 VarArgPowerPC32Helper(Function &
F, MemorySanitizer &MS,
8742 MemorySanitizerVisitor &MSV)
8743 : VarArgHelperBase(
F, MS, MSV, 12) {}
8745 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8749 unsigned VAArgOffset = VAArgBase;
8750 const DataLayout &
DL =
F.getDataLayout();
8751 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8754 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8756 assert(
A->getType()->isPointerTy());
8758 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8760 if (ArgAlign < IntptrSize)
8761 ArgAlign =
Align(IntptrSize);
8762 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8765 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8767 Value *AShadowPtr, *AOriginPtr;
8768 std::tie(AShadowPtr, AOriginPtr) =
8769 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8779 Type *ArgTy =
A->getType();
8785 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8792 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8795 ArgAlign =
Align(ArgSize);
8797 if (ArgAlign < IntptrSize)
8798 ArgAlign =
Align(IntptrSize);
8799 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8800 if (
DL.isBigEndian()) {
8803 if (ArgSize < IntptrSize)
8804 VAArgOffset += (IntptrSize - ArgSize);
8807 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
8813 VAArgOffset += ArgSize;
8820 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8823 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8826 void finalizeInstrumentation()
override {
8827 assert(!VAArgSize && !VAArgTLSCopy &&
8828 "finalizeInstrumentation called twice");
8830 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8831 Value *CopySize = VAArgSize;
8833 if (!VAStartInstrumentationList.empty()) {
8837 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8843 Intrinsic::umin, CopySize,
8851 for (CallInst *OrigInst : VAStartInstrumentationList) {
8852 NextNodeIRBuilder IRB(OrigInst);
8853 Value *VAListTag = OrigInst->getArgOperand(0);
8855 Value *RegSaveAreaSize = CopySize;
8859 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
8863 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
8865 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8868 const DataLayout &
DL =
F.getDataLayout();
8869 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8873 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8874 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8875 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8877 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
8878 Alignment, RegSaveAreaSize);
8880 RegSaveAreaShadowPtr =
8883 ConstantInt::get(MS.IntptrTy, 32));
8888 ConstantInt::get(MS.IntptrTy, 32), Alignment);
8893 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
8896 OverflowAreaPtrPtr =
8897 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
8898 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
8900 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
8902 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
8903 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
8904 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
8907 Value *OverflowVAArgTLSCopyPtr =
8909 OverflowVAArgTLSCopyPtr =
8910 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
8912 OverflowVAArgTLSCopyPtr =
8915 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
8922struct VarArgSystemZHelper :
public VarArgHelperBase {
8923 static const unsigned SystemZGpOffset = 16;
8924 static const unsigned SystemZGpEndOffset = 56;
8925 static const unsigned SystemZFpOffset = 128;
8926 static const unsigned SystemZFpEndOffset = 160;
8927 static const unsigned SystemZMaxVrArgs = 8;
8928 static const unsigned SystemZRegSaveAreaSize = 160;
8929 static const unsigned SystemZOverflowOffset = 160;
8930 static const unsigned SystemZVAListTagSize = 32;
8931 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
8932 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
8934 bool IsSoftFloatABI;
8935 AllocaInst *VAArgTLSCopy =
nullptr;
8936 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8937 Value *VAArgOverflowSize =
nullptr;
8939 enum class ArgKind {
8947 enum class ShadowExtension {
None,
Zero, Sign };
8949 VarArgSystemZHelper(Function &
F, MemorySanitizer &MS,
8950 MemorySanitizerVisitor &MSV)
8951 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
8952 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
8954 ArgKind classifyArgument(
Type *
T) {
8961 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
8962 return ArgKind::Indirect;
8963 if (
T->isFloatingPointTy())
8964 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
8965 if (
T->isIntegerTy() ||
T->isPointerTy())
8966 return ArgKind::GeneralPurpose;
8967 if (
T->isVectorTy())
8968 return ArgKind::Vector;
8969 return ArgKind::Memory;
8972 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
8982 return ShadowExtension::Zero;
8986 return ShadowExtension::Sign;
8988 return ShadowExtension::None;
8991 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8992 unsigned GpOffset = SystemZGpOffset;
8993 unsigned FpOffset = SystemZFpOffset;
8994 unsigned VrIndex = 0;
8995 unsigned OverflowOffset = SystemZOverflowOffset;
8996 const DataLayout &
DL =
F.getDataLayout();
9002 ArgKind AK = classifyArgument(
T);
9003 if (AK == ArgKind::Indirect) {
9005 AK = ArgKind::GeneralPurpose;
9007 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
9008 AK = ArgKind::Memory;
9009 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
9010 AK = ArgKind::Memory;
9011 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
9012 AK = ArgKind::Memory;
9013 Value *ShadowBase =
nullptr;
9014 Value *OriginBase =
nullptr;
9015 ShadowExtension SE = ShadowExtension::None;
9017 case ArgKind::GeneralPurpose: {
9019 uint64_t ArgSize = 8;
9022 SE = getShadowExtension(CB, ArgNo);
9023 uint64_t GapSize = 0;
9024 if (SE == ShadowExtension::None) {
9025 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9026 assert(ArgAllocSize <= ArgSize);
9027 GapSize = ArgSize - ArgAllocSize;
9029 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9030 if (MS.TrackOrigins)
9031 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9033 GpOffset += ArgSize;
9039 case ArgKind::FloatingPoint: {
9041 uint64_t ArgSize = 8;
9048 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9049 if (MS.TrackOrigins)
9050 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9052 FpOffset += ArgSize;
9058 case ArgKind::Vector: {
9065 case ArgKind::Memory: {
9070 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9071 uint64_t ArgSize =
alignTo(ArgAllocSize, 8);
9073 SE = getShadowExtension(CB, ArgNo);
9075 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9077 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9078 if (MS.TrackOrigins)
9080 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9081 OverflowOffset += ArgSize;
9088 case ArgKind::Indirect:
9091 if (ShadowBase ==
nullptr)
9093 Value *Shadow = MSV.getShadow(
A);
9094 if (SE != ShadowExtension::None)
9095 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9096 SE == ShadowExtension::Sign);
9097 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9099 if (MS.TrackOrigins) {
9100 Value *Origin = MSV.getOrigin(
A);
9101 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9102 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9106 Constant *OverflowSize = ConstantInt::get(
9107 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9108 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9115 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9118 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9120 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9121 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9126 unsigned RegSaveAreaSize =
9127 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9128 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9130 if (MS.TrackOrigins)
9131 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9132 Alignment, RegSaveAreaSize);
9141 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9143 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9144 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9146 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9147 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9150 SystemZOverflowOffset);
9151 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9153 if (MS.TrackOrigins) {
9155 SystemZOverflowOffset);
9156 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9161 void finalizeInstrumentation()
override {
9162 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9163 "finalizeInstrumentation called twice");
9164 if (!VAStartInstrumentationList.empty()) {
9171 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9173 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9179 Intrinsic::umin, CopySize,
9183 if (MS.TrackOrigins) {
9184 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9193 for (CallInst *OrigInst : VAStartInstrumentationList) {
9194 NextNodeIRBuilder IRB(OrigInst);
9195 Value *VAListTag = OrigInst->getArgOperand(0);
9196 copyRegSaveArea(IRB, VAListTag);
9197 copyOverflowArea(IRB, VAListTag);
9203struct VarArgI386Helper :
public VarArgHelperBase {
9204 AllocaInst *VAArgTLSCopy =
nullptr;
9205 Value *VAArgSize =
nullptr;
9207 VarArgI386Helper(Function &
F, MemorySanitizer &MS,
9208 MemorySanitizerVisitor &MSV)
9209 : VarArgHelperBase(
F, MS, MSV, 4) {}
9211 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9212 const DataLayout &
DL =
F.getDataLayout();
9213 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9214 unsigned VAArgOffset = 0;
9217 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
9219 assert(
A->getType()->isPointerTy());
9221 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9223 if (ArgAlign < IntptrSize)
9224 ArgAlign =
Align(IntptrSize);
9225 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9227 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9229 Value *AShadowPtr, *AOriginPtr;
9230 std::tie(AShadowPtr, AOriginPtr) =
9231 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9241 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9243 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9244 if (
DL.isBigEndian()) {
9247 if (ArgSize < IntptrSize)
9248 VAArgOffset += (IntptrSize - ArgSize);
9251 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9254 VAArgOffset += ArgSize;
9260 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9263 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9266 void finalizeInstrumentation()
override {
9267 assert(!VAArgSize && !VAArgTLSCopy &&
9268 "finalizeInstrumentation called twice");
9270 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9271 Value *CopySize = VAArgSize;
9273 if (!VAStartInstrumentationList.empty()) {
9276 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9282 Intrinsic::umin, CopySize,
9290 for (CallInst *OrigInst : VAStartInstrumentationList) {
9291 NextNodeIRBuilder IRB(OrigInst);
9292 Value *VAListTag = OrigInst->getArgOperand(0);
9293 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9294 Value *RegSaveAreaPtrPtr =
9296 PointerType::get(*MS.C, 0));
9297 Value *RegSaveAreaPtr =
9298 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9299 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9300 const DataLayout &
DL =
F.getDataLayout();
9301 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9303 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9304 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9306 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9314struct VarArgGenericHelper :
public VarArgHelperBase {
9315 AllocaInst *VAArgTLSCopy =
nullptr;
9316 Value *VAArgSize =
nullptr;
9318 VarArgGenericHelper(Function &
F, MemorySanitizer &MS,
9319 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9320 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9322 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9323 unsigned VAArgOffset = 0;
9324 const DataLayout &
DL =
F.getDataLayout();
9325 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9330 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9331 if (
DL.isBigEndian()) {
9334 if (ArgSize < IntptrSize)
9335 VAArgOffset += (IntptrSize - ArgSize);
9337 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9338 VAArgOffset += ArgSize;
9339 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9345 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9348 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9351 void finalizeInstrumentation()
override {
9352 assert(!VAArgSize && !VAArgTLSCopy &&
9353 "finalizeInstrumentation called twice");
9355 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9356 Value *CopySize = VAArgSize;
9358 if (!VAStartInstrumentationList.empty()) {
9361 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9367 Intrinsic::umin, CopySize,
9375 for (CallInst *OrigInst : VAStartInstrumentationList) {
9376 NextNodeIRBuilder IRB(OrigInst);
9377 Value *VAListTag = OrigInst->getArgOperand(0);
9378 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9379 Value *RegSaveAreaPtrPtr =
9381 PointerType::get(*MS.C, 0));
9382 Value *RegSaveAreaPtr =
9383 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9384 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9385 const DataLayout &
DL =
F.getDataLayout();
9386 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9388 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9389 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9391 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9399using VarArgARM32Helper = VarArgGenericHelper;
9400using VarArgRISCVHelper = VarArgGenericHelper;
9401using VarArgMIPSHelper = VarArgGenericHelper;
9402using VarArgLoongArch64Helper = VarArgGenericHelper;
9403using VarArgHexagonHelper = VarArgGenericHelper;
9406struct VarArgNoOpHelper :
public VarArgHelper {
9407 VarArgNoOpHelper(Function &
F, MemorySanitizer &MS,
9408 MemorySanitizerVisitor &MSV) {}
9410 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9412 void visitVAStartInst(VAStartInst &
I)
override {}
9414 void visitVACopyInst(VACopyInst &
I)
override {}
9416 void finalizeInstrumentation()
override {}
9422 MemorySanitizerVisitor &Visitor) {
9425 Triple TargetTriple(Func.getParent()->getTargetTriple());
9428 return new VarArgI386Helper(Func, Msan, Visitor);
9431 return new VarArgAMD64Helper(Func, Msan, Visitor);
9433 if (TargetTriple.
isARM())
9434 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9437 return new VarArgAArch64Helper(Func, Msan, Visitor);
9440 return new VarArgSystemZHelper(Func, Msan, Visitor);
9445 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9448 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9451 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9454 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9457 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9460 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9463 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9467 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9469 return new VarArgNoOpHelper(Func, Msan, Visitor);
9476 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9479 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9486 return Visitor.runOnFunction();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isStore(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClWithComdat("asan-with-comdat", cl::desc("Place ASan constructors in comdat sections"), cl::Hidden, cl::init(true))
VarLocInsertPt getNextNode(const DbgRecord *DVR)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_S390X_MemoryMapParams
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static bool isAMustTailRetVal(Value *RetVal)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static const PlatformMemoryMapParams Linux_S390_MemoryMapParams
static const Align kMinOriginAlignment
static cl::opt< uint64_t > ClShadowBase("msan-shadow-base", cl::desc("Define custom MSan ShadowBase"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClPoisonUndef("msan-poison-undef", cl::desc("Poison fully undef temporary values. " "Partially undefined constant vectors " "are unaffected by this flag (see " "-msan-poison-undef-vectors)."), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_X86_MemoryMapParams
static cl::opt< uint64_t > ClOriginBase("msan-origin-base", cl::desc("Define custom MSan OriginBase"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClCheckConstantShadow("msan-check-constant-shadow", cl::desc("Insert checks for constant shadow values"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_LoongArch_MemoryMapParams
static const MemoryMapParams NetBSD_X86_64_MemoryMapParams
static const PlatformMemoryMapParams Linux_MIPS_MemoryMapParams
static const unsigned kOriginSize
static cl::opt< bool > ClWithComdat("msan-with-comdat", cl::desc("Place MSan constructors in comdat sections"), cl::Hidden, cl::init(false))
static cl::opt< int > ClTrackOrigins("msan-track-origins", cl::desc("Track origins (allocation sites) of poisoned memory"), cl::Hidden, cl::init(0))
Track origins of uninitialized values.
static cl::opt< int > ClInstrumentationWithCallThreshold("msan-instrumentation-with-call-threshold", cl::desc("If the function being instrumented requires more than " "this number of checks and origin stores, use callbacks instead of " "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(3500))
static cl::opt< int > ClPoisonStackPattern("msan-poison-stack-pattern", cl::desc("poison uninitialized stack variables with the given pattern"), cl::Hidden, cl::init(0xff))
static const Align kShadowTLSAlignment
static cl::opt< bool > ClHandleICmpExact("msan-handle-icmp-exact", cl::desc("exact handling of relational integer ICmp"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_ARM_MemoryMapParams
static cl::opt< bool > ClDumpStrictInstructions("msan-dump-strict-instructions", cl::desc("print out instructions with default strict semantics i.e.," "check that all the inputs are fully initialized, and mark " "the output as fully initialized. These semantics are applied " "to instructions that could not be handled explicitly nor " "heuristically."), cl::Hidden, cl::init(false))
static Constant * getOrInsertGlobal(Module &M, StringRef Name, Type *Ty)
static cl::opt< bool > ClPreciseDisjointOr("msan-precise-disjoint-or", cl::desc("Precisely poison disjoint OR. If false (legacy behavior), " "disjointedness is ignored (i.e., 1|1 is initialized)."), cl::Hidden, cl::init(false))
static const PlatformMemoryMapParams Linux_Hexagon_MemoryMapParams_P
static cl::opt< bool > ClPoisonStack("msan-poison-stack", cl::desc("poison uninitialized stack variables"), cl::Hidden, cl::init(true))
static const MemoryMapParams Linux_I386_MemoryMapParams
const char kMsanInitName[]
static cl::opt< bool > ClPoisonUndefVectors("msan-poison-undef-vectors", cl::desc("Precisely poison partially undefined constant vectors. " "If false (legacy behavior), the entire vector is " "considered fully initialized, which may lead to false " "negatives. Fully undefined constant vectors are " "unaffected by this flag (see -msan-poison-undef)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClPrintStackNames("msan-print-stack-names", cl::desc("Print name of local stack variable"), cl::Hidden, cl::init(true))
static cl::opt< uint64_t > ClAndMask("msan-and-mask", cl::desc("Define custom MSan AndMask"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClHandleLifetimeIntrinsics("msan-handle-lifetime-intrinsics", cl::desc("when possible, poison scoped variables at the beginning of the scope " "(slower, but more precise)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKeepGoing("msan-keep-going", cl::desc("keep going after reporting a UMR"), cl::Hidden, cl::init(false))
static const MemoryMapParams FreeBSD_X86_64_MemoryMapParams
static GlobalVariable * createPrivateConstGlobalForString(Module &M, StringRef Str)
Create a non-const global initialized with the given string.
static const PlatformMemoryMapParams Linux_PowerPC_MemoryMapParams
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClEagerChecks("msan-eager-checks", cl::desc("check arguments and return values at function call boundaries"), cl::Hidden, cl::init(false))
static cl::opt< int > ClDisambiguateWarning("msan-disambiguate-warning-threshold", cl::desc("Define threshold for number of checks per " "debug location to force origin update."), cl::Hidden, cl::init(3))
static VarArgHelper * CreateVarArgHelper(Function &Func, MemorySanitizer &Msan, MemorySanitizerVisitor &Visitor)
static const MemoryMapParams Linux_MIPS64_MemoryMapParams
static const MemoryMapParams Linux_PowerPC64_MemoryMapParams
static cl::opt< int > ClSwitchPrecision("msan-switch-precision", cl::desc("Controls the number of cases considered by MSan for LLVM switch " "instructions. 0 means no UUMs detected. Higher values lead to " "fewer false negatives but may impact compiler and/or " "application performance. N.B. LLVM switch instructions do not " "correspond exactly to C++ switch statements."), cl::Hidden, cl::init(99))
static cl::opt< uint64_t > ClXorMask("msan-xor-mask", cl::desc("Define custom MSan XorMask"), cl::Hidden, cl::init(0))
static const MemoryMapParams Linux_Hexagon_MemoryMapParams
static cl::opt< bool > ClHandleAsmConservative("msan-handle-asm-conservative", cl::desc("conservative handling of inline assembly"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams FreeBSD_X86_MemoryMapParams
static const PlatformMemoryMapParams FreeBSD_ARM_MemoryMapParams
static const unsigned kParamTLSSize
static cl::opt< bool > ClHandleICmp("msan-handle-icmp", cl::desc("propagate shadow through ICmpEQ and ICmpNE"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClEnableKmsan("msan-kernel", cl::desc("Enable KernelMemorySanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClPoisonStackWithCall("msan-poison-stack-with-call", cl::desc("poison uninitialized stack variables with a call"), cl::Hidden, cl::init(false))
static const PlatformMemoryMapParams NetBSD_X86_MemoryMapParams
static cl::opt< bool > ClDumpHeuristicInstructions("msan-dump-heuristic-instructions", cl::desc("Prints 'unknown' instructions that were handled heuristically. " "Use -msan-dump-strict-instructions to print instructions that " "could not be handled explicitly nor heuristically."), cl::Hidden, cl::init(false))
static const unsigned kRetvalTLSSize
static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams
const char kMsanModuleCtorName[]
static const MemoryMapParams FreeBSD_I386_MemoryMapParams
static cl::opt< bool > ClCheckAccessAddress("msan-check-access-address", cl::desc("report accesses through a pointer which has poisoned shadow"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClDisableChecks("msan-disable-checks", cl::desc("Apply no_sanitize to the whole file"), cl::Hidden, cl::init(false))
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
void setAlignment(Align Align)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
const T & front() const
Get the first element.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
void removeFnAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the function.
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getCalledOperand() const
Type * getParamElementType(unsigned ArgNo) const
Extract the elementtype type for a parameter.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
LLVM_ABI bool isAllOnesValue() const
Return true if this is the value that would be returned by getAllOnesValue.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
static bool shouldExecute(CounterInfo &Counter)
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
static FixedVectorType * getHalfElementsVectorType(FixedVectorType *VTy)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
LLVM_ABI void setComdat(Comdat *C)
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ ExternalLinkage
Externally visible function.
Analysis pass providing a never-invalidated alias analysis result.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LLVM_ABI Value * CreateAndReduce(Value *Src)
Create a vector int AND reduction intrinsic of the source vector.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
LLVM_ABI CallInst * CreateMaskedCompressStore(Value *Val, Value *Ptr, MaybeAlign Align, Value *Mask=nullptr)
Create a call to Masked Compress Store intrinsic.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateAllocationSize(Type *DestTy, AllocaInst *AI)
Get allocation size of an alloca as a runtime Value* (handles both static and dynamic allocas and vsc...
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memcpy between the specified pointers.
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
LLVM_ABI Value * CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 2 operands which is mangled on the first type.
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI DebugLoc getCurrentDebugLocation() const
Get location information used by debugging information.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended from a 64-bit value.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedExpandLoad(Type *Ty, Value *Ptr, MaybeAlign Align, Value *Mask=nullptr, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Expand Load intrinsic.
Value * CreateInBoundsPtrAdd(Value *Ptr, Value *Offset, const Twine &Name="")
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI CallInst * CreateMaskedScatter(Value *Val, Value *Ptrs, Align Alignment, Value *Mask=nullptr)
Create a call to Masked Scatter intrinsic.
LLVM_ABI CallInst * CreateMaskedGather(Type *Ty, Value *Ptrs, Align Alignment, Value *Mask=nullptr, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Gather intrinsic.
Value * CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
std::vector< ConstraintInfo > ConstraintInfoVector
void visit(Iterator Start, Iterator End)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
bool remove(const value_type &X)
Remove an item from the set vector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Triple - Helper class for working with autoconf configuration names.
bool isMIPS64() const
Tests whether the target is MIPS 64-bit (little and big endian).
bool isRISCV32() const
Tests whether the target is 32-bit RISC-V.
bool isPPC32() const
Tests whether the target is 32-bit PowerPC (little and big endian).
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isLoongArch64() const
Tests whether the target is 64-bit LoongArch.
bool isMIPS32() const
Tests whether the target is MIPS 32-bit (little and big endian).
bool isARM() const
Tests whether the target is ARM (little and big endian).
bool isPPC64() const
Tests whether the target is 64-bit PowerPC (little and big endian).
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isSystemZ() const
Tests whether the target is SystemZ.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
bool isPPC_FP128Ty() const
Return true if this is powerpc long double.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
int getNumOccurrences() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
initializer< Ty > init(const Ty &Val)
Function * Kernel
Summary of a kernel (=entry point for target offloading).
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI std::pair< Instruction *, Value * > SplitBlockAndInsertSimpleForLoop(Value *End, BasicBlock::iterator SplitBefore)
Insert a for (int i = 0; i < End; i++) loop structure (with the exception that End is assumed > 0,...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< df_iterator< T > > depth_first(const T &G)
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A CRTP mix-in to automatically provide informational APIs needed for passes.