LLVM: lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

17

42

43#include

44

45using namespace llvm;

46

47#define DEBUG_TYPE "nsan"

48

50 "Number of instrumented floating-point loads");

51

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");

64

65

66

67

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 "

74 "`fp128`"),

76

79 cl::desc("Instrument floating-point comparisons"),

81

83 "check-functions-filter",

84 cl::desc("Only emit checks for arguments of functions "

85 "whose names match the given regular expression"),

87

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"),

99

100

101

102

103

104

105

106

107

108

110 cl::desc("Check floating-point load"),

112

114 cl::desc("Check floating-point stores"),

116

118 cl::desc("Check floating-point return values"),

120

121

122

123

124

125

126

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"),

133

136

137

142

143namespace {

144

145

146

147class ShadowTypeConfig {

148public:

149 static std::unique_ptr fromNsanTypeId(char TypeId);

150

151

153

154

155 virtual char getNsanTypeId() const = 0;

156

157 virtual ~ShadowTypeConfig() = default;

158};

159

160template

161class ShadowTypeConfigImpl : public ShadowTypeConfig {

162public:

163 char getNsanTypeId() const override { return NsanTypeId; }

164 static constexpr char kNsanTypeId = NsanTypeId;

165};

166

167

168class F64ShadowConfig : public ShadowTypeConfigImpl<'d'> {

171 }

172};

173

174

175class F80ShadowConfig : public ShadowTypeConfigImpl<'l'> {

178 }

179};

180

181

182class F128ShadowConfig : public ShadowTypeConfigImpl<'q'> {

185 }

186};

187

188

189class PPC128ShadowConfig : public ShadowTypeConfigImpl<'e'> {

192 }

193};

194

195

196std::unique_ptr

197ShadowTypeConfig::fromNsanTypeId(const char TypeId) {

198 switch (TypeId) {

199 case F64ShadowConfig::kNsanTypeId:

200 return std::make_unique();

201 case F80ShadowConfig::kNsanTypeId:

202 return std::make_unique();

203 case F128ShadowConfig::kNsanTypeId:

204 return std::make_unique();

205 case PPC128ShadowConfig::kNsanTypeId:

206 return std::make_unique();

207 }

209}

210

211

212

213enum FTValueType { kFloat, kDouble, kLongDouble, kNumValueTypes };

214

215

216static std::optional ftValueTypeFromType(Type *FT) {

218 return kFloat;

220 return kDouble;

222 return kLongDouble;

223 return {};

224}

225

226

227static Type *typeFromFTValueType(FTValueType VT, LLVMContext &Context) {

228 switch (VT) {

229 case kFloat:

231 case kDouble:

233 case kLongDouble:

235 case kNumValueTypes:

236 return nullptr;

237 }

239}

240

241

242static const char *typeNameFromFTValueType(FTValueType VT) {

243 switch (VT) {

244 case kFloat:

245 return "float";

246 case kDouble:

247 return "double";

248 case kLongDouble:

249 return "longdouble";

250 case kNumValueTypes:

251 return nullptr;

252 }

254}

255

256

257

258class MappingConfig {

259public:

263 unsigned ShadowTypeSizeBits[kNumValueTypes];

264 for (int VT = 0; VT < kNumValueTypes; ++VT) {

265 auto Config = ShadowTypeConfig::fromNsanTypeId(ClShadowMapping[VT]);

266 if (!Config)

269 const unsigned AppTypeSize =

270 typeFromFTValueType(static_cast<FTValueType>(VT), Context)

271 ->getScalarSizeInBits();

272 const unsigned ShadowTypeSize =

273 Config->getType(Context)->getScalarSizeInBits();

274

275

276 if (ShadowTypeSize > kShadowScale * AppTypeSize)

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);

284 }

285

286

287

288

289

290

291

292 if (ShadowTypeSizeBits[kFloat] > ShadowTypeSizeBits[kDouble] ||

293 ShadowTypeSizeBits[kDouble] > ShadowTypeSizeBits[kLongDouble])

295 Twine(ShadowTypeSizeBits[kFloat]) + "; double->f" +

296 Twine(ShadowTypeSizeBits[kDouble]) +

297 "; long double->f" +

298 Twine(ShadowTypeSizeBits[kLongDouble]) + " }");

299 }

300

301 const ShadowTypeConfig &byValueType(FTValueType VT) const {

302 assert(VT < FTValueType::kNumValueTypes && "invalid value type");

303 return *Configs[VT];

304 }

305

306

307 Type *getExtendedFPType(Type *FT) const {

308 if (const auto VT = ftValueTypeFromType(FT))

309 return Configs[*VT]->getType(Context);

312

313 if (VecTy->isScalableTy())

314 return nullptr;

315 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());

316 return ExtendedScalar

317 ? VectorType::get(ExtendedScalar, VecTy->getElementCount())

318 : nullptr;

319 }

320 return nullptr;

321 }

322

323private:

325 std::unique_ptr Configs[FTValueType::kNumValueTypes];

326};

327

328

329

330struct MemoryExtents {

333};

334

335static MemoryExtents getMemoryExtentsOrDie(Type *FT) {

336 if (const auto VT = ftValueTypeFromType(FT))

337 return {*VT, 1};

339 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());

340 return {ScalarExtents.ValueType,

341 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};

342 }

344}

345

346

347class CheckLoc {

348public:

349

350 static CheckLoc makeStore(Value *Address) {

351 CheckLoc Result(kStore);

352 Result.Address = Address;

353 return Result;

354 }

355 static CheckLoc makeLoad(Value *Address) {

356 CheckLoc Result(kLoad);

357 Result.Address = Address;

358 return Result;

359 }

360

361

362 static CheckLoc makeArg(int ArgId) {

363 CheckLoc Result(kArg);

364 Result.ArgId = ArgId;

365 return Result;

366 }

367

368

369 static CheckLoc makeRet() { return CheckLoc(kRet); }

370

371

372 static CheckLoc makeInsert() { return CheckLoc(kInsert); }

373

374

375

377 return ConstantInt::get(Type::getInt32Ty(C), static_cast<int>(CheckTy));

378 }

379

380

381

382

384 switch (CheckTy) {

385 case kUnknown:

387 case kRet:

388 case kInsert:

389 return ConstantInt::get(IntptrTy, 0);

390 case kArg:

391 return ConstantInt::get(IntptrTy, ArgId);

392 case kLoad:

393 case kStore:

394 return Builder.CreatePtrToInt(Address, IntptrTy);

395 }

397 }

398

399private:

400

401

403 kUnknown = 0,

404 kRet,

405 kArg,

406 kLoad,

407 kStore,

408 kInsert,

409 };

410 explicit CheckLoc(CheckType CheckTy) : CheckTy(CheckTy) {}

411

412 Value *Address = nullptr;

414 int ArgId = -1;

415};

416

417

418class ValueToShadowMap {

419public:

420 explicit ValueToShadowMap(const MappingConfig &Config) : Config(Config) {}

421

422 ValueToShadowMap(const ValueToShadowMap &) = delete;

423 ValueToShadowMap &operator=(const ValueToShadowMap &) = delete;

424

425

426

427 void setShadow(Value &V, Value &Shadow) {

428 [[maybe_unused]] const bool Inserted = Map.try_emplace(&V, &Shadow).second;

430 if (!Inserted) {

432 errs() << I->getFunction()->getName() << ": ";

433 errs() << "duplicate shadow (" << &V << "): ";

434 V.dump();

435 }

436 });

