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