LLVM 24.0.0git
NumericalStabilitySanitizer.cpp
Go to the documentation of this file.
1//===-- NumericalStabilitySanitizer.cpp -----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the instrumentation pass for the numerical sanitizer.
10// Conceptually the pass injects shadow computations using higher precision
11// types and inserts consistency checks. For details see the paper
12// https://arxiv.org/abs/2102.12782.
13//
14//===----------------------------------------------------------------------===//
15
18
19#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/Statistic.h"
25#include "llvm/IR/DataLayout.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/IRBuilder.h"
29#include "llvm/IR/Intrinsics.h"
30#include "llvm/IR/LLVMContext.h"
31#include "llvm/IR/MDBuilder.h"
32#include "llvm/IR/Metadata.h"
33#include "llvm/IR/Module.h"
34#include "llvm/IR/Type.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/Regex.h"
42
43#include <cstdint>
44
45using namespace llvm;
46
47#define DEBUG_TYPE "nsan"
48
49STATISTIC(NumInstrumentedFTLoads,
50 "Number of instrumented floating-point loads");
51
52STATISTIC(NumInstrumentedFTCalls,
53 "Number of instrumented floating-point calls");
54STATISTIC(NumInstrumentedFTRets,
55 "Number of instrumented floating-point returns");
56STATISTIC(NumInstrumentedFTStores,
57 "Number of instrumented floating-point stores");
58STATISTIC(NumInstrumentedNonFTStores,
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
65constexpr StringLiteral kNsanModuleCtorName("nsan.module_ctor");
66constexpr StringLiteral kNsanInitName("__nsan_init");
67
68// The following values must be kept in sync with the runtime.
69constexpr int kShadowScale = 2;
70constexpr int kMaxVectorWidth = 8;
71constexpr int kMaxNumArgs = 128;
72constexpr int kMaxShadowTypeSizeBytes = 16; // fp128
73
74namespace {
75
76// Defines the characteristics (type id, type, and floating-point semantics)
77// attached for all possible shadow types.
78class ShadowTypeConfig {
79public:
80 static std::unique_ptr<ShadowTypeConfig> fromNsanTypeId(char TypeId);
81
82 // The LLVM Type corresponding to the shadow type.
83 virtual Type *getType(LLVMContext &Context) const = 0;
84
85 // The nsan type id of the shadow type (`d`, `l`, `q`, ...).
86 virtual char getNsanTypeId() const = 0;
87
88 virtual ~ShadowTypeConfig() = default;
89};
90
91template <char NsanTypeId>
92class ShadowTypeConfigImpl : public ShadowTypeConfig {
93public:
94 char getNsanTypeId() const override { return NsanTypeId; }
95 static constexpr char kNsanTypeId = NsanTypeId;
96};
97
98// `double` (`d`) shadow type.
99class F64ShadowConfig : public ShadowTypeConfigImpl<'d'> {
100 Type *getType(LLVMContext &Context) const override {
101 return Type::getDoubleTy(Context);
102 }
103};
104
105// `x86_fp80` (`l`) shadow type: X86 long double.
106class F80ShadowConfig : public ShadowTypeConfigImpl<'l'> {
107 Type *getType(LLVMContext &Context) const override {
108 return Type::getX86_FP80Ty(Context);
109 }
110};
111
112// `fp128` (`q`) shadow type.
113class F128ShadowConfig : public ShadowTypeConfigImpl<'q'> {
114 Type *getType(LLVMContext &Context) const override {
115 return Type::getFP128Ty(Context);
116 }
117};
118
119// `ppc_fp128` (`e`) shadow type: IBM extended double with 106 bits of mantissa.
120class PPC128ShadowConfig : public ShadowTypeConfigImpl<'e'> {
121 Type *getType(LLVMContext &Context) const override {
122 return Type::getPPC_FP128Ty(Context);
123 }
124};
125
126// Creates a ShadowTypeConfig given its type id.
127std::unique_ptr<ShadowTypeConfig>
128ShadowTypeConfig::fromNsanTypeId(const char TypeId) {
129 switch (TypeId) {
130 case F64ShadowConfig::kNsanTypeId:
131 return std::make_unique<F64ShadowConfig>();
132 case F80ShadowConfig::kNsanTypeId:
133 return std::make_unique<F80ShadowConfig>();
134 case F128ShadowConfig::kNsanTypeId:
135 return std::make_unique<F128ShadowConfig>();
136 case PPC128ShadowConfig::kNsanTypeId:
137 return std::make_unique<PPC128ShadowConfig>();
138 }
139 report_fatal_error("nsan: invalid shadow type id '" + Twine(TypeId) + "'");
140}
141
142// An enum corresponding to shadow value types. Used as indices in arrays, so
143// not an `enum class`.
144enum FTValueType { kFloat, kDouble, kLongDouble, kNumValueTypes };
145
146// If `FT` corresponds to a primitive FTValueType, return it.
147static std::optional<FTValueType> ftValueTypeFromType(Type *FT) {
148 if (FT->isFloatTy())
149 return kFloat;
150 if (FT->isDoubleTy())
151 return kDouble;
152 if (FT->isX86_FP80Ty())
153 return kLongDouble;
154 return {};
155}
156
157// Returns the LLVM type for an FTValueType.
158static Type *typeFromFTValueType(FTValueType VT, LLVMContext &Context) {
159 switch (VT) {
160 case kFloat:
161 return Type::getFloatTy(Context);
162 case kDouble:
163 return Type::getDoubleTy(Context);
164 case kLongDouble:
165 return Type::getX86_FP80Ty(Context);
166 case kNumValueTypes:
167 return nullptr;
168 }
169 llvm_unreachable("Unhandled FTValueType enum");
170}
171
172// Returns the type name for an FTValueType.
173static const char *typeNameFromFTValueType(FTValueType VT) {
174 switch (VT) {
175 case kFloat:
176 return "float";
177 case kDouble:
178 return "double";
179 case kLongDouble:
180 return "longdouble";
181 case kNumValueTypes:
182 return nullptr;
183 }
184 llvm_unreachable("Unhandled FTValueType enum");
185}
186
187// A specific mapping configuration of application type to shadow type for nsan
188// (see -nsan-shadow-mapping flag).
189class MappingConfig {
190public:
191 MappingConfig(const InstrumentationOptions &Opts, LLVMContext &C)
192 : Context(C) {
193 if (Opts.nsan_shadow_type_mapping.size() != 3)
194 report_fatal_error("Invalid nsan mapping: " +
195 Twine(Opts.nsan_shadow_type_mapping));
196 unsigned ShadowTypeSizeBits[kNumValueTypes];
197 for (int VT = 0; VT < kNumValueTypes; ++VT) {
198 auto Config =
199 ShadowTypeConfig::fromNsanTypeId(Opts.nsan_shadow_type_mapping[VT]);
200 if (!Config)
201 report_fatal_error("Failed to get ShadowTypeConfig for " +
202 Twine(Opts.nsan_shadow_type_mapping[VT]));
203 const unsigned AppTypeSize =
204 typeFromFTValueType(static_cast<FTValueType>(VT), Context)
205 ->getScalarSizeInBits();
206 const unsigned ShadowTypeSize =
207 Config->getType(Context)->getScalarSizeInBits();
208 // Check that the shadow type size is at most kShadowScale times the
209 // application type size, so that shadow memory compoutations are valid.
210 if (ShadowTypeSize > kShadowScale * AppTypeSize)
211 report_fatal_error("Invalid nsan mapping f" + Twine(AppTypeSize) +
212 "->f" + Twine(ShadowTypeSize) +
213 ": The shadow type size should be at most " +
215 " times the application type size");
216 ShadowTypeSizeBits[VT] = ShadowTypeSize;
217 Configs[VT] = std::move(Config);
218 }
219
220 // Check that the mapping is monotonous. This is required because if one
221 // does an fpextend of `float->long double` in application code, nsan is
222 // going to do an fpextend of `shadow(float) -> shadow(long double)` in
223 // shadow code. This will fail in `qql` mode, since nsan would be
224 // fpextending `f128->long`, which is invalid.
225 // TODO: Relax this.
226 if (ShadowTypeSizeBits[kFloat] > ShadowTypeSizeBits[kDouble] ||
227 ShadowTypeSizeBits[kDouble] > ShadowTypeSizeBits[kLongDouble])
228 report_fatal_error("Invalid nsan mapping: { float->f" +
229 Twine(ShadowTypeSizeBits[kFloat]) + "; double->f" +
230 Twine(ShadowTypeSizeBits[kDouble]) +
231 "; long double->f" +
232 Twine(ShadowTypeSizeBits[kLongDouble]) + " }");
233 }
234
235 const ShadowTypeConfig &byValueType(FTValueType VT) const {
236 assert(VT < FTValueType::kNumValueTypes && "invalid value type");
237 return *Configs[VT];
238 }
239
240 // Returns the extended shadow type for a given application type.
241 Type *getExtendedFPType(Type *FT) const {
242 if (const auto VT = ftValueTypeFromType(FT))
243 return Configs[*VT]->getType(Context);
244 if (FT->isVectorTy()) {
245 auto *VecTy = cast<VectorType>(FT);
246 // TODO: add support for scalable vector types.
247 if (VecTy->isScalableTy())
248 return nullptr;
249 Type *ExtendedScalar = getExtendedFPType(VecTy->getElementType());
250 return ExtendedScalar
251 ? VectorType::get(ExtendedScalar, VecTy->getElementCount())
252 : nullptr;
253 }
254 return nullptr;
255 }
256
257private:
258 LLVMContext &Context;
259 std::unique_ptr<ShadowTypeConfig> Configs[FTValueType::kNumValueTypes];
260};
261
262// The memory extents of a type specifies how many elements of a given
263// FTValueType needs to be stored when storing this type.
264struct MemoryExtents {
265 FTValueType ValueType;
266 uint64_t NumElts;
267};
268
269static MemoryExtents getMemoryExtentsOrDie(Type *FT) {
270 if (const auto VT = ftValueTypeFromType(FT))
271 return {*VT, 1};
272 if (auto *VecTy = dyn_cast<VectorType>(FT)) {
273 const auto ScalarExtents = getMemoryExtentsOrDie(VecTy->getElementType());
274 return {ScalarExtents.ValueType,
275 ScalarExtents.NumElts * VecTy->getElementCount().getFixedValue()};
276 }
277 llvm_unreachable("invalid value type");
278}
279
280// The location of a check. Passed as parameters to runtime checking functions.
281class CheckLoc {
282public:
283 // Creates a location that references an application memory location.
284 static CheckLoc makeStore(Value *Address) {
285 CheckLoc Result(kStore);
286 Result.Address = Address;
287 return Result;
288 }
289 static CheckLoc makeLoad(Value *Address) {
290 CheckLoc Result(kLoad);
291 Result.Address = Address;
292 return Result;
293 }
294
295 // Creates a location that references an argument, given by id.
296 static CheckLoc makeArg(int ArgId) {
297 CheckLoc Result(kArg);
298 Result.ArgId = ArgId;
299 return Result;
300 }
301
302 // Creates a location that references the return value of a function.
303 static CheckLoc makeRet() { return CheckLoc(kRet); }
304
305 // Creates a location that references a vector insert.
306 static CheckLoc makeInsert() { return CheckLoc(kInsert); }
307
308 // Returns the CheckType of location this refers to, as an integer-typed LLVM
309 // IR value.
310 Value *getType(LLVMContext &C) const {
311 return ConstantInt::get(Type::getInt32Ty(C), static_cast<int>(CheckTy));
312 }
313
314 // Returns a CheckType-specific value representing details of the location
315 // (e.g. application address for loads or stores), as an `IntptrTy`-typed LLVM
316 // IR value.
317 Value *getValue(Type *IntptrTy, IRBuilder<> &Builder) const {
318 switch (CheckTy) {
319 case kUnknown:
320 llvm_unreachable("unknown type");
321 case kRet:
322 case kInsert:
323 return ConstantInt::get(IntptrTy, 0);
324 case kArg:
325 return ConstantInt::get(IntptrTy, ArgId);
326 case kLoad:
327 case kStore:
328 return Builder.CreatePtrToInt(Address, IntptrTy);
329 }
330 llvm_unreachable("Unhandled CheckType enum");
331 }
332
333private:
334 // Must be kept in sync with the runtime,
335 // see compiler-rt/lib/nsan/nsan_stats.h
336 enum CheckType {
337 kUnknown = 0,
338 kRet,
339 kArg,
340 kLoad,
341 kStore,
342 kInsert,
343 };
344 explicit CheckLoc(CheckType CheckTy) : CheckTy(CheckTy) {}
345
346 Value *Address = nullptr;
347 const CheckType CheckTy;
348 int ArgId = -1;
349};
350
351// A map of LLVM IR values to shadow LLVM IR values.
352class ValueToShadowMap {
353public:
354 explicit ValueToShadowMap(const MappingConfig &Config) : Config(Config) {}
355
356 ValueToShadowMap(const ValueToShadowMap &) = delete;
357 ValueToShadowMap &operator=(const ValueToShadowMap &) = delete;
358
359 // Sets the shadow value for a value. Asserts that the value does not already
360 // have a value.
361 void setShadow(Value &V, Value &Shadow) {
362 [[maybe_unused]] const bool Inserted = Map.try_emplace(&V, &Shadow).second;
363 LLVM_DEBUG({
364 if (!Inserted) {
365 if (auto *I = dyn_cast<Instruction>(&V))
366 errs() << I->getFunction()->getName() << ": ";
367 errs() << "duplicate shadow (" << &V << "): ";
368 V.dump();
369 }
370 });
371 assert(Inserted && "duplicate shadow");
372 }
373
374 // Returns true if the value already has a shadow (including if the value is a
375 // constant). If true, calling getShadow() is valid.
376 bool hasShadow(Value *V) const { return isa<Constant>(V) || Map.contains(V); }
377
378 // Returns the shadow value for a given value. Asserts that the value has
379 // a shadow value. Lazily creates shadows for constant values.
380 Value *getShadow(Value *V) const {
381 if (Constant *C = dyn_cast<Constant>(V))
382 return getShadowConstant(C);
383 return Map.find(V)->second;
384 }
385
386 bool empty() const { return Map.empty(); }
387
388private:
389 // Extends a constant application value to its shadow counterpart.
390 APFloat extendConstantFP(APFloat CV, const fltSemantics &To) const {
391 bool LosesInfo = false;
392 CV.convert(To, APFloatBase::rmTowardZero, &LosesInfo);
393 return CV;
394 }
395
396 // Returns the shadow constant for the given application constant.
397 Constant *getShadowConstant(Constant *C) const {
399 return UndefValue::get(Config.getExtendedFPType(U->getType()));
400 }
401 if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
402 // Floating-point constants.
403 Type *Ty = Config.getExtendedFPType(CFP->getType());
404 return ConstantFP::get(
405 Ty, extendConstantFP(CFP->getValueAPF(),
406 Ty->getScalarType()->getFltSemantics()));
407 }
408 // Vector, array, or aggregate constants.
409 if (C->getType()->isVectorTy()) {
411 for (int I = 0, E = cast<VectorType>(C->getType())
412 ->getElementCount()
413 .getFixedValue();
414 I < E; ++I)
415 Elements.push_back(getShadowConstant(C->getAggregateElement(I)));
416 return ConstantVector::get(Elements);
417 }
418 llvm_unreachable("unimplemented");
419 }
420
421 const MappingConfig &Config;
423};
424
425class NsanMemOpFn {
426public:
427 NsanMemOpFn(Module &M, ArrayRef<StringRef> Sized, StringRef Fallback,
428 size_t NumArgs);
429 FunctionCallee getFunctionFor(uint64_t MemOpSize) const;
430 FunctionCallee getFallback() const;
431
432private:
434 size_t NumSizedFuncs;
435};
436
437NsanMemOpFn::NsanMemOpFn(Module &M, ArrayRef<StringRef> Sized,
438 StringRef Fallback, size_t NumArgs) {
439 LLVMContext &Ctx = M.getContext();
440 AttributeList Attr;
441 Attr = Attr.addFnAttribute(Ctx, Attribute::NoUnwind);
442 Type *PtrTy = PointerType::getUnqual(Ctx);
443 Type *VoidTy = Type::getVoidTy(Ctx);
444 IntegerType *IntptrTy = M.getDataLayout().getIntPtrType(Ctx);
445 FunctionType *SizedFnTy = nullptr;
446
447 NumSizedFuncs = Sized.size();
448
449 // First entry is fallback function
450 if (NumArgs == 3) {
451 Funcs.push_back(
452 M.getOrInsertFunction(Fallback, Attr, VoidTy, PtrTy, PtrTy, IntptrTy));
453 SizedFnTy = FunctionType::get(VoidTy, {PtrTy, PtrTy}, false);
454 } else if (NumArgs == 2) {
455 Funcs.push_back(
456 M.getOrInsertFunction(Fallback, Attr, VoidTy, PtrTy, IntptrTy));
457 SizedFnTy = FunctionType::get(VoidTy, {PtrTy}, false);
458 } else {
459 llvm_unreachable("Unexpected value of sized functions arguments");
460 }
461
462 for (size_t i = 0; i < NumSizedFuncs; ++i)
463 Funcs.push_back(M.getOrInsertFunction(Sized[i], SizedFnTy, Attr));
464}
465
466FunctionCallee NsanMemOpFn::getFunctionFor(uint64_t MemOpSize) const {
467 // Now `getFunctionFor` operates on `Funcs` of size 4 (at least) and the
468 // following code assumes that the number of functions in `Func` is sufficient
469 assert(NumSizedFuncs >= 3 && "Unexpected number of sized functions");
470
471 size_t Idx =
472 MemOpSize == 4 ? 1 : (MemOpSize == 8 ? 2 : (MemOpSize == 16 ? 3 : 0));
473
474 return Funcs[Idx];
475}
476
477FunctionCallee NsanMemOpFn::getFallback() const { return Funcs[0]; }
478
479/// Instantiating NumericalStabilitySanitizer inserts the nsan runtime library
480/// API function declarations into the module if they don't exist already.
481/// Instantiating ensures the __nsan_init function is in the list of global
482/// constructors for the module.
483class NumericalStabilitySanitizer {
484public:
485 NumericalStabilitySanitizer(const InstrumentationOptions &Opts, Module &M);
486 bool sanitizeFunction(Function &F, const TargetLibraryInfo &TLI);
487
488private:
489 bool instrumentMemIntrinsic(MemIntrinsic *MI);
490 void maybeAddSuffixForNsanInterface(CallBase *CI);
491 bool addrPointsToConstantData(Value *Addr);
492 void maybeCreateShadowValue(Instruction &Root, const TargetLibraryInfo &TLI,
493 ValueToShadowMap &Map);
494 Value *createShadowValueWithOperandsAvailable(Instruction &Inst,
495 const TargetLibraryInfo &TLI,
496 const ValueToShadowMap &Map);
497 PHINode *maybeCreateShadowPhi(PHINode &Phi, const TargetLibraryInfo &TLI);
498 void createShadowArguments(Function &F, const TargetLibraryInfo &TLI,
499 ValueToShadowMap &Map);
500
501 void populateShadowStack(CallBase &CI, const TargetLibraryInfo &TLI,
502 const ValueToShadowMap &Map);
503
504 void propagateShadowValues(Instruction &Inst, const TargetLibraryInfo &TLI,
505 const ValueToShadowMap &Map);
506 Value *emitCheck(Value *V, Value *ShadowV, IRBuilder<> &Builder,
507 CheckLoc Loc);
508 Value *emitCheckInternal(Value *V, Value *ShadowV, IRBuilder<> &Builder,
509 CheckLoc Loc);
510 void emitFCmpCheck(FCmpInst &FCmp, const ValueToShadowMap &Map);
511
512 // Value creation handlers.
513 Value *handleLoad(LoadInst &Load, Type *VT, Type *ExtendedVT);
514 Value *handleCallBase(CallBase &Call, Type *VT, Type *ExtendedVT,
515 const TargetLibraryInfo &TLI,
516 const ValueToShadowMap &Map, IRBuilder<> &Builder);
517 Value *maybeHandleKnownCallBase(CallBase &Call, Type *VT, Type *ExtendedVT,
518 const TargetLibraryInfo &TLI,
519 const ValueToShadowMap &Map,
520 IRBuilder<> &Builder);
521 Value *handleTrunc(const FPTruncInst &Trunc, Type *VT, Type *ExtendedVT,
522 const ValueToShadowMap &Map, IRBuilder<> &Builder);
523 Value *handleExt(const FPExtInst &Ext, Type *VT, Type *ExtendedVT,
524 const ValueToShadowMap &Map, IRBuilder<> &Builder);
525
526 // Value propagation handlers.
527 void propagateFTStore(StoreInst &Store, Type *VT, Type *ExtendedVT,
528 const ValueToShadowMap &Map);
529 void propagateNonFTStore(StoreInst &Store, Type *VT,
530 const ValueToShadowMap &Map);
531
532 const InstrumentationOptions &Opts;
533 const DataLayout &DL;
534 LLVMContext &Context;
535 MappingConfig Config;
536 IntegerType *IntptrTy = nullptr;
537
538 // TODO: Use std::array instead?
539 FunctionCallee NsanGetShadowPtrForStore[FTValueType::kNumValueTypes] = {};
540 FunctionCallee NsanGetShadowPtrForLoad[FTValueType::kNumValueTypes] = {};
541 FunctionCallee NsanCheckValue[FTValueType::kNumValueTypes] = {};
542 FunctionCallee NsanFCmpFail[FTValueType::kNumValueTypes] = {};
543
544 NsanMemOpFn NsanCopyFns;
545 NsanMemOpFn NsanSetUnknownFns;
546
547 FunctionCallee NsanGetRawShadowTypePtr;
548 FunctionCallee NsanGetRawShadowPtr;
549 GlobalValue *NsanShadowRetTag = nullptr;
550
551 Type *NsanShadowRetType = nullptr;
552 GlobalValue *NsanShadowRetPtr = nullptr;
553
554 GlobalValue *NsanShadowArgsTag = nullptr;
555
556 Type *NsanShadowArgsType = nullptr;
557 GlobalValue *NsanShadowArgsPtr = nullptr;
558
559 std::optional<Regex> CheckFunctionsFilter;
560};
561} // end anonymous namespace
562
563PreservedAnalyses
566 M, kNsanModuleCtorName, kNsanInitName, /*InitArgTypes=*/{},
567 /*InitArgs=*/{},
568 // This callback is invoked when the functions are created the first
569 // time. Hook them into the global ctors list in that case:
570 [&](Function *Ctor, FunctionCallee) { appendToGlobalCtors(M, Ctor, 0); });
571
572 const InstrumentationOptions &Opts = getInstrumentationOptions(M);
573 NumericalStabilitySanitizer Nsan(Opts, M);
574 auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
575 for (Function &F : M)
576 Nsan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
577
579}
580
581static GlobalValue *createThreadLocalGV(const char *Name, Module &M, Type *Ty) {
582 return M.getOrInsertGlobal(Name, Ty, [&M, Ty, Name] {
583 return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
584 nullptr, Name, nullptr,
586 });
587}
588
589NumericalStabilitySanitizer::NumericalStabilitySanitizer(
590 const InstrumentationOptions &Opts, Module &M)
591 : Opts(Opts), DL(M.getDataLayout()), Context(M.getContext()),
592 Config(Opts, Context),
593 NsanCopyFns(M, {"__nsan_copy_4", "__nsan_copy_8", "__nsan_copy_16"},
594 "__nsan_copy_values", /*NumArgs=*/3),
595 NsanSetUnknownFns(M,
596 {"__nsan_set_value_unknown_4",
597 "__nsan_set_value_unknown_8",
598 "__nsan_set_value_unknown_16"},
599 "__nsan_set_value_unknown", /*NumArgs=*/2) {
600 IntptrTy = DL.getIntPtrType(Context);
601 Type *PtrTy = PointerType::getUnqual(Context);
602 Type *Int32Ty = Type::getInt32Ty(Context);
603 Type *Int1Ty = Type::getInt1Ty(Context);
604 Type *VoidTy = Type::getVoidTy(Context);
605
606 AttributeList Attr;
607 Attr = Attr.addFnAttribute(Context, Attribute::NoUnwind);
608
609 Triple TT(M.getTargetTriple());
610 Attribute::AttrKind I32RetExtAttr =
611 TargetLibraryInfo::getExtAttrForI32Return(TT, /*Signed=*/true);
612 Attribute::AttrKind I32ArgExtAttr =
613 TargetLibraryInfo::getExtAttrForI32Param(TT, /*Signed=*/true);
614 Attribute::AttrKind BoolExtAttr =
616
617 // Initialize the runtime values (functions and global variables).
618 for (int I = 0; I < kNumValueTypes; ++I) {
619 const FTValueType VT = static_cast<FTValueType>(I);
620 const char *VTName = typeNameFromFTValueType(VT);
621 Type *VTTy = typeFromFTValueType(VT, Context);
622
623 // Load/store.
624 const std::string GetterPrefix =
625 std::string("__nsan_get_shadow_ptr_for_") + VTName;
626 NsanGetShadowPtrForStore[VT] = M.getOrInsertFunction(
627 GetterPrefix + "_store", Attr, PtrTy, PtrTy, IntptrTy);
628 NsanGetShadowPtrForLoad[VT] = M.getOrInsertFunction(
629 GetterPrefix + "_load", Attr, PtrTy, PtrTy, IntptrTy);
630
631 // Check.
632 const auto &ShadowConfig = Config.byValueType(VT);
633 Type *ShadowTy = ShadowConfig.getType(Context);
634 {
635 AttributeList AL = Attr;
636 AL = AL.maybeAddRetAttribute(Context, I32RetExtAttr);
637 AL = AL.maybeAddParamAttribute(Context, 2, I32ArgExtAttr);
638 NsanCheckValue[VT] =
639 M.getOrInsertFunction(std::string("__nsan_internal_check_") + VTName +
640 "_" + ShadowConfig.getNsanTypeId(),
641 AL, Int32Ty, VTTy, ShadowTy, Int32Ty, IntptrTy);
642 }
643
644 {
645 AttributeList AL = Attr;
646 AL = AL.maybeAddParamAttribute(Context, 4, I32ArgExtAttr);
647 AL = AL.maybeAddParamAttribute(Context, 5, BoolExtAttr);
648 AL = AL.maybeAddParamAttribute(Context, 6, BoolExtAttr);
649 NsanFCmpFail[VT] = M.getOrInsertFunction(
650 std::string("__nsan_fcmp_fail_") + VTName + "_" +
651 ShadowConfig.getNsanTypeId(),
652 AL, VoidTy, VTTy, VTTy, ShadowTy, ShadowTy, Int32Ty, Int1Ty, Int1Ty);
653 }
654 }
655
656 // TODO: Add attributes nofree, nosync, readnone, readonly,
657 NsanGetRawShadowTypePtr = M.getOrInsertFunction(
658 "__nsan_internal_get_raw_shadow_type_ptr", Attr, PtrTy, PtrTy);
659 NsanGetRawShadowPtr = M.getOrInsertFunction(
660 "__nsan_internal_get_raw_shadow_ptr", Attr, PtrTy, PtrTy);
661
662 NsanShadowRetTag = createThreadLocalGV("__nsan_shadow_ret_tag", M, IntptrTy);
663
664 NsanShadowRetType = ArrayType::get(Type::getInt8Ty(Context),
666 NsanShadowRetPtr =
667 createThreadLocalGV("__nsan_shadow_ret_ptr", M, NsanShadowRetType);
668
669 NsanShadowArgsTag =
670 createThreadLocalGV("__nsan_shadow_args_tag", M, IntptrTy);
671
672 NsanShadowArgsType =
675
676 NsanShadowArgsPtr =
677 createThreadLocalGV("__nsan_shadow_args_ptr", M, NsanShadowArgsType);
678
679 if (!Opts.check_functions_filter.empty()) {
680 Regex R = Regex(Opts.check_functions_filter);
681 std::string RegexError;
682 assert(R.isValid(RegexError));
683 CheckFunctionsFilter = std::move(R);
684 }
685}
686
687// Returns true if the given LLVM Value points to constant data (typically, a
688// global variable reference).
689bool NumericalStabilitySanitizer::addrPointsToConstantData(Value *Addr) {
690 // If this is a GEP, just analyze its pointer operand.
691 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Addr))
692 Addr = GEP->getPointerOperand();
693
694 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr))
695 return GV->isConstant();
696 return false;
697}
698
699// This instruments the function entry to create shadow arguments.
700// Pseudocode:
701// if (this_fn_ptr == __nsan_shadow_args_tag) {
702// s(arg0) = LOAD<sizeof(arg0)>(__nsan_shadow_args);
703// s(arg1) = LOAD<sizeof(arg1)>(__nsan_shadow_args + sizeof(arg0));
704// ...
705// __nsan_shadow_args_tag = 0;
706// } else {
707// s(arg0) = fext(arg0);
708// s(arg1) = fext(arg1);
709// ...
710// }
711void NumericalStabilitySanitizer::createShadowArguments(
712 Function &F, const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
713 assert(!F.getIntrinsicID() && "found a definition of an intrinsic");
714
715 // Do not bother if there are no FP args.
716 if (all_of(F.args(), [this](const Argument &Arg) {
717 return Config.getExtendedFPType(Arg.getType()) == nullptr;
718 }))
719 return;
720
721 IRBuilder<> Builder(F.getEntryBlock().getFirstNonPHIIt());
722 // The function has shadow args if the shadow args tag matches the function
723 // address.
724 Value *HasShadowArgs = Builder.CreateICmpEQ(
725 Builder.CreateLoad(IntptrTy, NsanShadowArgsTag, /*isVolatile=*/false),
726 Builder.CreatePtrToInt(&F, IntptrTy));
727
728 unsigned ShadowArgsOffsetBytes = 0;
729 for (Argument &Arg : F.args()) {
730 Type *VT = Arg.getType();
731 Type *ExtendedVT = Config.getExtendedFPType(VT);
732 if (ExtendedVT == nullptr)
733 continue; // Not an FT value.
734 Value *L = Builder.CreateAlignedLoad(
735 ExtendedVT,
736 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
737 ShadowArgsOffsetBytes),
738 Align(1), /*isVolatile=*/false);
739 Value *Shadow = Builder.CreateSelect(HasShadowArgs, L,
740 Builder.CreateFPExt(&Arg, ExtendedVT));
741 Map.setShadow(Arg, *Shadow);
742 TypeSize SlotSize = DL.getTypeStoreSize(ExtendedVT);
743 assert(!SlotSize.isScalable() && "unsupported");
744 ShadowArgsOffsetBytes += SlotSize;
745 }
746 Builder.CreateStore(ConstantInt::get(IntptrTy, 0), NsanShadowArgsTag);
747}
748
749// Returns true if the instrumentation should emit code to check arguments
750// before a function call.
751static bool shouldCheckArgs(CallBase &CI, const TargetLibraryInfo &TLI,
752 const std::optional<Regex> &CheckFunctionsFilter) {
753
754 Function *Fn = CI.getCalledFunction();
755
756 if (CheckFunctionsFilter) {
757 // Skip checking args of indirect calls.
758 if (Fn == nullptr)
759 return false;
760 if (CheckFunctionsFilter->match(Fn->getName()))
761 return true;
762 return false;
763 }
764
765 if (Fn == nullptr)
766 return true; // Always check args of indirect calls.
767
768 // Never check nsan functions, the user called them for a reason.
769 if (Fn->getName().starts_with("__nsan_"))
770 return false;
771
772 const auto ID = Fn->getIntrinsicID();
773 LibFunc LFunc = TLI.getLibFunc(*Fn);
774 // Always check args of unknown functions.
775 if (ID == Intrinsic::ID() && LFunc == NotLibFunc)
776 return true;
777
778 // Do not check args of an `fabs` call that is used for a comparison.
779 // This is typically used for `fabs(a-b) < tolerance`, where what matters is
780 // the result of the comparison, which is already caught be the fcmp checks.
781 if (ID == Intrinsic::fabs || LFunc == LibFunc_fabsf ||
782 LFunc == LibFunc_fabs || LFunc == LibFunc_fabsl)
783 for (const auto &U : CI.users())
784 if (isa<CmpInst>(U))
785 return false;
786
787 return true; // Default is check.
788}
789
790// Populates the shadow call stack (which contains shadow values for every
791// floating-point parameter to the function).
792void NumericalStabilitySanitizer::populateShadowStack(
793 CallBase &CI, const TargetLibraryInfo &TLI, const ValueToShadowMap &Map) {
794 // Do not create a shadow stack for inline asm.
795 if (CI.isInlineAsm())
796 return;
797
798 // Do not bother if there are no FP args.
799 if (all_of(CI.operands(), [this](const Value *Arg) {
800 return Config.getExtendedFPType(Arg->getType()) == nullptr;
801 }))
802 return;
803
804 IRBuilder<> Builder(&CI);
805 SmallVector<Value *, 8> ArgShadows;
806 const bool ShouldCheckArgs = shouldCheckArgs(CI, TLI, CheckFunctionsFilter);
807 for (auto [ArgIdx, Arg] : enumerate(CI.operands())) {
808 if (Config.getExtendedFPType(Arg->getType()) == nullptr)
809 continue; // Not an FT value.
810 Value *ArgShadow = Map.getShadow(Arg);
811 ArgShadows.push_back(ShouldCheckArgs ? emitCheck(Arg, ArgShadow, Builder,
812 CheckLoc::makeArg(ArgIdx))
813 : ArgShadow);
814 }
815
816 // Do not create shadow stacks for intrinsics/known lib funcs.
817 if (Function *Fn = CI.getCalledFunction()) {
818 if (Fn->isIntrinsic() || TLI.getLibFunc(*Fn) != NotLibFunc)
819 return;
820 }
821
822 // Set the shadow stack tag.
823 Builder.CreateStore(CI.getCalledOperand(), NsanShadowArgsTag);
824 TypeSize ShadowArgsOffsetBytes = TypeSize::getFixed(0);
825
826 unsigned ShadowArgId = 0;
827 for (const Value *Arg : CI.operands()) {
828 Type *VT = Arg->getType();
829 Type *ExtendedVT = Config.getExtendedFPType(VT);
830 if (ExtendedVT == nullptr)
831 continue; // Not an FT value.
832 Builder.CreateAlignedStore(
833 ArgShadows[ShadowArgId++],
834 Builder.CreateConstGEP2_64(NsanShadowArgsType, NsanShadowArgsPtr, 0,
835 ShadowArgsOffsetBytes),
836 Align(1), /*isVolatile=*/false);
837 TypeSize SlotSize = DL.getTypeStoreSize(ExtendedVT);
838 assert(!SlotSize.isScalable() && "unsupported");
839 ShadowArgsOffsetBytes += SlotSize;
840 }
841}
842
843// Internal part of emitCheck(). Returns a value that indicates whether
844// computation should continue with the shadow or resume by re-fextending the
845// value.
846enum class ContinuationType { // Keep in sync with runtime.
849};
850
851Value *NumericalStabilitySanitizer::emitCheckInternal(Value *V, Value *ShadowV,
852 IRBuilder<> &Builder,
853 CheckLoc Loc) {
854 // Do not emit checks for constant values, this is redundant.
855 if (isa<Constant>(V))
856 return ConstantInt::get(
857 Builder.getInt32Ty(),
858 static_cast<int>(ContinuationType::ContinueWithShadow));
859
860 Type *Ty = V->getType();
861 if (const auto VT = ftValueTypeFromType(Ty))
862 return Builder.CreateCall(
863 NsanCheckValue[*VT],
864 {V, ShadowV, Loc.getType(Context), Loc.getValue(IntptrTy, Builder)});
865
866 if (Ty->isVectorTy()) {
867 auto *VecTy = cast<VectorType>(Ty);
868 // We currently skip scalable vector types in MappingConfig,
869 // thus we should not encounter any such types here.
870 assert(!VecTy->isScalableTy() &&
871 "Scalable vector types are not supported yet");
872 Value *CheckResult = nullptr;
873 for (int I = 0, E = VecTy->getElementCount().getFixedValue(); I < E; ++I) {
874 // We resume if any element resumes. Another option would be to create a
875 // vector shuffle with the array of ContinueWithShadow, but that is too
876 // complex.
877 Value *ExtractV = Builder.CreateExtractElement(V, I);
878 Value *ExtractShadowV = Builder.CreateExtractElement(ShadowV, I);
879 Value *ComponentCheckResult =
880 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
881 CheckResult = CheckResult
882 ? Builder.CreateOr(CheckResult, ComponentCheckResult)
883 : ComponentCheckResult;
884 }
885 return CheckResult;
886 }
887 if (Ty->isArrayTy()) {
888 Value *CheckResult = nullptr;
889 for (auto I : seq(Ty->getArrayNumElements())) {
890 Value *ExtractV = Builder.CreateExtractElement(V, I);
891 Value *ExtractShadowV = Builder.CreateExtractElement(ShadowV, I);
892 Value *ComponentCheckResult =
893 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
894 CheckResult = CheckResult
895 ? Builder.CreateOr(CheckResult, ComponentCheckResult)
896 : ComponentCheckResult;
897 }
898 return CheckResult;
899 }
900 if (Ty->isStructTy()) {
901 Value *CheckResult = nullptr;
902 for (auto I : seq(Ty->getStructNumElements())) {
903 if (Config.getExtendedFPType(Ty->getStructElementType(I)) == nullptr)
904 continue; // Only check FT values.
905 Value *ExtractV = Builder.CreateExtractValue(V, I);
906 Value *ExtractShadowV = Builder.CreateExtractElement(ShadowV, I);
907 Value *ComponentCheckResult =
908 emitCheckInternal(ExtractV, ExtractShadowV, Builder, Loc);
909 CheckResult = CheckResult
910 ? Builder.CreateOr(CheckResult, ComponentCheckResult)
911 : ComponentCheckResult;
912 }
913 if (!CheckResult)
914 return ConstantInt::get(
915 Builder.getInt32Ty(),
916 static_cast<int>(ContinuationType::ContinueWithShadow));
917 return CheckResult;
918 }
919
920 llvm_unreachable("not implemented");
921}
922
923// Inserts a runtime check of V against its shadow value ShadowV.
924// We check values whenever they escape: on return, call, stores, and
925// insertvalue.
926// Returns the shadow value that should be used to continue the computations,
927// depending on the answer from the runtime.
928// TODO: Should we check on select ? phi ?
929Value *NumericalStabilitySanitizer::emitCheck(Value *V, Value *ShadowV,
930 IRBuilder<> &Builder,
931 CheckLoc Loc) {
932 // Do not emit checks for constant values, this is redundant.
933 if (isa<Constant>(V))
934 return ShadowV;
935
936 if (Instruction *Inst = dyn_cast<Instruction>(V)) {
937 Function *F = Inst->getFunction();
938 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(F->getName())) {
939 return ShadowV;
940 }
941 }
942
943 Value *CheckResult = emitCheckInternal(V, ShadowV, Builder, Loc);
944 Value *ICmpEQ = Builder.CreateICmpEQ(
945 CheckResult,
946 ConstantInt::get(Builder.getInt32Ty(),
947 static_cast<int>(ContinuationType::ResumeFromValue)));
948 return Builder.CreateSelect(
949 ICmpEQ, Builder.CreateFPExt(V, Config.getExtendedFPType(V->getType())),
950 ShadowV);
951}
952
953// Inserts a check that fcmp on shadow values are consistent with that on base
954// values.
955void NumericalStabilitySanitizer::emitFCmpCheck(FCmpInst &FCmp,
956 const ValueToShadowMap &Map) {
957 if (!Opts.nsan_instrument_fcmp)
958 return;
959
960 Function *F = FCmp.getFunction();
961 if (CheckFunctionsFilter && !CheckFunctionsFilter->match(F->getName()))
962 return;
963
964 Value *LHS = FCmp.getOperand(0);
965 if (Config.getExtendedFPType(LHS->getType()) == nullptr)
966 return;
967 Value *RHS = FCmp.getOperand(1);
968
969 // Split the basic block. On mismatch, we'll jump to the new basic block with
970 // a call to the runtime for error reporting.
971 BasicBlock *FCmpBB = FCmp.getParent();
972 BasicBlock *NextBB = FCmpBB->splitBasicBlock(FCmp.getNextNode());
973 // Remove the newly created terminator unconditional branch.
974 FCmpBB->back().eraseFromParent();
975 BasicBlock *FailBB =
976 BasicBlock::Create(Context, "", FCmpBB->getParent(), NextBB);
977
978 // Create the shadow fcmp and comparison between the fcmps.
979 IRBuilder<> FCmpBuilder(FCmpBB);
980 FCmpBuilder.SetCurrentDebugLocation(FCmp.getDebugLoc());
981 Value *ShadowLHS = Map.getShadow(LHS);
982 Value *ShadowRHS = Map.getShadow(RHS);
983 // See the help text of -nsan-truncate-fcmp-eq.
984 if (FCmp.isEquality() && Opts.nsan_truncate_fcmp_eq) {
985 Type *Ty = ShadowLHS->getType();
986 ShadowLHS = FCmpBuilder.CreateFPExt(
987 FCmpBuilder.CreateFPTrunc(ShadowLHS, LHS->getType()), Ty);
988 ShadowRHS = FCmpBuilder.CreateFPExt(
989 FCmpBuilder.CreateFPTrunc(ShadowRHS, RHS->getType()), Ty);
990 }
991 Value *ShadowFCmp =
992 FCmpBuilder.CreateFCmp(FCmp.getPredicate(), ShadowLHS, ShadowRHS);
993 Value *OriginalAndShadowFcmpMatch =
994 FCmpBuilder.CreateICmpEQ(&FCmp, ShadowFCmp);
995
996 if (OriginalAndShadowFcmpMatch->getType()->isVectorTy()) {
997 // If we have a vector type, `OriginalAndShadowFcmpMatch` is a vector of i1,
998 // where an element is true if the corresponding elements in original and
999 // shadow are the same. We want all elements to be 1.
1000 OriginalAndShadowFcmpMatch =
1001 FCmpBuilder.CreateAndReduce(OriginalAndShadowFcmpMatch);
1002 }
1003
1004 // Use MDBuilder(*C).createLikelyBranchWeights() because "match" is the common
1005 // case.
1006 FCmpBuilder.CreateCondBr(OriginalAndShadowFcmpMatch, NextBB, FailBB,
1007 MDBuilder(Context).createLikelyBranchWeights());
1008
1009 // Fill in FailBB.
1010 IRBuilder<> FailBuilder(FailBB);
1011 FailBuilder.SetCurrentDebugLocation(FCmp.getDebugLoc());
1012
1013 const auto EmitFailCall = [this, &FCmp, &FCmpBuilder,
1014 &FailBuilder](Value *L, Value *R, Value *ShadowL,
1015 Value *ShadowR, Value *Result,
1016 Value *ShadowResult) {
1017 Type *FT = L->getType();
1018 FunctionCallee *Callee = nullptr;
1019 if (FT->isFloatTy()) {
1020 Callee = &(NsanFCmpFail[kFloat]);
1021 } else if (FT->isDoubleTy()) {
1022 Callee = &(NsanFCmpFail[kDouble]);
1023 } else if (FT->isX86_FP80Ty()) {
1024 // TODO: make NsanFCmpFailLongDouble work.
1025 Callee = &(NsanFCmpFail[kDouble]);
1026 L = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(Context));
1027 R = FailBuilder.CreateFPTrunc(L, Type::getDoubleTy(Context));
1028 } else {
1029 llvm_unreachable("not implemented");
1030 }
1031 FailBuilder.CreateCall(*Callee, {L, R, ShadowL, ShadowR,
1032 ConstantInt::get(FCmpBuilder.getInt32Ty(),
1033 FCmp.getPredicate()),
1034 Result, ShadowResult});
1035 };
1036 if (LHS->getType()->isVectorTy()) {
1037 for (int I = 0, E = cast<VectorType>(LHS->getType())
1038 ->getElementCount()
1039 .getFixedValue();
1040 I < E; ++I) {
1041 Value *ExtractLHS = FailBuilder.CreateExtractElement(LHS, I);
1042 Value *ExtractRHS = FailBuilder.CreateExtractElement(RHS, I);
1043 Value *ExtractShaodwLHS = FailBuilder.CreateExtractElement(ShadowLHS, I);
1044 Value *ExtractShaodwRHS = FailBuilder.CreateExtractElement(ShadowRHS, I);
1045 Value *ExtractFCmp = FailBuilder.CreateExtractElement(&FCmp, I);
1046 Value *ExtractShadowFCmp =
1047 FailBuilder.CreateExtractElement(ShadowFCmp, I);
1048 EmitFailCall(ExtractLHS, ExtractRHS, ExtractShaodwLHS, ExtractShaodwRHS,
1049 ExtractFCmp, ExtractShadowFCmp);
1050 }
1051 } else {
1052 EmitFailCall(LHS, RHS, ShadowLHS, ShadowRHS, &FCmp, ShadowFCmp);
1053 }
1054 FailBuilder.CreateBr(NextBB);
1055
1056 ++NumInstrumentedFCmp;
1057}
1058
1059// Creates a shadow phi value for any phi that defines a value of FT type.
1060PHINode *NumericalStabilitySanitizer::maybeCreateShadowPhi(
1061 PHINode &Phi, const TargetLibraryInfo &TLI) {
1062 Type *VT = Phi.getType();
1063 Type *ExtendedVT = Config.getExtendedFPType(VT);
1064 if (ExtendedVT == nullptr)
1065 return nullptr; // Not an FT value.
1066 // The phi operands are shadow values and are not available when the phi is
1067 // created. They will be populated in a final phase, once all shadow values
1068 // have been created.
1069 PHINode *Shadow = PHINode::Create(ExtendedVT, Phi.getNumIncomingValues());
1070 Shadow->insertAfter(Phi.getIterator());
1071 return Shadow;
1072}
1073
1074Value *NumericalStabilitySanitizer::handleLoad(LoadInst &Load, Type *VT,
1075 Type *ExtendedVT) {
1076 IRBuilder<> Builder(Load.getNextNode());
1077 Builder.SetCurrentDebugLocation(Load.getDebugLoc());
1078 if (addrPointsToConstantData(Load.getPointerOperand())) {
1079 // No need to look into the shadow memory, the value is a constant. Just
1080 // convert from FT to 2FT.
1081 return Builder.CreateFPExt(&Load, ExtendedVT);
1082 }
1083
1084 // if (%shadowptr == &)
1085 // %shadow = fpext %v
1086 // else
1087 // %shadow = load (ptrcast %shadow_ptr))
1088 // Considered options here:
1089 // - Have `NsanGetShadowPtrForLoad` return a fixed address
1090 // &__nsan_unknown_value_shadow_address that is valid to load from, and
1091 // use a select. This has the advantage that the generated IR is simpler.
1092 // - Have `NsanGetShadowPtrForLoad` return nullptr. Because `select` does
1093 // not short-circuit, dereferencing the returned pointer is no longer an
1094 // option, have to split and create a separate basic block. This has the
1095 // advantage of being easier to debug because it crashes if we ever mess
1096 // up.
1097
1098 const auto Extents = getMemoryExtentsOrDie(VT);
1099 Value *ShadowPtr = Builder.CreateCall(
1100 NsanGetShadowPtrForLoad[Extents.ValueType],
1101 {Load.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1102 ++NumInstrumentedFTLoads;
1103
1104 // Split the basic block.
1105 BasicBlock *LoadBB = Load.getParent();
1106 BasicBlock *NextBB = LoadBB->splitBasicBlock(Builder.GetInsertPoint());
1107 // Create the two options for creating the shadow value.
1108 BasicBlock *ShadowLoadBB =
1109 BasicBlock::Create(Context, "", LoadBB->getParent(), NextBB);
1110 BasicBlock *FExtBB =
1111 BasicBlock::Create(Context, "", LoadBB->getParent(), NextBB);
1112
1113 // Replace the newly created terminator unconditional branch by a conditional
1114 // branch to one of the options.
1115 {
1116 LoadBB->back().eraseFromParent();
1117 IRBuilder<> LoadBBBuilder(LoadBB); // The old builder has been invalidated.
1118 LoadBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1119 LoadBBBuilder.CreateCondBr(LoadBBBuilder.CreateIsNull(ShadowPtr), FExtBB,
1120 ShadowLoadBB);
1121 }
1122
1123 // Fill in ShadowLoadBB.
1124 IRBuilder<> ShadowLoadBBBuilder(ShadowLoadBB);
1125 ShadowLoadBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1126 Value *ShadowLoad = ShadowLoadBBBuilder.CreateAlignedLoad(
1127 ExtendedVT, ShadowPtr, Align(1), Load.isVolatile());
1128 if (Opts.nsan_check_loads) {
1129 ShadowLoad = emitCheck(&Load, ShadowLoad, ShadowLoadBBBuilder,
1130 CheckLoc::makeLoad(Load.getPointerOperand()));
1131 }
1132 ShadowLoadBBBuilder.CreateBr(NextBB);
1133
1134 // Fill in FExtBB.
1135 IRBuilder<> FExtBBBuilder(FExtBB);
1136 FExtBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1137 Value *FExt = FExtBBBuilder.CreateFPExt(&Load, ExtendedVT);
1138 FExtBBBuilder.CreateBr(NextBB);
1139
1140 // The shadow value come from any of the options.
1141 IRBuilder<> NextBBBuilder(&*NextBB->begin());
1142 NextBBBuilder.SetCurrentDebugLocation(Load.getDebugLoc());
1143 PHINode *ShadowPhi = NextBBBuilder.CreatePHI(ExtendedVT, 2);
1144 ShadowPhi->addIncoming(ShadowLoad, ShadowLoadBB);
1145 ShadowPhi->addIncoming(FExt, FExtBB);
1146 return ShadowPhi;
1147}
1148
1149Value *NumericalStabilitySanitizer::handleTrunc(const FPTruncInst &Trunc,
1150 Type *VT, Type *ExtendedVT,
1151 const ValueToShadowMap &Map,
1152 IRBuilder<> &Builder) {
1153 Value *OrigSource = Trunc.getOperand(0);
1154 Type *OrigSourceTy = OrigSource->getType();
1155 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1156
1157 // When truncating:
1158 // - (A) If the source has a shadow, we truncate from the shadow, else we
1159 // truncate from the original source.
1160 // - (B) If the shadow of the source is larger than the shadow of the dest,
1161 // we still need a truncate. Else, the shadow of the source is the same
1162 // type as the shadow of the dest (because mappings are non-decreasing), so
1163 // we don't need to emit a truncate.
1164 // Examples,
1165 // with a mapping of {f32->f64;f64->f80;f80->f128}
1166 // fptrunc double %1 to float -> fptrunc x86_fp80 s(%1) to double
1167 // fptrunc x86_fp80 %1 to float -> fptrunc fp128 s(%1) to double
1168 // fptrunc fp128 %1 to float -> fptrunc fp128 %1 to double
1169 // fptrunc x86_fp80 %1 to double -> x86_fp80 s(%1)
1170 // fptrunc fp128 %1 to double -> fptrunc fp128 %1 to x86_fp80
1171 // fptrunc fp128 %1 to x86_fp80 -> fp128 %1
1172 // with a mapping of {f32->f64;f64->f128;f80->f128}
1173 // fptrunc double %1 to float -> fptrunc fp128 s(%1) to double
1174 // fptrunc x86_fp80 %1 to float -> fptrunc fp128 s(%1) to double
1175 // fptrunc fp128 %1 to float -> fptrunc fp128 %1 to double
1176 // fptrunc x86_fp80 %1 to double -> fp128 %1
1177 // fptrunc fp128 %1 to double -> fp128 %1
1178 // fptrunc fp128 %1 to x86_fp80 -> fp128 %1
1179 // with a mapping of {f32->f32;f64->f32;f80->f64}
1180 // fptrunc double %1 to float -> float s(%1)
1181 // fptrunc x86_fp80 %1 to float -> fptrunc double s(%1) to float
1182 // fptrunc fp128 %1 to float -> fptrunc fp128 %1 to float
1183 // fptrunc x86_fp80 %1 to double -> fptrunc double s(%1) to float
1184 // fptrunc fp128 %1 to double -> fptrunc fp128 %1 to float
1185 // fptrunc fp128 %1 to x86_fp80 -> fptrunc fp128 %1 to double
1186
1187 // See (A) above.
1188 Value *Source = ExtendedSourceTy ? Map.getShadow(OrigSource) : OrigSource;
1189 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1190 // See (B) above.
1191 if (SourceTy == ExtendedVT)
1192 return Source;
1193
1194 return Builder.CreateFPTrunc(Source, ExtendedVT);
1195}
1196
1197Value *NumericalStabilitySanitizer::handleExt(const FPExtInst &Ext, Type *VT,
1198 Type *ExtendedVT,
1199 const ValueToShadowMap &Map,
1200 IRBuilder<> &Builder) {
1201 Value *OrigSource = Ext.getOperand(0);
1202 Type *OrigSourceTy = OrigSource->getType();
1203 Type *ExtendedSourceTy = Config.getExtendedFPType(OrigSourceTy);
1204 // When extending:
1205 // - (A) If the source has a shadow, we extend from the shadow, else we
1206 // extend from the original source.
1207 // - (B) If the shadow of the dest is larger than the shadow of the source,
1208 // we still need an extend. Else, the shadow of the source is the same
1209 // type as the shadow of the dest (because mappings are non-decreasing), so
1210 // we don't need to emit an extend.
1211 // Examples,
1212 // with a mapping of {f32->f64;f64->f80;f80->f128}
1213 // fpext half %1 to float -> fpext half %1 to double
1214 // fpext half %1 to double -> fpext half %1 to x86_fp80
1215 // fpext half %1 to x86_fp80 -> fpext half %1 to fp128
1216 // fpext float %1 to double -> double s(%1)
1217 // fpext float %1 to x86_fp80 -> fpext double s(%1) to fp128
1218 // fpext double %1 to x86_fp80 -> fpext x86_fp80 s(%1) to fp128
1219 // with a mapping of {f32->f64;f64->f128;f80->f128}
1220 // fpext half %1 to float -> fpext half %1 to double
1221 // fpext half %1 to double -> fpext half %1 to fp128
1222 // fpext half %1 to x86_fp80 -> fpext half %1 to fp128
1223 // fpext float %1 to double -> fpext double s(%1) to fp128
1224 // fpext float %1 to x86_fp80 -> fpext double s(%1) to fp128
1225 // fpext double %1 to x86_fp80 -> fp128 s(%1)
1226 // with a mapping of {f32->f32;f64->f32;f80->f64}
1227 // fpext half %1 to float -> fpext half %1 to float
1228 // fpext half %1 to double -> fpext half %1 to float
1229 // fpext half %1 to x86_fp80 -> fpext half %1 to double
1230 // fpext float %1 to double -> s(%1)
1231 // fpext float %1 to x86_fp80 -> fpext float s(%1) to double
1232 // fpext double %1 to x86_fp80 -> fpext float s(%1) to double
1233
1234 // See (A) above.
1235 Value *Source = ExtendedSourceTy ? Map.getShadow(OrigSource) : OrigSource;
1236 Type *SourceTy = ExtendedSourceTy ? ExtendedSourceTy : OrigSourceTy;
1237 // See (B) above.
1238 if (SourceTy == ExtendedVT)
1239 return Source;
1240
1241 return Builder.CreateFPExt(Source, ExtendedVT);
1242}
1243
1244namespace {
1245// TODO: This should be tablegen-ed.
1246struct KnownIntrinsic {
1247 struct WidenedIntrinsic {
1248 const char *NarrowName;
1249 Intrinsic::ID ID; // wide id.
1250 using FnTypeFactory = FunctionType *(*)(LLVMContext &);
1251 FnTypeFactory MakeFnTy;
1252 };
1253
1254 static const char *get(LibFunc LFunc);
1255
1256 // Given an intrinsic with an `FT` argument, try to find a wider intrinsic
1257 // that applies the same operation on the shadow argument.
1258 // Options are:
1259 // - pass in the ID and full function type,
1260 // - pass in the name, which includes the function type through mangling.
1261 static const WidenedIntrinsic *widen(StringRef Name);
1262
1263private:
1264 struct LFEntry {
1265 LibFunc LFunc;
1266 const char *IntrinsicName;
1267 };
1268 static const LFEntry kLibfuncIntrinsics[];
1269
1270 static const WidenedIntrinsic kWidenedIntrinsics[];
1271};
1272} // namespace
1273
1277
1282
1287
1293
1298
1304
1311
1318
1319const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = {
1320 // TODO: Right now we ignore vector intrinsics.
1321 // This is hard because we have to model the semantics of the intrinsics,
1322 // e.g. llvm.x86.sse2.min.sd means extract first element, min, insert back.
1323 // Intrinsics that take any non-vector FT types:
1324 // NOTE: Right now because of
1325 // https://github.com/llvm/llvm-project/issues/44744
1326 // for f128 we need to use makeX86FP80X86FP80 (go to a lower precision and
1327 // come back).
1328 {"llvm.sqrt.f32", Intrinsic::sqrt, makeDoubleDouble},
1329 {"llvm.sqrt.f64", Intrinsic::sqrt, makeX86FP80X86FP80},
1330 {"llvm.sqrt.f80", Intrinsic::sqrt, makeX86FP80X86FP80},
1331 {"llvm.powi.f32", Intrinsic::powi, makeDoubleDoubleI32},
1332 {"llvm.powi.f64", Intrinsic::powi, makeX86FP80X86FP80I32},
1333 {"llvm.powi.f80", Intrinsic::powi, makeX86FP80X86FP80I32},
1334 {"llvm.sin.f32", Intrinsic::sin, makeDoubleDouble},
1335 {"llvm.sin.f64", Intrinsic::sin, makeX86FP80X86FP80},
1336 {"llvm.sin.f80", Intrinsic::sin, makeX86FP80X86FP80},
1337 {"llvm.cos.f32", Intrinsic::cos, makeDoubleDouble},
1338 {"llvm.cos.f64", Intrinsic::cos, makeX86FP80X86FP80},
1339 {"llvm.cos.f80", Intrinsic::cos, makeX86FP80X86FP80},
1340 {"llvm.pow.f32", Intrinsic::pow, makeDoubleDoubleDouble},
1341 {"llvm.pow.f64", Intrinsic::pow, makeX86FP80X86FP80X86FP80},
1342 {"llvm.pow.f80", Intrinsic::pow, makeX86FP80X86FP80X86FP80},
1343 {"llvm.exp.f32", Intrinsic::exp, makeDoubleDouble},
1344 {"llvm.exp.f64", Intrinsic::exp, makeX86FP80X86FP80},
1345 {"llvm.exp.f80", Intrinsic::exp, makeX86FP80X86FP80},
1346 {"llvm.exp2.f32", Intrinsic::exp2, makeDoubleDouble},
1347 {"llvm.exp2.f64", Intrinsic::exp2, makeX86FP80X86FP80},
1348 {"llvm.exp2.f80", Intrinsic::exp2, makeX86FP80X86FP80},
1349 {"llvm.log.f32", Intrinsic::log, makeDoubleDouble},
1350 {"llvm.log.f64", Intrinsic::log, makeX86FP80X86FP80},
1351 {"llvm.log.f80", Intrinsic::log, makeX86FP80X86FP80},
1352 {"llvm.log10.f32", Intrinsic::log10, makeDoubleDouble},
1353 {"llvm.log10.f64", Intrinsic::log10, makeX86FP80X86FP80},
1354 {"llvm.log10.f80", Intrinsic::log10, makeX86FP80X86FP80},
1355 {"llvm.log2.f32", Intrinsic::log2, makeDoubleDouble},
1356 {"llvm.log2.f64", Intrinsic::log2, makeX86FP80X86FP80},
1357 {"llvm.log2.f80", Intrinsic::log2, makeX86FP80X86FP80},
1358 {"llvm.fma.f32", Intrinsic::fma, makeDoubleDoubleDoubleDouble},
1359 {"llvm.fma.f64", Intrinsic::fma, makeX86FP80X86FP80X86FP80X86FP80},
1360 {"llvm.fma.f80", Intrinsic::fma, makeX86FP80X86FP80X86FP80X86FP80},
1361 {"llvm.fmuladd.f32", Intrinsic::fmuladd, makeDoubleDoubleDoubleDouble},
1362 {"llvm.fmuladd.f64", Intrinsic::fmuladd, makeX86FP80X86FP80X86FP80X86FP80},
1363 {"llvm.fmuladd.f80", Intrinsic::fmuladd, makeX86FP80X86FP80X86FP80X86FP80},
1364 {"llvm.fabs.f32", Intrinsic::fabs, makeDoubleDouble},
1365 {"llvm.fabs.f64", Intrinsic::fabs, makeX86FP80X86FP80},
1366 {"llvm.fabs.f80", Intrinsic::fabs, makeX86FP80X86FP80},
1367 {"llvm.minnum.f32", Intrinsic::minnum, makeDoubleDoubleDouble},
1368 {"llvm.minnum.f64", Intrinsic::minnum, makeX86FP80X86FP80X86FP80},
1369 {"llvm.minnum.f80", Intrinsic::minnum, makeX86FP80X86FP80X86FP80},
1370 {"llvm.maxnum.f32", Intrinsic::maxnum, makeDoubleDoubleDouble},
1371 {"llvm.maxnum.f64", Intrinsic::maxnum, makeX86FP80X86FP80X86FP80},
1372 {"llvm.maxnum.f80", Intrinsic::maxnum, makeX86FP80X86FP80X86FP80},
1373 {"llvm.minimum.f32", Intrinsic::minimum, makeDoubleDoubleDouble},
1374 {"llvm.minimum.f64", Intrinsic::minimum, makeX86FP80X86FP80X86FP80},
1375 {"llvm.minimum.f80", Intrinsic::minimum, makeX86FP80X86FP80X86FP80},
1376 {"llvm.maximum.f32", Intrinsic::maximum, makeDoubleDoubleDouble},
1377 {"llvm.maximum.f64", Intrinsic::maximum, makeX86FP80X86FP80X86FP80},
1378 {"llvm.maximum.f80", Intrinsic::maximum, makeX86FP80X86FP80X86FP80},
1379 {"llvm.minimumnum.f32", Intrinsic::minimumnum, makeDoubleDoubleDouble},
1380 {"llvm.minimumnum.f64", Intrinsic::minimumnum, makeX86FP80X86FP80X86FP80},
1381 {"llvm.minimumnum.f80", Intrinsic::minimumnum, makeX86FP80X86FP80X86FP80},
1382 {"llvm.maximumnum.f32", Intrinsic::maximumnum, makeDoubleDoubleDouble},
1383 {"llvm.maximumnum.f64", Intrinsic::maximumnum, makeX86FP80X86FP80X86FP80},
1384 {"llvm.maximumnum.f80", Intrinsic::maximumnum, makeX86FP80X86FP80X86FP80},
1385 {"llvm.copysign.f32", Intrinsic::copysign, makeDoubleDoubleDouble},
1386 {"llvm.copysign.f64", Intrinsic::copysign, makeX86FP80X86FP80X86FP80},
1387 {"llvm.copysign.f80", Intrinsic::copysign, makeX86FP80X86FP80X86FP80},
1388 {"llvm.floor.f32", Intrinsic::floor, makeDoubleDouble},
1389 {"llvm.floor.f64", Intrinsic::floor, makeX86FP80X86FP80},
1390 {"llvm.floor.f80", Intrinsic::floor, makeX86FP80X86FP80},
1391 {"llvm.ceil.f32", Intrinsic::ceil, makeDoubleDouble},
1392 {"llvm.ceil.f64", Intrinsic::ceil, makeX86FP80X86FP80},
1393 {"llvm.ceil.f80", Intrinsic::ceil, makeX86FP80X86FP80},
1394 {"llvm.trunc.f32", Intrinsic::trunc, makeDoubleDouble},
1395 {"llvm.trunc.f64", Intrinsic::trunc, makeX86FP80X86FP80},
1396 {"llvm.trunc.f80", Intrinsic::trunc, makeX86FP80X86FP80},
1397 {"llvm.rint.f32", Intrinsic::rint, makeDoubleDouble},
1398 {"llvm.rint.f64", Intrinsic::rint, makeX86FP80X86FP80},
1399 {"llvm.rint.f80", Intrinsic::rint, makeX86FP80X86FP80},
1400 {"llvm.nearbyint.f32", Intrinsic::nearbyint, makeDoubleDouble},
1401 {"llvm.nearbyint.f64", Intrinsic::nearbyint, makeX86FP80X86FP80},
1402 {"llvm.nearbyint.f80", Intrinsic::nearbyint, makeX86FP80X86FP80},
1403 {"llvm.round.f32", Intrinsic::round, makeDoubleDouble},
1404 {"llvm.round.f64", Intrinsic::round, makeX86FP80X86FP80},
1405 {"llvm.round.f80", Intrinsic::round, makeX86FP80X86FP80},
1406};
1407
1408const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
1409 {LibFunc_sqrtf, "llvm.sqrt.f32"},
1410 {LibFunc_sqrt, "llvm.sqrt.f64"},
1411 {LibFunc_sqrtl, "llvm.sqrt.f80"},
1412 {LibFunc_sinf, "llvm.sin.f32"},
1413 {LibFunc_sin, "llvm.sin.f64"},
1414 {LibFunc_sinl, "llvm.sin.f80"},
1415 {LibFunc_cosf, "llvm.cos.f32"},
1416 {LibFunc_cos, "llvm.cos.f64"},
1417 {LibFunc_cosl, "llvm.cos.f80"},
1418 {LibFunc_powf, "llvm.pow.f32"},
1419 {LibFunc_pow, "llvm.pow.f64"},
1420 {LibFunc_powl, "llvm.pow.f80"},
1421 {LibFunc_expf, "llvm.exp.f32"},
1422 {LibFunc_exp, "llvm.exp.f64"},
1423 {LibFunc_expl, "llvm.exp.f80"},
1424 {LibFunc_exp2f, "llvm.exp2.f32"},
1425 {LibFunc_exp2, "llvm.exp2.f64"},
1426 {LibFunc_exp2l, "llvm.exp2.f80"},
1427 {LibFunc_logf, "llvm.log.f32"},
1428 {LibFunc_log, "llvm.log.f64"},
1429 {LibFunc_logl, "llvm.log.f80"},
1430 {LibFunc_log10f, "llvm.log10.f32"},
1431 {LibFunc_log10, "llvm.log10.f64"},
1432 {LibFunc_log10l, "llvm.log10.f80"},
1433 {LibFunc_log2f, "llvm.log2.f32"},
1434 {LibFunc_log2, "llvm.log2.f64"},
1435 {LibFunc_log2l, "llvm.log2.f80"},
1436 {LibFunc_fabsf, "llvm.fabs.f32"},
1437 {LibFunc_fabs, "llvm.fabs.f64"},
1438 {LibFunc_fabsl, "llvm.fabs.f80"},
1439 {LibFunc_copysignf, "llvm.copysign.f32"},
1440 {LibFunc_copysign, "llvm.copysign.f64"},
1441 {LibFunc_copysignl, "llvm.copysign.f80"},
1442 {LibFunc_floorf, "llvm.floor.f32"},
1443 {LibFunc_floor, "llvm.floor.f64"},
1444 {LibFunc_floorl, "llvm.floor.f80"},
1445 {LibFunc_fmaxf, "llvm.maxnum.f32"},
1446 {LibFunc_fmax, "llvm.maxnum.f64"},
1447 {LibFunc_fmaxl, "llvm.maxnum.f80"},
1448 {LibFunc_fminf, "llvm.minnum.f32"},
1449 {LibFunc_fmin, "llvm.minnum.f64"},
1450 {LibFunc_fminl, "llvm.minnum.f80"},
1451 {LibFunc_fmaximum_numf, "llvm.maximumnum.f32"},
1452 {LibFunc_fmaximum_num, "llvm.maximumnum.f64"},
1453 {LibFunc_fmaximum_numl, "llvm.maximumnum.f80"},
1454 {LibFunc_fminimum_numf, "llvm.minimumnum.f32"},
1455 {LibFunc_fminimum_num, "llvm.minimumnum.f64"},
1456 {LibFunc_fminimum_numl, "llvm.minimumnum.f80"},
1457 {LibFunc_ceilf, "llvm.ceil.f32"},
1458 {LibFunc_ceil, "llvm.ceil.f64"},
1459 {LibFunc_ceill, "llvm.ceil.f80"},
1460 {LibFunc_truncf, "llvm.trunc.f32"},
1461 {LibFunc_trunc, "llvm.trunc.f64"},
1462 {LibFunc_truncl, "llvm.trunc.f80"},
1463 {LibFunc_rintf, "llvm.rint.f32"},
1464 {LibFunc_rint, "llvm.rint.f64"},
1465 {LibFunc_rintl, "llvm.rint.f80"},
1466 {LibFunc_nearbyintf, "llvm.nearbyint.f32"},
1467 {LibFunc_nearbyint, "llvm.nearbyint.f64"},
1468 {LibFunc_nearbyintl, "llvm.nearbyint.f80"},
1469 {LibFunc_roundf, "llvm.round.f32"},
1470 {LibFunc_round, "llvm.round.f64"},
1471 {LibFunc_roundl, "llvm.round.f80"},
1472};
1473
1474const char *KnownIntrinsic::get(LibFunc LFunc) {
1475 for (const auto &E : kLibfuncIntrinsics) {
1476 if (E.LFunc == LFunc)
1477 return E.IntrinsicName;
1478 }
1479 return nullptr;
1480}
1481
1482const KnownIntrinsic::WidenedIntrinsic *KnownIntrinsic::widen(StringRef Name) {
1483 for (const auto &E : kWidenedIntrinsics) {
1484 if (E.NarrowName == Name)
1485 return &E;
1486 }
1487 return nullptr;
1488}
1489
1490// Returns the name of the LLVM intrinsic corresponding to the given function.
1491static const char *getIntrinsicFromLibfunc(Function &Fn, Type *VT,
1492 const TargetLibraryInfo &TLI) {
1493 LibFunc LFunc = TLI.getLibFunc(Fn);
1494 if (LFunc == NotLibFunc)
1495 return nullptr;
1496
1497 if (const char *Name = KnownIntrinsic::get(LFunc))
1498 return Name;
1499
1500 LLVM_DEBUG(errs() << "TODO: LibFunc: " << TLI.getName(LFunc) << "\n");
1501 return nullptr;
1502}
1503
1504// Try to handle a known function call.
1505Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
1506 CallBase &Call, Type *VT, Type *ExtendedVT, const TargetLibraryInfo &TLI,
1507 const ValueToShadowMap &Map, IRBuilder<> &Builder) {
1509 if (Fn == nullptr)
1510 return nullptr;
1511
1512 Intrinsic::ID WidenedId = Intrinsic::ID();
1513 FunctionType *WidenedFnTy = nullptr;
1514 if (const auto ID = Fn->getIntrinsicID()) {
1515 const auto *Widened = KnownIntrinsic::widen(Fn->getName());
1516 if (Widened) {
1517 WidenedId = Widened->ID;
1518 WidenedFnTy = Widened->MakeFnTy(Context);
1519 } else {
1520 // If we don't know how to widen the intrinsic, we have no choice but to
1521 // call the non-wide version on a truncated shadow and extend again
1522 // afterwards.
1523 WidenedId = ID;
1524 WidenedFnTy = Fn->getFunctionType();
1525 }
1526 } else if (const char *Name = getIntrinsicFromLibfunc(*Fn, VT, TLI)) {
1527 // We might have a call to a library function that we can replace with a
1528 // wider Intrinsic.
1529 const auto *Widened = KnownIntrinsic::widen(Name);
1530 assert(Widened && "make sure KnownIntrinsic entries are consistent");
1531 WidenedId = Widened->ID;
1532 WidenedFnTy = Widened->MakeFnTy(Context);
1533 } else {
1534 // This is not a known library function or intrinsic.
1535 return nullptr;
1536 }
1537
1538 // Check that the widened intrinsic is valid.
1539 SmallVector<Type *, 4> OverloadTys;
1540 [[maybe_unused]] bool IsValid =
1541 Intrinsic::isSignatureValid(WidenedId, WidenedFnTy, OverloadTys);
1542 assert(IsValid && "invalid widened intrinsic");
1543 // For known intrinsic functions, we create a second call to the same
1544 // intrinsic with a different type.
1545 SmallVector<Value *, 4> Args;
1546 // The last operand is the intrinsic itself, skip it.
1547 for (unsigned I = 0, E = Call.getNumOperands() - 1; I < E; ++I) {
1548 Value *Arg = Call.getOperand(I);
1549 Type *OrigArgTy = Arg->getType();
1550 Type *IntrinsicArgTy = WidenedFnTy->getParamType(I);
1551 if (OrigArgTy == IntrinsicArgTy) {
1552 Args.push_back(Arg); // The arg is passed as is.
1553 continue;
1554 }
1555 Type *ShadowArgTy = Config.getExtendedFPType(Arg->getType());
1556 assert(ShadowArgTy &&
1557 "don't know how to get the shadow value for a non-FT");
1558 Value *Shadow = Map.getShadow(Arg);
1559 if (ShadowArgTy == IntrinsicArgTy) {
1560 // The shadow is the right type for the intrinsic.
1561 assert(Shadow->getType() == ShadowArgTy);
1562 Args.push_back(Shadow);
1563 continue;
1564 }
1565 // There is no intrinsic with his level of precision, truncate the shadow.
1566 Args.push_back(Builder.CreateFPTrunc(Shadow, IntrinsicArgTy));
1567 }
1568 Value *IntrinsicCall = Builder.CreateIntrinsic(WidenedId, OverloadTys, Args);
1569 return WidenedFnTy->getReturnType() == ExtendedVT
1570 ? IntrinsicCall
1571 : Builder.CreateFPExt(IntrinsicCall, ExtendedVT);
1572}
1573
1574// Handle a CallBase, i.e. a function call, an inline asm sequence, or an
1575// invoke.
1576Value *NumericalStabilitySanitizer::handleCallBase(CallBase &Call, Type *VT,
1577 Type *ExtendedVT,
1578 const TargetLibraryInfo &TLI,
1579 const ValueToShadowMap &Map,
1580 IRBuilder<> &Builder) {
1581 // We cannot look inside inline asm, just expand the result again.
1582 if (Call.isInlineAsm())
1583 return Builder.CreateFPExt(&Call, ExtendedVT);
1584
1585 // Intrinsics and library functions (e.g. sin, exp) are handled
1586 // specifically, because we know their semantics and can do better than
1587 // blindly calling them (e.g. compute the sinus in the actual shadow domain).
1588 if (Value *V =
1589 maybeHandleKnownCallBase(Call, VT, ExtendedVT, TLI, Map, Builder))
1590 return V;
1591
1592 // If the return tag matches that of the called function, read the extended
1593 // return value from the shadow ret ptr. Else, just extend the return value.
1594 Value *L =
1595 Builder.CreateLoad(IntptrTy, NsanShadowRetTag, /*isVolatile=*/false);
1596 Value *HasShadowRet = Builder.CreateICmpEQ(
1597 L, Builder.CreatePtrToInt(Call.getCalledOperand(), IntptrTy));
1598
1599 Value *ShadowRetVal = Builder.CreateLoad(
1600 ExtendedVT,
1601 Builder.CreateConstGEP2_64(NsanShadowRetType, NsanShadowRetPtr, 0, 0),
1602 /*isVolatile=*/false);
1603 Value *Shadow = Builder.CreateSelect(HasShadowRet, ShadowRetVal,
1604 Builder.CreateFPExt(&Call, ExtendedVT));
1605 ++NumInstrumentedFTCalls;
1606 return Shadow;
1607}
1608
1609// Creates a shadow value for the given FT value. At that point all operands are
1610// guaranteed to be available.
1611Value *NumericalStabilitySanitizer::createShadowValueWithOperandsAvailable(
1612 Instruction &Inst, const TargetLibraryInfo &TLI,
1613 const ValueToShadowMap &Map) {
1614 Type *VT = Inst.getType();
1615 Type *ExtendedVT = Config.getExtendedFPType(VT);
1616 assert(ExtendedVT != nullptr && "trying to create a shadow for a non-FT");
1617
1618 if (auto *Load = dyn_cast<LoadInst>(&Inst))
1619 return handleLoad(*Load, VT, ExtendedVT);
1620
1621 if (auto *Call = dyn_cast<CallInst>(&Inst)) {
1622 // Insert after the call.
1623 BasicBlock::iterator It(Inst);
1624 IRBuilder<> Builder(++It);
1626 return handleCallBase(*Call, VT, ExtendedVT, TLI, Map, Builder);
1627 }
1628
1629 if (auto *Invoke = dyn_cast<InvokeInst>(&Inst)) {
1630 // The Invoke terminates the basic block, create a new basic block in
1631 // between the successful invoke and the next block.
1632 BasicBlock *InvokeBB = Invoke->getParent();
1633 BasicBlock *NextBB = Invoke->getNormalDest();
1634 BasicBlock *NewBB =
1635 BasicBlock::Create(Context, "", NextBB->getParent(), NextBB);
1636 Inst.replaceSuccessorWith(NextBB, NewBB);
1637
1638 IRBuilder<> Builder(NewBB);
1639 Builder.SetCurrentDebugLocation(Invoke->getDebugLoc());
1640 Value *Shadow = handleCallBase(*Invoke, VT, ExtendedVT, TLI, Map, Builder);
1641 Builder.CreateBr(NextBB);
1642 NewBB->replaceSuccessorsPhiUsesWith(InvokeBB, NewBB);
1643 return Shadow;
1644 }
1645
1646 IRBuilder<> Builder(Inst.getNextNode());
1647 Builder.SetCurrentDebugLocation(Inst.getDebugLoc());
1648
1649 if (auto *Trunc = dyn_cast<FPTruncInst>(&Inst))
1650 return handleTrunc(*Trunc, VT, ExtendedVT, Map, Builder);
1651 if (auto *Ext = dyn_cast<FPExtInst>(&Inst))
1652 return handleExt(*Ext, VT, ExtendedVT, Map, Builder);
1653
1654 if (auto *UnaryOp = dyn_cast<UnaryOperator>(&Inst))
1655 return Builder.CreateUnOp(UnaryOp->getOpcode(),
1656 Map.getShadow(UnaryOp->getOperand(0)));
1657
1658 if (auto *BinOp = dyn_cast<BinaryOperator>(&Inst))
1659 return Builder.CreateBinOp(BinOp->getOpcode(),
1660 Map.getShadow(BinOp->getOperand(0)),
1661 Map.getShadow(BinOp->getOperand(1)));
1662
1663 if (isa<UIToFPInst>(&Inst) || isa<SIToFPInst>(&Inst)) {
1664 auto *Cast = cast<CastInst>(&Inst);
1665 return Builder.CreateCast(Cast->getOpcode(), Cast->getOperand(0),
1666 ExtendedVT);
1667 }
1668
1669 if (auto *S = dyn_cast<SelectInst>(&Inst))
1670 return Builder.CreateSelect(S->getCondition(),
1671 Map.getShadow(S->getTrueValue()),
1672 Map.getShadow(S->getFalseValue()));
1673
1674 if (auto *Freeze = dyn_cast<FreezeInst>(&Inst))
1675 return Builder.CreateFreeze(Map.getShadow(Freeze->getOperand(0)));
1676
1677 if (auto *Extract = dyn_cast<ExtractElementInst>(&Inst))
1678 return Builder.CreateExtractElement(
1679 Map.getShadow(Extract->getVectorOperand()), Extract->getIndexOperand());
1680
1681 if (auto *Insert = dyn_cast<InsertElementInst>(&Inst))
1682 return Builder.CreateInsertElement(Map.getShadow(Insert->getOperand(0)),
1683 Map.getShadow(Insert->getOperand(1)),
1684 Insert->getOperand(2));
1685
1686 if (auto *Shuffle = dyn_cast<ShuffleVectorInst>(&Inst))
1687 return Builder.CreateShuffleVector(Map.getShadow(Shuffle->getOperand(0)),
1688 Map.getShadow(Shuffle->getOperand(1)),
1689 Shuffle->getShuffleMask());
1690 // TODO: We could make aggregate object first class citizens. For now we
1691 // just extend the extracted value.
1692 if (auto *Extract = dyn_cast<ExtractValueInst>(&Inst))
1693 return Builder.CreateFPExt(Extract, ExtendedVT);
1694
1695 if (auto *BC = dyn_cast<BitCastInst>(&Inst))
1696 return Builder.CreateFPExt(BC, ExtendedVT);
1697
1698 report_fatal_error("Unimplemented support for " +
1699 Twine(Inst.getOpcodeName()));
1700}
1701
1702// Creates a shadow value for an instruction that defines a value of FT type.
1703// FT operands that do not already have shadow values are created recursively.
1704// The DFS is guaranteed to not loop as phis and arguments already have
1705// shadows.
1706void NumericalStabilitySanitizer::maybeCreateShadowValue(
1707 Instruction &Root, const TargetLibraryInfo &TLI, ValueToShadowMap &Map) {
1708 Type *VT = Root.getType();
1709 Type *ExtendedVT = Config.getExtendedFPType(VT);
1710 if (ExtendedVT == nullptr)
1711 return; // Not an FT value.
1712
1713 if (Map.hasShadow(&Root))
1714 return; // Shadow already exists.
1715
1716 assert(!isa<PHINode>(Root) && "phi nodes should already have shadows");
1717
1718 std::vector<Instruction *> DfsStack(1, &Root);
1719 while (!DfsStack.empty()) {
1720 // Ensure that all operands to the instruction have shadows before
1721 // proceeding.
1722 Instruction *I = DfsStack.back();
1723 // The shadow for the instruction might have been created deeper in the DFS,
1724 // see `forward_use_with_two_uses` test.
1725 if (Map.hasShadow(I)) {
1726 DfsStack.pop_back();
1727 continue;
1728 }
1729
1730 bool MissingShadow = false;
1731 for (Value *Op : I->operands()) {
1732 Type *VT = Op->getType();
1733 if (!Config.getExtendedFPType(VT))
1734 continue; // Not an FT value.
1735 if (Map.hasShadow(Op))
1736 continue; // Shadow is already available.
1737 MissingShadow = true;
1738 DfsStack.push_back(cast<Instruction>(Op));
1739 }
1740 if (MissingShadow)
1741 continue; // Process operands and come back to this instruction later.
1742
1743 // All operands have shadows. Create a shadow for the current value.
1744 Value *Shadow = createShadowValueWithOperandsAvailable(*I, TLI, Map);
1745 Map.setShadow(*I, *Shadow);
1746 DfsStack.pop_back();
1747 }
1748}
1749
1750// A floating-point store needs its value and type written to shadow memory.
1751void NumericalStabilitySanitizer::propagateFTStore(
1752 StoreInst &Store, Type *VT, Type *ExtendedVT, const ValueToShadowMap &Map) {
1753 Value *StoredValue = Store.getValueOperand();
1754 IRBuilder<> Builder(&Store);
1755 Builder.SetCurrentDebugLocation(Store.getDebugLoc());
1756 const auto Extents = getMemoryExtentsOrDie(VT);
1757 Value *ShadowPtr = Builder.CreateCall(
1758 NsanGetShadowPtrForStore[Extents.ValueType],
1759 {Store.getPointerOperand(), ConstantInt::get(IntptrTy, Extents.NumElts)});
1760
1761 Value *StoredShadow = Map.getShadow(StoredValue);
1762 if (!Store.getParent()->getParent()->hasOptNone()) {
1763 // Only check stores when optimizing, because non-optimized code generates
1764 // too many stores to the stack, creating false positives.
1765 if (Opts.nsan_check_stores) {
1766 StoredShadow = emitCheck(StoredValue, StoredShadow, Builder,
1767 CheckLoc::makeStore(Store.getPointerOperand()));
1768 ++NumInstrumentedFTStores;
1769 }
1770 }
1771
1772 Builder.CreateAlignedStore(StoredShadow, ShadowPtr, Align(1),
1773 Store.isVolatile());
1774}
1775
1776// A non-ft store needs to invalidate shadow memory. Exceptions are:
1777// - memory transfers of floating-point data through other pointer types (llvm
1778// optimization passes transform `*(float*)a = *(float*)b` into
1779// `*(i32*)a = *(i32*)b` ). These have the same semantics as memcpy.
1780// - Writes of FT-sized constants. LLVM likes to do float stores as bitcasted
1781// ints. Note that this is not really necessary because if the value is
1782// unknown the framework will re-extend it on load anyway. It just felt
1783// easier to debug tests with vectors of FTs.
1784void NumericalStabilitySanitizer::propagateNonFTStore(
1785 StoreInst &Store, Type *VT, const ValueToShadowMap &Map) {
1786 Value *PtrOp = Store.getPointerOperand();
1787 IRBuilder<> Builder(Store.getNextNode());
1788 Builder.SetCurrentDebugLocation(Store.getDebugLoc());
1789 Value *Dst = PtrOp;
1790 TypeSize SlotSize = DL.getTypeStoreSize(VT);
1791 assert(!SlotSize.isScalable() && "unsupported");
1792 const auto LoadSizeBytes = SlotSize.getFixedValue();
1793 Value *ValueSize = Constant::getIntegerValue(
1794 IntptrTy, APInt(IntptrTy->getPrimitiveSizeInBits(), LoadSizeBytes));
1795
1796 ++NumInstrumentedNonFTStores;
1797 Value *StoredValue = Store.getValueOperand();
1798 if (LoadInst *Load = dyn_cast<LoadInst>(StoredValue)) {
1799 // TODO: Handle the case when the value is from a phi.
1800 // This is a memory transfer with memcpy semantics. Copy the type and
1801 // value from the source. Note that we cannot use __nsan_copy_values()
1802 // here, because that will not work when there is a write to memory in
1803 // between the load and the store, e.g. in the case of a swap.
1804 Type *ShadowTypeIntTy = Type::getIntNTy(Context, 8 * LoadSizeBytes);
1805 Type *ShadowValueIntTy =
1806 Type::getIntNTy(Context, 8 * kShadowScale * LoadSizeBytes);
1807 IRBuilder<> LoadBuilder(Load->getNextNode());
1808 Builder.SetCurrentDebugLocation(Store.getDebugLoc());
1809 Value *LoadSrc = Load->getPointerOperand();
1810 // Read the shadow type and value at load time. The type has the same size
1811 // as the FT value, the value has twice its size.
1812 // TODO: cache them to avoid re-creating them when a load is used by
1813 // several stores. Maybe create them like the FT shadows when a load is
1814 // encountered.
1815 Value *RawShadowType = LoadBuilder.CreateAlignedLoad(
1816 ShadowTypeIntTy,
1817 LoadBuilder.CreateCall(NsanGetRawShadowTypePtr, {LoadSrc}), Align(1),
1818 /*isVolatile=*/false);
1819 Value *RawShadowValue = LoadBuilder.CreateAlignedLoad(
1820 ShadowValueIntTy,
1821 LoadBuilder.CreateCall(NsanGetRawShadowPtr, {LoadSrc}), Align(1),
1822 /*isVolatile=*/false);
1823
1824 // Write back the shadow type and value at store time.
1825 Builder.CreateAlignedStore(
1826 RawShadowType, Builder.CreateCall(NsanGetRawShadowTypePtr, {Dst}),
1827 Align(1),
1828 /*isVolatile=*/false);
1829 Builder.CreateAlignedStore(RawShadowValue,
1830 Builder.CreateCall(NsanGetRawShadowPtr, {Dst}),
1831 Align(1),
1832 /*isVolatile=*/false);
1833
1834 ++NumInstrumentedNonFTMemcpyStores;
1835 return;
1836 }
1837 if (Constant *C; Opts.nsan_propagate_non_ft_const_stores_as_ft &&
1838 (C = dyn_cast<Constant>(StoredValue))) {
1839 // This might be a fp constant stored as an int. Bitcast and store if it has
1840 // appropriate size.
1841 Type *BitcastTy = nullptr; // The FT type to bitcast to.
1843 switch (C->getType()->getScalarSizeInBits()) {
1844 case 32:
1845 BitcastTy = Type::getFloatTy(Context);
1846 break;
1847 case 64:
1848 BitcastTy = Type::getDoubleTy(Context);
1849 break;
1850 case 80:
1851 BitcastTy = Type::getX86_FP80Ty(Context);
1852 break;
1853 default:
1854 break;
1855 }
1856
1857 if (BitcastTy)
1858 if (auto *VectorTy = dyn_cast<VectorType>(C->getType()))
1859 BitcastTy = VectorType::get(BitcastTy, VectorTy->getElementCount());
1860 }
1861 if (BitcastTy) {
1862 const MemoryExtents Extents = getMemoryExtentsOrDie(BitcastTy);
1863 Value *ShadowPtr = Builder.CreateCall(
1864 NsanGetShadowPtrForStore[Extents.ValueType],
1865 {PtrOp, ConstantInt::get(IntptrTy, Extents.NumElts)});
1866 // Bitcast the integer value to the appropriate FT type and extend to 2FT.
1867 Type *ExtVT = Config.getExtendedFPType(BitcastTy);
1868 Value *Shadow =
1869 Builder.CreateFPExt(Builder.CreateBitCast(C, BitcastTy), ExtVT);
1870 Builder.CreateAlignedStore(Shadow, ShadowPtr, Align(1),
1871 Store.isVolatile());
1872 return;
1873 }
1874 }
1875 // All other stores just reset the shadow value to unknown.
1876 Builder.CreateCall(NsanSetUnknownFns.getFallback(), {Dst, ValueSize});
1877}
1878
1879void NumericalStabilitySanitizer::propagateShadowValues(
1880 Instruction &Inst, const TargetLibraryInfo &TLI,
1881 const ValueToShadowMap &Map) {
1882 if (auto *Store = dyn_cast<StoreInst>(&Inst)) {
1883 Value *StoredValue = Store->getValueOperand();
1884 Type *VT = StoredValue->getType();
1885 Type *ExtendedVT = Config.getExtendedFPType(VT);
1886 if (ExtendedVT == nullptr)
1887 return propagateNonFTStore(*Store, VT, Map);
1888 return propagateFTStore(*Store, VT, ExtendedVT, Map);
1889 }
1890
1891 if (auto *FCmp = dyn_cast<FCmpInst>(&Inst)) {
1892 emitFCmpCheck(*FCmp, Map);
1893 return;
1894 }
1895
1896 if (auto *CB = dyn_cast<CallBase>(&Inst)) {
1897 maybeAddSuffixForNsanInterface(CB);
1898 if (CallInst *CI = dyn_cast<CallInst>(&Inst))
1900 if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&Inst)) {
1901 instrumentMemIntrinsic(MI);
1902 return;
1903 }
1904 populateShadowStack(*CB, TLI, Map);
1905 return;
1906 }
1907
1908 if (auto *RetInst = dyn_cast<ReturnInst>(&Inst)) {
1909 if (!Opts.nsan_check_ret)
1910 return;
1911
1912 Value *RV = RetInst->getReturnValue();
1913 if (RV == nullptr)
1914 return; // This is a `ret void`.
1915 Type *VT = RV->getType();
1916 Type *ExtendedVT = Config.getExtendedFPType(VT);
1917 if (ExtendedVT == nullptr)
1918 return; // Not an FT ret.
1919 Value *RVShadow = Map.getShadow(RV);
1920 IRBuilder<> Builder(RetInst);
1921
1922 RVShadow = emitCheck(RV, RVShadow, Builder, CheckLoc::makeRet());
1923 ++NumInstrumentedFTRets;
1924 // Store tag.
1925 Value *FnAddr =
1926 Builder.CreatePtrToInt(Inst.getParent()->getParent(), IntptrTy);
1927 Builder.CreateStore(FnAddr, NsanShadowRetTag);
1928 // Store value.
1929 Value *ShadowRetValPtr =
1930 Builder.CreateConstGEP2_64(NsanShadowRetType, NsanShadowRetPtr, 0, 0);
1931 Builder.CreateStore(RVShadow, ShadowRetValPtr);
1932 return;
1933 }
1934
1935 if (InsertValueInst *Insert = dyn_cast<InsertValueInst>(&Inst)) {
1936 Value *V = Insert->getOperand(1);
1937 Type *VT = V->getType();
1938 Type *ExtendedVT = Config.getExtendedFPType(VT);
1939 if (ExtendedVT == nullptr)
1940 return;
1941 IRBuilder<> Builder(Insert);
1942 emitCheck(V, Map.getShadow(V), Builder, CheckLoc::makeInsert());
1943 return;
1944 }
1945}
1946
1947// Moves fast math flags from the function to individual instructions, and
1948// removes the attribute from the function.
1949// TODO: Make this controllable with a flag.
1951 std::vector<Instruction *> &Instructions) {
1952 FastMathFlags FMF;
1953#define MOVE_FLAG(attr, setter) \
1954 if (F.getFnAttribute(attr).getValueAsString() == "true") { \
1955 F.removeFnAttr(attr); \
1956 FMF.set##setter(); \
1957 }
1958 MOVE_FLAG("no-signed-zeros-fp-math", NoSignedZeros)
1959#undef MOVE_FLAG
1960
1961 for (Instruction *I : Instructions)
1963 I->setFastMathFlags(FMF);
1964}
1965
1966bool NumericalStabilitySanitizer::sanitizeFunction(
1967 Function &F, const TargetLibraryInfo &TLI) {
1968 if (!F.hasFnAttribute(Attribute::SanitizeNumericalStability) ||
1969 F.isDeclaration())
1970 return false;
1971
1972 if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1973 return false;
1974
1975 // This is required to prevent instrumenting call to __nsan_init from within
1976 // the module constructor.
1977 if (F.getName() == kNsanModuleCtorName)
1978 return false;
1979
1980 // The instrumentation maintains:
1981 // - for each IR value `v` of floating-point (or vector floating-point) type
1982 // FT, a shadow IR value `s(v)` with twice the precision 2FT (e.g.
1983 // double for float and f128 for double).
1984 // - A shadow memory, which stores `s(v)` for any `v` that has been stored,
1985 // along with a shadow memory tag, which stores whether the value in the
1986 // corresponding shadow memory is valid. Note that this might be
1987 // incorrect if a non-instrumented function stores to memory, or if
1988 // memory is stored to through a char pointer.
1989 // - A shadow stack, which holds `s(v)` for any floating-point argument `v`
1990 // of a call to an instrumented function. This allows
1991 // instrumented functions to retrieve the shadow values for their
1992 // arguments.
1993 // Because instrumented functions can be called from non-instrumented
1994 // functions, the stack needs to include a tag so that the instrumented
1995 // function knows whether shadow values are available for their
1996 // parameters (i.e. whether is was called by an instrumented function).
1997 // When shadow arguments are not available, they have to be recreated by
1998 // extending the precision of the non-shadow arguments to the non-shadow
1999 // value. Non-instrumented functions do not modify (or even know about) the
2000 // shadow stack. The shadow stack pointer is __nsan_shadow_args. The shadow
2001 // stack tag is __nsan_shadow_args_tag. The tag is any unique identifier
2002 // for the function (we use the address of the function). Both variables
2003 // are thread local.
2004 // Example:
2005 // calls shadow stack tag shadow stack
2006 // =======================================================================
2007 // non_instrumented_1() 0 0
2008 // |
2009 // v
2010 // instrumented_2(float a) 0 0
2011 // |
2012 // v
2013 // instrumented_3(float b, double c) &instrumented_3 s(b),s(c)
2014 // |
2015 // v
2016 // instrumented_4(float d) &instrumented_4 s(d)
2017 // |
2018 // v
2019 // non_instrumented_5(float e) &non_instrumented_5 s(e)
2020 // |
2021 // v
2022 // instrumented_6(float f) &non_instrumented_5 s(e)
2023 //
2024 // On entry, instrumented_2 checks whether the tag corresponds to its
2025 // function ptr.
2026 // Note that functions reset the tag to 0 after reading shadow parameters.
2027 // This ensures that the function does not erroneously read invalid data if
2028 // called twice in the same stack, once from an instrumented function and
2029 // once from an uninstrumented one. For example, in the following example,
2030 // resetting the tag in (A) ensures that (B) does not reuse the same the
2031 // shadow arguments (which would be incorrect).
2032 // instrumented_1(float a)
2033 // |
2034 // v
2035 // instrumented_2(float b) (A)
2036 // |
2037 // v
2038 // non_instrumented_3()
2039 // |
2040 // v
2041 // instrumented_2(float b) (B)
2042 //
2043 // - A shadow return slot. Any function that returns a floating-point value
2044 // places a shadow return value in __nsan_shadow_ret_val. Again, because
2045 // we might be calling non-instrumented functions, this value is guarded
2046 // by __nsan_shadow_ret_tag marker indicating which instrumented function
2047 // placed the value in __nsan_shadow_ret_val, so that the caller can check
2048 // that this corresponds to the callee. Both variables are thread local.
2049 //
2050 // For example, in the following example, the instrumentation in
2051 // `instrumented_1` rejects the shadow return value from `instrumented_3`
2052 // because it is not tagged as expected (`&instrumented_3` instead of
2053 // `non_instrumented_2`):
2054 //
2055 // instrumented_1()
2056 // |
2057 // v
2058 // float non_instrumented_2()
2059 // |
2060 // v
2061 // float instrumented_3()
2062 //
2063 // Calls of known math functions (sin, cos, exp, ...) are duplicated to call
2064 // their overload on the shadow type.
2065
2066 // Collect all instructions before processing, as creating shadow values
2067 // creates new instructions inside the function.
2068 std::vector<Instruction *> OriginalInstructions;
2069 for (BasicBlock &BB : F)
2070 for (Instruction &Inst : BB)
2071 OriginalInstructions.emplace_back(&Inst);
2072
2073 moveFastMathFlags(F, OriginalInstructions);
2074 ValueToShadowMap ValueToShadow(Config);
2075
2076 // In the first pass, we create shadow values for all FT function arguments
2077 // and all phis. This ensures that the DFS of the next pass does not have
2078 // any loops.
2079 std::vector<PHINode *> OriginalPhis;
2080 createShadowArguments(F, TLI, ValueToShadow);
2081 for (Instruction *I : OriginalInstructions) {
2082 if (PHINode *Phi = dyn_cast<PHINode>(I)) {
2083 if (PHINode *Shadow = maybeCreateShadowPhi(*Phi, TLI)) {
2084 OriginalPhis.push_back(Phi);
2085 ValueToShadow.setShadow(*Phi, *Shadow);
2086 }
2087 }
2088 }
2089
2090 // Create shadow values for all instructions creating FT values.
2091 for (Instruction *I : OriginalInstructions)
2092 maybeCreateShadowValue(*I, TLI, ValueToShadow);
2093
2094 // Propagate shadow values across stores, calls and rets.
2095 for (Instruction *I : OriginalInstructions)
2096 propagateShadowValues(*I, TLI, ValueToShadow);
2097
2098 // The last pass populates shadow phis with shadow values.
2099 for (PHINode *Phi : OriginalPhis) {
2100 PHINode *ShadowPhi = cast<PHINode>(ValueToShadow.getShadow(Phi));
2101 for (unsigned I : seq(Phi->getNumOperands())) {
2102 Value *V = Phi->getOperand(I);
2103 Value *Shadow = ValueToShadow.getShadow(V);
2104 BasicBlock *IncomingBB = Phi->getIncomingBlock(I);
2105 // For some instructions (e.g. invoke), we create the shadow in a separate
2106 // block, different from the block where the original value is created.
2107 // In that case, the shadow phi might need to refer to this block instead
2108 // of the original block.
2109 // Note that this can only happen for instructions as constant shadows are
2110 // always created in the same block.
2111 ShadowPhi->addIncoming(Shadow, IncomingBB);
2112 }
2113 }
2114
2115 return !ValueToShadow.empty();
2116}
2117
2119 uint64_t OpSize = 0;
2120 if (Constant *C = dyn_cast<Constant>(V)) {
2121 auto *CInt = dyn_cast<ConstantInt>(C);
2122 if (CInt && CInt->getValue().getBitWidth() <= 64)
2123 OpSize = CInt->getValue().getZExtValue();
2124 }
2125
2126 return OpSize;
2127}
2128
2129// Instrument the memory intrinsics so that they properly modify the shadow
2130// memory.
2131bool NumericalStabilitySanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
2132 IRBuilder<> Builder(MI);
2133 if (auto *M = dyn_cast<MemSetInst>(MI)) {
2134 FunctionCallee SetUnknownFn =
2135 NsanSetUnknownFns.getFunctionFor(GetMemOpSize(M->getArgOperand(2)));
2136 if (SetUnknownFn.getFunctionType()->getNumParams() == 1)
2137 Builder.CreateCall(SetUnknownFn, {/*Address=*/M->getArgOperand(0)});
2138 else
2139 Builder.CreateCall(SetUnknownFn,
2140 {/*Address=*/M->getArgOperand(0),
2141 /*Size=*/Builder.CreateIntCast(M->getArgOperand(2),
2142 IntptrTy, false)});
2143
2144 } else if (auto *M = dyn_cast<MemTransferInst>(MI)) {
2145 FunctionCallee CopyFn =
2146 NsanCopyFns.getFunctionFor(GetMemOpSize(M->getArgOperand(2)));
2147
2148 if (CopyFn.getFunctionType()->getNumParams() == 2)
2149 Builder.CreateCall(CopyFn, {/*Destination=*/M->getArgOperand(0),
2150 /*Source=*/M->getArgOperand(1)});
2151 else
2152 Builder.CreateCall(CopyFn, {/*Destination=*/M->getArgOperand(0),
2153 /*Source=*/M->getArgOperand(1),
2154 /*Size=*/
2155 Builder.CreateIntCast(M->getArgOperand(2),
2156 IntptrTy, false)});
2157 }
2158 return false;
2159}
2160
2161void NumericalStabilitySanitizer::maybeAddSuffixForNsanInterface(CallBase *CI) {
2162 Function *Fn = CI->getCalledFunction();
2163 if (Fn == nullptr)
2164 return;
2165
2166 if (!Fn->getName().starts_with("__nsan_"))
2167 return;
2168
2169 if (Fn->getName() == "__nsan_dump_shadow_mem") {
2170 assert(CI->arg_size() == 4 &&
2171 "invalid prototype for __nsan_dump_shadow_mem");
2172 // __nsan_dump_shadow_mem requires an extra parameter with the dynamic
2173 // configuration:
2174 // (shadow_type_id_for_long_double << 16) | (shadow_type_id_for_double << 8)
2175 // | shadow_type_id_for_double
2176 const uint64_t shadow_value_type_ids =
2177 (static_cast<size_t>(Config.byValueType(kLongDouble).getNsanTypeId())
2178 << 16) |
2179 (static_cast<size_t>(Config.byValueType(kDouble).getNsanTypeId())
2180 << 8) |
2181 static_cast<size_t>(Config.byValueType(kFloat).getNsanTypeId());
2182 CI->setArgOperand(3, ConstantInt::get(IntptrTy, shadow_value_type_ids));
2183 }
2184}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Hexagon Common GEP
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
static constexpr Value * getValue(Ty &ValueOrUse)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file contains the declarations for metadata subclasses.
static GlobalValue * createThreadLocalGV(const char *Name, Module &M, Type *Ty)
static FunctionType * makeDoubleDouble(LLVMContext &C)
constexpr int kMaxVectorWidth
static bool shouldCheckArgs(CallBase &CI, const TargetLibraryInfo &TLI, const std::optional< Regex > &CheckFunctionsFilter)
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
constexpr StringLiteral kNsanModuleCtorName("nsan.module_ctor")
static FunctionType * makeDoubleDoubleDoubleDouble(LLVMContext &C)
static FunctionType * makeDoubleDoubleI32(LLVMContext &C)
static void moveFastMathFlags(Function &F, std::vector< Instruction * > &Instructions)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
Value * RHS
Value * LHS
static constexpr roundingMode rmTowardZero
Definition APFloat.h:365
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6045
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:125
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.
Definition BasicBlock.h:440
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
const Instruction & back() const
Definition BasicBlock.h:465
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
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.
Definition InstrTypes.h:828
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:44
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.
Definition DataLayout.h:64
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:757
bool empty() const
Definition DenseMap.h:716
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
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.
Definition FMF.h:23
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.
Definition Function.h:212
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:247
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2669
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition IRBuilder.h:2657
Value * CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2201
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2716
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="")
Definition IRBuilder.h:2067
BasicBlock::iterator GetInsertPoint() const
Definition IRBuilder.h:176
Value * CreateFreeze(Value *V, const Twine &Name="")
Definition IRBuilder.h:2735
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
Definition IRBuilder.h:228
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition IRBuilder.h:522
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Definition IRBuilder.h:2284
Value * CreateUnOp(Instruction::UnaryOps Opc, Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1854
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Definition IRBuilder.h:1206
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2382
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2243
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1907
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Definition IRBuilder.h:2691
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition IRBuilder.h:1925
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2233
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2561
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:1727
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Definition IRBuilder.h:2323
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Definition IRBuilder.h:1953
Value * CreateFPExt(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2216
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1588
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
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.
iterator_range< user_iterator > users()
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.
Definition LLVMContext.h:76
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.
Definition Module.h:68
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
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...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
static Attribute::AttrKind getExtAttrForBoolParam(const Triple &T)
StringRef getName(LibFunc F) const
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:348
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI Type * getStructElementType(unsigned N) const
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:283
bool isX86_FP80Ty() const
Return true if this is x86 long double.
Definition Type.h:161
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:274
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
static LLVM_ABI Type * getPPC_FP128Ty(LLVMContext &C)
Definition Type.cpp:282
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
Definition Type.cpp:281
LLVM_ABI unsigned getStructNumElements() const
LLVM_ABI uint64_t getArrayNumElements() const
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:272
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:271
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:296
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:277
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
Definition Type.cpp:280
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:276
'undef' values are things that do not have specified contents.
Definition Constants.h:1657
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
op_range operands()
Definition User.h:267
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
const ParentTy * getParent() const
Definition ilist_node.h:34
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT, SmallVectorImpl< Type * > &OverloadTys, raw_ostream &OS=nulls())
Returns true if FT is a valid function type for intrinsic ID.
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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)
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
Definition Local.cpp:3902
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)