437 assert(Inserted && "duplicate shadow");

438 }

439

440

441

443

444

445

448 return getShadowConstant(C);

449 return Map.find(V)->second;

450 }

451

452 bool empty() const { return Map.empty(); }

453

454private:

455

457 bool LosesInfo = false;

459 return CV;

460 }

461

462

465 return UndefValue::get(Config.getExtendedFPType(U->getType()));

466 }

468

469 Type *Ty = Config.getExtendedFPType(CFP->getType());

470 return ConstantFP::get(

471 Ty, extendConstantFP(CFP->getValueAPF(),

472 Ty->getScalarType()->getFltSemantics()));

473 }

474

475 if (C->getType()->isVectorTy()) {

478 ->getElementCount()

479 .getFixedValue();

480 I < E; ++I)

481 Elements.push_back(getShadowConstant(C->getAggregateElement(I)));

483 }

485 }

486

487 const MappingConfig &Config;

489};

490

491class NsanMemOpFn {

492public:

494 size_t NumArgs);

497

498private:

500 size_t NumSizedFuncs;

501};

502

506 AttributeList Attr;

507 Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);

510 IntegerType *IntptrTy = M.getDataLayout().getIntPtrType(Ctx);

512

513 NumSizedFuncs = Sized.size();

514

515

516 if (NumArgs == 3) {

517 Funcs.push_back(

518 M.getOrInsertFunction(Fallback, Attr, VoidTy, PtrTy, PtrTy, IntptrTy));

520 } else if (NumArgs == 2) {

521 Funcs.push_back(

522 M.getOrInsertFunction(Fallback, Attr, VoidTy, PtrTy, IntptrTy));

524 } else {

525 llvm_unreachable("Unexpected value of sized functions arguments");

526 }

527

528 for (size_t i = 0; i < NumSizedFuncs; ++i)

529 Funcs.push_back(M.getOrInsertFunction(Sized[i], SizedFnTy, Attr));

530}

531

533

534

535 assert(NumSizedFuncs >= 3 && "Unexpected number of sized functions");

536

537 size_t Idx =

538 MemOpSize == 4 ? 1 : (MemOpSize == 8 ? 2 : (MemOpSize == 16 ? 3 : 0));

539

540 return Funcs[Idx];

541}

542

543FunctionCallee NsanMemOpFn::getFallback() const { return Funcs[0]; }

544

545

546

547

548

549class NumericalStabilitySanitizer {

550public:

551 NumericalStabilitySanitizer(Module &M);

553

554private:

556 void maybeAddSuffixForNsanInterface(CallBase *CI);

557 bool addrPointsToConstantData(Value *Addr);

559 ValueToShadowMap &Map);

560 Value *createShadowValueWithOperandsAvailable(Instruction &Inst,

562 const ValueToShadowMap &Map);

565 ValueToShadowMap &Map);

566

568 const ValueToShadowMap &Map);

569

571 const ValueToShadowMap &Map);

573 CheckLoc Loc);

575 CheckLoc Loc);

576 void emitFCmpCheck(FCmpInst &FCmp, const ValueToShadowMap &Map);

577

578

582 const ValueToShadowMap &Map, IRBuilder<> &Builder);

585 const ValueToShadowMap &Map,

588 const ValueToShadowMap &Map, IRBuilder<> &Builder);

590 const ValueToShadowMap &Map, IRBuilder<> &Builder);

591

592

593 void propagateFTStore(StoreInst &Store, Type *VT, Type *ExtendedVT,

594 const ValueToShadowMap &Map);

595 void propagateNonFTStore(StoreInst &Store, Type *VT,

596 const ValueToShadowMap &Map);

597

600 MappingConfig Config;

602

603

604 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};

605 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};

606 FunctionCallee NsanCheckValue[FTValueType::kNumValueTypes] = {};

607 FunctionCallee NsanFCmpFail[FTValueType::kNumValueTypes] = {};

608

609 NsanMemOpFn NsanCopyFns;

610 NsanMemOpFn NsanSetUnknownFns;

611

615

616 Type *NsanShadowRetType = nullptr;

618

619 GlobalValue *NsanShadowArgsTag = nullptr;

620

621 Type *NsanShadowArgsType = nullptr;

622 GlobalValue *NsanShadowArgsPtr = nullptr;

623

624 std::optional CheckFunctionsFilter;

625};

626}

627

628PreservedAnalyses

632 {},

633

634

636

637 NumericalStabilitySanitizer Nsan(M);

641

643}

644

646 return M.getOrInsertGlobal(Name, Ty, [&M, Ty, Name] {

648 nullptr, Name, nullptr,

650 });

651}

652

653NumericalStabilitySanitizer::NumericalStabilitySanitizer(Module &M)

655 NsanCopyFns(M, {"__nsan_copy_4", "__nsan_copy_8", "__nsan_copy_16"},

656 "__nsan_copy_values", 3),

657 NsanSetUnknownFns(M,

658 {"__nsan_set_value_unknown_4",

659 "__nsan_set_value_unknown_8",

660 "__nsan_set_value_unknown_16"},

661 "__nsan_set_value_unknown", 2) {

662 IntptrTy = DL.getIntPtrType(Context);

667

668 AttributeList Attr;

669 Attr = Attr.addFnAttribute(Context, Attribute::NoUnwind);

670

671 for (int I = 0; I < kNumValueTypes; ++I) {

672 const FTValueType VT = static_cast<FTValueType>(I);

673 const char *VTName = typeNameFromFTValueType(VT);

674 Type *VTTy = typeFromFTValueType(VT, Context);

675

676

677 const std::string GetterPrefix =

678 std::string("__nsan_get_shadow_ptr_for_") + VTName;

679 NsanGetShadowPtrForStore[VT] = M.getOrInsertFunction(

680 GetterPrefix + "_store", Attr, PtrTy, PtrTy, IntptrTy);

681 NsanGetShadowPtrForLoad[VT] = M.getOrInsertFunction(

682 GetterPrefix + "_load", Attr, PtrTy, PtrTy, IntptrTy);

683

684

685 const auto &ShadowConfig = Config.byValueType(VT);

686 Type *ShadowTy = ShadowConfig.getType(Context);

687 NsanCheckValue[VT] =

688 M.getOrInsertFunction(std::string("__nsan_internal_check_") + VTName +

689 "_" + ShadowConfig.getNsanTypeId(),

691 NsanFCmpFail[VT] = M.getOrInsertFunction(

692 std::string("__nsan_fcmp_fail_") + VTName + "_" +

693 ShadowConfig.getNsanTypeId(),

694 Attr, VoidTy, VTTy, VTTy, ShadowTy, ShadowTy, Int32Ty, Int1Ty, Int1Ty);

695 }

696

697

698 NsanGetRawShadowTypePtr = M.getOrInsertFunction(

699 "__nsan_internal_get_raw_shadow_type_ptr", Attr, PtrTy, PtrTy);

700 NsanGetRawShadowPtr = M.getOrInsertFunction(

701 "__nsan_internal_get_raw_shadow_ptr", Attr, PtrTy, PtrTy);

702

703 NsanShadowRetTag = createThreadLocalGV("__nsan_shadow_ret_tag", M, IntptrTy);

704

707 NsanShadowRetPtr =

709

710 NsanShadowArgsTag =

712

713 NsanShadowArgsType =

716

717 NsanShadowArgsPtr =

719

722 std::string RegexError;

723 assert(R.isValid(RegexError));

724 CheckFunctionsFilter = std::move(R);

725 }

726}

