LLVM 23.0.0git
CodeViewDebug.h
Go to the documentation of this file.
1//===- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains support for writing Microsoft CodeView debug info.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
14#define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
15
16#include "llvm/ADT/APSInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/DenseSet.h"
20#include "llvm/ADT/MapVector.h"
22#include "llvm/ADT/SetVector.h"
23#include "llvm/ADT/SmallSet.h"
31#include "llvm/IR/DebugLoc.h"
34#include <cstdint>
35#include <map>
36#include <string>
37#include <tuple>
38#include <unordered_map>
39#include <utility>
40#include <vector>
41
42namespace llvm {
43
44struct ClassInfo;
45class StringRef;
46class AsmPrinter;
47class Function;
48class GlobalVariable;
49class MCSectionCOFF;
50class MCStreamer;
51class MCSymbol;
52class MachineFunction;
53
54/// Collects and handles line tables information in a CodeView format.
56public:
57 struct LocalVarDef {
58 /// Indicates that variable data is stored in memory relative to the
59 /// specified register.
60 int InMemory : 1;
61
62 /// Offset of variable data in memory.
63 int DataOffset : 31;
64
65 /// Non-zero if this is a piece of an aggregate.
67
68 /// Offset into aggregate.
70
71 /// Register containing the data or the register base of the memory
72 /// location containing the data.
74
75 /// Value for `DerefOffset` indicating this is not an indirect load.
76 constexpr static int32_t NoDeref = INT32_MIN;
77
78 /// Offset to add after dereferencing `CVRegister + DataOffset` for
79 /// indirect loads. If this is not an indirect load, it's set to NoDeref.
81
84 std::memset(&V, 0xff, sizeof(LocalVarDef));
85 return V;
86 }
87
88 unsigned hashValue() const {
89 uint64_t H = 0;
90 std::memcpy(&H, this, sizeof(uint64_t));
91 static_assert(sizeof(LocalVarDef) == 8 + 4 &&
94 return H;
95 }
96
97 bool operator==(const LocalVarDef &Other) const {
98 return InMemory == Other.InMemory && DataOffset == Other.DataOffset &&
99 IsSubfield == Other.IsSubfield &&
100 StructOffset == Other.StructOffset &&
101 CVRegister == Other.CVRegister && DerefOffset == Other.DerefOffset;
102 }
103 };
104
105private:
106 MCStreamer &OS;
109
110 /// Whether to emit type record hashes into .debug$H.
111 bool EmitDebugGlobalHashes = false;
112
113 /// The codeview CPU type used by the translation unit.
114 codeview::CPUType TheCPU;
115
116 const DICompileUnit *TheCU = nullptr;
117
118 /// The AsmPrinter used for emitting compiler metadata. When only compiler
119 /// info is being emitted, DebugHandlerBase::Asm may be null.
120 AsmPrinter *CompilerInfoAsm = nullptr;
121
122 static LocalVarDef createDefRangeMem(uint16_t CVRegister, int Offset,
123 int32_t DerefOffset);
124
125 /// Similar to DbgVariable in DwarfDebug, but not dwarf-specific.
126 struct LocalVariable {
127 const DILocalVariable *DIVar = nullptr;
128 MapVector<LocalVarDef,
130 DefRanges;
131 std::optional<APSInt> ConstantValue;
132 };
133
134 struct CVGlobalVariable {
135 const DIGlobalVariable *DIGV;
136 PointerUnion<const GlobalVariable *, const DIExpression *> GVInfo;
137 };
138
139 struct InlineSite {
140 SmallVector<LocalVariable, 1> InlinedLocals;
141 SmallVector<const DILocation *, 1> ChildSites;
142 const DISubprogram *Inlinee = nullptr;
143
144 /// The ID of the inline site or function used with .cv_loc. Not a type
145 /// index.
146 unsigned SiteFuncId = 0;
147 };
148
149 // Combines information from DILexicalBlock and LexicalScope.
150 struct LexicalBlock {
151 SmallVector<LocalVariable, 1> Locals;
152 SmallVector<CVGlobalVariable, 1> Globals;
153 SmallVector<LexicalBlock *, 1> Children;
154 const MCSymbol *Begin;
155 const MCSymbol *End;
156 StringRef Name;
157 };
158
159 struct JumpTableInfo {
160 codeview::JumpTableEntrySize EntrySize;
161 const MCSymbol *Base;
162 uint64_t BaseOffset;
163 const MCSymbol *Branch;
164 const MCSymbol *Table;
165 size_t TableSize;
166 std::vector<const MCSymbol *> Cases;
167 };
168
169 // For each function, store a vector of labels to its instructions, as well as
170 // to the end of the function.
171 struct FunctionInfo {
172 FunctionInfo() = default;
173
174 // Uncopyable.
175 FunctionInfo(const FunctionInfo &FI) = delete;
176
177 /// Map from inlined call site to inlined instructions and child inlined
178 /// call sites. Listed in program order.
179 std::unordered_map<const DILocation *, InlineSite> InlineSites;
180
181 /// Ordered list of top-level inlined call sites.
182 SmallVector<const DILocation *, 1> ChildSites;
183
184 /// Set of all functions directly inlined into this one.
185 SmallSet<codeview::TypeIndex, 1> Inlinees;
186
187 SmallVector<LocalVariable, 1> Locals;
188 SmallVector<CVGlobalVariable, 1> Globals;
189
190 std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks;
191
192 // Lexical blocks containing local variables.
193 SmallVector<LexicalBlock *, 1> ChildBlocks;
194
195 std::vector<std::pair<MCSymbol *, MDNode *>> Annotations;
196 std::vector<std::tuple<const MCSymbol *, const MCSymbol *, const DIType *>>
197 HeapAllocSites;
198
199 std::vector<JumpTableInfo> JumpTables;
200
201 const MCSymbol *Begin = nullptr;
202 const MCSymbol *End = nullptr;
203 unsigned FuncId = 0;
204 unsigned LastFileId = 0;
205
206 /// Number of bytes allocated in the prologue for all local stack objects.
207 unsigned FrameSize = 0;
208
209 /// Number of bytes of parameters on the stack.
210 unsigned ParamSize = 0;
211
212 /// Number of bytes pushed to save CSRs.
213 unsigned CSRSize = 0;
214
215 /// Adjustment to apply on x86 when using the VFRAME frame pointer.
216 int OffsetAdjustment = 0;
217
218 /// Two-bit value indicating which register is the designated frame pointer
219 /// register for local variables. Included in S_FRAMEPROC.
220 codeview::EncodedFramePtrReg EncodedLocalFramePtrReg =
221 codeview::EncodedFramePtrReg::None;
222
223 /// Two-bit value indicating which register is the designated frame pointer
224 /// register for stack parameters. Included in S_FRAMEPROC.
225 codeview::EncodedFramePtrReg EncodedParamFramePtrReg =
226 codeview::EncodedFramePtrReg::None;
227
228 codeview::FrameProcedureOptions FrameProcOpts;
229
230 bool HasStackRealignment = false;
231
232 bool HaveLineInfo = false;
233
234 bool HasFramePointer = false;
235 };
236 FunctionInfo *CurFn = nullptr;
237
238 codeview::SourceLanguage CurrentSourceLanguage =
239 codeview::SourceLanguage::Masm;
240
241 // This map records the constant offset in DIExpression of the
242 // DIGlobalVariableExpression referencing the DIGlobalVariable.
243 DenseMap<const DIGlobalVariable *, uint64_t> CVGlobalVariableOffsets;
244
245 // Map used to separate variables according to the lexical scope they belong
246 // in. This is populated by recordLocalVariable() before
247 // collectLexicalBlocks() separates the variables between the FunctionInfo
248 // and LexicalBlocks.
249 DenseMap<const LexicalScope *, SmallVector<LocalVariable, 1>> ScopeVariables;
250
251 // Map to separate global variables according to the lexical scope they
252 // belong in. A null local scope represents the global scope.
253 typedef SmallVector<CVGlobalVariable, 1> GlobalVariableList;
254 DenseMap<const DIScope*, std::unique_ptr<GlobalVariableList> > ScopeGlobals;
255
256 // Array of global variables which need to be emitted into a COMDAT section.
257 SmallVector<CVGlobalVariable, 1> ComdatVariables;
258
259 // Array of non-COMDAT global variables.
260 SmallVector<CVGlobalVariable, 1> GlobalVariables;
261
262 /// List of static const data members to be emitted as S_CONSTANTs.
263 SmallVector<const DIDerivedType *, 4> StaticConstMembers;
264
265 /// The set of comdat .debug$S sections that we've seen so far. Each section
266 /// must start with a magic version number that must only be emitted once.
267 /// This set tracks which sections we've already opened.
268 DenseSet<MCSectionCOFF *> ComdatDebugSections;
269
270 /// Switch to the appropriate .debug$S section for GVSym. If GVSym, the symbol
271 /// of an emitted global value, is in a comdat COFF section, this will switch
272 /// to a new .debug$S section in that comdat. This method ensures that the
273 /// section starts with the magic version number on first use. If GVSym is
274 /// null, uses the main .debug$S section.
275 void switchToDebugSectionForSymbol(const MCSymbol *GVSym);
276
277 /// The next available function index for use with our .cv_* directives. Not
278 /// to be confused with type indices for LF_FUNC_ID records.
279 unsigned NextFuncId = 0;
280
281 InlineSite &getInlineSite(const DILocation *InlinedAt,
282 const DISubprogram *Inlinee);
283
284 codeview::TypeIndex getFuncIdForSubprogram(const DISubprogram *SP);
285
286 void calculateRanges(LocalVariable &Var,
287 const DbgValueHistoryMap::Entries &Entries);
288
289 /// Remember some debug info about each function. Keep it in a stable order to
290 /// emit at the end of the TU.
291 MapVector<const Function *, std::unique_ptr<FunctionInfo>> FnDebugInfo;
292
293 /// Map from full file path to .cv_file id. Full paths are built from DIFiles
294 /// and are stored in FileToFilepathMap;
295 DenseMap<StringRef, unsigned> FileIdMap;
296
297 /// All inlined subprograms in the order they should be emitted.
298 SmallSetVector<const DISubprogram *, 4> InlinedSubprograms;
299
300 /// Map from a pair of DI metadata nodes and its DI type (or scope) that can
301 /// be nullptr, to CodeView type indices. Primarily indexed by
302 /// {DIType*, DIType*} and {DISubprogram*, DIType*}.
303 ///
304 /// The second entry in the key is needed for methods as DISubroutineType
305 /// representing static method type are shared with non-method function type.
306 DenseMap<std::pair<const DINode *, const DIType *>, codeview::TypeIndex>
307 TypeIndices;
308
309 /// Map from DICompositeType* to complete type index. Non-record types are
310 /// always looked up in the normal TypeIndices map.
311 DenseMap<const DICompositeType *, codeview::TypeIndex> CompleteTypeIndices;
312
313 /// Complete record types to emit after all active type lowerings are
314 /// finished.
315 SmallVector<const DICompositeType *, 4> DeferredCompleteTypes;
316
317 /// Number of type lowering frames active on the stack.
318 unsigned TypeEmissionLevel = 0;
319
320 codeview::TypeIndex VBPType;
321
322 const DISubprogram *CurrentSubprogram = nullptr;
323
324 // The UDTs we have seen while processing types; each entry is a pair of type
325 // index and type name.
326 std::vector<std::pair<std::string, const DIType *>> LocalUDTs;
327 std::vector<std::pair<std::string, const DIType *>> GlobalUDTs;
328
329 using FileToFilepathMapTy = std::map<const DIFile *, std::string>;
330 FileToFilepathMapTy FileToFilepathMap;
331
332 StringRef getFullFilepath(const DIFile *File);
333
334 unsigned maybeRecordFile(const DIFile *F);
335
336 void maybeRecordLocation(const DebugLoc &DL, const MachineFunction *MF);
337
338 void clear();
339
340 void setCurrentSubprogram(const DISubprogram *SP) {
341 CurrentSubprogram = SP;
342 LocalUDTs.clear();
343 }
344
345 /// Emit the magic version number at the start of a CodeView type or symbol
346 /// section. Appears at the front of every .debug$S or .debug$T or .debug$P
347 /// section.
348 void emitCodeViewMagicVersion();
349
350 void emitTypeInformation();
351
352 void emitTypeGlobalHashes();
353
354 void emitObjName();
355
356 void emitCompilerInformation();
357
358 void emitSecureHotPatchInformation();
359
360 void emitBuildInfo();
361
362 void emitInlineeLinesSubsection();
363
364 void emitDebugInfoForThunk(const Function *GV,
365 FunctionInfo &FI,
366 const MCSymbol *Fn);
367
368 void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
369
370 void emitDebugInfoForRetainedTypes();
371
372 void emitDebugInfoForUDTs(
373 const std::vector<std::pair<std::string, const DIType *>> &UDTs);
374
375 void collectDebugInfoForGlobals();
376 void emitDebugInfoForGlobals();
377 void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals);
378 void emitConstantSymbolRecord(const DIType *DTy, APSInt &Value,
379 const std::string &QualifiedName);
380 void emitDebugInfoForGlobal(const CVGlobalVariable &CVGV);
381 void emitStaticConstMemberList();
382
383 /// Opens a subsection of the given kind in a .debug$S codeview section.
384 /// Returns an end label for use with endCVSubsection when the subsection is
385 /// finished.
386 MCSymbol *beginCVSubsection(codeview::DebugSubsectionKind Kind);
387 void endCVSubsection(MCSymbol *EndLabel);
388
389 /// Opens a symbol record of the given kind. Returns an end label for use with
390 /// endSymbolRecord.
391 MCSymbol *beginSymbolRecord(codeview::SymbolKind Kind);
392 void endSymbolRecord(MCSymbol *SymEnd);
393
394 /// Emits an S_END, S_INLINESITE_END, or S_PROC_ID_END record. These records
395 /// are empty, so we emit them with a simpler assembly sequence that doesn't
396 /// involve labels.
397 void emitEndSymbolRecord(codeview::SymbolKind EndKind);
398
399 void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
400 const InlineSite &Site);
401
402 void emitInlinees(const SmallSet<codeview::TypeIndex, 1> &Inlinees);
403
404 using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
405
406 void collectGlobalVariableInfo();
407 void collectVariableInfo(const DISubprogram *SP);
408
409 void collectVariableInfoFromMFTable(DenseSet<InlinedEntity> &Processed);
410
411 // Construct the lexical block tree for a routine, pruning emptpy lexical
412 // scopes, and populate it with local variables.
413 void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes,
414 SmallVectorImpl<LexicalBlock *> &Blocks,
415 SmallVectorImpl<LocalVariable> &Locals,
416 SmallVectorImpl<CVGlobalVariable> &Globals);
417 void collectLexicalBlockInfo(LexicalScope &Scope,
418 SmallVectorImpl<LexicalBlock *> &ParentBlocks,
419 SmallVectorImpl<LocalVariable> &ParentLocals,
420 SmallVectorImpl<CVGlobalVariable> &ParentGlobals);
421
422 /// Records information about a local variable in the appropriate scope. In
423 /// particular, locals from inlined code live inside the inlining site.
424 void recordLocalVariable(LocalVariable &&Var, const LexicalScope *LS);
425
426 /// Emits local variables in the appropriate order.
427 void emitLocalVariableList(const FunctionInfo &FI,
428 ArrayRef<LocalVariable> Locals);
429
430 /// Emits an S_LOCAL record and its associated defined ranges.
431 void emitLocalVariable(const FunctionInfo &FI, const LocalVariable &Var);
432
433 /// Emits a sequence of lexical block scopes and their children.
434 void emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
435 const FunctionInfo& FI);
436
437 /// Emit a lexical block scope and its children.
438 void emitLexicalBlock(const LexicalBlock &Block, const FunctionInfo& FI);
439
440 /// Translates the DIType to codeview if necessary and returns a type index
441 /// for it.
442 codeview::TypeIndex getTypeIndex(const DIType *Ty,
443 const DIType *ClassTy = nullptr);
444
445 codeview::TypeIndex
446 getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
447 const DISubroutineType *SubroutineTy);
448
449 codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
450 const DICompositeType *Class);
451
452 codeview::TypeIndex getScopeIndex(const DIScope *Scope);
453
454 codeview::TypeIndex getVBPTypeIndex();
455
456 void addToUDTs(const DIType *Ty);
457
458 void addUDTSrcLine(const DIType *Ty, codeview::TypeIndex TI);
459
460 codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
461 codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
462 codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
463 codeview::TypeIndex lowerTypeString(const DIStringType *Ty);
464 codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty);
465 codeview::TypeIndex lowerTypePointer(
466 const DIDerivedType *Ty,
467 codeview::PointerOptions PO = codeview::PointerOptions::None);
468 codeview::TypeIndex lowerTypeMemberPointer(
469 const DIDerivedType *Ty,
470 codeview::PointerOptions PO = codeview::PointerOptions::None);
471 codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
472 codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
473 codeview::TypeIndex lowerTypeVFTableShape(const DIDerivedType *Ty);
474 codeview::TypeIndex lowerTypeMemberFunction(
475 const DISubroutineType *Ty, const DIType *ClassTy, int ThisAdjustment,
476 bool IsStaticMethod,
477 codeview::FunctionOptions FO = codeview::FunctionOptions::None);
478 codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty);
479 codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
480 codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
481
482 /// Symbol records should point to complete types, but type records should
483 /// always point to incomplete types to avoid cycles in the type graph. Only
484 /// use this entry point when generating symbol records. The complete and
485 /// incomplete type indices only differ for record types. All other types use
486 /// the same index.
487 codeview::TypeIndex getCompleteTypeIndex(const DIType *Ty);
488
489 codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
490 codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
491
492 struct TypeLoweringScope;
493
494 void emitDeferredCompleteTypes();
495
496 void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy);
497 ClassInfo collectClassInfo(const DICompositeType *Ty);
498
499 /// Common record member lowering functionality for record types, which are
500 /// structs, classes, and unions. Returns the field list index and the member
501 /// count.
502 std::tuple<codeview::TypeIndex, codeview::TypeIndex, unsigned, bool>
503 lowerRecordFieldList(const DICompositeType *Ty);
504
505 /// Inserts {{Node, ClassTy}, TI} into TypeIndices and checks for duplicates.
506 codeview::TypeIndex recordTypeIndexForDINode(const DINode *Node,
507 codeview::TypeIndex TI,
508 const DIType *ClassTy = nullptr);
509
510 /// Collect the names of parent scopes, innermost to outermost. Return the
511 /// innermost subprogram scope if present. Ensure that parent type scopes are
512 /// inserted into the type table.
513 const DISubprogram *
514 collectParentScopeNames(const DIScope *Scope,
515 SmallVectorImpl<StringRef> &ParentScopeNames);
516 std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name);
517 std::string getFullyQualifiedName(const DIScope *Scope);
518
519 unsigned getPointerSizeInBytes();
520
521 void discoverJumpTableBranches(const MachineFunction *MF, bool isThumb);
522 void collectDebugInfoForJumpTables(const MachineFunction *MF, bool isThumb);
523 void emitDebugInfoForJumpTables(const FunctionInfo &FI);
524
525protected:
526 /// Gather pre-function debug information.
527 void beginFunctionImpl(const MachineFunction *MF) override;
528
529 /// Gather post-function debug information.
530 void endFunctionImpl(const MachineFunction *) override;
531
532 /// Check if the current module is in Fortran.
534 return CurrentSourceLanguage == codeview::SourceLanguage::Fortran;
535 }
536
537public:
539
540 void beginModule(Module *M) override;
541
542 /// Emit the COFF section that holds the line table information.
543 void endModule() override;
544
545 /// Process beginning of an instruction.
546 void beginInstruction(const MachineInstr *MI) override;
547};
548
549template <> struct DenseMapInfo<CodeViewDebug::LocalVarDef> {
550
554
555 static unsigned getHashValue(const CodeViewDebug::LocalVarDef &DR) {
556 return DR.hashValue();
557 }
558
561 return LHS == RHS;
562 }
563};
564
565} // end namespace llvm
566
567#endif // LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
static bool isThumb(const MCSubtargetInfo &STI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file defines the BumpPtrAllocator interface.
#define LLVM_LIBRARY_VISIBILITY
Definition Compiler.h:137
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
IRTranslator LLVM IR MI
#define offsetof(TYPE, MEMBER)
#define F(x, y, z)
Definition MD5.cpp:54
#define H(x, y, z)
Definition MD5.cpp:56
This file implements a map that provides insertion order iteration.
This file defines the PointerUnion class, which is a discriminated union of pointer types.
Basic Register Allocator
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
This file defines the SmallVector class.
Value * RHS
Value * LHS
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
Collects and handles line tables information in a CodeView format.
CodeViewDebug(AsmPrinter *AP)
bool moduleIsInFortran()
Check if the current module is in Fortran.
This represents a section on Windows.
Streaming machine code generation interface.
Definition MCStreamer.h:222
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
Representation of each machine instruction.
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
CPUType
These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....
Definition CodeView.h:76
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
std::tuple< uint64_t, uint32_t > InlineSite
@ Other
Any other memory.
Definition ModRef.h:68
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:325
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
int DataOffset
Offset of variable data in memory.
uint32_t IsSubfield
Non-zero if this is a piece of an aggregate.
int InMemory
Indicates that variable data is stored in memory relative to the specified register.
int32_t DerefOffset
Offset to add after dereferencing CVRegister + DataOffset for indirect loads.
uint32_t StructOffset
Offset into aggregate.
bool operator==(const LocalVarDef &Other) const
uint32_t CVRegister
Register containing the data or the register base of the memory location containing the data.
static LocalVarDef emptyValue()
static constexpr int32_t NoDeref
Value for DerefOffset indicating this is not an indirect load.
static bool isEqual(const CodeViewDebug::LocalVarDef &LHS, const CodeViewDebug::LocalVarDef &RHS)
static CodeViewDebug::LocalVarDef getEmptyKey()
static unsigned getHashValue(const CodeViewDebug::LocalVarDef &DR)
An information struct used to provide DenseMap with the various necessary components for a given valu...