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);
311 auto *VecTy = cast<VectorType>(FT);
313 if (VecTy->isScalableTy())
315 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());
316 return ExtendedScalar
317 ? VectorType::get(ExtendedScalar, VecTy->getElementCount())
325 std::unique_ptr<ShadowTypeConfig> Configs[FTValueType::kNumValueTypes];
330struct MemoryExtents {
335static MemoryExtents getMemoryExtentsOrDie(
Type *FT) {
336 if (
const auto VT = ftValueTypeFromType(FT))
338 if (
auto *VecTy = dyn_cast<VectorType>(FT)) {
339 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());
340 return {ScalarExtents.ValueType,
341 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};
351 CheckLoc Result(kStore);
356 CheckLoc Result(kLoad);
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);
410 explicit CheckLoc(CheckType CheckTy) : CheckTy(CheckTy) {}
413 const CheckType CheckTy;
418class ValueToShadowMap {
422 ValueToShadowMap(
const ValueToShadowMap &) =
delete;
423 ValueToShadowMap &operator=(
const ValueToShadowMap &) =
delete;
428 [[maybe_unused]]
const bool Inserted = Map.try_emplace(&V, &Shadow).second;
431 if (
auto *
I = dyn_cast<Instruction>(&V))
432 errs() <<
I->getFunction()->getName() <<
": ";
433 errs() <<
"duplicate shadow (" << &V <<
"): ";
437 assert(Inserted &&
"duplicate shadow");
442 bool hasShadow(
Value *V)
const {
443 return isa<Constant>(V) || (Map.find(V) != Map.end());
450 return getShadowConstant(
C);
451 return Map.find(V)->second;
454 bool empty()
const {
return Map.empty(); }
459 bool LosesInfo =
false;
471 Type *Ty =
Config.getExtendedFPType(CFP->getType());
472 return ConstantFP::get(
476 if (
C->getType()->isVectorTy()) {
478 for (
int I = 0, E = cast<VectorType>(
C->getType())
482 Elements.push_back(getShadowConstant(
C->getAggregateElement(
I)));
488 const MappingConfig &
Config;
501 size_t NumSizedFuncs;
509 Type *PtrTy = PointerType::getUnqual(Ctx);
511 IntegerType *IntptrTy = M.getDataLayout().getIntPtrType(Ctx);
514 NumSizedFuncs = Sized.
size();
519 M.getOrInsertFunction(
Fallback, Attr, VoidTy, PtrTy, PtrTy, IntptrTy));
520 SizedFnTy = FunctionType::get(VoidTy, {PtrTy, PtrTy},
false);
521 }
else if (NumArgs == 2) {
523 M.getOrInsertFunction(
Fallback, Attr, VoidTy, PtrTy, IntptrTy));
524 SizedFnTy = FunctionType::get(VoidTy, {PtrTy},
false);
529 for (
size_t i = 0; i < NumSizedFuncs; ++i)
530 Funcs.push_back(M.getOrInsertFunction(Sized[i], SizedFnTy, Attr));
536 assert(NumSizedFuncs >= 3 &&
"Unexpected number of sized functions");
539 MemOpSize == 4 ? 1 : (MemOpSize == 8 ? 2 : (MemOpSize == 16 ? 3 : 0));
544FunctionCallee NsanMemOpFn::getFallback()
const {
return Funcs[0]; }
550class NumericalStabilitySanitizer {
552 NumericalStabilitySanitizer(
Module &M);
557 void maybeAddSuffixForNsanInterface(
CallBase *CI);
558 bool addrPointsToConstantData(
Value *
Addr);
560 ValueToShadowMap &Map);
563 const ValueToShadowMap &Map);
566 ValueToShadowMap &Map);
569 const ValueToShadowMap &Map);
572 const ValueToShadowMap &Map);
577 void emitFCmpCheck(
FCmpInst &FCmp,
const ValueToShadowMap &Map);
583 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
586 const ValueToShadowMap &Map,
589 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
591 const ValueToShadowMap &Map,
IRBuilder<> &Builder);
595 const ValueToShadowMap &Map);
597 const ValueToShadowMap &Map);
605 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};
606 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};
610 NsanMemOpFn NsanCopyFns;
611 NsanMemOpFn NsanSetUnknownFns;
617 Type *NsanShadowRetType =
nullptr;
622 Type *NsanShadowArgsType =
nullptr;
625 std::optional<Regex> CheckFunctionsFilter;
638 NumericalStabilitySanitizer Nsan(M);
647 return dyn_cast<GlobalValue>(M.getOrInsertGlobal(
Name, Ty, [&M, Ty,
Name] {
648 return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
649 nullptr, Name, nullptr,
650 GlobalVariable::InitialExecTLSModel);
654NumericalStabilitySanitizer::NumericalStabilitySanitizer(
Module &M)
655 :
DL(
M.getDataLayout()), Context(
M.getContext()),
Config(Context),
656 NsanCopyFns(
M, {
"__nsan_copy_4",
"__nsan_copy_8",
"__nsan_copy_16"},
657 "__nsan_copy_values", 3),
659 {
"__nsan_set_value_unknown_4",
660 "__nsan_set_value_unknown_8",
661 "__nsan_set_value_unknown_16"},
662 "__nsan_set_value_unknown", 2) {
663 IntptrTy =
DL.getIntPtrType(Context);
664 Type *PtrTy = PointerType::getUnqual(Context);
672 for (
int I = 0;
I < kNumValueTypes; ++
I) {
673 const FTValueType VT =
static_cast<FTValueType
>(
I);
674 const char *VTName = typeNameFromFTValueType(VT);
675 Type *VTTy = typeFromFTValueType(VT, Context);
678 const std::string GetterPrefix =
679 std::string(
"__nsan_get_shadow_ptr_for_") + VTName;
680 NsanGetShadowPtrForStore[VT] =
M.getOrInsertFunction(
681 GetterPrefix +
"_store", Attr, PtrTy, PtrTy, IntptrTy);
682 NsanGetShadowPtrForLoad[VT] =
M.getOrInsertFunction(
683 GetterPrefix +
"_load", Attr, PtrTy, PtrTy, IntptrTy);
686 const auto &ShadowConfig =
Config.byValueType(VT);
687 Type *ShadowTy = ShadowConfig.getType(Context);
689 M.getOrInsertFunction(std::string(
"__nsan_internal_check_") + VTName +
690 "_" + ShadowConfig.getNsanTypeId(),
691 Attr, Int32Ty, VTTy, ShadowTy, Int32Ty, IntptrTy);
692 NsanFCmpFail[VT] =
M.getOrInsertFunction(
693 std::string(
"__nsan_fcmp_fail_") + VTName +
"_" +
694 ShadowConfig.getNsanTypeId(),
695 Attr, VoidTy, VTTy, VTTy, ShadowTy, ShadowTy, Int32Ty, Int1Ty, Int1Ty);
699 NsanGetRawShadowTypePtr =
M.getOrInsertFunction(
700 "__nsan_internal_get_raw_shadow_type_ptr", Attr, PtrTy, PtrTy);
701 NsanGetRawShadowPtr =
M.getOrInsertFunction(
702 "__nsan_internal_get_raw_shadow_ptr", Attr, PtrTy, PtrTy);
723 std::string RegexError;
725 CheckFunctionsFilter = std::move(R);
731bool NumericalStabilitySanitizer::addrPointsToConstantData(
Value *
Addr) {
734 Addr =
GEP->getPointerOperand();
737 return GV->isConstant();
753void NumericalStabilitySanitizer::createShadowArguments(
755 assert(!
F.getIntrinsicID() &&
"found a definition of an intrinsic");
759 return Config.getExtendedFPType(Arg.getType()) == nullptr;
763 IRBuilder<> Builder(
F.getEntryBlock().getFirstNonPHI());
766 Value *HasShadowArgs = Builder.CreateICmpEQ(
767 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag,
false),
768 Builder.CreatePtrToInt(&
F, IntptrTy));
770 unsigned ShadowArgsOffsetBytes = 0;
773 Type *ExtendedVT =
Config.getExtendedFPType(VT);
774 if (ExtendedVT ==
nullptr)
776 Value *
L = Builder.CreateAlignedLoad(
778 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
779 ShadowArgsOffsetBytes),
781 Value *Shadow = Builder.CreateSelect(HasShadowArgs, L,
782 Builder.CreateFPExt(&Arg, ExtendedVT));
783 Map.setShadow(Arg, *Shadow);
784 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
786 ShadowArgsOffsetBytes += SlotSize;
788 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);
794 const std::optional<Regex> &CheckFunctionsFilter) {
798 if (CheckFunctionsFilter) {
802 if (CheckFunctionsFilter->match(Fn->
getName()))
815 LibFunc LFunc = LibFunc::NumLibFuncs;
823 if (
ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||
824 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)
825 for (
const auto &U : CI.
users())
834void NumericalStabilitySanitizer::populateShadowStack(
842 return Config.getExtendedFPType(Arg->getType()) == nullptr;
848 const bool ShouldCheckArgs =
shouldCheckArgs(CI, TLI, CheckFunctionsFilter);
852 Value *ArgShadow =
Map.getShadow(Arg);
853 ArgShadows.
push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,
854 CheckLoc::makeArg(ArgIdx))
861 if (Fn->isIntrinsic() || TLI.
getLibFunc(*Fn, LFunc))
869 unsigned ShadowArgId = 0;
872 Type *ExtendedVT =
Config.getExtendedFPType(VT);
873 if (ExtendedVT ==
nullptr)
875 Builder.CreateAlignedStore(
876 ArgShadows[ShadowArgId++],
877 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
878 ShadowArgsOffsetBytes),
880 TypeSize SlotSize =
DL.getTypeStoreSize(ExtendedVT);
882 ShadowArgsOffsetBytes += SlotSize;
894Value *NumericalStabilitySanitizer::emitCheckInternal(
Value *V,
Value *ShadowV,
898 if (isa<Constant>(V))
899 return ConstantInt::get(
903 Type *Ty =
V->getType();
904 if (
const auto VT = ftValueTypeFromType(Ty))
907 {
V, ShadowV, Loc.
getType(Context), Loc.getValue(IntptrTy, Builder)});
910 auto *VecTy = cast<VectorType>(Ty);
913 assert(!VecTy->isScalableTy() &&
914 "Scalable vector types are not supported yet");
915 Value *CheckResult =
nullptr;
916 for (
int I = 0, E = VecTy->getElementCount().getFixedValue();
I < E; ++
I) {
922 Value *ComponentCheckResult =
923 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
924 CheckResult = CheckResult
925 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
926 : ComponentCheckResult;
931 Value *CheckResult =
nullptr;
935 Value *ComponentCheckResult =
936 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
937 CheckResult = CheckResult
938 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
939 : ComponentCheckResult;
944 Value *CheckResult =
nullptr;
950 Value *ComponentCheckResult =
951 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
952 CheckResult = CheckResult
953 ? Builder.
CreateOr(CheckResult, ComponentCheckResult)
954 : ComponentCheckResult;
957 return ConstantInt::get(
976 if (isa<Constant>(V))
979 if (
Instruction *Inst = dyn_cast<Instruction>(V)) {
981 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName())) {
986 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
998void NumericalStabilitySanitizer::emitFCmpCheck(
FCmpInst &FCmp,
999 const ValueToShadowMap &Map) {
1004 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(
F->getName()))
1023 FCmpBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1024 Value *ShadowLHS =
Map.getShadow(LHS);
1025 Value *ShadowRHS =
Map.getShadow(RHS);
1029 ShadowLHS = FCmpBuilder.CreateFPExt(
1030 FCmpBuilder.CreateFPTrunc(ShadowLHS,
LHS->
getType()), Ty);
1031 ShadowRHS = FCmpBuilder.CreateFPExt(
1032 FCmpBuilder.CreateFPTrunc(ShadowRHS,
RHS->
getType()), Ty);
1035 FCmpBuilder.CreateFCmp(FCmp.
getPredicate(), ShadowLHS, ShadowRHS);
1036 Value *OriginalAndShadowFcmpMatch =
1037 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
1043 OriginalAndShadowFcmpMatch =
1044 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
1049 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
1050 MDBuilder(Context).createLikelyBranchWeights());
1054 FailBuilder.SetCurrentDebugLocation(FCmp.
getDebugLoc());
1056 const auto EmitFailCall = [
this, &FCmp, &FCmpBuilder,
1059 Value *ShadowResult) {
1060 Type *FT =
L->getType();
1063 Callee = &(NsanFCmpFail[kFloat]);
1065 Callee = &(NsanFCmpFail[kDouble]);
1068 Callee = &(NsanFCmpFail[kDouble]);
1074 FailBuilder.CreateCall(*Callee, {
L,
R, ShadowL, ShadowR,
1075 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1080 for (
int I = 0, E = cast<VectorType>(
LHS->
getType())
1084 Value *ExtractLHS = FailBuilder.CreateExtractElement(LHS,
I);
1085 Value *ExtractRHS = FailBuilder.CreateExtractElement(RHS,
I);
1086 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS,
I);
1087 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS,
I);
1088 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp,
I);
1089 Value *ExtractShadowFCmp =
1090 FailBuilder.CreateExtractElement(ShadowFCmp,
I);
1091 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1092 ExtractFCmp, ExtractShadowFCmp);
1095 EmitFailCall(LHS, RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1097 FailBuilder.CreateBr(NextBB);
1099 ++NumInstrumentedFCmp;
1103PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1106 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1107 if (ExtendedVT ==
nullptr)
1121 if (addrPointsToConstantData(
Load.getPointerOperand())) {
1141 const auto Extents = getMemoryExtentsOrDie(VT);
1143 NsanGetShadowPtrForLoad[Extents.ValueType],
1144 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1145 ++NumInstrumentedFTLoads;
1161 LoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1162 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1168 ShadowLoadBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1169 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1170 ExtendedVT, ShadowPtr,
Align(1),
Load.isVolatile());
1172 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,
1173 CheckLoc::makeLoad(
Load.getPointerOperand()));
1175 ShadowLoadBBBuilder.CreateBr(NextBB);
1179 FExtBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1180 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);
1181 FExtBBBuilder.CreateBr(NextBB);
1185 NextBBBuilder.SetCurrentDebugLocation(
Load.getDebugLoc());
1186 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1194 const ValueToShadowMap &Map,
1198 Type *ExtendedSourceTy =
Config.getExtendedFPType(OrigSourceTy);
1231 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1232 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1234 if (SourceTy == ExtendedVT)
1242 const ValueToShadowMap &Map,
1244 Value *OrigSource =
Ext.getOperand(0);
1246 Type *ExtendedSourceTy =
Config.getExtendedFPType(OrigSourceTy);
1278 Value *
Source = ExtendedSourceTy ?
Map.getShadow(OrigSource) : OrigSource;
1279 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1281 if (SourceTy == ExtendedVT)
1289struct KnownIntrinsic {
1290 struct WidenedIntrinsic {
1291 const char *NarrowName;
1294 FnTypeFactory MakeFnTy;
1309 const char *IntrinsicName;
1311 static const LFEntry kLibfuncIntrinsics[];
1313 static const WidenedIntrinsic kWidenedIntrinsics[];
1349 return FunctionType::get(
1356 return FunctionType::get(
1362const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1460const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1461 {LibFunc_sqrtf,
"llvm.sqrt.f32"},
1462 {LibFunc_sqrt,
"llvm.sqrt.f64"},
1463 {LibFunc_sqrtl,
"llvm.sqrt.f80"},
1464 {LibFunc_sinf,
"llvm.sin.f32"},
1465 {LibFunc_sin,
"llvm.sin.f64"},
1466 {LibFunc_sinl,
"llvm.sin.f80"},
1467 {LibFunc_cosf,
"llvm.cos.f32"},
1468 {LibFunc_cos,
"llvm.cos.f64"},
1469 {LibFunc_cosl,
"llvm.cos.f80"},
1470 {LibFunc_powf,
"llvm.pow.f32"},
1471 {LibFunc_pow,
"llvm.pow.f64"},
1472 {LibFunc_powl,
"llvm.pow.f80"},
1473 {LibFunc_expf,
"llvm.exp.f32"},
1474 {LibFunc_exp,
"llvm.exp.f64"},
1475 {LibFunc_expl,
"llvm.exp.f80"},
1476 {LibFunc_exp2f,
"llvm.exp2.f32"},
1477 {LibFunc_exp2,
"llvm.exp2.f64"},
1478 {LibFunc_exp2l,
"llvm.exp2.f80"},
1479 {LibFunc_logf,
"llvm.log.f32"},
1480 {LibFunc_log,
"llvm.log.f64"},
1481 {LibFunc_logl,
"llvm.log.f80"},
1482 {LibFunc_log10f,
"llvm.log10.f32"},
1483 {LibFunc_log10,
"llvm.log10.f64"},
1484 {LibFunc_log10l,
"llvm.log10.f80"},
1485 {LibFunc_log2f,
"llvm.log2.f32"},
1486 {LibFunc_log2,
"llvm.log2.f64"},
1487 {LibFunc_log2l,
"llvm.log2.f80"},
1488 {LibFunc_fabsf,
"llvm.fabs.f32"},
1489 {LibFunc_fabs,
"llvm.fabs.f64"},
1490 {LibFunc_fabsl,
"llvm.fabs.f80"},
1491 {LibFunc_copysignf,
"llvm.copysign.f32"},
1492 {LibFunc_copysign,
"llvm.copysign.f64"},
1493 {LibFunc_copysignl,
"llvm.copysign.f80"},
1494 {LibFunc_floorf,
"llvm.floor.f32"},
1495 {LibFunc_floor,
"llvm.floor.f64"},
1496 {LibFunc_floorl,
"llvm.floor.f80"},
1497 {LibFunc_fmaxf,
"llvm.maxnum.f32"},
1498 {LibFunc_fmax,
"llvm.maxnum.f64"},
1499 {LibFunc_fmaxl,
"llvm.maxnum.f80"},
1500 {LibFunc_fminf,
"llvm.minnum.f32"},
1501 {LibFunc_fmin,
"llvm.minnum.f64"},
1502 {LibFunc_fminl,
"llvm.minnum.f80"},
1503 {LibFunc_ceilf,
"llvm.ceil.f32"},
1504 {LibFunc_ceil,
"llvm.ceil.f64"},
1505 {LibFunc_ceill,
"llvm.ceil.f80"},
1506 {LibFunc_truncf,
"llvm.trunc.f32"},
1507 {LibFunc_trunc,
"llvm.trunc.f64"},
1508 {LibFunc_truncl,
"llvm.trunc.f80"},
1509 {LibFunc_rintf,
"llvm.rint.f32"},
1510 {LibFunc_rint,
"llvm.rint.f64"},
1511 {LibFunc_rintl,
"llvm.rint.f80"},
1512 {LibFunc_nearbyintf,
"llvm.nearbyint.f32"},
1513 {LibFunc_nearbyint,
"llvm.nearbyint.f64"},
1514 {LibFunc_nearbyintl,
"llvm.nearbyint.f80"},
1515 {LibFunc_roundf,
"llvm.round.f32"},
1516 {LibFunc_round,
"llvm.round.f64"},
1517 {LibFunc_roundl,
"llvm.round.f80"},
1520const char *KnownIntrinsic::get(
LibFunc LFunc) {
1521 for (
const auto &E : kLibfuncIntrinsics) {
1522 if (E.LFunc == LFunc)
1523 return E.IntrinsicName;
1528const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(
StringRef Name) {
1529 for (
const auto &E : kWidenedIntrinsics) {
1530 if (E.NarrowName ==
Name)
1543 if (
const char *
Name = KnownIntrinsic::get(LFunc))
1551Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1553 const ValueToShadowMap &Map,
IRBuilder<> &Builder) {
1561 const auto *Widened = KnownIntrinsic::widen(Fn->
getName());
1563 WidenedId = Widened->ID;
1564 WidenedFnTy = Widened->MakeFnTy(Context);
1575 const auto *Widened = KnownIntrinsic::widen(
Name);
1576 assert(Widened &&
"make sure KnownIntrinsic entries are consistent");
1577 WidenedId = Widened->ID;
1578 WidenedFnTy = Widened->MakeFnTy(Context);
1592 "invalid widened intrinsic");
1597 for (
unsigned I = 0, E =
Call.getNumOperands() - 1;
I < E; ++
I) {
1600 Type *IntrinsicArgTy = WidenedFnTy->getParamType(
I);
1601 if (OrigArgTy == IntrinsicArgTy) {
1602 Args.push_back(Arg);
1607 "don't know how to get the shadow value for a non-FT");
1608 Value *Shadow =
Map.getShadow(Arg);
1609 if (ShadowArgTy == IntrinsicArgTy) {
1612 Args.push_back(Shadow);
1619 return WidenedFnTy->getReturnType() == ExtendedVT
1629 const ValueToShadowMap &Map,
1632 if (
Call.isInlineAsm())
1639 maybeHandleKnownCallBase(Call, VT, ExtendedVT, TLI, Map, Builder))
1645 Builder.
CreateLoad(IntptrTy, NsanShadowRetTag,
false);
1655 ++NumInstrumentedFTCalls;
1661Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1663 const ValueToShadowMap &Map) {
1665 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1666 assert(ExtendedVT !=
nullptr &&
"trying to create a shadow for a non-FT");
1668 if (
auto *Load = dyn_cast<LoadInst>(&Inst))
1669 return handleLoad(*Load, VT, ExtendedVT);
1671 if (
auto *Call = dyn_cast<CallInst>(&Inst)) {
1676 return handleCallBase(*Call, VT, ExtendedVT, TLI, Map, Builder);
1679 if (
auto *Invoke = dyn_cast<InvokeInst>(&Inst)) {
1683 BasicBlock *NextBB = Invoke->getNormalDest();
1690 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1699 if (
auto *Trunc = dyn_cast<FPTruncInst>(&Inst))
1700 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1701 if (
auto *Ext = dyn_cast<FPExtInst>(&Inst))
1702 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1704 if (
auto *UnaryOp = dyn_cast<UnaryOperator>(&Inst))
1705 return Builder.
CreateUnOp(UnaryOp->getOpcode(),
1706 Map.getShadow(UnaryOp->getOperand(0)));
1708 if (
auto *BinOp = dyn_cast<BinaryOperator>(&Inst))
1710 Map.getShadow(BinOp->getOperand(0)),
1711 Map.getShadow(BinOp->getOperand(1)));
1713 if (isa<UIToFPInst>(&Inst) || isa<SIToFPInst>(&Inst)) {
1714 auto *Cast = cast<CastInst>(&Inst);
1715 return Builder.
CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1719 if (
auto *S = dyn_cast<SelectInst>(&Inst))
1721 Map.getShadow(S->getTrueValue()),
1722 Map.getShadow(S->getFalseValue()));
1724 if (
auto *Freeze = dyn_cast<FreezeInst>(&Inst))
1727 if (
auto *Extract = dyn_cast<ExtractElementInst>(&Inst))
1729 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1731 if (
auto *Insert = dyn_cast<InsertElementInst>(&Inst))
1736 if (
auto *Shuffle = dyn_cast<ShuffleVectorInst>(&Inst))
1738 Map.getShadow(Shuffle->getOperand(1)),
1739 Shuffle->getShuffleMask());
1742 if (
auto *Extract = dyn_cast<ExtractValueInst>(&Inst))
1745 if (
auto *BC = dyn_cast<BitCastInst>(&Inst))
1756void NumericalStabilitySanitizer::maybeCreateShadowValue(
1759 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1760 if (ExtendedVT ==
nullptr)
1763 if (
Map.hasShadow(&Root))
1766 assert(!isa<PHINode>(Root) &&
"phi nodes should already have shadows");
1768 std::vector<Instruction *> DfsStack(1, &Root);
1769 while (!DfsStack.empty()) {
1775 if (
Map.hasShadow(
I)) {
1776 DfsStack.pop_back();
1780 bool MissingShadow =
false;
1782 Type *VT =
Op->getType();
1783 if (!
Config.getExtendedFPType(VT))
1785 if (
Map.hasShadow(
Op))
1787 MissingShadow =
true;
1788 DfsStack.push_back(cast<Instruction>(
Op));
1794 Value *Shadow = createShadowValueWithOperandsAvailable(*
I, TLI, Map);
1795 Map.setShadow(*
I, *Shadow);
1796 DfsStack.pop_back();
1801void NumericalStabilitySanitizer::propagateFTStore(
1803 Value *StoredValue =
Store.getValueOperand();
1806 const auto Extents = getMemoryExtentsOrDie(VT);
1808 NsanGetShadowPtrForStore[Extents.ValueType],
1809 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1811 Value *StoredShadow =
Map.getShadow(StoredValue);
1812 if (!
Store.getParent()->getParent()->hasOptNone()) {
1816 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1817 CheckLoc::makeStore(
Store.getPointerOperand()));
1818 ++NumInstrumentedFTStores;
1823 Store.isVolatile());
1834void NumericalStabilitySanitizer::propagateNonFTStore(
1844 IntptrTy,
APInt(IntptrTy->getPrimitiveSizeInBits(), LoadSizeBytes));
1846 ++NumInstrumentedNonFTStores;
1847 Value *StoredValue =
Store.getValueOperand();
1848 if (
LoadInst *Load = dyn_cast<LoadInst>(StoredValue)) {
1855 Type *ShadowValueIntTy =
1859 Value *LoadSrc =
Load->getPointerOperand();
1865 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1867 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}),
Align(1),
1869 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1871 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}),
Align(1),
1876 RawShadowType, Builder.
CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1880 Builder.
CreateCall(NsanGetRawShadowPtr, {Dst}),
1884 ++NumInstrumentedNonFTMemcpyStores;
1889 (
C = dyn_cast<Constant>(StoredValue))) {
1892 Type *BitcastTy =
nullptr;
1893 if (
auto *CInt = dyn_cast<ConstantInt>(
C)) {
1894 switch (CInt->getType()->getScalarSizeInBits()) {
1907 }
else if (
auto *CDV = dyn_cast<ConstantDataVector>(
C)) {
1908 const int NumElements =
1909 cast<VectorType>(CDV->getType())->getElementCount().getFixedValue();
1910 switch (CDV->getType()->getScalarSizeInBits()) {
1928 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1930 NsanGetShadowPtrForStore[Extents.ValueType],
1931 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1933 Type *ExtVT =
Config.getExtendedFPType(BitcastTy);
1937 Store.isVolatile());
1942 Builder.
CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});
1945void NumericalStabilitySanitizer::propagateShadowValues(
1947 const ValueToShadowMap &Map) {
1948 if (
auto *Store = dyn_cast<StoreInst>(&Inst)) {
1949 Value *StoredValue =
Store->getValueOperand();
1951 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1952 if (ExtendedVT ==
nullptr)
1953 return propagateNonFTStore(*Store, VT, Map);
1954 return propagateFTStore(*Store, VT, ExtendedVT, Map);
1957 if (
auto *FCmp = dyn_cast<FCmpInst>(&Inst)) {
1958 emitFCmpCheck(*FCmp, Map);
1962 if (
auto *CB = dyn_cast<CallBase>(&Inst)) {
1963 maybeAddSuffixForNsanInterface(CB);
1964 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
1967 instrumentMemIntrinsic(
MI);
1970 populateShadowStack(*CB, TLI, Map);
1974 if (
auto *RetInst = dyn_cast<ReturnInst>(&Inst)) {
1978 Value *RV = RetInst->getReturnValue();
1982 Type *ExtendedVT =
Config.getExtendedFPType(VT);
1983 if (ExtendedVT ==
nullptr)
1985 Value *RVShadow =
Map.getShadow(RV);
1988 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1989 ++NumInstrumentedFTRets;
1995 Value *ShadowRetValPtr =
2003 Type *VT =
V->getType();
2004 Type *ExtendedVT =
Config.getExtendedFPType(VT);
2005 if (ExtendedVT ==
nullptr)
2008 emitCheck(V,
Map.getShadow(V), Builder, CheckLoc::makeInsert());
2017 std::vector<Instruction *> &Instructions) {
2019#define MOVE_FLAG(attr, setter) \
2020 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
2021 F.removeFnAttr(attr); \
2022 FMF.set##setter(); \
2027 MOVE_FLAG(
"no-signed-zeros-fp-math", NoSignedZeros)
2031 if (isa<FPMathOperator>(
I))
2032 I->setFastMathFlags(FMF);
2035bool NumericalStabilitySanitizer::sanitizeFunction(
2037 if (!
F.hasFnAttribute(Attribute::SanitizeNumericalStability) ||
2136 std::vector<Instruction *> OriginalInstructions;
2142 ValueToShadowMap ValueToShadow(
Config);
2147 std::vector<PHINode *> OriginalPhis;
2148 createShadowArguments(
F, TLI, ValueToShadow);
2150 if (
PHINode *Phi = dyn_cast<PHINode>(
I)) {
2151 if (
PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2152 OriginalPhis.push_back(Phi);
2153 ValueToShadow.setShadow(*Phi, *Shadow);
2160 maybeCreateShadowValue(*
I, TLI, ValueToShadow);
2164 propagateShadowValues(*
I, TLI, ValueToShadow);
2167 for (
PHINode *Phi : OriginalPhis) {
2168 PHINode *ShadowPhi = cast<PHINode>(ValueToShadow.getShadow(Phi));
2169 for (
unsigned I :
seq(
Phi->getNumOperands())) {
2171 Value *Shadow = ValueToShadow.getShadow(V);
2183 return !ValueToShadow.empty();
2188 if (
Constant *
C = dyn_cast<Constant>(V)) {
2189 auto *CInt = dyn_cast<ConstantInt>(
C);
2190 if (CInt && CInt->getValue().getBitWidth() <= 64)
2191 OpSize = CInt->getValue().getZExtValue();
2199bool NumericalStabilitySanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
2201 if (
auto *M = dyn_cast<MemSetInst>(
MI)) {
2203 NsanSetUnknownFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2205 Builder.
CreateCall(SetUnknownFn, {
M->getArgOperand(0)});
2208 {
M->getArgOperand(0),
2212 }
else if (
auto *M = dyn_cast<MemTransferInst>(
MI)) {
2214 NsanCopyFns.getFunctionFor(
GetMemOpSize(
M->getArgOperand(2)));
2218 M->getArgOperand(1)});
2221 M->getArgOperand(1),
2229void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(
CallBase *CI) {
2237 if (Fn->
getName() ==
"__nsan_dump_shadow_mem") {
2239 "invalid prototype for __nsan_dump_shadow_mem");
2244 const uint64_t shadow_value_type_ids =
2245 (
static_cast<size_t>(
Config.byValueType(kLongDouble).getNsanTypeId())
2247 (
static_cast<size_t>(
Config.byValueType(kDouble).getNsanTypeId())
2249 static_cast<size_t>(
Config.byValueType(kFloat).getNsanTypeId());
2250 CI->
setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)
static FunctionType * makeDoubleDouble(LLVMContext &C)
constexpr int kMaxVectorWidth
static cl::opt< bool > ClCheckRet("nsan-check-ret", cl::init(true), cl::desc("Check floating-point return values"), cl::Hidden)
static bool shouldCheckArgs(CallBase &CI, const TargetLibraryInfo &TLI, const std::optional< Regex > &CheckFunctionsFilter)
static cl::opt< bool > ClCheckStores("nsan-check-stores", cl::init(true), cl::desc("Check floating-point stores"), cl::Hidden)
static FunctionType * makeX86FP80X86FP80(LLVMContext &C)
#define MOVE_FLAG(attr, setter)
static FunctionType * makeX86FP80X86FP80I32(LLVMContext &C)
constexpr int kMaxNumArgs
constexpr int kMaxShadowTypeSizeBytes
static const char * getIntrinsicFromLibfunc(Function &Fn, Type *VT, const TargetLibraryInfo &TLI)
static FunctionType * makeX86FP80X86FP80X86FP80(LLVMContext &C)
static FunctionType * makeX86FP80X86FP80X86FP80X86FP80(LLVMContext &C)
static uint64_t GetMemOpSize(Value *V)
constexpr StringLiteral kNsanInitName("__nsan_init")
static FunctionType * makeDoubleDoubleDouble(LLVMContext &C)
constexpr int kShadowScale
static cl::opt< bool > ClCheckLoads("nsan-check-loads", cl::desc("Check floating-point load"), cl::Hidden)
constexpr StringLiteral kNsanModuleCtorName("nsan.module_ctor")
static cl::opt< bool > ClPropagateNonFTConstStoresAsFT("nsan-propagate-non-ft-const-stores-as-ft", cl::desc("Propagate non floating-point const stores as floating point values." "For debugging purposes only"), cl::Hidden)
static cl::opt< std::string > ClShadowMapping("nsan-shadow-type-mapping", cl::init("dqq"), cl::desc("One shadow type id for each of `float`, `double`, `long double`. " "`d`,`l`,`q`,`e` mean double, x86_fp80, fp128 (quad) and " "ppc_fp128 (extended double) respectively. The default is to " "shadow `float` as `double`, and `double` and `x86_fp80` as " "`fp128`"), cl::Hidden)
static FunctionType * makeDoubleDoubleDoubleDouble(LLVMContext &C)
static cl::opt< bool > ClTruncateFCmpEq("nsan-truncate-fcmp-eq", cl::init(true), cl::desc("This flag controls the behaviour of fcmp equality comparisons." "For equality comparisons such as `x == 0.0f`, we can perform the " "shadow check in the shadow (`x_shadow == 0.0) == (x == 0.0f)`) or app " " domain (`(trunc(x_shadow) == 0.0f) == (x == 0.0f)`). This helps " "catch the case when `x_shadow` is accurate enough (and therefore " "close enough to zero) so that `trunc(x_shadow)` is zero even though " "both `x` and `x_shadow` are not"), cl::Hidden)
static cl::opt< std::string > ClCheckFunctionsFilter("check-functions-filter", cl::desc("Only emit checks for arguments of functions " "whose names match the given regular expression"), cl::value_desc("regex"))
static FunctionType * makeDoubleDoubleI32(LLVMContext &C)
static void moveFastMathFlags(Function &F, std::vector< Instruction * > &Instructions)
static cl::opt< bool > ClInstrumentFCmp("nsan-instrument-fcmp", cl::init(true), cl::desc("Instrument floating-point comparisons"), cl::Hidden)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Class for arbitrary precision integers.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
AttributeList addFnAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add a function attribute to the list.
LLVM Basic Block Representation.
void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction & back() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
void setArgOperand(unsigned i, Value *v)
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Predicate getPredicate() const
Return the predicate for this instruction.
ConstantFP - Floating Point Values [float, double].
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
This instruction compares its operands according to the predicate given to the constructor.
static bool isEquality(Predicate Pred)
This class represents an extension of floating point types.
This class represents a truncation of floating point types.
Convenience struct for specifying and reasoning about fast-math flags.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType()
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateFreeze(Value *V, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
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 * 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 * 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)
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 tuples (A, B,...
std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)