727

728

729

730bool NumericalStabilitySanitizer::addrPointsToConstantData(Value *Addr) {

731

733 Addr = GEP->getPointerOperand();

734

736 return GV->isConstant();

737 return false;

738}

739

740

741

742

743

744

745

746

747

748

749

750

751

752void NumericalStabilitySanitizer::createShadowArguments(

753 Function &F, const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {

754 assert(F.getIntrinsicID() && "found a definition of an intrinsic");

755

756

757 if (all_of(F.args(), [this](const Argument &Arg) {

758 return Config.getExtendedFPType(Arg.getType()) == nullptr;

759 }))

760 return;

761

762 IRBuilder<> Builder(&F.getEntryBlock(), F.getEntryBlock().getFirstNonPHIIt());

763

764

765 Value *HasShadowArgs = Builder.CreateICmpEQ(

766 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag, false),

767 Builder.CreatePtrToInt(&F, IntptrTy));

768

769 unsigned ShadowArgsOffsetBytes = 0;

770 for (Argument &Arg : F.args()) {

772 Type *ExtendedVT = Config.getExtendedFPType(VT);

773 if (ExtendedVT == nullptr)

774 continue;

775 Value *L = Builder.CreateAlignedLoad(

776 ExtendedVT,

777 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,

778 ShadowArgsOffsetBytes),

779 Align(1), false);

780 Value *Shadow = Builder.CreateSelect(HasShadowArgs, L,

781 Builder.CreateFPExt(&Arg, ExtendedVT));

782 Map.setShadow(Arg, *Shadow);

783 TypeSize SlotSize = DL.getTypeStoreSize(ExtendedVT);

785 ShadowArgsOffsetBytes += SlotSize;

786 }

787 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);

788}

789

790

791

793 const std::optional &CheckFunctionsFilter) {

794

796

797 if (CheckFunctionsFilter) {

798

799 if (Fn == nullptr)

800 return false;

801 if (CheckFunctionsFilter->match(Fn->getName()))

802 return true;

803 return false;

804 }

805

806 if (Fn == nullptr)

807 return true;

808

809

811 return false;

812

814 LibFunc LFunc = LibFunc::NotLibFunc;

815

817 return true;

818

819

820

821

822 if (ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||

823 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)

824 for (const auto &U : CI.users())

826 return false;

827

828 return true;

829}

830

831

832

833void NumericalStabilitySanitizer::populateShadowStack(

834 CallBase &CI, const TargetLibraryInfo &TLI, const ValueToShadowMap &Map) {

835

837 return;

838

839

841 return Config.getExtendedFPType(Arg->getType()) == nullptr;

842 }))

843 return;

844

846 SmallVector<Value *, 8> ArgShadows;

847 const bool ShouldCheckArgs = shouldCheckArgs(CI, TLI, CheckFunctionsFilter);

849 if (Config.getExtendedFPType(Arg->getType()) == nullptr)

850 continue;

851 Value *ArgShadow = Map.getShadow(Arg);

852 ArgShadows.push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,

853 CheckLoc::makeArg(ArgIdx))

854 : ArgShadow);

855 }

856

857

859 LibFunc LFunc;

860 if (Fn->isIntrinsic() || TLI.getLibFunc(*Fn, LFunc))

861 return;

862 }

863

864

865 Builder.CreateStore(CI.getCalledOperand(), NsanShadowArgsTag);

867

868 unsigned ShadowArgId = 0;

871 Type *ExtendedVT = Config.getExtendedFPType(VT);

872 if (ExtendedVT == nullptr)

873 continue;

874 Builder.CreateAlignedStore(

875 ArgShadows[ShadowArgId++],

876 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,

877 ShadowArgsOffsetBytes),

878 Align(1), false);

879 TypeSize SlotSize = DL.getTypeStoreSize(ExtendedVT);

881 ShadowArgsOffsetBytes += SlotSize;

882 }

883}

884

885

886

887

892

893Value *NumericalStabilitySanitizer::emitCheckInternal(Value *V, Value *ShadowV,

895 CheckLoc Loc) {

896

898 return ConstantInt::get(

901

902 Type *Ty = V->getType();

903 if (const auto VT = ftValueTypeFromType(Ty))

905 NsanCheckValue[*VT],

906 {V, ShadowV, Loc.getType(Context), Loc.getValue(IntptrTy, Builder)});

907

910

911

912 assert(!VecTy->isScalableTy() &&

913 "Scalable vector types are not supported yet");

914 Value *CheckResult = nullptr;

915 for (int I = 0, E = VecTy->getElementCount().getFixedValue(); I < E; ++I) {

916

917

918

921 Value *ComponentCheckResult =

922 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);

923 CheckResult = CheckResult

924 ? Builder.CreateOr(CheckResult, ComponentCheckResult)

925 : ComponentCheckResult;

926 }

927 return CheckResult;

928 }

930 Value *CheckResult = nullptr;

934 Value *ComponentCheckResult =

935 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);

936 CheckResult = CheckResult

937 ? Builder.CreateOr(CheckResult, ComponentCheckResult)

938 : ComponentCheckResult;

939 }

940 return CheckResult;

941 }

943 Value *CheckResult = nullptr;

946 continue;

949 Value *ComponentCheckResult =

950 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);

951 CheckResult = CheckResult

952 ? Builder.CreateOr(CheckResult, ComponentCheckResult)

953 : ComponentCheckResult;

954 }

955 if (!CheckResult)

956 return ConstantInt::get(

959 return CheckResult;

960 }

961

963}

964

965

966

967

968

969

970

971Value *NumericalStabilitySanitizer::emitCheck(Value *V, Value *ShadowV,

973 CheckLoc Loc) {

974

976 return ShadowV;

977

979 Function *F = Inst->getFunction();

980 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(F->getName())) {

981 return ShadowV;

982 }

983 }

984

985 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);

987 CheckResult,

988 ConstantInt::get(Builder.getInt32Ty(),

991 ICmpEQ, Builder.CreateFPExt(V, Config.getExtendedFPType(V->getType())),

992 ShadowV);

993}

994

995

996

997void NumericalStabilitySanitizer::emitFCmpCheck(FCmpInst &FCmp,

998 const ValueToShadowMap &Map) {

1000 return;

1001

1003 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(F->getName()))

1004 return;

1005

1007 if (Config.getExtendedFPType(LHS->getType()) == nullptr)

1008 return;

1010

1011

1012

1015

1019

1020

1022 FCmpBuilder.SetCurrentDebugLocation(FCmp.getDebugLoc());

1025

1028 ShadowLHS = FCmpBuilder.CreateFPExt(

1029 FCmpBuilder.CreateFPTrunc(ShadowLHS, LHS->getType()), Ty);

1030 ShadowRHS = FCmpBuilder.CreateFPExt(

1031 FCmpBuilder.CreateFPTrunc(ShadowRHS, RHS->getType()), Ty);

