LLVM: lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
17
42
43#include
44
45using namespace llvm;
46
47#define DEBUG_TYPE "nsan"
48
50 "Number of instrumented floating-point loads");
51
53 "Number of instrumented floating-point calls");
55 "Number of instrumented floating-point returns");
57 "Number of instrumented floating-point stores");
59 "Number of instrumented non floating-point stores");
61 NumInstrumentedNonFTMemcpyStores,
62 "Number of instrumented non floating-point stores with memcpy semantics");
63STATISTIC(NumInstrumentedFCmp, "Number of instrumented fcmps");
64
65
66
67
69 "nsan-shadow-type-mapping", cl::init("dqq"),
70 cl::desc("One shadow type id for each of `float`, `double`, `long double`. "
71 "`d`,`l`,`q`,`e` mean double, x86_fp80, fp128 (quad) and "
72 "ppc_fp128 (extended double) respectively. The default is to "
73 "shadow `float` as `double`, and `double` and `x86_fp80` as "
74 "`fp128`"),
76
79 cl::desc("Instrument floating-point comparisons"),
81
83 "check-functions-filter",
84 cl::desc("Only emit checks for arguments of functions "
85 "whose names match the given regular expression"),
87
89 "nsan-truncate-fcmp-eq", cl::init(true),
91 "This flag controls the behaviour of fcmp equality comparisons."
92 "For equality comparisons such as `x == 0.0f`, we can perform the "
93 "shadow check in the shadow (`x_shadow == 0.0) == (x == 0.0f)`) or app "
94 " domain (`(trunc(x_shadow) == 0.0f) == (x == 0.0f)`). This helps "
95 "catch the case when `x_shadow` is accurate enough (and therefore "
96 "close enough to zero) so that `trunc(x_shadow)` is zero even though "
97 "both `x` and `x_shadow` are not"),
99
100
101
102
103
104
105
106
107
108
110 cl::desc("Check floating-point load"),
112
114 cl::desc("Check floating-point stores"),
116
118 cl::desc("Check floating-point return values"),
120
121
122
123
124
125
126
128 "nsan-propagate-non-ft-const-stores-as-ft",
130 "Propagate non floating-point const stores as floating point values."
131 "For debugging purposes only"),
133
136
137
142
143namespace {
144
145
146
147class ShadowTypeConfig {
148public:
149 static std::unique_ptr fromNsanTypeId(char TypeId);
150
151
153
154
155 virtual char getNsanTypeId() const = 0;
156
157 virtual ~ShadowTypeConfig() = default;
158};
159
160template
161class ShadowTypeConfigImpl : public ShadowTypeConfig {
162public:
163 char getNsanTypeId() const override { return NsanTypeId; }
164 static constexpr char kNsanTypeId = NsanTypeId;
165};
166
167
168class F64ShadowConfig : public ShadowTypeConfigImpl<'d'> {
171 }
172};
173
174
175class F80ShadowConfig : public ShadowTypeConfigImpl<'l'> {
178 }
179};
180
181
182class F128ShadowConfig : public ShadowTypeConfigImpl<'q'> {
185 }
186};
187
188
189class PPC128ShadowConfig : public ShadowTypeConfigImpl<'e'> {
192 }
193};
194
195
196std::unique_ptr
197ShadowTypeConfig::fromNsanTypeId(const char TypeId) {
198 switch (TypeId) {
199 case F64ShadowConfig::kNsanTypeId:
200 return std::make_unique();
201 case F80ShadowConfig::kNsanTypeId:
202 return std::make_unique();
203 case F128ShadowConfig::kNsanTypeId:
204 return std::make_unique();
205 case PPC128ShadowConfig::kNsanTypeId:
206 return std::make_unique();
207 }
209}
210
211
212
213enum FTValueType { kFloat, kDouble, kLongDouble, kNumValueTypes };
214
215
216static std::optional ftValueTypeFromType(Type *FT) {
218 return kFloat;
220 return kDouble;
222 return kLongDouble;
223 return {};
224}
225
226
227static Type *typeFromFTValueType(FTValueType VT, LLVMContext &Context) {
228 switch (VT) {
229 case kFloat:
231 case kDouble:
233 case kLongDouble:
235 case kNumValueTypes:
236 return nullptr;
237 }
239}
240
241
242static const char *typeNameFromFTValueType(FTValueType VT) {
243 switch (VT) {
244 case kFloat:
245 return "float";
246 case kDouble:
247 return "double";
248 case kLongDouble:
249 return "longdouble";
250 case kNumValueTypes:
251 return nullptr;
252 }
254}
255
256
257
258class MappingConfig {
259public:
263 unsigned ShadowTypeSizeBits[kNumValueTypes];
264 for (int VT = 0; VT < kNumValueTypes; ++VT) {
265 auto Config = ShadowTypeConfig::fromNsanTypeId(ClShadowMapping[VT]);
266 if (!Config)
269 const unsigned AppTypeSize =
270 typeFromFTValueType(static_cast<FTValueType>(VT), Context)
271 ->getScalarSizeInBits();
272 const unsigned ShadowTypeSize =
273 Config->getType(Context)->getScalarSizeInBits();
274
275
276 if (ShadowTypeSize > kShadowScale * AppTypeSize)
278 "->f" + Twine(ShadowTypeSize) +
279 ": The shadow type size should be at most " +
281 " times the application type size");
282 ShadowTypeSizeBits[VT] = ShadowTypeSize;
283 Configs[VT] = std::move(Config);
284 }
285
286
287
288
289
290
291
292 if (ShadowTypeSizeBits[kFloat] > ShadowTypeSizeBits[kDouble] ||
293 ShadowTypeSizeBits[kDouble] > ShadowTypeSizeBits[kLongDouble])
295 Twine(ShadowTypeSizeBits[kFloat]) + "; double->f" +
296 Twine(ShadowTypeSizeBits[kDouble]) +
297 "; long double->f" +
298 Twine(ShadowTypeSizeBits[kLongDouble]) + " }");
299 }
300
301 const ShadowTypeConfig &byValueType(FTValueType VT) const {
302 assert(VT < FTValueType::kNumValueTypes && "invalid value type");
303 return *Configs[VT];
304 }
305
306
307 Type *getExtendedFPType(Type *FT) const {
308 if (const auto VT = ftValueTypeFromType(FT))
309 return Configs[*VT]->getType(Context);
312
313 if (VecTy->isScalableTy())
314 return nullptr;
315 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());
316 return ExtendedScalar
317 ? VectorType::get(ExtendedScalar, VecTy->getElementCount())
318 : nullptr;
319 }
320 return nullptr;
321 }
322
323private:
325 std::unique_ptr Configs[FTValueType::kNumValueTypes];
326};
327
328
329
330struct MemoryExtents {
333};
334
335static MemoryExtents getMemoryExtentsOrDie(Type *FT) {
336 if (const auto VT = ftValueTypeFromType(FT))
337 return {*VT, 1};
339 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());
340 return {ScalarExtents.ValueType,
341 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};
342 }
344}
345
346
347class CheckLoc {
348public:
349
350 static CheckLoc makeStore(Value *Address) {
351 CheckLoc Result(kStore);
352 Result.Address = Address;
353 return Result;
354 }
355 static CheckLoc makeLoad(Value *Address) {
356 CheckLoc Result(kLoad);
357 Result.Address = Address;
358 return Result;
359 }
360
361
362 static CheckLoc makeArg(int ArgId) {
363 CheckLoc Result(kArg);
364 Result.ArgId = ArgId;
365 return Result;
366 }
367
368
369 static CheckLoc makeRet() { return CheckLoc(kRet); }
370
371
372 static CheckLoc makeInsert() { return CheckLoc(kInsert); }
373
374
375
377 return ConstantInt::get(Type::getInt32Ty(C), static_cast<int>(CheckTy));
378 }
379
380
381
382
384 switch (CheckTy) {
385 case kUnknown:
387 case kRet:
388 case kInsert:
389 return ConstantInt::get(IntptrTy, 0);
390 case kArg:
391 return ConstantInt::get(IntptrTy, ArgId);
392 case kLoad:
393 case kStore:
394 return Builder.CreatePtrToInt(Address, IntptrTy);
395 }
397 }
398
399private:
400
401
403 kUnknown = 0,
404 kRet,
405 kArg,
406 kLoad,
407 kStore,
408 kInsert,
409 };
410 explicit CheckLoc(CheckType CheckTy) : CheckTy(CheckTy) {}
411
412 Value *Address = nullptr;
414 int ArgId = -1;
415};
416
417
418class ValueToShadowMap {
419public:
420 explicit ValueToShadowMap(const MappingConfig &Config) : Config(Config) {}
421
422 ValueToShadowMap(const ValueToShadowMap &) = delete;
423 ValueToShadowMap &operator=(const ValueToShadowMap &) = delete;
424
425
426
427 void setShadow(Value &V, Value &Shadow) {
428 [[maybe_unused]] const bool Inserted = Map.try_emplace(&V, &Shadow).second;
430 if (!Inserted) {
432 errs() << I->getFunction()->getName() << ": ";
433 errs() << "duplicate shadow (" << &V << "): ";
434 V.dump();
435 }
436 });
437 assert(Inserted && "duplicate shadow");
438 }
439
440
441
443
444
445
448 return getShadowConstant(C);
449 return Map.find(V)->second;
450 }
451
452 bool empty() const { return Map.empty(); }
453
454private:
455
457 bool LosesInfo = false;
459 return CV;
460 }
461
462
465 return UndefValue::get(Config.getExtendedFPType(U->getType()));
466 }
468
469 Type *Ty = Config.getExtendedFPType(CFP->getType());
470 return ConstantFP::get(
471 Ty, extendConstantFP(CFP->getValueAPF(),
472 Ty->getScalarType()->getFltSemantics()));
473 }
474
475 if (C->getType()->isVectorTy()) {
478 ->getElementCount()
479 .getFixedValue();
481 Elements.push_back(getShadowConstant(C->getAggregateElement(I)));
483 }
485 }
486
487 const MappingConfig &Config;
489};
490
491class NsanMemOpFn {
492public:
494 size_t NumArgs);
497
498private:
500 size_t NumSizedFuncs;
501};
502
506 AttributeList Attr;
507 Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);
510 IntegerType *IntptrTy = M.getDataLayout().getIntPtrType(Ctx);
512
513 NumSizedFuncs = Sized.size();
514
515
516 if (NumArgs == 3) {
517 Funcs.push_back(
518 M.getOrInsertFunction(Fallback, Attr, VoidTy, PtrTy, PtrTy, IntptrTy));
520 } else if (NumArgs == 2) {
521 Funcs.push_back(
522 M.getOrInsertFunction(Fallback, Attr, VoidTy, PtrTy, IntptrTy));
524 } else {
525 llvm_unreachable("Unexpected value of sized functions arguments");
526 }
527
528 for (size_t i = 0; i < NumSizedFuncs; ++i)
529 Funcs.push_back(M.getOrInsertFunction(Sized[i], SizedFnTy, Attr));
530}
531
533
534
535 assert(NumSizedFuncs >= 3 && "Unexpected number of sized functions");
536
537 size_t Idx =
538 MemOpSize == 4 ? 1 : (MemOpSize == 8 ? 2 : (MemOpSize == 16 ? 3 : 0));
539
540 return Funcs[Idx];
541}
542
543FunctionCallee NsanMemOpFn::getFallback() const { return Funcs[0]; }
544
545
546
547
548
549class NumericalStabilitySanitizer {
550public:
551 NumericalStabilitySanitizer(Module &M);
553
554private:
556 void maybeAddSuffixForNsanInterface(CallBase *CI);
557 bool addrPointsToConstantData(Value *Addr);
559 ValueToShadowMap &Map);
560 Value *createShadowValueWithOperandsAvailable(Instruction &Inst,
562 const ValueToShadowMap &Map);
565 ValueToShadowMap &Map);
566
568 const ValueToShadowMap &Map);
569
571 const ValueToShadowMap &Map);
573 CheckLoc Loc);
575 CheckLoc Loc);
576 void emitFCmpCheck(FCmpInst &FCmp, const ValueToShadowMap &Map);
577
578
582 const ValueToShadowMap &Map, IRBuilder<> &Builder);
585 const ValueToShadowMap &Map,
588 const ValueToShadowMap &Map, IRBuilder<> &Builder);
590 const ValueToShadowMap &Map, IRBuilder<> &Builder);
591
592
593 void propagateFTStore(StoreInst &Store, Type *VT, Type *ExtendedVT,
594 const ValueToShadowMap &Map);
595 void propagateNonFTStore(StoreInst &Store, Type *VT,
596 const ValueToShadowMap &Map);
597
600 MappingConfig Config;
602
603
604 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};
605 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};
606 FunctionCallee NsanCheckValue[FTValueType::kNumValueTypes] = {};
607 FunctionCallee NsanFCmpFail[FTValueType::kNumValueTypes] = {};
608
609 NsanMemOpFn NsanCopyFns;
610 NsanMemOpFn NsanSetUnknownFns;
611
615
616 Type *NsanShadowRetType = nullptr;
618
619 GlobalValue *NsanShadowArgsTag = nullptr;
620
621 Type *NsanShadowArgsType = nullptr;
622 GlobalValue *NsanShadowArgsPtr = nullptr;
623
624 std::optional CheckFunctionsFilter;
625};
626}
627
628PreservedAnalyses
632 {},
633
634
636
637 NumericalStabilitySanitizer Nsan(M);
641
643}
644
646 return M.getOrInsertGlobal(Name, Ty, [&M, Ty, Name] {
648 nullptr, Name, nullptr,
650 });
651}
652
653NumericalStabilitySanitizer::NumericalStabilitySanitizer(Module &M)
655 NsanCopyFns(M, {"__nsan_copy_4", "__nsan_copy_8", "__nsan_copy_16"},
656 "__nsan_copy_values", 3),
657 NsanSetUnknownFns(M,
658 {"__nsan_set_value_unknown_4",
659 "__nsan_set_value_unknown_8",
660 "__nsan_set_value_unknown_16"},
661 "__nsan_set_value_unknown", 2) {
662 IntptrTy = DL.getIntPtrType(Context);
667
668 AttributeList Attr;
669 Attr = Attr.addFnAttribute(Context, Attribute::NoUnwind);
670
671 for (int I = 0; I < kNumValueTypes; ++I) {
672 const FTValueType VT = static_cast<FTValueType>(I);
673 const char *VTName = typeNameFromFTValueType(VT);
674 Type *VTTy = typeFromFTValueType(VT, Context);
675
676
677 const std::string GetterPrefix =
678 std::string("__nsan_get_shadow_ptr_for_") + VTName;
679 NsanGetShadowPtrForStore[VT] = M.getOrInsertFunction(
680 GetterPrefix + "_store", Attr, PtrTy, PtrTy, IntptrTy);
681 NsanGetShadowPtrForLoad[VT] = M.getOrInsertFunction(
682 GetterPrefix + "_load", Attr, PtrTy, PtrTy, IntptrTy);
683
684
685 const auto &ShadowConfig = Config.byValueType(VT);
686 Type *ShadowTy = ShadowConfig.getType(Context);
687 NsanCheckValue[VT] =
688 M.getOrInsertFunction(std::string("__nsan_internal_check_") + VTName +
689 "_" + ShadowConfig.getNsanTypeId(),
691 NsanFCmpFail[VT] = M.getOrInsertFunction(
692 std::string("__nsan_fcmp_fail_") + VTName + "_" +
693 ShadowConfig.getNsanTypeId(),
694 Attr, VoidTy, VTTy, VTTy, ShadowTy, ShadowTy, Int32Ty, Int1Ty, Int1Ty);
695 }
696
697
698 NsanGetRawShadowTypePtr = M.getOrInsertFunction(
699 "__nsan_internal_get_raw_shadow_type_ptr", Attr, PtrTy, PtrTy);
700 NsanGetRawShadowPtr = M.getOrInsertFunction(
701 "__nsan_internal_get_raw_shadow_ptr", Attr, PtrTy, PtrTy);
702
703 NsanShadowRetTag = createThreadLocalGV("__nsan_shadow_ret_tag", M, IntptrTy);
704
707 NsanShadowRetPtr =
709
710 NsanShadowArgsTag =
712
713 NsanShadowArgsType =
716
717 NsanShadowArgsPtr =
719
722 std::string RegexError;
723 assert(R.isValid(RegexError));
724 CheckFunctionsFilter = std::move(R);
725 }
726}
727
728
729
730bool NumericalStabilitySanitizer::addrPointsToConstantData(Value *Addr) {
731
733 Addr = GEP->getPointerOperand();
734
736 return GV->isConstant();
737 return false;
738}
739
740
741
742
743
744
745
746
747
748
749
750
751
752void NumericalStabilitySanitizer::createShadowArguments(
753 Function &F, const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
754 assert(.getIntrinsicID() && "found a definition of an intrinsic");
755
756
757 if (all_of(F.args(), [this](const Argument &Arg) {
758 return Config.getExtendedFPType(Arg.getType()) == nullptr;
759 }))
760 return;
761
762 IRBuilder<> Builder(&F.getEntryBlock(), F.getEntryBlock().getFirstNonPHIIt());
763
764
765 Value *HasShadowArgs = Builder.CreateICmpEQ(
766 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag, false),
767 Builder.CreatePtrToInt(&F, IntptrTy));
768
769 unsigned ShadowArgsOffsetBytes = 0;
770 for (Argument &Arg : F.args()) {
772 Type *ExtendedVT = Config.getExtendedFPType(VT);
773 if (ExtendedVT == nullptr)
774 continue;
775 Value *L = Builder.CreateAlignedLoad(
776 ExtendedVT,
777 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
778 ShadowArgsOffsetBytes),
779 Align(1), false);
780 Value *Shadow = Builder.CreateSelect(HasShadowArgs, L,
781 Builder.CreateFPExt(&Arg, ExtendedVT));
782 Map.setShadow(Arg, *Shadow);
783 TypeSize SlotSize = DL.getTypeStoreSize(ExtendedVT);
785 ShadowArgsOffsetBytes += SlotSize;
786 }
787 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);
788}
789
790
791
793 const std::optional &CheckFunctionsFilter) {
794
796
797 if (CheckFunctionsFilter) {
798
799 if (Fn == nullptr)
800 return false;
801 if (CheckFunctionsFilter->match(Fn->getName()))
802 return true;
803 return false;
804 }
805
806 if (Fn == nullptr)
807 return true;
808
809
811 return false;
812
814 LibFunc LFunc = LibFunc::NotLibFunc;
815
817 return true;
818
819
820
821
822 if (ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||
823 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)
824 for (const auto &U : CI.users())
826 return false;
827
828 return true;
829}
830
831
832
833void NumericalStabilitySanitizer::populateShadowStack(
834 CallBase &CI, const TargetLibraryInfo &TLI, const ValueToShadowMap &Map) {
835
837 return;
838
839
841 return Config.getExtendedFPType(Arg->getType()) == nullptr;
842 }))
843 return;
844
846 SmallVector<Value *, 8> ArgShadows;
847 const bool ShouldCheckArgs = shouldCheckArgs(CI, TLI, CheckFunctionsFilter);
849 if (Config.getExtendedFPType(Arg->getType()) == nullptr)
850 continue;
851 Value *ArgShadow = Map.getShadow(Arg);
852 ArgShadows.push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,
853 CheckLoc::makeArg(ArgIdx))
854 : ArgShadow);
855 }
856
857
859 LibFunc LFunc;
860 if (Fn->isIntrinsic() || TLI.getLibFunc(*Fn, LFunc))
861 return;
862 }
863
864
865 Builder.CreateStore(CI.getCalledOperand(), NsanShadowArgsTag);
867
868 unsigned ShadowArgId = 0;
871 Type *ExtendedVT = Config.getExtendedFPType(VT);
872 if (ExtendedVT == nullptr)
873 continue;
874 Builder.CreateAlignedStore(
875 ArgShadows[ShadowArgId++],
876 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
877 ShadowArgsOffsetBytes),
878 Align(1), false);
879 TypeSize SlotSize = DL.getTypeStoreSize(ExtendedVT);
881 ShadowArgsOffsetBytes += SlotSize;
882 }
883}
884
885
886
887
892
893Value *NumericalStabilitySanitizer::emitCheckInternal(Value *V, Value *ShadowV,
895 CheckLoc Loc) {
896
898 return ConstantInt::get(
901
903 if (const auto VT = ftValueTypeFromType(Ty))
905 NsanCheckValue[*VT],
906 {V, ShadowV, Loc.getType(Context), Loc.getValue(IntptrTy, Builder)});
907
910
911
912 assert(!VecTy->isScalableTy() &&
913 "Scalable vector types are not supported yet");
914 Value *CheckResult = nullptr;
915 for (int I = 0, E = VecTy->getElementCount().getFixedValue(); I < E; ++I) {
916
917
918
921 Value *ComponentCheckResult =
922 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
923 CheckResult = CheckResult
924 ? Builder.CreateOr(CheckResult, ComponentCheckResult)
925 : ComponentCheckResult;
926 }
927 return CheckResult;
928 }
930 Value *CheckResult = nullptr;
934 Value *ComponentCheckResult =
935 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
936 CheckResult = CheckResult
937 ? Builder.CreateOr(CheckResult, ComponentCheckResult)
938 : ComponentCheckResult;
939 }
940 return CheckResult;
941 }
943 Value *CheckResult = nullptr;
946 continue;
949 Value *ComponentCheckResult =
950 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
951 CheckResult = CheckResult
952 ? Builder.CreateOr(CheckResult, ComponentCheckResult)
953 : ComponentCheckResult;
954 }
955 if (!CheckResult)
956 return ConstantInt::get(
959 return CheckResult;
960 }
961
963}
964
965
966
967
968
969
970
971Value *NumericalStabilitySanitizer::emitCheck(Value *V, Value *ShadowV,
973 CheckLoc Loc) {
974
976 return ShadowV;
977
979 Function *F = Inst->getFunction();
980 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(F->getName())) {
981 return ShadowV;
982 }
983 }
984
985 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
987 CheckResult,
988 ConstantInt::get(Builder.getInt32Ty(),
991 ICmpEQ, Builder.CreateFPExt(V, Config.getExtendedFPType(V->getType())),
992 ShadowV);
993}
994
995
996
997void NumericalStabilitySanitizer::emitFCmpCheck(FCmpInst &FCmp,
998 const ValueToShadowMap &Map) {
1000 return;
1001
1003 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(F->getName()))
1004 return;
1005
1007 if (Config.getExtendedFPType(LHS->getType()) == nullptr)
1008 return;
1010
1011
1012
1015
1019
1020
1022 FCmpBuilder.SetCurrentDebugLocation(FCmp.getDebugLoc());
1025
1028 ShadowLHS = FCmpBuilder.CreateFPExt(
1029 FCmpBuilder.CreateFPTrunc(ShadowLHS, LHS->getType()), Ty);
1030 ShadowRHS = FCmpBuilder.CreateFPExt(
1031 FCmpBuilder.CreateFPTrunc(ShadowRHS, RHS->getType()), Ty);
1032 }
1033 Value *ShadowFCmp =
1034 FCmpBuilder.CreateFCmp(FCmp.getPredicate(), ShadowLHS, ShadowRHS);
1035 Value *OriginalAndShadowFcmpMatch =
1036 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
1037
1039
1040
1041
1042 OriginalAndShadowFcmpMatch =
1043 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
1044 }
1045
1046
1047
1048 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
1049 MDBuilder(Context).createLikelyBranchWeights());
1050
1051
1053 FailBuilder.SetCurrentDebugLocation(FCmp.getDebugLoc());
1054
1055 const auto EmitFailCall = [this, &FCmp, &FCmpBuilder,
1058 Value *ShadowResult) {
1060 FunctionCallee *Callee = nullptr;
1062 Callee = &(NsanFCmpFail[kFloat]);
1064 Callee = &(NsanFCmpFail[kDouble]);
1066
1067 Callee = &(NsanFCmpFail[kDouble]);
1068 L = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(Context));
1069 R = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(Context));
1070 } else {
1072 }
1073 FailBuilder.CreateCall(*Callee, {L, R, ShadowL, ShadowR,
1074 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1076 Result, ShadowResult});
1077 };
1080 ->getElementCount()
1081 .getFixedValue();
1083 Value *ExtractLHS = FailBuilder.CreateExtractElement(LHS, I);
1084 Value *ExtractRHS = FailBuilder.CreateExtractElement(RHS, I);
1085 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS, I);
1086 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS, I);
1087 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp, I);
1088 Value *ExtractShadowFCmp =
1089 FailBuilder.CreateExtractElement(ShadowFCmp, I);
1090 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1091 ExtractFCmp, ExtractShadowFCmp);
1092 }
1093 } else {
1094 EmitFailCall(LHS, RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1095 }
1096 FailBuilder.CreateBr(NextBB);
1097
1098 ++NumInstrumentedFCmp;
1099}
1100
1101
1102PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1103 PHINode &Phi, const TargetLibraryInfo &TLI) {
1104 Type *VT = Phi.getType();
1105 Type *ExtendedVT = Config.getExtendedFPType(VT);
1106 if (ExtendedVT == nullptr)
1107 return nullptr;
1108
1109
1110
1111 PHINode *Shadow = PHINode::Create(ExtendedVT, Phi.getNumIncomingValues());
1113 return Shadow;
1114}
1115
1116Value *NumericalStabilitySanitizer::handleLoad(LoadInst &Load, Type *VT,
1117 Type *ExtendedVT) {
1120 if (addrPointsToConstantData(Load.getPointerOperand())) {
1121
1122
1123 return Builder.CreateFPExt(&Load, ExtendedVT);
1124 }
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140 const auto Extents = getMemoryExtentsOrDie(VT);
1142 NsanGetShadowPtrForLoad[Extents.ValueType],
1143 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1144 ++NumInstrumentedFTLoads;
1145
1146
1149
1154
1155
1156
1157 {
1159 IRBuilder<> LoadBBBuilder(LoadBB);
1160 LoadBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1161 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1162 ShadowLoadBB);
1163 }
1164
1165
1166 IRBuilder<> ShadowLoadBBBuilder(ShadowLoadBB);
1167 ShadowLoadBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1168 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1169 ExtendedVT, ShadowPtr, Align(1), Load.isVolatile());
1171 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,
1172 CheckLoc::makeLoad(Load.getPointerOperand()));
1173 }
1174 ShadowLoadBBBuilder.CreateBr(NextBB);
1175
1176
1178 FExtBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1179 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);
1180 FExtBBBuilder.CreateBr(NextBB);
1181
1182
1184 NextBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1185 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1186 ShadowPhi->addIncoming(ShadowLoad, ShadowLoadBB);
1188 return ShadowPhi;
1189}
1190
1191Value *NumericalStabilitySanitizer::handleTrunc(const FPTruncInst &Trunc,
1193 const ValueToShadowMap &Map,
1196 Type *OrigSourceTy = OrigSource->getType();
1197 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230 Value *Source = ExtendedSourceTy ? Map.getShadow(OrigSource) : OrigSource;
1231 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1232
1233 if (SourceTy == ExtendedVT)
1235
1236 return Builder.CreateFPTrunc(Source, ExtendedVT);
1237}
1238
1239Value *NumericalStabilitySanitizer::handleExt(const FPExtInst &Ext, Type *VT,
1240 Type *ExtendedVT,
1241 const ValueToShadowMap &Map,
1244 Type *OrigSourceTy = OrigSource->getType();
1245 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 Value *Source = ExtendedSourceTy ? Map.getShadow(OrigSource) : OrigSource;
1278 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1279
1280 if (SourceTy == ExtendedVT)
1282
1283 return Builder.CreateFPExt(Source, ExtendedVT);
1284}
1285
1286namespace {
1287
1288struct KnownIntrinsic {
1289 struct WidenedIntrinsic {
1290 const char *NarrowName;
1292 using FnTypeFactory = FunctionType *(*)(LLVMContext &);
1293 FnTypeFactory MakeFnTy;
1294 };
1295
1296 static const char *get(LibFunc LFunc);
1297
1298
1299
1300
1301
1302
1303 static const WidenedIntrinsic *widen(StringRef Name);
1304
1305private:
1306 struct LFEntry {
1307 LibFunc LFunc;
1308 const char *IntrinsicName;
1309 };
1310 static const LFEntry kLibfuncIntrinsics[];
1311
1312 static const WidenedIntrinsic kWidenedIntrinsics[];
1313};
1314}
1315
1319
1324
1329
1335
1340
1346
1353
1360
1361const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1362
1363
1364
1365
1366
1367
1368
1369
1401
1403
1405
1407
1439 {"llvm.nearbyint.f32", Intrinsic::nearbyint, makeDoubleDouble},
1457};
1458
1459const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1460 {LibFunc_sqrtf, "llvm.sqrt.f32"},
1461 {LibFunc_sqrt, "llvm.sqrt.f64"},
1462 {LibFunc_sqrtl, "llvm.sqrt.f80"},
1463 {LibFunc_sinf, "llvm.sin.f32"},
1464 {LibFunc_sin, "llvm.sin.f64"},
1465 {LibFunc_sinl, "llvm.sin.f80"},
1466 {LibFunc_cosf, "llvm.cos.f32"},
1467 {LibFunc_cos, "llvm.cos.f64"},
1468 {LibFunc_cosl, "llvm.cos.f80"},
1469 {LibFunc_powf, "llvm.pow.f32"},
1470 {LibFunc_pow, "llvm.pow.f64"},
1471 {LibFunc_powl, "llvm.pow.f80"},
1472 {LibFunc_expf, "llvm.exp.f32"},
1473 {LibFunc_exp, "llvm.exp.f64"},
1474 {LibFunc_expl, "llvm.exp.f80"},
1475 {LibFunc_exp2f, "llvm.exp2.f32"},
1476 {LibFunc_exp2, "llvm.exp2.f64"},
1477 {LibFunc_exp2l, "llvm.exp2.f80"},
1478 {LibFunc_logf, "llvm.log.f32"},
1479 {LibFunc_log, "llvm.log.f64"},
1480 {LibFunc_logl, "llvm.log.f80"},
1481 {LibFunc_log10f, "llvm.log10.f32"},
1482 {LibFunc_log10, "llvm.log10.f64"},
1483 {LibFunc_log10l, "llvm.log10.f80"},
1484 {LibFunc_log2f, "llvm.log2.f32"},
1485 {LibFunc_log2, "llvm.log2.f64"},
1486 {LibFunc_log2l, "llvm.log2.f80"},
1487 {LibFunc_fabsf, "llvm.fabs.f32"},
1488 {LibFunc_fabs, "llvm.fabs.f64"},
1489 {LibFunc_fabsl, "llvm.fabs.f80"},
1490 {LibFunc_copysignf, "llvm.copysign.f32"},
1491 {LibFunc_copysign, "llvm.copysign.f64"},
1492 {LibFunc_copysignl, "llvm.copysign.f80"},
1493 {LibFunc_floorf, "llvm.floor.f32"},
1494 {LibFunc_floor, "llvm.floor.f64"},
1495 {LibFunc_floorl, "llvm.floor.f80"},
1496 {LibFunc_fmaxf, "llvm.maxnum.f32"},
1497 {LibFunc_fmax, "llvm.maxnum.f64"},
1498 {LibFunc_fmaxl, "llvm.maxnum.f80"},
1499 {LibFunc_fminf, "llvm.minnum.f32"},
1500 {LibFunc_fmin, "llvm.minnum.f64"},
1501 {LibFunc_fminl, "llvm.minnum.f80"},
1502 {LibFunc_ceilf, "llvm.ceil.f32"},
1503 {LibFunc_ceil, "llvm.ceil.f64"},
1504 {LibFunc_ceill, "llvm.ceil.f80"},
1505 {LibFunc_truncf, "llvm.trunc.f32"},
1506 {LibFunc_trunc, "llvm.trunc.f64"},
1507 {LibFunc_truncl, "llvm.trunc.f80"},
1508 {LibFunc_rintf, "llvm.rint.f32"},
1509 {LibFunc_rint, "llvm.rint.f64"},
1510 {LibFunc_rintl, "llvm.rint.f80"},
1511 {LibFunc_nearbyintf, "llvm.nearbyint.f32"},
1512 {LibFunc_nearbyint, "llvm.nearbyint.f64"},
1513 {LibFunc_nearbyintl, "llvm.nearbyint.f80"},
1514 {LibFunc_roundf, "llvm.round.f32"},
1515 {LibFunc_round, "llvm.round.f64"},
1516 {LibFunc_roundl, "llvm.round.f80"},
1517};
1518
1519const char *KnownIntrinsic::get(LibFunc LFunc) {
1520 for (const auto &E : kLibfuncIntrinsics) {
1521 if (E.LFunc == LFunc)
1522 return E.IntrinsicName;
1523 }
1524 return nullptr;
1525}
1526
1527const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(StringRef Name) {
1528 for (const auto &E : kWidenedIntrinsics) {
1529 if (E.NarrowName == Name)
1530 return &E;
1531 }
1532 return nullptr;
1533}
1534
1535
1538 LibFunc LFunc;
1540 return nullptr;
1541
1542 if (const char *Name = KnownIntrinsic::get(LFunc))
1543 return Name;
1544
1546 return nullptr;
1547}
1548
1549
1550Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1551 CallBase &Call, Type *VT, Type *ExtendedVT, const TargetLibraryInfo &TLI,
1552 const ValueToShadowMap &Map, IRBuilder<> &Builder) {
1554 if (Fn == nullptr)
1555 return nullptr;
1556
1558 FunctionType *WidenedFnTy = nullptr;
1560 const auto *Widened = KnownIntrinsic::widen(Fn->getName());
1561 if (Widened) {
1562 WidenedId = Widened->ID;
1563 WidenedFnTy = Widened->MakeFnTy(Context);
1564 } else {
1565
1566
1567
1568 WidenedId = ID;
1570 }
1572
1573
1574 const auto *Widened = KnownIntrinsic::widen(Name);
1575 assert(Widened && "make sure KnownIntrinsic entries are consistent");
1576 WidenedId = Widened->ID;
1577 WidenedFnTy = Widened->MakeFnTy(Context);
1578 } else {
1579
1580 return nullptr;
1581 }
1582
1583
1591 "invalid widened intrinsic");
1592
1593
1595
1599 Type *IntrinsicArgTy = WidenedFnTy->getParamType(I);
1600 if (OrigArgTy == IntrinsicArgTy) {
1601 Args.push_back(Arg);
1602 continue;
1603 }
1604 Type *ShadowArgTy = Config.getExtendedFPType(Arg->getType());
1605 assert(ShadowArgTy &&
1606 "don't know how to get the shadow value for a non-FT");
1607 Value *Shadow = Map.getShadow(Arg);
1608 if (ShadowArgTy == IntrinsicArgTy) {
1609
1611 Args.push_back(Shadow);
1612 continue;
1613 }
1614
1616 }
1618 return WidenedFnTy->getReturnType() == ExtendedVT
1619 ? IntrinsicCall
1620 : Builder.CreateFPExt(IntrinsicCall, ExtendedVT);
1621}
1622
1623
1624
1625Value *NumericalStabilitySanitizer::handleCallBase(CallBase &Call, Type *VT,
1626 Type *ExtendedVT,
1627 const TargetLibraryInfo &TLI,
1628 const ValueToShadowMap &Map,
1630
1633
1634
1635
1636
1638 maybeHandleKnownCallBase(Call, VT, ExtendedVT, TLI, Map, Builder))
1639 return V;
1640
1641
1642
1644 Builder.CreateLoad(IntptrTy, NsanShadowRetTag, false);
1647
1649 ExtendedVT,
1650 Builder.CreateConstGEP2_64(NsanShadowRetType, NsanShadowRetPtr, 0, 0),
1651 false);
1652 Value *Shadow = Builder.CreateSelect(HasShadowRet, ShadowRetVal,
1654 ++NumInstrumentedFTCalls;
1655 return Shadow;
1656}
1657
1658
1659
1660Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1661 Instruction &Inst, const TargetLibraryInfo &TLI,
1662 const ValueToShadowMap &Map) {
1664 Type *ExtendedVT = Config.getExtendedFPType(VT);
1665 assert(ExtendedVT != nullptr && "trying to create a shadow for a non-FT");
1666
1668 return handleLoad(*Load, VT, ExtendedVT);
1669
1671
1675 return handleCallBase(*Call, VT, ExtendedVT, TLI, Map, Builder);
1676 }
1677
1679
1680
1681 BasicBlock *InvokeBB = Invoke->getParent();
1682 BasicBlock *NextBB = Invoke->getNormalDest();
1686
1689 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1692 return Shadow;
1693 }
1694
1697
1699 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1701 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1702
1704 return Builder.CreateUnOp(UnaryOp->getOpcode(),
1705 Map.getShadow(UnaryOp->getOperand(0)));
1706
1708 return Builder.CreateBinOp(BinOp->getOpcode(),
1709 Map.getShadow(BinOp->getOperand(0)),
1710 Map.getShadow(BinOp->getOperand(1)));
1711
1714 return Builder.CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1715 ExtendedVT);
1716 }
1717
1719 return Builder.CreateSelect(S->getCondition(),
1720 Map.getShadow(S->getTrueValue()),
1721 Map.getShadow(S->getFalseValue()));
1722
1724 return Builder.CreateFreeze(Map.getShadow(Freeze->getOperand(0)));
1725
1728 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1729
1732 Map.getShadow(Insert->getOperand(1)),
1733 Insert->getOperand(2));
1734
1737 Map.getShadow(Shuffle->getOperand(1)),
1738 Shuffle->getShuffleMask());
1739
1740
1742 return Builder.CreateFPExt(Extract, ExtendedVT);
1743
1745 return Builder.CreateFPExt(BC, ExtendedVT);
1746
1749}
1750
1751
1752
1753
1754
1755void NumericalStabilitySanitizer::maybeCreateShadowValue(
1756 Instruction &Root, const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
1758 Type *ExtendedVT = Config.getExtendedFPType(VT);
1759 if (ExtendedVT == nullptr)
1760 return;
1761
1762 if (Map.hasShadow(&Root))
1763 return;
1764
1765 assert((Root) && "phi nodes should already have shadows");
1766
1767 std::vector<Instruction *> DfsStack(1, &Root);
1768 while (!DfsStack.empty()) {
1769
1770
1772
1773
1775 DfsStack.pop_back();
1776 continue;
1777 }
1778
1779 bool MissingShadow = false;
1780 for (Value *Op : I->operands()) {
1781 Type *VT = Op->getType();
1782 if (!Config.getExtendedFPType(VT))
1783 continue;
1785 continue;
1786 MissingShadow = true;
1788 }
1789 if (MissingShadow)
1790 continue;
1791
1792
1793 Value *Shadow = createShadowValueWithOperandsAvailable(*I, TLI, Map);
1794 Map.setShadow(*I, *Shadow);
1795 DfsStack.pop_back();
1796 }
1797}
1798
1799
1800void NumericalStabilitySanitizer::propagateFTStore(
1801 StoreInst &Store, Type *VT, Type *ExtendedVT, const ValueToShadowMap &Map) {
1802 Value *StoredValue = Store.getValueOperand();
1805 const auto Extents = getMemoryExtentsOrDie(VT);
1807 NsanGetShadowPtrForStore[Extents.ValueType],
1808 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1809
1810 Value *StoredShadow = Map.getShadow(StoredValue);
1811 if (.getParent()->getParent()->hasOptNone()) {
1812
1813
1815 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1816 CheckLoc::makeStore(Store.getPointerOperand()));
1817 ++NumInstrumentedFTStores;
1818 }
1819 }
1820
1822 Store.isVolatile());
1823}
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833void NumericalStabilitySanitizer::propagateNonFTStore(
1834 StoreInst &Store, Type *VT, const ValueToShadowMap &Map) {
1835 Value *PtrOp = Store.getPointerOperand();
1838 Value *Dst = PtrOp;
1839 TypeSize SlotSize = DL.getTypeStoreSize(VT);
1841 const auto LoadSizeBytes = SlotSize.getFixedValue();
1844
1845 ++NumInstrumentedNonFTStores;
1846 Value *StoredValue = Store.getValueOperand();
1848
1849
1850
1851
1852
1853 Type *ShadowTypeIntTy = Type::getIntNTy(Context, 8 * LoadSizeBytes);
1854 Type *ShadowValueIntTy =
1858 Value *LoadSrc = Load->getPointerOperand();
1859
1860
1861
1862
1863
1864 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1865 ShadowTypeIntTy,
1866 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}), Align(1),
1867 false);
1868 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1869 ShadowValueIntTy,
1870 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}), Align(1),
1871 false);
1872
1873
1875 RawShadowType, Builder.CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1877 false);
1879 Builder.CreateCall(NsanGetRawShadowPtr, {Dst}),
1881 false);
1882
1883 ++NumInstrumentedNonFTMemcpyStores;
1884 return;
1885 }
1886
1889
1890
1891 Type *BitcastTy = nullptr;
1893 switch (CInt->getType()->getScalarSizeInBits()) {
1894 case 32:
1895 BitcastTy = Type::getFloatTy(Context);
1896 break;
1897 case 64:
1898 BitcastTy = Type::getDoubleTy(Context);
1899 break;
1900 case 80:
1901 BitcastTy = Type::getX86_FP80Ty(Context);
1902 break;
1903 default:
1904 break;
1905 }
1907 const int NumElements =
1908 cast(CDV->getType())->getElementCount().getFixedValue();
1909 switch (CDV->getType()->getScalarSizeInBits()) {
1910 case 32:
1911 BitcastTy =
1912 VectorType::get(Type::getFloatTy(Context), NumElements, false);
1913 break;
1914 case 64:
1915 BitcastTy =
1916 VectorType::get(Type::getDoubleTy(Context), NumElements, false);
1917 break;
1918 case 80:
1919 BitcastTy =
1920 VectorType::get(Type::getX86_FP80Ty(Context), NumElements, false);
1921 break;
1922 default:
1923 break;
1924 }
1925 }
1926 if (BitcastTy) {
1927 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1929 NsanGetShadowPtrForStore[Extents.ValueType],
1930 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1931
1932 Type *ExtVT = Config.getExtendedFPType(BitcastTy);
1936 Store.isVolatile());
1937 return;
1938 }
1939 }
1940
1941 Builder.CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});
1942}
1943
1944void NumericalStabilitySanitizer::propagateShadowValues(
1945 Instruction &Inst, const TargetLibraryInfo &TLI,
1946 const ValueToShadowMap &Map) {
1948 Value *StoredValue = Store->getValueOperand();
1950 Type *ExtendedVT = Config.getExtendedFPType(VT);
1951 if (ExtendedVT == nullptr)
1952 return propagateNonFTStore(*Store, VT, Map);
1953 return propagateFTStore(*Store, VT, ExtendedVT, Map);
1954 }
1955
1957 emitFCmpCheck(*FCmp, Map);
1958 return;
1959 }
1960
1962 maybeAddSuffixForNsanInterface(CB);
1966 instrumentMemIntrinsic(MI);
1967 return;
1968 }
1969 populateShadowStack(*CB, TLI, Map);
1970 return;
1971 }
1972
1975 return;
1976
1977 Value *RV = RetInst->getReturnValue();
1978 if (RV == nullptr)
1979 return;
1981 Type *ExtendedVT = Config.getExtendedFPType(VT);
1982 if (ExtendedVT == nullptr)
1983 return;
1984 Value *RVShadow = Map.getShadow(RV);
1986
1987 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1988 ++NumInstrumentedFTRets;
1989
1992 Builder.CreateStore(FnAddr, NsanShadowRetTag);
1993
1994 Value *ShadowRetValPtr =
1995 Builder.CreateConstGEP2_64(NsanShadowRetType, NsanShadowRetPtr, 0, 0);
1996 Builder.CreateStore(RVShadow, ShadowRetValPtr);
1997 return;
1998 }
1999
2003 Type *ExtendedVT = Config.getExtendedFPType(VT);
2004 if (ExtendedVT == nullptr)
2005 return;
2007 emitCheck(V, Map.getShadow(V), Builder, CheckLoc::makeInsert());
2008 return;
2009 }
2010}
2011
2012
2013
2014
2016 std::vector<Instruction *> &Instructions) {
2018#define MOVE_FLAG(attr, setter) \
2019 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
2020 F.removeFnAttr(attr); \
2021 FMF.set##setter(); \
2022 }
2023 MOVE_FLAG("no-infs-fp-math", NoInfs)
2024 MOVE_FLAG("no-nans-fp-math", NoNaNs)
2025 MOVE_FLAG("no-signed-zeros-fp-math", NoSignedZeros)
2026#undef MOVE_FLAG
2027
2030 I->setFastMathFlags(FMF);
2031}
2032
2033bool NumericalStabilitySanitizer::sanitizeFunction(
2034 Function &F, const TargetLibraryInfo &TLI) {
2035 if (.hasFnAttribute(Attribute::SanitizeNumericalStability) ||
2036 F.isDeclaration())
2037 return false;
2038
2039
2040
2042 return false;
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132 std::vector<Instruction *> OriginalInstructions;
2133 for (BasicBlock &BB : F)
2134 for (Instruction &Inst : BB)
2135 OriginalInstructions.emplace_back(&Inst);
2136
2138 ValueToShadowMap ValueToShadow(Config);
2139
2140
2141
2142
2143 std::vector<PHINode *> OriginalPhis;
2144 createShadowArguments(F, TLI, ValueToShadow);
2145 for (Instruction *I : OriginalInstructions) {
2147 if (PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2148 OriginalPhis.push_back(Phi);
2149 ValueToShadow.setShadow(*Phi, *Shadow);
2150 }
2151 }
2152 }
2153
2154
2155 for (Instruction *I : OriginalInstructions)
2156 maybeCreateShadowValue(*I, TLI, ValueToShadow);
2157
2158
2159 for (Instruction *I : OriginalInstructions)
2160 propagateShadowValues(*I, TLI, ValueToShadow);
2161
2162
2163 for (PHINode *Phi : OriginalPhis) {
2164 PHINode *ShadowPhi = cast(ValueToShadow.getShadow(Phi));
2165 for (unsigned I : seq(Phi->getNumOperands())) {
2167 Value *Shadow = ValueToShadow.getShadow(V);
2169
2170
2171
2172
2173
2174
2175 ShadowPhi->addIncoming(Shadow, IncomingBB);
2176 }
2177 }
2178
2179 return !ValueToShadow.empty();
2180}
2181
2186 if (CInt && CInt->getValue().getBitWidth() <= 64)
2187 OpSize = CInt->getValue().getZExtValue();
2188 }
2189
2190 return OpSize;
2191}
2192
2193
2194
2195bool NumericalStabilitySanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
2198 FunctionCallee SetUnknownFn =
2199 NsanSetUnknownFns.getFunctionFor(GetMemOpSize(M->getArgOperand(2)));
2201 Builder.CreateCall(SetUnknownFn, {M->getArgOperand(0)});
2202 else
2204 {M->getArgOperand(0),
2206 IntptrTy, false)});
2207
2209 FunctionCallee CopyFn =
2210 NsanCopyFns.getFunctionFor(GetMemOpSize(M->getArgOperand(2)));
2211
2213 Builder.CreateCall(CopyFn, {M->getArgOperand(0),
2214 M->getArgOperand(1)});
2215 else
2216 Builder.CreateCall(CopyFn, {M->getArgOperand(0),
2217 M->getArgOperand(1),
2218
2220 IntptrTy, false)});
2221 }
2222 return false;
2223}
2224
2225void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(CallBase *CI) {
2227 if (Fn == nullptr)
2228 return;
2229
2231 return;
2232
2233 if (Fn->getName() == "__nsan_dump_shadow_mem") {
2235 "invalid prototype for __nsan_dump_shadow_mem");
2236
2237
2238
2239
2240 const uint64_t shadow_value_type_ids =
2241 (static_cast<size_t>(Config.byValueType(kLongDouble).getNsanTypeId())
2242 << 16) |
2243 (static_cast<size_t>(Config.byValueType(kDouble).getNsanTypeId())
2244 << 8) |
2245 static_cast<size_t>(Config.byValueType(kFloat).getNsanTypeId());
2246 CI->setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
2247 }
2248}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ArrayRef< TableEntry > TableRef
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)
Definition NumericalStabilitySanitizer.cpp:645
static FunctionType * makeDoubleDouble(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1316
constexpr int kMaxVectorWidth
Definition NumericalStabilitySanitizer.cpp:139
static cl::opt< bool > ClCheckRet("nsan-check-ret", cl::init(true), cl::desc("Check floating-point return values"), cl::Hidden)
static bool shouldCheckArgs(CallBase &CI, const TargetLibraryInfo &TLI, const std::optional< Regex > &CheckFunctionsFilter)
Definition NumericalStabilitySanitizer.cpp:792
static cl::opt< bool > ClCheckStores("nsan-check-stores", cl::init(true), cl::desc("Check floating-point stores"), cl::Hidden)
static FunctionType * makeX86FP80X86FP80(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1320
#define MOVE_FLAG(attr, setter)
static FunctionType * makeX86FP80X86FP80I32(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1330
constexpr int kMaxNumArgs
Definition NumericalStabilitySanitizer.cpp:140
constexpr int kMaxShadowTypeSizeBytes
Definition NumericalStabilitySanitizer.cpp:141
static const char * getIntrinsicFromLibfunc(Function &Fn, Type *VT, const TargetLibraryInfo &TLI)
Definition NumericalStabilitySanitizer.cpp:1536
static FunctionType * makeX86FP80X86FP80X86FP80(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1341
static FunctionType * makeX86FP80X86FP80X86FP80X86FP80(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1354
static uint64_t GetMemOpSize(Value *V)
Definition NumericalStabilitySanitizer.cpp:2182
ContinuationType
Definition NumericalStabilitySanitizer.cpp:888
@ ContinueWithShadow
Definition NumericalStabilitySanitizer.cpp:889
@ ResumeFromValue
Definition NumericalStabilitySanitizer.cpp:890
constexpr StringLiteral kNsanInitName("__nsan_init")
static FunctionType * makeDoubleDoubleDouble(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1336
constexpr int kShadowScale
Definition NumericalStabilitySanitizer.cpp:138
static cl::opt< bool > ClCheckLoads("nsan-check-loads", cl::desc("Check floating-point load"), cl::Hidden)
constexpr StringLiteral kNsanModuleCtorName("nsan.module_ctor")
static cl::opt< bool > ClPropagateNonFTConstStoresAsFT("nsan-propagate-non-ft-const-stores-as-ft", cl::desc("Propagate non floating-point const stores as floating point values." "For debugging purposes only"), cl::Hidden)
static cl::opt< std::string > ClShadowMapping("nsan-shadow-type-mapping", cl::init("dqq"), cl::desc("One shadow type id for each of `float`, `double`, `long double`. " "`d`,`l`,`q`,`e` mean double, x86_fp80, fp128 (quad) and " "ppc_fp128 (extended double) respectively. The default is to " "shadow `float` as `double`, and `double` and `x86_fp80` as " "`fp128`"), cl::Hidden)
static FunctionType * makeDoubleDoubleDoubleDouble(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1347
static cl::opt< bool > ClTruncateFCmpEq("nsan-truncate-fcmp-eq", cl::init(true), cl::desc("This flag controls the behaviour of fcmp equality comparisons." "For equality comparisons such as `x == 0.0f`, we can perform the " "shadow check in the shadow (`x_shadow == 0.0) == (x == 0.0f)`) or app " " domain (`(trunc(x_shadow) == 0.0f) == (x == 0.0f)`). This helps " "catch the case when `x_shadow` is accurate enough (and therefore " "close enough to zero) so that `trunc(x_shadow)` is zero even though " "both `x` and `x_shadow` are not"), cl::Hidden)
static cl::opt< std::string > ClCheckFunctionsFilter("check-functions-filter", cl::desc("Only emit checks for arguments of functions " "whose names match the given regular expression"), cl::value_desc("regex"))
static FunctionType * makeDoubleDoubleI32(LLVMContext &C)
Definition NumericalStabilitySanitizer.cpp:1325
static void moveFastMathFlags(Function &F, std::vector< Instruction * > &Instructions)
Definition NumericalStabilitySanitizer.cpp:2015
static cl::opt< bool > ClInstrumentFCmp("nsan-instrument-fcmp", cl::init(true), cl::desc("Instrument floating-point comparisons"), cl::Hidden)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static constexpr roundingMode rmTowardZero
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction & back() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
InstListType::iterator iterator
Instruction iterators...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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...
Value * getCalledOperand() const
void setArgOperand(unsigned i, Value *v)
unsigned arg_size() const
Predicate getPredicate() const
Return the predicate for this instruction.
ConstantFP - Floating Point Values [float, double].
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
This instruction compares its operands according to the predicate given to the constructor.
static bool isEquality(Predicate Pred)
This class represents an extension of floating point types.
This class represents a truncation of floating point types.
Convenience struct for specifying and reasoning about fast-math flags.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType()
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
@ ExternalLinkage
Externally visible function.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateFreeze(Value *V, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
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.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateFPExt(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
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.
LLVM_ABI void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB)
Replace specified successor OldBB to point at the provided block.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
const char * getOpcodeName() const
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
This is the common base class for memset/memcpy/memmove.
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 PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
StringRef getName(LibFunc F) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isX86_FP80Ty() const
Return true if this is x86 long double.
bool isArrayTy() const
True if this is an instance of ArrayType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getPPC_FP128Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
LLVM_ABI unsigned getStructNumElements() const
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
'undef' values are things that do not have specified contents.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#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 char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI MatchIntrinsicTypesResult matchIntrinsicSignature(FunctionType *FTy, ArrayRef< IITDescriptor > &Infos, SmallVectorImpl< Type * > &ArgTys)
Match the specified function type with the type constraints specified by the .td file.
LLVM_ABI void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl< IITDescriptor > &T)
Return the IIT table descriptor for the specified intrinsic into an array of IITDescriptors.
MatchIntrinsicTypesResult
@ MatchIntrinsicTypes_Match
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
Context & getContext() const
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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 - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
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.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
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 - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
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 - Return the argument parameter cast to the specified type.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
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...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition NumericalStabilitySanitizer.cpp:629