51#define DEBUG_TYPE "nsan"
54 "Number of instrumented floating-point loads");
57 "Number of instrumented floating-point calls");
59 "Number of instrumented floating-point returns");
61 "Number of instrumented floating-point stores");
63 "Number of instrumented non floating-point stores");
65 NumInstrumentedNonFTMemcpyStores,
66 "Number of instrumented non floating-point stores with memcpy semantics");
67STATISTIC(NumInstrumentedFCmp,
"Number of instrumented fcmps");
73 "nsan-shadow-type-mapping",
cl::init(
"dqq"),
74 cl::desc(
"One shadow type id for each of `float`, `double`, `long double`. "
75 "`d`,`l`,`q`,`e` mean double, x86_fp80, fp128 (quad) and "
76 "ppc_fp128 (extended double) respectively. The default is to "
77 "shadow `float` as `double`, and `double` and `x86_fp80` as "
83 cl::desc(
"Instrument floating-point comparisons"),
87 "check-functions-filter",
88 cl::desc(
"Only emit checks for arguments of functions "
89 "whose names match the given regular expression"),
93 "nsan-truncate-fcmp-eq",
cl::init(
true),
95 "This flag controls the behaviour of fcmp equality comparisons."
96 "For equality comparisons such as `x == 0.0f`, we can perform the "
97 "shadow check in the shadow (`x_shadow == 0.0) == (x == 0.0f)`) or app "
98 " domain (`(trunc(x_shadow) == 0.0f) == (x == 0.0f)`). This helps "
99 "catch the case when `x_shadow` is accurate enough (and therefore "
100 "close enough to zero) so that `trunc(x_shadow)` is zero even though "
101 "both `x` and `x_shadow` are not"),
114 cl::desc(
"Check floating-point load"),
118 cl::desc(
"Check floating-point stores"),
122 cl::desc(
"Check floating-point return values"),
132 "nsan-propagate-non-ft-const-stores-as-ft",
134 "Propagate non floating-point const stores as floating point values."
135 "For debugging purposes only"),
151class ShadowTypeConfig {
153 static std::unique_ptr<ShadowTypeConfig> fromNsanTypeId(
char TypeId);
159 virtual char getNsanTypeId()
const = 0;
161 virtual ~ShadowTypeConfig() =
default;
164template <
char NsanTypeId>
165class ShadowTypeConfigImpl :
public ShadowTypeConfig {
167 char getNsanTypeId()
const override {
return NsanTypeId; }
168 static constexpr const char kNsanTypeId = NsanTypeId;
172class F64ShadowConfig :
public ShadowTypeConfigImpl<'d'> {
179class F80ShadowConfig :
public ShadowTypeConfigImpl<'l'> {
186class F128ShadowConfig :
public ShadowTypeConfigImpl<'q'> {
193class PPC128ShadowConfig :
public ShadowTypeConfigImpl<'e'> {
200std::unique_ptr<ShadowTypeConfig>
201ShadowTypeConfig::fromNsanTypeId(
const char TypeId) {
203 case F64ShadowConfig::kNsanTypeId:
204 return std::make_unique<F64ShadowConfig>();
205 case F80ShadowConfig::kNsanTypeId:
206 return std::make_unique<F80ShadowConfig>();
207 case F128ShadowConfig::kNsanTypeId:
208 return std::make_unique<F128ShadowConfig>();
209 case PPC128ShadowConfig::kNsanTypeId:
210 return std::make_unique<PPC128ShadowConfig>();
217enum FTValueType { kFloat, kDouble, kLongDouble, kNumValueTypes };
220static std::optional<FTValueType> ftValueTypeFromType(
Type *FT) {
231static Type *typeFromFTValueType(FTValueType VT,
LLVMContext &Context) {
246static const char *typeNameFromFTValueType(FTValueType VT) {
267 unsigned ShadowTypeSizeBits[kNumValueTypes];
268 for (
int VT = 0; VT < kNumValueTypes; ++VT) {
273 const unsigned AppTypeSize =
274 typeFromFTValueType(
static_cast<FTValueType
>(VT), Context)
275 ->getScalarSizeInBits();
276 const unsigned ShadowTypeSize =
277 Config->getType(Context)->getScalarSizeInBits();
282 "->f" +
Twine(ShadowTypeSize) +
283 ": The shadow type size should be at most " +
285 " times the application type size");
286 ShadowTypeSizeBits[VT] = ShadowTypeSize;
287 Configs[VT] = std::move(
Config);
296 if (ShadowTypeSizeBits[kFloat] > ShadowTypeSizeBits[kDouble] ||
297 ShadowTypeSizeBits[kDouble] > ShadowTypeSizeBits[kLongDouble])
299 Twine(ShadowTypeSizeBits[kFloat]) +
"; double->f" +
300 Twine(ShadowTypeSizeBits[kDouble]) +
302 Twine(ShadowTypeSizeBits[kLongDouble]) +
" }");
305 const ShadowTypeConfig &byValueType(FTValueType VT)
const {
306 assert(VT < FTValueType::kNumValueTypes &&
"invalid value type");
311 Type *getExtendedFPType(
Type *FT)
const {
312 if (
const auto VT = ftValueTypeFromType(FT))
313 return Configs[*VT]->getType(Context);
315 auto *VecTy = cast<VectorType>(FT);
317 if (VecTy->isScalableTy())
319 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());
320 return ExtendedScalar
321 ? VectorType::get(ExtendedScalar, VecTy->getElementCount())
329 std::unique_ptr<ShadowTypeConfig> Configs[FTValueType::kNumValueTypes];
334struct MemoryExtents {
339static MemoryExtents getMemoryExtentsOrDie(
Type *FT) {
340 if (
const auto VT = ftValueTypeFromType(FT))
342 if (
auto *VecTy = dyn_cast<VectorType>(FT)) {
343 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());
344 return {ScalarExtents.ValueType,
345 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};
354 static CheckLoc makeStore(
Value *Address) {
355 CheckLoc Result(kStore);
356 Result.Address = Address;
359 static CheckLoc makeLoad(
Value *Address) {
360 CheckLoc Result(kLoad);
361 Result.Address = Address;
366 static CheckLoc makeArg(
int ArgId) {
367 CheckLoc Result(kArg);
368 Result.ArgId = ArgId;
373 static CheckLoc makeRet() {
return CheckLoc(kRet); }
376 static CheckLoc makeInsert() {
return CheckLoc(kInsert); }
393 return ConstantInt::get(IntptrTy, 0);
395 return ConstantInt::get(IntptrTy, ArgId);
414 explicit CheckLoc(CheckType CheckTy) : CheckTy(CheckTy) {}
416 Value *Address =
nullptr;
417 const CheckType CheckTy;
422class ValueToShadowMap {
426 ValueToShadowMap(
const ValueToShadowMap &) =
delete;
427 ValueToShadowMap &operator=(
const ValueToShadowMap &) =
delete;
432 [[maybe_unused]]
const bool Inserted = Map.try_emplace(&V, &Shadow).second;
435 if (
auto *
I = dyn_cast<Instruction>(&V))
436 errs() <<
I->getFunction()->getName() <<
": ";
437 errs() <<
"duplicate shadow (" << &V <<
"): ";
441 assert(Inserted &&
"duplicate shadow");
446 bool hasShadow(
Value *V)
const {
447 return isa<Constant>(V) || (Map.find(V) != Map.end());
454 return getShadowConstant(
C);
455 return Map.find(V)->second;
458 bool empty()
const {
return Map.empty(); }
463 bool LosesInfo =
false;
475 Type *Ty =
Config.getExtendedFPType(CFP->getType());
476 return ConstantFP::get(
480 if (
C->getType()->isVectorTy()) {
482 for (
int I = 0, E = cast<VectorType>(
C->getType())
486 Elements.push_back(getShadowConstant(
C->getAggregateElement(
I)));
492 const MappingConfig &
Config;
500class NumericalStabilitySanitizer {
502 NumericalStabilitySanitizer(
Module &M);
507 void maybeAddSuffixForNsanInterface(
CallBase *CI);
508 bool addrPointsToConstantData(
Value *
Addr);
510 ValueToShadowMap &Map);
513 const ValueToShadowMap &Map);
516 ValueToShadowMap &Map);
519 const ValueToShadowMap &Map);
522 const ValueToShadowMap &Map);
527 void emitFCmpCheck(
FCmpInst &FCmp,
const ValueToShadowMap &Map);
533 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
536 const ValueToShadowMap &Map,
539 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
541 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
545 const ValueToShadowMap &Map);
547 const ValueToShadowMap &Map);
553 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};
554 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};
563 Type *NsanShadowRetType =
nullptr;
568 Type *NsanShadowArgsType =
nullptr;
571 std::optional<Regex> CheckFunctionsFilter;
584 NumericalStabilitySanitizer Nsan(M);
593 return dyn_cast<GlobalValue>(M.getOrInsertGlobal(
Name, Ty, [&M, Ty,
Name] {
594 return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
595 nullptr, Name, nullptr,
596 GlobalVariable::InitialExecTLSModel);
600NumericalStabilitySanitizer::NumericalStabilitySanitizer(
Module &M)
601 :
DL(
M.getDataLayout()), Context(
M.getContext()),
Config(Context) {
602 IntptrTy =
DL.getIntPtrType(Context);
603 Type *PtrTy = PointerType::getUnqual(Context);
611 for (
int I = 0;
I < kNumValueTypes; ++
I) {
612 const FTValueType VT =
static_cast<FTValueType
>(
I);
613 const char *VTName = typeNameFromFTValueType(VT);
614 Type *VTTy = typeFromFTValueType(VT, Context);
617 const std::string GetterPrefix =
618 std::string(
"__nsan_get_shadow_ptr_for_") + VTName;
619 NsanGetShadowPtrForStore[VT] =
M.getOrInsertFunction(
620 GetterPrefix +
"_store", Attr, PtrTy, PtrTy, IntptrTy);
621 NsanGetShadowPtrForLoad[VT] =
M.getOrInsertFunction(
622 GetterPrefix +
"_load", Attr, PtrTy, PtrTy, IntptrTy);
625 const auto &ShadowConfig =
Config.byValueType(VT);
626 Type *ShadowTy = ShadowConfig.getType(Context);
628 M.getOrInsertFunction(std::string(
"__nsan_internal_check_") + VTName +
629 "_" + ShadowConfig.getNsanTypeId(),
630 Attr, Int32Ty, VTTy, ShadowTy, Int32Ty, IntptrTy);
631 NsanFCmpFail[VT] =
M.getOrInsertFunction(
632 std::string(
"__nsan_fcmp_fail_") + VTName +
"_" +
633 ShadowConfig.getNsanTypeId(),
634 Attr, VoidTy, VTTy, VTTy, ShadowTy, ShadowTy, Int32Ty, Int1Ty, Int1Ty);
637 NsanCopyValues =
M.getOrInsertFunction(
"__nsan_copy_values", Attr, VoidTy,
638 PtrTy, PtrTy, IntptrTy);
639 NsanSetValueUnknown =
M.getOrInsertFunction(
"__nsan_set_value_unknown", Attr,
640 VoidTy, PtrTy, IntptrTy);
643 NsanGetRawShadowTypePtr =
M.getOrInsertFunction(
644 "__nsan_internal_get_raw_shadow_type_ptr", Attr, PtrTy, PtrTy);
645 NsanGetRawShadowPtr =
M.getOrInsertFunction(
646 "__nsan_internal_get_raw_shadow_ptr", Attr, PtrTy, PtrTy);
667 std::string RegexError;
669 CheckFunctionsFilter = std::move(R);
675bool NumericalStabilitySanitizer::addrPointsToConstantData(
Value *
Addr) {
678 Addr =
GEP->getPointerOperand();
681 return GV->isConstant();
697void NumericalStabilitySanitizer::createShadowArguments(
699 assert(!
F.getIntrinsicID() &&
"found a definition of an intrinsic");
703 return Config.getExtendedFPType(Arg.getType()) == nullptr;
707 IRBuilder<> Builder(
F.getEntryBlock().getFirstNonPHI());
710 Value *HasShadowArgs = Builder.CreateICmpEQ(
711 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag,
false),
712 Builder.CreatePtrToInt(&
F, IntptrTy));
714 unsigned ShadowArgsOffsetBytes = 0;
717 Type *ExtendedVT =
Config.getExtendedFPType(VT);
718 if (ExtendedVT ==
nullptr)
720 Value *
L = Builder.CreateAlignedLoad(
722 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
723 ShadowArgsOffsetBytes),
725 Value *Shadow = Builder.CreateSelect(HasShadowArgs, L,
726 Builder.CreateFPExt(&Arg, ExtendedVT));
727 Map.setShadow(Arg, *Shadow);
728 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
730 ShadowArgsOffsetBytes += SlotSize;
732 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);
738 const std::optional<Regex> &CheckFunctionsFilter) {
742 if (CheckFunctionsFilter) {
746 if (CheckFunctionsFilter->match(Fn->
getName()))
759 LibFunc LFunc = LibFunc::NumLibFuncs;
767 if (
ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||
768 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)
769 for (
const auto &U : CI.
users())
778void NumericalStabilitySanitizer::populateShadowStack(
786 return Config.getExtendedFPType(Arg->getType()) == nullptr;
792 const bool ShouldCheckArgs =
shouldCheckArgs(CI, TLI, CheckFunctionsFilter);
796 Value *ArgShadow =
Map.getShadow(Arg);
797 ArgShadows.
push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,
798 CheckLoc::makeArg(ArgIdx))
805 if (Fn->isIntrinsic() || TLI.
getLibFunc(*Fn, LFunc))
813 unsigned ShadowArgId = 0;
816 Type *ExtendedVT =
Config.getExtendedFPType(VT);
817 if (ExtendedVT ==
nullptr)
819 Builder.CreateAlignedStore(
820 ArgShadows[ShadowArgId++],
821 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
822 ShadowArgsOffsetBytes),
824 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
826 ShadowArgsOffsetBytes += SlotSize;
838Value *NumericalStabilitySanitizer::emitCheckInternal(
Value *V,
Value *ShadowV,
842 if (isa<Constant>(V))
843 return ConstantInt::get(
847 Type *Ty =
V->getType();
848 if (
const auto VT = ftValueTypeFromType(Ty))
851 {
V, ShadowV, Loc.
getType(Context), Loc.getValue(IntptrTy, Builder)});
854 auto *VecTy = cast<VectorType>(Ty);
857 assert(!VecTy->isScalableTy() &&
858 "Scalable vector types are not supported yet");
859 Value *CheckResult =
nullptr;
860 for (
int I = 0, E = VecTy->getElementCount().getFixedValue();
I < E; ++
I) {
866 Value *ComponentCheckResult =
867 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
868 CheckResult = CheckResult
869 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
870 : ComponentCheckResult;
875 Value *CheckResult =
nullptr;
879 Value *ComponentCheckResult =
880 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
881 CheckResult = CheckResult
882 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
883 : ComponentCheckResult;
888 Value *CheckResult =
nullptr;
894 Value *ComponentCheckResult =
895 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
896 CheckResult = CheckResult
897 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
898 : ComponentCheckResult;
901 return ConstantInt::get(
920 if (isa<Constant>(V))
923 if (
Instruction *Inst = dyn_cast<Instruction>(V)) {
925 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName())) {
930 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
942void NumericalStabilitySanitizer::emitFCmpCheck(
FCmpInst &FCmp,
943 const ValueToShadowMap &Map) {
948 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName()))
967 FCmpBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
968 Value *ShadowLHS =
Map.getShadow(LHS);
969 Value *ShadowRHS =
Map.getShadow(RHS);
973 ShadowLHS = FCmpBuilder.CreateFPExt(
974 FCmpBuilder.CreateFPTrunc(ShadowLHS,
LHS->
getType()), Ty);
975 ShadowRHS = FCmpBuilder.CreateFPExt(
976 FCmpBuilder.CreateFPTrunc(ShadowRHS,
RHS->
getType()), Ty);
979 FCmpBuilder.CreateFCmp(FCmp.
getPredicate(), ShadowLHS, ShadowRHS);
980 Value *OriginalAndShadowFcmpMatch =
981 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
987 OriginalAndShadowFcmpMatch =
988 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
993 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
994 MDBuilder(Context).createLikelyBranchWeights());
998 FailBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1000 const auto EmitFailCall = [
this, &FCmp, &FCmpBuilder,
1003 Value *ShadowResult) {
1004 Type *FT =
L->getType();
1007 Callee = &(NsanFCmpFail[kFloat]);
1009 Callee = &(NsanFCmpFail[kDouble]);
1012 Callee = &(NsanFCmpFail[kDouble]);
1018 FailBuilder.CreateCall(*Callee, {
L,
R, ShadowL, ShadowR,
1019 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1024 for (
int I = 0, E = cast<VectorType>(
LHS->
getType())
1028 Value *ExtractLHS = FailBuilder.CreateExtractElement(LHS,
I);
1029 Value *ExtractRHS = FailBuilder.CreateExtractElement(RHS,
I);
1030 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS,
I);
1031 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS,
I);
1032 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp,
I);
1033 Value *ExtractShadowFCmp =
1034 FailBuilder.CreateExtractElement(ShadowFCmp,
I);
1035 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1036 ExtractFCmp, ExtractShadowFCmp);
1039 EmitFailCall(LHS, RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1041 FailBuilder.CreateBr(NextBB);
1043 ++NumInstrumentedFCmp;
1047PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1050 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1051 if (ExtendedVT ==
nullptr)
1065 if (addrPointsToConstantData(
Load.getPointerOperand())) {
1085 const auto Extents = getMemoryExtentsOrDie(VT);
1087 NsanGetShadowPtrForLoad[Extents.ValueType],
1088 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1089 ++NumInstrumentedFTLoads;
1105 LoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1106 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1112 ShadowLoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1113 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1114 ExtendedVT, ShadowPtr,
Align(1),
Load.isVolatile());
1116 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,
1117 CheckLoc::makeLoad(
Load.getPointerOperand()));
1119 ShadowLoadBBBuilder.CreateBr(NextBB);
1123 FExtBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1124 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);
1125 FExtBBBuilder.CreateBr(NextBB);
1129 NextBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1130 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1138 const ValueToShadowMap &Map,
1142 Type *ExtendedSourceTy =
Config.getExtendedFPType(OrigSourceTy);
1175 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1176 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1178 if (SourceTy == ExtendedVT)
1186 const ValueToShadowMap &Map,
1188 Value *OrigSource =
Ext.getOperand(0);
1190 Type *ExtendedSourceTy =
Config.getExtendedFPType(OrigSourceTy);
1222 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1223 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1225 if (SourceTy == ExtendedVT)
1233struct KnownIntrinsic {
1234 struct WidenedIntrinsic {
1235 const char *NarrowName;
1238 FnTypeFactory MakeFnTy;
1253 const char *IntrinsicName;
1255 static const LFEntry kLibfuncIntrinsics[];
1257 static const WidenedIntrinsic kWidenedIntrinsics[];
1293 return FunctionType::get(
1300 return FunctionType::get(
1306const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1404const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1405 {LibFunc_sqrtf,
"llvm.sqrt.f32"},
1406 {LibFunc_sqrt,
"llvm.sqrt.f64"},
1407 {LibFunc_sqrtl,
"llvm.sqrt.f80"},
1408 {LibFunc_sinf,
"llvm.sin.f32"},
1409 {LibFunc_sin,
"llvm.sin.f64"},
1410 {LibFunc_sinl,
"llvm.sin.f80"},
1411 {LibFunc_cosf,
"llvm.cos.f32"},
1412 {LibFunc_cos,
"llvm.cos.f64"},
1413 {LibFunc_cosl,
"llvm.cos.f80"},
1414 {LibFunc_powf,
"llvm.pow.f32"},
1415 {LibFunc_pow,
"llvm.pow.f64"},
1416 {LibFunc_powl,
"llvm.pow.f80"},
1417 {LibFunc_expf,
"llvm.exp.f32"},
1418 {LibFunc_exp,
"llvm.exp.f64"},
1419 {LibFunc_expl,
"llvm.exp.f80"},
1420 {LibFunc_exp2f,
"llvm.exp2.f32"},
1421 {LibFunc_exp2,
"llvm.exp2.f64"},
1422 {LibFunc_exp2l,
"llvm.exp2.f80"},
1423 {LibFunc_logf,
"llvm.log.f32"},
1424 {LibFunc_log,
"llvm.log.f64"},
1425 {LibFunc_logl,
"llvm.log.f80"},
1426 {LibFunc_log10f,
"llvm.log10.f32"},
1427 {LibFunc_log10,
"llvm.log10.f64"},
1428 {LibFunc_log10l,
"llvm.log10.f80"},
1429 {LibFunc_log2f,
"llvm.log2.f32"},
1430 {LibFunc_log2,
"llvm.log2.f64"},
1431 {LibFunc_log2l,
"llvm.log2.f80"},
1432 {LibFunc_fabsf,
"llvm.fabs.f32"},
1433 {LibFunc_fabs,
"llvm.fabs.f64"},
1434 {LibFunc_fabsl,
"llvm.fabs.f80"},
1435 {LibFunc_copysignf,
"llvm.copysign.f32"},
1436 {LibFunc_copysign,
"llvm.copysign.f64"},
1437 {LibFunc_copysignl,
"llvm.copysign.f80"},
1438 {LibFunc_floorf,
"llvm.floor.f32"},
1439 {LibFunc_floor,
"llvm.floor.f64"},
1440 {LibFunc_floorl,
"llvm.floor.f80"},
1441 {LibFunc_fmaxf,
"llvm.maxnum.f32"},
1442 {LibFunc_fmax,
"llvm.maxnum.f64"},
1443 {LibFunc_fmaxl,
"llvm.maxnum.f80"},
1444 {LibFunc_fminf,
"llvm.minnum.f32"},
1445 {LibFunc_fmin,
"llvm.minnum.f64"},
1446 {LibFunc_fminl,
"llvm.minnum.f80"},
1447 {LibFunc_ceilf,
"llvm.ceil.f32"},
1448 {LibFunc_ceil,
"llvm.ceil.f64"},
1449 {LibFunc_ceill,
"llvm.ceil.f80"},
1450 {LibFunc_truncf,
"llvm.trunc.f32"},
1451 {LibFunc_trunc,
"llvm.trunc.f64"},
1452 {LibFunc_truncl,
"llvm.trunc.f80"},
1453 {LibFunc_rintf,
"llvm.rint.f32"},
1454 {LibFunc_rint,
"llvm.rint.f64"},
1455 {LibFunc_rintl,
"llvm.rint.f80"},
1456 {LibFunc_nearbyintf,
"llvm.nearbyint.f32"},
1457 {LibFunc_nearbyint,
"llvm.nearbyint.f64"},
1458 {LibFunc_nearbyintl,
"llvm.nearbyint.f80"},
1459 {LibFunc_roundf,
"llvm.round.f32"},
1460 {LibFunc_round,
"llvm.round.f64"},
1461 {LibFunc_roundl,
"llvm.round.f80"},
1464const char *KnownIntrinsic::get(
LibFunc LFunc) {
1465 for (
const auto &E : kLibfuncIntrinsics) {
1466 if (E.LFunc == LFunc)
1467 return E.IntrinsicName;
1472const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(
StringRef Name) {
1473 for (
const auto &E : kWidenedIntrinsics) {
1474 if (E.NarrowName ==
Name)
1487 if (
const char *
Name = KnownIntrinsic::get(LFunc))
1495Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1497 const ValueToShadowMap &Map,
IRBuilder<> &Builder) {
1505 const auto *Widened = KnownIntrinsic::widen(Fn->
getName());
1507 WidenedId = Widened->ID;
1508 WidenedFnTy = Widened->MakeFnTy(Context);
1519 const auto *Widened = KnownIntrinsic::widen(
Name);
1520 assert(Widened &&
"make sure KnownIntrinsic entries are consistent");
1521 WidenedId = Widened->ID;
1522 WidenedFnTy = Widened->MakeFnTy(Context);
1536 "invalid widened intrinsic");
1541 for (
unsigned I = 0, E =
Call.getNumOperands() - 1;
I < E; ++
I) {
1544 Type *IntrinsicArgTy = WidenedFnTy->getParamType(
I);
1545 if (OrigArgTy == IntrinsicArgTy) {
1546 Args.push_back(Arg);
1551 "don't know how to get the shadow value for a non-FT");
1552 Value *Shadow =
Map.getShadow(Arg);
1553 if (ShadowArgTy == IntrinsicArgTy) {
1556 Args.push_back(Shadow);
1563 return WidenedFnTy->getReturnType() == ExtendedVT
1573 const ValueToShadowMap &Map,
1576 if (
Call.isInlineAsm())
1583 maybeHandleKnownCallBase(Call, VT, ExtendedVT, TLI, Map, Builder))
1589 Builder.
CreateLoad(IntptrTy, NsanShadowRetTag,
false);
1599 ++NumInstrumentedFTCalls;
1605Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1607 const ValueToShadowMap &Map) {
1609 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1610 assert(ExtendedVT !=
nullptr &&
"trying to create a shadow for a non-FT");
1612 if (
auto *Load = dyn_cast<LoadInst>(&Inst))
1613 return handleLoad(*Load, VT, ExtendedVT);
1615 if (
auto *Call = dyn_cast<CallInst>(&Inst)) {
1620 return handleCallBase(*Call, VT, ExtendedVT, TLI, Map, Builder);
1623 if (
auto *Invoke = dyn_cast<InvokeInst>(&Inst)) {
1627 BasicBlock *NextBB = Invoke->getNormalDest();
1634 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1643 if (
auto *Trunc = dyn_cast<FPTruncInst>(&Inst))
1644 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1645 if (
auto *Ext = dyn_cast<FPExtInst>(&Inst))
1646 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1648 if (
auto *UnaryOp = dyn_cast<UnaryOperator>(&Inst))
1649 return Builder.
CreateUnOp(UnaryOp->getOpcode(),
1650 Map.getShadow(UnaryOp->getOperand(0)));
1652 if (
auto *BinOp = dyn_cast<BinaryOperator>(&Inst))
1654 Map.getShadow(BinOp->getOperand(0)),
1655 Map.getShadow(BinOp->getOperand(1)));
1657 if (isa<UIToFPInst>(&Inst) || isa<SIToFPInst>(&Inst)) {
1658 auto *Cast = dyn_cast<CastInst>(&Inst);
1659 return Builder.
CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1663 if (
auto *S = dyn_cast<SelectInst>(&Inst))
1665 Map.getShadow(S->getTrueValue()),
1666 Map.getShadow(S->getFalseValue()));
1668 if (
auto *Extract = dyn_cast<ExtractElementInst>(&Inst))
1670 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1672 if (
auto *Insert = dyn_cast<InsertElementInst>(&Inst))
1677 if (
auto *Shuffle = dyn_cast<ShuffleVectorInst>(&Inst))
1679 Map.getShadow(Shuffle->getOperand(1)),
1680 Shuffle->getShuffleMask());
1683 if (
auto *Extract = dyn_cast<ExtractValueInst>(&Inst))
1686 if (
auto *BC = dyn_cast<BitCastInst>(&Inst))
1697void NumericalStabilitySanitizer::maybeCreateShadowValue(
1700 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1701 if (ExtendedVT ==
nullptr)
1704 if (
Map.hasShadow(&Root))
1707 assert(!isa<PHINode>(Root) &&
"phi nodes should already have shadows");
1709 std::vector<Instruction *> DfsStack(1, &Root);
1710 while (!DfsStack.empty()) {
1716 if (
Map.hasShadow(
I)) {
1717 DfsStack.pop_back();
1721 bool MissingShadow =
false;
1723 Type *VT =
Op->getType();
1724 if (!
Config.getExtendedFPType(VT))
1726 if (
Map.hasShadow(
Op))
1728 MissingShadow =
true;
1729 DfsStack.push_back(cast<Instruction>(
Op));
1735 Value *Shadow = createShadowValueWithOperandsAvailable(*
I, TLI, Map);
1736 Map.setShadow(*
I, *Shadow);
1737 DfsStack.pop_back();
1742void NumericalStabilitySanitizer::propagateFTStore(
1744 Value *StoredValue =
Store.getValueOperand();
1747 const auto Extents = getMemoryExtentsOrDie(VT);
1749 NsanGetShadowPtrForStore[Extents.ValueType],
1750 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1752 Value *StoredShadow =
Map.getShadow(StoredValue);
1753 if (!
Store.getParent()->getParent()->hasOptNone()) {
1757 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1758 CheckLoc::makeStore(
Store.getPointerOperand()));
1759 ++NumInstrumentedFTStores;
1764 Store.isVolatile());
1775void NumericalStabilitySanitizer::propagateNonFTStore(
1785 IntptrTy,
APInt(IntptrTy->getPrimitiveSizeInBits(), LoadSizeBytes));
1787 ++NumInstrumentedNonFTStores;
1788 Value *StoredValue =
Store.getValueOperand();
1789 if (
LoadInst *Load = dyn_cast<LoadInst>(StoredValue)) {
1796 Type *ShadowValueIntTy =
1800 Value *LoadSrc =
Load->getPointerOperand();
1806 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1808 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}),
Align(1),
1810 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1812 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}),
Align(1),
1817 RawShadowType, Builder.
CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1821 Builder.
CreateCall(NsanGetRawShadowPtr, {Dst}),
1825 ++NumInstrumentedNonFTMemcpyStores;
1830 (
C = dyn_cast<Constant>(StoredValue))) {
1833 Type *BitcastTy =
nullptr;
1834 if (
auto *CInt = dyn_cast<ConstantInt>(
C)) {
1835 switch (CInt->getType()->getScalarSizeInBits()) {
1848 }
else if (
auto *CDV = dyn_cast<ConstantDataVector>(
C)) {
1849 const int NumElements =
1850 cast<VectorType>(CDV->getType())->getElementCount().getFixedValue();
1851 switch (CDV->getType()->getScalarSizeInBits()) {
1869 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1871 NsanGetShadowPtrForStore[Extents.ValueType],
1872 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1874 Type *ExtVT =
Config.getExtendedFPType(BitcastTy);
1878 Store.isVolatile());
1883 Builder.
CreateCall(NsanSetValueUnknown, {Dst, ValueSize});
1886void NumericalStabilitySanitizer::propagateShadowValues(
1888 const ValueToShadowMap &Map) {
1889 if (
auto *Store = dyn_cast<StoreInst>(&Inst)) {
1890 Value *StoredValue =
Store->getValueOperand();
1892 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1893 if (ExtendedVT ==
nullptr)
1894 return propagateNonFTStore(*Store, VT, Map);
1895 return propagateFTStore(*Store, VT, ExtendedVT, Map);
1898 if (
auto *FCmp = dyn_cast<FCmpInst>(&Inst)) {
1899 emitFCmpCheck(*FCmp, Map);
1903 if (
auto *CB = dyn_cast<CallBase>(&Inst)) {
1904 maybeAddSuffixForNsanInterface(CB);
1905 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
1908 instrumentMemIntrinsic(
MI);
1911 populateShadowStack(*CB, TLI, Map);
1915 if (
auto *RetInst = dyn_cast<ReturnInst>(&Inst)) {
1919 Value *RV = RetInst->getReturnValue();
1923 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1924 if (ExtendedVT ==
nullptr)
1926 Value *RVShadow =
Map.getShadow(RV);
1929 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1930 ++NumInstrumentedFTRets;
1936 Value *ShadowRetValPtr =
1944 Type *VT =
V->getType();
1945 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1946 if (ExtendedVT ==
nullptr)
1949 emitCheck(V,
Map.getShadow(V), Builder, CheckLoc::makeInsert());
1958 std::vector<Instruction *> &Instructions) {
1960#define MOVE_FLAG(attr, setter) \
1961 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
1962 F.removeFnAttr(attr); \
1963 FMF.set##setter(); \
1968 MOVE_FLAG(
"no-signed-zeros-fp-math", NoSignedZeros)
1972 if (isa<FPMathOperator>(
I))
1973 I->setFastMathFlags(FMF);
1976bool NumericalStabilitySanitizer::sanitizeFunction(
1978 if (!
F.hasFnAttribute(Attribute::SanitizeNumericalStability))
2076 std::vector<Instruction *> OriginalInstructions;
2082 ValueToShadowMap ValueToShadow(
Config);
2087 std::vector<PHINode *> OriginalPhis;
2088 createShadowArguments(
F, TLI, ValueToShadow);
2090 if (
PHINode *Phi = dyn_cast<PHINode>(
I)) {
2091 if (
PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2092 OriginalPhis.push_back(Phi);
2093 ValueToShadow.setShadow(*Phi, *Shadow);
2100 maybeCreateShadowValue(*
I, TLI, ValueToShadow);
2104 propagateShadowValues(*
I, TLI, ValueToShadow);
2107 for (
PHINode *Phi : OriginalPhis) {
2108 PHINode *ShadowPhi = dyn_cast<PHINode>(ValueToShadow.getShadow(Phi));
2109 for (
unsigned I :
seq(
Phi->getNumOperands())) {
2111 Value *Shadow = ValueToShadow.getShadow(V);
2123 return !ValueToShadow.empty();
2128bool NumericalStabilitySanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
2130 if (
auto *M = dyn_cast<MemSetInst>(
MI)) {
2132 NsanSetValueUnknown,
2133 {
M->getArgOperand(0),
2135 }
else if (
auto *M = dyn_cast<MemTransferInst>(
MI)) {
2138 {
M->getArgOperand(0),
2139 M->getArgOperand(1),
2145void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(
CallBase *CI) {
2153 if (Fn->
getName() ==
"__nsan_dump_shadow_mem") {
2155 "invalid prototype for __nsan_dump_shadow_mem");
2160 const uint64_t shadow_value_type_ids =
2161 (
static_cast<size_t>(
Config.byValueType(kLongDouble).getNsanTypeId())
2163 (
static_cast<size_t>(
Config.byValueType(kDouble).getNsanTypeId())
2165 static_cast<size_t>(
Config.byValueType(kFloat).getNsanTypeId());
2166 CI->
setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)
static FunctionType * makeDoubleDouble(LLVMContext &C)
constexpr int kMaxVectorWidth
static cl::opt< bool > ClCheckRet("nsan-check-ret", cl::init(true), cl::desc("Check floating-point return values"), cl::Hidden)
static bool shouldCheckArgs(CallBase &CI, const TargetLibraryInfo &TLI, const std::optional< Regex > &CheckFunctionsFilter)
static cl::opt< bool > ClCheckStores("nsan-check-stores", cl::init(true), cl::desc("Check floating-point stores"), cl::Hidden)
static FunctionType * makeX86FP80X86FP80(LLVMContext &C)
#define MOVE_FLAG(attr, setter)
static FunctionType * makeX86FP80X86FP80I32(LLVMContext &C)
constexpr int kMaxNumArgs
constexpr int kMaxShadowTypeSizeBytes
static const char * getIntrinsicFromLibfunc(Function &Fn, Type *VT, const TargetLibraryInfo &TLI)
static FunctionType * makeX86FP80X86FP80X86FP80(LLVMContext &C)
static FunctionType * makeX86FP80X86FP80X86FP80X86FP80(LLVMContext &C)
constexpr StringLiteral kNsanInitName("__nsan_init")
static FunctionType * makeDoubleDoubleDouble(LLVMContext &C)
constexpr int kShadowScale
static cl::opt< bool > ClCheckLoads("nsan-check-loads", cl::desc("Check floating-point load"), cl::Hidden)
constexpr StringLiteral kNsanModuleCtorName("nsan.module_ctor")
static cl::opt< bool > ClPropagateNonFTConstStoresAsFT("nsan-propagate-non-ft-const-stores-as-ft", cl::desc("Propagate non floating-point const stores as floating point values." "For debugging purposes only"), cl::Hidden)
static cl::opt< std::string > ClShadowMapping("nsan-shadow-type-mapping", cl::init("dqq"), cl::desc("One shadow type id for each of `float`, `double`, `long double`. " "`d`,`l`,`q`,`e` mean double, x86_fp80, fp128 (quad) and " "ppc_fp128 (extended double) respectively. The default is to " "shadow `float` as `double`, and `double` and `x86_fp80` as " "`fp128`"), cl::Hidden)
static FunctionType * makeDoubleDoubleDoubleDouble(LLVMContext &C)
static cl::opt< bool > ClTruncateFCmpEq("nsan-truncate-fcmp-eq", cl::init(true), cl::desc("This flag controls the behaviour of fcmp equality comparisons." "For equality comparisons such as `x == 0.0f`, we can perform the " "shadow check in the shadow (`x_shadow == 0.0) == (x == 0.0f)`) or app " " domain (`(trunc(x_shadow) == 0.0f) == (x == 0.0f)`). This helps " "catch the case when `x_shadow` is accurate enough (and therefore " "close enough to zero) so that `trunc(x_shadow)` is zero even though " "both `x` and `x_shadow` are not"), cl::Hidden)
static cl::opt< std::string > ClCheckFunctionsFilter("check-functions-filter", cl::desc("Only emit checks for arguments of functions " "whose names match the given regular expression"), cl::value_desc("regex"))
static FunctionType * makeDoubleDoubleI32(LLVMContext &C)
static void moveFastMathFlags(Function &F, std::vector< Instruction * > &Instructions)
static cl::opt< bool > ClInstrumentFCmp("nsan-instrument-fcmp", cl::init(true), cl::desc("Instrument floating-point comparisons"), cl::Hidden)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
AttributeList addFnAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add a function attribute to the list.
LLVM Basic Block Representation.
void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction & back() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
void setArgOperand(unsigned i, Value *v)
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Predicate getPredicate() const
Return the predicate for this instruction.
ConstantFP - Floating Point Values [float, double].
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
This instruction compares its operands according to the predicate given to the constructor.
static bool isEquality(Predicate Pred)
This class represents an extension of floating point types.
This class represents a truncation of floating point types.
Convenience struct for specifying and reasoning about fast-math flags.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateFPExt(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This instruction inserts a struct field of array element value into an aggregate value.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB)
Replace specified successor OldBB to point at the provided block.
const Function * getFunction() const
Return the function this instruction belongs to.
const char * getOpcodeName() const
void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
This is the common base class for memset/memcpy/memmove.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
StringRef getName(LibFunc F) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
Type * getStructElementType(unsigned N) const
static Type * getDoubleTy(LLVMContext &C)
const fltSemantics & getFltSemantics() const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isX86_FP80Ty() const
Return true if this is x86 long double.
bool isArrayTy() const
True if this is an instance of ArrayType.
static Type * getX86_FP80Ty(LLVMContext &C)
static IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
unsigned getStructNumElements() const
uint64_t getArrayNumElements() const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
static Type * getFP128Ty(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static IntegerType * getInt32Ty(LLVMContext &C)
static Type * getFloatTy(LLVMContext &C)
static Type * getPPC_FP128Ty(LLVMContext &C)
'undef' values are things that do not have specified contents.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
StringRef getName() const
Return a constant reference to the value's name.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
MatchIntrinsicTypesResult matchIntrinsicSignature(FunctionType *FTy, ArrayRef< IITDescriptor > &Infos, SmallVectorImpl< Type * > &ArgTys)
Match the specified function type with the type constraints specified by the .td file.
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl< IITDescriptor > &T)
Return the IIT table descriptor for the specified intrinsic into an array of IITDescriptors.
MatchIntrinsicTypesResult
@ MatchIntrinsicTypes_Match
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are are tuples (A,...
std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)