1032 }

1033 Value *ShadowFCmp =

1034 FCmpBuilder.CreateFCmp(FCmp.getPredicate(), ShadowLHS, ShadowRHS);

1035 Value *OriginalAndShadowFcmpMatch =

1036 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);

1037

1039

1040

1041

1042 OriginalAndShadowFcmpMatch =

1043 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);

1044 }

1045

1046

1047

1048 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,

1049 MDBuilder(Context).createLikelyBranchWeights());

1050

1051

1053 FailBuilder.SetCurrentDebugLocation(FCmp.getDebugLoc());

1054

1055 const auto EmitFailCall = [this, &FCmp, &FCmpBuilder,

1058 Value *ShadowResult) {

1059 Type *FT = L->getType();

1060 FunctionCallee *Callee = nullptr;

1062 Callee = &(NsanFCmpFail[kFloat]);

1064 Callee = &(NsanFCmpFail[kDouble]);

1066

1067 Callee = &(NsanFCmpFail[kDouble]);

1068 L = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(Context));

1069 R = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(Context));

1070 } else {

1072 }

1073 FailBuilder.CreateCall(*Callee, {L, R, ShadowL, ShadowR,

1074 ConstantInt::get(FCmpBuilder.getInt32Ty(),

1076 Result, ShadowResult});

1077 };

1080 ->getElementCount()

1081 .getFixedValue();

1082 I < E; ++I) {

1083 Value *ExtractLHS = FailBuilder.CreateExtractElement(LHS, I);

1084 Value *ExtractRHS = FailBuilder.CreateExtractElement(RHS, I);

1085 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS, I);

1086 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS, I);

1087 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp, I);

1088 Value *ExtractShadowFCmp =

1089 FailBuilder.CreateExtractElement(ShadowFCmp, I);

1090 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,

1091 ExtractFCmp, ExtractShadowFCmp);

1092 }

1093 } else {

1094 EmitFailCall(LHS, RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);

1095 }

1096 FailBuilder.CreateBr(NextBB);

1097

1098 ++NumInstrumentedFCmp;

1099}

1100

1101

1102PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(

1103 PHINode &Phi, const TargetLibraryInfo &TLI) {

1104 Type *VT = Phi.getType();

1105 Type *ExtendedVT = Config.getExtendedFPType(VT);

1106 if (ExtendedVT == nullptr)

1107 return nullptr;

1108

1109

1110

1111 PHINode *Shadow = PHINode::Create(ExtendedVT, Phi.getNumIncomingValues());

1113 return Shadow;

1114}

1115

1116Value *NumericalStabilitySanitizer::handleLoad(LoadInst &Load, Type *VT,

1117 Type *ExtendedVT) {

1120 if (addrPointsToConstantData(Load.getPointerOperand())) {

1121

1122

1123 return Builder.CreateFPExt(&Load, ExtendedVT);

1124 }

1125

1126

1127

1128

1129

1130

1131

1132

1133

1134

1135

1136

1137

1138

1139

1140 const auto Extents = getMemoryExtentsOrDie(VT);

1142 NsanGetShadowPtrForLoad[Extents.ValueType],

1143 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});

1144 ++NumInstrumentedFTLoads;

1145

1146

1149

1154

1155

1156

1157 {

1159 IRBuilder<> LoadBBBuilder(LoadBB);

1160 LoadBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());

1161 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,

1162 ShadowLoadBB);

1163 }

1164

1165

1166 IRBuilder<> ShadowLoadBBBuilder(ShadowLoadBB);

1167 ShadowLoadBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());

1168 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(

1169 ExtendedVT, ShadowPtr, Align(1), Load.isVolatile());

1171 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,

1172 CheckLoc::makeLoad(Load.getPointerOperand()));

1173 }

1174 ShadowLoadBBBuilder.CreateBr(NextBB);

1175

1176

1178 FExtBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());

1179 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);

1180 FExtBBBuilder.CreateBr(NextBB);

1181

1182

1184 NextBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());

1185 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);

1186 ShadowPhi->addIncoming(ShadowLoad, ShadowLoadBB);

1188 return ShadowPhi;

1189}

1190

1191Value *NumericalStabilitySanitizer::handleTrunc(const FPTruncInst &Trunc,

1193 const ValueToShadowMap &Map,

1196 Type *OrigSourceTy = OrigSource->getType();

1197 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);

1198

1199

1200

1201

1202

1203

1204

1205

1206

1207

1208

1209

1210

1211

1212

1213

1214

1215

1216

1217

1218

1219

1220

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230 Value *Source = ExtendedSourceTy ? Map.getShadow(OrigSource) : OrigSource;

1231 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;

1232

1233 if (SourceTy == ExtendedVT)

1235

1236 return Builder.CreateFPTrunc(Source, ExtendedVT);

1237}

1238

1239Value *NumericalStabilitySanitizer::handleExt(const FPExtInst &Ext, Type *VT,

1240 Type *ExtendedVT,

1241 const ValueToShadowMap &Map,

1244 Type *OrigSourceTy = OrigSource->getType();

1245 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);

1246

1247

1248

1249

1250

1251

1252

1253

1254

1255

1256

1257

1258

1259

1260

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1277 Value *Source = ExtendedSourceTy ? Map.getShadow(OrigSource) : OrigSource;

1278 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;

1279

1280 if (SourceTy == ExtendedVT)

1282

1283 return Builder.CreateFPExt(Source, ExtendedVT);

1284}

1285

1286namespace {

1287

1288struct KnownIntrinsic {

1289 struct WidenedIntrinsic {

1290 const char *NarrowName;

1292 using FnTypeFactory = FunctionType *(*)(LLVMContext &);

1293 FnTypeFactory MakeFnTy;

1294 };

1295

1296 static const char *get(LibFunc LFunc);

1297

1298

1299

1300

1301

1302

1303 static const WidenedIntrinsic *widen(StringRef Name);

1304

1305private:

1306 struct LFEntry {

1307 LibFunc LFunc;

1308 const char *IntrinsicName;

1309 };

1310 static const LFEntry kLibfuncIntrinsics[];

1311

1312 static const WidenedIntrinsic kWidenedIntrinsics[];

1313};

1314}

1315

1319

1324

1329

1335

1340

1346

1353

1360

1361const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {

1362

1363

1364

1365

1366

1367

1368

1369

1401

1403

1405

1407

1439 {"llvm.nearbyint.f32", Intrinsic::nearbyint, makeDoubleDouble},

1457};

1458

