47#define DEBUG_TYPE "nsan"
50 "Number of instrumented floating-point loads");
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");
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 "
79 cl::desc(
"Instrument floating-point comparisons"),
83 "check-functions-filter",
84 cl::desc(
"Only emit checks for arguments of functions "
85 "whose names match the given regular expression"),
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"),
110 cl::desc(
"Check floating-point load"),
114 cl::desc(
"Check floating-point stores"),
118 cl::desc(
"Check floating-point return values"),
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"),
147class ShadowTypeConfig {
149 static std::unique_ptr<ShadowTypeConfig> fromNsanTypeId(
char TypeId);
155 virtual char getNsanTypeId()
const = 0;
157 virtual ~ShadowTypeConfig() =
default;
160template <
char NsanTypeId>
161class ShadowTypeConfigImpl :
public ShadowTypeConfig {
163 char getNsanTypeId()
const override {
return NsanTypeId; }
164 static constexpr char kNsanTypeId = NsanTypeId;
168class F64ShadowConfig :
public ShadowTypeConfigImpl<'d'> {
175class F80ShadowConfig :
public ShadowTypeConfigImpl<'l'> {
182class F128ShadowConfig :
public ShadowTypeConfigImpl<'q'> {
189class PPC128ShadowConfig :
public ShadowTypeConfigImpl<'e'> {
196std::unique_ptr<ShadowTypeConfig>
197ShadowTypeConfig::fromNsanTypeId(
const char TypeId) {
199 case F64ShadowConfig::kNsanTypeId:
200 return std::make_unique<F64ShadowConfig>();
201 case F80ShadowConfig::kNsanTypeId:
202 return std::make_unique<F80ShadowConfig>();
203 case F128ShadowConfig::kNsanTypeId:
204 return std::make_unique<F128ShadowConfig>();
205 case PPC128ShadowConfig::kNsanTypeId:
206 return std::make_unique<PPC128ShadowConfig>();
213enum FTValueType { kFloat, kDouble, kLongDouble, kNumValueTypes };
216static std::optional<FTValueType> ftValueTypeFromType(
Type *FT) {
227static Type *typeFromFTValueType(FTValueType VT,
LLVMContext &Context) {
242static const char *typeNameFromFTValueType(FTValueType VT) {
263 unsigned ShadowTypeSizeBits[kNumValueTypes];
264 for (
int VT = 0; VT < kNumValueTypes; ++VT) {
269 const unsigned AppTypeSize =
270 typeFromFTValueType(
static_cast<FTValueType
>(VT), Context)
271 ->getScalarSizeInBits();
272 const unsigned ShadowTypeSize =
273 Config->getType(Context)->getScalarSizeInBits();
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);
292 if (ShadowTypeSizeBits[kFloat] > ShadowTypeSizeBits[kDouble] ||
293 ShadowTypeSizeBits[kDouble] > ShadowTypeSizeBits[kLongDouble])
295 Twine(ShadowTypeSizeBits[kFloat]) +
"; double->f" +
296 Twine(ShadowTypeSizeBits[kDouble]) +
298 Twine(ShadowTypeSizeBits[kLongDouble]) +
" }");
301 const ShadowTypeConfig &byValueType(FTValueType VT)
const {
302 assert(VT < FTValueType::kNumValueTypes &&
"invalid value type");
307 Type *getExtendedFPType(
Type *FT)
const {
308 if (
const auto VT = ftValueTypeFromType(FT))
309 return Configs[*VT]->getType(Context);
313 if (VecTy->isScalableTy())
315 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());
316 return ExtendedScalar
325 std::unique_ptr<ShadowTypeConfig> Configs[FTValueType::kNumValueTypes];
330struct MemoryExtents {
335static MemoryExtents getMemoryExtentsOrDie(
Type *FT) {
336 if (
const auto VT = ftValueTypeFromType(FT))
339 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());
340 return {ScalarExtents.ValueType,
341 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};
350 static CheckLoc makeStore(
Value *Address) {
351 CheckLoc Result(kStore);
352 Result.Address = Address;
355 static CheckLoc makeLoad(
Value *Address) {
356 CheckLoc Result(kLoad);
357 Result.Address = Address;
362 static CheckLoc makeArg(
int ArgId) {
363 CheckLoc Result(kArg);
364 Result.ArgId = ArgId;
369 static CheckLoc makeRet() {
return CheckLoc(kRet); }
372 static CheckLoc makeInsert() {
return CheckLoc(kInsert); }
389 return ConstantInt::get(IntptrTy, 0);
391 return ConstantInt::get(IntptrTy, ArgId);
394 return Builder.CreatePtrToInt(Address, IntptrTy);
410 explicit CheckLoc(
CheckType CheckTy) : CheckTy(CheckTy) {}
412 Value *Address =
nullptr;
418class ValueToShadowMap {
420 explicit ValueToShadowMap(
const MappingConfig &Config) : Config(Config) {}
422 ValueToShadowMap(
const ValueToShadowMap &) =
delete;
423 ValueToShadowMap &operator=(
const ValueToShadowMap &) =
delete;
428 [[maybe_unused]]
const bool Inserted = Map.
try_emplace(&V, &Shadow).second;
432 errs() <<
I->getFunction()->getName() <<
": ";
433 errs() <<
"duplicate shadow (" << &V <<
"): ";
437 assert(Inserted &&
"duplicate shadow");
448 return getShadowConstant(
C);
449 return Map.
find(V)->second;
452 bool empty()
const {
return Map.
empty(); }
457 bool LosesInfo =
false;
469 Type *Ty = Config.getExtendedFPType(CFP->getType());
470 return ConstantFP::get(
471 Ty, extendConstantFP(CFP->getValueAPF(),
472 Ty->getScalarType()->getFltSemantics()));
475 if (
C->getType()->isVectorTy()) {
481 Elements.push_back(getShadowConstant(
C->getAggregateElement(
I)));
487 const MappingConfig &Config;
500 size_t NumSizedFuncs;
507 Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);
510 IntegerType *IntptrTy = M.getDataLayout().getIntPtrType(Ctx);
513 NumSizedFuncs = Sized.
size();
518 M.getOrInsertFunction(
Fallback, Attr, VoidTy, PtrTy, PtrTy, IntptrTy));
520 }
else if (NumArgs == 2) {
522 M.getOrInsertFunction(
Fallback, Attr, VoidTy, PtrTy, IntptrTy));
528 for (
size_t i = 0; i < NumSizedFuncs; ++i)
529 Funcs.push_back(M.getOrInsertFunction(Sized[i], SizedFnTy, Attr));
535 assert(NumSizedFuncs >= 3 &&
"Unexpected number of sized functions");
538 MemOpSize == 4 ? 1 : (MemOpSize == 8 ? 2 : (MemOpSize == 16 ? 3 : 0));
543FunctionCallee NsanMemOpFn::getFallback()
const {
return Funcs[0]; }
549class NumericalStabilitySanitizer {
551 NumericalStabilitySanitizer(
Module &M);
556 void maybeAddSuffixForNsanInterface(
CallBase *CI);
557 bool addrPointsToConstantData(
Value *Addr);
559 ValueToShadowMap &Map);
562 const ValueToShadowMap &Map);
565 ValueToShadowMap &Map);
568 const ValueToShadowMap &Map);
571 const ValueToShadowMap &Map);
576 void emitFCmpCheck(
FCmpInst &FCmp,
const ValueToShadowMap &Map);
582 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
585 const ValueToShadowMap &Map,
588 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
590 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
594 const ValueToShadowMap &Map);
596 const ValueToShadowMap &Map);
600 MappingConfig Config;
604 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};
605 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};
609 NsanMemOpFn NsanCopyFns;
610 NsanMemOpFn NsanSetUnknownFns;
616 Type *NsanShadowRetType =
nullptr;
621 Type *NsanShadowArgsType =
nullptr;
624 std::optional<Regex> CheckFunctionsFilter;
637 NumericalStabilitySanitizer Nsan(M);
646 return M.getOrInsertGlobal(Name, Ty, [&M, Ty, Name] {
648 nullptr, Name,
nullptr,
653NumericalStabilitySanitizer::NumericalStabilitySanitizer(
Module &M)
655 NsanCopyFns(
M, {
"__nsan_copy_4",
"__nsan_copy_8",
"__nsan_copy_16"},
656 "__nsan_copy_values", 3),
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);
669 Attr = Attr.addFnAttribute(Context, Attribute::NoUnwind);
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);
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);
685 const auto &ShadowConfig = Config.byValueType(VT);
686 Type *ShadowTy = ShadowConfig.getType(Context);
688 M.getOrInsertFunction(std::string(
"__nsan_internal_check_") + VTName +
689 "_" + ShadowConfig.getNsanTypeId(),
690 Attr, Int32Ty, VTTy, ShadowTy, Int32Ty, IntptrTy);
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);
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);
722 std::string RegexError;
724 CheckFunctionsFilter = std::move(R);
730bool NumericalStabilitySanitizer::addrPointsToConstantData(
Value *Addr) {
733 Addr =
GEP->getPointerOperand();
736 return GV->isConstant();
752void NumericalStabilitySanitizer::createShadowArguments(
753 Function &
F,
const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
754 assert(!
F.getIntrinsicID() &&
"found a definition of an intrinsic");
757 if (
all_of(
F.args(), [
this](
const Argument &Arg) {
758 return Config.getExtendedFPType(Arg.getType()) == nullptr;
762 IRBuilder<> Builder(&
F.getEntryBlock(),
F.getEntryBlock().getFirstNonPHIIt());
765 Value *HasShadowArgs = Builder.CreateICmpEQ(
766 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag,
false),
767 Builder.CreatePtrToInt(&
F, IntptrTy));
769 unsigned ShadowArgsOffsetBytes = 0;
770 for (Argument &Arg :
F.args()) {
772 Type *ExtendedVT = Config.getExtendedFPType(VT);
773 if (ExtendedVT ==
nullptr)
775 Value *
L = Builder.CreateAlignedLoad(
777 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
778 ShadowArgsOffsetBytes),
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;
787 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);
793 const std::optional<Regex> &CheckFunctionsFilter) {
797 if (CheckFunctionsFilter) {
801 if (CheckFunctionsFilter->match(Fn->
getName()))
822 if (ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||
823 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)
824 for (
const auto &U : CI.
users())
833void NumericalStabilitySanitizer::populateShadowStack(
834 CallBase &CI,
const TargetLibraryInfo &TLI,
const ValueToShadowMap &Map) {
841 return Config.getExtendedFPType(Arg->getType()) == nullptr;
846 SmallVector<Value *, 8> ArgShadows;
847 const bool ShouldCheckArgs =
shouldCheckArgs(CI, TLI, CheckFunctionsFilter);
849 if (Config.getExtendedFPType(Arg->
getType()) ==
nullptr)
851 Value *ArgShadow =
Map.getShadow(Arg);
852 ArgShadows.
push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,
853 CheckLoc::makeArg(ArgIdx))
859 if (Fn->isIntrinsic() || TLI.
getLibFunc(*Fn) != NotLibFunc)
867 unsigned ShadowArgId = 0;
870 Type *ExtendedVT = Config.getExtendedFPType(VT);
871 if (ExtendedVT ==
nullptr)
873 Builder.CreateAlignedStore(
874 ArgShadows[ShadowArgId++],
875 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
876 ShadowArgsOffsetBytes),
878 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
880 ShadowArgsOffsetBytes += SlotSize;
892Value *NumericalStabilitySanitizer::emitCheckInternal(
Value *V,
Value *ShadowV,
897 return ConstantInt::get(
901 Type *Ty =
V->getType();
902 if (
const auto VT = ftValueTypeFromType(Ty))
905 {
V, ShadowV, Loc.getType(
Context), Loc.getValue(IntptrTy, Builder)});
911 assert(!VecTy->isScalableTy() &&
912 "Scalable vector types are not supported yet");
913 Value *CheckResult =
nullptr;
914 for (
int I = 0,
E = VecTy->getElementCount().getFixedValue();
I <
E; ++
I) {
920 Value *ComponentCheckResult =
921 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
922 CheckResult = CheckResult
923 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
924 : ComponentCheckResult;
929 Value *CheckResult =
nullptr;
933 Value *ComponentCheckResult =
934 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
935 CheckResult = CheckResult
936 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
937 : ComponentCheckResult;
942 Value *CheckResult =
nullptr;
948 Value *ComponentCheckResult =
949 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
950 CheckResult = CheckResult
951 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
952 : ComponentCheckResult;
955 return ConstantInt::get(
979 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName())) {
984 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
990 ICmpEQ, Builder.
CreateFPExt(V, Config.getExtendedFPType(
V->getType())),
996void NumericalStabilitySanitizer::emitFCmpCheck(FCmpInst &FCmp,
997 const ValueToShadowMap &Map) {
1002 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName()))
1006 if (Config.getExtendedFPType(
LHS->
getType()) ==
nullptr)
1021 FCmpBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1027 ShadowLHS = FCmpBuilder.CreateFPExt(
1028 FCmpBuilder.CreateFPTrunc(ShadowLHS,
LHS->
getType()), Ty);
1029 ShadowRHS = FCmpBuilder.CreateFPExt(
1030 FCmpBuilder.CreateFPTrunc(ShadowRHS,
RHS->
getType()), Ty);
1033 FCmpBuilder.CreateFCmp(FCmp.
getPredicate(), ShadowLHS, ShadowRHS);
1034 Value *OriginalAndShadowFcmpMatch =
1035 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
1041 OriginalAndShadowFcmpMatch =
1042 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
1047 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
1048 MDBuilder(
Context).createLikelyBranchWeights());
1052 FailBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1054 const auto EmitFailCall = [
this, &FCmp, &FCmpBuilder,
1057 Value *ShadowResult) {
1058 Type *FT =
L->getType();
1059 FunctionCallee *
Callee =
nullptr;
1061 Callee = &(NsanFCmpFail[kFloat]);
1063 Callee = &(NsanFCmpFail[kDouble]);
1066 Callee = &(NsanFCmpFail[kDouble]);
1067 L = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(
Context));
1068 R = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(
Context));
1072 FailBuilder.CreateCall(*Callee, {
L,
R, ShadowL, ShadowR,
1073 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1082 Value *ExtractLHS = FailBuilder.CreateExtractElement(
LHS,
I);
1083 Value *ExtractRHS = FailBuilder.CreateExtractElement(
RHS,
I);
1084 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS,
I);
1085 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS,
I);
1086 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp,
I);
1087 Value *ExtractShadowFCmp =
1088 FailBuilder.CreateExtractElement(ShadowFCmp,
I);
1089 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1090 ExtractFCmp, ExtractShadowFCmp);
1093 EmitFailCall(
LHS,
RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1095 FailBuilder.CreateBr(NextBB);
1097 ++NumInstrumentedFCmp;
1101PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1102 PHINode &Phi,
const TargetLibraryInfo &TLI) {
1104 Type *ExtendedVT = Config.getExtendedFPType(VT);
1105 if (ExtendedVT ==
nullptr)
1115Value *NumericalStabilitySanitizer::handleLoad(LoadInst &
Load,
Type *VT,
1119 if (addrPointsToConstantData(
Load.getPointerOperand())) {
1139 const auto Extents = getMemoryExtentsOrDie(VT);
1141 NsanGetShadowPtrForLoad[Extents.ValueType],
1142 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1143 ++NumInstrumentedFTLoads;
1159 LoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1160 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1166 ShadowLoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1167 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1168 ExtendedVT, ShadowPtr,
Align(1),
Load.isVolatile());
1170 ShadowLoad = emitCheck(&
Load, ShadowLoad, ShadowLoadBBBuilder,
1171 CheckLoc::makeLoad(
Load.getPointerOperand()));
1173 ShadowLoadBBBuilder.CreateBr(NextBB);
1177 FExtBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1178 Value *FExt = FExtBBBuilder.CreateFPExt(&
Load, ExtendedVT);
1179 FExtBBBuilder.CreateBr(NextBB);
1183 NextBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1184 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1190Value *NumericalStabilitySanitizer::handleTrunc(
const FPTruncInst &Trunc,
1192 const ValueToShadowMap &Map,
1196 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1229 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1230 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1232 if (SourceTy == ExtendedVT)
1238Value *NumericalStabilitySanitizer::handleExt(
const FPExtInst &Ext,
Type *VT,
1240 const ValueToShadowMap &Map,
1244 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1276 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1277 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1279 if (SourceTy == ExtendedVT)
1287struct KnownIntrinsic {
1288 struct WidenedIntrinsic {
1289 const char *NarrowName;
1291 using FnTypeFactory = FunctionType *(*)(LLVMContext &);
1292 FnTypeFactory MakeFnTy;
1295 static const char *
get(LibFunc LFunc);
1302 static const WidenedIntrinsic *widen(StringRef Name);
1307 const char *IntrinsicName;
1309 static const LFEntry kLibfuncIntrinsics[];
1311 static const WidenedIntrinsic kWidenedIntrinsics[];
1360const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1449const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1450 {LibFunc_sqrtf,
"llvm.sqrt.f32"},
1451 {LibFunc_sqrt,
"llvm.sqrt.f64"},
1452 {LibFunc_sqrtl,
"llvm.sqrt.f80"},
1453 {LibFunc_sinf,
"llvm.sin.f32"},
1454 {LibFunc_sin,
"llvm.sin.f64"},
1455 {LibFunc_sinl,
"llvm.sin.f80"},
1456 {LibFunc_cosf,
"llvm.cos.f32"},
1457 {LibFunc_cos,
"llvm.cos.f64"},
1458 {LibFunc_cosl,
"llvm.cos.f80"},
1459 {LibFunc_powf,
"llvm.pow.f32"},
1460 {LibFunc_pow,
"llvm.pow.f64"},
1461 {LibFunc_powl,
"llvm.pow.f80"},
1462 {LibFunc_expf,
"llvm.exp.f32"},
1463 {LibFunc_exp,
"llvm.exp.f64"},
1464 {LibFunc_expl,
"llvm.exp.f80"},
1465 {LibFunc_exp2f,
"llvm.exp2.f32"},
1466 {LibFunc_exp2,
"llvm.exp2.f64"},
1467 {LibFunc_exp2l,
"llvm.exp2.f80"},
1468 {LibFunc_logf,
"llvm.log.f32"},
1469 {LibFunc_log,
"llvm.log.f64"},
1470 {LibFunc_logl,
"llvm.log.f80"},
1471 {LibFunc_log10f,
"llvm.log10.f32"},
1472 {LibFunc_log10,
"llvm.log10.f64"},
1473 {LibFunc_log10l,
"llvm.log10.f80"},
1474 {LibFunc_log2f,
"llvm.log2.f32"},
1475 {LibFunc_log2,
"llvm.log2.f64"},
1476 {LibFunc_log2l,
"llvm.log2.f80"},
1477 {LibFunc_fabsf,
"llvm.fabs.f32"},
1478 {LibFunc_fabs,
"llvm.fabs.f64"},
1479 {LibFunc_fabsl,
"llvm.fabs.f80"},
1480 {LibFunc_copysignf,
"llvm.copysign.f32"},
1481 {LibFunc_copysign,
"llvm.copysign.f64"},
1482 {LibFunc_copysignl,
"llvm.copysign.f80"},
1483 {LibFunc_floorf,
"llvm.floor.f32"},
1484 {LibFunc_floor,
"llvm.floor.f64"},
1485 {LibFunc_floorl,
"llvm.floor.f80"},
1486 {LibFunc_fmaxf,
"llvm.maxnum.f32"},
1487 {LibFunc_fmax,
"llvm.maxnum.f64"},
1488 {LibFunc_fmaxl,
"llvm.maxnum.f80"},
1489 {LibFunc_fminf,
"llvm.minnum.f32"},
1490 {LibFunc_fmin,
"llvm.minnum.f64"},
1491 {LibFunc_fminl,
"llvm.minnum.f80"},
1492 {LibFunc_fmaximum_numf,
"llvm.maximumnum.f32"},
1493 {LibFunc_fmaximum_num,
"llvm.maximumnum.f64"},
1494 {LibFunc_fmaximum_numl,
"llvm.maximumnum.f80"},
1495 {LibFunc_fminimum_numf,
"llvm.minimumnum.f32"},
1496 {LibFunc_fminimum_num,
"llvm.minimumnum.f64"},
1497 {LibFunc_fminimum_numl,
"llvm.minimumnum.f80"},
1498 {LibFunc_ceilf,
"llvm.ceil.f32"},
1499 {LibFunc_ceil,
"llvm.ceil.f64"},
1500 {LibFunc_ceill,
"llvm.ceil.f80"},
1501 {LibFunc_truncf,
"llvm.trunc.f32"},
1502 {LibFunc_trunc,
"llvm.trunc.f64"},
1503 {LibFunc_truncl,
"llvm.trunc.f80"},
1504 {LibFunc_rintf,
"llvm.rint.f32"},
1505 {LibFunc_rint,
"llvm.rint.f64"},
1506 {LibFunc_rintl,
"llvm.rint.f80"},
1507 {LibFunc_nearbyintf,
"llvm.nearbyint.f32"},
1508 {LibFunc_nearbyint,
"llvm.nearbyint.f64"},
1509 {LibFunc_nearbyintl,
"llvm.nearbyint.f80"},
1510 {LibFunc_roundf,
"llvm.round.f32"},
1511 {LibFunc_round,
"llvm.round.f64"},
1512 {LibFunc_roundl,
"llvm.round.f80"},
1515const char *KnownIntrinsic::get(LibFunc LFunc) {
1516 for (
const auto &
E : kLibfuncIntrinsics) {
1517 if (
E.LFunc == LFunc)
1518 return E.IntrinsicName;
1523const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(StringRef Name) {
1524 for (
const auto &
E : kWidenedIntrinsics) {
1525 if (
E.NarrowName == Name)
1535 if (LFunc == NotLibFunc)
1538 if (
const char *Name = KnownIntrinsic::get(LFunc))
1546Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1547 CallBase &
Call,
Type *VT,
Type *ExtendedVT,
const TargetLibraryInfo &TLI,
1548 const ValueToShadowMap &Map,
IRBuilder<> &Builder) {
1554 FunctionType *WidenedFnTy =
nullptr;
1556 const auto *Widened = KnownIntrinsic::widen(Fn->
getName());
1558 WidenedId = Widened->ID;
1559 WidenedFnTy = Widened->MakeFnTy(
Context);
1570 const auto *Widened = KnownIntrinsic::widen(Name);
1571 assert(Widened &&
"make sure KnownIntrinsic entries are consistent");
1572 WidenedId = Widened->ID;
1573 WidenedFnTy = Widened->MakeFnTy(
Context);
1581 [[maybe_unused]]
bool IsValid =
1583 assert(IsValid &&
"invalid widened intrinsic");
1586 SmallVector<Value *, 4>
Args;
1591 Type *IntrinsicArgTy = WidenedFnTy->getParamType(
I);
1592 if (OrigArgTy == IntrinsicArgTy) {
1593 Args.push_back(Arg);
1596 Type *ShadowArgTy = Config.getExtendedFPType(Arg->
getType());
1598 "don't know how to get the shadow value for a non-FT");
1599 Value *Shadow =
Map.getShadow(Arg);
1600 if (ShadowArgTy == IntrinsicArgTy) {
1603 Args.push_back(Shadow);
1610 return WidenedFnTy->getReturnType() == ExtendedVT
1617Value *NumericalStabilitySanitizer::handleCallBase(CallBase &
Call,
Type *VT,
1619 const TargetLibraryInfo &TLI,
1620 const ValueToShadowMap &Map,
1630 maybeHandleKnownCallBase(
Call, VT, ExtendedVT, TLI, Map, Builder))
1636 Builder.
CreateLoad(IntptrTy, NsanShadowRetTag,
false);
1646 ++NumInstrumentedFTCalls;
1652Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1653 Instruction &Inst,
const TargetLibraryInfo &TLI,
1654 const ValueToShadowMap &Map) {
1656 Type *ExtendedVT = Config.getExtendedFPType(VT);
1657 assert(ExtendedVT !=
nullptr &&
"trying to create a shadow for a non-FT");
1660 return handleLoad(*
Load, VT, ExtendedVT);
1667 return handleCallBase(*
Call, VT, ExtendedVT, TLI, Map, Builder);
1674 BasicBlock *NextBB = Invoke->getNormalDest();
1681 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1691 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1693 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1696 return Builder.
CreateUnOp(UnaryOp->getOpcode(),
1697 Map.getShadow(UnaryOp->getOperand(0)));
1701 Map.getShadow(BinOp->getOperand(0)),
1702 Map.getShadow(BinOp->getOperand(1)));
1706 return Builder.
CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1712 Map.getShadow(S->getTrueValue()),
1713 Map.getShadow(S->getFalseValue()));
1720 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1729 Map.getShadow(Shuffle->getOperand(1)),
1730 Shuffle->getShuffleMask());
1747void NumericalStabilitySanitizer::maybeCreateShadowValue(
1748 Instruction &Root,
const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
1750 Type *ExtendedVT = Config.getExtendedFPType(VT);
1751 if (ExtendedVT ==
nullptr)
1754 if (
Map.hasShadow(&Root))
1759 std::vector<Instruction *> DfsStack(1, &Root);
1760 while (!DfsStack.empty()) {
1766 if (
Map.hasShadow(
I)) {
1767 DfsStack.pop_back();
1771 bool MissingShadow =
false;
1773 Type *VT =
Op->getType();
1774 if (!Config.getExtendedFPType(VT))
1776 if (
Map.hasShadow(
Op))
1778 MissingShadow =
true;
1785 Value *Shadow = createShadowValueWithOperandsAvailable(*
I, TLI, Map);
1786 Map.setShadow(*
I, *Shadow);
1787 DfsStack.pop_back();
1792void NumericalStabilitySanitizer::propagateFTStore(
1793 StoreInst &
Store,
Type *VT,
Type *ExtendedVT,
const ValueToShadowMap &Map) {
1794 Value *StoredValue =
Store.getValueOperand();
1797 const auto Extents = getMemoryExtentsOrDie(VT);
1799 NsanGetShadowPtrForStore[Extents.ValueType],
1800 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1802 Value *StoredShadow =
Map.getShadow(StoredValue);
1803 if (!
Store.getParent()->getParent()->hasOptNone()) {
1807 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1808 CheckLoc::makeStore(
Store.getPointerOperand()));
1809 ++NumInstrumentedFTStores;
1814 Store.isVolatile());
1825void NumericalStabilitySanitizer::propagateNonFTStore(
1826 StoreInst &
Store,
Type *VT,
const ValueToShadowMap &Map) {
1831 TypeSize SlotSize =
DL.getTypeStoreSize(VT);
1837 ++NumInstrumentedNonFTStores;
1838 Value *StoredValue =
Store.getValueOperand();
1845 Type *ShadowTypeIntTy = Type::getIntNTy(
Context, 8 * LoadSizeBytes);
1846 Type *ShadowValueIntTy =
1850 Value *LoadSrc =
Load->getPointerOperand();
1856 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1858 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}),
Align(1),
1860 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1862 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}),
Align(1),
1867 RawShadowType, Builder.
CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1871 Builder.
CreateCall(NsanGetRawShadowPtr, {Dst}),
1875 ++NumInstrumentedNonFTMemcpyStores;
1883 Type *BitcastTy =
nullptr;
1885 switch (
C->getType()->getScalarSizeInBits()) {
1887 BitcastTy = Type::getFloatTy(
Context);
1890 BitcastTy = Type::getDoubleTy(
Context);
1893 BitcastTy = Type::getX86_FP80Ty(
Context);
1901 BitcastTy = VectorType::get(BitcastTy, VectorTy->getElementCount());
1904 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1906 NsanGetShadowPtrForStore[Extents.ValueType],
1907 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1909 Type *ExtVT = Config.getExtendedFPType(BitcastTy);
1913 Store.isVolatile());
1918 Builder.
CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});
1921void NumericalStabilitySanitizer::propagateShadowValues(
1922 Instruction &Inst,
const TargetLibraryInfo &TLI,
1923 const ValueToShadowMap &Map) {
1925 Value *StoredValue =
Store->getValueOperand();
1927 Type *ExtendedVT = Config.getExtendedFPType(VT);
1928 if (ExtendedVT ==
nullptr)
1929 return propagateNonFTStore(*
Store, VT, Map);
1930 return propagateFTStore(*
Store, VT, ExtendedVT, Map);
1934 emitFCmpCheck(*FCmp, Map);
1939 maybeAddSuffixForNsanInterface(CB);
1943 instrumentMemIntrinsic(
MI);
1946 populateShadowStack(*CB, TLI, Map);
1954 Value *RV = RetInst->getReturnValue();
1958 Type *ExtendedVT = Config.getExtendedFPType(VT);
1959 if (ExtendedVT ==
nullptr)
1961 Value *RVShadow =
Map.getShadow(RV);
1964 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1965 ++NumInstrumentedFTRets;
1971 Value *ShadowRetValPtr =
1979 Type *VT =
V->getType();
1980 Type *ExtendedVT = Config.getExtendedFPType(VT);
1981 if (ExtendedVT ==
nullptr)
1984 emitCheck(V,
Map.getShadow(V), Builder, CheckLoc::makeInsert());
1993 std::vector<Instruction *> &Instructions) {
1995#define MOVE_FLAG(attr, setter) \
1996 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
1997 F.removeFnAttr(attr); \
1998 FMF.set##setter(); \
2000 MOVE_FLAG(
"no-signed-zeros-fp-math", NoSignedZeros)
2005 I->setFastMathFlags(FMF);
2008bool NumericalStabilitySanitizer::sanitizeFunction(
2009 Function &
F,
const TargetLibraryInfo &TLI) {
2010 if (!
F.hasFnAttribute(Attribute::SanitizeNumericalStability) ||
2107 std::vector<Instruction *> OriginalInstructions;
2108 for (BasicBlock &BB :
F)
2109 for (Instruction &Inst : BB)
2110 OriginalInstructions.emplace_back(&Inst);
2113 ValueToShadowMap ValueToShadow(Config);
2118 std::vector<PHINode *> OriginalPhis;
2119 createShadowArguments(
F, TLI, ValueToShadow);
2120 for (Instruction *
I : OriginalInstructions) {
2122 if (PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2123 OriginalPhis.push_back(Phi);
2124 ValueToShadow.setShadow(*Phi, *Shadow);
2130 for (Instruction *
I : OriginalInstructions)
2131 maybeCreateShadowValue(*
I, TLI, ValueToShadow);
2134 for (Instruction *
I : OriginalInstructions)
2135 propagateShadowValues(*
I, TLI, ValueToShadow);
2138 for (PHINode *Phi : OriginalPhis) {
2139 PHINode *ShadowPhi =
cast<PHINode>(ValueToShadow.getShadow(Phi));
2140 for (
unsigned I :
seq(
Phi->getNumOperands())) {
2142 Value *Shadow = ValueToShadow.getShadow(V);
2154 return !ValueToShadow.empty();
2161 if (CInt && CInt->getValue().getBitWidth() <= 64)
2162 OpSize = CInt->getValue().getZExtValue();
2170bool NumericalStabilitySanitizer::instrumentMemIntrinsic(MemIntrinsic *
MI) {
2173 FunctionCallee SetUnknownFn =
2174 NsanSetUnknownFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2176 Builder.
CreateCall(SetUnknownFn, {
M->getArgOperand(0)});
2179 {
M->getArgOperand(0),
2184 FunctionCallee CopyFn =
2185 NsanCopyFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2189 M->getArgOperand(1)});
2192 M->getArgOperand(1),
2200void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(CallBase *CI) {
2208 if (Fn->
getName() ==
"__nsan_dump_shadow_mem") {
2210 "invalid prototype for __nsan_dump_shadow_mem");
2215 const uint64_t shadow_value_type_ids =
2216 (
static_cast<size_t>(Config.byValueType(kLongDouble).getNsanTypeId())
2218 (
static_cast<size_t>(Config.byValueType(kDouble).getNsanTypeId())
2220 static_cast<size_t>(Config.byValueType(kFloat).getNsanTypeId());
2221 CI->
setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
static constexpr Value * getValue(Ty &ValueOrUse)
Machine Check Debug Module
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
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
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)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
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.
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="")
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
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={})
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
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="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
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)
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(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
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...
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.
StringRef getName(LibFunc F) const
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
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.
@ BasicBlock
Various leaf nodes.
LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT, SmallVectorImpl< Type * > &OverloadTys, raw_ostream &OS=nulls())
Returns true if FT is a valid function type for intrinsic ID.
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
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,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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<X> - 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
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
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)