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 const 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(),
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))
860 if (Fn->isIntrinsic() || TLI.
getLibFunc(*Fn, LFunc))
868 unsigned ShadowArgId = 0;
871 Type *ExtendedVT = Config.getExtendedFPType(VT);
872 if (ExtendedVT ==
nullptr)
874 Builder.CreateAlignedStore(
875 ArgShadows[ShadowArgId++],
876 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
877 ShadowArgsOffsetBytes),
879 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
881 ShadowArgsOffsetBytes += SlotSize;
893Value *NumericalStabilitySanitizer::emitCheckInternal(
Value *V,
Value *ShadowV,
898 return ConstantInt::get(
902 Type *Ty =
V->getType();
903 if (
const auto VT = ftValueTypeFromType(Ty))
906 {
V, ShadowV, Loc.getType(
Context), Loc.getValue(IntptrTy, Builder)});
912 assert(!VecTy->isScalableTy() &&
913 "Scalable vector types are not supported yet");
914 Value *CheckResult =
nullptr;
915 for (
int I = 0,
E = VecTy->getElementCount().getFixedValue();
I <
E; ++
I) {
921 Value *ComponentCheckResult =
922 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
923 CheckResult = CheckResult
924 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
925 : ComponentCheckResult;
930 Value *CheckResult =
nullptr;
934 Value *ComponentCheckResult =
935 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
936 CheckResult = CheckResult
937 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
938 : ComponentCheckResult;
943 Value *CheckResult =
nullptr;
949 Value *ComponentCheckResult =
950 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
951 CheckResult = CheckResult
952 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
953 : ComponentCheckResult;
956 return ConstantInt::get(
980 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName())) {
985 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
991 ICmpEQ, Builder.
CreateFPExt(V, Config.getExtendedFPType(
V->getType())),
997void NumericalStabilitySanitizer::emitFCmpCheck(FCmpInst &FCmp,
998 const ValueToShadowMap &Map) {
1003 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName()))
1007 if (Config.getExtendedFPType(
LHS->
getType()) ==
nullptr)
1022 FCmpBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1028 ShadowLHS = FCmpBuilder.CreateFPExt(
1029 FCmpBuilder.CreateFPTrunc(ShadowLHS,
LHS->
getType()), Ty);
1030 ShadowRHS = FCmpBuilder.CreateFPExt(
1031 FCmpBuilder.CreateFPTrunc(ShadowRHS,
RHS->
getType()), Ty);
1034 FCmpBuilder.CreateFCmp(FCmp.
getPredicate(), ShadowLHS, ShadowRHS);
1035 Value *OriginalAndShadowFcmpMatch =
1036 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
1042 OriginalAndShadowFcmpMatch =
1043 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
1048 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
1049 MDBuilder(
Context).createLikelyBranchWeights());
1053 FailBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1055 const auto EmitFailCall = [
this, &FCmp, &FCmpBuilder,
1058 Value *ShadowResult) {
1059 Type *FT =
L->getType();
1060 FunctionCallee *
Callee =
nullptr;
1062 Callee = &(NsanFCmpFail[kFloat]);
1064 Callee = &(NsanFCmpFail[kDouble]);
1067 Callee = &(NsanFCmpFail[kDouble]);
1068 L = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(
Context));
1069 R = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(
Context));
1073 FailBuilder.CreateCall(*Callee, {
L,
R, ShadowL, ShadowR,
1074 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1083 Value *ExtractLHS = FailBuilder.CreateExtractElement(
LHS,
I);
1084 Value *ExtractRHS = FailBuilder.CreateExtractElement(
RHS,
I);
1085 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS,
I);
1086 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS,
I);
1087 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp,
I);
1088 Value *ExtractShadowFCmp =
1089 FailBuilder.CreateExtractElement(ShadowFCmp,
I);
1090 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1091 ExtractFCmp, ExtractShadowFCmp);
1094 EmitFailCall(
LHS,
RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1096 FailBuilder.CreateBr(NextBB);
1098 ++NumInstrumentedFCmp;
1102PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1103 PHINode &Phi,
const TargetLibraryInfo &TLI) {
1105 Type *ExtendedVT = Config.getExtendedFPType(VT);
1106 if (ExtendedVT ==
nullptr)
1116Value *NumericalStabilitySanitizer::handleLoad(LoadInst &Load,
Type *VT,
1120 if (addrPointsToConstantData(
Load.getPointerOperand())) {
1140 const auto Extents = getMemoryExtentsOrDie(VT);
1142 NsanGetShadowPtrForLoad[Extents.ValueType],
1143 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1144 ++NumInstrumentedFTLoads;
1160 LoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1161 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1167 ShadowLoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1168 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1169 ExtendedVT, ShadowPtr,
Align(1),
Load.isVolatile());
1171 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,
1172 CheckLoc::makeLoad(
Load.getPointerOperand()));
1174 ShadowLoadBBBuilder.CreateBr(NextBB);
1178 FExtBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1179 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);
1180 FExtBBBuilder.CreateBr(NextBB);
1184 NextBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1185 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1191Value *NumericalStabilitySanitizer::handleTrunc(
const FPTruncInst &Trunc,
1193 const ValueToShadowMap &Map,
1197 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1230 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1231 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1233 if (SourceTy == ExtendedVT)
1239Value *NumericalStabilitySanitizer::handleExt(
const FPExtInst &Ext,
Type *VT,
1241 const ValueToShadowMap &Map,
1243 Value *OrigSource =
Ext.getOperand(0);
1245 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1277 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1278 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1280 if (SourceTy == ExtendedVT)
1288struct KnownIntrinsic {
1289 struct WidenedIntrinsic {
1290 const char *NarrowName;
1292 using FnTypeFactory = FunctionType *(*)(LLVMContext &);
1293 FnTypeFactory MakeFnTy;
1303 static const WidenedIntrinsic *widen(StringRef Name);
1308 const char *IntrinsicName;
1310 static const LFEntry kLibfuncIntrinsics[];
1312 static const WidenedIntrinsic kWidenedIntrinsics[];
1361const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1459const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1460 {LibFunc_sqrtf,
"llvm.sqrt.f32"},
1461 {LibFunc_sqrt,
"llvm.sqrt.f64"},
1462 {LibFunc_sqrtl,
"llvm.sqrt.f80"},
1463 {LibFunc_sinf,
"llvm.sin.f32"},
1464 {LibFunc_sin,
"llvm.sin.f64"},
1465 {LibFunc_sinl,
"llvm.sin.f80"},
1466 {LibFunc_cosf,
"llvm.cos.f32"},
1467 {LibFunc_cos,
"llvm.cos.f64"},
1468 {LibFunc_cosl,
"llvm.cos.f80"},
1469 {LibFunc_powf,
"llvm.pow.f32"},
1470 {LibFunc_pow,
"llvm.pow.f64"},
1471 {LibFunc_powl,
"llvm.pow.f80"},
1472 {LibFunc_expf,
"llvm.exp.f32"},
1473 {LibFunc_exp,
"llvm.exp.f64"},
1474 {LibFunc_expl,
"llvm.exp.f80"},
1475 {LibFunc_exp2f,
"llvm.exp2.f32"},
1476 {LibFunc_exp2,
"llvm.exp2.f64"},
1477 {LibFunc_exp2l,
"llvm.exp2.f80"},
1478 {LibFunc_logf,
"llvm.log.f32"},
1479 {LibFunc_log,
"llvm.log.f64"},
1480 {LibFunc_logl,
"llvm.log.f80"},
1481 {LibFunc_log10f,
"llvm.log10.f32"},
1482 {LibFunc_log10,
"llvm.log10.f64"},
1483 {LibFunc_log10l,
"llvm.log10.f80"},
1484 {LibFunc_log2f,
"llvm.log2.f32"},
1485 {LibFunc_log2,
"llvm.log2.f64"},
1486 {LibFunc_log2l,
"llvm.log2.f80"},
1487 {LibFunc_fabsf,
"llvm.fabs.f32"},
1488 {LibFunc_fabs,
"llvm.fabs.f64"},
1489 {LibFunc_fabsl,
"llvm.fabs.f80"},
1490 {LibFunc_copysignf,
"llvm.copysign.f32"},
1491 {LibFunc_copysign,
"llvm.copysign.f64"},
1492 {LibFunc_copysignl,
"llvm.copysign.f80"},
1493 {LibFunc_floorf,
"llvm.floor.f32"},
1494 {LibFunc_floor,
"llvm.floor.f64"},
1495 {LibFunc_floorl,
"llvm.floor.f80"},
1496 {LibFunc_fmaxf,
"llvm.maxnum.f32"},
1497 {LibFunc_fmax,
"llvm.maxnum.f64"},
1498 {LibFunc_fmaxl,
"llvm.maxnum.f80"},
1499 {LibFunc_fminf,
"llvm.minnum.f32"},
1500 {LibFunc_fmin,
"llvm.minnum.f64"},
1501 {LibFunc_fminl,
"llvm.minnum.f80"},
1502 {LibFunc_ceilf,
"llvm.ceil.f32"},
1503 {LibFunc_ceil,
"llvm.ceil.f64"},
1504 {LibFunc_ceill,
"llvm.ceil.f80"},
1505 {LibFunc_truncf,
"llvm.trunc.f32"},
1506 {LibFunc_trunc,
"llvm.trunc.f64"},
1507 {LibFunc_truncl,
"llvm.trunc.f80"},
1508 {LibFunc_rintf,
"llvm.rint.f32"},
1509 {LibFunc_rint,
"llvm.rint.f64"},
1510 {LibFunc_rintl,
"llvm.rint.f80"},
1511 {LibFunc_nearbyintf,
"llvm.nearbyint.f32"},
1512 {LibFunc_nearbyint,
"llvm.nearbyint.f64"},
1513 {LibFunc_nearbyintl,
"llvm.nearbyint.f80"},
1514 {LibFunc_roundf,
"llvm.round.f32"},
1515 {LibFunc_round,
"llvm.round.f64"},
1516 {LibFunc_roundl,
"llvm.round.f80"},
1519const char *KnownIntrinsic::get(
LibFunc LFunc) {
1520 for (
const auto &
E : kLibfuncIntrinsics) {
1521 if (
E.LFunc == LFunc)
1522 return E.IntrinsicName;
1527const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(StringRef Name) {
1528 for (
const auto &
E : kWidenedIntrinsics) {
1529 if (
E.NarrowName == Name)
1542 if (
const char *Name = KnownIntrinsic::get(LFunc))
1550Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1551 CallBase &
Call,
Type *VT,
Type *ExtendedVT,
const TargetLibraryInfo &TLI,
1552 const ValueToShadowMap &Map,
IRBuilder<> &Builder) {
1558 FunctionType *WidenedFnTy =
nullptr;
1560 const auto *Widened = KnownIntrinsic::widen(Fn->
getName());
1562 WidenedId = Widened->ID;
1563 WidenedFnTy = Widened->MakeFnTy(
Context);
1574 const auto *Widened = KnownIntrinsic::widen(Name);
1575 assert(Widened &&
"make sure KnownIntrinsic entries are consistent");
1576 WidenedId = Widened->ID;
1577 WidenedFnTy = Widened->MakeFnTy(
Context);
1591 "invalid widened intrinsic");
1599 Type *IntrinsicArgTy = WidenedFnTy->getParamType(
I);
1600 if (OrigArgTy == IntrinsicArgTy) {
1601 Args.push_back(Arg);
1604 Type *ShadowArgTy = Config.getExtendedFPType(Arg->
getType());
1606 "don't know how to get the shadow value for a non-FT");
1607 Value *Shadow =
Map.getShadow(Arg);
1608 if (ShadowArgTy == IntrinsicArgTy) {
1611 Args.push_back(Shadow);
1618 return WidenedFnTy->getReturnType() == ExtendedVT
1625Value *NumericalStabilitySanitizer::handleCallBase(CallBase &
Call,
Type *VT,
1627 const TargetLibraryInfo &TLI,
1628 const ValueToShadowMap &Map,
1638 maybeHandleKnownCallBase(
Call, VT, ExtendedVT, TLI, Map, Builder))
1644 Builder.
CreateLoad(IntptrTy, NsanShadowRetTag,
false);
1654 ++NumInstrumentedFTCalls;
1660Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1661 Instruction &Inst,
const TargetLibraryInfo &TLI,
1662 const ValueToShadowMap &Map) {
1664 Type *ExtendedVT = Config.getExtendedFPType(VT);
1665 assert(ExtendedVT !=
nullptr &&
"trying to create a shadow for a non-FT");
1668 return handleLoad(*Load, VT, ExtendedVT);
1675 return handleCallBase(*
Call, VT, ExtendedVT, TLI, Map, Builder);
1682 BasicBlock *NextBB = Invoke->getNormalDest();
1689 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1699 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1701 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1704 return Builder.
CreateUnOp(UnaryOp->getOpcode(),
1705 Map.getShadow(UnaryOp->getOperand(0)));
1709 Map.getShadow(BinOp->getOperand(0)),
1710 Map.getShadow(BinOp->getOperand(1)));
1714 return Builder.
CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1720 Map.getShadow(S->getTrueValue()),
1721 Map.getShadow(S->getFalseValue()));
1728 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1737 Map.getShadow(Shuffle->getOperand(1)),
1738 Shuffle->getShuffleMask());
1755void NumericalStabilitySanitizer::maybeCreateShadowValue(
1756 Instruction &Root,
const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
1758 Type *ExtendedVT = Config.getExtendedFPType(VT);
1759 if (ExtendedVT ==
nullptr)
1762 if (
Map.hasShadow(&Root))
1767 std::vector<Instruction *> DfsStack(1, &Root);
1768 while (!DfsStack.empty()) {
1774 if (
Map.hasShadow(
I)) {
1775 DfsStack.pop_back();
1779 bool MissingShadow =
false;
1781 Type *VT =
Op->getType();
1782 if (!Config.getExtendedFPType(VT))
1784 if (
Map.hasShadow(
Op))
1786 MissingShadow =
true;
1793 Value *Shadow = createShadowValueWithOperandsAvailable(*
I, TLI, Map);
1794 Map.setShadow(*
I, *Shadow);
1795 DfsStack.pop_back();
1800void NumericalStabilitySanitizer::propagateFTStore(
1801 StoreInst &Store,
Type *VT,
Type *ExtendedVT,
const ValueToShadowMap &Map) {
1802 Value *StoredValue =
Store.getValueOperand();
1805 const auto Extents = getMemoryExtentsOrDie(VT);
1807 NsanGetShadowPtrForStore[Extents.ValueType],
1808 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1810 Value *StoredShadow =
Map.getShadow(StoredValue);
1811 if (!
Store.getParent()->getParent()->hasOptNone()) {
1815 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1816 CheckLoc::makeStore(
Store.getPointerOperand()));
1817 ++NumInstrumentedFTStores;
1822 Store.isVolatile());
1833void NumericalStabilitySanitizer::propagateNonFTStore(
1834 StoreInst &Store,
Type *VT,
const ValueToShadowMap &Map) {
1839 TypeSize SlotSize =
DL.getTypeStoreSize(VT);
1845 ++NumInstrumentedNonFTStores;
1846 Value *StoredValue =
Store.getValueOperand();
1853 Type *ShadowTypeIntTy = Type::getIntNTy(
Context, 8 * LoadSizeBytes);
1854 Type *ShadowValueIntTy =
1858 Value *LoadSrc =
Load->getPointerOperand();
1864 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1866 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}),
Align(1),
1868 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1870 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}),
Align(1),
1875 RawShadowType, Builder.
CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1879 Builder.
CreateCall(NsanGetRawShadowPtr, {Dst}),
1883 ++NumInstrumentedNonFTMemcpyStores;
1891 Type *BitcastTy =
nullptr;
1893 switch (CInt->getType()->getScalarSizeInBits()) {
1895 BitcastTy = Type::getFloatTy(
Context);
1898 BitcastTy = Type::getDoubleTy(
Context);
1901 BitcastTy = Type::getX86_FP80Ty(
Context);
1907 const int NumElements =
1909 switch (CDV->getType()->getScalarSizeInBits()) {
1912 VectorType::get(Type::getFloatTy(
Context), NumElements,
false);
1916 VectorType::get(Type::getDoubleTy(
Context), NumElements,
false);
1920 VectorType::get(Type::getX86_FP80Ty(
Context), NumElements,
false);
1927 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1929 NsanGetShadowPtrForStore[Extents.ValueType],
1930 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1932 Type *ExtVT = Config.getExtendedFPType(BitcastTy);
1936 Store.isVolatile());
1941 Builder.
CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});
1944void NumericalStabilitySanitizer::propagateShadowValues(
1945 Instruction &Inst,
const TargetLibraryInfo &TLI,
1946 const ValueToShadowMap &Map) {
1948 Value *StoredValue =
Store->getValueOperand();
1950 Type *ExtendedVT = Config.getExtendedFPType(VT);
1951 if (ExtendedVT ==
nullptr)
1952 return propagateNonFTStore(*Store, VT, Map);
1953 return propagateFTStore(*Store, VT, ExtendedVT, Map);
1957 emitFCmpCheck(*FCmp, Map);
1962 maybeAddSuffixForNsanInterface(CB);
1966 instrumentMemIntrinsic(
MI);
1969 populateShadowStack(*CB, TLI, Map);
1977 Value *RV = RetInst->getReturnValue();
1981 Type *ExtendedVT = Config.getExtendedFPType(VT);
1982 if (ExtendedVT ==
nullptr)
1984 Value *RVShadow =
Map.getShadow(RV);
1987 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1988 ++NumInstrumentedFTRets;
1994 Value *ShadowRetValPtr =
2002 Type *VT =
V->getType();
2003 Type *ExtendedVT = Config.getExtendedFPType(VT);
2004 if (ExtendedVT ==
nullptr)
2007 emitCheck(V,
Map.getShadow(V), Builder, CheckLoc::makeInsert());
2016 std::vector<Instruction *> &Instructions) {
2018#define MOVE_FLAG(attr, setter) \
2019 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
2020 F.removeFnAttr(attr); \
2021 FMF.set##setter(); \
2026 MOVE_FLAG(
"no-signed-zeros-fp-math", NoSignedZeros)
2031 I->setFastMathFlags(FMF);
2034bool NumericalStabilitySanitizer::sanitizeFunction(
2035 Function &
F,
const TargetLibraryInfo &TLI) {
2036 if (!
F.hasFnAttribute(Attribute::SanitizeNumericalStability) ||
2133 std::vector<Instruction *> OriginalInstructions;
2134 for (BasicBlock &BB :
F)
2135 for (Instruction &Inst : BB)
2136 OriginalInstructions.emplace_back(&Inst);
2139 ValueToShadowMap ValueToShadow(Config);
2144 std::vector<PHINode *> OriginalPhis;
2145 createShadowArguments(
F, TLI, ValueToShadow);
2146 for (Instruction *
I : OriginalInstructions) {
2148 if (PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2149 OriginalPhis.push_back(Phi);
2150 ValueToShadow.setShadow(*Phi, *Shadow);
2156 for (Instruction *
I : OriginalInstructions)
2157 maybeCreateShadowValue(*
I, TLI, ValueToShadow);
2160 for (Instruction *
I : OriginalInstructions)
2161 propagateShadowValues(*
I, TLI, ValueToShadow);
2164 for (PHINode *Phi : OriginalPhis) {
2165 PHINode *ShadowPhi =
cast<PHINode>(ValueToShadow.getShadow(Phi));
2166 for (
unsigned I :
seq(
Phi->getNumOperands())) {
2168 Value *Shadow = ValueToShadow.getShadow(V);
2180 return !ValueToShadow.empty();
2187 if (CInt && CInt->getValue().getBitWidth() <= 64)
2188 OpSize = CInt->getValue().getZExtValue();
2196bool NumericalStabilitySanitizer::instrumentMemIntrinsic(MemIntrinsic *
MI) {
2199 FunctionCallee SetUnknownFn =
2200 NsanSetUnknownFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2202 Builder.
CreateCall(SetUnknownFn, {
M->getArgOperand(0)});
2205 {
M->getArgOperand(0),
2210 FunctionCallee CopyFn =
2211 NsanCopyFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2215 M->getArgOperand(1)});
2218 M->getArgOperand(1),
2226void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(CallBase *CI) {
2234 if (Fn->
getName() ==
"__nsan_dump_shadow_mem") {
2236 "invalid prototype for __nsan_dump_shadow_mem");
2241 const uint64_t shadow_value_type_ids =
2242 (
static_cast<size_t>(Config.byValueType(kLongDouble).getNsanTypeId())
2244 (
static_cast<size_t>(Config.byValueType(kDouble).getNsanTypeId())
2246 static_cast<size_t>(Config.byValueType(kFloat).getNsanTypeId());
2247 CI->
setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ArrayRef< TableEntry > TableRef
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)
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
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)
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction & back() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
InstListType::iterator iterator
Instruction iterators...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
void setArgOperand(unsigned i, Value *v)
unsigned arg_size() const
Predicate getPredicate() const
Return the predicate for this instruction.
ConstantFP - Floating Point Values [float, double].
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
This instruction compares its operands according to the predicate given to the constructor.
static bool isEquality(Predicate Pred)
This class represents an extension of floating point types.
This class represents a truncation of floating point types.
Convenience struct for specifying and reasoning about fast-math flags.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType()
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
@ ExternalLinkage
Externally visible function.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateFreeze(Value *V, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateFPExt(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB)
Replace specified successor OldBB to point at the provided block.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
const char * getOpcodeName() const
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
This is the common base class for memset/memcpy/memmove.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
StringRef getName(LibFunc F) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isX86_FP80Ty() const
Return true if this is x86 long double.
bool isArrayTy() const
True if this is an instance of ArrayType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI Type * getPPC_FP128Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
LLVM_ABI unsigned getStructNumElements() const
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
'undef' values are things that do not have specified contents.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI MatchIntrinsicTypesResult matchIntrinsicSignature(FunctionType *FTy, ArrayRef< IITDescriptor > &Infos, SmallVectorImpl< Type * > &ArgTys)
Match the specified function type with the type constraints specified by the .td file.
LLVM_ABI void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl< IITDescriptor > &T)
Return the IIT table descriptor for the specified intrinsic into an array of IITDescriptors.
MatchIntrinsicTypesResult
@ MatchIntrinsicTypes_Match
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
Context & getContext() const
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<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
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
static constexpr roundingMode rmTowardZero
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)