1459const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {

1460 {LibFunc_sqrtf, "llvm.sqrt.f32"},

1461 {LibFunc_sqrt, "llvm.sqrt.f64"},

1462 {LibFunc_sqrtl, "llvm.sqrt.f80"},

1463 {LibFunc_sinf, "llvm.sin.f32"},

1464 {LibFunc_sin, "llvm.sin.f64"},

1465 {LibFunc_sinl, "llvm.sin.f80"},

1466 {LibFunc_cosf, "llvm.cos.f32"},

1467 {LibFunc_cos, "llvm.cos.f64"},

1468 {LibFunc_cosl, "llvm.cos.f80"},

1469 {LibFunc_powf, "llvm.pow.f32"},

1470 {LibFunc_pow, "llvm.pow.f64"},

1471 {LibFunc_powl, "llvm.pow.f80"},

1472 {LibFunc_expf, "llvm.exp.f32"},

1473 {LibFunc_exp, "llvm.exp.f64"},

1474 {LibFunc_expl, "llvm.exp.f80"},

1475 {LibFunc_exp2f, "llvm.exp2.f32"},

1476 {LibFunc_exp2, "llvm.exp2.f64"},

1477 {LibFunc_exp2l, "llvm.exp2.f80"},

1478 {LibFunc_logf, "llvm.log.f32"},

1479 {LibFunc_log, "llvm.log.f64"},

1480 {LibFunc_logl, "llvm.log.f80"},

1481 {LibFunc_log10f, "llvm.log10.f32"},

1482 {LibFunc_log10, "llvm.log10.f64"},

1483 {LibFunc_log10l, "llvm.log10.f80"},

1484 {LibFunc_log2f, "llvm.log2.f32"},

1485 {LibFunc_log2, "llvm.log2.f64"},

1486 {LibFunc_log2l, "llvm.log2.f80"},

1487 {LibFunc_fabsf, "llvm.fabs.f32"},

1488 {LibFunc_fabs, "llvm.fabs.f64"},

1489 {LibFunc_fabsl, "llvm.fabs.f80"},

1490 {LibFunc_copysignf, "llvm.copysign.f32"},

1491 {LibFunc_copysign, "llvm.copysign.f64"},

1492 {LibFunc_copysignl, "llvm.copysign.f80"},

1493 {LibFunc_floorf, "llvm.floor.f32"},

1494 {LibFunc_floor, "llvm.floor.f64"},

1495 {LibFunc_floorl, "llvm.floor.f80"},

1496 {LibFunc_fmaxf, "llvm.maxnum.f32"},

1497 {LibFunc_fmax, "llvm.maxnum.f64"},

1498 {LibFunc_fmaxl, "llvm.maxnum.f80"},

1499 {LibFunc_fminf, "llvm.minnum.f32"},

1500 {LibFunc_fmin, "llvm.minnum.f64"},

1501 {LibFunc_fminl, "llvm.minnum.f80"},

1502 {LibFunc_ceilf, "llvm.ceil.f32"},

1503 {LibFunc_ceil, "llvm.ceil.f64"},

1504 {LibFunc_ceill, "llvm.ceil.f80"},

1505 {LibFunc_truncf, "llvm.trunc.f32"},

1506 {LibFunc_trunc, "llvm.trunc.f64"},

1507 {LibFunc_truncl, "llvm.trunc.f80"},

1508 {LibFunc_rintf, "llvm.rint.f32"},

1509 {LibFunc_rint, "llvm.rint.f64"},

1510 {LibFunc_rintl, "llvm.rint.f80"},

1511 {LibFunc_nearbyintf, "llvm.nearbyint.f32"},

1512 {LibFunc_nearbyint, "llvm.nearbyint.f64"},

1513 {LibFunc_nearbyintl, "llvm.nearbyint.f80"},

1514 {LibFunc_roundf, "llvm.round.f32"},

1515 {LibFunc_round, "llvm.round.f64"},

1516 {LibFunc_roundl, "llvm.round.f80"},

1517};

1518

1519const char *KnownIntrinsic::get(LibFunc LFunc) {

1520 for (const auto &E : kLibfuncIntrinsics) {

1521 if (E.LFunc == LFunc)

1522 return E.IntrinsicName;

1523 }

1524 return nullptr;

1525}

1526

1527const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(StringRef Name) {

1528 for (const auto &E : kWidenedIntrinsics) {

1529 if (E.NarrowName == Name)

1530 return &E;

1531 }

1532 return nullptr;

1533}

1534

1535

1538 LibFunc LFunc;

1540 return nullptr;

1541

1542 if (const char *Name = KnownIntrinsic::get(LFunc))

1543 return Name;

1544

1546 return nullptr;

1547}

1548

1549

1550Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(

1551 CallBase &Call, Type *VT, Type *ExtendedVT, const TargetLibraryInfo &TLI,

1552 const ValueToShadowMap &Map, IRBuilder<> &Builder) {

1554 if (Fn == nullptr)

1555 return nullptr;

1556

1558 FunctionType *WidenedFnTy = nullptr;

1560 const auto *Widened = KnownIntrinsic::widen(Fn->getName());

1561 if (Widened) {

1562 WidenedId = Widened->ID;

1563 WidenedFnTy = Widened->MakeFnTy(Context);

1564 } else {

1565

1566

1567

1568 WidenedId = ID;

1570 }

1572

1573

1574 const auto *Widened = KnownIntrinsic::widen(Name);

1575 assert(Widened && "make sure KnownIntrinsic entries are consistent");

1576 WidenedId = Widened->ID;

1577 WidenedFnTy = Widened->MakeFnTy(Context);

1578 } else {

1579

1580 return nullptr;

1581 }

1582

1583

1591 "invalid widened intrinsic");

1592

1593

1595

1599 Type *IntrinsicArgTy = WidenedFnTy->getParamType(I);

1600 if (OrigArgTy == IntrinsicArgTy) {

1601 Args.push_back(Arg);

1602 continue;

1603 }

1604 Type *ShadowArgTy = Config.getExtendedFPType(Arg->getType());

1605 assert(ShadowArgTy &&

1606 "don't know how to get the shadow value for a non-FT");

1607 Value *Shadow = Map.getShadow(Arg);

1608 if (ShadowArgTy == IntrinsicArgTy) {

1609

1611 Args.push_back(Shadow);

1612 continue;

1613 }

1614

1616 }

1618 return WidenedFnTy->getReturnType() == ExtendedVT

1619 ? IntrinsicCall

1620 : Builder.CreateFPExt(IntrinsicCall, ExtendedVT);

1621}

1622

1623

1624

1625Value *NumericalStabilitySanitizer::handleCallBase(CallBase &Call, Type *VT,

1626 Type *ExtendedVT,

1627 const TargetLibraryInfo &TLI,

1628 const ValueToShadowMap &Map,

1630

1633

1634

1635

1636

1638 maybeHandleKnownCallBase(Call, VT, ExtendedVT, TLI, Map, Builder))

1639 return V;

1640

1641

1642

1644 Builder.CreateLoad(IntptrTy, NsanShadowRetTag, false);

1647

1649 ExtendedVT,

1650 Builder.CreateConstGEP2_64(NsanShadowRetType, NsanShadowRetPtr, 0, 0),

1651 false);

1652 Value *Shadow = Builder.CreateSelect(HasShadowRet, ShadowRetVal,

1654 ++NumInstrumentedFTCalls;

1655 return Shadow;

1656}

1657

1658

1659

1660Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(

1661 Instruction &Inst, const TargetLibraryInfo &TLI,

1662 const ValueToShadowMap &Map) {

1664 Type *ExtendedVT = Config.getExtendedFPType(VT);

1665 assert(ExtendedVT != nullptr && "trying to create a shadow for a non-FT");

1666

1668 return handleLoad(*Load, VT, ExtendedVT);

1669

1671

1675 return handleCallBase(*Call, VT, ExtendedVT, TLI, Map, Builder);

1676 }

1677

1679

1680

1681 BasicBlock *InvokeBB = Invoke->getParent();

