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;
793 if (!Options.Kernel) {
802 MemorySanitizer Msan(*
F.getParent(), Options);
820 static_cast<PassInfoMixin<MemorySanitizerPass> *
>(
this)->
printPipeline(
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);
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] =
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;
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());
1806 return VectorType::get(
1807 getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
1808 VectTy->getElementCount());
1817 VectTy->getElementCount(),
1818 constToIntPtr(VectTy->getElementType(),
C));
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;
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 visitPtrToAddrInst(PtrToAddrInst &
I) {
2615 "_msprop_ptrtoaddr"));
2616 setOrigin(&
I, getOrigin(&
I, 0));
2619 void visitIntToPtrInst(IntToPtrInst &
I) {
2622 "_msprop_inttoptr"));
2623 setOrigin(&
I, getOrigin(&
I, 0));
2644 void handleGenericVectorConvertIntrinsic(Instruction &
I,
bool FixedPoint) {
2645 [[maybe_unused]]
unsigned NumArgs =
I.getNumOperands();
2647 NumArgs = CI->arg_size();
2651 Value *Precision =
I.getOperand(1);
2652 insertCheckShadowOf(Precision, &
I);
2658 Value *S0 = getShadow(&
I, 0);
2668 setShadow(&
I, OutShadow);
2669 setOriginForNaryOp(
I);
2672 void visitFPToSIInst(CastInst &
I) {
2673 handleGenericVectorConvertIntrinsic(
I,
false);
2675 void visitFPToUIInst(CastInst &
I) {
2676 handleGenericVectorConvertIntrinsic(
I,
false);
2678 void visitSIToFPInst(CastInst &
I) {
2679 handleGenericVectorConvertIntrinsic(
I,
false);
2681 void visitUIToFPInst(CastInst &
I) {
2682 handleGenericVectorConvertIntrinsic(
I,
false);
2685 void visitFPExtInst(CastInst &
I) {
2686 handleGenericVectorConvertIntrinsic(
I,
false);
2688 void visitFPTruncInst(CastInst &
I) {
2689 handleGenericVectorConvertIntrinsic(
I,
false);
2710 assert(
V1->getType()->isIntOrIntVectorTy());
2721 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2725 void visitAnd(BinaryOperator &
I) {
2728 Value *V2 =
I.getOperand(1);
2730 Value *S2 = getShadow(&
I, 1);
2732 Value *OutShadow = handleBitwiseAnd(IRB,
V1, V2,
S1, S2);
2734 setShadow(&
I, OutShadow);
2735 setOriginForNaryOp(
I);
2738 void visitOr(BinaryOperator &
I) {
2751 Value *S2 = getShadow(&
I, 1);
2753 Value *V2 =
I.getOperand(1);
2757 assert(
V1->getType()->isIntOrIntVectorTy());
2777 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2781 setOriginForNaryOp(
I);
2799 template <
bool CombineShadow>
class Combiner {
2800 Value *Shadow =
nullptr;
2801 Value *Origin =
nullptr;
2803 MemorySanitizerVisitor *MSV;
2806 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2807 : IRB(IRB), MSV(MSV) {}
2811 if (CombineShadow) {
2816 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2817 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2821 if (MSV->MS.TrackOrigins) {
2828 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2829 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2839 Value *OpShadow = MSV->getShadow(V);
2840 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2841 return Add(OpShadow, OpOrigin);
2846 void Done(Instruction *
I) {
2847 if (CombineShadow) {
2849 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2850 MSV->setShadow(
I, Shadow);
2852 if (MSV->MS.TrackOrigins) {
2854 MSV->setOrigin(
I, Origin);
2860 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2861 if (MSV->MS.TrackOrigins) {
2868 using ShadowAndOriginCombiner = Combiner<true>;
2869 using OriginCombiner = Combiner<false>;
2872 void setOriginForNaryOp(Instruction &
I) {
2873 if (!MS.TrackOrigins)
2876 OriginCombiner OC(
this, IRB);
2877 for (Use &
Op :
I.operands())
2882 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2884 "Vector of pointers is not a valid shadow type");
2894 Type *srcTy =
V->getType();
2897 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2898 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2899 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2917 Type *ShadowTy = getShadowTy(V);
2918 if (
V->getType() == ShadowTy)
2920 if (
V->getType()->isPtrOrPtrVectorTy())
2927 void handleShadowOr(Instruction &
I) {
2929 ShadowAndOriginCombiner SC(
this, IRB);
2930 for (Use &
Op :
I.operands())
2957 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2958 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2963 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2969 assert(NumElems % (ReductionFactor * Shards) == 0);
2974 for (
unsigned i = 0; i < ReductionFactor; i++) {
2975 SmallVector<int, 16>
Mask;
2977 for (
unsigned j = 0;
j < Shards;
j++) {
2978 unsigned Offset = NumElems / Shards *
j;
2980 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2984 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
3009 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
3010 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3012 assert(
I.getType()->isVectorTy());
3013 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3015 [[maybe_unused]] FixedVectorType *ParamType =
3019 [[maybe_unused]] FixedVectorType *
ReturnType =
3027 Value *FirstArgShadow = getShadow(&
I, 0);
3028 Value *SecondArgShadow =
nullptr;
3029 if (
I.arg_size() == 2)
3030 SecondArgShadow = getShadow(&
I, 1);
3032 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3033 FirstArgShadow, SecondArgShadow);
3035 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3037 setShadow(&
I, OrShadow);
3038 setOriginForNaryOp(
I);
3048 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
3049 int ReinterpretElemWidth) {
3050 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3052 assert(
I.getType()->isVectorTy());
3053 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3055 FixedVectorType *ParamType =
3060 [[maybe_unused]] FixedVectorType *
ReturnType =
3067 FixedVectorType *ReinterpretShadowTy =
nullptr;
3075 Value *FirstArgShadow = getShadow(&
I, 0);
3076 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3086 Value *SecondArgShadow =
nullptr;
3087 if (
I.arg_size() == 2) {
3088 SecondArgShadow = getShadow(&
I, 1);
3089 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3092 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3093 FirstArgShadow, SecondArgShadow);
3095 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3097 setShadow(&
I, OrShadow);
3098 setOriginForNaryOp(
I);
3101 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3112 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3118 Type *EltTy = VTy->getElementType();
3120 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3121 if (ConstantInt *Elt =
3123 const APInt &
V = Elt->getValue();
3124 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3125 Elements.push_back(ConstantInt::get(EltTy, V2));
3127 Elements.push_back(ConstantInt::get(EltTy, 1));
3133 const APInt &
V = Elt->getValue();
3134 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3135 ShadowMul = ConstantInt::get(Ty, V2);
3137 ShadowMul = ConstantInt::get(Ty, 1);
3143 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3144 setOrigin(&
I, getOrigin(OtherArg));
3147 void visitMul(BinaryOperator &
I) {
3150 if (constOp0 && !constOp1)
3151 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3152 else if (constOp1 && !constOp0)
3153 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3158 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3159 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3160 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3161 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3162 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3163 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3165 void handleIntegerDiv(Instruction &
I) {
3168 insertCheckShadowOf(
I.getOperand(1), &
I);
3169 setShadow(&
I, getShadow(&
I, 0));
3170 setOrigin(&
I, getOrigin(&
I, 0));
3173 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3174 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3175 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3176 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3180 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3181 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3187 void handleEqualityComparison(ICmpInst &
I) {
3191 Value *Sa = getShadow(
A);
3192 Value *Sb = getShadow(
B);
3194 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3197 setOriginForNaryOp(
I);
3205 void handleRelationalComparisonExact(ICmpInst &
I) {
3209 Value *Sa = getShadow(
A);
3210 Value *Sb = getShadow(
B);
3221 bool IsSigned =
I.isSigned();
3223 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3233 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3238 return std::make_pair(Min, Max);
3241 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3242 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3248 setOriginForNaryOp(
I);
3255 void handleSignedRelationalComparison(ICmpInst &
I) {
3260 op =
I.getOperand(0);
3261 pre =
I.getPredicate();
3263 op =
I.getOperand(1);
3264 pre =
I.getSwappedPredicate();
3277 setShadow(&
I, Shadow);
3278 setOrigin(&
I, getOrigin(
op));
3284 void visitICmpInst(ICmpInst &
I) {
3289 if (
I.isEquality()) {
3290 handleEqualityComparison(
I);
3296 handleRelationalComparisonExact(
I);
3300 handleSignedRelationalComparison(
I);
3306 handleRelationalComparisonExact(
I);
3313 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3315 void handleShift(BinaryOperator &
I) {
3320 Value *S2 = getShadow(&
I, 1);
3323 Value *V2 =
I.getOperand(1);
3325 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3326 setOriginForNaryOp(
I);
3329 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3330 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3331 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3333 void handleFunnelShift(IntrinsicInst &
I) {
3337 Value *S0 = getShadow(&
I, 0);
3339 Value *S2 = getShadow(&
I, 2);
3342 Value *V2 =
I.getOperand(2);
3345 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3346 setOriginForNaryOp(
I);
3354 void handleGenericBitManipulation(IntrinsicInst &
I) {
3356 Type *ShadowTy = getShadowTy(&
I);
3359 Value *SMask = getShadow(&
I, 1);
3364 if (
Function *Func =
I.getCalledFunction())
3365 S = IRB.
CreateCall(Func, {getShadow(&
I, 0),
I.getOperand(1)});
3368 {getShadow(&I, 0), I.getOperand(1)});
3371 setOriginForNaryOp(
I);
3384 void visitMemMoveInst(MemMoveInst &
I) {
3385 getShadow(
I.getArgOperand(1));
3388 {I.getArgOperand(0), I.getArgOperand(1),
3389 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3407 void visitMemCpyInst(MemCpyInst &
I) {
3408 getShadow(
I.getArgOperand(1));
3411 {I.getArgOperand(0), I.getArgOperand(1),
3412 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3417 void visitMemSetInst(MemSetInst &
I) {
3421 {I.getArgOperand(0),
3422 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3423 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3427 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3429 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3435 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3439 Value *Addr =
I.getArgOperand(0);
3440 Value *Shadow = getShadow(&
I, 1);
3441 Value *ShadowPtr, *OriginPtr;
3445 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3450 insertCheckShadowOf(Addr, &
I);
3453 if (MS.TrackOrigins)
3462 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3466 Value *Addr =
I.getArgOperand(0);
3468 Type *ShadowTy = getShadowTy(&
I);
3469 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3470 if (PropagateShadow) {
3474 std::tie(ShadowPtr, OriginPtr) =
3475 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3479 setShadow(&
I, getCleanShadow(&
I));
3483 insertCheckShadowOf(Addr, &
I);
3485 if (MS.TrackOrigins) {
3486 if (PropagateShadow)
3487 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3489 setOrigin(&
I, getCleanOrigin());
3509 [[maybe_unused]]
bool
3510 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3511 unsigned int trailingFlags) {
3512 Type *RetTy =
I.getType();
3516 unsigned NumArgOperands =
I.arg_size();
3517 assert(NumArgOperands >= trailingFlags);
3518 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3519 Type *Ty =
I.getArgOperand(i)->getType();
3525 ShadowAndOriginCombiner SC(
this, IRB);
3526 for (
unsigned i = 0; i < NumArgOperands; ++i)
3527 SC.Add(
I.getArgOperand(i));
3544 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3545 unsigned NumArgOperands =
I.arg_size();
3546 if (NumArgOperands == 0)
3549 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3550 I.getArgOperand(1)->getType()->isVectorTy() &&
3551 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3553 return handleVectorStoreIntrinsic(
I);
3556 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3557 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3559 return handleVectorLoadIntrinsic(
I);
3562 if (
I.doesNotAccessMemory())
3563 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3571 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3572 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3574 dumpInst(
I,
"Heuristic");
3576 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3583 void handleInvariantGroup(IntrinsicInst &
I) {
3584 setShadow(&
I, getShadow(&
I, 0));
3585 setOrigin(&
I, getOrigin(&
I, 0));
3588 void handleLifetimeStart(IntrinsicInst &
I) {
3593 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3596 void handleBswap(IntrinsicInst &
I) {
3599 Type *OpType =
Op->getType();
3602 setOrigin(&
I, getOrigin(
Op));
3623 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3625 Value *Src =
I.getArgOperand(0);
3626 Value *SrcShadow = getShadow(Src);
3630 I.getType(),
I.getIntrinsicID(), {Src, False});
3632 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3635 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3637 Value *NotAllZeroShadow =
3639 Value *OutputShadow =
3640 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3646 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3649 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3651 setShadow(&
I, OutputShadow);
3652 setOriginForNaryOp(
I);
3661 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3681 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3686 Value *FullShadow = getCleanShadow(&
I);
3687 unsigned ShadowNumElems =
3689 unsigned FullShadowNumElems =
3692 assert((ShadowNumElems == FullShadowNumElems) ||
3693 (ShadowNumElems * 2 == FullShadowNumElems));
3695 if (ShadowNumElems == FullShadowNumElems) {
3696 FullShadow = Shadow;
3700 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3725 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3726 bool HasRoundingMode) {
3727 if (HasRoundingMode) {
3735 Value *Src =
I.getArgOperand(0);
3736 assert(Src->getType()->isVectorTy());
3740 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3743 Value *S0 = getShadow(&
I, 0);
3755 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3757 setShadow(&
I, FullShadow);
3758 setOriginForNaryOp(
I);
3779 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3780 bool HasRoundingMode =
false) {
3782 Value *CopyOp, *ConvertOp;
3784 assert((!HasRoundingMode ||
3786 "Invalid rounding mode");
3788 switch (
I.arg_size() - HasRoundingMode) {
3790 CopyOp =
I.getArgOperand(0);
3791 ConvertOp =
I.getArgOperand(1);
3794 ConvertOp =
I.getArgOperand(0);
3808 Value *ConvertShadow = getShadow(ConvertOp);
3809 Value *AggShadow =
nullptr;
3812 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3813 for (
int i = 1; i < NumUsedElements; ++i) {
3815 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3816 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3819 AggShadow = ConvertShadow;
3822 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3829 Value *ResultShadow = getShadow(CopyOp);
3831 for (
int i = 0; i < NumUsedElements; ++i) {
3833 ResultShadow, ConstantInt::getNullValue(EltTy),
3836 setShadow(&
I, ResultShadow);
3837 setOrigin(&
I, getOrigin(CopyOp));
3839 setShadow(&
I, getCleanShadow(&
I));
3840 setOrigin(&
I, getCleanOrigin());
3848 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3851 return CreateShadowCast(IRB, S2,
T,
true);
3859 return CreateShadowCast(IRB, S2,
T,
true);
3876 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3882 Value *S2 = getShadow(&
I, 1);
3884 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3886 Value *V2 =
I.getOperand(1);
3888 {IRB.CreateBitCast(S1, V1->getType()), V2});
3890 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3891 setOriginForNaryOp(
I);
3896 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3897 unsigned X86_MMXSizeInBits = 64) {
3898 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3899 "Illegal MMX vector element size");
3901 X86_MMXSizeInBits / EltSizeInBits);
3908 case Intrinsic::x86_sse2_packsswb_128:
3909 case Intrinsic::x86_sse2_packuswb_128:
3910 return Intrinsic::x86_sse2_packsswb_128;
3912 case Intrinsic::x86_sse2_packssdw_128:
3913 case Intrinsic::x86_sse41_packusdw:
3914 return Intrinsic::x86_sse2_packssdw_128;
3916 case Intrinsic::x86_avx2_packsswb:
3917 case Intrinsic::x86_avx2_packuswb:
3918 return Intrinsic::x86_avx2_packsswb;
3920 case Intrinsic::x86_avx2_packssdw:
3921 case Intrinsic::x86_avx2_packusdw:
3922 return Intrinsic::x86_avx2_packssdw;
3924 case Intrinsic::x86_mmx_packsswb:
3925 case Intrinsic::x86_mmx_packuswb:
3926 return Intrinsic::x86_mmx_packsswb;
3928 case Intrinsic::x86_mmx_packssdw:
3929 return Intrinsic::x86_mmx_packssdw;
3931 case Intrinsic::x86_avx512_packssdw_512:
3932 case Intrinsic::x86_avx512_packusdw_512:
3933 return Intrinsic::x86_avx512_packssdw_512;
3935 case Intrinsic::x86_avx512_packsswb_512:
3936 case Intrinsic::x86_avx512_packuswb_512:
3937 return Intrinsic::x86_avx512_packsswb_512;
3953 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3954 unsigned MMXEltSizeInBits = 0) {
3958 Value *S2 = getShadow(&
I, 1);
3959 assert(
S1->getType()->isVectorTy());
3965 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3966 if (MMXEltSizeInBits) {
3974 if (MMXEltSizeInBits) {
3980 {S1_ext, S2_ext},
nullptr,
3981 "_msprop_vector_pack");
3982 if (MMXEltSizeInBits)
3985 setOriginForNaryOp(
I);
3989 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3990 SmallVector<Constant *, 4>
R(Width);
4002 const unsigned Width =
4009 Value *DstMaskV = createDppMask(Width, DstMask);
4026 void handleDppIntrinsic(IntrinsicInst &
I) {
4029 Value *S0 = getShadow(&
I, 0);
4033 const unsigned Width =
4035 assert(Width == 2 || Width == 4 || Width == 8);
4038 const unsigned SrcMask =
Mask >> 4;
4039 const unsigned DstMask =
Mask & 0xf;
4042 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
4047 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4054 setOriginForNaryOp(
I);
4058 C = CreateAppToShadowCast(IRB,
C);
4067 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4072 Value *Sc = getShadow(&
I, 2);
4073 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4078 C = convertBlendvToSelectMask(IRB,
C);
4079 Sc = convertBlendvToSelectMask(IRB, Sc);
4085 handleSelectLikeInst(
I,
C,
T,
F);
4089 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4090 const unsigned SignificantBitsPerResultElement = 16;
4092 unsigned ZeroBitsPerResultElement =
4096 auto *Shadow0 = getShadow(&
I, 0);
4097 auto *Shadow1 = getShadow(&
I, 1);
4102 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4105 setOriginForNaryOp(
I);
4129 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4130 unsigned ReductionFactor,
4132 unsigned EltSizeInBits,
4136 [[maybe_unused]] FixedVectorType *
ReturnType =
4141 Value *Va =
nullptr;
4142 Value *Vb =
nullptr;
4143 Value *Sa =
nullptr;
4144 Value *Sb =
nullptr;
4146 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4147 if (
I.arg_size() == 2) {
4150 Va =
I.getOperand(0);
4151 Vb =
I.getOperand(1);
4153 Sa = getShadow(&
I, 0);
4154 Sb = getShadow(&
I, 1);
4155 }
else if (
I.arg_size() == 3) {
4157 Va =
I.getOperand(1);
4158 Vb =
I.getOperand(2);
4160 Sa = getShadow(&
I, 1);
4161 Sb = getShadow(&
I, 2);
4178 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4180 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4190 if (
I.arg_size() == 3) {
4191 [[maybe_unused]]
auto *AccumulatorType =
4193 assert(AccumulatorType == ReturnType);
4196 FixedVectorType *ImplicitReturnType =
4199 if (EltSizeInBits) {
4201 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4213 ReturnType->getNumElements() * ReductionFactor);
4230 VaInt = CreateAppToShadowCast(IRB, Va);
4231 VbInt = CreateAppToShadowCast(IRB, Vb);
4238 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4260 ImplicitReturnType);
4265 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4268 if (
I.arg_size() == 3)
4269 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4271 setShadow(&
I, OutShadow);
4272 setOriginForNaryOp(
I);
4289 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4290 bool PredicateAsOperand) {
4291 if (PredicateAsOperand) {
4293 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4301 Type *ResTy = getShadowTy(&
I);
4302 auto *Shadow0 = getShadow(&
I, 0);
4303 auto *Shadow1 = getShadow(&
I, 1);
4308 setOriginForNaryOp(
I);
4314 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4316 auto *Shadow0 = getShadow(&
I, 0);
4317 auto *Shadow1 = getShadow(&
I, 1);
4319 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4321 setOriginForNaryOp(
I);
4330 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4335 if (AllowShadowCast)
4336 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4340 setOriginForNaryOp(
I);
4350 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4354 Value *Shadow0 = getShadow(&
I, 0);
4360 setOriginForNaryOp(
I);
4366 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4370 Value *OperandShadow = getShadow(&
I, 0);
4372 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4380 setOrigin(&
I, getOrigin(&
I, 0));
4386 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4390 Value *OperandShadow = getShadow(&
I, 0);
4391 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4399 setOrigin(&
I, getOrigin(&
I, 0));
4402 void handleStmxcsr(IntrinsicInst &
I) {
4404 Value *Addr =
I.getArgOperand(0);
4407 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4412 insertCheckShadowOf(Addr, &
I);
4415 void handleLdmxcsr(IntrinsicInst &
I) {
4420 Value *Addr =
I.getArgOperand(0);
4423 Value *ShadowPtr, *OriginPtr;
4424 std::tie(ShadowPtr, OriginPtr) =
4425 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4428 insertCheckShadowOf(Addr, &
I);
4431 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4433 insertCheckShadow(Shadow, Origin, &
I);
4436 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4438 Value *Ptr =
I.getArgOperand(0);
4439 MaybeAlign
Align =
I.getParamAlign(0);
4441 Value *PassThru =
I.getArgOperand(2);
4444 insertCheckShadowOf(Ptr, &
I);
4445 insertCheckShadowOf(Mask, &
I);
4448 if (!PropagateShadow) {
4449 setShadow(&
I, getCleanShadow(&
I));
4450 setOrigin(&
I, getCleanOrigin());
4454 Type *ShadowTy = getShadowTy(&
I);
4456 auto [ShadowPtr, OriginPtr] =
4457 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4461 getShadow(PassThru),
"_msmaskedexpload");
4463 setShadow(&
I, Shadow);
4466 setOrigin(&
I, getCleanOrigin());
4469 void handleMaskedCompressStore(IntrinsicInst &
I) {
4472 Value *Ptr =
I.getArgOperand(1);
4473 MaybeAlign
Align =
I.getParamAlign(1);
4477 insertCheckShadowOf(Ptr, &
I);
4478 insertCheckShadowOf(Mask, &
I);
4482 Type *ElementShadowTy =
4484 auto [ShadowPtr, OriginPtrs] =
4485 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4492 void handleMaskedGather(IntrinsicInst &
I) {
4494 Value *Ptrs =
I.getArgOperand(0);
4497 Value *PassThru =
I.getArgOperand(2);
4499 Type *PtrsShadowTy = getShadowTy(Ptrs);
4501 insertCheckShadowOf(Mask, &
I);
4505 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4508 if (!PropagateShadow) {
4509 setShadow(&
I, getCleanShadow(&
I));
4510 setOrigin(&
I, getCleanOrigin());
4514 Type *ShadowTy = getShadowTy(&
I);
4516 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4517 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4521 getShadow(PassThru),
"_msmaskedgather");
4523 setShadow(&
I, Shadow);
4526 setOrigin(&
I, getCleanOrigin());
4529 void handleMaskedScatter(IntrinsicInst &
I) {
4532 Value *Ptrs =
I.getArgOperand(1);
4536 Type *PtrsShadowTy = getShadowTy(Ptrs);
4538 insertCheckShadowOf(Mask, &
I);
4542 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4546 Type *ElementShadowTy =
4548 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4549 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4560 void handleMaskedStore(IntrinsicInst &
I) {
4562 Value *
V =
I.getArgOperand(0);
4563 Value *Ptr =
I.getArgOperand(1);
4566 Value *Shadow = getShadow(V);
4569 insertCheckShadowOf(Ptr, &
I);
4570 insertCheckShadowOf(Mask, &
I);
4575 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4576 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4580 if (!MS.TrackOrigins)
4583 auto &
DL =
F.getDataLayout();
4584 paintOrigin(IRB, getOrigin(V), OriginPtr,
4593 void handleMaskedLoad(IntrinsicInst &
I) {
4595 Value *Ptr =
I.getArgOperand(0);
4598 Value *PassThru =
I.getArgOperand(2);
4601 insertCheckShadowOf(Ptr, &
I);
4602 insertCheckShadowOf(Mask, &
I);
4605 if (!PropagateShadow) {
4606 setShadow(&
I, getCleanShadow(&
I));
4607 setOrigin(&
I, getCleanOrigin());
4611 Type *ShadowTy = getShadowTy(&
I);
4612 Value *ShadowPtr, *OriginPtr;
4613 std::tie(ShadowPtr, OriginPtr) =
4614 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4616 getShadow(PassThru),
"_msmaskedld"));
4618 if (!MS.TrackOrigins)
4625 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4630 setOrigin(&
I, Origin);
4640 void handleMaskedIntegerDivRem(IntrinsicInst &
I) {
4643 Value *Dividend =
I.getArgOperand(0);
4644 Value *Divisor =
I.getArgOperand(1);
4647 insertCheckShadowOf(Mask, &
I);
4650 Mask, getShadow(Divisor), getCleanShadow(Divisor),
"_msmaskeddivisor");
4651 insertCheckShadow(MaskedDivisorShadow, getOrigin(Divisor), &
I);
4653 if (!PropagateShadow) {
4654 setShadow(&
I, getCleanShadow(&
I));
4655 setOrigin(&
I, getCleanOrigin());
4660 getPoisonedShadow(&
I),
"_msmaskeddiv"));
4661 setOrigin(&
I, getOrigin(Dividend));
4677 void handleAVXMaskedStore(IntrinsicInst &
I) {
4682 Value *Dst =
I.getArgOperand(0);
4683 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4688 Value *Src =
I.getArgOperand(2);
4693 Value *SrcShadow = getShadow(Src);
4696 insertCheckShadowOf(Dst, &
I);
4697 insertCheckShadowOf(Mask, &
I);
4700 Value *DstShadowPtr;
4701 Value *DstOriginPtr;
4702 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4703 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4705 SmallVector<Value *, 2> ShadowArgs;
4706 ShadowArgs.
append(1, DstShadowPtr);
4707 ShadowArgs.
append(1, Mask);
4715 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
4718 if (!MS.TrackOrigins)
4722 auto &
DL =
F.getDataLayout();
4723 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4724 DL.getTypeStoreSize(SrcShadow->
getType()),
4743 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4748 Value *Src =
I.getArgOperand(0);
4749 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4757 insertCheckShadowOf(Mask, &
I);
4760 Type *SrcShadowTy = getShadowTy(Src);
4761 Value *SrcShadowPtr, *SrcOriginPtr;
4762 std::tie(SrcShadowPtr, SrcOriginPtr) =
4763 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4765 SmallVector<Value *, 2> ShadowArgs;
4766 ShadowArgs.
append(1, SrcShadowPtr);
4767 ShadowArgs.
append(1, Mask);
4770 I.getType(),
I.getIntrinsicID(), ShadowArgs);
4776 if (!MS.TrackOrigins)
4783 setOrigin(&
I, PtrSrcOrigin);
4792 assert(isFixedIntVector(Idx));
4793 auto IdxVectorSize =
4801 auto *IdxShadow = getShadow(Idx);
4806 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4811 void handleAVXVpermilvar(IntrinsicInst &
I) {
4813 Value *Shadow = getShadow(&
I, 0);
4814 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4818 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4820 I.getType(),
I.getIntrinsicID(), {Shadow, I.getArgOperand(1)});
4823 setOriginForNaryOp(
I);
4828 void handleAVXVpermi2var(IntrinsicInst &
I) {
4833 [[maybe_unused]]
auto ArgVectorSize =
4836 ->getNumElements() == ArgVectorSize);
4838 ->getNumElements() == ArgVectorSize);
4839 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4840 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4841 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4843 Value *AShadow = getShadow(&
I, 0);
4844 Value *Idx =
I.getArgOperand(1);
4845 Value *BShadow = getShadow(&
I, 2);
4847 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4851 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4852 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4854 I.getType(),
I.getIntrinsicID(), {AShadow, Idx, BShadow});
4856 setOriginForNaryOp(
I);
4859 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4863 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4867 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4868 return isFixedIntVectorTy(
V->getType());
4871 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4872 return isFixedFPVectorTy(
V->getType());
4894 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4899 Value *WriteThrough;
4903 WriteThrough =
I.getOperand(2);
4904 Mask =
I.getOperand(3);
4907 WriteThrough =
I.getOperand(1);
4908 Mask =
I.getOperand(2);
4913 assert(isFixedIntVector(WriteThrough));
4915 unsigned ANumElements =
4917 [[maybe_unused]]
unsigned WriteThruNumElements =
4919 assert(ANumElements == WriteThruNumElements ||
4920 ANumElements * 2 == WriteThruNumElements);
4923 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4924 assert(ANumElements == MaskNumElements ||
4925 ANumElements * 2 == MaskNumElements);
4927 assert(WriteThruNumElements == MaskNumElements);
4931 insertCheckShadowOf(Mask, &
I);
4941 Value *AShadow = getShadow(
A);
4942 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4944 if (ANumElements * 2 == MaskNumElements) {
4956 "_ms_mask_bitcast");
4966 getShadowTy(&
I),
"_ms_a_shadow");
4968 Value *WriteThroughShadow = getShadow(WriteThrough);
4970 "_ms_writethru_select");
4972 setShadow(&
I, Shadow);
4973 setOriginForNaryOp(
I);
4976 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4977 SmallVector<int, 8>
Mask;
4978 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4992 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4997 "pclmul 3rd operand must be a constant");
5000 getPclmulMask(Width,
Imm & 0x01));
5002 getPclmulMask(Width,
Imm & 0x10));
5003 ShadowAndOriginCombiner SOC(
this, IRB);
5004 SOC.Add(Shuf0, getOrigin(&
I, 0));
5005 SOC.Add(Shuf1, getOrigin(&
I, 1));
5010 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
5015 Value *Second = getShadow(&
I, 1);
5017 SmallVector<int, 16>
Mask;
5018 Mask.push_back(Width);
5019 for (
unsigned i = 1; i < Width; i++)
5023 setShadow(&
I, Shadow);
5024 setOriginForNaryOp(
I);
5027 void handleVtestIntrinsic(IntrinsicInst &
I) {
5029 Value *Shadow0 = getShadow(&
I, 0);
5030 Value *Shadow1 = getShadow(&
I, 1);
5036 setShadow(&
I, Shadow);
5037 setOriginForNaryOp(
I);
5040 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
5045 Value *Second = getShadow(&
I, 1);
5048 SmallVector<int, 16>
Mask;
5049 Mask.push_back(Width);
5050 for (
unsigned i = 1; i < Width; i++)
5054 setShadow(&
I, Shadow);
5055 setOriginForNaryOp(
I);
5061 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
5062 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5067 ShadowAndOriginCombiner SC(
this, IRB);
5068 SC.Add(
I.getArgOperand(0));
5076 void handleAbsIntrinsic(IntrinsicInst &
I) {
5078 Value *Src =
I.getArgOperand(0);
5079 Value *IsIntMinPoison =
I.getArgOperand(1);
5081 assert(
I.getType()->isIntOrIntVectorTy());
5083 assert(Src->getType() ==
I.getType());
5089 Value *SrcShadow = getShadow(Src);
5093 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5096 Value *PoisonedShadow = getPoisonedShadow(Src);
5097 Value *PoisonedIfIntMinShadow =
5100 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5102 setShadow(&
I, Shadow);
5103 setOrigin(&
I, getOrigin(&
I, 0));
5106 void handleIsFpClass(IntrinsicInst &
I) {
5108 Value *Shadow = getShadow(&
I, 0);
5109 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5110 setOrigin(&
I, getOrigin(&
I, 0));
5113 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5115 Value *Shadow0 = getShadow(&
I, 0);
5116 Value *Shadow1 = getShadow(&
I, 1);
5119 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5125 setShadow(&
I, Shadow);
5126 setOriginForNaryOp(
I);
5129 void handleModfOrSincos(IntrinsicInst &
I) {
5131 Value *ArgShadow = getShadow(&
I, 0);
5135 setShadow(&
I, Shadow);
5136 setOrigin(&
I, getOrigin(&
I, 0));
5142 Value *Shadow = getShadow(V);
5164 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5169 Value *WriteThrough =
I.getOperand(1);
5173 assert(isFixedIntVector(WriteThrough));
5175 unsigned ANumElements =
5177 unsigned OutputNumElements =
5179 assert(ANumElements == OutputNumElements ||
5180 ANumElements * 2 == OutputNumElements);
5190 insertCheckShadowOf(Mask, &
I);
5193 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5194 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5195 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5206 if (ANumElements != OutputNumElements) {
5208 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5215 Value *AShadow = getShadow(
A);
5219 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5229 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5230 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5232 Value *WriteThroughShadow = getShadow(WriteThrough);
5235 setShadow(&
I, Shadow);
5236 setOriginForNaryOp(
I);
5270 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5271 SmallVector<unsigned, 4> DataIndices,
5272 unsigned WriteThruIndex,
5273 unsigned MaskIndex) {
5276 unsigned NumArgs =
I.arg_size();
5278 assert(WriteThruIndex < NumArgs);
5279 assert(MaskIndex < NumArgs);
5280 assert(WriteThruIndex != MaskIndex);
5281 Value *WriteThru =
I.getOperand(WriteThruIndex);
5283 unsigned OutputNumElements =
5288 bool isData[16] = {
false};
5290 for (
unsigned i : DataIndices) {
5292 assert(i != WriteThruIndex);
5299 [[maybe_unused]]
unsigned ANumElements =
5301 assert(ANumElements == OutputNumElements);
5306 assert(isFixedFPVector(WriteThru));
5308 for (
unsigned i = 0; i < NumArgs; ++i) {
5309 if (!isData[i] && i != WriteThruIndex) {
5312 assert(
I.getOperand(i)->getType()->isIntegerTy());
5313 insertCheckShadowOf(
I.getOperand(i), &
I);
5318 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5319 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5320 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5327 Value *DataShadow =
nullptr;
5328 for (
unsigned i : DataIndices) {
5331 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5333 DataShadow = getShadow(
A);
5341 Value *WriteThruShadow = getShadow(WriteThru);
5344 setShadow(&
I, Shadow);
5346 setOriginForNaryOp(
I);
5356 void handleAVX512FPClass(IntrinsicInst &
I) {
5361 Value *Input =
I.getOperand(0);
5362 assert(isFixedFPVector(Input));
5365 Value *Classifiers =
I.getOperand(1);
5369 assert(isFixedIntVectorTy(
I.getType()));
5375 Value *OutputShadow;
5380 OutputShadow = getCleanShadow(OutputType);
5386 OutputShadow = IRB.
CreateICmpNE(getShadow(Input), getCleanShadow(Input));
5388 setShadow(&
I, OutputShadow);
5390 setOriginForNaryOp(
I);
5400 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5406 Value *WriteThrough =
I.getOperand(2);
5413 insertCheckShadowOf(Mask, &
I);
5417 unsigned NumElements =
5419 assert(NumElements == 8);
5420 assert(
A->getType() ==
B->getType());
5422 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5425 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5426 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5428 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5430 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5437 Value *AShadow = getShadow(
A);
5438 Value *DstLowerShadow =
5439 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5441 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5444 setShadow(&
I, DstShadow);
5445 setOriginForNaryOp(
I);
5475 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5486 ->getScalarSizeInBits() == 8);
5488 assert(
A->getType() ==
X->getType());
5490 assert(
B->getType()->isIntegerTy());
5491 assert(
B->getType()->getScalarSizeInBits() == 8);
5493 assert(
I.getType() ==
A->getType());
5495 Value *AShadow = getShadow(
A);
5496 Value *XShadow = getShadow(
X);
5497 Value *BZeroShadow = getCleanShadow(
B);
5500 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5502 {X, AShadow, BZeroShadow});
5504 {XShadow, A, BZeroShadow});
5507 Value *BShadow = getShadow(
B);
5508 Value *BBroadcastShadow = getCleanShadow(AShadow);
5513 for (
unsigned i = 0; i < NumElements; i++)
5517 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5518 setOriginForNaryOp(
I);
5532 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5533 unsigned int numArgs =
I.arg_size();
5536 assert(
I.getType()->isStructTy());
5546 assert(4 <= numArgs && numArgs <= 6);
5560 for (
unsigned int i = 0; i < numArgs - 2; i++)
5561 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5564 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5568 insertCheckShadowOf(LaneNumber, &
I);
5571 Value *Src =
I.getArgOperand(numArgs - 1);
5572 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5574 Type *SrcShadowTy = getShadowTy(Src);
5575 auto [SrcShadowPtr, SrcOriginPtr] =
5576 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5583 getShadowTy(&
I),
I.getIntrinsicID(), ShadowArgs);
5586 if (!MS.TrackOrigins)
5590 setOrigin(&
I, PtrSrcOrigin);
5607 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5611 int numArgOperands =
I.arg_size();
5614 assert(numArgOperands >= 1);
5615 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5617 int skipTrailingOperands = 1;
5620 insertCheckShadowOf(Addr, &
I);
5624 skipTrailingOperands++;
5625 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5627 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5630 SmallVector<Value *, 8> ShadowArgs;
5632 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5634 Value *Shadow = getShadow(&
I, i);
5635 ShadowArgs.
append(1, Shadow);
5652 (numArgOperands - skipTrailingOperands));
5653 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5657 I.getArgOperand(numArgOperands - skipTrailingOperands));
5659 Value *OutputShadowPtr, *OutputOriginPtr;
5661 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5662 Addr, IRB, OutputShadowTy,
Align(1),
true);
5663 ShadowArgs.
append(1, OutputShadowPtr);
5666 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
5669 if (MS.TrackOrigins) {
5677 OriginCombiner OC(
this, IRB);
5678 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5679 OC.Add(
I.getArgOperand(i));
5681 const DataLayout &
DL =
F.getDataLayout();
5682 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5715 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5719 Value *
R =
I.getArgOperand(0);
5720 Value *
A =
I.getArgOperand(1);
5721 Value *
B =
I.getArgOperand(2);
5723 assert(
I.getType() ==
R->getType());
5748 Value *ShadowR = getShadow(&
I, 0);
5749 Value *ShadowA = getShadow(&
I, 1);
5750 Value *ShadowB = getShadow(&
I, 2);
5768 {getCleanShadow(RTy), ShadowA, ShadowB});
5794 {RZeros, ShadowA, ShadowB});
5808 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5809 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5811 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5813 setOriginForNaryOp(
I);
5853 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5855 unsigned int trailingVerbatimArgs,
5856 bool forceIntegerIntrinsic) {
5859 assert(trailingVerbatimArgs <
I.arg_size());
5861 SmallVector<Value *, 8> ShadowArgs;
5863 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5864 Value *Shadow = getShadow(&
I, i);
5866 if (forceIntegerIntrinsic)
5873 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5875 Value *Arg =
I.getArgOperand(i);
5876 if (forceIntegerIntrinsic)
5881 Value *CombinedShadow;
5882 if (forceIntegerIntrinsic) {
5892 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5895 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5896 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5899 setShadow(&
I, CombinedShadow);
5901 setOriginForNaryOp(
I);
5907 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5913 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5914 switch (
I.getIntrinsicID()) {
5915 case Intrinsic::uadd_with_overflow:
5916 case Intrinsic::sadd_with_overflow:
5917 case Intrinsic::usub_with_overflow:
5918 case Intrinsic::ssub_with_overflow:
5919 case Intrinsic::umul_with_overflow:
5920 case Intrinsic::smul_with_overflow:
5921 handleArithmeticWithOverflow(
I);
5923 case Intrinsic::modf:
5924 case Intrinsic::sincos:
5925 case Intrinsic::sincospi:
5926 handleModfOrSincos(
I);
5928 case Intrinsic::abs:
5929 handleAbsIntrinsic(
I);
5931 case Intrinsic::bitreverse:
5932 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5936 case Intrinsic::is_fpclass:
5939 case Intrinsic::lifetime_start:
5940 handleLifetimeStart(
I);
5942 case Intrinsic::launder_invariant_group:
5943 handleInvariantGroup(
I);
5945 case Intrinsic::bswap:
5948 case Intrinsic::ctlz:
5949 case Intrinsic::cttz:
5950 handleCountLeadingTrailingZeros(
I);
5952 case Intrinsic::masked_compressstore:
5953 handleMaskedCompressStore(
I);
5955 case Intrinsic::masked_expandload:
5956 handleMaskedExpandLoad(
I);
5958 case Intrinsic::masked_gather:
5959 handleMaskedGather(
I);
5961 case Intrinsic::masked_scatter:
5962 handleMaskedScatter(
I);
5964 case Intrinsic::masked_store:
5965 handleMaskedStore(
I);
5967 case Intrinsic::masked_load:
5968 handleMaskedLoad(
I);
5970 case Intrinsic::masked_udiv:
5971 case Intrinsic::masked_sdiv:
5972 case Intrinsic::masked_urem:
5973 case Intrinsic::masked_srem:
5974 handleMaskedIntegerDivRem(
I);
5976 case Intrinsic::vector_reduce_and:
5977 handleVectorReduceAndIntrinsic(
I);
5979 case Intrinsic::vector_reduce_or:
5980 handleVectorReduceOrIntrinsic(
I);
5983 case Intrinsic::vector_reduce_add:
5984 case Intrinsic::vector_reduce_xor:
5985 case Intrinsic::vector_reduce_mul:
5988 case Intrinsic::vector_reduce_smax:
5989 case Intrinsic::vector_reduce_smin:
5990 case Intrinsic::vector_reduce_umax:
5991 case Intrinsic::vector_reduce_umin:
5994 case Intrinsic::vector_reduce_fmax:
5995 case Intrinsic::vector_reduce_fmin:
5996 handleVectorReduceIntrinsic(
I,
false);
5999 case Intrinsic::vector_reduce_fadd:
6000 case Intrinsic::vector_reduce_fmul:
6001 handleVectorReduceWithStarterIntrinsic(
I);
6004 case Intrinsic::scmp:
6005 case Intrinsic::ucmp: {
6010 case Intrinsic::fshl:
6011 case Intrinsic::fshr:
6012 handleFunnelShift(
I);
6015 case Intrinsic::pdep:
6016 case Intrinsic::pext:
6017 handleGenericBitManipulation(
I);
6020 case Intrinsic::is_constant:
6022 setShadow(&
I, getCleanShadow(&
I));
6023 setOrigin(&
I, getCleanOrigin());
6030 case Intrinsic::fptosi_sat:
6031 case Intrinsic::fptoui_sat:
6032 handleGenericVectorConvertIntrinsic(
I,
false);
6042 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
6043 switch (
I.getIntrinsicID()) {
6044 case Intrinsic::x86_sse_stmxcsr:
6047 case Intrinsic::x86_sse_ldmxcsr:
6054 case Intrinsic::x86_avx512_vcvtsd2usi64:
6055 case Intrinsic::x86_avx512_vcvtsd2usi32:
6056 case Intrinsic::x86_avx512_vcvtss2usi64:
6057 case Intrinsic::x86_avx512_vcvtss2usi32:
6058 case Intrinsic::x86_avx512_cvttss2usi64:
6059 case Intrinsic::x86_avx512_cvttss2usi:
6060 case Intrinsic::x86_avx512_cvttsd2usi64:
6061 case Intrinsic::x86_avx512_cvttsd2usi:
6062 case Intrinsic::x86_avx512_cvtusi2ss:
6063 case Intrinsic::x86_avx512_cvtusi642sd:
6064 case Intrinsic::x86_avx512_cvtusi642ss:
6065 handleSSEVectorConvertIntrinsic(
I, 1,
true);
6067 case Intrinsic::x86_sse2_cvtsd2si64:
6068 case Intrinsic::x86_sse2_cvtsd2si:
6069 case Intrinsic::x86_sse2_cvtsd2ss:
6070 case Intrinsic::x86_sse2_cvttsd2si64:
6071 case Intrinsic::x86_sse2_cvttsd2si:
6072 case Intrinsic::x86_sse_cvtss2si64:
6073 case Intrinsic::x86_sse_cvtss2si:
6074 case Intrinsic::x86_sse_cvttss2si64:
6075 case Intrinsic::x86_sse_cvttss2si:
6076 handleSSEVectorConvertIntrinsic(
I, 1);
6078 case Intrinsic::x86_sse_cvtps2pi:
6079 case Intrinsic::x86_sse_cvttps2pi:
6080 handleSSEVectorConvertIntrinsic(
I, 2);
6088 case Intrinsic::x86_vcvtps2ph_128:
6089 case Intrinsic::x86_vcvtps2ph_256: {
6090 handleSSEVectorConvertIntrinsicByProp(
I,
true);
6099 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
6100 handleAVX512VectorConvertFPToInt(
I,
false);
6105 case Intrinsic::x86_sse2_cvtpd2ps:
6106 case Intrinsic::x86_sse2_cvtps2dq:
6107 case Intrinsic::x86_sse2_cvtpd2dq:
6108 case Intrinsic::x86_sse2_cvttps2dq:
6109 case Intrinsic::x86_sse2_cvttpd2dq:
6110 case Intrinsic::x86_avx_cvt_pd2_ps_256:
6111 case Intrinsic::x86_avx_cvt_ps2dq_256:
6112 case Intrinsic::x86_avx_cvt_pd2dq_256:
6113 case Intrinsic::x86_avx_cvtt_ps2dq_256:
6114 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
6115 handleSSEVectorConvertIntrinsicByProp(
I,
false);
6126 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
6127 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
6128 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
6129 handleAVX512VectorConvertFPToInt(
I,
true);
6133 case Intrinsic::x86_avx512_psll_w_512:
6134 case Intrinsic::x86_avx512_psll_d_512:
6135 case Intrinsic::x86_avx512_psll_q_512:
6136 case Intrinsic::x86_avx512_pslli_w_512:
6137 case Intrinsic::x86_avx512_pslli_d_512:
6138 case Intrinsic::x86_avx512_pslli_q_512:
6139 case Intrinsic::x86_avx512_psrl_w_512:
6140 case Intrinsic::x86_avx512_psrl_d_512:
6141 case Intrinsic::x86_avx512_psrl_q_512:
6142 case Intrinsic::x86_avx512_psra_w_512:
6143 case Intrinsic::x86_avx512_psra_d_512:
6144 case Intrinsic::x86_avx512_psra_q_512:
6145 case Intrinsic::x86_avx512_psrli_w_512:
6146 case Intrinsic::x86_avx512_psrli_d_512:
6147 case Intrinsic::x86_avx512_psrli_q_512:
6148 case Intrinsic::x86_avx512_psrai_w_512:
6149 case Intrinsic::x86_avx512_psrai_d_512:
6150 case Intrinsic::x86_avx512_psrai_q_512:
6151 case Intrinsic::x86_avx512_psra_q_256:
6152 case Intrinsic::x86_avx512_psra_q_128:
6153 case Intrinsic::x86_avx512_psrai_q_256:
6154 case Intrinsic::x86_avx512_psrai_q_128:
6155 case Intrinsic::x86_avx2_psll_w:
6156 case Intrinsic::x86_avx2_psll_d:
6157 case Intrinsic::x86_avx2_psll_q:
6158 case Intrinsic::x86_avx2_pslli_w:
6159 case Intrinsic::x86_avx2_pslli_d:
6160 case Intrinsic::x86_avx2_pslli_q:
6161 case Intrinsic::x86_avx2_psrl_w:
6162 case Intrinsic::x86_avx2_psrl_d:
6163 case Intrinsic::x86_avx2_psrl_q:
6164 case Intrinsic::x86_avx2_psra_w:
6165 case Intrinsic::x86_avx2_psra_d:
6166 case Intrinsic::x86_avx2_psrli_w:
6167 case Intrinsic::x86_avx2_psrli_d:
6168 case Intrinsic::x86_avx2_psrli_q:
6169 case Intrinsic::x86_avx2_psrai_w:
6170 case Intrinsic::x86_avx2_psrai_d:
6171 case Intrinsic::x86_sse2_psll_w:
6172 case Intrinsic::x86_sse2_psll_d:
6173 case Intrinsic::x86_sse2_psll_q:
6174 case Intrinsic::x86_sse2_pslli_w:
6175 case Intrinsic::x86_sse2_pslli_d:
6176 case Intrinsic::x86_sse2_pslli_q:
6177 case Intrinsic::x86_sse2_psrl_w:
6178 case Intrinsic::x86_sse2_psrl_d:
6179 case Intrinsic::x86_sse2_psrl_q:
6180 case Intrinsic::x86_sse2_psra_w:
6181 case Intrinsic::x86_sse2_psra_d:
6182 case Intrinsic::x86_sse2_psrli_w:
6183 case Intrinsic::x86_sse2_psrli_d:
6184 case Intrinsic::x86_sse2_psrli_q:
6185 case Intrinsic::x86_sse2_psrai_w:
6186 case Intrinsic::x86_sse2_psrai_d:
6187 case Intrinsic::x86_mmx_psll_w:
6188 case Intrinsic::x86_mmx_psll_d:
6189 case Intrinsic::x86_mmx_psll_q:
6190 case Intrinsic::x86_mmx_pslli_w:
6191 case Intrinsic::x86_mmx_pslli_d:
6192 case Intrinsic::x86_mmx_pslli_q:
6193 case Intrinsic::x86_mmx_psrl_w:
6194 case Intrinsic::x86_mmx_psrl_d:
6195 case Intrinsic::x86_mmx_psrl_q:
6196 case Intrinsic::x86_mmx_psra_w:
6197 case Intrinsic::x86_mmx_psra_d:
6198 case Intrinsic::x86_mmx_psrli_w:
6199 case Intrinsic::x86_mmx_psrli_d:
6200 case Intrinsic::x86_mmx_psrli_q:
6201 case Intrinsic::x86_mmx_psrai_w:
6202 case Intrinsic::x86_mmx_psrai_d:
6203 handleVectorShiftIntrinsic(
I,
false);
6205 case Intrinsic::x86_avx2_psllv_d:
6206 case Intrinsic::x86_avx2_psllv_d_256:
6207 case Intrinsic::x86_avx512_psllv_d_512:
6208 case Intrinsic::x86_avx2_psllv_q:
6209 case Intrinsic::x86_avx2_psllv_q_256:
6210 case Intrinsic::x86_avx512_psllv_q_512:
6211 case Intrinsic::x86_avx2_psrlv_d:
6212 case Intrinsic::x86_avx2_psrlv_d_256:
6213 case Intrinsic::x86_avx512_psrlv_d_512:
6214 case Intrinsic::x86_avx2_psrlv_q:
6215 case Intrinsic::x86_avx2_psrlv_q_256:
6216 case Intrinsic::x86_avx512_psrlv_q_512:
6217 case Intrinsic::x86_avx2_psrav_d:
6218 case Intrinsic::x86_avx2_psrav_d_256:
6219 case Intrinsic::x86_avx512_psrav_d_512:
6220 case Intrinsic::x86_avx512_psrav_q_128:
6221 case Intrinsic::x86_avx512_psrav_q_256:
6222 case Intrinsic::x86_avx512_psrav_q_512:
6223 handleVectorShiftIntrinsic(
I,
true);
6227 case Intrinsic::x86_sse2_packsswb_128:
6228 case Intrinsic::x86_sse2_packssdw_128:
6229 case Intrinsic::x86_sse2_packuswb_128:
6230 case Intrinsic::x86_sse41_packusdw:
6231 case Intrinsic::x86_avx2_packsswb:
6232 case Intrinsic::x86_avx2_packssdw:
6233 case Intrinsic::x86_avx2_packuswb:
6234 case Intrinsic::x86_avx2_packusdw:
6240 case Intrinsic::x86_avx512_packsswb_512:
6241 case Intrinsic::x86_avx512_packssdw_512:
6242 case Intrinsic::x86_avx512_packuswb_512:
6243 case Intrinsic::x86_avx512_packusdw_512:
6244 handleVectorPackIntrinsic(
I);
6247 case Intrinsic::x86_sse41_pblendvb:
6248 case Intrinsic::x86_sse41_blendvpd:
6249 case Intrinsic::x86_sse41_blendvps:
6250 case Intrinsic::x86_avx_blendv_pd_256:
6251 case Intrinsic::x86_avx_blendv_ps_256:
6252 case Intrinsic::x86_avx2_pblendvb:
6253 handleBlendvIntrinsic(
I);
6256 case Intrinsic::x86_avx_dp_ps_256:
6257 case Intrinsic::x86_sse41_dppd:
6258 case Intrinsic::x86_sse41_dpps:
6259 handleDppIntrinsic(
I);
6262 case Intrinsic::x86_mmx_packsswb:
6263 case Intrinsic::x86_mmx_packuswb:
6264 handleVectorPackIntrinsic(
I, 16);
6267 case Intrinsic::x86_mmx_packssdw:
6268 handleVectorPackIntrinsic(
I, 32);
6271 case Intrinsic::x86_mmx_psad_bw:
6272 handleVectorSadIntrinsic(
I,
true);
6274 case Intrinsic::x86_sse2_psad_bw:
6275 case Intrinsic::x86_avx2_psad_bw:
6276 handleVectorSadIntrinsic(
I);
6302 case Intrinsic::x86_sse2_pmadd_wd:
6303 case Intrinsic::x86_avx2_pmadd_wd:
6304 case Intrinsic::x86_avx512_pmaddw_d_512:
6305 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6306 case Intrinsic::x86_avx2_pmadd_ub_sw:
6307 case Intrinsic::x86_avx512_pmaddubs_w_512:
6308 handleVectorDotProductIntrinsic(
I, 2,
6315 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6316 handleVectorDotProductIntrinsic(
I, 2,
6323 case Intrinsic::x86_mmx_pmadd_wd:
6324 handleVectorDotProductIntrinsic(
I, 2,
6333 case Intrinsic::aarch64_neon_bfmlalt:
6334 handleVectorDotProductIntrinsic(
I, 2,
6342 case Intrinsic::aarch64_neon_bfmlalb:
6343 handleVectorDotProductIntrinsic(
I, 2,
6441 case Intrinsic::x86_avx512_vpdpbusd_128:
6442 case Intrinsic::x86_avx512_vpdpbusd_256:
6443 case Intrinsic::x86_avx512_vpdpbusd_512:
6444 case Intrinsic::x86_avx512_vpdpbusds_128:
6445 case Intrinsic::x86_avx512_vpdpbusds_256:
6446 case Intrinsic::x86_avx512_vpdpbusds_512:
6447 case Intrinsic::x86_avx2_vpdpbssd_128:
6448 case Intrinsic::x86_avx2_vpdpbssd_256:
6449 case Intrinsic::x86_avx10_vpdpbssd_512:
6450 case Intrinsic::x86_avx2_vpdpbssds_128:
6451 case Intrinsic::x86_avx2_vpdpbssds_256:
6452 case Intrinsic::x86_avx10_vpdpbssds_512:
6453 case Intrinsic::x86_avx2_vpdpbsud_128:
6454 case Intrinsic::x86_avx2_vpdpbsud_256:
6455 case Intrinsic::x86_avx10_vpdpbsud_512:
6456 case Intrinsic::x86_avx2_vpdpbsuds_128:
6457 case Intrinsic::x86_avx2_vpdpbsuds_256:
6458 case Intrinsic::x86_avx10_vpdpbsuds_512:
6459 case Intrinsic::x86_avx2_vpdpbuud_128:
6460 case Intrinsic::x86_avx2_vpdpbuud_256:
6461 case Intrinsic::x86_avx10_vpdpbuud_512:
6462 case Intrinsic::x86_avx2_vpdpbuuds_128:
6463 case Intrinsic::x86_avx2_vpdpbuuds_256:
6464 case Intrinsic::x86_avx10_vpdpbuuds_512:
6465 handleVectorDotProductIntrinsic(
I, 4,
6563 case Intrinsic::x86_avx512_vpdpwssd_128:
6564 case Intrinsic::x86_avx512_vpdpwssd_256:
6565 case Intrinsic::x86_avx512_vpdpwssd_512:
6566 case Intrinsic::x86_avx512_vpdpwssds_128:
6567 case Intrinsic::x86_avx512_vpdpwssds_256:
6568 case Intrinsic::x86_avx512_vpdpwssds_512:
6569 case Intrinsic::x86_avx2_vpdpwsud_128:
6570 case Intrinsic::x86_avx2_vpdpwsud_256:
6571 case Intrinsic::x86_avx10_vpdpwsud_512:
6572 case Intrinsic::x86_avx2_vpdpwsuds_128:
6573 case Intrinsic::x86_avx2_vpdpwsuds_256:
6574 case Intrinsic::x86_avx10_vpdpwsuds_512:
6575 case Intrinsic::x86_avx2_vpdpwusd_128:
6576 case Intrinsic::x86_avx2_vpdpwusd_256:
6577 case Intrinsic::x86_avx10_vpdpwusd_512:
6578 case Intrinsic::x86_avx2_vpdpwusds_128:
6579 case Intrinsic::x86_avx2_vpdpwusds_256:
6580 case Intrinsic::x86_avx10_vpdpwusds_512:
6581 case Intrinsic::x86_avx2_vpdpwuud_128:
6582 case Intrinsic::x86_avx2_vpdpwuud_256:
6583 case Intrinsic::x86_avx10_vpdpwuud_512:
6584 case Intrinsic::x86_avx2_vpdpwuuds_128:
6585 case Intrinsic::x86_avx2_vpdpwuuds_256:
6586 case Intrinsic::x86_avx10_vpdpwuuds_512:
6587 handleVectorDotProductIntrinsic(
I, 2,
6601 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6602 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6603 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6604 handleVectorDotProductIntrinsic(
I, 2,
6610 case Intrinsic::x86_sse_cmp_ss:
6611 case Intrinsic::x86_sse2_cmp_sd:
6612 case Intrinsic::x86_sse_comieq_ss:
6613 case Intrinsic::x86_sse_comilt_ss:
6614 case Intrinsic::x86_sse_comile_ss:
6615 case Intrinsic::x86_sse_comigt_ss:
6616 case Intrinsic::x86_sse_comige_ss:
6617 case Intrinsic::x86_sse_comineq_ss:
6618 case Intrinsic::x86_sse_ucomieq_ss:
6619 case Intrinsic::x86_sse_ucomilt_ss:
6620 case Intrinsic::x86_sse_ucomile_ss:
6621 case Intrinsic::x86_sse_ucomigt_ss:
6622 case Intrinsic::x86_sse_ucomige_ss:
6623 case Intrinsic::x86_sse_ucomineq_ss:
6624 case Intrinsic::x86_sse2_comieq_sd:
6625 case Intrinsic::x86_sse2_comilt_sd:
6626 case Intrinsic::x86_sse2_comile_sd:
6627 case Intrinsic::x86_sse2_comigt_sd:
6628 case Intrinsic::x86_sse2_comige_sd:
6629 case Intrinsic::x86_sse2_comineq_sd:
6630 case Intrinsic::x86_sse2_ucomieq_sd:
6631 case Intrinsic::x86_sse2_ucomilt_sd:
6632 case Intrinsic::x86_sse2_ucomile_sd:
6633 case Intrinsic::x86_sse2_ucomigt_sd:
6634 case Intrinsic::x86_sse2_ucomige_sd:
6635 case Intrinsic::x86_sse2_ucomineq_sd:
6636 handleVectorCompareScalarIntrinsic(
I);
6639 case Intrinsic::x86_avx_cmp_pd_256:
6640 case Intrinsic::x86_avx_cmp_ps_256:
6641 case Intrinsic::x86_sse2_cmp_pd:
6642 case Intrinsic::x86_sse_cmp_ps:
6643 handleVectorComparePackedIntrinsic(
I,
true);
6646 case Intrinsic::x86_bmi_bextr_32:
6647 case Intrinsic::x86_bmi_bextr_64:
6648 case Intrinsic::x86_bmi_bzhi_32:
6649 case Intrinsic::x86_bmi_bzhi_64:
6650 handleGenericBitManipulation(
I);
6653 case Intrinsic::x86_pclmulqdq:
6654 case Intrinsic::x86_pclmulqdq_256:
6655 case Intrinsic::x86_pclmulqdq_512:
6656 handlePclmulIntrinsic(
I);
6659 case Intrinsic::x86_avx_round_pd_256:
6660 case Intrinsic::x86_avx_round_ps_256:
6661 case Intrinsic::x86_sse41_round_pd:
6662 case Intrinsic::x86_sse41_round_ps:
6663 handleRoundPdPsIntrinsic(
I);
6666 case Intrinsic::x86_sse41_round_sd:
6667 case Intrinsic::x86_sse41_round_ss:
6668 handleUnarySdSsIntrinsic(
I);
6671 case Intrinsic::x86_sse2_max_sd:
6672 case Intrinsic::x86_sse_max_ss:
6673 case Intrinsic::x86_sse2_min_sd:
6674 case Intrinsic::x86_sse_min_ss:
6675 handleBinarySdSsIntrinsic(
I);
6678 case Intrinsic::x86_avx_vtestc_pd:
6679 case Intrinsic::x86_avx_vtestc_pd_256:
6680 case Intrinsic::x86_avx_vtestc_ps:
6681 case Intrinsic::x86_avx_vtestc_ps_256:
6682 case Intrinsic::x86_avx_vtestnzc_pd:
6683 case Intrinsic::x86_avx_vtestnzc_pd_256:
6684 case Intrinsic::x86_avx_vtestnzc_ps:
6685 case Intrinsic::x86_avx_vtestnzc_ps_256:
6686 case Intrinsic::x86_avx_vtestz_pd:
6687 case Intrinsic::x86_avx_vtestz_pd_256:
6688 case Intrinsic::x86_avx_vtestz_ps:
6689 case Intrinsic::x86_avx_vtestz_ps_256:
6690 case Intrinsic::x86_avx_ptestc_256:
6691 case Intrinsic::x86_avx_ptestnzc_256:
6692 case Intrinsic::x86_avx_ptestz_256:
6693 case Intrinsic::x86_sse41_ptestc:
6694 case Intrinsic::x86_sse41_ptestnzc:
6695 case Intrinsic::x86_sse41_ptestz:
6696 handleVtestIntrinsic(
I);
6700 case Intrinsic::x86_ssse3_phadd_w:
6701 case Intrinsic::x86_ssse3_phadd_w_128:
6702 case Intrinsic::x86_ssse3_phsub_w:
6703 case Intrinsic::x86_ssse3_phsub_w_128:
6704 handlePairwiseShadowOrIntrinsic(
I, 1,
6708 case Intrinsic::x86_avx2_phadd_w:
6709 case Intrinsic::x86_avx2_phsub_w:
6710 handlePairwiseShadowOrIntrinsic(
I, 2,
6715 case Intrinsic::x86_ssse3_phadd_d:
6716 case Intrinsic::x86_ssse3_phadd_d_128:
6717 case Intrinsic::x86_ssse3_phsub_d:
6718 case Intrinsic::x86_ssse3_phsub_d_128:
6719 handlePairwiseShadowOrIntrinsic(
I, 1,
6723 case Intrinsic::x86_avx2_phadd_d:
6724 case Intrinsic::x86_avx2_phsub_d:
6725 handlePairwiseShadowOrIntrinsic(
I, 2,
6730 case Intrinsic::x86_ssse3_phadd_sw:
6731 case Intrinsic::x86_ssse3_phadd_sw_128:
6732 case Intrinsic::x86_ssse3_phsub_sw:
6733 case Intrinsic::x86_ssse3_phsub_sw_128:
6734 handlePairwiseShadowOrIntrinsic(
I, 1,
6738 case Intrinsic::x86_avx2_phadd_sw:
6739 case Intrinsic::x86_avx2_phsub_sw:
6740 handlePairwiseShadowOrIntrinsic(
I, 2,
6745 case Intrinsic::x86_sse3_hadd_ps:
6746 case Intrinsic::x86_sse3_hadd_pd:
6747 case Intrinsic::x86_sse3_hsub_ps:
6748 case Intrinsic::x86_sse3_hsub_pd:
6749 handlePairwiseShadowOrIntrinsic(
I, 1);
6752 case Intrinsic::x86_avx_hadd_pd_256:
6753 case Intrinsic::x86_avx_hadd_ps_256:
6754 case Intrinsic::x86_avx_hsub_pd_256:
6755 case Intrinsic::x86_avx_hsub_ps_256:
6756 handlePairwiseShadowOrIntrinsic(
I, 2);
6759 case Intrinsic::x86_avx_maskstore_ps:
6760 case Intrinsic::x86_avx_maskstore_pd:
6761 case Intrinsic::x86_avx_maskstore_ps_256:
6762 case Intrinsic::x86_avx_maskstore_pd_256:
6763 case Intrinsic::x86_avx2_maskstore_d:
6764 case Intrinsic::x86_avx2_maskstore_q:
6765 case Intrinsic::x86_avx2_maskstore_d_256:
6766 case Intrinsic::x86_avx2_maskstore_q_256: {
6767 handleAVXMaskedStore(
I);
6771 case Intrinsic::x86_avx_maskload_ps:
6772 case Intrinsic::x86_avx_maskload_pd:
6773 case Intrinsic::x86_avx_maskload_ps_256:
6774 case Intrinsic::x86_avx_maskload_pd_256:
6775 case Intrinsic::x86_avx2_maskload_d:
6776 case Intrinsic::x86_avx2_maskload_q:
6777 case Intrinsic::x86_avx2_maskload_d_256:
6778 case Intrinsic::x86_avx2_maskload_q_256: {
6779 handleAVXMaskedLoad(
I);
6784 case Intrinsic::x86_avx512fp16_add_ph_512:
6785 case Intrinsic::x86_avx512fp16_sub_ph_512:
6786 case Intrinsic::x86_avx512fp16_mul_ph_512:
6787 case Intrinsic::x86_avx512fp16_div_ph_512:
6788 case Intrinsic::x86_avx512fp16_max_ph_512:
6789 case Intrinsic::x86_avx512fp16_min_ph_512:
6790 case Intrinsic::x86_avx512_min_ps_512:
6791 case Intrinsic::x86_avx512_min_pd_512:
6792 case Intrinsic::x86_avx512_max_ps_512:
6793 case Intrinsic::x86_avx512_max_pd_512: {
6798 [[maybe_unused]]
bool Success =
6799 maybeHandleSimpleNomemIntrinsic(
I, 1);
6804 case Intrinsic::x86_avx_vpermilvar_pd:
6805 case Intrinsic::x86_avx_vpermilvar_pd_256:
6806 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6807 case Intrinsic::x86_avx_vpermilvar_ps:
6808 case Intrinsic::x86_avx_vpermilvar_ps_256:
6809 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6810 handleAVXVpermilvar(
I);
6814 case Intrinsic::x86_avx512_vpermi2var_d_128:
6815 case Intrinsic::x86_avx512_vpermi2var_d_256:
6816 case Intrinsic::x86_avx512_vpermi2var_d_512:
6817 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6818 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6819 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6820 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6821 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6822 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6823 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6824 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6825 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6826 case Intrinsic::x86_avx512_vpermi2var_q_128:
6827 case Intrinsic::x86_avx512_vpermi2var_q_256:
6828 case Intrinsic::x86_avx512_vpermi2var_q_512:
6829 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6830 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6831 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6832 handleAVXVpermi2var(
I);
6846 case Intrinsic::x86_avx2_pshuf_b:
6847 case Intrinsic::x86_sse_pshuf_w:
6848 case Intrinsic::x86_ssse3_pshuf_b_128:
6849 case Intrinsic::x86_ssse3_pshuf_b:
6850 case Intrinsic::x86_avx512_pshuf_b_512:
6851 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6858 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6859 case Intrinsic::x86_avx512_mask_pmov_db_128:
6860 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6861 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6862 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6863 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6864 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6865 case Intrinsic::x86_avx512_mask_pmov_db_256:
6866 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6867 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6868 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6869 case Intrinsic::x86_avx512_mask_pmov_db_512:
6870 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6871 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6874 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6883 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6884 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6885 handleIntrinsicByApplyingToShadow(
6886 I, Intrinsic::x86_avx512_mask_pmov_dw_512,
6891 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6892 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6893 handleIntrinsicByApplyingToShadow(
6894 I, Intrinsic::x86_avx512_mask_pmov_dw_256,
6898 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6899 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6900 handleIntrinsicByApplyingToShadow(
6901 I, Intrinsic::x86_avx512_mask_pmov_dw_128,
6905 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6906 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6907 handleIntrinsicByApplyingToShadow(
6908 I, Intrinsic::x86_avx512_mask_pmov_db_512,
6913 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6914 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6915 handleIntrinsicByApplyingToShadow(
6916 I, Intrinsic::x86_avx512_mask_pmov_db_256,
6920 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6921 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6922 handleIntrinsicByApplyingToShadow(
6923 I, Intrinsic::x86_avx512_mask_pmov_db_128,
6927 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6928 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6929 handleIntrinsicByApplyingToShadow(
6930 I, Intrinsic::x86_avx512_mask_pmov_qb_512,
6935 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6936 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6937 handleIntrinsicByApplyingToShadow(
6938 I, Intrinsic::x86_avx512_mask_pmov_qb_256,
6942 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6943 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6944 handleIntrinsicByApplyingToShadow(
6945 I, Intrinsic::x86_avx512_mask_pmov_qb_128,
6949 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6950 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6951 handleIntrinsicByApplyingToShadow(
6952 I, Intrinsic::x86_avx512_mask_pmov_qw_512,
6957 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6958 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6959 handleIntrinsicByApplyingToShadow(
6960 I, Intrinsic::x86_avx512_mask_pmov_qw_256,
6964 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6965 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6966 handleIntrinsicByApplyingToShadow(
6967 I, Intrinsic::x86_avx512_mask_pmov_qw_128,
6971 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6972 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6973 handleIntrinsicByApplyingToShadow(
6974 I, Intrinsic::x86_avx512_mask_pmov_qd_128,
6978 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6979 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6980 handleIntrinsicByApplyingToShadow(
6981 I, Intrinsic::x86_avx512_mask_pmov_wb_128,
6985 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6986 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6987 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6988 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6989 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6990 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6991 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6992 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6996 handleAVX512VectorDownConvert(
I);
7007 case Intrinsic::x86_avx512_mask_compress:
7008 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7049 case Intrinsic::x86_avx512_rsqrt14_ps_512:
7050 case Intrinsic::x86_avx512_rsqrt14_ps_256:
7051 case Intrinsic::x86_avx512_rsqrt14_ps_128:
7052 case Intrinsic::x86_avx512_rsqrt14_pd_512:
7053 case Intrinsic::x86_avx512_rsqrt14_pd_256:
7054 case Intrinsic::x86_avx512_rsqrt14_pd_128:
7055 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
7056 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
7057 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
7058 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
7059 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
7060 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
7061 handleAVX512VectorGenericMaskedFP(
I, {0},
7102 case Intrinsic::x86_avx512_rcp14_ps_512:
7103 case Intrinsic::x86_avx512_rcp14_ps_256:
7104 case Intrinsic::x86_avx512_rcp14_ps_128:
7105 case Intrinsic::x86_avx512_rcp14_pd_512:
7106 case Intrinsic::x86_avx512_rcp14_pd_256:
7107 case Intrinsic::x86_avx512_rcp14_pd_128:
7108 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
7109 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
7110 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
7111 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
7112 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
7113 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
7114 handleAVX512VectorGenericMaskedFP(
I, {0},
7159 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
7160 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
7161 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
7162 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
7163 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
7164 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
7165 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
7166 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
7167 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
7168 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
7169 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
7170 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
7171 handleAVX512VectorGenericMaskedFP(
I, {0},
7207 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7208 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7209 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7210 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7211 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7212 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7213 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7214 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7215 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7219 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7239 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7240 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7241 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7242 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7243 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7244 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7245 visitGenericScalarHalfwordInst(
I);
7252 case Intrinsic::x86_avx512_fpclass_pd_512:
7253 case Intrinsic::x86_avx512_fpclass_ps_512:
7254 handleAVX512FPClass(
I);
7258 case Intrinsic::x86_vgf2p8affineqb_128:
7259 case Intrinsic::x86_vgf2p8affineqb_256:
7260 case Intrinsic::x86_vgf2p8affineqb_512:
7261 handleAVXGF2P8Affine(
I);
7271 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7272 switch (
I.getIntrinsicID()) {
7276 case Intrinsic::aarch64_neon_rshrn:
7277 case Intrinsic::aarch64_neon_sqrshl:
7278 case Intrinsic::aarch64_neon_sqrshrn:
7279 case Intrinsic::aarch64_neon_sqrshrun:
7280 case Intrinsic::aarch64_neon_sqshl:
7281 case Intrinsic::aarch64_neon_sqshlu:
7282 case Intrinsic::aarch64_neon_sqshrn:
7283 case Intrinsic::aarch64_neon_sqshrun:
7284 case Intrinsic::aarch64_neon_srshl:
7285 case Intrinsic::aarch64_neon_sshl:
7286 case Intrinsic::aarch64_neon_uqrshl:
7287 case Intrinsic::aarch64_neon_uqrshrn:
7288 case Intrinsic::aarch64_neon_uqshl:
7289 case Intrinsic::aarch64_neon_uqshrn:
7290 case Intrinsic::aarch64_neon_urshl:
7291 case Intrinsic::aarch64_neon_ushl:
7292 handleVectorShiftIntrinsic(
I,
false);
7305 case Intrinsic::aarch64_neon_vsli:
7306 case Intrinsic::aarch64_neon_vsri:
7307 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7314 case Intrinsic::aarch64_neon_fmaxp:
7315 case Intrinsic::aarch64_neon_fminp:
7317 case Intrinsic::aarch64_neon_fmaxnmp:
7318 case Intrinsic::aarch64_neon_fminnmp:
7320 case Intrinsic::aarch64_neon_smaxp:
7321 case Intrinsic::aarch64_neon_sminp:
7322 case Intrinsic::aarch64_neon_umaxp:
7323 case Intrinsic::aarch64_neon_uminp:
7325 case Intrinsic::aarch64_neon_addp:
7327 case Intrinsic::aarch64_neon_faddp:
7329 case Intrinsic::aarch64_neon_saddlp:
7330 case Intrinsic::aarch64_neon_uaddlp: {
7331 handlePairwiseShadowOrIntrinsic(
I, 1);
7336 case Intrinsic::aarch64_neon_fcvtas:
7337 case Intrinsic::aarch64_neon_fcvtau:
7339 case Intrinsic::aarch64_neon_fcvtms:
7340 case Intrinsic::aarch64_neon_fcvtmu:
7342 case Intrinsic::aarch64_neon_fcvtns:
7343 case Intrinsic::aarch64_neon_fcvtnu:
7345 case Intrinsic::aarch64_neon_fcvtps:
7346 case Intrinsic::aarch64_neon_fcvtpu:
7348 case Intrinsic::aarch64_neon_fcvtzs:
7349 case Intrinsic::aarch64_neon_fcvtzu:
7351 case Intrinsic::aarch64_neon_fcvtxn:
7352 handleGenericVectorConvertIntrinsic(
I,
false);
7356 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7357 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7358 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7359 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7360 handleGenericVectorConvertIntrinsic(
I,
true);
7369 case Intrinsic::aarch64_neon_faddv:
7370 case Intrinsic::aarch64_neon_saddv:
7371 case Intrinsic::aarch64_neon_uaddv:
7374 case Intrinsic::aarch64_neon_smaxv:
7375 case Intrinsic::aarch64_neon_sminv:
7376 case Intrinsic::aarch64_neon_umaxv:
7377 case Intrinsic::aarch64_neon_uminv:
7381 case Intrinsic::aarch64_neon_fmaxv:
7382 case Intrinsic::aarch64_neon_fminv:
7383 case Intrinsic::aarch64_neon_fmaxnmv:
7384 case Intrinsic::aarch64_neon_fminnmv:
7386 case Intrinsic::aarch64_neon_saddlv:
7387 case Intrinsic::aarch64_neon_uaddlv:
7388 handleVectorReduceIntrinsic(
I,
true);
7391 case Intrinsic::aarch64_neon_ld1x2:
7392 case Intrinsic::aarch64_neon_ld1x3:
7393 case Intrinsic::aarch64_neon_ld1x4:
7394 case Intrinsic::aarch64_neon_ld2:
7395 case Intrinsic::aarch64_neon_ld3:
7396 case Intrinsic::aarch64_neon_ld4:
7397 case Intrinsic::aarch64_neon_ld2r:
7398 case Intrinsic::aarch64_neon_ld3r:
7399 case Intrinsic::aarch64_neon_ld4r: {
7400 handleNEONVectorLoad(
I,
false);
7404 case Intrinsic::aarch64_neon_ld2lane:
7405 case Intrinsic::aarch64_neon_ld3lane:
7406 case Intrinsic::aarch64_neon_ld4lane: {
7407 handleNEONVectorLoad(
I,
true);
7412 case Intrinsic::aarch64_neon_sqxtn:
7413 case Intrinsic::aarch64_neon_sqxtun:
7414 case Intrinsic::aarch64_neon_uqxtn:
7421 case Intrinsic::aarch64_neon_st1x2:
7422 case Intrinsic::aarch64_neon_st1x3:
7423 case Intrinsic::aarch64_neon_st1x4:
7424 case Intrinsic::aarch64_neon_st2:
7425 case Intrinsic::aarch64_neon_st3:
7426 case Intrinsic::aarch64_neon_st4: {
7427 handleNEONVectorStoreIntrinsic(
I,
false);
7431 case Intrinsic::aarch64_neon_st2lane:
7432 case Intrinsic::aarch64_neon_st3lane:
7433 case Intrinsic::aarch64_neon_st4lane: {
7434 handleNEONVectorStoreIntrinsic(
I,
true);
7447 case Intrinsic::aarch64_neon_tbl1:
7448 case Intrinsic::aarch64_neon_tbl2:
7449 case Intrinsic::aarch64_neon_tbl3:
7450 case Intrinsic::aarch64_neon_tbl4:
7451 case Intrinsic::aarch64_neon_tbx1:
7452 case Intrinsic::aarch64_neon_tbx2:
7453 case Intrinsic::aarch64_neon_tbx3:
7454 case Intrinsic::aarch64_neon_tbx4: {
7456 handleIntrinsicByApplyingToShadow(
7457 I,
I.getIntrinsicID(),
7462 case Intrinsic::aarch64_neon_fmulx:
7463 case Intrinsic::aarch64_neon_pmul:
7464 case Intrinsic::aarch64_neon_pmull:
7465 case Intrinsic::aarch64_neon_smull:
7466 case Intrinsic::aarch64_neon_pmull64:
7467 case Intrinsic::aarch64_neon_umull: {
7468 handleNEONVectorMultiplyIntrinsic(
I);
7472 case Intrinsic::aarch64_neon_smmla:
7473 case Intrinsic::aarch64_neon_ummla:
7474 case Intrinsic::aarch64_neon_usmmla:
7475 case Intrinsic::aarch64_neon_bfmmla:
7476 handleNEONMatrixMultiply(
I);
7483 case Intrinsic::aarch64_neon_sdot:
7484 case Intrinsic::aarch64_neon_udot:
7485 case Intrinsic::aarch64_neon_usdot:
7486 handleVectorDotProductIntrinsic(
I, 4,
7496 case Intrinsic::aarch64_neon_bfdot:
7497 handleVectorDotProductIntrinsic(
I, 2,
7510 case Intrinsic::aarch64_neon_fp8_fdot2:
7511 handleVectorDotProductIntrinsic(
I, 2,
7524 case Intrinsic::aarch64_neon_fp8_fdot4:
7525 handleVectorDotProductIntrinsic(
I, 4,
7532 case Intrinsic::aarch64_neon_facge:
7533 case Intrinsic::aarch64_neon_facgt:
7534 handleVectorComparePackedIntrinsic(
I,
false);
7544 void visitIntrinsicInst(IntrinsicInst &
I) {
7545 if (maybeHandleCrossPlatformIntrinsic(
I))
7548 if (maybeHandleX86SIMDIntrinsic(
I))
7551 if (maybeHandleArmSIMDIntrinsic(
I))
7554 if (maybeHandleUnknownIntrinsic(
I))
7557 visitInstruction(
I);
7560 void visitLibAtomicLoad(CallBase &CB) {
7571 Value *NewOrdering =
7575 NextNodeIRBuilder NextIRB(&CB);
7576 Value *SrcShadowPtr, *SrcOriginPtr;
7577 std::tie(SrcShadowPtr, SrcOriginPtr) =
7578 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7580 Value *DstShadowPtr =
7581 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7585 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7586 if (MS.TrackOrigins) {
7587 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7589 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7590 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7594 void visitLibAtomicStore(CallBase &CB) {
7601 Value *NewOrdering =
7605 Value *DstShadowPtr =
7615 void visitCallBase(CallBase &CB) {
7623 visitAsmInstruction(CB);
7625 visitInstruction(CB);
7629 if (LF != NotLibFunc) {
7634 case LibFunc_atomic_load:
7636 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7640 visitLibAtomicLoad(CB);
7642 case LibFunc_atomic_store:
7643 visitLibAtomicStore(CB);
7659 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7663 Func->removeFnAttrs(
B);
7669 bool MayCheckCall = MS.EagerChecks;
7673 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7676 unsigned ArgOffset = 0;
7679 if (!
A->getType()->isSized()) {
7680 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7684 if (
A->getType()->isScalableTy()) {
7685 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7687 insertCheckShadowOf(
A, &CB);
7692 const DataLayout &
DL =
F.getDataLayout();
7696 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7699 insertCheckShadowOf(
A, &CB);
7700 Size =
DL.getTypeAllocSize(
A->getType());
7706 Value *ArgShadow = getShadow(
A);
7707 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7709 <<
" Shadow: " << *ArgShadow <<
"\n");
7713 assert(
A->getType()->isPointerTy() &&
7714 "ByVal argument is not a pointer!");
7722 Value *AShadowPtr, *AOriginPtr;
7723 std::tie(AShadowPtr, AOriginPtr) =
7724 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7726 if (!PropagateShadow) {
7733 if (MS.TrackOrigins) {
7734 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7748 Size =
DL.getTypeAllocSize(
A->getType());
7754 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7756 getOriginPtrForArgument(IRB, ArgOffset));
7768 if (FT->isVarArg()) {
7769 VAHelper->visitCallBase(CB, IRB);
7779 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7780 setShadow(&CB, getCleanShadow(&CB));
7781 setOrigin(&CB, getCleanOrigin());
7787 Value *
Base = getShadowPtrForRetval(IRBBefore);
7788 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7800 setShadow(&CB, getCleanShadow(&CB));
7801 setOrigin(&CB, getCleanOrigin());
7808 "Could not find insertion point for retval shadow load");
7811 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7814 setShadow(&CB, RetvalShadow);
7815 if (MS.TrackOrigins)
7816 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7821 RetVal =
I->getOperand(0);
7824 return I->isMustTailCall();
7829 void visitReturnInst(ReturnInst &
I) {
7831 Value *RetVal =
I.getReturnValue();
7837 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7838 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7839 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7842 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7844 Value *Shadow = getShadow(RetVal);
7845 bool StoreOrigin =
true;
7847 insertCheckShadowOf(RetVal, &
I);
7848 Shadow = getCleanShadow(RetVal);
7849 StoreOrigin =
false;
7856 if (MS.TrackOrigins && StoreOrigin)
7857 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7861 void visitPHINode(PHINode &
I) {
7863 if (!PropagateShadow) {
7864 setShadow(&
I, getCleanShadow(&
I));
7865 setOrigin(&
I, getCleanOrigin());
7869 ShadowPHINodes.push_back(&
I);
7870 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7872 if (MS.TrackOrigins)
7874 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7877 Value *getLocalVarIdptr(AllocaInst &
I) {
7878 ConstantInt *IntConst =
7879 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7880 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7885 Value *getLocalVarDescription(AllocaInst &
I) {
7891 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7893 Value *ShadowBase, *OriginBase;
7894 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7898 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7901 if (PoisonStack && MS.TrackOrigins) {
7902 Value *Idptr = getLocalVarIdptr(
I);
7904 Value *Descr = getLocalVarDescription(
I);
7905 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7906 {&I, Len, Idptr, Descr});
7908 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7914 Value *Descr = getLocalVarDescription(
I);
7916 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7918 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7922 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7925 NextNodeIRBuilder IRB(InsPoint);
7928 if (MS.CompileKernel)
7929 poisonAllocaKmsan(
I, IRB, Len);
7931 poisonAllocaUserspace(
I, IRB, Len);
7934 void visitAllocaInst(AllocaInst &
I) {
7935 setShadow(&
I, getCleanShadow(&
I));
7936 setOrigin(&
I, getCleanOrigin());
7942 void visitSelectInst(SelectInst &
I) {
7948 handleSelectLikeInst(
I,
B,
C,
D);
7954 Value *Sb = getShadow(
B);
7955 Value *Sc = getShadow(
C);
7956 Value *Sd = getShadow(
D);
7958 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7959 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7960 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7965 if (
I.getType()->isAggregateType()) {
7969 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7970 }
else if (isScalableNonVectorType(
I.getType())) {
7978 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7986 C = CreateAppToShadowCast(IRB,
C);
7987 D = CreateAppToShadowCast(IRB,
D);
7994 if (MS.TrackOrigins) {
7997 if (
B->getType()->isVectorTy()) {
7998 B = convertToBool(
B, IRB);
7999 Sb = convertToBool(Sb, IRB);
8007 void visitLandingPadInst(LandingPadInst &
I) {
8010 setShadow(&
I, getCleanShadow(&
I));
8011 setOrigin(&
I, getCleanOrigin());
8014 void visitCatchSwitchInst(CatchSwitchInst &
I) {
8015 setShadow(&
I, getCleanShadow(&
I));
8016 setOrigin(&
I, getCleanOrigin());
8019 void visitFuncletPadInst(FuncletPadInst &
I) {
8020 setShadow(&
I, getCleanShadow(&
I));
8021 setOrigin(&
I, getCleanOrigin());
8024 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
8026 void visitExtractValueInst(ExtractValueInst &
I) {
8028 Value *Agg =
I.getAggregateOperand();
8030 Value *AggShadow = getShadow(Agg);
8034 setShadow(&
I, ResShadow);
8035 setOriginForNaryOp(
I);
8038 void visitInsertValueInst(InsertValueInst &
I) {
8041 Value *AggShadow = getShadow(
I.getAggregateOperand());
8042 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
8048 setOriginForNaryOp(
I);
8051 void dumpInst(Instruction &
I,
const Twine &Prefix) {
8058 << CI->getCalledFunction()->
getName() <<
"\n";
8060 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
8067 unsigned NumOperands =
I.getNumOperands();
8069 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
8081 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
8082 <<
I.getOpcodeName() <<
"(";
8084 for (
size_t i = 0; i < NumOperands; i++) {
8102 void visitResumeInst(ResumeInst &
I) {
8107 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
8112 void visitCatchReturnInst(CatchReturnInst &CRI) {
8117 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
8126 insertCheckShadowOf(Operand, &
I);
8133 auto Size =
DL.getTypeStoreSize(ElemTy);
8135 if (MS.CompileKernel) {
8136 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
8142 auto [ShadowPtr,
_] =
8143 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
8153 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
8154 int NumRetOutputs = 0;
8161 NumRetOutputs =
ST->getNumElements();
8166 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
8167 switch (
Info.Type) {
8175 return NumOutputs - NumRetOutputs;
8178 void visitAsmInstruction(Instruction &
I) {
8194 const DataLayout &
DL =
F.getDataLayout();
8198 int OutputArgs = getNumOutputArgs(IA, CB);
8204 for (
int i = OutputArgs; i < NumOperands; i++) {
8212 for (
int i = 0; i < OutputArgs; i++) {
8218 setShadow(&
I, getCleanShadow(&
I));
8219 setOrigin(&
I, getCleanOrigin());
8222 void visitFreezeInst(FreezeInst &
I) {
8224 setShadow(&
I, getCleanShadow(&
I));
8225 setOrigin(&
I, getCleanOrigin());
8228 void visitInstruction(Instruction &
I) {
8231 dumpInst(
I,
"Strict");
8233 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8234 Value *Operand =
I.getOperand(i);
8236 insertCheckShadowOf(Operand, &
I);
8238 setShadow(&
I, getCleanShadow(&
I));
8239 setOrigin(&
I, getCleanOrigin());
8243struct VarArgHelperBase :
public VarArgHelper {
8245 MemorySanitizer &MS;
8246 MemorySanitizerVisitor &MSV;
8248 const unsigned VAListTagSize;
8250 VarArgHelperBase(
Function &
F, MemorySanitizer &MS,
8251 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8252 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8256 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8262 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8271 return getShadowPtrForVAArgument(IRB, ArgOffset);
8280 ConstantInt::get(MS.IntptrTy, ArgOffset),
8285 unsigned BaseOffset) {
8294 TailSize,
Align(8));
8297 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8299 Value *VAListTag =
I.getArgOperand(0);
8301 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8302 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8305 VAListTagSize, Alignment,
false);
8308 void visitVAStartInst(VAStartInst &
I)
override {
8309 if (
F.getCallingConv() == CallingConv::Win64)
8312 unpoisonVAListTagForInst(
I);
8315 void visitVACopyInst(VACopyInst &
I)
override {
8316 if (
F.getCallingConv() == CallingConv::Win64)
8318 unpoisonVAListTagForInst(
I);
8323struct VarArgAMD64Helper :
public VarArgHelperBase {
8326 static const unsigned AMD64GpEndOffset = 48;
8327 static const unsigned AMD64FpEndOffsetSSE = 176;
8329 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8331 unsigned AMD64FpEndOffset;
8332 AllocaInst *VAArgTLSCopy =
nullptr;
8333 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8334 Value *VAArgOverflowSize =
nullptr;
8336 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8338 VarArgAMD64Helper(
Function &
F, MemorySanitizer &MS,
8339 MemorySanitizerVisitor &MSV)
8340 : VarArgHelperBase(
F, MS, MSV, 24) {
8341 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8342 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8343 if (Attr.isStringAttribute() &&
8344 (Attr.getKindAsString() ==
"target-features")) {
8345 if (Attr.getValueAsString().contains(
"-sse"))
8346 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8352 ArgKind classifyArgument(
Value *arg) {
8355 if (
T->isX86_FP80Ty())
8357 if (
T->isFPOrFPVectorTy())
8358 return AK_FloatingPoint;
8359 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8360 return AK_GeneralPurpose;
8361 if (
T->isPointerTy())
8362 return AK_GeneralPurpose;
8374 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8375 unsigned GpOffset = 0;
8376 unsigned FpOffset = AMD64GpEndOffset;
8377 unsigned OverflowOffset = AMD64FpEndOffset;
8378 const DataLayout &
DL =
F.getDataLayout();
8389 assert(
A->getType()->isPointerTy());
8391 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8393 unsigned BaseOffset = OverflowOffset;
8394 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8395 Value *OriginBase =
nullptr;
8396 if (MS.TrackOrigins)
8397 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8398 OverflowOffset += AlignedSize;
8401 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8405 Value *ShadowPtr, *OriginPtr;
8406 std::tie(ShadowPtr, OriginPtr) =
8411 if (MS.TrackOrigins)
8415 ArgKind AK = classifyArgument(
A);
8416 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8418 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8420 Value *ShadowBase, *OriginBase =
nullptr;
8422 case AK_GeneralPurpose:
8423 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8424 if (MS.TrackOrigins)
8425 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8429 case AK_FloatingPoint:
8430 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8431 if (MS.TrackOrigins)
8432 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8439 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8441 unsigned BaseOffset = OverflowOffset;
8442 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8443 if (MS.TrackOrigins) {
8444 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8446 OverflowOffset += AlignedSize;
8449 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8458 Value *Shadow = MSV.getShadow(
A);
8460 if (MS.TrackOrigins) {
8461 Value *Origin = MSV.getOrigin(
A);
8462 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8463 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8469 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8470 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8473 void finalizeInstrumentation()
override {
8474 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8475 "finalizeInstrumentation called twice");
8476 if (!VAStartInstrumentationList.
empty()) {
8483 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8484 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8490 Intrinsic::umin, CopySize,
8494 if (MS.TrackOrigins) {
8495 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8504 for (CallInst *OrigInst : VAStartInstrumentationList) {
8505 NextNodeIRBuilder IRB(OrigInst);
8506 Value *VAListTag = OrigInst->getArgOperand(0);
8508 Value *RegSaveAreaPtrPtr =
8509 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8511 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8513 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8514 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8516 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8518 if (MS.TrackOrigins)
8519 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8520 Alignment, AMD64FpEndOffset);
8521 Value *OverflowArgAreaPtrPtr =
8522 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8523 Value *OverflowArgAreaPtr =
8524 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8525 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8526 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8527 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8531 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8533 if (MS.TrackOrigins) {
8536 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8544struct VarArgAArch64Helper :
public VarArgHelperBase {
8545 static const unsigned kAArch64GrArgSize = 64;
8546 static const unsigned kAArch64VrArgSize = 128;
8548 static const unsigned AArch64GrBegOffset = 0;
8549 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8551 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8552 static const unsigned AArch64VrEndOffset =
8553 AArch64VrBegOffset + kAArch64VrArgSize;
8554 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8556 AllocaInst *VAArgTLSCopy =
nullptr;
8557 Value *VAArgOverflowSize =
nullptr;
8559 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8561 VarArgAArch64Helper(
Function &
F, MemorySanitizer &MS,
8562 MemorySanitizerVisitor &MSV)
8563 : VarArgHelperBase(
F, MS, MSV, 32) {}
8566 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8567 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8568 return {AK_GeneralPurpose, 1};
8569 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8570 return {AK_FloatingPoint, 1};
8572 if (
T->isArrayTy()) {
8573 auto R = classifyArgument(
T->getArrayElementType());
8574 R.second *=
T->getScalarType()->getArrayNumElements();
8579 auto R = classifyArgument(FV->getScalarType());
8580 R.second *= FV->getNumElements();
8585 return {AK_Memory, 0};
8597 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8598 unsigned GrOffset = AArch64GrBegOffset;
8599 unsigned VrOffset = AArch64VrBegOffset;
8600 unsigned OverflowOffset = AArch64VAEndOffset;
8602 const DataLayout &
DL =
F.getDataLayout();
8605 auto [AK, RegNum] = classifyArgument(
A->getType());
8606 if (AK == AK_GeneralPurpose &&
8607 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8609 if (AK == AK_FloatingPoint &&
8610 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8614 case AK_GeneralPurpose:
8615 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8616 GrOffset += 8 * RegNum;
8618 case AK_FloatingPoint:
8619 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8620 VrOffset += 16 * RegNum;
8627 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8629 unsigned BaseOffset = OverflowOffset;
8630 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8631 OverflowOffset += AlignedSize;
8634 CleanUnusedTLS(IRB,
Base, BaseOffset);
8646 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8647 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8652 Value *SaveAreaPtrPtr =
8653 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8654 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8659 Value *SaveAreaPtr =
8660 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8662 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8665 void finalizeInstrumentation()
override {
8666 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8667 "finalizeInstrumentation called twice");
8668 if (!VAStartInstrumentationList.empty()) {
8675 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8676 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8682 Intrinsic::umin, CopySize,
8688 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8689 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8693 for (CallInst *OrigInst : VAStartInstrumentationList) {
8694 NextNodeIRBuilder IRB(OrigInst);
8696 Value *VAListTag = OrigInst->getArgOperand(0);
8713 Value *StackSaveAreaPtr =
8714 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8717 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8718 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8721 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8724 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8725 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8728 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8734 Value *GrRegSaveAreaShadowPtrOff =
8735 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8737 Value *GrRegSaveAreaShadowPtr =
8738 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8744 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8750 Value *VrRegSaveAreaShadowPtrOff =
8751 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8753 Value *VrRegSaveAreaShadowPtr =
8754 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8761 VrRegSaveAreaShadowPtrOff);
8762 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8768 Value *StackSaveAreaShadowPtr =
8769 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8774 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8777 Align(16), VAArgOverflowSize);
8783struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8784 AllocaInst *VAArgTLSCopy =
nullptr;
8785 Value *VAArgSize =
nullptr;
8787 VarArgPowerPC64Helper(
Function &
F, MemorySanitizer &MS,
8788 MemorySanitizerVisitor &MSV)
8789 : VarArgHelperBase(
F, MS, MSV, 8) {}
8791 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8799 Triple TargetTriple(
F.getParent()->getTargetTriple());
8803 if (TargetTriple.isPPC64ELFv2ABI())
8807 unsigned VAArgOffset = VAArgBase;
8808 const DataLayout &
DL =
F.getDataLayout();
8813 assert(
A->getType()->isPointerTy());
8815 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8818 ArgAlign =
Align(8);
8819 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8822 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8824 Value *AShadowPtr, *AOriginPtr;
8825 std::tie(AShadowPtr, AOriginPtr) =
8826 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8836 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8838 if (
A->getType()->isArrayTy()) {
8841 Type *ElementTy =
A->getType()->getArrayElementType();
8843 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8844 }
else if (
A->getType()->isVectorTy()) {
8846 ArgAlign =
Align(ArgSize);
8849 ArgAlign =
Align(8);
8850 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8851 if (
DL.isBigEndian()) {
8855 VAArgOffset += (8 - ArgSize);
8859 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8863 VAArgOffset += ArgSize;
8867 VAArgBase = VAArgOffset;
8871 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8874 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8877 void finalizeInstrumentation()
override {
8878 assert(!VAArgSize && !VAArgTLSCopy &&
8879 "finalizeInstrumentation called twice");
8882 Value *CopySize = VAArgSize;
8884 if (!VAStartInstrumentationList.empty()) {
8888 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8894 Intrinsic::umin, CopySize,
8902 for (CallInst *OrigInst : VAStartInstrumentationList) {
8903 NextNodeIRBuilder IRB(OrigInst);
8904 Value *VAListTag = OrigInst->getArgOperand(0);
8907 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8910 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8911 const DataLayout &
DL =
F.getDataLayout();
8912 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8914 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8915 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8917 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8924struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8925 AllocaInst *VAArgTLSCopy =
nullptr;
8926 Value *VAArgSize =
nullptr;
8928 VarArgPowerPC32Helper(
Function &
F, MemorySanitizer &MS,
8929 MemorySanitizerVisitor &MSV)
8930 : VarArgHelperBase(
F, MS, MSV, 12) {}
8932 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8936 unsigned VAArgOffset = VAArgBase;
8937 const DataLayout &
DL =
F.getDataLayout();
8938 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8943 assert(
A->getType()->isPointerTy());
8945 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8947 if (ArgAlign < IntptrSize)
8948 ArgAlign =
Align(IntptrSize);
8949 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8952 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8954 Value *AShadowPtr, *AOriginPtr;
8955 std::tie(AShadowPtr, AOriginPtr) =
8956 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8966 Type *ArgTy =
A->getType();
8972 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8979 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8982 ArgAlign =
Align(ArgSize);
8984 if (ArgAlign < IntptrSize)
8985 ArgAlign =
Align(IntptrSize);
8986 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8987 if (
DL.isBigEndian()) {
8990 if (ArgSize < IntptrSize)
8991 VAArgOffset += (IntptrSize - ArgSize);
8994 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
9000 VAArgOffset += ArgSize;
9007 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
9010 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9013 void finalizeInstrumentation()
override {
9014 assert(!VAArgSize && !VAArgTLSCopy &&
9015 "finalizeInstrumentation called twice");
9017 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9018 Value *CopySize = VAArgSize;
9020 if (!VAStartInstrumentationList.empty()) {
9024 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9030 Intrinsic::umin, CopySize,
9038 for (CallInst *OrigInst : VAStartInstrumentationList) {
9039 NextNodeIRBuilder IRB(OrigInst);
9040 Value *VAListTag = OrigInst->getArgOperand(0);
9042 Value *RegSaveAreaSize = CopySize;
9046 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
9050 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
9052 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
9055 const DataLayout &
DL =
F.getDataLayout();
9056 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9060 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9061 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9062 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9064 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
9065 Alignment, RegSaveAreaSize);
9067 RegSaveAreaShadowPtr =
9070 ConstantInt::get(MS.IntptrTy, 32));
9075 ConstantInt::get(MS.IntptrTy, 32), Alignment);
9080 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
9083 OverflowAreaPtrPtr =
9084 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
9085 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
9087 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
9089 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
9090 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
9091 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
9094 Value *OverflowVAArgTLSCopyPtr =
9096 OverflowVAArgTLSCopyPtr =
9097 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
9099 OverflowVAArgTLSCopyPtr =
9102 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
9109struct VarArgSystemZHelper :
public VarArgHelperBase {
9110 static const unsigned SystemZGpOffset = 16;
9111 static const unsigned SystemZGpEndOffset = 56;
9112 static const unsigned SystemZFpOffset = 128;
9113 static const unsigned SystemZFpEndOffset = 160;
9114 static const unsigned SystemZMaxVrArgs = 8;
9115 static const unsigned SystemZRegSaveAreaSize = 160;
9116 static const unsigned SystemZOverflowOffset = 160;
9117 static const unsigned SystemZVAListTagSize = 32;
9118 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
9119 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
9121 bool IsSoftFloatABI;
9122 AllocaInst *VAArgTLSCopy =
nullptr;
9123 AllocaInst *VAArgTLSOriginCopy =
nullptr;
9124 Value *VAArgOverflowSize =
nullptr;
9126 enum class ArgKind {
9134 enum class ShadowExtension {
None,
Zero, Sign };
9136 VarArgSystemZHelper(
Function &
F, MemorySanitizer &MS,
9137 MemorySanitizerVisitor &MSV)
9138 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
9139 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
9141 ArgKind classifyArgument(
Type *
T) {
9148 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
9149 return ArgKind::Indirect;
9150 if (
T->isFloatingPointTy())
9151 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
9152 if (
T->isIntegerTy() ||
T->isPointerTy())
9153 return ArgKind::GeneralPurpose;
9154 if (
T->isVectorTy())
9155 return ArgKind::Vector;
9156 return ArgKind::Memory;
9159 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
9169 return ShadowExtension::Zero;
9173 return ShadowExtension::Sign;
9175 return ShadowExtension::None;
9178 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9179 unsigned GpOffset = SystemZGpOffset;
9180 unsigned FpOffset = SystemZFpOffset;
9181 unsigned VrIndex = 0;
9182 unsigned OverflowOffset = SystemZOverflowOffset;
9183 const DataLayout &
DL =
F.getDataLayout();
9189 ArgKind AK = classifyArgument(
T);
9190 if (AK == ArgKind::Indirect) {
9192 AK = ArgKind::GeneralPurpose;
9194 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
9195 AK = ArgKind::Memory;
9196 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
9197 AK = ArgKind::Memory;
9198 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
9199 AK = ArgKind::Memory;
9200 Value *ShadowBase =
nullptr;
9201 Value *OriginBase =
nullptr;
9202 ShadowExtension SE = ShadowExtension::None;
9204 case ArgKind::GeneralPurpose: {
9209 SE = getShadowExtension(CB, ArgNo);
9211 if (SE == ShadowExtension::None) {
9213 assert(ArgAllocSize <= ArgSize);
9214 GapSize = ArgSize - ArgAllocSize;
9216 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9217 if (MS.TrackOrigins)
9218 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9220 GpOffset += ArgSize;
9226 case ArgKind::FloatingPoint: {
9235 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9236 if (MS.TrackOrigins)
9237 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9239 FpOffset += ArgSize;
9245 case ArgKind::Vector: {
9252 case ArgKind::Memory: {
9260 SE = getShadowExtension(CB, ArgNo);
9262 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9264 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9265 if (MS.TrackOrigins)
9267 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9268 OverflowOffset += ArgSize;
9275 case ArgKind::Indirect:
9278 if (ShadowBase ==
nullptr)
9280 Value *Shadow = MSV.getShadow(
A);
9281 if (SE != ShadowExtension::None)
9282 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9283 SE == ShadowExtension::Sign);
9284 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9286 if (MS.TrackOrigins) {
9287 Value *Origin = MSV.getOrigin(
A);
9288 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9289 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9293 Constant *OverflowSize = ConstantInt::get(
9294 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9295 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9302 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9305 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9307 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9308 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9313 unsigned RegSaveAreaSize =
9314 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9315 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9317 if (MS.TrackOrigins)
9318 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9319 Alignment, RegSaveAreaSize);
9328 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9330 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9331 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9333 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9334 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9337 SystemZOverflowOffset);
9338 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9340 if (MS.TrackOrigins) {
9342 SystemZOverflowOffset);
9343 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9348 void finalizeInstrumentation()
override {
9349 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9350 "finalizeInstrumentation called twice");
9351 if (!VAStartInstrumentationList.empty()) {
9358 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9360 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9366 Intrinsic::umin, CopySize,
9370 if (MS.TrackOrigins) {
9371 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9380 for (CallInst *OrigInst : VAStartInstrumentationList) {
9381 NextNodeIRBuilder IRB(OrigInst);
9382 Value *VAListTag = OrigInst->getArgOperand(0);
9383 copyRegSaveArea(IRB, VAListTag);
9384 copyOverflowArea(IRB, VAListTag);
9390struct VarArgI386Helper :
public VarArgHelperBase {
9391 AllocaInst *VAArgTLSCopy =
nullptr;
9392 Value *VAArgSize =
nullptr;
9394 VarArgI386Helper(
Function &
F, MemorySanitizer &MS,
9395 MemorySanitizerVisitor &MSV)
9396 : VarArgHelperBase(
F, MS, MSV, 4) {}
9398 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9399 const DataLayout &
DL =
F.getDataLayout();
9400 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9401 unsigned VAArgOffset = 0;
9406 assert(
A->getType()->isPointerTy());
9408 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9410 if (ArgAlign < IntptrSize)
9411 ArgAlign =
Align(IntptrSize);
9412 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9414 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9416 Value *AShadowPtr, *AOriginPtr;
9417 std::tie(AShadowPtr, AOriginPtr) =
9418 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9428 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9430 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9431 if (
DL.isBigEndian()) {
9434 if (ArgSize < IntptrSize)
9435 VAArgOffset += (IntptrSize - ArgSize);
9438 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9441 VAArgOffset += ArgSize;
9447 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9450 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9453 void finalizeInstrumentation()
override {
9454 assert(!VAArgSize && !VAArgTLSCopy &&
9455 "finalizeInstrumentation called twice");
9457 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9458 Value *CopySize = VAArgSize;
9460 if (!VAStartInstrumentationList.empty()) {
9463 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9469 Intrinsic::umin, CopySize,
9477 for (CallInst *OrigInst : VAStartInstrumentationList) {
9478 NextNodeIRBuilder IRB(OrigInst);
9479 Value *VAListTag = OrigInst->getArgOperand(0);
9480 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9481 Value *RegSaveAreaPtrPtr =
9483 PointerType::get(*MS.C, 0));
9484 Value *RegSaveAreaPtr =
9485 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9486 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9487 const DataLayout &
DL =
F.getDataLayout();
9488 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9490 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9491 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9493 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9501struct VarArgGenericHelper :
public VarArgHelperBase {
9502 AllocaInst *VAArgTLSCopy =
nullptr;
9503 Value *VAArgSize =
nullptr;
9505 VarArgGenericHelper(
Function &
F, MemorySanitizer &MS,
9506 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9507 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9509 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9510 unsigned VAArgOffset = 0;
9511 const DataLayout &
DL =
F.getDataLayout();
9512 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9517 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9518 if (
DL.isBigEndian()) {
9521 if (ArgSize < IntptrSize)
9522 VAArgOffset += (IntptrSize - ArgSize);
9524 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9525 VAArgOffset += ArgSize;
9526 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9532 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9535 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9538 void finalizeInstrumentation()
override {
9539 assert(!VAArgSize && !VAArgTLSCopy &&
9540 "finalizeInstrumentation called twice");
9542 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9543 Value *CopySize = VAArgSize;
9545 if (!VAStartInstrumentationList.empty()) {
9548 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9554 Intrinsic::umin, CopySize,
9562 for (CallInst *OrigInst : VAStartInstrumentationList) {
9563 NextNodeIRBuilder IRB(OrigInst);
9564 Value *VAListTag = OrigInst->getArgOperand(0);
9565 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9566 Value *RegSaveAreaPtrPtr =
9568 PointerType::get(*MS.C, 0));
9569 Value *RegSaveAreaPtr =
9570 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9571 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9572 const DataLayout &
DL =
F.getDataLayout();
9573 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9575 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9576 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9578 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9586using VarArgARM32Helper = VarArgGenericHelper;
9587using VarArgRISCVHelper = VarArgGenericHelper;
9588using VarArgMIPSHelper = VarArgGenericHelper;
9589using VarArgLoongArch64Helper = VarArgGenericHelper;
9590using VarArgHexagonHelper = VarArgGenericHelper;
9593struct VarArgNoOpHelper :
public VarArgHelper {
9594 VarArgNoOpHelper(
Function &
F, MemorySanitizer &MS,
9595 MemorySanitizerVisitor &MSV) {}
9597 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9599 void visitVAStartInst(VAStartInst &
I)
override {}
9601 void visitVACopyInst(VACopyInst &
I)
override {}
9603 void finalizeInstrumentation()
override {}
9609 MemorySanitizerVisitor &Visitor) {
9612 Triple TargetTriple(Func.getParent()->getTargetTriple());
9615 return new VarArgI386Helper(Func, Msan, Visitor);
9618 return new VarArgAMD64Helper(Func, Msan, Visitor);
9620 if (TargetTriple.
isARM())
9621 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9624 return new VarArgAArch64Helper(Func, Msan, Visitor);
9627 return new VarArgSystemZHelper(Func, Msan, Visitor);
9632 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9635 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9638 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9641 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9644 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9647 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9650 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9654 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9656 return new VarArgNoOpHelper(Func, Msan, Visitor);
9663 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9666 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9673 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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...
static bool insertModuleCtor(Module &M)
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.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
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.
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
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
LibFunc getLibFunc(StringRef funcName) 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.
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.
bool isSized() const
Return true if it makes sense to take the size of this type.
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.
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.
LLVM_ABI bool isScalableTy() const
Return true if this is a type whose size is a known multiple of vscale.
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.
@ 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.
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.
RelativeUniformCounterPtr Values
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.
@ Store
The extracted value is stored (ExtractElement only).
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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.
@ 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 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)