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");
240 "msan-track-origins",
245 cl::desc(
"keep going after reporting a UMR"),
254 "msan-poison-stack-with-call",
259 "msan-poison-stack-pattern",
260 cl::desc(
"poison uninitialized stack variables with the given pattern"),
265 cl::desc(
"Print name of local stack variable"),
270 cl::desc(
"Poison fully undef temporary values. "
271 "Partially undefined constant vectors "
272 "are unaffected by this flag (see "
273 "-msan-poison-undef-vectors)."),
277 "msan-poison-undef-vectors",
278 cl::desc(
"Precisely poison partially undefined constant vectors. "
279 "If false (legacy behavior), the entire vector is "
280 "considered fully initialized, which may lead to false "
281 "negatives. Fully undefined constant vectors are "
282 "unaffected by this flag (see -msan-poison-undef)."),
286 "msan-precise-disjoint-or",
287 cl::desc(
"Precisely poison disjoint OR. If false (legacy behavior), "
288 "disjointedness is ignored (i.e., 1|1 is initialized)."),
293 cl::desc(
"propagate shadow through ICmpEQ and ICmpNE"),
298 cl::desc(
"exact handling of relational integer ICmp"),
302 "msan-handle-lifetime-intrinsics",
304 "when possible, poison scoped variables at the beginning of the scope "
305 "(slower, but more precise)"),
316 "msan-handle-asm-conservative",
327 "msan-check-access-address",
328 cl::desc(
"report accesses through a pointer which has poisoned shadow"),
333 cl::desc(
"check arguments and return values at function call boundaries"),
337 "msan-dump-strict-instructions",
338 cl::desc(
"print out instructions with default strict semantics i.e.,"
339 "check that all the inputs are fully initialized, and mark "
340 "the output as fully initialized. These semantics are applied "
341 "to instructions that could not be handled explicitly nor "
350 "msan-dump-heuristic-instructions",
351 cl::desc(
"Prints 'unknown' instructions that were handled heuristically. "
352 "Use -msan-dump-strict-instructions to print instructions that "
353 "could not be handled explicitly nor heuristically."),
357 "msan-instrumentation-with-call-threshold",
359 "If the function being instrumented requires more than "
360 "this number of checks and origin stores, use callbacks instead of "
361 "inline checks (-1 means never use callbacks)."),
366 cl::desc(
"Enable KernelMemorySanitizer instrumentation"),
376 cl::desc(
"Insert checks for constant shadow values"),
383 cl::desc(
"Place MSan constructors in comdat sections"),
389 cl::desc(
"Define custom MSan AndMask"),
393 cl::desc(
"Define custom MSan XorMask"),
397 cl::desc(
"Define custom MSan ShadowBase"),
401 cl::desc(
"Define custom MSan OriginBase"),
406 cl::desc(
"Define threshold for number of checks per "
407 "debug location to force origin update."),
419struct MemoryMapParams {
426struct PlatformMemoryMapParams {
427 const MemoryMapParams *bits32;
428 const MemoryMapParams *bits64;
590class MemorySanitizer {
599 MemorySanitizer(MemorySanitizer &&) =
delete;
600 MemorySanitizer &operator=(MemorySanitizer &&) =
delete;
601 MemorySanitizer(
const MemorySanitizer &) =
delete;
602 MemorySanitizer &operator=(
const MemorySanitizer &) =
delete;
604 bool sanitizeFunction(Function &
F, TargetLibraryInfo &TLI);
607 friend struct MemorySanitizerVisitor;
608 friend struct VarArgHelperBase;
609 friend struct VarArgAMD64Helper;
610 friend struct VarArgAArch64Helper;
611 friend struct VarArgPowerPC64Helper;
612 friend struct VarArgPowerPC32Helper;
613 friend struct VarArgSystemZHelper;
614 friend struct VarArgI386Helper;
615 friend struct VarArgGenericHelper;
617 void initializeModule(
Module &M);
618 void initializeCallbacks(
Module &M,
const TargetLibraryInfo &TLI);
619 void createKernelApi(
Module &M,
const TargetLibraryInfo &TLI);
620 void createUserspaceApi(
Module &M,
const TargetLibraryInfo &TLI);
622 template <
typename... ArgsTy>
623 FunctionCallee getOrInsertMsanMetadataFunction(
Module &M, StringRef Name,
649 Value *ParamOriginTLS;
655 Value *RetvalOriginTLS;
661 Value *VAArgOriginTLS;
664 Value *VAArgOverflowSizeTLS;
667 bool CallbacksInitialized =
false;
670 FunctionCallee WarningFn;
674 FunctionCallee MaybeWarningVarSizeFn;
679 FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
681 FunctionCallee MsanSetAllocaOriginNoDescriptionFn;
684 FunctionCallee MsanPoisonStackFn;
688 FunctionCallee MsanChainOriginFn;
691 FunctionCallee MsanSetOriginFn;
694 FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
697 StructType *MsanContextStateTy;
698 FunctionCallee MsanGetContextStateFn;
701 FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;
707 FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;
708 FunctionCallee MsanMetadataPtrForLoad_1_8[4];
709 FunctionCallee MsanMetadataPtrForStore_1_8[4];
710 FunctionCallee MsanInstrumentAsmStoreFn;
713 Value *MsanMetadataAlloca;
716 FunctionCallee getKmsanShadowOriginAccessFn(
bool isStore,
int size);
719 const MemoryMapParams *MapParams;
723 MemoryMapParams CustomMapParams;
725 MDNode *ColdCallWeights;
728 MDNode *OriginStoreWeights;
731void insertModuleCtor(
Module &M) {
768 if (!Options.Kernel) {
777 MemorySanitizer Msan(*
F.getParent(), Options);
796 OS, MapClassName2PassName);
802 if (Options.EagerChecks)
803 OS <<
"eager-checks;";
804 OS <<
"track-origins=" << Options.TrackOrigins;
820template <
typename... ArgsTy>
822MemorySanitizer::getOrInsertMsanMetadataFunction(
Module &M,
StringRef Name,
827 std::forward<ArgsTy>(Args)...);
830 return M.getOrInsertFunction(Name, MsanMetadata,
831 std::forward<ArgsTy>(Args)...);
840 RetvalOriginTLS =
nullptr;
842 ParamOriginTLS =
nullptr;
844 VAArgOriginTLS =
nullptr;
845 VAArgOverflowSizeTLS =
nullptr;
847 WarningFn =
M.getOrInsertFunction(
"__msan_warning",
849 IRB.getVoidTy(), IRB.getInt32Ty());
860 MsanGetContextStateFn =
861 M.getOrInsertFunction(
"__msan_get_context_state", PtrTy);
865 for (
int ind = 0,
size = 1; ind < 4; ind++,
size <<= 1) {
866 std::string name_load =
867 "__msan_metadata_ptr_for_load_" + std::to_string(
size);
868 std::string name_store =
869 "__msan_metadata_ptr_for_store_" + std::to_string(
size);
870 MsanMetadataPtrForLoad_1_8[ind] =
871 getOrInsertMsanMetadataFunction(M, name_load, PtrTy);
872 MsanMetadataPtrForStore_1_8[ind] =
873 getOrInsertMsanMetadataFunction(M, name_store, PtrTy);
876 MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(
877 M,
"__msan_metadata_ptr_for_load_n", PtrTy, IntptrTy);
878 MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(
879 M,
"__msan_metadata_ptr_for_store_n", PtrTy, IntptrTy);
882 MsanPoisonAllocaFn =
M.getOrInsertFunction(
883 "__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
884 MsanUnpoisonAllocaFn =
M.getOrInsertFunction(
885 "__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);
889 return M.getOrInsertGlobal(Name, Ty, [&] {
891 nullptr, Name,
nullptr,
897void MemorySanitizer::createUserspaceApi(
Module &M,
905 StringRef WarningFnName = Recover ?
"__msan_warning_with_origin"
906 :
"__msan_warning_with_origin_noreturn";
907 WarningFn =
M.getOrInsertFunction(WarningFnName,
909 IRB.getVoidTy(), IRB.getInt32Ty());
912 Recover ?
"__msan_warning" :
"__msan_warning_noreturn";
913 WarningFn =
M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
940 IRB.getIntPtrTy(
M.getDataLayout()));
944 unsigned AccessSize = 1 << AccessSizeIndex;
945 std::string FunctionName =
"__msan_maybe_warning_" +
itostr(AccessSize);
946 MaybeWarningFn[AccessSizeIndex] =
M.getOrInsertFunction(
948 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());
949 MaybeWarningVarSizeFn =
M.getOrInsertFunction(
950 "__msan_maybe_warning_N", TLI.
getAttrList(
C, {},
false),
951 IRB.getVoidTy(), PtrTy, IRB.getInt64Ty(), IRB.getInt32Ty());
952 FunctionName =
"__msan_maybe_store_origin_" +
itostr(AccessSize);
953 MaybeStoreOriginFn[AccessSizeIndex] =
M.getOrInsertFunction(
955 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,
959 MsanSetAllocaOriginWithDescriptionFn =
960 M.getOrInsertFunction(
"__msan_set_alloca_origin_with_descr",
961 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);
962 MsanSetAllocaOriginNoDescriptionFn =
963 M.getOrInsertFunction(
"__msan_set_alloca_origin_no_descr",
964 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
965 MsanPoisonStackFn =
M.getOrInsertFunction(
"__msan_poison_stack",
966 IRB.getVoidTy(), PtrTy, IntptrTy);
970void MemorySanitizer::initializeCallbacks(
Module &M,
973 if (CallbacksInitialized)
979 MsanChainOriginFn =
M.getOrInsertFunction(
980 "__msan_chain_origin",
983 MsanSetOriginFn =
M.getOrInsertFunction(
985 IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
987 M.getOrInsertFunction(
"__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
989 M.getOrInsertFunction(
"__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
990 MemsetFn =
M.getOrInsertFunction(
"__msan_memset",
992 PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
994 MsanInstrumentAsmStoreFn =
M.getOrInsertFunction(
995 "__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
998 createKernelApi(M, TLI);
1000 createUserspaceApi(M, TLI);
1002 CallbacksInitialized =
true;
1008 isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;
1026void MemorySanitizer::initializeModule(
Module &M) {
1027 auto &
DL =
M.getDataLayout();
1029 TargetTriple =
M.getTargetTriple();
1031 bool ShadowPassed =
ClShadowBase.getNumOccurrences() > 0;
1032 bool OriginPassed =
ClOriginBase.getNumOccurrences() > 0;
1034 if (ShadowPassed || OriginPassed) {
1039 MapParams = &CustomMapParams;
1041 switch (TargetTriple.getOS()) {
1043 switch (TargetTriple.getArch()) {
1058 switch (TargetTriple.getArch()) {
1067 switch (TargetTriple.getArch()) {
1101 C = &(
M.getContext());
1103 IntptrTy = IRB.getIntPtrTy(
DL);
1104 OriginTy = IRB.getInt32Ty();
1105 PtrTy = IRB.getPtrTy();
1110 if (!CompileKernel) {
1112 M.getOrInsertGlobal(
"__msan_track_origins", IRB.getInt32Ty(), [&] {
1113 return new GlobalVariable(
1114 M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
1115 IRB.getInt32(TrackOrigins),
"__msan_track_origins");
1119 M.getOrInsertGlobal(
"__msan_keep_going", IRB.getInt32Ty(), [&] {
1120 return new GlobalVariable(M, IRB.getInt32Ty(), true,
1121 GlobalValue::WeakODRLinkage,
1122 IRB.getInt32(Recover),
"__msan_keep_going");
1137struct VarArgHelper {
1138 virtual ~VarArgHelper() =
default;
1141 virtual void visitCallBase(CallBase &CB,
IRBuilder<> &IRB) = 0;
1144 virtual void visitVAStartInst(VAStartInst &
I) = 0;
1147 virtual void visitVACopyInst(VACopyInst &
I) = 0;
1153 virtual void finalizeInstrumentation() = 0;
1156struct MemorySanitizerVisitor;
1161 MemorySanitizerVisitor &Visitor);
1168 if (TypeSizeFixed <= 8)
1177class NextNodeIRBuilder :
public IRBuilder<> {
1190struct MemorySanitizerVisitor :
public InstVisitor<MemorySanitizerVisitor> {
1192 MemorySanitizer &MS;
1194 ValueMap<Value *, Value *> ShadowMap, OriginMap;
1195 std::unique_ptr<VarArgHelper> VAHelper;
1196 const TargetLibraryInfo *TLI;
1203 bool PropagateShadow;
1206 bool PoisonUndefVectors;
1208 struct ShadowOriginAndInsertPoint {
1213 ShadowOriginAndInsertPoint(
Value *S,
Value *O, Instruction *
I)
1214 : Shadow(S), Origin(
O), OrigIns(
I) {}
1217 DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
1218 SmallSetVector<AllocaInst *, 16> AllocaSet;
1221 int64_t SplittableBlocksCount = 0;
1223 MemorySanitizerVisitor(Function &
F, MemorySanitizer &MS,
1224 const TargetLibraryInfo &TLI)
1226 bool SanitizeFunction =
1228 InsertChecks = SanitizeFunction;
1229 PropagateShadow = SanitizeFunction;
1240 MS.initializeCallbacks(*
F.getParent(), TLI);
1242 IRBuilder<>(&
F.getEntryBlock(),
F.getEntryBlock().getFirstNonPHIIt())
1243 .CreateIntrinsic(Intrinsic::donothing, {});
1245 if (MS.CompileKernel) {
1247 insertKmsanPrologue(IRB);
1251 <<
"MemorySanitizer is not inserting checks into '"
1252 <<
F.getName() <<
"'\n");
1255 bool instrumentWithCalls(
Value *V) {
1259 ++SplittableBlocksCount;
1264 bool isInPrologue(Instruction &
I) {
1265 return I.getParent() == FnPrologueEnd->
getParent() &&
1274 if (MS.TrackOrigins <= 1)
1276 return IRB.
CreateCall(MS.MsanChainOriginFn, V);
1280 const DataLayout &
DL =
F.getDataLayout();
1281 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1291 TypeSize TS, Align Alignment) {
1292 const DataLayout &
DL =
F.getDataLayout();
1293 const Align IntptrAlignment =
DL.getABITypeAlign(MS.IntptrTy);
1294 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1306 auto [InsertPt,
Index] =
1318 Align CurrentAlignment = Alignment;
1319 if (Alignment >= IntptrAlignment && IntptrSize >
kOriginSize) {
1320 Value *IntptrOrigin = originToIntptr(IRB, Origin);
1322 for (
unsigned i = 0; i <
Size / IntptrSize; ++i) {
1327 CurrentAlignment = IntptrAlignment;
1340 Value *OriginPtr, Align Alignment) {
1341 const DataLayout &
DL =
F.getDataLayout();
1343 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
1345 Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
1354 paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,
1361 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1363 if (instrumentWithCalls(ConvertedShadow) &&
1365 FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex];
1366 Value *ConvertedShadow2 =
1368 CallBase *CB = IRB.
CreateCall(Fn, {ConvertedShadow2, Addr, Origin});
1372 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1376 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize,
1381 void materializeStores() {
1382 for (StoreInst *SI : StoreList) {
1384 Value *Val =
SI->getValueOperand();
1385 Value *Addr =
SI->getPointerOperand();
1386 Value *Shadow =
SI->isAtomic() ? getCleanShadow(Val) : getShadow(Val);
1387 Value *ShadowPtr, *OriginPtr;
1389 const Align Alignment =
SI->getAlign();
1391 std::tie(ShadowPtr, OriginPtr) =
1392 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
true);
1394 [[maybe_unused]] StoreInst *NewSI =
1401 if (MS.TrackOrigins && !
SI->isAtomic())
1402 storeOrigin(IRB, Addr, Shadow, getOrigin(Val), OriginPtr,
1409 if (MS.TrackOrigins < 2)
1412 if (LazyWarningDebugLocationCount.
empty())
1413 for (
const auto &
I : InstrumentationList)
1414 ++LazyWarningDebugLocationCount[
I.OrigIns->getDebugLoc()];
1430 auto NewDebugLoc = OI->getDebugLoc();
1437 IRBOrigin.SetCurrentDebugLocation(NewDebugLoc);
1438 Origin = updateOrigin(Origin, IRBOrigin);
1443 if (MS.CompileKernel || MS.TrackOrigins)
1454 const DataLayout &
DL =
F.getDataLayout();
1455 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1457 if (instrumentWithCalls(ConvertedShadow) && !MS.CompileKernel) {
1459 ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);
1460 Value *ConvertedShadow2 =
1464 FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];
1468 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1472 FunctionCallee Fn = MS.MaybeWarningVarSizeFn;
1475 unsigned ShadowSize =
DL.getTypeAllocSize(ConvertedShadow2->
getType());
1478 {ShadowAlloca, ConstantInt::get(IRB.
getInt64Ty(), ShadowSize),
1479 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1484 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1487 !MS.Recover, MS.ColdCallWeights);
1490 insertWarningFn(IRB, Origin);
1495 void materializeInstructionChecks(
1497 const DataLayout &
DL =
F.getDataLayout();
1500 bool Combine = !MS.TrackOrigins;
1502 Value *Shadow =
nullptr;
1503 for (
const auto &ShadowData : InstructionChecks) {
1504 assert(ShadowData.OrigIns == Instruction);
1507 Value *ConvertedShadow = ShadowData.Shadow;
1516 insertWarningFn(IRB, ShadowData.Origin);
1526 materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin);
1531 Shadow = ConvertedShadow;
1535 Shadow = convertToBool(Shadow, IRB,
"_mscmp");
1536 ConvertedShadow = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1537 Shadow = IRB.
CreateOr(Shadow, ConvertedShadow,
"_msor");
1543 materializeOneCheck(IRB, Shadow,
nullptr);
1547 void materializeChecks() {
1550 SmallPtrSet<Instruction *, 16>
Done;
1553 for (
auto I = InstrumentationList.begin();
1554 I != InstrumentationList.end();) {
1555 auto OrigIns =
I->OrigIns;
1559 auto J = std::find_if(
I + 1, InstrumentationList.end(),
1560 [OrigIns](
const ShadowOriginAndInsertPoint &R) {
1561 return OrigIns != R.OrigIns;
1575 MS.ParamTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1576 {Zero, IRB.getInt32(0)},
"param_shadow");
1577 MS.RetvalTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1578 {Zero, IRB.getInt32(1)},
"retval_shadow");
1579 MS.VAArgTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1580 {Zero, IRB.getInt32(2)},
"va_arg_shadow");
1581 MS.VAArgOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1582 {Zero, IRB.getInt32(3)},
"va_arg_origin");
1583 MS.VAArgOverflowSizeTLS =
1584 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1585 {Zero, IRB.getInt32(4)},
"va_arg_overflow_size");
1586 MS.ParamOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1587 {Zero, IRB.getInt32(5)},
"param_origin");
1588 MS.RetvalOriginTLS =
1589 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1590 {Zero, IRB.getInt32(6)},
"retval_origin");
1592 MS.MsanMetadataAlloca = IRB.
CreateAlloca(MS.MsanMetadata, 0u);
1605 for (Instruction *
I : Instructions)
1609 for (PHINode *PN : ShadowPHINodes) {
1611 PHINode *PNO = MS.TrackOrigins ?
cast<PHINode>(getOrigin(PN)) : nullptr;
1612 size_t NumValues = PN->getNumIncomingValues();
1613 for (
size_t v = 0;
v < NumValues;
v++) {
1614 PNS->
addIncoming(getShadow(PN, v), PN->getIncomingBlock(v));
1616 PNO->
addIncoming(getOrigin(PN, v), PN->getIncomingBlock(v));
1620 VAHelper->finalizeInstrumentation();
1625 for (
auto Item : LifetimeStartList) {
1626 instrumentAlloca(*Item.second, Item.first);
1627 AllocaSet.
remove(Item.second);
1632 for (AllocaInst *AI : AllocaSet)
1633 instrumentAlloca(*AI);
1636 materializeChecks();
1640 materializeStores();
1646 Type *getShadowTy(
Value *V) {
return getShadowTy(
V->getType()); }
1657 const DataLayout &
DL =
F.getDataLayout();
1659 uint32_t EltSize =
DL.getTypeSizeInBits(VT->getElementType());
1661 VT->getElementCount());
1664 return ArrayType::get(getShadowTy(AT->getElementType()),
1665 AT->getNumElements());
1669 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
1670 Elements.push_back(getShadowTy(
ST->getElementType(i)));
1672 LLVM_DEBUG(
dbgs() <<
"getShadowTy: " << *ST <<
" ===> " << *Res <<
"\n");
1675 uint32_t TypeSize =
DL.getTypeSizeInBits(OrigTy);
1685 for (
unsigned Idx = 0; Idx <
Struct->getNumElements(); Idx++) {
1688 Value *ShadowBool = convertToBool(ShadowItem, IRB);
1690 if (Aggregator != FalseVal)
1691 Aggregator = IRB.
CreateOr(Aggregator, ShadowBool);
1693 Aggregator = ShadowBool;
1700 Value *collapseArrayShadow(ArrayType *Array,
Value *Shadow,
1702 if (!
Array->getNumElements())
1706 Value *Aggregator = convertShadowToScalar(FirstItem, IRB);
1708 for (
unsigned Idx = 1; Idx <
Array->getNumElements(); Idx++) {
1710 Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);
1711 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1721 return collapseStructShadow(
Struct, V, IRB);
1723 return collapseArrayShadow(Array, V, IRB);
1728 V->getType()->getPrimitiveSizeInBits().getFixedValue();
1736 Type *VTy =
V->getType();
1738 return convertToBool(convertShadowToScalar(V, IRB), IRB,
name);
1745 Type *ptrToIntPtrType(
Type *PtrTy)
const {
1747 return VectorType::get(ptrToIntPtrType(VectTy->getElementType()),
1748 VectTy->getElementCount());
1754 Type *getPtrToShadowPtrType(
Type *IntPtrTy,
Type *ShadowTy)
const {
1756 return VectorType::get(
1757 getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
1758 VectTy->getElementCount());
1760 assert(IntPtrTy == MS.IntptrTy);
1767 VectTy->getElementCount(),
1768 constToIntPtr(VectTy->getElementType(),
C));
1770 assert(IntPtrTy == MS.IntptrTy);
1771 return ConstantInt::get(MS.IntptrTy,
C);
1784 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1787 if (uint64_t AndMask = MS.MapParams->AndMask)
1788 OffsetLong = IRB.
CreateAnd(OffsetLong, constToIntPtr(IntptrTy, ~AndMask));
1790 if (uint64_t XorMask = MS.MapParams->XorMask)
1791 OffsetLong = IRB.
CreateXor(OffsetLong, constToIntPtr(IntptrTy, XorMask));
1803 std::pair<Value *, Value *>
1805 MaybeAlign Alignment) {
1810 assert(VectTy->getElementType()->isPointerTy());
1812 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1813 Value *ShadowOffset = getShadowPtrOffset(Addr, IRB);
1814 Value *ShadowLong = ShadowOffset;
1815 if (uint64_t ShadowBase = MS.MapParams->ShadowBase) {
1817 IRB.
CreateAdd(ShadowLong, constToIntPtr(IntptrTy, ShadowBase));
1820 ShadowLong, getPtrToShadowPtrType(IntptrTy, ShadowTy));
1822 Value *OriginPtr =
nullptr;
1823 if (MS.TrackOrigins) {
1824 Value *OriginLong = ShadowOffset;
1825 uint64_t OriginBase = MS.MapParams->OriginBase;
1826 if (OriginBase != 0)
1828 IRB.
CreateAdd(OriginLong, constToIntPtr(IntptrTy, OriginBase));
1831 OriginLong = IRB.
CreateAnd(OriginLong, constToIntPtr(IntptrTy, ~Mask));
1834 OriginLong, getPtrToShadowPtrType(IntptrTy, MS.OriginTy));
1836 return std::make_pair(ShadowPtr, OriginPtr);
1839 template <
typename... ArgsTy>
1844 {MS.MsanMetadataAlloca, std::forward<ArgsTy>(Args)...});
1845 return IRB.
CreateLoad(MS.MsanMetadata, MS.MsanMetadataAlloca);
1848 return IRB.
CreateCall(Callee, {std::forward<ArgsTy>(Args)...});
1851 std::pair<Value *, Value *> getShadowOriginPtrKernelNoVec(
Value *Addr,
1855 Value *ShadowOriginPtrs;
1856 const DataLayout &
DL =
F.getDataLayout();
1857 TypeSize
Size =
DL.getTypeStoreSize(ShadowTy);
1859 FunctionCallee Getter = MS.getKmsanShadowOriginAccessFn(
isStore,
Size);
1862 ShadowOriginPtrs = createMetadataCall(IRB, Getter, AddrCast);
1864 Value *SizeVal = ConstantInt::get(MS.IntptrTy,
Size);
1865 ShadowOriginPtrs = createMetadataCall(
1867 isStore ? MS.MsanMetadataPtrForStoreN : MS.MsanMetadataPtrForLoadN,
1874 return std::make_pair(ShadowPtr, OriginPtr);
1880 std::pair<Value *, Value *> getShadowOriginPtrKernel(
Value *Addr,
1887 return getShadowOriginPtrKernelNoVec(Addr, IRB, ShadowTy,
isStore);
1892 Value *ShadowPtrs = ConstantInt::getNullValue(
1894 Value *OriginPtrs =
nullptr;
1895 if (MS.TrackOrigins)
1896 OriginPtrs = ConstantInt::getNullValue(
1898 for (
unsigned i = 0; i < NumElements; ++i) {
1901 auto [ShadowPtr, OriginPtr] =
1902 getShadowOriginPtrKernelNoVec(OneAddr, IRB, ShadowTy,
isStore);
1905 ShadowPtrs, ShadowPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1906 if (MS.TrackOrigins)
1908 OriginPtrs, OriginPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1910 return {ShadowPtrs, OriginPtrs};
1913 std::pair<Value *, Value *> getShadowOriginPtr(
Value *Addr,
IRBuilder<> &IRB,
1915 MaybeAlign Alignment,
1917 if (MS.CompileKernel)
1918 return getShadowOriginPtrKernel(Addr, IRB, ShadowTy,
isStore);
1919 return getShadowOriginPtrUserspace(Addr, IRB, ShadowTy, Alignment);
1934 if (!MS.TrackOrigins)
1948 Value *getOriginPtrForRetval() {
1950 return MS.RetvalOriginTLS;
1955 assert(!ShadowMap.
count(V) &&
"Values may only have one shadow");
1956 ShadowMap[
V] = PropagateShadow ? SV : getCleanShadow(V);
1961 if (!MS.TrackOrigins)
1963 assert(!OriginMap.
count(V) &&
"Values may only have one origin");
1964 LLVM_DEBUG(
dbgs() <<
"ORIGIN: " << *V <<
" ==> " << *Origin <<
"\n");
1965 OriginMap[
V] = Origin;
1969 Type *ShadowTy = getShadowTy(OrigTy);
1979 Constant *getCleanShadow(
Value *V) {
return getCleanShadow(
V->getType()); }
1988 getPoisonedShadow(AT->getElementType()));
1993 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
1994 Vals.
push_back(getPoisonedShadow(
ST->getElementType(i)));
2002 Type *ShadowTy = getShadowTy(V);
2005 return getPoisonedShadow(ShadowTy);
2017 if (!PropagateShadow ||
I->getMetadata(LLVMContext::MD_nosanitize))
2018 return getCleanShadow(V);
2020 Value *Shadow = ShadowMap[
V];
2022 LLVM_DEBUG(
dbgs() <<
"No shadow: " << *V <<
"\n" << *(
I->getParent()));
2023 assert(Shadow &&
"No shadow for a value");
2030 Value *
AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
2031 : getCleanShadow(V);
2037 Value *&ShadowPtr = ShadowMap[
V];
2042 unsigned ArgOffset = 0;
2043 const DataLayout &
DL =
F->getDataLayout();
2044 for (
auto &FArg :
F->args()) {
2045 if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
2047 ?
"vscale not fully supported\n"
2048 :
"Arg is not sized\n"));
2050 ShadowPtr = getCleanShadow(V);
2051 setOrigin(
A, getCleanOrigin());
2057 unsigned Size = FArg.hasByValAttr()
2058 ?
DL.getTypeAllocSize(FArg.getParamByValType())
2059 :
DL.getTypeAllocSize(FArg.getType());
2063 if (FArg.hasByValAttr()) {
2067 const Align ArgAlign =
DL.getValueOrABITypeAlignment(
2068 FArg.getParamAlign(), FArg.getParamByValType());
2069 Value *CpShadowPtr, *CpOriginPtr;
2070 std::tie(CpShadowPtr, CpOriginPtr) =
2071 getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,
2073 if (!PropagateShadow || Overflow) {
2075 EntryIRB.CreateMemSet(
2079 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2081 [[maybe_unused]]
Value *Cpy = EntryIRB.CreateMemCpy(
2082 CpShadowPtr, CopyAlign,
Base, CopyAlign,
Size);
2085 if (MS.TrackOrigins) {
2086 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2090 EntryIRB.CreateMemCpy(
2099 if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||
2100 (MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {
2101 ShadowPtr = getCleanShadow(V);
2102 setOrigin(
A, getCleanOrigin());
2105 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2106 ShadowPtr = EntryIRB.CreateAlignedLoad(getShadowTy(&FArg),
Base,
2108 if (MS.TrackOrigins) {
2109 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2110 setOrigin(
A, EntryIRB.CreateLoad(MS.OriginTy, OriginPtr));
2114 <<
" ARG: " << FArg <<
" ==> " << *ShadowPtr <<
"\n");
2120 assert(ShadowPtr &&
"Could not find shadow for an argument");
2127 cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
2128 PoisonUndefVectors) {
2131 for (
unsigned i = 0; i != NumElems; ++i) {
2134 : getCleanShadow(Elem);
2138 LLVM_DEBUG(
dbgs() <<
"Partial undef constant vector: " << *V <<
" ==> "
2139 << *ShadowConstant <<
"\n");
2141 return ShadowConstant;
2147 return getCleanShadow(V);
2151 Value *getShadow(Instruction *
I,
int i) {
2152 return getShadow(
I->getOperand(i));
2157 if (!MS.TrackOrigins)
2160 return getCleanOrigin();
2162 "Unexpected value type in getOrigin()");
2164 if (
I->getMetadata(LLVMContext::MD_nosanitize))
2165 return getCleanOrigin();
2167 Value *Origin = OriginMap[
V];
2168 assert(Origin &&
"Missing origin");
2173 Value *getOrigin(Instruction *
I,
int i) {
2174 return getOrigin(
I->getOperand(i));
2181 void insertCheckShadow(
Value *Shadow,
Value *Origin, Instruction *OrigIns) {
2187 LLVM_DEBUG(
dbgs() <<
"Skipping check of " << *Shadow <<
" before "
2188 << *OrigIns <<
"\n");
2195 "Can only insert checks for integer, vector, and aggregate shadow "
2198 InstrumentationList.push_back(
2199 ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
2207 void insertCheckShadowOf(
Value *Val, Instruction *OrigIns) {
2209 Value *Shadow, *Origin;
2211 Shadow = getShadow(Val);
2214 Origin = getOrigin(Val);
2221 insertCheckShadow(Shadow, Origin, OrigIns);
2226 case AtomicOrdering::NotAtomic:
2227 return AtomicOrdering::NotAtomic;
2228 case AtomicOrdering::Unordered:
2229 case AtomicOrdering::Monotonic:
2230 case AtomicOrdering::Release:
2231 return AtomicOrdering::Release;
2232 case AtomicOrdering::Acquire:
2233 case AtomicOrdering::AcquireRelease:
2234 return AtomicOrdering::AcquireRelease;
2235 case AtomicOrdering::SequentiallyConsistent:
2236 return AtomicOrdering::SequentiallyConsistent;
2242 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2243 uint32_t OrderingTable[NumOrderings] = {};
2245 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2246 OrderingTable[(
int)AtomicOrderingCABI::release] =
2247 (int)AtomicOrderingCABI::release;
2248 OrderingTable[(int)AtomicOrderingCABI::consume] =
2249 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2250 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
2251 (
int)AtomicOrderingCABI::acq_rel;
2252 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2253 (
int)AtomicOrderingCABI::seq_cst;
2260 case AtomicOrdering::NotAtomic:
2261 return AtomicOrdering::NotAtomic;
2262 case AtomicOrdering::Unordered:
2263 case AtomicOrdering::Monotonic:
2264 case AtomicOrdering::Acquire:
2265 return AtomicOrdering::Acquire;
2266 case AtomicOrdering::Release:
2267 case AtomicOrdering::AcquireRelease:
2268 return AtomicOrdering::AcquireRelease;
2269 case AtomicOrdering::SequentiallyConsistent:
2270 return AtomicOrdering::SequentiallyConsistent;
2276 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2277 uint32_t OrderingTable[NumOrderings] = {};
2279 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2280 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2281 OrderingTable[(int)AtomicOrderingCABI::consume] =
2282 (
int)AtomicOrderingCABI::acquire;
2283 OrderingTable[(int)AtomicOrderingCABI::release] =
2284 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
2285 (int)AtomicOrderingCABI::acq_rel;
2286 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2287 (
int)AtomicOrderingCABI::seq_cst;
2293 using InstVisitor<MemorySanitizerVisitor>
::visit;
2294 void visit(Instruction &
I) {
2295 if (
I.getMetadata(LLVMContext::MD_nosanitize))
2298 if (isInPrologue(
I))
2303 setShadow(&
I, getCleanShadow(&
I));
2304 setOrigin(&
I, getCleanOrigin());
2315 void visitLoadInst(LoadInst &
I) {
2316 assert(
I.getType()->isSized() &&
"Load type must have size");
2317 assert(!
I.getMetadata(LLVMContext::MD_nosanitize));
2318 NextNodeIRBuilder IRB(&
I);
2319 Type *ShadowTy = getShadowTy(&
I);
2320 Value *Addr =
I.getPointerOperand();
2321 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
2322 const Align Alignment =
I.getAlign();
2323 if (PropagateShadow) {
2324 std::tie(ShadowPtr, OriginPtr) =
2325 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
2329 setShadow(&
I, getCleanShadow(&
I));
2333 insertCheckShadowOf(
I.getPointerOperand(), &
I);
2338 if (MS.TrackOrigins) {
2339 if (PropagateShadow) {
2344 setOrigin(&
I, getCleanOrigin());
2353 void visitStoreInst(StoreInst &
I) {
2354 StoreList.push_back(&
I);
2356 insertCheckShadowOf(
I.getPointerOperand(), &
I);
2359 void handleCASOrRMW(Instruction &
I) {
2363 Value *Addr =
I.getOperand(0);
2364 Value *Val =
I.getOperand(1);
2365 Value *ShadowPtr = getShadowOriginPtr(Addr, IRB, getShadowTy(Val),
Align(1),
2370 insertCheckShadowOf(Addr, &
I);
2376 insertCheckShadowOf(Val, &
I);
2380 setShadow(&
I, getCleanShadow(&
I));
2381 setOrigin(&
I, getCleanOrigin());
2384 void visitAtomicRMWInst(AtomicRMWInst &
I) {
2389 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2395 void visitExtractElementInst(ExtractElementInst &
I) {
2396 insertCheckShadowOf(
I.getOperand(1), &
I);
2400 setOrigin(&
I, getOrigin(&
I, 0));
2403 void visitInsertElementInst(InsertElementInst &
I) {
2404 insertCheckShadowOf(
I.getOperand(2), &
I);
2406 auto *Shadow0 = getShadow(&
I, 0);
2407 auto *Shadow1 = getShadow(&
I, 1);
2410 setOriginForNaryOp(
I);
2413 void visitShuffleVectorInst(ShuffleVectorInst &
I) {
2415 auto *Shadow0 = getShadow(&
I, 0);
2416 auto *Shadow1 = getShadow(&
I, 1);
2419 setOriginForNaryOp(
I);
2423 void visitSExtInst(SExtInst &
I) {
2425 setShadow(&
I, IRB.
CreateSExt(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2426 setOrigin(&
I, getOrigin(&
I, 0));
2429 void visitZExtInst(ZExtInst &
I) {
2431 setShadow(&
I, IRB.
CreateZExt(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2432 setOrigin(&
I, getOrigin(&
I, 0));
2435 void visitTruncInst(TruncInst &
I) {
2437 setShadow(&
I, IRB.
CreateTrunc(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2438 setOrigin(&
I, getOrigin(&
I, 0));
2441 void visitBitCastInst(BitCastInst &
I) {
2446 if (CI->isMustTailCall())
2450 setOrigin(&
I, getOrigin(&
I, 0));
2453 void visitPtrToIntInst(PtrToIntInst &
I) {
2456 "_msprop_ptrtoint"));
2457 setOrigin(&
I, getOrigin(&
I, 0));
2460 void visitIntToPtrInst(IntToPtrInst &
I) {
2463 "_msprop_inttoptr"));
2464 setOrigin(&
I, getOrigin(&
I, 0));
2467 void visitFPToSIInst(CastInst &
I) { handleShadowOr(
I); }
2468 void visitFPToUIInst(CastInst &
I) { handleShadowOr(
I); }
2469 void visitSIToFPInst(CastInst &
I) { handleShadowOr(
I); }
2470 void visitUIToFPInst(CastInst &
I) { handleShadowOr(
I); }
2471 void visitFPExtInst(CastInst &
I) { handleShadowOr(
I); }
2472 void visitFPTruncInst(CastInst &
I) { handleShadowOr(
I); }
2479 void visitAnd(BinaryOperator &
I) {
2487 Value *S2 = getShadow(&
I, 1);
2488 Value *V1 =
I.getOperand(0);
2489 Value *V2 =
I.getOperand(1);
2497 setShadow(&
I, IRB.
CreateOr({S1S2, V1S2, S1V2}));
2498 setOriginForNaryOp(
I);
2501 void visitOr(BinaryOperator &
I) {
2514 Value *S2 = getShadow(&
I, 1);
2515 Value *V1 =
I.getOperand(0);
2516 Value *V2 =
I.getOperand(1);
2535 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2539 setOriginForNaryOp(
I);
2557 template <
bool CombineShadow>
class Combiner {
2558 Value *Shadow =
nullptr;
2559 Value *Origin =
nullptr;
2561 MemorySanitizerVisitor *MSV;
2564 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2565 : IRB(IRB), MSV(MSV) {}
2569 if (CombineShadow) {
2574 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2575 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2579 if (MSV->MS.TrackOrigins) {
2586 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2587 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2597 Value *OpShadow = MSV->getShadow(V);
2598 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2599 return Add(OpShadow, OpOrigin);
2604 void Done(Instruction *
I) {
2605 if (CombineShadow) {
2607 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2608 MSV->setShadow(
I, Shadow);
2610 if (MSV->MS.TrackOrigins) {
2612 MSV->setOrigin(
I, Origin);
2618 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2619 if (MSV->MS.TrackOrigins) {
2626 using ShadowAndOriginCombiner = Combiner<true>;
2627 using OriginCombiner = Combiner<false>;
2630 void setOriginForNaryOp(Instruction &
I) {
2631 if (!MS.TrackOrigins)
2634 OriginCombiner
OC(
this, IRB);
2635 for (Use &
Op :
I.operands())
2640 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2642 "Vector of pointers is not a valid shadow type");
2652 Type *srcTy =
V->getType();
2655 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2656 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2657 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2675 Type *ShadowTy = getShadowTy(V);
2676 if (
V->getType() == ShadowTy)
2678 if (
V->getType()->isPtrOrPtrVectorTy())
2685 void handleShadowOr(Instruction &
I) {
2687 ShadowAndOriginCombiner SC(
this, IRB);
2688 for (Use &
Op :
I.operands())
2705 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2708 unsigned TotalNumElems =
2713 TotalNumElems = TotalNumElems * 2;
2716 assert(TotalNumElems % ReductionFactor == 0);
2721 for (
unsigned i = 0; i < ReductionFactor; i++) {
2722 SmallVector<int, 16>
Mask;
2723 for (
unsigned X = 0;
X < TotalNumElems;
X += ReductionFactor)
2724 Mask.push_back(
X + i);
2746 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I) {
2747 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2749 assert(
I.getType()->isVectorTy());
2750 assert(
I.getArgOperand(0)->getType()->isVectorTy());
2752 [[maybe_unused]] FixedVectorType *ParamType =
2756 [[maybe_unused]] FixedVectorType *
ReturnType =
2764 Value *FirstArgShadow = getShadow(&
I, 0);
2765 Value *SecondArgShadow =
nullptr;
2766 if (
I.arg_size() == 2)
2767 SecondArgShadow = getShadow(&
I, 1);
2769 Value *OrShadow = horizontalReduce(
I, 2, FirstArgShadow,
2772 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
2774 setShadow(&
I, OrShadow);
2775 setOriginForNaryOp(
I);
2785 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
2786 int ReinterpretElemWidth) {
2787 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2789 assert(
I.getType()->isVectorTy());
2790 assert(
I.getArgOperand(0)->getType()->isVectorTy());
2792 FixedVectorType *ParamType =
2797 [[maybe_unused]] FixedVectorType *
ReturnType =
2804 FixedVectorType *ReinterpretShadowTy =
nullptr;
2812 Value *FirstArgShadow = getShadow(&
I, 0);
2813 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
2823 Value *SecondArgShadow =
nullptr;
2824 if (
I.arg_size() == 2) {
2825 SecondArgShadow = getShadow(&
I, 1);
2826 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
2829 Value *OrShadow = horizontalReduce(
I, 2, FirstArgShadow,
2832 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
2834 setShadow(&
I, OrShadow);
2835 setOriginForNaryOp(
I);
2838 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
2849 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
2855 Type *EltTy = VTy->getElementType();
2857 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
2858 if (ConstantInt *Elt =
2860 const APInt &
V = Elt->getValue();
2861 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
2862 Elements.push_back(ConstantInt::get(EltTy, V2));
2864 Elements.push_back(ConstantInt::get(EltTy, 1));
2870 const APInt &
V = Elt->getValue();
2871 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
2872 ShadowMul = ConstantInt::get(Ty, V2);
2874 ShadowMul = ConstantInt::get(Ty, 1);
2880 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
2881 setOrigin(&
I, getOrigin(OtherArg));
2884 void visitMul(BinaryOperator &
I) {
2887 if (constOp0 && !constOp1)
2888 handleMulByConstant(
I, constOp0,
I.getOperand(1));
2889 else if (constOp1 && !constOp0)
2890 handleMulByConstant(
I, constOp1,
I.getOperand(0));
2895 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
2896 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
2897 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
2898 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
2899 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
2900 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
2902 void handleIntegerDiv(Instruction &
I) {
2905 insertCheckShadowOf(
I.getOperand(1), &
I);
2906 setShadow(&
I, getShadow(&
I, 0));
2907 setOrigin(&
I, getOrigin(&
I, 0));
2910 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
2911 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
2912 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
2913 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
2917 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
2918 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
2924 void handleEqualityComparison(ICmpInst &
I) {
2928 Value *Sa = getShadow(
A);
2929 Value *Sb = getShadow(
B);
2955 setOriginForNaryOp(
I);
2963 void handleRelationalComparisonExact(ICmpInst &
I) {
2967 Value *Sa = getShadow(
A);
2968 Value *Sb = getShadow(
B);
2979 bool IsSigned =
I.isSigned();
2981 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
2991 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
2996 return std::make_pair(Min, Max);
2999 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3000 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3006 setOriginForNaryOp(
I);
3013 void handleSignedRelationalComparison(ICmpInst &
I) {
3018 op =
I.getOperand(0);
3019 pre =
I.getPredicate();
3021 op =
I.getOperand(1);
3022 pre =
I.getSwappedPredicate();
3035 setShadow(&
I, Shadow);
3036 setOrigin(&
I, getOrigin(
op));
3042 void visitICmpInst(ICmpInst &
I) {
3047 if (
I.isEquality()) {
3048 handleEqualityComparison(
I);
3054 handleRelationalComparisonExact(
I);
3058 handleSignedRelationalComparison(
I);
3064 handleRelationalComparisonExact(
I);
3071 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3073 void handleShift(BinaryOperator &
I) {
3078 Value *S2 = getShadow(&
I, 1);
3081 Value *V2 =
I.getOperand(1);
3083 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3084 setOriginForNaryOp(
I);
3087 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3088 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3089 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3091 void handleFunnelShift(IntrinsicInst &
I) {
3095 Value *S0 = getShadow(&
I, 0);
3097 Value *S2 = getShadow(&
I, 2);
3100 Value *V2 =
I.getOperand(2);
3103 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3104 setOriginForNaryOp(
I);
3117 void visitMemMoveInst(MemMoveInst &
I) {
3118 getShadow(
I.getArgOperand(1));
3121 {I.getArgOperand(0), I.getArgOperand(1),
3122 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3140 void visitMemCpyInst(MemCpyInst &
I) {
3141 getShadow(
I.getArgOperand(1));
3144 {I.getArgOperand(0), I.getArgOperand(1),
3145 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3150 void visitMemSetInst(MemSetInst &
I) {
3154 {I.getArgOperand(0),
3155 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3156 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3160 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3162 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3168 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3172 Value *Addr =
I.getArgOperand(0);
3173 Value *Shadow = getShadow(&
I, 1);
3174 Value *ShadowPtr, *OriginPtr;
3178 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3183 insertCheckShadowOf(Addr, &
I);
3186 if (MS.TrackOrigins)
3195 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3199 Value *Addr =
I.getArgOperand(0);
3201 Type *ShadowTy = getShadowTy(&
I);
3202 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3203 if (PropagateShadow) {
3207 std::tie(ShadowPtr, OriginPtr) =
3208 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3212 setShadow(&
I, getCleanShadow(&
I));
3216 insertCheckShadowOf(Addr, &
I);
3218 if (MS.TrackOrigins) {
3219 if (PropagateShadow)
3220 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3222 setOrigin(&
I, getCleanOrigin());
3242 [[maybe_unused]]
bool
3243 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3244 unsigned int trailingFlags) {
3245 Type *RetTy =
I.getType();
3249 unsigned NumArgOperands =
I.arg_size();
3250 assert(NumArgOperands >= trailingFlags);
3251 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3252 Type *Ty =
I.getArgOperand(i)->getType();
3258 ShadowAndOriginCombiner SC(
this, IRB);
3259 for (
unsigned i = 0; i < NumArgOperands; ++i)
3260 SC.Add(
I.getArgOperand(i));
3277 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3278 unsigned NumArgOperands =
I.arg_size();
3279 if (NumArgOperands == 0)
3282 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3283 I.getArgOperand(1)->getType()->isVectorTy() &&
3284 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3286 return handleVectorStoreIntrinsic(
I);
3289 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3290 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3292 return handleVectorLoadIntrinsic(
I);
3295 if (
I.doesNotAccessMemory())
3296 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3304 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3305 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3309 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3316 void handleInvariantGroup(IntrinsicInst &
I) {
3317 setShadow(&
I, getShadow(&
I, 0));
3318 setOrigin(&
I, getOrigin(&
I, 0));
3321 void handleLifetimeStart(IntrinsicInst &
I) {
3326 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3329 void handleBswap(IntrinsicInst &
I) {
3332 Type *OpType =
Op->getType();
3335 setOrigin(&
I, getOrigin(
Op));
3356 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3358 Value *Src =
I.getArgOperand(0);
3359 Value *SrcShadow = getShadow(Src);
3363 I.getType(),
I.getIntrinsicID(), {Src, False});
3365 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3368 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3370 Value *NotAllZeroShadow =
3372 Value *OutputShadow =
3373 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3379 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3382 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3384 setShadow(&
I, OutputShadow);
3385 setOriginForNaryOp(
I);
3395 void handleNEONVectorConvertIntrinsic(IntrinsicInst &
I) {
3399 Value *S0 = getShadow(&
I, 0);
3408 setShadow(&
I, OutShadow);
3409 setOriginForNaryOp(
I);
3418 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3438 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3443 Value *FullShadow = getCleanShadow(&
I);
3444 unsigned ShadowNumElems =
3446 unsigned FullShadowNumElems =
3449 assert((ShadowNumElems == FullShadowNumElems) ||
3450 (ShadowNumElems * 2 == FullShadowNumElems));
3452 if (ShadowNumElems == FullShadowNumElems) {
3453 FullShadow = Shadow;
3457 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3482 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3483 bool HasRoundingMode) {
3484 if (HasRoundingMode) {
3492 Value *Src =
I.getArgOperand(0);
3493 assert(Src->getType()->isVectorTy());
3497 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3500 Value *S0 = getShadow(&
I, 0);
3512 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3514 setShadow(&
I, FullShadow);
3515 setOriginForNaryOp(
I);
3536 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3537 bool HasRoundingMode =
false) {
3539 Value *CopyOp, *ConvertOp;
3541 assert((!HasRoundingMode ||
3543 "Invalid rounding mode");
3545 switch (
I.arg_size() - HasRoundingMode) {
3547 CopyOp =
I.getArgOperand(0);
3548 ConvertOp =
I.getArgOperand(1);
3551 ConvertOp =
I.getArgOperand(0);
3565 Value *ConvertShadow = getShadow(ConvertOp);
3566 Value *AggShadow =
nullptr;
3569 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3570 for (
int i = 1; i < NumUsedElements; ++i) {
3572 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3573 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3576 AggShadow = ConvertShadow;
3579 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3586 Value *ResultShadow = getShadow(CopyOp);
3588 for (
int i = 0; i < NumUsedElements; ++i) {
3590 ResultShadow, ConstantInt::getNullValue(EltTy),
3593 setShadow(&
I, ResultShadow);
3594 setOrigin(&
I, getOrigin(CopyOp));
3596 setShadow(&
I, getCleanShadow(&
I));
3597 setOrigin(&
I, getCleanOrigin());
3605 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3608 return CreateShadowCast(IRB, S2,
T,
true);
3616 return CreateShadowCast(IRB, S2,
T,
true);
3633 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3639 Value *S2 = getShadow(&
I, 1);
3640 Value *S2Conv = Variable ? VariableShadowExtend(IRB, S2)
3641 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3642 Value *V1 =
I.getOperand(0);
3643 Value *V2 =
I.getOperand(1);
3645 {IRB.CreateBitCast(S1, V1->getType()), V2});
3647 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3648 setOriginForNaryOp(
I);
3653 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3654 unsigned X86_MMXSizeInBits = 64) {
3655 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3656 "Illegal MMX vector element size");
3658 X86_MMXSizeInBits / EltSizeInBits);
3665 case Intrinsic::x86_sse2_packsswb_128:
3666 case Intrinsic::x86_sse2_packuswb_128:
3667 return Intrinsic::x86_sse2_packsswb_128;
3669 case Intrinsic::x86_sse2_packssdw_128:
3670 case Intrinsic::x86_sse41_packusdw:
3671 return Intrinsic::x86_sse2_packssdw_128;
3673 case Intrinsic::x86_avx2_packsswb:
3674 case Intrinsic::x86_avx2_packuswb:
3675 return Intrinsic::x86_avx2_packsswb;
3677 case Intrinsic::x86_avx2_packssdw:
3678 case Intrinsic::x86_avx2_packusdw:
3679 return Intrinsic::x86_avx2_packssdw;
3681 case Intrinsic::x86_mmx_packsswb:
3682 case Intrinsic::x86_mmx_packuswb:
3683 return Intrinsic::x86_mmx_packsswb;
3685 case Intrinsic::x86_mmx_packssdw:
3686 return Intrinsic::x86_mmx_packssdw;
3699 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3700 unsigned MMXEltSizeInBits = 0) {
3704 Value *S2 = getShadow(&
I, 1);
3705 assert(
S1->getType()->isVectorTy());
3711 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3712 if (MMXEltSizeInBits) {
3720 if (MMXEltSizeInBits) {
3726 {S1_ext, S2_ext},
nullptr,
3727 "_msprop_vector_pack");
3728 if (MMXEltSizeInBits)
3731 setOriginForNaryOp(
I);
3735 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3748 const unsigned Width =
3755 Value *DstMaskV = createDppMask(Width, DstMask);
3772 void handleDppIntrinsic(IntrinsicInst &
I) {
3775 Value *S0 = getShadow(&
I, 0);
3779 const unsigned Width =
3781 assert(Width == 2 || Width == 4 || Width == 8);
3784 const unsigned SrcMask =
Mask >> 4;
3785 const unsigned DstMask =
Mask & 0xf;
3788 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
3793 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
3800 setOriginForNaryOp(
I);
3804 C = CreateAppToShadowCast(IRB,
C);
3813 void handleBlendvIntrinsic(IntrinsicInst &
I) {
3818 Value *Sc = getShadow(&
I, 2);
3819 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
3824 C = convertBlendvToSelectMask(IRB,
C);
3825 Sc = convertBlendvToSelectMask(IRB, Sc);
3831 handleSelectLikeInst(
I,
C,
T,
F);
3835 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
3836 const unsigned SignificantBitsPerResultElement = 16;
3838 unsigned ZeroBitsPerResultElement =
3842 auto *Shadow0 = getShadow(&
I, 0);
3843 auto *Shadow1 = getShadow(&
I, 1);
3848 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
3851 setOriginForNaryOp(
I);
3869 void handleVectorPmaddIntrinsic(IntrinsicInst &
I,
unsigned ReductionFactor,
3870 unsigned EltSizeInBits = 0) {
3873 [[maybe_unused]] FixedVectorType *
ReturnType =
3878 Value *Va =
nullptr;
3879 Value *Vb =
nullptr;
3880 Value *Sa =
nullptr;
3881 Value *Sb =
nullptr;
3883 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
3884 if (
I.arg_size() == 2) {
3885 Va =
I.getOperand(0);
3886 Vb =
I.getOperand(1);
3888 Sa = getShadow(&
I, 0);
3889 Sb = getShadow(&
I, 1);
3890 }
else if (
I.arg_size() == 3) {
3892 Va =
I.getOperand(1);
3893 Vb =
I.getOperand(2);
3895 Sa = getShadow(&
I, 1);
3896 Sb = getShadow(&
I, 2);
3905 if (
I.arg_size() == 3) {
3906 [[maybe_unused]]
auto *AccumulatorType =
3908 assert(AccumulatorType == ReturnType);
3911 FixedVectorType *ImplicitReturnType =
ReturnType;
3913 if (EltSizeInBits) {
3915 getMMXVectorTy(EltSizeInBits * ReductionFactor,
3927 ReturnType->getNumElements() * ReductionFactor);
3953 Value *
And = IRB.
CreateOr({SaAndSbNonZero, VaAndSbNonZero, SaAndVbNonZero});
3972 ImplicitReturnType);
3977 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
3980 if (
I.arg_size() == 3)
3981 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
3983 setShadow(&
I, OutShadow);
3984 setOriginForNaryOp(
I);
3990 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I) {
3992 Type *ResTy = getShadowTy(&
I);
3993 auto *Shadow0 = getShadow(&
I, 0);
3994 auto *Shadow1 = getShadow(&
I, 1);
3999 setOriginForNaryOp(
I);
4005 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4007 auto *Shadow0 = getShadow(&
I, 0);
4008 auto *Shadow1 = getShadow(&
I, 1);
4010 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4012 setOriginForNaryOp(
I);
4021 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4026 if (AllowShadowCast)
4027 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4031 setOriginForNaryOp(
I);
4041 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4045 Value *Shadow0 = getShadow(&
I, 0);
4051 setOriginForNaryOp(
I);
4057 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4061 Value *OperandShadow = getShadow(&
I, 0);
4063 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4071 setOrigin(&
I, getOrigin(&
I, 0));
4077 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4081 Value *OperandShadow = getShadow(&
I, 0);
4082 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4090 setOrigin(&
I, getOrigin(&
I, 0));
4093 void handleStmxcsr(IntrinsicInst &
I) {
4095 Value *Addr =
I.getArgOperand(0);
4098 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4103 insertCheckShadowOf(Addr, &
I);
4106 void handleLdmxcsr(IntrinsicInst &
I) {
4111 Value *Addr =
I.getArgOperand(0);
4114 Value *ShadowPtr, *OriginPtr;
4115 std::tie(ShadowPtr, OriginPtr) =
4116 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4119 insertCheckShadowOf(Addr, &
I);
4122 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4124 insertCheckShadow(Shadow, Origin, &
I);
4127 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4130 MaybeAlign
Align =
I.getParamAlign(0);
4132 Value *PassThru =
I.getArgOperand(2);
4135 insertCheckShadowOf(
Ptr, &
I);
4136 insertCheckShadowOf(Mask, &
I);
4139 if (!PropagateShadow) {
4140 setShadow(&
I, getCleanShadow(&
I));
4141 setOrigin(&
I, getCleanOrigin());
4145 Type *ShadowTy = getShadowTy(&
I);
4147 auto [ShadowPtr, OriginPtr] =
4148 getShadowOriginPtr(
Ptr, IRB, ElementShadowTy, Align,
false);
4152 getShadow(PassThru),
"_msmaskedexpload");
4154 setShadow(&
I, Shadow);
4157 setOrigin(&
I, getCleanOrigin());
4160 void handleMaskedCompressStore(IntrinsicInst &
I) {
4162 Value *Values =
I.getArgOperand(0);
4164 MaybeAlign
Align =
I.getParamAlign(1);
4168 insertCheckShadowOf(
Ptr, &
I);
4169 insertCheckShadowOf(Mask, &
I);
4172 Value *Shadow = getShadow(Values);
4173 Type *ElementShadowTy =
4175 auto [ShadowPtr, OriginPtrs] =
4176 getShadowOriginPtr(
Ptr, IRB, ElementShadowTy, Align,
true);
4183 void handleMaskedGather(IntrinsicInst &
I) {
4185 Value *Ptrs =
I.getArgOperand(0);
4186 const Align Alignment(
4189 Value *PassThru =
I.getArgOperand(3);
4191 Type *PtrsShadowTy = getShadowTy(Ptrs);
4193 insertCheckShadowOf(Mask, &
I);
4197 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4200 if (!PropagateShadow) {
4201 setShadow(&
I, getCleanShadow(&
I));
4202 setOrigin(&
I, getCleanOrigin());
4206 Type *ShadowTy = getShadowTy(&
I);
4208 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4209 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4213 getShadow(PassThru),
"_msmaskedgather");
4215 setShadow(&
I, Shadow);
4218 setOrigin(&
I, getCleanOrigin());
4221 void handleMaskedScatter(IntrinsicInst &
I) {
4223 Value *Values =
I.getArgOperand(0);
4224 Value *Ptrs =
I.getArgOperand(1);
4225 const Align Alignment(
4229 Type *PtrsShadowTy = getShadowTy(Ptrs);
4231 insertCheckShadowOf(Mask, &
I);
4235 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4238 Value *Shadow = getShadow(Values);
4239 Type *ElementShadowTy =
4241 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4242 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4253 void handleMaskedStore(IntrinsicInst &
I) {
4255 Value *
V =
I.getArgOperand(0);
4257 const Align Alignment(
4260 Value *Shadow = getShadow(V);
4263 insertCheckShadowOf(
Ptr, &
I);
4264 insertCheckShadowOf(Mask, &
I);
4269 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4270 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4274 if (!MS.TrackOrigins)
4277 auto &
DL =
F.getDataLayout();
4278 paintOrigin(IRB, getOrigin(V), OriginPtr,
4287 void handleMaskedLoad(IntrinsicInst &
I) {
4290 const Align Alignment(
4293 Value *PassThru =
I.getArgOperand(3);
4296 insertCheckShadowOf(
Ptr, &
I);
4297 insertCheckShadowOf(Mask, &
I);
4300 if (!PropagateShadow) {
4301 setShadow(&
I, getCleanShadow(&
I));
4302 setOrigin(&
I, getCleanOrigin());
4306 Type *ShadowTy = getShadowTy(&
I);
4307 Value *ShadowPtr, *OriginPtr;
4308 std::tie(ShadowPtr, OriginPtr) =
4309 getShadowOriginPtr(
Ptr, IRB, ShadowTy, Alignment,
false);
4311 getShadow(PassThru),
"_msmaskedld"));
4313 if (!MS.TrackOrigins)
4320 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4325 setOrigin(&
I, Origin);
4341 void handleAVXMaskedStore(IntrinsicInst &
I) {
4346 Value *Dst =
I.getArgOperand(0);
4347 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4352 Value *Src =
I.getArgOperand(2);
4357 Value *SrcShadow = getShadow(Src);
4360 insertCheckShadowOf(Dst, &
I);
4361 insertCheckShadowOf(Mask, &
I);
4364 Value *DstShadowPtr;
4365 Value *DstOriginPtr;
4366 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4367 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4369 SmallVector<Value *, 2> ShadowArgs;
4370 ShadowArgs.
append(1, DstShadowPtr);
4371 ShadowArgs.
append(1, Mask);
4382 if (!MS.TrackOrigins)
4386 auto &
DL =
F.getDataLayout();
4387 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4388 DL.getTypeStoreSize(SrcShadow->
getType()),
4407 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4412 Value *Src =
I.getArgOperand(0);
4413 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4421 insertCheckShadowOf(Mask, &
I);
4424 Type *SrcShadowTy = getShadowTy(Src);
4425 Value *SrcShadowPtr, *SrcOriginPtr;
4426 std::tie(SrcShadowPtr, SrcOriginPtr) =
4427 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4429 SmallVector<Value *, 2> ShadowArgs;
4430 ShadowArgs.
append(1, SrcShadowPtr);
4431 ShadowArgs.
append(1, Mask);
4440 if (!MS.TrackOrigins)
4447 setOrigin(&
I, PtrSrcOrigin);
4456 assert(isFixedIntVector(Idx));
4457 auto IdxVectorSize =
4465 auto *IdxShadow = getShadow(Idx);
4470 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4475 void handleAVXVpermilvar(IntrinsicInst &
I) {
4477 Value *Shadow = getShadow(&
I, 0);
4478 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4482 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4484 {Shadow, I.getArgOperand(1)});
4487 setOriginForNaryOp(
I);
4492 void handleAVXVpermi2var(IntrinsicInst &
I) {
4497 [[maybe_unused]]
auto ArgVectorSize =
4500 ->getNumElements() == ArgVectorSize);
4502 ->getNumElements() == ArgVectorSize);
4503 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4504 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4505 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4507 Value *AShadow = getShadow(&
I, 0);
4508 Value *Idx =
I.getArgOperand(1);
4509 Value *BShadow = getShadow(&
I, 2);
4511 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4515 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4516 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4518 {AShadow, Idx, BShadow});
4520 setOriginForNaryOp(
I);
4523 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4527 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4531 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4532 return isFixedIntVectorTy(
V->getType());
4535 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4536 return isFixedFPVectorTy(
V->getType());
4558 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4563 Value *WriteThrough;
4567 WriteThrough =
I.getOperand(2);
4568 Mask =
I.getOperand(3);
4571 WriteThrough =
I.getOperand(1);
4572 Mask =
I.getOperand(2);
4577 assert(isFixedIntVector(WriteThrough));
4579 unsigned ANumElements =
4581 [[maybe_unused]]
unsigned WriteThruNumElements =
4583 assert(ANumElements == WriteThruNumElements ||
4584 ANumElements * 2 == WriteThruNumElements);
4587 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4588 assert(ANumElements == MaskNumElements ||
4589 ANumElements * 2 == MaskNumElements);
4591 assert(WriteThruNumElements == MaskNumElements);
4595 insertCheckShadowOf(Mask, &
I);
4605 Value *AShadow = getShadow(
A);
4606 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4608 if (ANumElements * 2 == MaskNumElements) {
4620 "_ms_mask_bitcast");
4630 getShadowTy(&
I),
"_ms_a_shadow");
4632 Value *WriteThroughShadow = getShadow(WriteThrough);
4634 "_ms_writethru_select");
4636 setShadow(&
I, Shadow);
4637 setOriginForNaryOp(
I);
4645 void handleBmiIntrinsic(IntrinsicInst &
I) {
4647 Type *ShadowTy = getShadowTy(&
I);
4650 Value *SMask = getShadow(&
I, 1);
4655 {getShadow(&I, 0), I.getOperand(1)});
4658 setOriginForNaryOp(
I);
4661 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4662 SmallVector<int, 8>
Mask;
4663 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4677 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4682 "pclmul 3rd operand must be a constant");
4685 getPclmulMask(Width, Imm & 0x01));
4687 getPclmulMask(Width, Imm & 0x10));
4688 ShadowAndOriginCombiner SOC(
this, IRB);
4689 SOC.Add(Shuf0, getOrigin(&
I, 0));
4690 SOC.Add(Shuf1, getOrigin(&
I, 1));
4695 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4700 Value *Second = getShadow(&
I, 1);
4702 SmallVector<int, 16>
Mask;
4703 Mask.push_back(Width);
4704 for (
unsigned i = 1; i < Width; i++)
4708 setShadow(&
I, Shadow);
4709 setOriginForNaryOp(
I);
4712 void handleVtestIntrinsic(IntrinsicInst &
I) {
4714 Value *Shadow0 = getShadow(&
I, 0);
4715 Value *Shadow1 = getShadow(&
I, 1);
4721 setShadow(&
I, Shadow);
4722 setOriginForNaryOp(
I);
4725 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
4730 Value *Second = getShadow(&
I, 1);
4733 SmallVector<int, 16>
Mask;
4734 Mask.push_back(Width);
4735 for (
unsigned i = 1; i < Width; i++)
4739 setShadow(&
I, Shadow);
4740 setOriginForNaryOp(
I);
4746 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
4747 assert(
I.getArgOperand(0)->getType() ==
I.getType());
4752 ShadowAndOriginCombiner SC(
this, IRB);
4753 SC.Add(
I.getArgOperand(0));
4761 void handleAbsIntrinsic(IntrinsicInst &
I) {
4763 Value *Src =
I.getArgOperand(0);
4764 Value *IsIntMinPoison =
I.getArgOperand(1);
4766 assert(
I.getType()->isIntOrIntVectorTy());
4768 assert(Src->getType() ==
I.getType());
4774 Value *SrcShadow = getShadow(Src);
4778 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
4781 Value *PoisonedShadow = getPoisonedShadow(Src);
4782 Value *PoisonedIfIntMinShadow =
4785 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
4787 setShadow(&
I, Shadow);
4788 setOrigin(&
I, getOrigin(&
I, 0));
4791 void handleIsFpClass(IntrinsicInst &
I) {
4793 Value *Shadow = getShadow(&
I, 0);
4794 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
4795 setOrigin(&
I, getOrigin(&
I, 0));
4798 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
4800 Value *Shadow0 = getShadow(&
I, 0);
4801 Value *Shadow1 = getShadow(&
I, 1);
4804 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
4810 setShadow(&
I, Shadow);
4811 setOriginForNaryOp(
I);
4817 Value *Shadow = getShadow(V);
4839 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
4844 Value *WriteThrough =
I.getOperand(1);
4848 assert(isFixedIntVector(WriteThrough));
4850 unsigned ANumElements =
4852 unsigned OutputNumElements =
4854 assert(ANumElements == OutputNumElements ||
4855 ANumElements * 2 == OutputNumElements);
4858 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
4859 insertCheckShadowOf(Mask, &
I);
4870 if (ANumElements != OutputNumElements) {
4872 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
4879 Value *AShadow = getShadow(
A);
4883 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
4893 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
4894 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4896 Value *WriteThroughShadow = getShadow(WriteThrough);
4899 setShadow(&
I, Shadow);
4900 setOriginForNaryOp(
I);
4910 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
4916 Value *WriteThrough =
I.getOperand(2);
4923 insertCheckShadowOf(Mask, &
I);
4927 unsigned NumElements =
4929 assert(NumElements == 8);
4930 assert(
A->getType() ==
B->getType());
4932 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
4935 Value *ALowerShadow = extractLowerShadow(IRB,
A);
4936 Value *BLowerShadow = extractLowerShadow(IRB,
B);
4938 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
4940 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
4947 Value *AShadow = getShadow(
A);
4948 Value *DstLowerShadow =
4949 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
4951 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
4954 setShadow(&
I, DstShadow);
4955 setOriginForNaryOp(
I);
4985 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
4996 ->getScalarSizeInBits() == 8);
4998 assert(
A->getType() ==
X->getType());
5000 assert(
B->getType()->isIntegerTy());
5001 assert(
B->getType()->getScalarSizeInBits() == 8);
5003 assert(
I.getType() ==
A->getType());
5005 Value *AShadow = getShadow(
A);
5006 Value *XShadow = getShadow(
X);
5007 Value *BZeroShadow = getCleanShadow(
B);
5010 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5012 {X, AShadow, BZeroShadow});
5014 {XShadow, A, BZeroShadow});
5017 Value *BShadow = getShadow(
B);
5018 Value *BBroadcastShadow = getCleanShadow(AShadow);
5023 for (
unsigned i = 0; i < NumElements; i++)
5027 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5028 setOriginForNaryOp(
I);
5042 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5043 unsigned int numArgs =
I.arg_size();
5046 assert(
I.getType()->isStructTy());
5056 assert(4 <= numArgs && numArgs <= 6);
5070 for (
unsigned int i = 0; i < numArgs - 2; i++)
5071 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5074 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5078 insertCheckShadowOf(LaneNumber, &
I);
5081 Value *Src =
I.getArgOperand(numArgs - 1);
5082 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5084 Type *SrcShadowTy = getShadowTy(Src);
5085 auto [SrcShadowPtr, SrcOriginPtr] =
5086 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5096 if (!MS.TrackOrigins)
5100 setOrigin(&
I, PtrSrcOrigin);
5117 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5121 int numArgOperands =
I.arg_size();
5124 assert(numArgOperands >= 1);
5125 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5127 int skipTrailingOperands = 1;
5130 insertCheckShadowOf(Addr, &
I);
5134 skipTrailingOperands++;
5135 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5137 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5140 SmallVector<Value *, 8> ShadowArgs;
5142 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5144 Value *Shadow = getShadow(&
I, i);
5145 ShadowArgs.
append(1, Shadow);
5162 (numArgOperands - skipTrailingOperands));
5163 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5167 I.getArgOperand(numArgOperands - skipTrailingOperands));
5169 Value *OutputShadowPtr, *OutputOriginPtr;
5171 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5172 Addr, IRB, OutputShadowTy,
Align(1),
true);
5173 ShadowArgs.
append(1, OutputShadowPtr);
5179 if (MS.TrackOrigins) {
5187 OriginCombiner
OC(
this, IRB);
5188 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5189 OC.Add(
I.getArgOperand(i));
5191 const DataLayout &
DL =
F.getDataLayout();
5192 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5219 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5221 unsigned int trailingVerbatimArgs) {
5224 assert(trailingVerbatimArgs <
I.arg_size());
5226 SmallVector<Value *, 8> ShadowArgs;
5228 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5229 Value *Shadow = getShadow(&
I, i);
5237 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5239 Value *Arg =
I.getArgOperand(i);
5245 Value *CombinedShadow = CI;
5248 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5251 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5252 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5257 setOriginForNaryOp(
I);
5263 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5269 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5270 switch (
I.getIntrinsicID()) {
5271 case Intrinsic::uadd_with_overflow:
5272 case Intrinsic::sadd_with_overflow:
5273 case Intrinsic::usub_with_overflow:
5274 case Intrinsic::ssub_with_overflow:
5275 case Intrinsic::umul_with_overflow:
5276 case Intrinsic::smul_with_overflow:
5277 handleArithmeticWithOverflow(
I);
5279 case Intrinsic::abs:
5280 handleAbsIntrinsic(
I);
5282 case Intrinsic::bitreverse:
5283 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5286 case Intrinsic::is_fpclass:
5289 case Intrinsic::lifetime_start:
5290 handleLifetimeStart(
I);
5292 case Intrinsic::launder_invariant_group:
5293 case Intrinsic::strip_invariant_group:
5294 handleInvariantGroup(
I);
5296 case Intrinsic::bswap:
5299 case Intrinsic::ctlz:
5300 case Intrinsic::cttz:
5301 handleCountLeadingTrailingZeros(
I);
5303 case Intrinsic::masked_compressstore:
5304 handleMaskedCompressStore(
I);
5306 case Intrinsic::masked_expandload:
5307 handleMaskedExpandLoad(
I);
5309 case Intrinsic::masked_gather:
5310 handleMaskedGather(
I);
5312 case Intrinsic::masked_scatter:
5313 handleMaskedScatter(
I);
5315 case Intrinsic::masked_store:
5316 handleMaskedStore(
I);
5318 case Intrinsic::masked_load:
5319 handleMaskedLoad(
I);
5321 case Intrinsic::vector_reduce_and:
5322 handleVectorReduceAndIntrinsic(
I);
5324 case Intrinsic::vector_reduce_or:
5325 handleVectorReduceOrIntrinsic(
I);
5328 case Intrinsic::vector_reduce_add:
5329 case Intrinsic::vector_reduce_xor:
5330 case Intrinsic::vector_reduce_mul:
5333 case Intrinsic::vector_reduce_smax:
5334 case Intrinsic::vector_reduce_smin:
5335 case Intrinsic::vector_reduce_umax:
5336 case Intrinsic::vector_reduce_umin:
5339 case Intrinsic::vector_reduce_fmax:
5340 case Intrinsic::vector_reduce_fmin:
5341 handleVectorReduceIntrinsic(
I,
false);
5344 case Intrinsic::vector_reduce_fadd:
5345 case Intrinsic::vector_reduce_fmul:
5346 handleVectorReduceWithStarterIntrinsic(
I);
5349 case Intrinsic::scmp:
5350 case Intrinsic::ucmp: {
5355 case Intrinsic::fshl:
5356 case Intrinsic::fshr:
5357 handleFunnelShift(
I);
5360 case Intrinsic::is_constant:
5362 setShadow(&
I, getCleanShadow(&
I));
5363 setOrigin(&
I, getCleanOrigin());
5373 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
5374 switch (
I.getIntrinsicID()) {
5375 case Intrinsic::x86_sse_stmxcsr:
5378 case Intrinsic::x86_sse_ldmxcsr:
5385 case Intrinsic::x86_avx512_vcvtsd2usi64:
5386 case Intrinsic::x86_avx512_vcvtsd2usi32:
5387 case Intrinsic::x86_avx512_vcvtss2usi64:
5388 case Intrinsic::x86_avx512_vcvtss2usi32:
5389 case Intrinsic::x86_avx512_cvttss2usi64:
5390 case Intrinsic::x86_avx512_cvttss2usi:
5391 case Intrinsic::x86_avx512_cvttsd2usi64:
5392 case Intrinsic::x86_avx512_cvttsd2usi:
5393 case Intrinsic::x86_avx512_cvtusi2ss:
5394 case Intrinsic::x86_avx512_cvtusi642sd:
5395 case Intrinsic::x86_avx512_cvtusi642ss:
5396 handleSSEVectorConvertIntrinsic(
I, 1,
true);
5398 case Intrinsic::x86_sse2_cvtsd2si64:
5399 case Intrinsic::x86_sse2_cvtsd2si:
5400 case Intrinsic::x86_sse2_cvtsd2ss:
5401 case Intrinsic::x86_sse2_cvttsd2si64:
5402 case Intrinsic::x86_sse2_cvttsd2si:
5403 case Intrinsic::x86_sse_cvtss2si64:
5404 case Intrinsic::x86_sse_cvtss2si:
5405 case Intrinsic::x86_sse_cvttss2si64:
5406 case Intrinsic::x86_sse_cvttss2si:
5407 handleSSEVectorConvertIntrinsic(
I, 1);
5409 case Intrinsic::x86_sse_cvtps2pi:
5410 case Intrinsic::x86_sse_cvttps2pi:
5411 handleSSEVectorConvertIntrinsic(
I, 2);
5419 case Intrinsic::x86_vcvtps2ph_128:
5420 case Intrinsic::x86_vcvtps2ph_256: {
5421 handleSSEVectorConvertIntrinsicByProp(
I,
true);
5430 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
5431 handleAVX512VectorConvertFPToInt(
I,
false);
5436 case Intrinsic::x86_sse2_cvtpd2ps:
5437 case Intrinsic::x86_sse2_cvtps2dq:
5438 case Intrinsic::x86_sse2_cvtpd2dq:
5439 case Intrinsic::x86_sse2_cvttps2dq:
5440 case Intrinsic::x86_sse2_cvttpd2dq:
5441 case Intrinsic::x86_avx_cvt_pd2_ps_256:
5442 case Intrinsic::x86_avx_cvt_ps2dq_256:
5443 case Intrinsic::x86_avx_cvt_pd2dq_256:
5444 case Intrinsic::x86_avx_cvtt_ps2dq_256:
5445 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
5446 handleSSEVectorConvertIntrinsicByProp(
I,
false);
5457 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
5458 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
5459 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
5460 handleAVX512VectorConvertFPToInt(
I,
true);
5464 case Intrinsic::x86_avx512_psll_w_512:
5465 case Intrinsic::x86_avx512_psll_d_512:
5466 case Intrinsic::x86_avx512_psll_q_512:
5467 case Intrinsic::x86_avx512_pslli_w_512:
5468 case Intrinsic::x86_avx512_pslli_d_512:
5469 case Intrinsic::x86_avx512_pslli_q_512:
5470 case Intrinsic::x86_avx512_psrl_w_512:
5471 case Intrinsic::x86_avx512_psrl_d_512:
5472 case Intrinsic::x86_avx512_psrl_q_512:
5473 case Intrinsic::x86_avx512_psra_w_512:
5474 case Intrinsic::x86_avx512_psra_d_512:
5475 case Intrinsic::x86_avx512_psra_q_512:
5476 case Intrinsic::x86_avx512_psrli_w_512:
5477 case Intrinsic::x86_avx512_psrli_d_512:
5478 case Intrinsic::x86_avx512_psrli_q_512:
5479 case Intrinsic::x86_avx512_psrai_w_512:
5480 case Intrinsic::x86_avx512_psrai_d_512:
5481 case Intrinsic::x86_avx512_psrai_q_512:
5482 case Intrinsic::x86_avx512_psra_q_256:
5483 case Intrinsic::x86_avx512_psra_q_128:
5484 case Intrinsic::x86_avx512_psrai_q_256:
5485 case Intrinsic::x86_avx512_psrai_q_128:
5486 case Intrinsic::x86_avx2_psll_w:
5487 case Intrinsic::x86_avx2_psll_d:
5488 case Intrinsic::x86_avx2_psll_q:
5489 case Intrinsic::x86_avx2_pslli_w:
5490 case Intrinsic::x86_avx2_pslli_d:
5491 case Intrinsic::x86_avx2_pslli_q:
5492 case Intrinsic::x86_avx2_psrl_w:
5493 case Intrinsic::x86_avx2_psrl_d:
5494 case Intrinsic::x86_avx2_psrl_q:
5495 case Intrinsic::x86_avx2_psra_w:
5496 case Intrinsic::x86_avx2_psra_d:
5497 case Intrinsic::x86_avx2_psrli_w:
5498 case Intrinsic::x86_avx2_psrli_d:
5499 case Intrinsic::x86_avx2_psrli_q:
5500 case Intrinsic::x86_avx2_psrai_w:
5501 case Intrinsic::x86_avx2_psrai_d:
5502 case Intrinsic::x86_sse2_psll_w:
5503 case Intrinsic::x86_sse2_psll_d:
5504 case Intrinsic::x86_sse2_psll_q:
5505 case Intrinsic::x86_sse2_pslli_w:
5506 case Intrinsic::x86_sse2_pslli_d:
5507 case Intrinsic::x86_sse2_pslli_q:
5508 case Intrinsic::x86_sse2_psrl_w:
5509 case Intrinsic::x86_sse2_psrl_d:
5510 case Intrinsic::x86_sse2_psrl_q:
5511 case Intrinsic::x86_sse2_psra_w:
5512 case Intrinsic::x86_sse2_psra_d:
5513 case Intrinsic::x86_sse2_psrli_w:
5514 case Intrinsic::x86_sse2_psrli_d:
5515 case Intrinsic::x86_sse2_psrli_q:
5516 case Intrinsic::x86_sse2_psrai_w:
5517 case Intrinsic::x86_sse2_psrai_d:
5518 case Intrinsic::x86_mmx_psll_w:
5519 case Intrinsic::x86_mmx_psll_d:
5520 case Intrinsic::x86_mmx_psll_q:
5521 case Intrinsic::x86_mmx_pslli_w:
5522 case Intrinsic::x86_mmx_pslli_d:
5523 case Intrinsic::x86_mmx_pslli_q:
5524 case Intrinsic::x86_mmx_psrl_w:
5525 case Intrinsic::x86_mmx_psrl_d:
5526 case Intrinsic::x86_mmx_psrl_q:
5527 case Intrinsic::x86_mmx_psra_w:
5528 case Intrinsic::x86_mmx_psra_d:
5529 case Intrinsic::x86_mmx_psrli_w:
5530 case Intrinsic::x86_mmx_psrli_d:
5531 case Intrinsic::x86_mmx_psrli_q:
5532 case Intrinsic::x86_mmx_psrai_w:
5533 case Intrinsic::x86_mmx_psrai_d:
5534 handleVectorShiftIntrinsic(
I,
false);
5536 case Intrinsic::x86_avx2_psllv_d:
5537 case Intrinsic::x86_avx2_psllv_d_256:
5538 case Intrinsic::x86_avx512_psllv_d_512:
5539 case Intrinsic::x86_avx2_psllv_q:
5540 case Intrinsic::x86_avx2_psllv_q_256:
5541 case Intrinsic::x86_avx512_psllv_q_512:
5542 case Intrinsic::x86_avx2_psrlv_d:
5543 case Intrinsic::x86_avx2_psrlv_d_256:
5544 case Intrinsic::x86_avx512_psrlv_d_512:
5545 case Intrinsic::x86_avx2_psrlv_q:
5546 case Intrinsic::x86_avx2_psrlv_q_256:
5547 case Intrinsic::x86_avx512_psrlv_q_512:
5548 case Intrinsic::x86_avx2_psrav_d:
5549 case Intrinsic::x86_avx2_psrav_d_256:
5550 case Intrinsic::x86_avx512_psrav_d_512:
5551 case Intrinsic::x86_avx512_psrav_q_128:
5552 case Intrinsic::x86_avx512_psrav_q_256:
5553 case Intrinsic::x86_avx512_psrav_q_512:
5554 handleVectorShiftIntrinsic(
I,
true);
5557 case Intrinsic::x86_sse2_packsswb_128:
5558 case Intrinsic::x86_sse2_packssdw_128:
5559 case Intrinsic::x86_sse2_packuswb_128:
5560 case Intrinsic::x86_sse41_packusdw:
5561 case Intrinsic::x86_avx2_packsswb:
5562 case Intrinsic::x86_avx2_packssdw:
5563 case Intrinsic::x86_avx2_packuswb:
5564 case Intrinsic::x86_avx2_packusdw:
5565 handleVectorPackIntrinsic(
I);
5568 case Intrinsic::x86_sse41_pblendvb:
5569 case Intrinsic::x86_sse41_blendvpd:
5570 case Intrinsic::x86_sse41_blendvps:
5571 case Intrinsic::x86_avx_blendv_pd_256:
5572 case Intrinsic::x86_avx_blendv_ps_256:
5573 case Intrinsic::x86_avx2_pblendvb:
5574 handleBlendvIntrinsic(
I);
5577 case Intrinsic::x86_avx_dp_ps_256:
5578 case Intrinsic::x86_sse41_dppd:
5579 case Intrinsic::x86_sse41_dpps:
5580 handleDppIntrinsic(
I);
5583 case Intrinsic::x86_mmx_packsswb:
5584 case Intrinsic::x86_mmx_packuswb:
5585 handleVectorPackIntrinsic(
I, 16);
5588 case Intrinsic::x86_mmx_packssdw:
5589 handleVectorPackIntrinsic(
I, 32);
5592 case Intrinsic::x86_mmx_psad_bw:
5593 handleVectorSadIntrinsic(
I,
true);
5595 case Intrinsic::x86_sse2_psad_bw:
5596 case Intrinsic::x86_avx2_psad_bw:
5597 handleVectorSadIntrinsic(
I);
5623 case Intrinsic::x86_sse2_pmadd_wd:
5624 case Intrinsic::x86_avx2_pmadd_wd:
5625 case Intrinsic::x86_avx512_pmaddw_d_512:
5626 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
5627 case Intrinsic::x86_avx2_pmadd_ub_sw:
5628 case Intrinsic::x86_avx512_pmaddubs_w_512:
5629 handleVectorPmaddIntrinsic(
I, 2);
5633 case Intrinsic::x86_ssse3_pmadd_ub_sw:
5634 handleVectorPmaddIntrinsic(
I, 2, 8);
5638 case Intrinsic::x86_mmx_pmadd_wd:
5639 handleVectorPmaddIntrinsic(
I, 2, 16);
5701 case Intrinsic::x86_avx512_vpdpbusd_128:
5702 case Intrinsic::x86_avx512_vpdpbusd_256:
5703 case Intrinsic::x86_avx512_vpdpbusd_512:
5704 case Intrinsic::x86_avx512_vpdpbusds_128:
5705 case Intrinsic::x86_avx512_vpdpbusds_256:
5706 case Intrinsic::x86_avx512_vpdpbusds_512:
5707 case Intrinsic::x86_avx2_vpdpbssd_128:
5708 case Intrinsic::x86_avx2_vpdpbssd_256:
5709 case Intrinsic::x86_avx2_vpdpbssds_128:
5710 case Intrinsic::x86_avx2_vpdpbssds_256:
5711 case Intrinsic::x86_avx10_vpdpbssd_512:
5712 case Intrinsic::x86_avx10_vpdpbssds_512:
5713 handleVectorPmaddIntrinsic(
I, 4, 8);
5760 case Intrinsic::x86_avx512_vpdpwssd_128:
5761 case Intrinsic::x86_avx512_vpdpwssd_256:
5762 case Intrinsic::x86_avx512_vpdpwssd_512:
5763 case Intrinsic::x86_avx512_vpdpwssds_128:
5764 case Intrinsic::x86_avx512_vpdpwssds_256:
5765 case Intrinsic::x86_avx512_vpdpwssds_512:
5766 handleVectorPmaddIntrinsic(
I, 2, 16);
5779 case Intrinsic::x86_sse_cmp_ss:
5780 case Intrinsic::x86_sse2_cmp_sd:
5781 case Intrinsic::x86_sse_comieq_ss:
5782 case Intrinsic::x86_sse_comilt_ss:
5783 case Intrinsic::x86_sse_comile_ss:
5784 case Intrinsic::x86_sse_comigt_ss:
5785 case Intrinsic::x86_sse_comige_ss:
5786 case Intrinsic::x86_sse_comineq_ss:
5787 case Intrinsic::x86_sse_ucomieq_ss:
5788 case Intrinsic::x86_sse_ucomilt_ss:
5789 case Intrinsic::x86_sse_ucomile_ss:
5790 case Intrinsic::x86_sse_ucomigt_ss:
5791 case Intrinsic::x86_sse_ucomige_ss:
5792 case Intrinsic::x86_sse_ucomineq_ss:
5793 case Intrinsic::x86_sse2_comieq_sd:
5794 case Intrinsic::x86_sse2_comilt_sd:
5795 case Intrinsic::x86_sse2_comile_sd:
5796 case Intrinsic::x86_sse2_comigt_sd:
5797 case Intrinsic::x86_sse2_comige_sd:
5798 case Intrinsic::x86_sse2_comineq_sd:
5799 case Intrinsic::x86_sse2_ucomieq_sd:
5800 case Intrinsic::x86_sse2_ucomilt_sd:
5801 case Intrinsic::x86_sse2_ucomile_sd:
5802 case Intrinsic::x86_sse2_ucomigt_sd:
5803 case Intrinsic::x86_sse2_ucomige_sd:
5804 case Intrinsic::x86_sse2_ucomineq_sd:
5805 handleVectorCompareScalarIntrinsic(
I);
5808 case Intrinsic::x86_avx_cmp_pd_256:
5809 case Intrinsic::x86_avx_cmp_ps_256:
5810 case Intrinsic::x86_sse2_cmp_pd:
5811 case Intrinsic::x86_sse_cmp_ps:
5812 handleVectorComparePackedIntrinsic(
I);
5815 case Intrinsic::x86_bmi_bextr_32:
5816 case Intrinsic::x86_bmi_bextr_64:
5817 case Intrinsic::x86_bmi_bzhi_32:
5818 case Intrinsic::x86_bmi_bzhi_64:
5819 case Intrinsic::x86_bmi_pdep_32:
5820 case Intrinsic::x86_bmi_pdep_64:
5821 case Intrinsic::x86_bmi_pext_32:
5822 case Intrinsic::x86_bmi_pext_64:
5823 handleBmiIntrinsic(
I);
5826 case Intrinsic::x86_pclmulqdq:
5827 case Intrinsic::x86_pclmulqdq_256:
5828 case Intrinsic::x86_pclmulqdq_512:
5829 handlePclmulIntrinsic(
I);
5832 case Intrinsic::x86_avx_round_pd_256:
5833 case Intrinsic::x86_avx_round_ps_256:
5834 case Intrinsic::x86_sse41_round_pd:
5835 case Intrinsic::x86_sse41_round_ps:
5836 handleRoundPdPsIntrinsic(
I);
5839 case Intrinsic::x86_sse41_round_sd:
5840 case Intrinsic::x86_sse41_round_ss:
5841 handleUnarySdSsIntrinsic(
I);
5844 case Intrinsic::x86_sse2_max_sd:
5845 case Intrinsic::x86_sse_max_ss:
5846 case Intrinsic::x86_sse2_min_sd:
5847 case Intrinsic::x86_sse_min_ss:
5848 handleBinarySdSsIntrinsic(
I);
5851 case Intrinsic::x86_avx_vtestc_pd:
5852 case Intrinsic::x86_avx_vtestc_pd_256:
5853 case Intrinsic::x86_avx_vtestc_ps:
5854 case Intrinsic::x86_avx_vtestc_ps_256:
5855 case Intrinsic::x86_avx_vtestnzc_pd:
5856 case Intrinsic::x86_avx_vtestnzc_pd_256:
5857 case Intrinsic::x86_avx_vtestnzc_ps:
5858 case Intrinsic::x86_avx_vtestnzc_ps_256:
5859 case Intrinsic::x86_avx_vtestz_pd:
5860 case Intrinsic::x86_avx_vtestz_pd_256:
5861 case Intrinsic::x86_avx_vtestz_ps:
5862 case Intrinsic::x86_avx_vtestz_ps_256:
5863 case Intrinsic::x86_avx_ptestc_256:
5864 case Intrinsic::x86_avx_ptestnzc_256:
5865 case Intrinsic::x86_avx_ptestz_256:
5866 case Intrinsic::x86_sse41_ptestc:
5867 case Intrinsic::x86_sse41_ptestnzc:
5868 case Intrinsic::x86_sse41_ptestz:
5869 handleVtestIntrinsic(
I);
5873 case Intrinsic::x86_ssse3_phadd_w:
5874 case Intrinsic::x86_ssse3_phadd_w_128:
5875 case Intrinsic::x86_avx2_phadd_w:
5876 case Intrinsic::x86_ssse3_phsub_w:
5877 case Intrinsic::x86_ssse3_phsub_w_128:
5878 case Intrinsic::x86_avx2_phsub_w: {
5879 handlePairwiseShadowOrIntrinsic(
I, 16);
5884 case Intrinsic::x86_ssse3_phadd_d:
5885 case Intrinsic::x86_ssse3_phadd_d_128:
5886 case Intrinsic::x86_avx2_phadd_d:
5887 case Intrinsic::x86_ssse3_phsub_d:
5888 case Intrinsic::x86_ssse3_phsub_d_128:
5889 case Intrinsic::x86_avx2_phsub_d: {
5890 handlePairwiseShadowOrIntrinsic(
I, 32);
5895 case Intrinsic::x86_ssse3_phadd_sw:
5896 case Intrinsic::x86_ssse3_phadd_sw_128:
5897 case Intrinsic::x86_avx2_phadd_sw:
5898 case Intrinsic::x86_ssse3_phsub_sw:
5899 case Intrinsic::x86_ssse3_phsub_sw_128:
5900 case Intrinsic::x86_avx2_phsub_sw: {
5901 handlePairwiseShadowOrIntrinsic(
I, 16);
5906 case Intrinsic::x86_sse3_hadd_ps:
5907 case Intrinsic::x86_sse3_hadd_pd:
5908 case Intrinsic::x86_avx_hadd_pd_256:
5909 case Intrinsic::x86_avx_hadd_ps_256:
5910 case Intrinsic::x86_sse3_hsub_ps:
5911 case Intrinsic::x86_sse3_hsub_pd:
5912 case Intrinsic::x86_avx_hsub_pd_256:
5913 case Intrinsic::x86_avx_hsub_ps_256: {
5914 handlePairwiseShadowOrIntrinsic(
I);
5918 case Intrinsic::x86_avx_maskstore_ps:
5919 case Intrinsic::x86_avx_maskstore_pd:
5920 case Intrinsic::x86_avx_maskstore_ps_256:
5921 case Intrinsic::x86_avx_maskstore_pd_256:
5922 case Intrinsic::x86_avx2_maskstore_d:
5923 case Intrinsic::x86_avx2_maskstore_q:
5924 case Intrinsic::x86_avx2_maskstore_d_256:
5925 case Intrinsic::x86_avx2_maskstore_q_256: {
5926 handleAVXMaskedStore(
I);
5930 case Intrinsic::x86_avx_maskload_ps:
5931 case Intrinsic::x86_avx_maskload_pd:
5932 case Intrinsic::x86_avx_maskload_ps_256:
5933 case Intrinsic::x86_avx_maskload_pd_256:
5934 case Intrinsic::x86_avx2_maskload_d:
5935 case Intrinsic::x86_avx2_maskload_q:
5936 case Intrinsic::x86_avx2_maskload_d_256:
5937 case Intrinsic::x86_avx2_maskload_q_256: {
5938 handleAVXMaskedLoad(
I);
5943 case Intrinsic::x86_avx512fp16_add_ph_512:
5944 case Intrinsic::x86_avx512fp16_sub_ph_512:
5945 case Intrinsic::x86_avx512fp16_mul_ph_512:
5946 case Intrinsic::x86_avx512fp16_div_ph_512:
5947 case Intrinsic::x86_avx512fp16_max_ph_512:
5948 case Intrinsic::x86_avx512fp16_min_ph_512:
5949 case Intrinsic::x86_avx512_min_ps_512:
5950 case Intrinsic::x86_avx512_min_pd_512:
5951 case Intrinsic::x86_avx512_max_ps_512:
5952 case Intrinsic::x86_avx512_max_pd_512: {
5957 [[maybe_unused]]
bool Success =
5958 maybeHandleSimpleNomemIntrinsic(
I, 1);
5963 case Intrinsic::x86_avx_vpermilvar_pd:
5964 case Intrinsic::x86_avx_vpermilvar_pd_256:
5965 case Intrinsic::x86_avx512_vpermilvar_pd_512:
5966 case Intrinsic::x86_avx_vpermilvar_ps:
5967 case Intrinsic::x86_avx_vpermilvar_ps_256:
5968 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
5969 handleAVXVpermilvar(
I);
5973 case Intrinsic::x86_avx512_vpermi2var_d_128:
5974 case Intrinsic::x86_avx512_vpermi2var_d_256:
5975 case Intrinsic::x86_avx512_vpermi2var_d_512:
5976 case Intrinsic::x86_avx512_vpermi2var_hi_128:
5977 case Intrinsic::x86_avx512_vpermi2var_hi_256:
5978 case Intrinsic::x86_avx512_vpermi2var_hi_512:
5979 case Intrinsic::x86_avx512_vpermi2var_pd_128:
5980 case Intrinsic::x86_avx512_vpermi2var_pd_256:
5981 case Intrinsic::x86_avx512_vpermi2var_pd_512:
5982 case Intrinsic::x86_avx512_vpermi2var_ps_128:
5983 case Intrinsic::x86_avx512_vpermi2var_ps_256:
5984 case Intrinsic::x86_avx512_vpermi2var_ps_512:
5985 case Intrinsic::x86_avx512_vpermi2var_q_128:
5986 case Intrinsic::x86_avx512_vpermi2var_q_256:
5987 case Intrinsic::x86_avx512_vpermi2var_q_512:
5988 case Intrinsic::x86_avx512_vpermi2var_qi_128:
5989 case Intrinsic::x86_avx512_vpermi2var_qi_256:
5990 case Intrinsic::x86_avx512_vpermi2var_qi_512:
5991 handleAVXVpermi2var(
I);
6005 case Intrinsic::x86_avx2_pshuf_b:
6006 case Intrinsic::x86_sse_pshuf_w:
6007 case Intrinsic::x86_ssse3_pshuf_b_128:
6008 case Intrinsic::x86_ssse3_pshuf_b:
6009 case Intrinsic::x86_avx512_pshuf_b_512:
6010 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6016 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6017 case Intrinsic::x86_avx512_mask_pmov_db_512:
6018 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6019 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6022 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6030 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6031 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6032 handleIntrinsicByApplyingToShadow(
I,
6033 Intrinsic::x86_avx512_mask_pmov_dw_512,
6038 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6039 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6040 handleIntrinsicByApplyingToShadow(
I,
6041 Intrinsic::x86_avx512_mask_pmov_db_512,
6046 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6047 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6048 handleIntrinsicByApplyingToShadow(
I,
6049 Intrinsic::x86_avx512_mask_pmov_qb_512,
6054 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6055 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6056 handleIntrinsicByApplyingToShadow(
I,
6057 Intrinsic::x86_avx512_mask_pmov_qw_512,
6062 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6063 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6064 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6065 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6069 handleAVX512VectorDownConvert(
I);
6074 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
6075 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
6076 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
6077 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
6078 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
6079 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
6080 visitGenericScalarHalfwordInst(
I);
6085 case Intrinsic::x86_vgf2p8affineqb_128:
6086 case Intrinsic::x86_vgf2p8affineqb_256:
6087 case Intrinsic::x86_vgf2p8affineqb_512:
6088 handleAVXGF2P8Affine(
I);
6098 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
6099 switch (
I.getIntrinsicID()) {
6100 case Intrinsic::aarch64_neon_rshrn:
6101 case Intrinsic::aarch64_neon_sqrshl:
6102 case Intrinsic::aarch64_neon_sqrshrn:
6103 case Intrinsic::aarch64_neon_sqrshrun:
6104 case Intrinsic::aarch64_neon_sqshl:
6105 case Intrinsic::aarch64_neon_sqshlu:
6106 case Intrinsic::aarch64_neon_sqshrn:
6107 case Intrinsic::aarch64_neon_sqshrun:
6108 case Intrinsic::aarch64_neon_srshl:
6109 case Intrinsic::aarch64_neon_sshl:
6110 case Intrinsic::aarch64_neon_uqrshl:
6111 case Intrinsic::aarch64_neon_uqrshrn:
6112 case Intrinsic::aarch64_neon_uqshl:
6113 case Intrinsic::aarch64_neon_uqshrn:
6114 case Intrinsic::aarch64_neon_urshl:
6115 case Intrinsic::aarch64_neon_ushl:
6117 handleVectorShiftIntrinsic(
I,
false);
6122 case Intrinsic::aarch64_neon_fmaxp:
6123 case Intrinsic::aarch64_neon_fminp:
6125 case Intrinsic::aarch64_neon_fmaxnmp:
6126 case Intrinsic::aarch64_neon_fminnmp:
6128 case Intrinsic::aarch64_neon_smaxp:
6129 case Intrinsic::aarch64_neon_sminp:
6130 case Intrinsic::aarch64_neon_umaxp:
6131 case Intrinsic::aarch64_neon_uminp:
6133 case Intrinsic::aarch64_neon_addp:
6135 case Intrinsic::aarch64_neon_faddp:
6137 case Intrinsic::aarch64_neon_saddlp:
6138 case Intrinsic::aarch64_neon_uaddlp: {
6139 handlePairwiseShadowOrIntrinsic(
I);
6144 case Intrinsic::aarch64_neon_fcvtas:
6145 case Intrinsic::aarch64_neon_fcvtau:
6147 case Intrinsic::aarch64_neon_fcvtms:
6148 case Intrinsic::aarch64_neon_fcvtmu:
6150 case Intrinsic::aarch64_neon_fcvtns:
6151 case Intrinsic::aarch64_neon_fcvtnu:
6153 case Intrinsic::aarch64_neon_fcvtps:
6154 case Intrinsic::aarch64_neon_fcvtpu:
6156 case Intrinsic::aarch64_neon_fcvtzs:
6157 case Intrinsic::aarch64_neon_fcvtzu:
6159 case Intrinsic::aarch64_neon_fcvtxn: {
6160 handleNEONVectorConvertIntrinsic(
I);
6165 case Intrinsic::aarch64_neon_faddv:
6166 case Intrinsic::aarch64_neon_saddv:
6167 case Intrinsic::aarch64_neon_uaddv:
6170 case Intrinsic::aarch64_neon_smaxv:
6171 case Intrinsic::aarch64_neon_sminv:
6172 case Intrinsic::aarch64_neon_umaxv:
6173 case Intrinsic::aarch64_neon_uminv:
6177 case Intrinsic::aarch64_neon_fmaxv:
6178 case Intrinsic::aarch64_neon_fminv:
6179 case Intrinsic::aarch64_neon_fmaxnmv:
6180 case Intrinsic::aarch64_neon_fminnmv:
6182 case Intrinsic::aarch64_neon_saddlv:
6183 case Intrinsic::aarch64_neon_uaddlv:
6184 handleVectorReduceIntrinsic(
I,
true);
6187 case Intrinsic::aarch64_neon_ld1x2:
6188 case Intrinsic::aarch64_neon_ld1x3:
6189 case Intrinsic::aarch64_neon_ld1x4:
6190 case Intrinsic::aarch64_neon_ld2:
6191 case Intrinsic::aarch64_neon_ld3:
6192 case Intrinsic::aarch64_neon_ld4:
6193 case Intrinsic::aarch64_neon_ld2r:
6194 case Intrinsic::aarch64_neon_ld3r:
6195 case Intrinsic::aarch64_neon_ld4r: {
6196 handleNEONVectorLoad(
I,
false);
6200 case Intrinsic::aarch64_neon_ld2lane:
6201 case Intrinsic::aarch64_neon_ld3lane:
6202 case Intrinsic::aarch64_neon_ld4lane: {
6203 handleNEONVectorLoad(
I,
true);
6208 case Intrinsic::aarch64_neon_sqxtn:
6209 case Intrinsic::aarch64_neon_sqxtun:
6210 case Intrinsic::aarch64_neon_uqxtn:
6217 case Intrinsic::aarch64_neon_st1x2:
6218 case Intrinsic::aarch64_neon_st1x3:
6219 case Intrinsic::aarch64_neon_st1x4:
6220 case Intrinsic::aarch64_neon_st2:
6221 case Intrinsic::aarch64_neon_st3:
6222 case Intrinsic::aarch64_neon_st4: {
6223 handleNEONVectorStoreIntrinsic(
I,
false);
6227 case Intrinsic::aarch64_neon_st2lane:
6228 case Intrinsic::aarch64_neon_st3lane:
6229 case Intrinsic::aarch64_neon_st4lane: {
6230 handleNEONVectorStoreIntrinsic(
I,
true);
6243 case Intrinsic::aarch64_neon_tbl1:
6244 case Intrinsic::aarch64_neon_tbl2:
6245 case Intrinsic::aarch64_neon_tbl3:
6246 case Intrinsic::aarch64_neon_tbl4:
6247 case Intrinsic::aarch64_neon_tbx1:
6248 case Intrinsic::aarch64_neon_tbx2:
6249 case Intrinsic::aarch64_neon_tbx3:
6250 case Intrinsic::aarch64_neon_tbx4: {
6252 handleIntrinsicByApplyingToShadow(
6253 I,
I.getIntrinsicID(),
6258 case Intrinsic::aarch64_neon_fmulx:
6259 case Intrinsic::aarch64_neon_pmul:
6260 case Intrinsic::aarch64_neon_pmull:
6261 case Intrinsic::aarch64_neon_smull:
6262 case Intrinsic::aarch64_neon_pmull64:
6263 case Intrinsic::aarch64_neon_umull: {
6264 handleNEONVectorMultiplyIntrinsic(
I);
6275 void visitIntrinsicInst(IntrinsicInst &
I) {
6276 if (maybeHandleCrossPlatformIntrinsic(
I))
6279 if (maybeHandleX86SIMDIntrinsic(
I))
6282 if (maybeHandleArmSIMDIntrinsic(
I))
6285 if (maybeHandleUnknownIntrinsic(
I))
6288 visitInstruction(
I);
6291 void visitLibAtomicLoad(CallBase &CB) {
6302 Value *NewOrdering =
6306 NextNodeIRBuilder NextIRB(&CB);
6307 Value *SrcShadowPtr, *SrcOriginPtr;
6308 std::tie(SrcShadowPtr, SrcOriginPtr) =
6309 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
6311 Value *DstShadowPtr =
6312 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
6316 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
6317 if (MS.TrackOrigins) {
6318 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
6320 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
6321 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
6325 void visitLibAtomicStore(CallBase &CB) {
6332 Value *NewOrdering =
6336 Value *DstShadowPtr =
6346 void visitCallBase(CallBase &CB) {
6354 visitAsmInstruction(CB);
6356 visitInstruction(CB);
6365 case LibFunc_atomic_load:
6367 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
6371 visitLibAtomicLoad(CB);
6373 case LibFunc_atomic_store:
6374 visitLibAtomicStore(CB);
6390 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
6394 Func->removeFnAttrs(
B);
6400 bool MayCheckCall = MS.EagerChecks;
6404 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
6407 unsigned ArgOffset = 0;
6410 if (!
A->getType()->isSized()) {
6411 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
6415 if (
A->getType()->isScalableTy()) {
6416 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
6418 insertCheckShadowOf(
A, &CB);
6423 const DataLayout &
DL =
F.getDataLayout();
6427 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
6430 insertCheckShadowOf(
A, &CB);
6431 Size =
DL.getTypeAllocSize(
A->getType());
6437 Value *ArgShadow = getShadow(
A);
6438 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
6440 <<
" Shadow: " << *ArgShadow <<
"\n");
6444 assert(
A->getType()->isPointerTy() &&
6445 "ByVal argument is not a pointer!");
6450 MaybeAlign Alignment = std::nullopt;
6453 Value *AShadowPtr, *AOriginPtr;
6454 std::tie(AShadowPtr, AOriginPtr) =
6455 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
6457 if (!PropagateShadow) {
6464 if (MS.TrackOrigins) {
6465 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
6479 Size =
DL.getTypeAllocSize(
A->getType());
6485 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
6487 getOriginPtrForArgument(IRB, ArgOffset));
6490 assert(Store !=
nullptr);
6499 if (FT->isVarArg()) {
6500 VAHelper->visitCallBase(CB, IRB);
6510 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
6511 setShadow(&CB, getCleanShadow(&CB));
6512 setOrigin(&CB, getCleanOrigin());
6518 Value *
Base = getShadowPtrForRetval(IRBBefore);
6519 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
6531 setShadow(&CB, getCleanShadow(&CB));
6532 setOrigin(&CB, getCleanOrigin());
6539 "Could not find insertion point for retval shadow load");
6542 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
6545 setShadow(&CB, RetvalShadow);
6546 if (MS.TrackOrigins)
6547 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
6552 RetVal =
I->getOperand(0);
6555 return I->isMustTailCall();
6560 void visitReturnInst(ReturnInst &
I) {
6562 Value *RetVal =
I.getReturnValue();
6568 Value *ShadowPtr = getShadowPtrForRetval(IRB);
6569 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
6570 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
6573 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
6575 Value *Shadow = getShadow(RetVal);
6576 bool StoreOrigin =
true;
6578 insertCheckShadowOf(RetVal, &
I);
6579 Shadow = getCleanShadow(RetVal);
6580 StoreOrigin =
false;
6587 if (MS.TrackOrigins && StoreOrigin)
6588 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
6592 void visitPHINode(PHINode &
I) {
6594 if (!PropagateShadow) {
6595 setShadow(&
I, getCleanShadow(&
I));
6596 setOrigin(&
I, getCleanOrigin());
6600 ShadowPHINodes.push_back(&
I);
6601 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
6603 if (MS.TrackOrigins)
6605 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
6608 Value *getLocalVarIdptr(AllocaInst &
I) {
6609 ConstantInt *IntConst =
6610 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
6611 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
6616 Value *getLocalVarDescription(AllocaInst &
I) {
6622 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
6624 Value *ShadowBase, *OriginBase;
6625 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
6629 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
6632 if (PoisonStack && MS.TrackOrigins) {
6633 Value *Idptr = getLocalVarIdptr(
I);
6635 Value *Descr = getLocalVarDescription(
I);
6636 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
6637 {&I, Len, Idptr, Descr});
6639 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
6645 Value *Descr = getLocalVarDescription(
I);
6647 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
6649 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
6653 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
6656 NextNodeIRBuilder IRB(InsPoint);
6657 const DataLayout &
DL =
F.getDataLayout();
6658 TypeSize TS =
DL.getTypeAllocSize(
I.getAllocatedType());
6660 if (
I.isArrayAllocation())
6664 if (MS.CompileKernel)
6665 poisonAllocaKmsan(
I, IRB, Len);
6667 poisonAllocaUserspace(
I, IRB, Len);
6670 void visitAllocaInst(AllocaInst &
I) {
6671 setShadow(&
I, getCleanShadow(&
I));
6672 setOrigin(&
I, getCleanOrigin());
6678 void visitSelectInst(SelectInst &
I) {
6684 handleSelectLikeInst(
I,
B,
C,
D);
6690 Value *Sb = getShadow(
B);
6691 Value *Sc = getShadow(
C);
6692 Value *Sd = getShadow(
D);
6694 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
6695 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
6696 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
6701 if (
I.getType()->isAggregateType()) {
6705 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
6713 C = CreateAppToShadowCast(IRB,
C);
6714 D = CreateAppToShadowCast(IRB,
D);
6721 if (MS.TrackOrigins) {
6724 if (
B->getType()->isVectorTy()) {
6725 B = convertToBool(
B, IRB);
6726 Sb = convertToBool(Sb, IRB);
6734 void visitLandingPadInst(LandingPadInst &
I) {
6737 setShadow(&
I, getCleanShadow(&
I));
6738 setOrigin(&
I, getCleanOrigin());
6741 void visitCatchSwitchInst(CatchSwitchInst &
I) {
6742 setShadow(&
I, getCleanShadow(&
I));
6743 setOrigin(&
I, getCleanOrigin());
6746 void visitFuncletPadInst(FuncletPadInst &
I) {
6747 setShadow(&
I, getCleanShadow(&
I));
6748 setOrigin(&
I, getCleanOrigin());
6751 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
6753 void visitExtractValueInst(ExtractValueInst &
I) {
6755 Value *Agg =
I.getAggregateOperand();
6757 Value *AggShadow = getShadow(Agg);
6761 setShadow(&
I, ResShadow);
6762 setOriginForNaryOp(
I);
6765 void visitInsertValueInst(InsertValueInst &
I) {
6768 Value *AggShadow = getShadow(
I.getAggregateOperand());
6769 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
6775 setOriginForNaryOp(
I);
6778 void dumpInst(Instruction &
I) {
6782 errs() <<
"ZZZ " <<
I.getOpcodeName() <<
"\n";
6784 errs() <<
"QQQ " <<
I <<
"\n";
6787 void visitResumeInst(ResumeInst &
I) {
6792 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
6797 void visitCatchReturnInst(CatchReturnInst &CRI) {
6802 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
6811 insertCheckShadowOf(Operand, &
I);
6818 auto Size =
DL.getTypeStoreSize(ElemTy);
6820 if (MS.CompileKernel) {
6821 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
6827 auto [ShadowPtr,
_] =
6828 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
6838 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
6839 int NumRetOutputs = 0;
6846 NumRetOutputs =
ST->getNumElements();
6851 for (
const InlineAsm::ConstraintInfo &
Info : Constraints) {
6852 switch (
Info.Type) {
6860 return NumOutputs - NumRetOutputs;
6863 void visitAsmInstruction(Instruction &
I) {
6879 const DataLayout &
DL =
F.getDataLayout();
6883 int OutputArgs = getNumOutputArgs(IA, CB);
6889 for (
int i = OutputArgs; i < NumOperands; i++) {
6897 for (
int i = 0; i < OutputArgs; i++) {
6903 setShadow(&
I, getCleanShadow(&
I));
6904 setOrigin(&
I, getCleanOrigin());
6907 void visitFreezeInst(FreezeInst &
I) {
6909 setShadow(&
I, getCleanShadow(&
I));
6910 setOrigin(&
I, getCleanOrigin());
6913 void visitInstruction(Instruction &
I) {
6918 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
6919 Value *Operand =
I.getOperand(i);
6921 insertCheckShadowOf(Operand, &
I);
6923 setShadow(&
I, getCleanShadow(&
I));
6924 setOrigin(&
I, getCleanOrigin());
6928struct VarArgHelperBase :
public VarArgHelper {
6930 MemorySanitizer &MS;
6931 MemorySanitizerVisitor &MSV;
6933 const unsigned VAListTagSize;
6935 VarArgHelperBase(Function &
F, MemorySanitizer &MS,
6936 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
6937 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
6941 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
6957 return getShadowPtrForVAArgument(IRB, ArgOffset);
6971 unsigned BaseOffset) {
6980 TailSize,
Align(8));
6983 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
6985 Value *VAListTag =
I.getArgOperand(0);
6987 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
6988 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
6991 VAListTagSize, Alignment,
false);
6994 void visitVAStartInst(VAStartInst &
I)
override {
6995 if (
F.getCallingConv() == CallingConv::Win64)
6998 unpoisonVAListTagForInst(
I);
7001 void visitVACopyInst(VACopyInst &
I)
override {
7002 if (
F.getCallingConv() == CallingConv::Win64)
7004 unpoisonVAListTagForInst(
I);
7009struct VarArgAMD64Helper :
public VarArgHelperBase {
7012 static const unsigned AMD64GpEndOffset = 48;
7013 static const unsigned AMD64FpEndOffsetSSE = 176;
7015 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
7017 unsigned AMD64FpEndOffset;
7018 AllocaInst *VAArgTLSCopy =
nullptr;
7019 AllocaInst *VAArgTLSOriginCopy =
nullptr;
7020 Value *VAArgOverflowSize =
nullptr;
7022 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
7024 VarArgAMD64Helper(Function &
F, MemorySanitizer &MS,
7025 MemorySanitizerVisitor &MSV)
7026 : VarArgHelperBase(
F, MS, MSV, 24) {
7027 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
7028 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
7029 if (Attr.isStringAttribute() &&
7030 (Attr.getKindAsString() ==
"target-features")) {
7031 if (Attr.getValueAsString().contains(
"-sse"))
7032 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
7038 ArgKind classifyArgument(
Value *arg) {
7041 if (
T->isX86_FP80Ty())
7043 if (
T->isFPOrFPVectorTy())
7044 return AK_FloatingPoint;
7045 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
7046 return AK_GeneralPurpose;
7047 if (
T->isPointerTy())
7048 return AK_GeneralPurpose;
7060 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
7061 unsigned GpOffset = 0;
7062 unsigned FpOffset = AMD64GpEndOffset;
7063 unsigned OverflowOffset = AMD64FpEndOffset;
7064 const DataLayout &
DL =
F.getDataLayout();
7068 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
7075 assert(
A->getType()->isPointerTy());
7077 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
7078 uint64_t AlignedSize =
alignTo(ArgSize, 8);
7079 unsigned BaseOffset = OverflowOffset;
7080 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
7081 Value *OriginBase =
nullptr;
7082 if (MS.TrackOrigins)
7083 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
7084 OverflowOffset += AlignedSize;
7087 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
7091 Value *ShadowPtr, *OriginPtr;
7092 std::tie(ShadowPtr, OriginPtr) =
7097 if (MS.TrackOrigins)
7101 ArgKind AK = classifyArgument(
A);
7102 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
7104 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
7106 Value *ShadowBase, *OriginBase =
nullptr;
7108 case AK_GeneralPurpose:
7109 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
7110 if (MS.TrackOrigins)
7111 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
7115 case AK_FloatingPoint:
7116 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
7117 if (MS.TrackOrigins)
7118 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
7125 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
7126 uint64_t AlignedSize =
alignTo(ArgSize, 8);
7127 unsigned BaseOffset = OverflowOffset;
7128 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
7129 if (MS.TrackOrigins) {
7130 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
7132 OverflowOffset += AlignedSize;
7135 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
7144 Value *Shadow = MSV.getShadow(
A);
7146 if (MS.TrackOrigins) {
7147 Value *Origin = MSV.getOrigin(
A);
7148 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
7149 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
7155 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
7156 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
7159 void finalizeInstrumentation()
override {
7160 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
7161 "finalizeInstrumentation called twice");
7162 if (!VAStartInstrumentationList.
empty()) {
7169 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
7170 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
7176 Intrinsic::umin, CopySize,
7180 if (MS.TrackOrigins) {
7181 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
7190 for (CallInst *OrigInst : VAStartInstrumentationList) {
7191 NextNodeIRBuilder IRB(OrigInst);
7192 Value *VAListTag = OrigInst->getArgOperand(0);
7196 ConstantInt::get(MS.IntptrTy, 16)),
7199 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
7201 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
7202 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
7204 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
7206 if (MS.TrackOrigins)
7207 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
7208 Alignment, AMD64FpEndOffset);
7211 ConstantInt::get(MS.IntptrTy, 8)),
7213 Value *OverflowArgAreaPtr =
7214 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
7215 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
7216 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
7217 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
7221 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
7223 if (MS.TrackOrigins) {
7226 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
7234struct VarArgAArch64Helper :
public VarArgHelperBase {
7235 static const unsigned kAArch64GrArgSize = 64;
7236 static const unsigned kAArch64VrArgSize = 128;
7238 static const unsigned AArch64GrBegOffset = 0;
7239 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
7241 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
7242 static const unsigned AArch64VrEndOffset =
7243 AArch64VrBegOffset + kAArch64VrArgSize;
7244 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
7246 AllocaInst *VAArgTLSCopy =
nullptr;
7247 Value *VAArgOverflowSize =
nullptr;
7249 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
7251 VarArgAArch64Helper(Function &
F, MemorySanitizer &MS,
7252 MemorySanitizerVisitor &MSV)
7253 : VarArgHelperBase(
F, MS, MSV, 32) {}
7256 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
7257 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
7258 return {AK_GeneralPurpose, 1};
7259 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
7260 return {AK_FloatingPoint, 1};
7262 if (
T->isArrayTy()) {
7263 auto R = classifyArgument(
T->getArrayElementType());
7264 R.second *=
T->getScalarType()->getArrayNumElements();
7269 auto R = classifyArgument(FV->getScalarType());
7270 R.second *= FV->getNumElements();
7275 return {AK_Memory, 0};
7287 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
7288 unsigned GrOffset = AArch64GrBegOffset;
7289 unsigned VrOffset = AArch64VrBegOffset;
7290 unsigned OverflowOffset = AArch64VAEndOffset;
7292 const DataLayout &
DL =
F.getDataLayout();
7295 auto [AK, RegNum] = classifyArgument(
A->getType());
7296 if (AK == AK_GeneralPurpose &&
7297 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
7299 if (AK == AK_FloatingPoint &&
7300 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
7304 case AK_GeneralPurpose:
7305 Base = getShadowPtrForVAArgument(IRB, GrOffset);
7306 GrOffset += 8 * RegNum;
7308 case AK_FloatingPoint:
7309 Base = getShadowPtrForVAArgument(IRB, VrOffset);
7310 VrOffset += 16 * RegNum;
7317 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
7318 uint64_t AlignedSize =
alignTo(ArgSize, 8);
7319 unsigned BaseOffset = OverflowOffset;
7320 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
7321 OverflowOffset += AlignedSize;
7324 CleanUnusedTLS(IRB,
Base, BaseOffset);
7336 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
7337 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
7344 ConstantInt::get(MS.IntptrTy, offset)),
7346 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
7353 ConstantInt::get(MS.IntptrTy, offset)),
7356 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
7359 void finalizeInstrumentation()
override {
7360 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
7361 "finalizeInstrumentation called twice");
7362 if (!VAStartInstrumentationList.empty()) {
7369 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
7370 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
7376 Intrinsic::umin, CopySize,
7382 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
7383 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
7387 for (CallInst *OrigInst : VAStartInstrumentationList) {
7388 NextNodeIRBuilder IRB(OrigInst);
7390 Value *VAListTag = OrigInst->getArgOperand(0);
7407 Value *StackSaveAreaPtr =
7408 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
7411 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
7412 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
7415 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
7418 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
7419 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
7422 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
7428 Value *GrRegSaveAreaShadowPtrOff =
7429 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
7431 Value *GrRegSaveAreaShadowPtr =
7432 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
7438 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
7444 Value *VrRegSaveAreaShadowPtrOff =
7445 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
7447 Value *VrRegSaveAreaShadowPtr =
7448 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
7455 VrRegSaveAreaShadowPtrOff);
7456 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
7462 Value *StackSaveAreaShadowPtr =
7463 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
7468 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
7471 Align(16), VAArgOverflowSize);
7477struct VarArgPowerPC64Helper :
public VarArgHelperBase {
7478 AllocaInst *VAArgTLSCopy =
nullptr;
7479 Value *VAArgSize =
nullptr;
7481 VarArgPowerPC64Helper(Function &
F, MemorySanitizer &MS,
7482 MemorySanitizerVisitor &MSV)
7483 : VarArgHelperBase(
F, MS, MSV, 8) {}
7485 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
7493 Triple TargetTriple(
F.getParent()->getTargetTriple());
7497 if (TargetTriple.isPPC64ELFv2ABI())
7501 unsigned VAArgOffset = VAArgBase;
7502 const DataLayout &
DL =
F.getDataLayout();
7505 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
7507 assert(
A->getType()->isPointerTy());
7509 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
7512 ArgAlign =
Align(8);
7513 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
7516 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
7518 Value *AShadowPtr, *AOriginPtr;
7519 std::tie(AShadowPtr, AOriginPtr) =
7520 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
7530 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
7532 if (
A->getType()->isArrayTy()) {
7535 Type *ElementTy =
A->getType()->getArrayElementType();
7537 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
7538 }
else if (
A->getType()->isVectorTy()) {
7540 ArgAlign =
Align(ArgSize);
7543 ArgAlign =
Align(8);
7544 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
7545 if (
DL.isBigEndian()) {
7549 VAArgOffset += (8 - ArgSize);
7553 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
7557 VAArgOffset += ArgSize;
7561 VAArgBase = VAArgOffset;
7565 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
7568 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
7571 void finalizeInstrumentation()
override {
7572 assert(!VAArgSize && !VAArgTLSCopy &&
7573 "finalizeInstrumentation called twice");
7576 Value *CopySize = VAArgSize;
7578 if (!VAStartInstrumentationList.empty()) {
7582 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
7588 Intrinsic::umin, CopySize,
7596 for (CallInst *OrigInst : VAStartInstrumentationList) {
7597 NextNodeIRBuilder IRB(OrigInst);
7598 Value *VAListTag = OrigInst->getArgOperand(0);
7601 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
7604 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
7605 const DataLayout &
DL =
F.getDataLayout();
7606 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
7608 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
7609 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
7611 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
7618struct VarArgPowerPC32Helper :
public VarArgHelperBase {
7619 AllocaInst *VAArgTLSCopy =
nullptr;
7620 Value *VAArgSize =
nullptr;
7622 VarArgPowerPC32Helper(Function &
F, MemorySanitizer &MS,
7623 MemorySanitizerVisitor &MSV)
7624 : VarArgHelperBase(
F, MS, MSV, 12) {}
7626 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
7630 unsigned VAArgOffset = VAArgBase;
7631 const DataLayout &
DL =
F.getDataLayout();
7632 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
7635 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
7637 assert(
A->getType()->isPointerTy());
7639 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
7641 if (ArgAlign < IntptrSize)
7642 ArgAlign =
Align(IntptrSize);
7643 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
7646 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
7648 Value *AShadowPtr, *AOriginPtr;
7649 std::tie(AShadowPtr, AOriginPtr) =
7650 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
7660 Type *ArgTy =
A->getType();
7666 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
7673 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
7676 ArgAlign =
Align(ArgSize);
7678 if (ArgAlign < IntptrSize)
7679 ArgAlign =
Align(IntptrSize);
7680 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
7681 if (
DL.isBigEndian()) {
7684 if (ArgSize < IntptrSize)
7685 VAArgOffset += (IntptrSize - ArgSize);
7688 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
7694 VAArgOffset += ArgSize;
7701 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
7704 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
7707 void finalizeInstrumentation()
override {
7708 assert(!VAArgSize && !VAArgTLSCopy &&
7709 "finalizeInstrumentation called twice");
7711 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
7712 Value *CopySize = VAArgSize;
7714 if (!VAStartInstrumentationList.empty()) {
7718 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
7724 Intrinsic::umin, CopySize,
7732 for (CallInst *OrigInst : VAStartInstrumentationList) {
7733 NextNodeIRBuilder IRB(OrigInst);
7734 Value *VAListTag = OrigInst->getArgOperand(0);
7736 Value *RegSaveAreaSize = CopySize;
7740 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
7744 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
7746 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
7749 const DataLayout &
DL =
F.getDataLayout();
7750 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
7754 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
7755 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
7756 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
7758 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
7759 Alignment, RegSaveAreaSize);
7761 RegSaveAreaShadowPtr =
7764 ConstantInt::get(MS.IntptrTy, 32));
7769 ConstantInt::get(MS.IntptrTy, 32), Alignment);
7774 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
7777 OverflowAreaPtrPtr =
7778 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
7779 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
7781 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
7783 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
7784 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
7785 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
7788 Value *OverflowVAArgTLSCopyPtr =
7790 OverflowVAArgTLSCopyPtr =
7791 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
7793 OverflowVAArgTLSCopyPtr =
7796 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
7803struct VarArgSystemZHelper :
public VarArgHelperBase {
7804 static const unsigned SystemZGpOffset = 16;
7805 static const unsigned SystemZGpEndOffset = 56;
7806 static const unsigned SystemZFpOffset = 128;
7807 static const unsigned SystemZFpEndOffset = 160;
7808 static const unsigned SystemZMaxVrArgs = 8;
7809 static const unsigned SystemZRegSaveAreaSize = 160;
7810 static const unsigned SystemZOverflowOffset = 160;
7811 static const unsigned SystemZVAListTagSize = 32;
7812 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
7813 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
7815 bool IsSoftFloatABI;
7816 AllocaInst *VAArgTLSCopy =
nullptr;
7817 AllocaInst *VAArgTLSOriginCopy =
nullptr;
7818 Value *VAArgOverflowSize =
nullptr;
7820 enum class ArgKind {
7828 enum class ShadowExtension {
None,
Zero, Sign };
7830 VarArgSystemZHelper(Function &
F, MemorySanitizer &MS,
7831 MemorySanitizerVisitor &MSV)
7832 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
7833 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
7835 ArgKind classifyArgument(
Type *
T) {
7842 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
7843 return ArgKind::Indirect;
7844 if (
T->isFloatingPointTy())
7845 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
7846 if (
T->isIntegerTy() ||
T->isPointerTy())
7847 return ArgKind::GeneralPurpose;
7848 if (
T->isVectorTy())
7849 return ArgKind::Vector;
7850 return ArgKind::Memory;
7853 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
7863 return ShadowExtension::Zero;
7867 return ShadowExtension::Sign;
7869 return ShadowExtension::None;
7872 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
7873 unsigned GpOffset = SystemZGpOffset;
7874 unsigned FpOffset = SystemZFpOffset;
7875 unsigned VrIndex = 0;
7876 unsigned OverflowOffset = SystemZOverflowOffset;
7877 const DataLayout &
DL =
F.getDataLayout();
7883 ArgKind AK = classifyArgument(
T);
7884 if (AK == ArgKind::Indirect) {
7886 AK = ArgKind::GeneralPurpose;
7888 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
7889 AK = ArgKind::Memory;
7890 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
7891 AK = ArgKind::Memory;
7892 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
7893 AK = ArgKind::Memory;
7894 Value *ShadowBase =
nullptr;
7895 Value *OriginBase =
nullptr;
7896 ShadowExtension SE = ShadowExtension::None;
7898 case ArgKind::GeneralPurpose: {
7900 uint64_t ArgSize = 8;
7903 SE = getShadowExtension(CB, ArgNo);
7904 uint64_t GapSize = 0;
7905 if (SE == ShadowExtension::None) {
7906 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
7907 assert(ArgAllocSize <= ArgSize);
7908 GapSize = ArgSize - ArgAllocSize;
7910 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
7911 if (MS.TrackOrigins)
7912 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
7914 GpOffset += ArgSize;
7920 case ArgKind::FloatingPoint: {
7922 uint64_t ArgSize = 8;
7929 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
7930 if (MS.TrackOrigins)
7931 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
7933 FpOffset += ArgSize;
7939 case ArgKind::Vector: {
7946 case ArgKind::Memory: {
7951 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
7952 uint64_t ArgSize =
alignTo(ArgAllocSize, 8);
7954 SE = getShadowExtension(CB, ArgNo);
7956 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
7958 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
7959 if (MS.TrackOrigins)
7961 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
7962 OverflowOffset += ArgSize;
7969 case ArgKind::Indirect:
7972 if (ShadowBase ==
nullptr)
7974 Value *Shadow = MSV.getShadow(
A);
7975 if (SE != ShadowExtension::None)
7976 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
7977 SE == ShadowExtension::Sign);
7978 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
7980 if (MS.TrackOrigins) {
7981 Value *Origin = MSV.getOrigin(
A);
7982 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
7983 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
7987 Constant *OverflowSize = ConstantInt::get(
7988 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
7989 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
7996 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
7999 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8001 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8002 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
8007 unsigned RegSaveAreaSize =
8008 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
8009 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8011 if (MS.TrackOrigins)
8012 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8013 Alignment, RegSaveAreaSize);
8022 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
8024 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8025 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8027 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8028 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8031 SystemZOverflowOffset);
8032 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8034 if (MS.TrackOrigins) {
8036 SystemZOverflowOffset);
8037 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8042 void finalizeInstrumentation()
override {
8043 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8044 "finalizeInstrumentation called twice");
8045 if (!VAStartInstrumentationList.empty()) {
8052 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
8054 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8060 Intrinsic::umin, CopySize,
8064 if (MS.TrackOrigins) {
8065 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8074 for (CallInst *OrigInst : VAStartInstrumentationList) {
8075 NextNodeIRBuilder IRB(OrigInst);
8076 Value *VAListTag = OrigInst->getArgOperand(0);
8077 copyRegSaveArea(IRB, VAListTag);
8078 copyOverflowArea(IRB, VAListTag);
8084struct VarArgI386Helper :
public VarArgHelperBase {
8085 AllocaInst *VAArgTLSCopy =
nullptr;
8086 Value *VAArgSize =
nullptr;
8088 VarArgI386Helper(Function &
F, MemorySanitizer &MS,
8089 MemorySanitizerVisitor &MSV)
8090 : VarArgHelperBase(
F, MS, MSV, 4) {}
8092 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8093 const DataLayout &
DL =
F.getDataLayout();
8094 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8095 unsigned VAArgOffset = 0;
8098 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8100 assert(
A->getType()->isPointerTy());
8102 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8104 if (ArgAlign < IntptrSize)
8105 ArgAlign =
Align(IntptrSize);
8106 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8108 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
8110 Value *AShadowPtr, *AOriginPtr;
8111 std::tie(AShadowPtr, AOriginPtr) =
8112 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8122 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8124 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8125 if (
DL.isBigEndian()) {
8128 if (ArgSize < IntptrSize)
8129 VAArgOffset += (IntptrSize - ArgSize);
8132 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
8135 VAArgOffset += ArgSize;
8141 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
8144 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8147 void finalizeInstrumentation()
override {
8148 assert(!VAArgSize && !VAArgTLSCopy &&
8149 "finalizeInstrumentation called twice");
8151 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8152 Value *CopySize = VAArgSize;
8154 if (!VAStartInstrumentationList.empty()) {
8157 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8163 Intrinsic::umin, CopySize,
8171 for (CallInst *OrigInst : VAStartInstrumentationList) {
8172 NextNodeIRBuilder IRB(OrigInst);
8173 Value *VAListTag = OrigInst->getArgOperand(0);
8174 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
8175 Value *RegSaveAreaPtrPtr =
8177 PointerType::get(*MS.C, 0));
8178 Value *RegSaveAreaPtr =
8179 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
8180 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8181 const DataLayout &
DL =
F.getDataLayout();
8182 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8184 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8185 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8187 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8195struct VarArgGenericHelper :
public VarArgHelperBase {
8196 AllocaInst *VAArgTLSCopy =
nullptr;
8197 Value *VAArgSize =
nullptr;
8199 VarArgGenericHelper(Function &
F, MemorySanitizer &MS,
8200 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
8201 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
8203 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8204 unsigned VAArgOffset = 0;
8205 const DataLayout &
DL =
F.getDataLayout();
8206 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8211 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8212 if (
DL.isBigEndian()) {
8215 if (ArgSize < IntptrSize)
8216 VAArgOffset += (IntptrSize - ArgSize);
8218 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
8219 VAArgOffset += ArgSize;
8220 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
8226 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
8229 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8232 void finalizeInstrumentation()
override {
8233 assert(!VAArgSize && !VAArgTLSCopy &&
8234 "finalizeInstrumentation called twice");
8236 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8237 Value *CopySize = VAArgSize;
8239 if (!VAStartInstrumentationList.empty()) {
8242 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8248 Intrinsic::umin, CopySize,
8256 for (CallInst *OrigInst : VAStartInstrumentationList) {
8257 NextNodeIRBuilder IRB(OrigInst);
8258 Value *VAListTag = OrigInst->getArgOperand(0);
8259 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
8260 Value *RegSaveAreaPtrPtr =
8262 PointerType::get(*MS.C, 0));
8263 Value *RegSaveAreaPtr =
8264 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
8265 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8266 const DataLayout &
DL =
F.getDataLayout();
8267 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8269 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8270 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8272 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8280using VarArgARM32Helper = VarArgGenericHelper;
8281using VarArgRISCVHelper = VarArgGenericHelper;
8282using VarArgMIPSHelper = VarArgGenericHelper;
8283using VarArgLoongArch64Helper = VarArgGenericHelper;
8286struct VarArgNoOpHelper :
public VarArgHelper {
8287 VarArgNoOpHelper(Function &
F, MemorySanitizer &MS,
8288 MemorySanitizerVisitor &MSV) {}
8290 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
8292 void visitVAStartInst(VAStartInst &
I)
override {}
8294 void visitVACopyInst(VACopyInst &
I)
override {}
8296 void finalizeInstrumentation()
override {}
8302 MemorySanitizerVisitor &Visitor) {
8305 Triple TargetTriple(Func.getParent()->getTargetTriple());
8308 return new VarArgI386Helper(Func, Msan, Visitor);
8311 return new VarArgAMD64Helper(Func, Msan, Visitor);
8313 if (TargetTriple.
isARM())
8314 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
8317 return new VarArgAArch64Helper(Func, Msan, Visitor);
8320 return new VarArgSystemZHelper(Func, Msan, Visitor);
8325 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
8328 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
8331 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
8334 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
8337 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
8340 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
8343 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
8346 return new VarArgNoOpHelper(Func, Msan, Visitor);
8353 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
8356 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
8363 return Visitor.runOnFunction();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isStore(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClWithComdat("asan-with-comdat", cl::desc("Place ASan constructors in comdat sections"), cl::Hidden, cl::init(true))
VarLocInsertPt getNextNode(const DbgRecord *DVR)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static bool isAMustTailRetVal(Value *RetVal)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static const PlatformMemoryMapParams Linux_S390_MemoryMapParams
static const Align kMinOriginAlignment
static cl::opt< uint64_t > ClShadowBase("msan-shadow-base", cl::desc("Define custom MSan ShadowBase"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClPoisonUndef("msan-poison-undef", cl::desc("Poison fully undef temporary values. " "Partially undefined constant vectors " "are unaffected by this flag (see " "-msan-poison-undef-vectors)."), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_X86_MemoryMapParams
static cl::opt< uint64_t > ClOriginBase("msan-origin-base", cl::desc("Define custom MSan OriginBase"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClCheckConstantShadow("msan-check-constant-shadow", cl::desc("Insert checks for constant shadow values"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_LoongArch_MemoryMapParams
static const MemoryMapParams NetBSD_X86_64_MemoryMapParams
static const PlatformMemoryMapParams Linux_MIPS_MemoryMapParams
static const unsigned kOriginSize
static cl::opt< bool > ClWithComdat("msan-with-comdat", cl::desc("Place MSan constructors in comdat sections"), cl::Hidden, cl::init(false))
static cl::opt< int > ClTrackOrigins("msan-track-origins", cl::desc("Track origins (allocation sites) of poisoned memory"), cl::Hidden, cl::init(0))
Track origins of uninitialized values.
static cl::opt< int > ClInstrumentationWithCallThreshold("msan-instrumentation-with-call-threshold", cl::desc("If the function being instrumented requires more than " "this number of checks and origin stores, use callbacks instead of " "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(3500))
static cl::opt< int > ClPoisonStackPattern("msan-poison-stack-pattern", cl::desc("poison uninitialized stack variables with the given pattern"), cl::Hidden, cl::init(0xff))
static const Align kShadowTLSAlignment
static cl::opt< bool > ClHandleICmpExact("msan-handle-icmp-exact", cl::desc("exact handling of relational integer ICmp"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_ARM_MemoryMapParams
static cl::opt< bool > ClDumpStrictInstructions("msan-dump-strict-instructions", cl::desc("print out instructions with default strict semantics i.e.," "check that all the inputs are fully initialized, and mark " "the output as fully initialized. These semantics are applied " "to instructions that could not be handled explicitly nor " "heuristically."), cl::Hidden, cl::init(false))
static Constant * getOrInsertGlobal(Module &M, StringRef Name, Type *Ty)
static cl::opt< bool > ClPreciseDisjointOr("msan-precise-disjoint-or", cl::desc("Precisely poison disjoint OR. If false (legacy behavior), " "disjointedness is ignored (i.e., 1|1 is initialized)."), cl::Hidden, cl::init(false))
static const MemoryMapParams Linux_S390X_MemoryMapParams
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< uint64_t > ClXorMask("msan-xor-mask", cl::desc("Define custom MSan XorMask"), cl::Hidden, cl::init(0))
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))
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> 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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton 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
front - Get the first element.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
void removeFnAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the function.
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getCalledOperand() const
Type * getParamElementType(unsigned ArgNo) const
Extract the elementtype type for a parameter.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
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)
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.
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...
LLVM_ABI bool isZeroValue() const
Return true if the value is negative zero or null value.
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
static bool shouldExecute(unsigned CounterName)
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.
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="")
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)
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
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.
LLVM_ABI CallInst * CreateAndReduce(Value *Src)
Create a vector int AND reduction intrinsic of the source vector.
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.
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 CallInst * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
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 CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
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 or truncated 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="")
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.
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)
StringRef - Represent a constant reference to a string, i.e.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Triple - Helper class for working with autoconf configuration names.
bool isMIPS64() const
Tests whether the target is MIPS 64-bit (little and big endian).
bool isRISCV32() const
Tests whether the target is 32-bit RISC-V.
bool isPPC32() const
Tests whether the target is 32-bit PowerPC (little and big endian).
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isLoongArch64() const
Tests whether the target is 64-bit LoongArch.
bool isMIPS32() const
Tests whether the target is MIPS 32-bit (little and big endian).
bool isARM() const
Tests whether the target is ARM (little and big endian).
bool isPPC64() const
Tests whether the target is 64-bit PowerPC (little and big endian).
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isSystemZ() const
Tests whether the target is SystemZ.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
bool isPPC_FP128Ty() const
Return true if this is powerpc long double.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
int getNumOccurrences() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
Function * Kernel
Summary of a kernel (=entry point for target offloading).
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI std::pair< Instruction *, Value * > SplitBlockAndInsertSimpleForLoop(Value *End, BasicBlock::iterator SplitBefore)
Insert a for (int i = 0; i < End; i++) loop structure (with the exception that End is assumed > 0,...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< df_iterator< T > > depth_first(const T &G)
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A CRTP mix-in to automatically provide informational APIs needed for passes.