1682 BasicBlock *NextBB = Invoke->getNormalDest();

1686

1689 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);

1692 return Shadow;

1693 }

1694

1697

1699 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);

1701 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);

1702

1704 return Builder.CreateUnOp(UnaryOp->getOpcode(),

1705 Map.getShadow(UnaryOp->getOperand(0)));

1706

1708 return Builder.CreateBinOp(BinOp->getOpcode(),

1709 Map.getShadow(BinOp->getOperand(0)),

1710 Map.getShadow(BinOp->getOperand(1)));

1711

1714 return Builder.CreateCast(Cast->getOpcode(), Cast->getOperand(0),

1715 ExtendedVT);

1716 }

1717

1719 return Builder.CreateSelect(S->getCondition(),

1720 Map.getShadow(S->getTrueValue()),

1721 Map.getShadow(S->getFalseValue()));

1722

1724 return Builder.CreateFreeze(Map.getShadow(Freeze->getOperand(0)));

1725

1728 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());

1729

1732 Map.getShadow(Insert->getOperand(1)),

1733 Insert->getOperand(2));

1734

1737 Map.getShadow(Shuffle->getOperand(1)),

1738 Shuffle->getShuffleMask());

1739

1740

1742 return Builder.CreateFPExt(Extract, ExtendedVT);

1743

1745 return Builder.CreateFPExt(BC, ExtendedVT);

1746

1749}

1750

1751

1752

1753

1754

1755void NumericalStabilitySanitizer::maybeCreateShadowValue(

1756 Instruction &Root, const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {

1758 Type *ExtendedVT = Config.getExtendedFPType(VT);

1759 if (ExtendedVT == nullptr)

1760 return;

1761

1762 if (Map.hasShadow(&Root))

1763 return;

1764

1765 assert(isa<PHINode>(Root) && "phi nodes should already have shadows");

1766

1767 std::vector<Instruction *> DfsStack(1, &Root);

1768 while (!DfsStack.empty()) {

1769

1770

1772

1773

1774 if (Map.hasShadow(I)) {

1775 DfsStack.pop_back();

1776 continue;

1777 }

1778

1779 bool MissingShadow = false;

1780 for (Value *Op : I->operands()) {

1781 Type *VT = Op->getType();

1782 if (!Config.getExtendedFPType(VT))

1783 continue;

1784 if (Map.hasShadow(Op))

1785 continue;

1786 MissingShadow = true;

1788 }

1789 if (MissingShadow)

1790 continue;

1791

1792

1793 Value *Shadow = createShadowValueWithOperandsAvailable(*I, TLI, Map);

1794 Map.setShadow(*I, *Shadow);

1795 DfsStack.pop_back();

1796 }

1797}

1798

1799

1800void NumericalStabilitySanitizer::propagateFTStore(

1801 StoreInst &Store, Type *VT, Type *ExtendedVT, const ValueToShadowMap &Map) {

1802 Value *StoredValue = Store.getValueOperand();

1805 const auto Extents = getMemoryExtentsOrDie(VT);

1807 NsanGetShadowPtrForStore[Extents.ValueType],

1808 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});

1809

1810 Value *StoredShadow = Map.getShadow(StoredValue);

1811 if (Store.getParent()->getParent()->hasOptNone()) {

1812

1813

1815 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,

1816 CheckLoc::makeStore(Store.getPointerOperand()));

1817 ++NumInstrumentedFTStores;

1818 }

1819 }

1820

1822 Store.isVolatile());

1823}

1824

1825

1826

1827

1828

1829

1830

1831

1832

1833void NumericalStabilitySanitizer::propagateNonFTStore(

1834 StoreInst &Store, Type *VT, const ValueToShadowMap &Map) {

1835 Value *PtrOp = Store.getPointerOperand();

1838 Value *Dst = PtrOp;

1839 TypeSize SlotSize = DL.getTypeStoreSize(VT);

1841 const auto LoadSizeBytes = SlotSize.getFixedValue();

1844

1845 ++NumInstrumentedNonFTStores;

1846 Value *StoredValue = Store.getValueOperand();

1848

1849

1850

1851

1852

1853 Type *ShadowTypeIntTy = Type::getIntNTy(Context, 8 * LoadSizeBytes);

1854 Type *ShadowValueIntTy =

1858 Value *LoadSrc = Load->getPointerOperand();

1859

1860

1861

1862

1863

1864 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(

1865 ShadowTypeIntTy,

1866 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}), Align(1),

1867 false);

1868 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(

1869 ShadowValueIntTy,

1870 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}), Align(1),

1871 false);

1872

1873

1875 RawShadowType, Builder.CreateCall(NsanGetRawShadowTypePtr, {Dst}),

1877 false);

1879 Builder.CreateCall(NsanGetRawShadowPtr, {Dst}),

1881 false);

1882

1883 ++NumInstrumentedNonFTMemcpyStores;

1884 return;

1885 }

1886

1889

1890

1891 Type *BitcastTy = nullptr;

1893 switch (CInt->getType()->getScalarSizeInBits()) {

1894 case 32:

1895 BitcastTy = Type::getFloatTy(Context);

1896 break;

1897 case 64:

1898 BitcastTy = Type::getDoubleTy(Context);

1899 break;

1900 case 80:

1901 BitcastTy = Type::getX86_FP80Ty(Context);

1902 break;

1903 default:

1904 break;

1905 }

1907 const int NumElements =

1908 cast(CDV->getType())->getElementCount().getFixedValue();

1909 switch (CDV->getType()->getScalarSizeInBits()) {

1910 case 32:

1911 BitcastTy =

1912 VectorType::get(Type::getFloatTy(Context), NumElements, false);

1913 break;

1914 case 64:

1915 BitcastTy =

1916 VectorType::get(Type::getDoubleTy(Context), NumElements, false);

1917 break;

1918 case 80:

1919 BitcastTy =

1920 VectorType::get(Type::getX86_FP80Ty(Context), NumElements, false);

1921 break;

1922 default:

1923 break;

1924 }

1925 }

1926 if (BitcastTy) {

1927 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);

1929 NsanGetShadowPtrForStore[Extents.ValueType],

1930 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});

1931

1932 Type *ExtVT = Config.getExtendedFPType(BitcastTy);

1936 Store.isVolatile());

1937 return;

1938 }

1939 }

1940

1941 Builder.CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});

1942}

1943

1944void NumericalStabilitySanitizer::propagateShadowValues(

1945 Instruction &Inst, const TargetLibraryInfo &TLI,

1946 const ValueToShadowMap &Map) {

1948 Value *StoredValue = Store->getValueOperand();

1950 Type *ExtendedVT = Config.getExtendedFPType(VT);

1951 if (ExtendedVT == nullptr)

1952 return propagateNonFTStore(*Store, VT, Map);

1953 return propagateFTStore(*Store, VT, ExtendedVT, Map);

1954 }

1955

1957 emitFCmpCheck(*FCmp, Map);

1958 return;

1959 }

1960

1962 maybeAddSuffixForNsanInterface(CB);

1966 instrumentMemIntrinsic(MI);

1967 return;

1968 }

1969 populateShadowStack(*CB, TLI, Map);

1970 return;

1971 }

1972

1975 return;

1976

1977 Value *RV = RetInst->getReturnValue();

1978 if (RV == nullptr)

