170f5bc99SReid Kleckner //===-- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h ----*- C++ -*--===// 270f5bc99SReid Kleckner // 370f5bc99SReid Kleckner // The LLVM Compiler Infrastructure 470f5bc99SReid Kleckner // 570f5bc99SReid Kleckner // This file is distributed under the University of Illinois Open Source 670f5bc99SReid Kleckner // License. See LICENSE.TXT for details. 770f5bc99SReid Kleckner // 870f5bc99SReid Kleckner //===----------------------------------------------------------------------===// 970f5bc99SReid Kleckner // 1070f5bc99SReid Kleckner // This file contains support for writing Microsoft CodeView debug info. 1170f5bc99SReid Kleckner // 1270f5bc99SReid Kleckner //===----------------------------------------------------------------------===// 1370f5bc99SReid Kleckner 1470f5bc99SReid Kleckner #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H 1570f5bc99SReid Kleckner #define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H 1670f5bc99SReid Kleckner 17f9c275feSReid Kleckner #include "DebugHandlerBase.h" 1870f5bc99SReid Kleckner #include "llvm/ADT/DenseMap.h" 1970f5bc99SReid Kleckner #include "llvm/ADT/StringMap.h" 2070f5bc99SReid Kleckner #include "llvm/CodeGen/AsmPrinter.h" 2170f5bc99SReid Kleckner #include "llvm/CodeGen/MachineFunction.h" 2270f5bc99SReid Kleckner #include "llvm/CodeGen/MachineModuleInfo.h" 232280f932SReid Kleckner #include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h" 24f3b9ba49SReid Kleckner #include "llvm/DebugInfo/CodeView/TypeIndex.h" 2570f5bc99SReid Kleckner #include "llvm/IR/DebugInfo.h" 2670f5bc99SReid Kleckner #include "llvm/IR/DebugLoc.h" 2770f5bc99SReid Kleckner #include "llvm/MC/MCStreamer.h" 2870f5bc99SReid Kleckner #include "llvm/Target/TargetLoweringObjectFile.h" 2970f5bc99SReid Kleckner 3070f5bc99SReid Kleckner namespace llvm { 31f9c275feSReid Kleckner 32b550cb17SMehdi Amini class StringRef; 33f9c275feSReid Kleckner class LexicalScope; 34f9c275feSReid Kleckner 3570f5bc99SReid Kleckner /// \brief Collects and handles line tables information in a CodeView format. 36f9c275feSReid Kleckner class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { 37dac21b43SReid Kleckner MCStreamer &OS; 382280f932SReid Kleckner codeview::MemoryTypeTableBuilder TypeTable; 39f9c275feSReid Kleckner 40876330d5SReid Kleckner /// Represents the most general definition range. 41876330d5SReid Kleckner struct LocalVarDefRange { 42876330d5SReid Kleckner /// Indicates that variable data is stored in memory relative to the 43876330d5SReid Kleckner /// specified register. 44876330d5SReid Kleckner int InMemory : 1; 45876330d5SReid Kleckner 46876330d5SReid Kleckner /// Offset of variable data in memory. 47876330d5SReid Kleckner int DataOffset : 31; 48876330d5SReid Kleckner 49876330d5SReid Kleckner /// Offset of the data into the user level struct. If zero, no splitting 50876330d5SReid Kleckner /// occurred. 51876330d5SReid Kleckner uint16_t StructOffset; 52876330d5SReid Kleckner 53876330d5SReid Kleckner /// Register containing the data or the register base of the memory 54876330d5SReid Kleckner /// location containing the data. 55876330d5SReid Kleckner uint16_t CVRegister; 56876330d5SReid Kleckner 57876330d5SReid Kleckner /// Compares all location fields. This includes all fields except the label 58876330d5SReid Kleckner /// ranges. 59876330d5SReid Kleckner bool isDifferentLocation(LocalVarDefRange &O) { 60876330d5SReid Kleckner return InMemory != O.InMemory || DataOffset != O.DataOffset || 61876330d5SReid Kleckner StructOffset != O.StructOffset || CVRegister != O.CVRegister; 62876330d5SReid Kleckner } 63876330d5SReid Kleckner 64876330d5SReid Kleckner SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 1> Ranges; 65876330d5SReid Kleckner }; 66876330d5SReid Kleckner 67876330d5SReid Kleckner static LocalVarDefRange createDefRangeMem(uint16_t CVRegister, int Offset); 68876330d5SReid Kleckner static LocalVarDefRange createDefRangeReg(uint16_t CVRegister); 69876330d5SReid Kleckner 70f9c275feSReid Kleckner /// Similar to DbgVariable in DwarfDebug, but not dwarf-specific. 71f9c275feSReid Kleckner struct LocalVariable { 72f9c275feSReid Kleckner const DILocalVariable *DIVar = nullptr; 73876330d5SReid Kleckner SmallVector<LocalVarDefRange, 1> DefRanges; 74f9c275feSReid Kleckner }; 7570f5bc99SReid Kleckner 76f3b9ba49SReid Kleckner struct InlineSite { 77f9c275feSReid Kleckner SmallVector<LocalVariable, 1> InlinedLocals; 78f9c275feSReid Kleckner SmallVector<const DILocation *, 1> ChildSites; 79f3b9ba49SReid Kleckner const DISubprogram *Inlinee = nullptr; 80f3b9ba49SReid Kleckner unsigned SiteFuncId = 0; 81f3b9ba49SReid Kleckner }; 82f3b9ba49SReid Kleckner 8370f5bc99SReid Kleckner // For each function, store a vector of labels to its instructions, as well as 8470f5bc99SReid Kleckner // to the end of the function. 8570f5bc99SReid Kleckner struct FunctionInfo { 86f3b9ba49SReid Kleckner /// Map from inlined call site to inlined instructions and child inlined 87f3b9ba49SReid Kleckner /// call sites. Listed in program order. 88f9c275feSReid Kleckner std::unordered_map<const DILocation *, InlineSite> InlineSites; 89f9c275feSReid Kleckner 90f9c275feSReid Kleckner /// Ordered list of top-level inlined call sites. 91f9c275feSReid Kleckner SmallVector<const DILocation *, 1> ChildSites; 92f9c275feSReid Kleckner 93f9c275feSReid Kleckner SmallVector<LocalVariable, 1> Locals; 94f3b9ba49SReid Kleckner 959533af4fSReid Kleckner DebugLoc LastLoc; 961fcd610cSReid Kleckner const MCSymbol *Begin = nullptr; 971fcd610cSReid Kleckner const MCSymbol *End = nullptr; 982214ed89SReid Kleckner unsigned FuncId = 0; 99f3b9ba49SReid Kleckner unsigned LastFileId = 0; 1002214ed89SReid Kleckner bool HaveLineInfo = false; 1019533af4fSReid Kleckner }; 1029533af4fSReid Kleckner FunctionInfo *CurFn; 10370f5bc99SReid Kleckner 1045d122f87SReid Kleckner /// The set of comdat .debug$S sections that we've seen so far. Each section 1055d122f87SReid Kleckner /// must start with a magic version number that must only be emitted once. 1065d122f87SReid Kleckner /// This set tracks which sections we've already opened. 1075d122f87SReid Kleckner DenseSet<MCSectionCOFF *> ComdatDebugSections; 1085d122f87SReid Kleckner 1095d122f87SReid Kleckner /// Switch to the appropriate .debug$S section for GVSym. If GVSym, the symbol 1105d122f87SReid Kleckner /// of an emitted global value, is in a comdat COFF section, this will switch 1115d122f87SReid Kleckner /// to a new .debug$S section in that comdat. This method ensures that the 1125d122f87SReid Kleckner /// section starts with the magic version number on first use. If GVSym is 1135d122f87SReid Kleckner /// null, uses the main .debug$S section. 1145d122f87SReid Kleckner void switchToDebugSectionForSymbol(const MCSymbol *GVSym); 1155d122f87SReid Kleckner 116fbd7787dSReid Kleckner /// The next available function index for use with our .cv_* directives. Not 117fbd7787dSReid Kleckner /// to be confused with type indices for LF_FUNC_ID records. 1182214ed89SReid Kleckner unsigned NextFuncId = 0; 11970f5bc99SReid Kleckner 120876330d5SReid Kleckner InlineSite &getInlineSite(const DILocation *InlinedAt, 121876330d5SReid Kleckner const DISubprogram *Inlinee); 122f3b9ba49SReid Kleckner 123*75c3ebfaSDavid Majnemer codeview::TypeIndex getFuncIdForSubprogram(const DISubprogram *SP); 1242280f932SReid Kleckner 1251fcd610cSReid Kleckner static void collectInlineSiteChildren(SmallVectorImpl<unsigned> &Children, 1261fcd610cSReid Kleckner const FunctionInfo &FI, 1271fcd610cSReid Kleckner const InlineSite &Site); 1281fcd610cSReid Kleckner 1292214ed89SReid Kleckner /// Remember some debug info about each function. Keep it in a stable order to 1302214ed89SReid Kleckner /// emit at the end of the TU. 1312214ed89SReid Kleckner MapVector<const Function *, FunctionInfo> FnDebugInfo; 13270f5bc99SReid Kleckner 1332214ed89SReid Kleckner /// Map from DIFile to .cv_file id. 1342214ed89SReid Kleckner DenseMap<const DIFile *, unsigned> FileIdMap; 13570f5bc99SReid Kleckner 136fbd7787dSReid Kleckner /// All inlined subprograms in the order they should be emitted. 1372280f932SReid Kleckner SmallSetVector<const DISubprogram *, 4> InlinedSubprograms; 138f3b9ba49SReid Kleckner 1392280f932SReid Kleckner /// Map from DI metadata nodes to CodeView type indices. Primarily indexed by 1402280f932SReid Kleckner /// DIType* and DISubprogram*. 1412280f932SReid Kleckner DenseMap<const DINode *, codeview::TypeIndex> TypeIndices; 142f3b9ba49SReid Kleckner 1439533af4fSReid Kleckner typedef std::map<const DIFile *, std::string> FileToFilepathMapTy; 1449533af4fSReid Kleckner FileToFilepathMapTy FileToFilepathMap; 1459533af4fSReid Kleckner StringRef getFullFilepath(const DIFile *S); 14670f5bc99SReid Kleckner 1472214ed89SReid Kleckner unsigned maybeRecordFile(const DIFile *F); 1482214ed89SReid Kleckner 14970f5bc99SReid Kleckner void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF); 15070f5bc99SReid Kleckner 15170f5bc99SReid Kleckner void clear() { 15270f5bc99SReid Kleckner assert(CurFn == nullptr); 1532214ed89SReid Kleckner FileIdMap.clear(); 1542214ed89SReid Kleckner FnDebugInfo.clear(); 1552214ed89SReid Kleckner FileToFilepathMap.clear(); 15670f5bc99SReid Kleckner } 15770f5bc99SReid Kleckner 1585d122f87SReid Kleckner /// Emit the magic version number at the start of a CodeView type or symbol 1595d122f87SReid Kleckner /// section. Appears at the front of every .debug$S or .debug$T section. 1605d122f87SReid Kleckner void emitCodeViewMagicVersion(); 1615d122f87SReid Kleckner 162f3b9ba49SReid Kleckner void emitTypeInformation(); 163f3b9ba49SReid Kleckner 1645d122f87SReid Kleckner void emitInlineeLinesSubsection(); 1651fcd610cSReid Kleckner 1662214ed89SReid Kleckner void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI); 16770f5bc99SReid Kleckner 168f3b9ba49SReid Kleckner void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt, 169f3b9ba49SReid Kleckner const InlineSite &Site); 170f3b9ba49SReid Kleckner 171876330d5SReid Kleckner typedef DbgValueHistoryMap::InlinedVariable InlinedVariable; 172876330d5SReid Kleckner 173876330d5SReid Kleckner void collectVariableInfo(const DISubprogram *SP); 174876330d5SReid Kleckner 175876330d5SReid Kleckner void collectVariableInfoFromMMITable(DenseSet<InlinedVariable> &Processed); 176876330d5SReid Kleckner 177876330d5SReid Kleckner /// Records information about a local variable in the appropriate scope. In 178876330d5SReid Kleckner /// particular, locals from inlined code live inside the inlining site. 179876330d5SReid Kleckner void recordLocalVariable(LocalVariable &&Var, const DILocation *Loc); 180f9c275feSReid Kleckner 181f9c275feSReid Kleckner void emitLocalVariable(const LocalVariable &Var); 182f9c275feSReid Kleckner 1835acacbb0SReid Kleckner /// Translates the DIType to codeview if necessary and returns a type index 1845acacbb0SReid Kleckner /// for it. 1855acacbb0SReid Kleckner codeview::TypeIndex getTypeIndex(DITypeRef Ty); 1865acacbb0SReid Kleckner 1875acacbb0SReid Kleckner codeview::TypeIndex lowerType(const DIType *Ty); 188d065e23dSDavid Majnemer codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty); 1895acacbb0SReid Kleckner codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty); 1905acacbb0SReid Kleckner codeview::TypeIndex lowerTypePointer(const DIDerivedType *Ty); 1915acacbb0SReid Kleckner codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty); 1925acacbb0SReid Kleckner codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty); 193*75c3ebfaSDavid Majnemer codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty); 1945acacbb0SReid Kleckner 19570f5bc99SReid Kleckner public: 19670f5bc99SReid Kleckner CodeViewDebug(AsmPrinter *Asm); 19770f5bc99SReid Kleckner 19870f5bc99SReid Kleckner void setSymbolSize(const llvm::MCSymbol *, uint64_t) override {} 19970f5bc99SReid Kleckner 20070f5bc99SReid Kleckner /// \brief Emit the COFF section that holds the line table information. 20170f5bc99SReid Kleckner void endModule() override; 20270f5bc99SReid Kleckner 20370f5bc99SReid Kleckner /// \brief Gather pre-function debug information. 20470f5bc99SReid Kleckner void beginFunction(const MachineFunction *MF) override; 20570f5bc99SReid Kleckner 20670f5bc99SReid Kleckner /// \brief Gather post-function debug information. 20770f5bc99SReid Kleckner void endFunction(const MachineFunction *) override; 20870f5bc99SReid Kleckner 20970f5bc99SReid Kleckner /// \brief Process beginning of an instruction. 21070f5bc99SReid Kleckner void beginInstruction(const MachineInstr *MI) override; 21170f5bc99SReid Kleckner }; 21270f5bc99SReid Kleckner } // End of namespace llvm 21370f5bc99SReid Kleckner 21470f5bc99SReid Kleckner #endif 215