LLVM 20.0.0git
MemoryTaggingSupport.cpp
Go to the documentation of this file.
1//== MemoryTaggingSupport.cpp - helpers for memory tagging implementations ===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7//
8// This file declares common infrastructure for HWAddressSanitizer and
9// Aarch64StackTagging.
10//
11//===----------------------------------------------------------------------===//
12
14
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/Analysis/CFG.h"
21#include "llvm/IR/BasicBlock.h"
22#include "llvm/IR/IRBuilder.h"
26
27namespace llvm {
28namespace memtag {
29namespace {
30bool maybeReachableFromEachOther(const SmallVectorImpl<IntrinsicInst *> &Insts,
31 const DominatorTree *DT, const LoopInfo *LI,
32 size_t MaxLifetimes) {
33 // If we have too many lifetime ends, give up, as the algorithm below is N^2.
34 if (Insts.size() > MaxLifetimes)
35 return true;
36 for (size_t I = 0; I < Insts.size(); ++I) {
37 for (size_t J = 0; J < Insts.size(); ++J) {
38 if (I == J)
39 continue;
40 if (isPotentiallyReachable(Insts[I], Insts[J], nullptr, DT, LI))
41 return true;
42 }
43 }
44 return false;
45}
46} // namespace
47
49 const LoopInfo &LI, const Instruction *Start,
52 llvm::function_ref<void(Instruction *)> Callback) {
53 if (Ends.size() == 1 && PDT.dominates(Ends[0], Start)) {
54 Callback(Ends[0]);
55 return true;
56 }
58 for (auto *End : Ends) {
59 EndBlocks.insert(End->getParent());
60 }
61 SmallVector<Instruction *, 8> ReachableRetVec;
62 unsigned NumCoveredExits = 0;
63 for (auto *RI : RetVec) {
64 if (!isPotentiallyReachable(Start, RI, nullptr, &DT, &LI))
65 continue;
66 ReachableRetVec.push_back(RI);
67 // If there is an end in the same basic block as the return, we know for
68 // sure that the return is covered. Otherwise, we can check whether there
69 // is a way to reach the RI from the start of the lifetime without passing
70 // through an end.
71 if (EndBlocks.contains(RI->getParent()) ||
72 !isPotentiallyReachable(Start, RI, &EndBlocks, &DT, &LI)) {
73 ++NumCoveredExits;
74 }
75 }
76 if (NumCoveredExits == ReachableRetVec.size()) {
77 for_each(Ends, Callback);
78 } else {
79 // If there's a mix of covered and non-covered exits, just put the untag
80 // on exits, so we avoid the redundancy of untagging twice.
81 for_each(ReachableRetVec, Callback);
82 // We may have inserted untag outside of the lifetime interval.
83 // Signal the caller to remove the lifetime end call for this alloca.
84 return false;
85 }
86 return true;
87}
88
90 const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd,
91 const DominatorTree *DT, const LoopInfo *LI,
92 size_t MaxLifetimes) {
93 // An alloca that has exactly one start and end in every possible execution.
94 // If it has multiple ends, they have to be unreachable from each other, so
95 // at most one of them is actually used for each execution of the function.
96 return LifetimeStart.size() == 1 &&
97 (LifetimeEnd.size() == 1 ||
98 (LifetimeEnd.size() > 0 &&
99 !maybeReachableFromEachOther(LifetimeEnd, DT, LI, MaxLifetimes)));
100}
101
103 if (isa<ReturnInst>(Inst)) {
104 if (CallInst *CI = Inst.getParent()->getTerminatingMustTailCall())
105 return CI;
106 return &Inst;
107 }
108 if (isa<ResumeInst, CleanupReturnInst>(Inst)) {
109 return &Inst;
110 }
111 return nullptr;
112}
113
115 Instruction &Inst) {
116 // Visit non-intrinsic debug-info records attached to Inst.
118 auto AddIfInteresting = [&](Value *V) {
119 if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
120 if (getAllocaInterestingness(*AI) !=
122 return;
123 AllocaInfo &AInfo = Info.AllocasToInstrument[AI];
124 auto &DVRVec = AInfo.DbgVariableRecords;
125 if (DVRVec.empty() || DVRVec.back() != &DVR)
126 DVRVec.push_back(&DVR);
127 }
128 };
129
130 for_each(DVR.location_ops(), AddIfInteresting);
131 if (DVR.isDbgAssign())
132 AddIfInteresting(DVR.getAddress());
133 }
134
135 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
136 if (CI->canReturnTwice()) {
137 Info.CallsReturnTwice = true;
138 }
139 }
140 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
141 switch (getAllocaInterestingness(*AI)) {
143 Info.AllocasToInstrument[AI].AI = AI;
144 ORE.emit([&]() {
145 return OptimizationRemarkMissed(DebugType, "safeAlloca", &Inst);
146 });
147 break;
149 ORE.emit(
150 [&]() { return OptimizationRemark(DebugType, "safeAlloca", &Inst); });
151 break;
153 break;
154 }
155 return;
156 }
157 auto *II = dyn_cast<IntrinsicInst>(&Inst);
158 if (II && (II->getIntrinsicID() == Intrinsic::lifetime_start ||
159 II->getIntrinsicID() == Intrinsic::lifetime_end)) {
160 AllocaInst *AI = findAllocaForValue(II->getArgOperand(1));
161 if (!AI) {
162 Info.UnrecognizedLifetimes.push_back(&Inst);
163 return;
164 }
166 return;
167 if (II->getIntrinsicID() == Intrinsic::lifetime_start)
168 Info.AllocasToInstrument[AI].LifetimeStart.push_back(II);
169 else
170 Info.AllocasToInstrument[AI].LifetimeEnd.push_back(II);
171 return;
172 }
173 if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst)) {
174 auto AddIfInteresting = [&](Value *V) {
175 if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
176 if (getAllocaInterestingness(*AI) !=
178 return;
179 AllocaInfo &AInfo = Info.AllocasToInstrument[AI];
180 auto &DVIVec = AInfo.DbgVariableIntrinsics;
181 if (DVIVec.empty() || DVIVec.back() != DVI)
182 DVIVec.push_back(DVI);
183 }
184 };
185 for_each(DVI->location_ops(), AddIfInteresting);
186 if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
187 AddIfInteresting(DAI->getAddress());
188 }
189
191 if (ExitUntag)
192 Info.RetVec.push_back(ExitUntag);
193}
194
197 if (AI.getAllocatedType()->isSized() &&
198 // FIXME: support vscale.
200 // FIXME: instrument dynamic allocas, too
201 AI.isStaticAlloca() &&
202 // alloca() may be called with 0 size, ignore it.
204 // We are only interested in allocas not promotable to registers.
205 // Promotable allocas are common under -O0.
206 !isAllocaPromotable(&AI) &&
207 // inalloca allocas are not treated as static, and we don't want
208 // dynamic alloca instrumentation for them as well.
209 !AI.isUsedWithInAlloca() &&
210 // swifterror allocas are register promoted by ISel
211 !AI.isSwiftError()) {
212 if (!(SSI && SSI->isSafe(AI))) {
214 }
215 // safe allocas are not interesting
217 }
219}
220
222 auto DL = AI.getDataLayout();
223 return *AI.getAllocationSize(DL);
224}
225
227 const Align NewAlignment = std::max(Info.AI->getAlign(), Alignment);
228 Info.AI->setAlignment(NewAlignment);
229 auto &Ctx = Info.AI->getFunction()->getContext();
230
232 uint64_t AlignedSize = alignTo(Size, Alignment);
233 if (Size == AlignedSize)
234 return;
235
236 // Add padding to the alloca.
237 Type *AllocatedType =
238 Info.AI->isArrayAllocation()
240 Info.AI->getAllocatedType(),
241 cast<ConstantInt>(Info.AI->getArraySize())->getZExtValue())
242 : Info.AI->getAllocatedType();
243 Type *PaddingType = ArrayType::get(Type::getInt8Ty(Ctx), AlignedSize - Size);
244 Type *TypeWithPadding = StructType::get(AllocatedType, PaddingType);
245 auto *NewAI = new AllocaInst(TypeWithPadding, Info.AI->getAddressSpace(),
246 nullptr, "", Info.AI->getIterator());
247 NewAI->takeName(Info.AI);
248 NewAI->setAlignment(Info.AI->getAlign());
249 NewAI->setUsedWithInAlloca(Info.AI->isUsedWithInAlloca());
250 NewAI->setSwiftError(Info.AI->isSwiftError());
251 NewAI->copyMetadata(*Info.AI);
252
253 Value *NewPtr = NewAI;
254
255 // TODO: Remove when typed pointers dropped
256 if (Info.AI->getType() != NewAI->getType())
257 NewPtr = new BitCastInst(NewAI, Info.AI->getType(), "", Info.AI->getIterator());
258
259 Info.AI->replaceAllUsesWith(NewPtr);
260 Info.AI->eraseFromParent();
261 Info.AI = NewAI;
262}
263
265 auto *II = dyn_cast<IntrinsicInst>(V);
266 return II && II->isLifetimeStartOrEnd();
267}
268
270 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
271 MDNode *MD =
272 MDNode::get(M->getContext(), {MDString::get(M->getContext(), Name)});
273 Value *Args[] = {MetadataAsValue::get(M->getContext(), MD)};
274 return IRB.CreateIntrinsic(Intrinsic::read_register,
275 IRB.getIntPtrTy(M->getDataLayout()), Args);
276}
277
278Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB) {
279 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
280 if (TargetTriple.getArch() == Triple::aarch64)
281 return memtag::readRegister(IRB, "pc");
282 return IRB.CreatePtrToInt(IRB.GetInsertBlock()->getParent(),
283 IRB.getIntPtrTy(M->getDataLayout()));
284}
285
288 Module *M = F->getParent();
289 return IRB.CreatePtrToInt(
290 IRB.CreateIntrinsic(Intrinsic::frameaddress,
291 IRB.getPtrTy(M->getDataLayout().getAllocaAddrSpace()),
292 {Constant::getNullValue(IRB.getInt32Ty())}),
293 IRB.getIntPtrTy(M->getDataLayout()));
294}
295
297 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
298 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
299 // in Bionic's libc/private/bionic_tls.h.
300 Function *ThreadPointerFunc =
301 Intrinsic::getOrInsertDeclaration(M, Intrinsic::thread_pointer);
302 return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
303 IRB.CreateCall(ThreadPointerFunc), 8 * Slot);
304}
305
307 return dyn_cast<DbgAssignIntrinsic>(DVI);
308}
309
311 return DVR->isDbgAssign() ? DVR : nullptr;
312}
313
315 // Helper utility for adding DW_OP_LLVM_tag_offset to debug-info records,
316 // abstracted over whether they're intrinsic-stored or DbgVariableRecord
317 // stored.
318 auto AnnotateDbgRecord = [&](auto *DPtr) {
319 // Prepend "tag_offset, N" to the dwarf expression.
320 // Tag offset logically applies to the alloca pointer, and it makes sense
321 // to put it at the beginning of the expression.
323 for (size_t LocNo = 0; LocNo < DPtr->getNumVariableLocationOps(); ++LocNo)
324 if (DPtr->getVariableLocationOp(LocNo) == Info.AI)
325 DPtr->setExpression(
326 DIExpression::appendOpsToArg(DPtr->getExpression(), NewOps, LocNo));
327 if (auto *DAI = DynCastToDbgAssign(DPtr)) {
328 if (DAI->getAddress() == Info.AI)
329 DAI->setAddressExpression(
330 DIExpression::prependOpcodes(DAI->getAddressExpression(), NewOps));
331 }
332 };
333
334 llvm::for_each(Info.DbgVariableIntrinsics, AnnotateDbgRecord);
335 llvm::for_each(Info.DbgVariableRecords, AnnotateDbgRecord);
336}
337
339 unsigned int Inc) {
340 // Update the ring buffer. Top byte of ThreadLong defines the size of the
341 // buffer in pages, it must be a power of two, and the start of the buffer
342 // must be aligned by twice that much. Therefore wrap around of the ring
343 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
344 // The use of AShr instead of LShr is due to
345 // https://bugs.llvm.org/show_bug.cgi?id=39030
346 // Runtime library makes sure not to use the highest bit.
347 //
348 // Mechanical proof of this address calculation can be found at:
349 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/prove_hwasanwrap.smt2
350 //
351 // Example of the wrap case for N = 1
352 // Pointer: 0x01AAAAAAAAAAAFF8
353 // +
354 // 0x0000000000000008
355 // =
356 // 0x01AAAAAAAAAAB000
357 // &
358 // WrapMask: 0xFFFFFFFFFFFFF000
359 // =
360 // 0x01AAAAAAAAAAA000
361 //
362 // Then the WrapMask will be a no-op until the next wrap case.
363 assert((4096 % Inc) == 0);
364 Value *WrapMask = IRB.CreateXor(
365 IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true),
366 ConstantInt::get(ThreadLong->getType(), (uint64_t)-1));
367 return IRB.CreateAnd(
368 IRB.CreateAdd(ThreadLong, ConstantInt::get(ThreadLong->getType(), Inc)),
369 WrapMask);
370}
371
372} // namespace memtag
373} // namespace llvm
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
This file contains constants used for implementing Dwarf debug support.
std::string Name
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
an instruction to allocate memory on the stack
Definition: Instructions.h:63
bool isSwiftError() const
Return true if this alloca is used as a swifterror argument to a call.
Definition: Instructions.h:149
bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
Definition: Instructions.h:117
bool isUsedWithInAlloca() const
Return true if this alloca is used as an inalloca argument to a call.
Definition: Instructions.h:139
std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:219
This class represents a no-op cast from one type to another.
This class represents a function call, abstracting a target machine's calling convention.
static DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
static DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)
Prepend DIExpr with the given opcodes and optionally turn it into a stack value.
This represents the llvm.dbg.assign instruction.
This is the common base class for debug info intrinsics for variables.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:162
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:656
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Definition: IRBuilder.h:1902
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:890
IntegerType * getIntPtrTy(const DataLayout &DL, unsigned AddrSpace=0)
Fetch the type of an integer with size at least as big as that of a pointer in the given address spac...
Definition: IRBuilder.h:572
BasicBlock * GetInsertBlock() const
Definition: IRBuilder.h:171
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1439
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1498
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1350
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2145
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2444
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition: IRBuilder.h:566
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition: IRBuilder.h:1479
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1542
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Definition: IRBuilder.h:513
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
iterator_range< simple_ilist< DbgRecord >::iterator > getDbgRecordRange() const
Return a range over the DbgRecords attached to this instruction.
Definition: Instruction.h:104
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Definition: Instruction.cpp:76
Metadata node.
Definition: Metadata.h:1069
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1543
static MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition: Metadata.cpp:103
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
The optimization diagnostic interface.
void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for missed-optimization remarks.
Diagnostic information for applied optimization remarks.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:384
bool contains(ConstPtrType Ptr) const
Definition: SmallPtrSet.h:458
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:519
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
bool isSafe(const AllocaInst &AI) const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition: Type.cpp:406
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition: Triple.h:383
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:310
bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
static IntegerType * getInt8Ty(LLVMContext &C)
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition: ilist_node.h:32
void visit(OptimizationRemarkEmitter &ORE, Instruction &Inst)
AllocaInterestingness getAllocaInterestingness(const AllocaInst &AI)
Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
Definition: Intrinsics.cpp:731
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
Definition: Dwarf.h:144
static DbgAssignIntrinsic * DynCastToDbgAssign(DbgVariableIntrinsic *DVI)
Value * getFP(IRBuilder<> &IRB)
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
Value * readRegister(IRBuilder<> &IRB, StringRef Name)
Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc)
void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
Instruction * getUntagLocationIfFunctionExit(Instruction &Inst)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
bool isLifetimeIntrinsic(Value *V)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1732
AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
Definition: CFG.cpp:281
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
SmallVector< DbgVariableIntrinsic *, 2 > DbgVariableIntrinsics
SmallVector< DbgVariableRecord *, 2 > DbgVariableRecords
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 4 > UnrecognizedLifetimes
SmallVector< Instruction *, 8 > RetVec