1979 return;

1981 Type *ExtendedVT = Config.getExtendedFPType(VT);

1982 if (ExtendedVT == nullptr)

1983 return;

1984 Value *RVShadow = Map.getShadow(RV);

1986

1987 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());

1988 ++NumInstrumentedFTRets;

1989

1992 Builder.CreateStore(FnAddr, NsanShadowRetTag);

1993

1994 Value *ShadowRetValPtr =

1995 Builder.CreateConstGEP2_64(NsanShadowRetType, NsanShadowRetPtr, 0, 0);

1996 Builder.CreateStore(RVShadow, ShadowRetValPtr);

1997 return;

1998 }

1999

2002 Type *VT = V->getType();

2003 Type *ExtendedVT = Config.getExtendedFPType(VT);

2004 if (ExtendedVT == nullptr)

2005 return;

2007 emitCheck(V, Map.getShadow(V), Builder, CheckLoc::makeInsert());

2008 return;

2009 }

2010}

2011

2012

2013

2014

2016 std::vector<Instruction *> &Instructions) {

2018#define MOVE_FLAG(attr, setter) \

2019 if (F.getFnAttribute(attr).getValueAsString() == "true") { \

2020 F.removeFnAttr(attr); \

2021 FMF.set##setter(); \

2022 }

2023 MOVE_FLAG("no-infs-fp-math", NoInfs)

2024 MOVE_FLAG("no-nans-fp-math", NoNaNs)

2025 MOVE_FLAG("no-signed-zeros-fp-math", NoSignedZeros)

2026#undef MOVE_FLAG

2027

2030 I->setFastMathFlags(FMF);

2031}

2032

2033bool NumericalStabilitySanitizer::sanitizeFunction(

2034 Function &F, const TargetLibraryInfo &TLI) {

2035 if (F.hasFnAttribute(Attribute::SanitizeNumericalStability) ||

2036 F.isDeclaration())

2037 return false;

2038

2039

2040

2042 return false;

2043

2044

2045

2046

2047

2048

2049

2050

2051

2052

2053

2054

2055

2056

2057

2058

2059

2060

2061

2062

2063

2064

2065

2066

2067

2068

2069

2070

2071

2072

2073

2074

2075

2076

2077

2078

2079

2080

2081

2082

2083

2084

2085

2086

2087

2088

2089

2090

2091

2092

2093

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107

2108

2109

2110

2111

2112

2113

2114

2115

2116

2117

2118

2119

2120

2121

2122

2123

2124

2125

2126

2127

2128

2129

2130

2131

2132 std::vector<Instruction *> OriginalInstructions;

2133 for (BasicBlock &BB : F)

2134 for (Instruction &Inst : BB)

2135 OriginalInstructions.emplace_back(&Inst);

2136

2138 ValueToShadowMap ValueToShadow(Config);

2139

2140

2141

2142

2143 std::vector<PHINode *> OriginalPhis;

2144 createShadowArguments(F, TLI, ValueToShadow);

2145 for (Instruction *I : OriginalInstructions) {

2147 if (PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {

2148 OriginalPhis.push_back(Phi);

2149 ValueToShadow.setShadow(*Phi, *Shadow);

2150 }

2151 }

2152 }

2153

2154

2155 for (Instruction *I : OriginalInstructions)

2156 maybeCreateShadowValue(*I, TLI, ValueToShadow);

2157

2158

2159 for (Instruction *I : OriginalInstructions)

2160 propagateShadowValues(*I, TLI, ValueToShadow);

2161

2162

2163 for (PHINode *Phi : OriginalPhis) {

2164 PHINode *ShadowPhi = cast(ValueToShadow.getShadow(Phi));

2165 for (unsigned I : seq(Phi->getNumOperands())) {

2167 Value *Shadow = ValueToShadow.getShadow(V);

2169

2170

2171

2172

2173

2174

2175 ShadowPhi->addIncoming(Shadow, IncomingBB);

2176 }

2177 }

2178

2179 return !ValueToShadow.empty();

2180}

2181

2186 if (CInt && CInt->getValue().getBitWidth() <= 64)

2187 OpSize = CInt->getValue().getZExtValue();

2188 }

2189

2190 return OpSize;

2191}

2192

2193

2194

2195bool NumericalStabilitySanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {

2198 FunctionCallee SetUnknownFn =

2199 NsanSetUnknownFns.getFunctionFor(GetMemOpSize(M->getArgOperand(2)));

2201 Builder.CreateCall(SetUnknownFn, {M->getArgOperand(0)});

2202 else

2204 {M->getArgOperand(0),

2206 IntptrTy, false)});

2207

2209 FunctionCallee CopyFn =

2210 NsanCopyFns.getFunctionFor(GetMemOpSize(M->getArgOperand(2)));

2211

2213 Builder.CreateCall(CopyFn, {M->getArgOperand(0),

2214 M->getArgOperand(1)});

2215 else

2216 Builder.CreateCall(CopyFn, {M->getArgOperand(0),

2217 M->getArgOperand(1),

2218

2220 IntptrTy, false)});

2221 }

2222 return false;

2223}

2224

2225void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(CallBase *CI) {

2227 if (Fn == nullptr)

2228 return;

2229

2231 return;

2232

2233 if (Fn->getName() == "__nsan_dump_shadow_mem") {

2235 "invalid prototype for __nsan_dump_shadow_mem");

2236

2237

2238

2239

2240 const uint64_t shadow_value_type_ids =

2241 (static_cast<size_t>(Config.byValueType(kLongDouble).getNsanTypeId())

2242 << 16) |

2243 (static_cast<size_t>(Config.byValueType(kDouble).getNsanTypeId())

2244 << 8) |

2245 static_cast<size_t>(Config.byValueType(kFloat).getNsanTypeId());

2246 CI->setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));

2247 }

2248}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

ArrayRef< TableEntry > TableRef

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file defines the DenseMap class.

Module.h This file contains the declarations for the Module class.

Machine Check Debug Module

static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)

Definition NumericalStabilitySanitizer.cpp:645

static FunctionType * makeDoubleDouble(LLVMContext &C)

Definition NumericalStabilitySanitizer.cpp:1316

constexpr int kMaxVectorWidth

Definition NumericalStabilitySanitizer.cpp:139

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)

Definition NumericalStabilitySanitizer.cpp:792

static cl::opt< bool > ClCheckStores("nsan-check-stores", cl::init(true), cl::desc("Check floating-point stores"), cl::Hidden)

static FunctionType * makeX86FP80X86FP80(LLVMContext &C)

Definition NumericalStabilitySanitizer.cpp:1320

#define MOVE_FLAG(attr, setter)

static FunctionType * makeX86FP80X86FP80I32(LLVMContext &C)

Definition NumericalStabilitySanitizer.cpp:1330

constexpr int kMaxNumArgs

Definition NumericalStabilitySanitizer.cpp:140

constexpr int kMaxShadowTypeSizeBytes

Definition NumericalStabilitySanitizer.cpp:141

static const char * getIntrinsicFromLibfunc(Function &Fn, Type *VT, const TargetLibraryInfo &TLI)

Definition NumericalStabilitySanitizer.cpp:1536

static FunctionType * makeX86FP80X86FP80X86FP80(LLVMContext &C)

