51#define DEBUG_TYPE "nsan"
54 "Number of instrumented floating-point loads");
57 "Number of instrumented floating-point calls");
59 "Number of instrumented floating-point returns");
61 "Number of instrumented floating-point stores");
63 "Number of instrumented non floating-point stores");
65 NumInstrumentedNonFTMemcpyStores,
66 "Number of instrumented non floating-point stores with memcpy semantics");
67STATISTIC(NumInstrumentedFCmp,
"Number of instrumented fcmps");
73 "nsan-shadow-type-mapping",
cl::init(
"dqq"),
74 cl::desc(
"One shadow type id for each of `float`, `double`, `long double`. "
75 "`d`,`l`,`q`,`e` mean double, x86_fp80, fp128 (quad) and "
76 "ppc_fp128 (extended double) respectively. The default is to "
77 "shadow `float` as `double`, and `double` and `x86_fp80` as "
83 cl::desc(
"Instrument floating-point comparisons"),
87 "check-functions-filter",
88 cl::desc(
"Only emit checks for arguments of functions "
89 "whose names match the given regular expression"),
93 "nsan-truncate-fcmp-eq",
cl::init(
true),
95 "This flag controls the behaviour of fcmp equality comparisons."
96 "For equality comparisons such as `x == 0.0f`, we can perform the "
97 "shadow check in the shadow (`x_shadow == 0.0) == (x == 0.0f)`) or app "
98 " domain (`(trunc(x_shadow) == 0.0f) == (x == 0.0f)`). This helps "
99 "catch the case when `x_shadow` is accurate enough (and therefore "
100 "close enough to zero) so that `trunc(x_shadow)` is zero even though "
101 "both `x` and `x_shadow` are not"),
114 cl::desc(
"Check floating-point load"),
118 cl::desc(
"Check floating-point stores"),
122 cl::desc(
"Check floating-point return values"),
132 "nsan-propagate-non-ft-const-stores-as-ft",
134 "Propagate non floating-point const stores as floating point values."
135 "For debugging purposes only"),
151class ShadowTypeConfig {
153 static std::unique_ptr<ShadowTypeConfig> fromNsanTypeId(
char TypeId);
159 virtual char getNsanTypeId()
const = 0;
161 virtual ~ShadowTypeConfig() =
default;
164template <
char NsanTypeId>
165class ShadowTypeConfigImpl :
public ShadowTypeConfig {
167 char getNsanTypeId()
const override {
return NsanTypeId; }
168 static constexpr const char kNsanTypeId = NsanTypeId;
172class F64ShadowConfig :
public ShadowTypeConfigImpl<'d'> {
179class F80ShadowConfig :
public ShadowTypeConfigImpl<'l'> {
186class F128ShadowConfig :
public ShadowTypeConfigImpl<'q'> {
193class PPC128ShadowConfig :
public ShadowTypeConfigImpl<'e'> {
200std::unique_ptr<ShadowTypeConfig>
201ShadowTypeConfig::fromNsanTypeId(
const char TypeId) {
203 case F64ShadowConfig::kNsanTypeId:
204 return std::make_unique<F64ShadowConfig>();
205 case F80ShadowConfig::kNsanTypeId:
206 return std::make_unique<F80ShadowConfig>();
207 case F128ShadowConfig::kNsanTypeId:
208 return std::make_unique<F128ShadowConfig>();
209 case PPC128ShadowConfig::kNsanTypeId:
210 return std::make_unique<PPC128ShadowConfig>();
217enum FTValueType { kFloat, kDouble, kLongDouble, kNumValueTypes };
220static std::optional<FTValueType> ftValueTypeFromType(
Type *FT) {
231static Type *typeFromFTValueType(FTValueType VT,
LLVMContext &Context) {
246static const char *typeNameFromFTValueType(FTValueType VT) {
267 unsigned ShadowTypeSizeBits[kNumValueTypes];
268 for (
int VT = 0; VT < kNumValueTypes; ++VT) {
273 const unsigned AppTypeSize =
274 typeFromFTValueType(
static_cast<FTValueType
>(VT), Context)
275 ->getScalarSizeInBits();
276 const unsigned ShadowTypeSize =
277 Config->getType(Context)->getScalarSizeInBits();
282 "->f" +
Twine(ShadowTypeSize) +
283 ": The shadow type size should be at most " +
285 " times the application type size");
286 ShadowTypeSizeBits[VT] = ShadowTypeSize;
287 Configs[VT] = std::move(
Config);
296 if (ShadowTypeSizeBits[kFloat] > ShadowTypeSizeBits[kDouble] ||
297 ShadowTypeSizeBits[kDouble] > ShadowTypeSizeBits[kLongDouble])
299 Twine(ShadowTypeSizeBits[kFloat]) +
"; double->f" +
300 Twine(ShadowTypeSizeBits[kDouble]) +
302 Twine(ShadowTypeSizeBits[kLongDouble]) +
" }");
305 const ShadowTypeConfig &byValueType(FTValueType VT)
const {
306 assert(VT < FTValueType::kNumValueTypes &&
"invalid value type");
311 Type *getExtendedFPType(
Type *FT)
const {
312 if (
const auto VT = ftValueTypeFromType(FT))
313 return Configs[*VT]->getType(Context);
315 auto *VecTy = cast<VectorType>(FT);
317 if (VecTy->isScalableTy())
319 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());
320 return ExtendedScalar
321 ? VectorType::get(ExtendedScalar, VecTy->getElementCount())
329 std::unique_ptr<ShadowTypeConfig> Configs[FTValueType::kNumValueTypes];
334struct MemoryExtents {
339static MemoryExtents getMemoryExtentsOrDie(
Type *FT) {
340 if (
const auto VT = ftValueTypeFromType(FT))
342 if (
auto *VecTy = dyn_cast<VectorType>(FT)) {
343 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());
344 return {ScalarExtents.ValueType,
345 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};
354 static CheckLoc makeStore(
Value *Address) {
355 CheckLoc Result(kStore);
356 Result.Address = Address;
359 static CheckLoc makeLoad(
Value *Address) {
360 CheckLoc Result(kLoad);
361 Result.Address = Address;
366 static CheckLoc makeArg(
int ArgId) {
367 CheckLoc Result(kArg);
368 Result.ArgId = ArgId;
373 static CheckLoc makeRet() {
return CheckLoc(kRet); }
376 static CheckLoc makeInsert() {
return CheckLoc(kInsert); }
393 return ConstantInt::get(IntptrTy, 0);
395 return ConstantInt::get(IntptrTy, ArgId);
414 explicit CheckLoc(CheckType CheckTy) : CheckTy(CheckTy) {}
416 Value *Address =
nullptr;
417 const CheckType CheckTy;
422class ValueToShadowMap {
426 ValueToShadowMap(
const ValueToShadowMap &) =
delete;
427 ValueToShadowMap &operator=(
const ValueToShadowMap &) =
delete;
432 [[maybe_unused]]
const bool Inserted = Map.try_emplace(&V, &Shadow).second;
435 if (
auto *
I = dyn_cast<Instruction>(&V))
436 errs() <<
I->getFunction()->getName() <<
": ";
437 errs() <<
"duplicate shadow (" << &V <<
"): ";
441 assert(Inserted &&
"duplicate shadow");
446 bool hasShadow(
Value *V)
const {
447 return isa<Constant>(V) || (Map.find(V) != Map.end());
454 return getShadowConstant(
C);
455 return Map.find(V)->second;
458 bool empty()
const {
return Map.empty(); }
463 bool LosesInfo =
false;
475 Type *Ty =
Config.getExtendedFPType(CFP->getType());
476 return ConstantFP::get(
480 if (
C->getType()->isVectorTy()) {
482 for (
int I = 0, E = cast<VectorType>(
C->getType())
486 Elements.push_back(getShadowConstant(
C->getAggregateElement(
I)));
492 const MappingConfig &
Config;
505 size_t NumSizedFuncs;
513 Type *PtrTy = PointerType::getUnqual(Ctx);
515 IntegerType *IntptrTy = M.getDataLayout().getIntPtrType(Ctx);
518 NumSizedFuncs = Sized.
size();
523 M.getOrInsertFunction(
Fallback, Attr, VoidTy, PtrTy, PtrTy, IntptrTy));
524 SizedFnTy = FunctionType::get(VoidTy, {PtrTy, PtrTy},
false);
525 }
else if (NumArgs == 2) {
527 M.getOrInsertFunction(
Fallback, Attr, VoidTy, PtrTy, IntptrTy));
528 SizedFnTy = FunctionType::get(VoidTy, {PtrTy},
false);
533 for (
size_t i = 0; i < NumSizedFuncs; ++i)
534 Funcs.push_back(M.getOrInsertFunction(Sized[i], SizedFnTy, Attr));
540 assert(NumSizedFuncs >= 3 &&
"Unexpected number of sized functions");
543 MemOpSize == 4 ? 1 : (MemOpSize == 8 ? 2 : (MemOpSize == 16 ? 3 : 0));
548FunctionCallee NsanMemOpFn::getFallback()
const {
return Funcs[0]; }
554class NumericalStabilitySanitizer {
556 NumericalStabilitySanitizer(
Module &M);
561 void maybeAddSuffixForNsanInterface(
CallBase *CI);
562 bool addrPointsToConstantData(
Value *
Addr);
564 ValueToShadowMap &Map);
567 const ValueToShadowMap &Map);
570 ValueToShadowMap &Map);
573 const ValueToShadowMap &Map);
576 const ValueToShadowMap &Map);
581 void emitFCmpCheck(
FCmpInst &FCmp,
const ValueToShadowMap &Map);
587 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
590 const ValueToShadowMap &Map,
593 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
595 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
599 const ValueToShadowMap &Map);
601 const ValueToShadowMap &Map);
609 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};
610 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};
614 NsanMemOpFn NsanCopyFns;
615 NsanMemOpFn NsanSetUnknownFns;
621 Type *NsanShadowRetType =
nullptr;
626 Type *NsanShadowArgsType =
nullptr;
629 std::optional<Regex> CheckFunctionsFilter;
642 NumericalStabilitySanitizer Nsan(M);
651 return dyn_cast<GlobalValue>(M.getOrInsertGlobal(
Name, Ty, [&M, Ty,
Name] {
652 return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
653 nullptr, Name, nullptr,
654 GlobalVariable::InitialExecTLSModel);
658NumericalStabilitySanitizer::NumericalStabilitySanitizer(
Module &M)
659 :
DL(
M.getDataLayout()), Context(
M.getContext()),
Config(Context),
660 NsanCopyFns(
M, {
"__nsan_copy_4",
"__nsan_copy_8",
"__nsan_copy_16"},
661 "__nsan_copy_values", 3),
663 {
"__nsan_set_value_unknown_4",
664 "__nsan_set_value_unknown_8",
665 "__nsan_set_value_unknown_16"},
666 "__nsan_set_value_unknown", 2) {
667 IntptrTy =
DL.getIntPtrType(Context);
668 Type *PtrTy = PointerType::getUnqual(Context);
676 for (
int I = 0;
I < kNumValueTypes; ++
I) {
677 const FTValueType VT =
static_cast<FTValueType
>(
I);
678 const char *VTName = typeNameFromFTValueType(VT);
679 Type *VTTy = typeFromFTValueType(VT, Context);
682 const std::string GetterPrefix =
683 std::string(
"__nsan_get_shadow_ptr_for_") + VTName;
684 NsanGetShadowPtrForStore[VT] =
M.getOrInsertFunction(
685 GetterPrefix +
"_store", Attr, PtrTy, PtrTy, IntptrTy);
686 NsanGetShadowPtrForLoad[VT] =
M.getOrInsertFunction(
687 GetterPrefix +
"_load", Attr, PtrTy, PtrTy, IntptrTy);
690 const auto &ShadowConfig =
Config.byValueType(VT);
691 Type *ShadowTy = ShadowConfig.getType(Context);
693 M.getOrInsertFunction(std::string(
"__nsan_internal_check_") + VTName +
694 "_" + ShadowConfig.getNsanTypeId(),
695 Attr, Int32Ty, VTTy, ShadowTy, Int32Ty, IntptrTy);
696 NsanFCmpFail[VT] =
M.getOrInsertFunction(
697 std::string(
"__nsan_fcmp_fail_") + VTName +
"_" +
698 ShadowConfig.getNsanTypeId(),
699 Attr, VoidTy, VTTy, VTTy, ShadowTy, ShadowTy, Int32Ty, Int1Ty, Int1Ty);
703 NsanGetRawShadowTypePtr =
M.getOrInsertFunction(
704 "__nsan_internal_get_raw_shadow_type_ptr", Attr, PtrTy, PtrTy);
705 NsanGetRawShadowPtr =
M.getOrInsertFunction(
706 "__nsan_internal_get_raw_shadow_ptr", Attr, PtrTy, PtrTy);
727 std::string RegexError;
729 CheckFunctionsFilter = std::move(R);
735bool NumericalStabilitySanitizer::addrPointsToConstantData(
Value *
Addr) {
738 Addr =
GEP->getPointerOperand();
741 return GV->isConstant();
757void NumericalStabilitySanitizer::createShadowArguments(
759 assert(!
F.getIntrinsicID() &&
"found a definition of an intrinsic");
763 return Config.getExtendedFPType(Arg.getType()) == nullptr;
767 IRBuilder<> Builder(
F.getEntryBlock().getFirstNonPHI());
770 Value *HasShadowArgs = Builder.CreateICmpEQ(
771 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag,
false),
772 Builder.CreatePtrToInt(&
F, IntptrTy));
774 unsigned ShadowArgsOffsetBytes = 0;
777 Type *ExtendedVT =
Config.getExtendedFPType(VT);
778 if (ExtendedVT ==
nullptr)
780 Value *
L = Builder.CreateAlignedLoad(
782 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
783 ShadowArgsOffsetBytes),
785 Value *Shadow = Builder.CreateSelect(HasShadowArgs, L,
786 Builder.CreateFPExt(&Arg, ExtendedVT));
787 Map.setShadow(Arg, *Shadow);
788 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
790 ShadowArgsOffsetBytes += SlotSize;
792 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);
798 const std::optional<Regex> &CheckFunctionsFilter) {
802 if (CheckFunctionsFilter) {
806 if (CheckFunctionsFilter->match(Fn->
getName()))
819 LibFunc LFunc = LibFunc::NumLibFuncs;
827 if (
ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||
828 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)
829 for (
const auto &U : CI.
users())
838void NumericalStabilitySanitizer::populateShadowStack(
846 return Config.getExtendedFPType(Arg->getType()) == nullptr;
852 const bool ShouldCheckArgs =
shouldCheckArgs(CI, TLI, CheckFunctionsFilter);
856 Value *ArgShadow =
Map.getShadow(Arg);
857 ArgShadows.
push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,
858 CheckLoc::makeArg(ArgIdx))
865 if (Fn->isIntrinsic() || TLI.
getLibFunc(*Fn, LFunc))
873 unsigned ShadowArgId = 0;
876 Type *ExtendedVT =
Config.getExtendedFPType(VT);
877 if (ExtendedVT ==
nullptr)
879 Builder.CreateAlignedStore(
880 ArgShadows[ShadowArgId++],
881 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
882 ShadowArgsOffsetBytes),
884 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
886 ShadowArgsOffsetBytes += SlotSize;
898Value *NumericalStabilitySanitizer::emitCheckInternal(
Value *V,
Value *ShadowV,
902 if (isa<Constant>(V))
903 return ConstantInt::get(
907 Type *Ty =
V->getType();
908 if (
const auto VT = ftValueTypeFromType(Ty))
911 {
V, ShadowV, Loc.
getType(Context), Loc.getValue(IntptrTy, Builder)});
914 auto *VecTy = cast<VectorType>(Ty);
917 assert(!VecTy->isScalableTy() &&
918 "Scalable vector types are not supported yet");
919 Value *CheckResult =
nullptr;
920 for (
int I = 0, E = VecTy->getElementCount().getFixedValue();
I < E; ++
I) {
926 Value *ComponentCheckResult =
927 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
928 CheckResult = CheckResult
929 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
930 : ComponentCheckResult;
935 Value *CheckResult =
nullptr;
939 Value *ComponentCheckResult =
940 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
941 CheckResult = CheckResult
942 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
943 : ComponentCheckResult;
948 Value *CheckResult =
nullptr;
954 Value *ComponentCheckResult =
955 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
956 CheckResult = CheckResult
957 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
958 : ComponentCheckResult;
961 return ConstantInt::get(
980 if (isa<Constant>(V))
983 if (
Instruction *Inst = dyn_cast<Instruction>(V)) {
985 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName())) {
990 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
1002void NumericalStabilitySanitizer::emitFCmpCheck(
FCmpInst &FCmp,
1003 const ValueToShadowMap &Map) {
1008 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName()))
1027 FCmpBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1028 Value *ShadowLHS =
Map.getShadow(LHS);
1029 Value *ShadowRHS =
Map.getShadow(RHS);
1033 ShadowLHS = FCmpBuilder.CreateFPExt(
1034 FCmpBuilder.CreateFPTrunc(ShadowLHS,
LHS->
getType()), Ty);
1035 ShadowRHS = FCmpBuilder.CreateFPExt(
1036 FCmpBuilder.CreateFPTrunc(ShadowRHS,
RHS->
getType()), Ty);
1039 FCmpBuilder.CreateFCmp(FCmp.
getPredicate(), ShadowLHS, ShadowRHS);
1040 Value *OriginalAndShadowFcmpMatch =
1041 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
1047 OriginalAndShadowFcmpMatch =
1048 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
1053 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
1054 MDBuilder(Context).createLikelyBranchWeights());
1058 FailBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1060 const auto EmitFailCall = [
this, &FCmp, &FCmpBuilder,
1063 Value *ShadowResult) {
1064 Type *FT =
L->getType();
1067 Callee = &(NsanFCmpFail[kFloat]);
1069 Callee = &(NsanFCmpFail[kDouble]);
1072 Callee = &(NsanFCmpFail[kDouble]);
1078 FailBuilder.CreateCall(*Callee, {
L,
R, ShadowL, ShadowR,
1079 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1084 for (
int I = 0, E = cast<VectorType>(
LHS->
getType())
1088 Value *ExtractLHS = FailBuilder.CreateExtractElement(LHS,
I);
1089 Value *ExtractRHS = FailBuilder.CreateExtractElement(RHS,
I);
1090 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS,
I);
1091 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS,
I);
1092 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp,
I);
1093 Value *ExtractShadowFCmp =
1094 FailBuilder.CreateExtractElement(ShadowFCmp,
I);
1095 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1096 ExtractFCmp, ExtractShadowFCmp);
1099 EmitFailCall(LHS, RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1101 FailBuilder.CreateBr(NextBB);
1103 ++NumInstrumentedFCmp;
1107PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1110 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1111 if (ExtendedVT ==
nullptr)
1125 if (addrPointsToConstantData(
Load.getPointerOperand())) {
1145 const auto Extents = getMemoryExtentsOrDie(VT);
1147 NsanGetShadowPtrForLoad[Extents.ValueType],
1148 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1149 ++NumInstrumentedFTLoads;
1165 LoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1166 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1172 ShadowLoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1173 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1174 ExtendedVT, ShadowPtr,
Align(1),
Load.isVolatile());
1176 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,
1177 CheckLoc::makeLoad(
Load.getPointerOperand()));
1179 ShadowLoadBBBuilder.CreateBr(NextBB);
1183 FExtBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1184 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);
1185 FExtBBBuilder.CreateBr(NextBB);
1189 NextBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1190 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1198 const ValueToShadowMap &Map,
1202 Type *ExtendedSourceTy =
Config.getExtendedFPType(OrigSourceTy);
1235 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1236 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1238 if (SourceTy == ExtendedVT)
1246 const ValueToShadowMap &Map,
1248 Value *OrigSource =
Ext.getOperand(0);
1250 Type *ExtendedSourceTy =
Config.getExtendedFPType(OrigSourceTy);
1282 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1283 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1285 if (SourceTy == ExtendedVT)
1293struct KnownIntrinsic {
1294 struct WidenedIntrinsic {
1295 const char *NarrowName;
1298 FnTypeFactory MakeFnTy;
1313 const char *IntrinsicName;
1315 static const LFEntry kLibfuncIntrinsics[];
1317 static const WidenedIntrinsic kWidenedIntrinsics[];
1353 return FunctionType::get(
1360 return FunctionType::get(
1366const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1464const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1465 {LibFunc_sqrtf,
"llvm.sqrt.f32"},
1466 {LibFunc_sqrt,
"llvm.sqrt.f64"},
1467 {LibFunc_sqrtl,
"llvm.sqrt.f80"},
1468 {LibFunc_sinf,
"llvm.sin.f32"},
1469 {LibFunc_sin,
"llvm.sin.f64"},
1470 {LibFunc_sinl,
"llvm.sin.f80"},
1471 {LibFunc_cosf,
"llvm.cos.f32"},
1472 {LibFunc_cos,
"llvm.cos.f64"},
1473 {LibFunc_cosl,
"llvm.cos.f80"},
1474 {LibFunc_powf,
"llvm.pow.f32"},
1475 {LibFunc_pow,
"llvm.pow.f64"},
1476 {LibFunc_powl,
"llvm.pow.f80"},
1477 {LibFunc_expf,
"llvm.exp.f32"},
1478 {LibFunc_exp,
"llvm.exp.f64"},
1479 {LibFunc_expl,
"llvm.exp.f80"},
1480 {LibFunc_exp2f,
"llvm.exp2.f32"},
1481 {LibFunc_exp2,
"llvm.exp2.f64"},
1482 {LibFunc_exp2l,
"llvm.exp2.f80"},
1483 {LibFunc_logf,
"llvm.log.f32"},
1484 {LibFunc_log,
"llvm.log.f64"},
1485 {LibFunc_logl,
"llvm.log.f80"},
1486 {LibFunc_log10f,
"llvm.log10.f32"},
1487 {LibFunc_log10,
"llvm.log10.f64"},
1488 {LibFunc_log10l,
"llvm.log10.f80"},
1489 {LibFunc_log2f,
"llvm.log2.f32"},
1490 {LibFunc_log2,
"llvm.log2.f64"},
1491 {LibFunc_log2l,
"llvm.log2.f80"},
1492 {LibFunc_fabsf,
"llvm.fabs.f32"},
1493 {LibFunc_fabs,
"llvm.fabs.f64"},
1494 {LibFunc_fabsl,
"llvm.fabs.f80"},
1495 {LibFunc_copysignf,
"llvm.copysign.f32"},
1496 {LibFunc_copysign,
"llvm.copysign.f64"},
1497 {LibFunc_copysignl,
"llvm.copysign.f80"},
1498 {LibFunc_floorf,
"llvm.floor.f32"},
1499 {LibFunc_floor,
"llvm.floor.f64"},
1500 {LibFunc_floorl,
"llvm.floor.f80"},
1501 {LibFunc_fmaxf,
"llvm.maxnum.f32"},
1502 {LibFunc_fmax,
"llvm.maxnum.f64"},
1503 {LibFunc_fmaxl,
"llvm.maxnum.f80"},
1504 {LibFunc_fminf,
"llvm.minnum.f32"},
1505 {LibFunc_fmin,
"llvm.minnum.f64"},
1506 {LibFunc_fminl,
"llvm.minnum.f80"},
1507 {LibFunc_ceilf,
"llvm.ceil.f32"},
1508 {LibFunc_ceil,
"llvm.ceil.f64"},
1509 {LibFunc_ceill,
"llvm.ceil.f80"},
1510 {LibFunc_truncf,
"llvm.trunc.f32"},
1511 {LibFunc_trunc,
"llvm.trunc.f64"},
1512 {LibFunc_truncl,
"llvm.trunc.f80"},
1513 {LibFunc_rintf,
"llvm.rint.f32"},
1514 {LibFunc_rint,
"llvm.rint.f64"},
1515 {LibFunc_rintl,
"llvm.rint.f80"},
1516 {LibFunc_nearbyintf,
"llvm.nearbyint.f32"},
1517 {LibFunc_nearbyint,
"llvm.nearbyint.f64"},
1518 {LibFunc_nearbyintl,
"llvm.nearbyint.f80"},
1519 {LibFunc_roundf,
"llvm.round.f32"},
1520 {LibFunc_round,
"llvm.round.f64"},
1521 {LibFunc_roundl,
"llvm.round.f80"},
1524const char *KnownIntrinsic::get(
LibFunc LFunc) {
1525 for (
const auto &E : kLibfuncIntrinsics) {
1526 if (E.LFunc == LFunc)
1527 return E.IntrinsicName;
1532const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(
StringRef Name) {
1533 for (
const auto &E : kWidenedIntrinsics) {
1534 if (E.NarrowName ==
Name)
1547 if (
const char *
Name = KnownIntrinsic::get(LFunc))
1555Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1557 const ValueToShadowMap &Map,
IRBuilder<> &Builder) {
1565 const auto *Widened = KnownIntrinsic::widen(Fn->
getName());
1567 WidenedId = Widened->ID;
1568 WidenedFnTy = Widened->MakeFnTy(Context);
1579 const auto *Widened = KnownIntrinsic::widen(
Name);
1580 assert(Widened &&
"make sure KnownIntrinsic entries are consistent");
1581 WidenedId = Widened->ID;
1582 WidenedFnTy = Widened->MakeFnTy(Context);
1596 "invalid widened intrinsic");
1601 for (
unsigned I = 0, E =
Call.getNumOperands() - 1;
I < E; ++
I) {
1604 Type *IntrinsicArgTy = WidenedFnTy->getParamType(
I);
1605 if (OrigArgTy == IntrinsicArgTy) {
1606 Args.push_back(Arg);
1611 "don't know how to get the shadow value for a non-FT");
1612 Value *Shadow =
Map.getShadow(Arg);
1613 if (ShadowArgTy == IntrinsicArgTy) {
1616 Args.push_back(Shadow);
1623 return WidenedFnTy->getReturnType() == ExtendedVT
1633 const ValueToShadowMap &Map,
1636 if (
Call.isInlineAsm())
1643 maybeHandleKnownCallBase(Call, VT, ExtendedVT, TLI, Map, Builder))
1649 Builder.
CreateLoad(IntptrTy, NsanShadowRetTag,
false);
1659 ++NumInstrumentedFTCalls;
1665Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1667 const ValueToShadowMap &Map) {
1669 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1670 assert(ExtendedVT !=
nullptr &&
"trying to create a shadow for a non-FT");
1672 if (
auto *Load = dyn_cast<LoadInst>(&Inst))
1673 return handleLoad(*Load, VT, ExtendedVT);
1675 if (
auto *Call = dyn_cast<CallInst>(&Inst)) {
1680 return handleCallBase(*Call, VT, ExtendedVT, TLI, Map, Builder);
1683 if (
auto *Invoke = dyn_cast<InvokeInst>(&Inst)) {
1687 BasicBlock *NextBB = Invoke->getNormalDest();
1694 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1703 if (
auto *Trunc = dyn_cast<FPTruncInst>(&Inst))
1704 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1705 if (
auto *Ext = dyn_cast<FPExtInst>(&Inst))
1706 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1708 if (
auto *UnaryOp = dyn_cast<UnaryOperator>(&Inst))
1709 return Builder.
CreateUnOp(UnaryOp->getOpcode(),
1710 Map.getShadow(UnaryOp->getOperand(0)));
1712 if (
auto *BinOp = dyn_cast<BinaryOperator>(&Inst))
1714 Map.getShadow(BinOp->getOperand(0)),
1715 Map.getShadow(BinOp->getOperand(1)));
1717 if (isa<UIToFPInst>(&Inst) || isa<SIToFPInst>(&Inst)) {
1718 auto *Cast = cast<CastInst>(&Inst);
1719 return Builder.
CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1723 if (
auto *S = dyn_cast<SelectInst>(&Inst))
1725 Map.getShadow(S->getTrueValue()),
1726 Map.getShadow(S->getFalseValue()));
1728 if (
auto *Freeze = dyn_cast<FreezeInst>(&Inst))
1731 if (
auto *Extract = dyn_cast<ExtractElementInst>(&Inst))
1733 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1735 if (
auto *Insert = dyn_cast<InsertElementInst>(&Inst))
1740 if (
auto *Shuffle = dyn_cast<ShuffleVectorInst>(&Inst))
1742 Map.getShadow(Shuffle->getOperand(1)),
1743 Shuffle->getShuffleMask());
1746 if (
auto *Extract = dyn_cast<ExtractValueInst>(&Inst))
1749 if (
auto *BC = dyn_cast<BitCastInst>(&Inst))
1760void NumericalStabilitySanitizer::maybeCreateShadowValue(
1763 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1764 if (ExtendedVT ==
nullptr)
1767 if (
Map.hasShadow(&Root))
1770 assert(!isa<PHINode>(Root) &&
"phi nodes should already have shadows");
1772 std::vector<Instruction *> DfsStack(1, &Root);
1773 while (!DfsStack.empty()) {
1779 if (
Map.hasShadow(
I)) {
1780 DfsStack.pop_back();
1784 bool MissingShadow =
false;
1786 Type *VT =
Op->getType();
1787 if (!
Config.getExtendedFPType(VT))
1789 if (
Map.hasShadow(
Op))
1791 MissingShadow =
true;
1792 DfsStack.push_back(cast<Instruction>(
Op));
1798 Value *Shadow = createShadowValueWithOperandsAvailable(*
I, TLI, Map);
1799 Map.setShadow(*
I, *Shadow);
1800 DfsStack.pop_back();
1805void NumericalStabilitySanitizer::propagateFTStore(
1807 Value *StoredValue =
Store.getValueOperand();
1810 const auto Extents = getMemoryExtentsOrDie(VT);
1812 NsanGetShadowPtrForStore[Extents.ValueType],
1813 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1815 Value *StoredShadow =
Map.getShadow(StoredValue);
1816 if (!
Store.getParent()->getParent()->hasOptNone()) {
1820 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1821 CheckLoc::makeStore(
Store.getPointerOperand()));
1822 ++NumInstrumentedFTStores;
1827 Store.isVolatile());
1838void NumericalStabilitySanitizer::propagateNonFTStore(
1848 IntptrTy,
APInt(IntptrTy->getPrimitiveSizeInBits(), LoadSizeBytes));
1850 ++NumInstrumentedNonFTStores;
1851 Value *StoredValue =
Store.getValueOperand();
1852 if (
LoadInst *Load = dyn_cast<LoadInst>(StoredValue)) {
1859 Type *ShadowValueIntTy =
1863 Value *LoadSrc =
Load->getPointerOperand();
1869 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1871 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}),
Align(1),
1873 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1875 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}),
Align(1),
1880 RawShadowType, Builder.
CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1884 Builder.
CreateCall(NsanGetRawShadowPtr, {Dst}),
1888 ++NumInstrumentedNonFTMemcpyStores;
1893 (
C = dyn_cast<Constant>(StoredValue))) {
1896 Type *BitcastTy =
nullptr;
1897 if (
auto *CInt = dyn_cast<ConstantInt>(
C)) {
1898 switch (CInt->getType()->getScalarSizeInBits()) {
1911 }
else if (
auto *CDV = dyn_cast<ConstantDataVector>(
C)) {
1912 const int NumElements =
1913 cast<VectorType>(CDV->getType())->getElementCount().getFixedValue();
1914 switch (CDV->getType()->getScalarSizeInBits()) {
1932 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1934 NsanGetShadowPtrForStore[Extents.ValueType],
1935 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1937 Type *ExtVT =
Config.getExtendedFPType(BitcastTy);
1941 Store.isVolatile());
1946 Builder.
CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});
1949void NumericalStabilitySanitizer::propagateShadowValues(
1951 const ValueToShadowMap &Map) {
1952 if (
auto *Store = dyn_cast<StoreInst>(&Inst)) {
1953 Value *StoredValue =
Store->getValueOperand();
1955 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1956 if (ExtendedVT ==
nullptr)
1957 return propagateNonFTStore(*Store, VT, Map);
1958 return propagateFTStore(*Store, VT, ExtendedVT, Map);
1961 if (
auto *FCmp = dyn_cast<FCmpInst>(&Inst)) {
1962 emitFCmpCheck(*FCmp, Map);
1966 if (
auto *CB = dyn_cast<CallBase>(&Inst)) {
1967 maybeAddSuffixForNsanInterface(CB);
1968 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
1971 instrumentMemIntrinsic(
MI);
1974 populateShadowStack(*CB, TLI, Map);
1978 if (
auto *RetInst = dyn_cast<ReturnInst>(&Inst)) {
1982 Value *RV = RetInst->getReturnValue();
1986 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1987 if (ExtendedVT ==
nullptr)
1989 Value *RVShadow =
Map.getShadow(RV);
1992 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1993 ++NumInstrumentedFTRets;
1999 Value *ShadowRetValPtr =
2007 Type *VT =
V->getType();
2008 Type *ExtendedVT =
Config.getExtendedFPType(VT);
2009 if (ExtendedVT ==
nullptr)
2012 emitCheck(V,
Map.getShadow(V), Builder, CheckLoc::makeInsert());
2021 std::vector<Instruction *> &Instructions) {
2023#define MOVE_FLAG(attr, setter) \
2024 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
2025 F.removeFnAttr(attr); \
2026 FMF.set##setter(); \
2031 MOVE_FLAG(
"no-signed-zeros-fp-math", NoSignedZeros)
2035 if (isa<FPMathOperator>(
I))
2036 I->setFastMathFlags(FMF);
2039bool NumericalStabilitySanitizer::sanitizeFunction(
2041 if (!
F.hasFnAttribute(Attribute::SanitizeNumericalStability))
2139 std::vector<Instruction *> OriginalInstructions;
2145 ValueToShadowMap ValueToShadow(
Config);
2150 std::vector<PHINode *> OriginalPhis;
2151 createShadowArguments(
F, TLI, ValueToShadow);
2153 if (
PHINode *Phi = dyn_cast<PHINode>(
I)) {
2154 if (
PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2155 OriginalPhis.push_back(Phi);
2156 ValueToShadow.setShadow(*Phi, *Shadow);
2163 maybeCreateShadowValue(*
I, TLI, ValueToShadow);
2167 propagateShadowValues(*
I, TLI, ValueToShadow);
2170 for (
PHINode *Phi : OriginalPhis) {
2171 PHINode *ShadowPhi = cast<PHINode>(ValueToShadow.getShadow(Phi));
2172 for (
unsigned I :
seq(
Phi->getNumOperands())) {
2174 Value *Shadow = ValueToShadow.getShadow(V);
2186 return !ValueToShadow.empty();
2191 if (
Constant *
C = dyn_cast<Constant>(V)) {
2192 auto *CInt = dyn_cast<ConstantInt>(
C);
2193 if (CInt && CInt->getValue().getBitWidth() <= 64)
2194 OpSize = CInt->getValue().getZExtValue();
2202bool NumericalStabilitySanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
2204 if (
auto *M = dyn_cast<MemSetInst>(
MI)) {
2206 NsanSetUnknownFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2208 Builder.
CreateCall(SetUnknownFn, {
M->getArgOperand(0)});
2211 {
M->getArgOperand(0),
2215 }
else if (
auto *M = dyn_cast<MemTransferInst>(
MI)) {
2217 NsanCopyFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2221 M->getArgOperand(1)});
2224 M->getArgOperand(1),
2232void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(
CallBase *CI) {
2240 if (Fn->
getName() ==
"__nsan_dump_shadow_mem") {
2242 "invalid prototype for __nsan_dump_shadow_mem");
2247 const uint64_t shadow_value_type_ids =
2248 (
static_cast<size_t>(
Config.byValueType(kLongDouble).getNsanTypeId())
2250 (
static_cast<size_t>(
Config.byValueType(kDouble).getNsanTypeId())
2252 static_cast<size_t>(
Config.byValueType(kFloat).getNsanTypeId());
2253 CI->
setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)
static FunctionType * makeDoubleDouble(LLVMContext &C)
constexpr int kMaxVectorWidth
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)
static cl::opt< bool > ClCheckStores("nsan-check-stores", cl::init(true), cl::desc("Check floating-point stores"), cl::Hidden)
static FunctionType * makeX86FP80X86FP80(LLVMContext &C)
#define MOVE_FLAG(attr, setter)
static FunctionType * makeX86FP80X86FP80I32(LLVMContext &C)
constexpr int kMaxNumArgs
constexpr int kMaxShadowTypeSizeBytes
static const char * getIntrinsicFromLibfunc(Function &Fn, Type *VT, const TargetLibraryInfo &TLI)
static FunctionType * makeX86FP80X86FP80X86FP80(LLVMContext &C)
static FunctionType * makeX86FP80X86FP80X86FP80X86FP80(LLVMContext &C)
static uint64_t GetMemOpSize(Value *V)
constexpr StringLiteral kNsanInitName("__nsan_init")
static FunctionType * makeDoubleDoubleDouble(LLVMContext &C)
constexpr int kShadowScale
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)
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)
static void moveFastMathFlags(Function &F, std::vector< Instruction * > &Instructions)
static cl::opt< bool > ClInstrumentFCmp("nsan-instrument-fcmp", cl::init(true), cl::desc("Instrument floating-point comparisons"), cl::Hidden)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
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)
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
AttributeList addFnAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add a function attribute to the list.
LLVM Basic Block Representation.
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.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction & back() const
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
This class represents a function call, abstracting a target machine's calling convention.
Predicate getPredicate() const
Return the predicate for this instruction.
ConstantFP - Floating Point Values [float, double].
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static 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...
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
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.
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...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
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="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
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.
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
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="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
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 * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateFPExt(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This instruction inserts a struct field of array element value into an aggregate value.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB)
Replace specified successor OldBB to point at the provided block.
const Function * getFunction() const
Return the function this instruction belongs to.
const char * getOpcodeName() const
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...
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.
reference emplace_back(ArgTypes &&... Args)
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.
Type * getStructElementType(unsigned N) const
static Type * getDoubleTy(LLVMContext &C)
const fltSemantics & getFltSemantics() 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 Type * getX86_FP80Ty(LLVMContext &C)
static IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
unsigned getStructNumElements() const
uint64_t getArrayNumElements() const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
static Type * getFP128Ty(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static IntegerType * getInt32Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
static Type * getPPC_FP128Ty(LLVMContext &C)
'undef' values are things that do not have specified contents.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
StringRef getName() const
Return a constant reference to the value's name.
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 Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
MatchIntrinsicTypesResult matchIntrinsicSignature(FunctionType *FTy, ArrayRef< IITDescriptor > &Infos, SmallVectorImpl< Type * > &ArgTys)
Match the specified function type with the type constraints specified by the .td file.
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
This is an optimization pass for GlobalISel generic memory operations.
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,...
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)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
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...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)