Definition NumericalStabilitySanitizer.cpp:1341

static FunctionType * makeX86FP80X86FP80X86FP80X86FP80(LLVMContext &C)

Definition NumericalStabilitySanitizer.cpp:1354

static uint64_t GetMemOpSize(Value *V)

Definition NumericalStabilitySanitizer.cpp:2182

ContinuationType

Definition NumericalStabilitySanitizer.cpp:888

@ ContinueWithShadow

Definition NumericalStabilitySanitizer.cpp:889

@ ResumeFromValue

Definition NumericalStabilitySanitizer.cpp:890

constexpr StringLiteral kNsanInitName("__nsan_init")

static FunctionType * makeDoubleDoubleDouble(LLVMContext &C)

Definition NumericalStabilitySanitizer.cpp:1336

constexpr int kShadowScale

Definition NumericalStabilitySanitizer.cpp:138

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)

Definition NumericalStabilitySanitizer.cpp:1347

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)

Definition NumericalStabilitySanitizer.cpp:1325

static void moveFastMathFlags(Function &F, std::vector< Instruction * > &Instructions)

Definition NumericalStabilitySanitizer.cpp:2015

static cl::opt< bool > ClInstrumentFCmp("nsan-instrument-fcmp", cl::init(true), cl::desc("Instrument floating-point comparisons"), cl::Hidden)

FunctionAnalysisManager FAM

ModuleAnalysisManager MAM

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

static SymbolRef::Type getType(const Symbol *Sym)

static constexpr roundingMode rmTowardZero

LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)

Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...

iterator begin()

Instruction iterator methods.

const Function * getParent() const

Return the enclosing method, or null if none.

const Instruction & back() const

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)

Split the basic block into two basic blocks at the specified instruction.

InstListType::iterator iterator

Instruction iterators...

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

bool isInlineAsm() const

Check if this call is an inline asm statement.

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

Value * getCalledOperand() const

void setArgOperand(unsigned i, Value *v)

unsigned arg_size() const

Predicate getPredicate() const

Return the predicate for this instruction.

ConstantFP - Floating Point Values [float, double].

static LLVM_ABI Constant * get(ArrayRef< Constant * > V)

This is an important base class in LLVM.

static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)

Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...

A parsed version of the target data layout string in and methods for querying it.

iterator find(const_arg_type_t< KeyT > Val)

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

bool contains(const_arg_type_t< KeyT > Val) const

Return true if the specified key is in the map, false otherwise.

This instruction compares its operands according to the predicate given to the constructor.

static bool isEquality(Predicate Pred)

This class represents an extension of floating point types.

This class represents a truncation of floating point types.

Convenience struct for specifying and reasoning about fast-math flags.

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

FunctionType * getFunctionType()

unsigned getNumParams() const

Return the number of fixed parameters this function type requires.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

FunctionType * getFunctionType() const

Returns the FunctionType for me.

Intrinsic::ID getIntrinsicID() const LLVM_READONLY

getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...

@ ExternalLinkage

Externally visible function.

Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")

Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")

Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)

Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")

LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)

Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")

BasicBlock::iterator GetInsertPoint() const

Value * CreateFreeze(Value *V, const Twine &Name="")

IntegerType * getInt32Ty()

Fetch the type representing a 32-bit integer.

Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})

void SetCurrentDebugLocation(DebugLoc L)

Set location information used by debugging information.

Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)

LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with Args, mangled using Types.

Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")

LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)

Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...

Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")

StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)

Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")

CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)

Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)

BranchInst * CreateBr(BasicBlock *Dest)

Create an unconditional 'br label X' instruction.

Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")

StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)

Value * CreateFPExt(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)

Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

LLVM_ABI void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB)

Replace specified successor OldBB to point at the provided block.

LLVM_ABI const Function * getFunction() const

Return the function this instruction belongs to.

const char * getOpcodeName() const

LLVM_ABI void insertAfter(Instruction *InsertPos)

Insert an unlinked instruction into a basic block immediately after the specified instruction.

Class to represent integer types.

This is an important class for using LLVM in a threaded context.

An instruction for reading from memory.

This is the common base class for memset/memcpy/memmove.

A Module instance is used to store all the information related to an LLVM module.

void addIncoming(Value *V, BasicBlock *BB)

Add an incoming value to the end of the PHI list.

static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...

static PointerType * getUnqual(Type *ElementType)

This constructs a pointer to an object of the specified type in the default address space (address sp...

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

An instruction for storing to memory.

A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...

StringRef - Represent a constant reference to a string, i.e.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

Analysis pass providing the TargetLibraryInfo.

Provides information about what library functions are available for the current target.

bool getLibFunc(StringRef funcName, LibFunc &F) const

Searches for a particular function name.

StringRef getName(LibFunc F) const

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

static constexpr TypeSize getFixed(ScalarTy ExactSize)

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM_ABI Type * getStructElementType(unsigned N) const

bool isVectorTy() const

True if this is an instance of VectorType.

bool isX86_FP80Ty() const

Return true if this is x86 long double.

bool isArrayTy() const

True if this is an instance of ArrayType.

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

bool isFloatTy() const

Return true if this is 'float', a 32-bit IEEE fp type.

static LLVM_ABI Type * getPPC_FP128Ty(LLVMContext &C)

static LLVM_ABI Type * getFP128Ty(LLVMContext &C)

LLVM_ABI unsigned getStructNumElements() const

LLVM_ABI uint64_t getArrayNumElements() const

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)

bool isStructTy() const

True if this is an instance of StructType.

LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY

Return the basic size of this type if it is a primitive type.

bool isDoubleTy() const

Return true if this is 'double', a 64-bit IEEE fp type.

static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)

static LLVM_ABI Type * getDoubleTy(LLVMContext &C)

static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)

static LLVM_ABI Type * getFloatTy(LLVMContext &C)

'undef' values are things that do not have specified contents.

static LLVM_ABI UndefValue * get(Type *T)

Static factory methods - Return an 'undef' object of the specified type.

Value * getOperand(unsigned i) const

unsigned getNumOperands() const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

iterator_range< user_iterator > users()

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)

This static method is the primary way to construct an VectorType.

constexpr ScalarTy getFixedValue() const

constexpr bool isScalable() const

Returns whether the quantity is scaled by a runtime quantity (vscale).

const ParentTy * getParent() const

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

constexpr char Args[]

Key for Kernel::Metadata::mArgs.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

LLVM_ABI MatchIntrinsicTypesResult matchIntrinsicSignature(FunctionType *FTy, ArrayRef< IITDescriptor > &Infos, SmallVectorImpl< Type * > &ArgTys)

Match the specified function type with the type constraints specified by the .td file.

LLVM_ABI void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl< IITDescriptor > &T)

Return the IIT table descriptor for the specified intrinsic into an array of IITDescriptors.

MatchIntrinsicTypesResult

@ MatchIntrinsicTypes_Match

initializer< Ty > init(const Ty &Val)

NodeAddr< PhiNode * > Phi

Context & getContext() const

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)

Creates sanitizer constructor function lazily.

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)

Append F to the list of global ctors of module M with the given Priority.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

PointerUnion< const Value *, const PseudoSourceValue * > ValueType

auto seq(T Begin, T End)

Iterate over an integral type from Begin up to - but not including - End.

LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)

Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Definition NumericalStabilitySanitizer.cpp:629