170f5bc99SReid Kleckner //===-- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --*- 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 #include "CodeViewDebug.h"
1570f5bc99SReid Kleckner #include "llvm/DebugInfo/CodeView/CodeView.h"
16a8d57407SReid Kleckner #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
172214ed89SReid Kleckner #include "llvm/DebugInfo/CodeView/Line.h"
1870f5bc99SReid Kleckner #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
19fbdbe9e2SReid Kleckner #include "llvm/DebugInfo/CodeView/TypeDumper.h"
20f3b9ba49SReid Kleckner #include "llvm/DebugInfo/CodeView/TypeIndex.h"
21f3b9ba49SReid Kleckner #include "llvm/DebugInfo/CodeView/TypeRecord.h"
2270f5bc99SReid Kleckner #include "llvm/MC/MCExpr.h"
235d122f87SReid Kleckner #include "llvm/MC/MCSectionCOFF.h"
2470f5bc99SReid Kleckner #include "llvm/MC/MCSymbol.h"
2570f5bc99SReid Kleckner #include "llvm/Support/COFF.h"
26fbdbe9e2SReid Kleckner #include "llvm/Support/ScopedPrinter.h"
27f9c275feSReid Kleckner #include "llvm/Target/TargetFrameLowering.h"
2876c9eb99SAmjad Aboud #include "llvm/Target/TargetRegisterInfo.h"
2976c9eb99SAmjad Aboud #include "llvm/Target/TargetSubtargetInfo.h"
3070f5bc99SReid Kleckner 
31f9c275feSReid Kleckner using namespace llvm;
3270f5bc99SReid Kleckner using namespace llvm::codeview;
3370f5bc99SReid Kleckner 
34f9c275feSReid Kleckner CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
35f9c275feSReid Kleckner     : DebugHandlerBase(AP), OS(*Asm->OutStreamer), CurFn(nullptr) {
36f9c275feSReid Kleckner   // If module doesn't have named metadata anchors or COFF debug section
37f9c275feSReid Kleckner   // is not available, skip any debug info related stuff.
38f9c275feSReid Kleckner   if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
39f9c275feSReid Kleckner       !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) {
40f9c275feSReid Kleckner     Asm = nullptr;
41f9c275feSReid Kleckner     return;
42f9c275feSReid Kleckner   }
43f9c275feSReid Kleckner 
44f9c275feSReid Kleckner   // Tell MMI that we have debug info.
45f9c275feSReid Kleckner   MMI->setDebugInfoAvailability(true);
46f9c275feSReid Kleckner }
4770f5bc99SReid Kleckner 
489533af4fSReid Kleckner StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
499533af4fSReid Kleckner   std::string &Filepath = FileToFilepathMap[File];
5070f5bc99SReid Kleckner   if (!Filepath.empty())
5170f5bc99SReid Kleckner     return Filepath;
5270f5bc99SReid Kleckner 
539533af4fSReid Kleckner   StringRef Dir = File->getDirectory(), Filename = File->getFilename();
549533af4fSReid Kleckner 
5570f5bc99SReid Kleckner   // Clang emits directory and relative filename info into the IR, but CodeView
5670f5bc99SReid Kleckner   // operates on full paths.  We could change Clang to emit full paths too, but
5770f5bc99SReid Kleckner   // that would increase the IR size and probably not needed for other users.
5870f5bc99SReid Kleckner   // For now, just concatenate and canonicalize the path here.
5970f5bc99SReid Kleckner   if (Filename.find(':') == 1)
6070f5bc99SReid Kleckner     Filepath = Filename;
6170f5bc99SReid Kleckner   else
6270f5bc99SReid Kleckner     Filepath = (Dir + "\\" + Filename).str();
6370f5bc99SReid Kleckner 
6470f5bc99SReid Kleckner   // Canonicalize the path.  We have to do it textually because we may no longer
6570f5bc99SReid Kleckner   // have access the file in the filesystem.
6670f5bc99SReid Kleckner   // First, replace all slashes with backslashes.
6770f5bc99SReid Kleckner   std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
6870f5bc99SReid Kleckner 
6970f5bc99SReid Kleckner   // Remove all "\.\" with "\".
7070f5bc99SReid Kleckner   size_t Cursor = 0;
7170f5bc99SReid Kleckner   while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
7270f5bc99SReid Kleckner     Filepath.erase(Cursor, 2);
7370f5bc99SReid Kleckner 
7470f5bc99SReid Kleckner   // Replace all "\XXX\..\" with "\".  Don't try too hard though as the original
7570f5bc99SReid Kleckner   // path should be well-formatted, e.g. start with a drive letter, etc.
7670f5bc99SReid Kleckner   Cursor = 0;
7770f5bc99SReid Kleckner   while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
7870f5bc99SReid Kleckner     // Something's wrong if the path starts with "\..\", abort.
7970f5bc99SReid Kleckner     if (Cursor == 0)
8070f5bc99SReid Kleckner       break;
8170f5bc99SReid Kleckner 
8270f5bc99SReid Kleckner     size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
8370f5bc99SReid Kleckner     if (PrevSlash == std::string::npos)
8470f5bc99SReid Kleckner       // Something's wrong, abort.
8570f5bc99SReid Kleckner       break;
8670f5bc99SReid Kleckner 
8770f5bc99SReid Kleckner     Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
8870f5bc99SReid Kleckner     // The next ".." might be following the one we've just erased.
8970f5bc99SReid Kleckner     Cursor = PrevSlash;
9070f5bc99SReid Kleckner   }
9170f5bc99SReid Kleckner 
9270f5bc99SReid Kleckner   // Remove all duplicate backslashes.
9370f5bc99SReid Kleckner   Cursor = 0;
9470f5bc99SReid Kleckner   while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
9570f5bc99SReid Kleckner     Filepath.erase(Cursor, 1);
9670f5bc99SReid Kleckner 
9770f5bc99SReid Kleckner   return Filepath;
9870f5bc99SReid Kleckner }
9970f5bc99SReid Kleckner 
1002214ed89SReid Kleckner unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
1012214ed89SReid Kleckner   unsigned NextId = FileIdMap.size() + 1;
1022214ed89SReid Kleckner   auto Insertion = FileIdMap.insert(std::make_pair(F, NextId));
1032214ed89SReid Kleckner   if (Insertion.second) {
1042214ed89SReid Kleckner     // We have to compute the full filepath and emit a .cv_file directive.
1052214ed89SReid Kleckner     StringRef FullPath = getFullFilepath(F);
106dac21b43SReid Kleckner     NextId = OS.EmitCVFileDirective(NextId, FullPath);
1072214ed89SReid Kleckner     assert(NextId == FileIdMap.size() && ".cv_file directive failed");
1082214ed89SReid Kleckner   }
1092214ed89SReid Kleckner   return Insertion.first->second;
1102214ed89SReid Kleckner }
1112214ed89SReid Kleckner 
112876330d5SReid Kleckner CodeViewDebug::InlineSite &
113876330d5SReid Kleckner CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
114876330d5SReid Kleckner                              const DISubprogram *Inlinee) {
115fbd7787dSReid Kleckner   auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
116fbd7787dSReid Kleckner   InlineSite *Site = &SiteInsertion.first->second;
117fbd7787dSReid Kleckner   if (SiteInsertion.second) {
118f9c275feSReid Kleckner     Site->SiteFuncId = NextFuncId++;
119876330d5SReid Kleckner     Site->Inlinee = Inlinee;
1202280f932SReid Kleckner     InlinedSubprograms.insert(Inlinee);
12175c3ebfaSDavid Majnemer     getFuncIdForSubprogram(Inlinee);
122f3b9ba49SReid Kleckner   }
123f9c275feSReid Kleckner   return *Site;
124f3b9ba49SReid Kleckner }
125f3b9ba49SReid Kleckner 
12675c3ebfaSDavid Majnemer TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
12775c3ebfaSDavid Majnemer   // It's possible to ask for the FuncId of a function which doesn't have a
12875c3ebfaSDavid Majnemer   // subprogram: inlining a function with debug info into a function with none.
12975c3ebfaSDavid Majnemer   if (!SP)
130b68f32f0SDavid Majnemer     return TypeIndex::None();
1312280f932SReid Kleckner 
13275c3ebfaSDavid Majnemer   // Check if we've already translated this subprogram.
13376c9eb99SAmjad Aboud   auto I = TypeIndices.find({SP, nullptr});
13475c3ebfaSDavid Majnemer   if (I != TypeIndices.end())
13575c3ebfaSDavid Majnemer     return I->second;
1362280f932SReid Kleckner 
1372280f932SReid Kleckner   TypeIndex ParentScope = TypeIndex(0);
138ac945e27SReid Kleckner   // The display name includes function template arguments. Drop them to match
139ac945e27SReid Kleckner   // MSVC.
140ac945e27SReid Kleckner   StringRef DisplayName = SP->getDisplayName().split('<').first;
14176c9eb99SAmjad Aboud   FuncIdRecord FuncId(ParentScope, lowerSubprogramType(SP), DisplayName);
1422280f932SReid Kleckner   TypeIndex TI = TypeTable.writeFuncId(FuncId);
14375c3ebfaSDavid Majnemer 
144a8d57407SReid Kleckner   recordTypeIndexForDINode(SP, TI);
14575c3ebfaSDavid Majnemer   return TI;
1462280f932SReid Kleckner }
1472280f932SReid Kleckner 
14876c9eb99SAmjad Aboud void CodeViewDebug::recordTypeIndexForDINode(const DINode *Node, TypeIndex TI,
14976c9eb99SAmjad Aboud                                              const DIType *ClassTy) {
15076c9eb99SAmjad Aboud   auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
151a8d57407SReid Kleckner   (void)InsertResult;
152a8d57407SReid Kleckner   assert(InsertResult.second && "DINode was already assigned a type index");
153a8d57407SReid Kleckner }
154a8d57407SReid Kleckner 
15576c9eb99SAmjad Aboud unsigned CodeViewDebug::getPointerSizeInBytes() {
15676c9eb99SAmjad Aboud   return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
15776c9eb99SAmjad Aboud }
15876c9eb99SAmjad Aboud 
159876330d5SReid Kleckner void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
160876330d5SReid Kleckner                                         const DILocation *InlinedAt) {
161876330d5SReid Kleckner   if (InlinedAt) {
162876330d5SReid Kleckner     // This variable was inlined. Associate it with the InlineSite.
163876330d5SReid Kleckner     const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
164876330d5SReid Kleckner     InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
165876330d5SReid Kleckner     Site.InlinedLocals.emplace_back(Var);
166876330d5SReid Kleckner   } else {
167876330d5SReid Kleckner     // This variable goes in the main ProcSym.
168876330d5SReid Kleckner     CurFn->Locals.emplace_back(Var);
169876330d5SReid Kleckner   }
170876330d5SReid Kleckner }
171876330d5SReid Kleckner 
172829365aeSReid Kleckner static void addLocIfNotPresent(SmallVectorImpl<const DILocation *> &Locs,
173829365aeSReid Kleckner                                const DILocation *Loc) {
174829365aeSReid Kleckner   auto B = Locs.begin(), E = Locs.end();
175829365aeSReid Kleckner   if (std::find(B, E, Loc) == E)
176829365aeSReid Kleckner     Locs.push_back(Loc);
177829365aeSReid Kleckner }
178829365aeSReid Kleckner 
179bdc4956bSBenjamin Kramer void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL,
18070f5bc99SReid Kleckner                                         const MachineFunction *MF) {
1819533af4fSReid Kleckner   // Skip this instruction if it has the same location as the previous one.
1829533af4fSReid Kleckner   if (DL == CurFn->LastLoc)
1839533af4fSReid Kleckner     return;
1849533af4fSReid Kleckner 
1859533af4fSReid Kleckner   const DIScope *Scope = DL.get()->getScope();
18670f5bc99SReid Kleckner   if (!Scope)
18770f5bc99SReid Kleckner     return;
1889533af4fSReid Kleckner 
18970f5bc99SReid Kleckner   // Skip this line if it is longer than the maximum we can record.
1902214ed89SReid Kleckner   LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true);
1912214ed89SReid Kleckner   if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
1922214ed89SReid Kleckner       LI.isNeverStepInto())
19370f5bc99SReid Kleckner     return;
19470f5bc99SReid Kleckner 
1952214ed89SReid Kleckner   ColumnInfo CI(DL.getCol(), /*EndColumn=*/0);
1962214ed89SReid Kleckner   if (CI.getStartColumn() != DL.getCol())
1972214ed89SReid Kleckner     return;
19800d9639cSReid Kleckner 
1992214ed89SReid Kleckner   if (!CurFn->HaveLineInfo)
2002214ed89SReid Kleckner     CurFn->HaveLineInfo = true;
2012214ed89SReid Kleckner   unsigned FileId = 0;
2022214ed89SReid Kleckner   if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile())
2032214ed89SReid Kleckner     FileId = CurFn->LastFileId;
2042214ed89SReid Kleckner   else
2052214ed89SReid Kleckner     FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
2062214ed89SReid Kleckner   CurFn->LastLoc = DL;
207f3b9ba49SReid Kleckner 
208f3b9ba49SReid Kleckner   unsigned FuncId = CurFn->FuncId;
209876330d5SReid Kleckner   if (const DILocation *SiteLoc = DL->getInlinedAt()) {
210829365aeSReid Kleckner     const DILocation *Loc = DL.get();
211829365aeSReid Kleckner 
212f3b9ba49SReid Kleckner     // If this location was actually inlined from somewhere else, give it the ID
213f3b9ba49SReid Kleckner     // of the inline call site.
214876330d5SReid Kleckner     FuncId =
215876330d5SReid Kleckner         getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
216829365aeSReid Kleckner 
217f3b9ba49SReid Kleckner     // Ensure we have links in the tree of inline call sites.
218829365aeSReid Kleckner     bool FirstLoc = true;
219829365aeSReid Kleckner     while ((SiteLoc = Loc->getInlinedAt())) {
220876330d5SReid Kleckner       InlineSite &Site =
221876330d5SReid Kleckner           getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
222829365aeSReid Kleckner       if (!FirstLoc)
223829365aeSReid Kleckner         addLocIfNotPresent(Site.ChildSites, Loc);
224829365aeSReid Kleckner       FirstLoc = false;
225829365aeSReid Kleckner       Loc = SiteLoc;
226f3b9ba49SReid Kleckner     }
227829365aeSReid Kleckner     addLocIfNotPresent(CurFn->ChildSites, Loc);
228f3b9ba49SReid Kleckner   }
229f3b9ba49SReid Kleckner 
230dac21b43SReid Kleckner   OS.EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(),
231dac21b43SReid Kleckner                         /*PrologueEnd=*/false,
2322214ed89SReid Kleckner                         /*IsStmt=*/false, DL->getFilename());
23370f5bc99SReid Kleckner }
23470f5bc99SReid Kleckner 
2355d122f87SReid Kleckner void CodeViewDebug::emitCodeViewMagicVersion() {
2365d122f87SReid Kleckner   OS.EmitValueToAlignment(4);
2375d122f87SReid Kleckner   OS.AddComment("Debug section magic");
2385d122f87SReid Kleckner   OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
2395d122f87SReid Kleckner }
2405d122f87SReid Kleckner 
24170f5bc99SReid Kleckner void CodeViewDebug::endModule() {
2426f3406dfSReid Kleckner   if (!Asm || !MMI->hasDebugInfo())
24370f5bc99SReid Kleckner     return;
24470f5bc99SReid Kleckner 
24570f5bc99SReid Kleckner   assert(Asm != nullptr);
24670f5bc99SReid Kleckner 
24770f5bc99SReid Kleckner   // The COFF .debug$S section consists of several subsections, each starting
24870f5bc99SReid Kleckner   // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
24970f5bc99SReid Kleckner   // of the payload followed by the payload itself.  The subsections are 4-byte
25070f5bc99SReid Kleckner   // aligned.
25170f5bc99SReid Kleckner 
2526f3406dfSReid Kleckner   // Use the generic .debug$S section, and make a subsection for all the inlined
2536f3406dfSReid Kleckner   // subprograms.
2546f3406dfSReid Kleckner   switchToDebugSectionForSymbol(nullptr);
2555d122f87SReid Kleckner   emitInlineeLinesSubsection();
2561fcd610cSReid Kleckner 
2572214ed89SReid Kleckner   // Emit per-function debug information.
2582214ed89SReid Kleckner   for (auto &P : FnDebugInfo)
259577be0feSDavid Majnemer     if (!P.first->isDeclarationForLinker())
2602214ed89SReid Kleckner       emitDebugInfoForFunction(P.first, P.second);
26170f5bc99SReid Kleckner 
2626f3406dfSReid Kleckner   // Emit global variable debug information.
2633128b10cSDavid Majnemer   setCurrentSubprogram(nullptr);
2646f3406dfSReid Kleckner   emitDebugInfoForGlobals();
2656f3406dfSReid Kleckner 
2665d122f87SReid Kleckner   // Switch back to the generic .debug$S section after potentially processing
2675d122f87SReid Kleckner   // comdat symbol sections.
2685d122f87SReid Kleckner   switchToDebugSectionForSymbol(nullptr);
2695d122f87SReid Kleckner 
2703128b10cSDavid Majnemer   // Emit UDT records for any types used by global variables.
2713128b10cSDavid Majnemer   if (!GlobalUDTs.empty()) {
2723128b10cSDavid Majnemer     MCSymbol *SymbolsEnd = beginCVSubsection(ModuleSubstreamKind::Symbols);
2733128b10cSDavid Majnemer     emitDebugInfoForUDTs(GlobalUDTs);
2743128b10cSDavid Majnemer     endCVSubsection(SymbolsEnd);
2753128b10cSDavid Majnemer   }
2763128b10cSDavid Majnemer 
27770f5bc99SReid Kleckner   // This subsection holds a file index to offset in string table table.
278dac21b43SReid Kleckner   OS.AddComment("File index to string table offset subsection");
279dac21b43SReid Kleckner   OS.EmitCVFileChecksumsDirective();
28070f5bc99SReid Kleckner 
28170f5bc99SReid Kleckner   // This subsection holds the string table.
282dac21b43SReid Kleckner   OS.AddComment("String table");
283dac21b43SReid Kleckner   OS.EmitCVStringTableDirective();
28470f5bc99SReid Kleckner 
2855acacbb0SReid Kleckner   // Emit type information last, so that any types we translate while emitting
2865acacbb0SReid Kleckner   // function info are included.
2875acacbb0SReid Kleckner   emitTypeInformation();
2885acacbb0SReid Kleckner 
28970f5bc99SReid Kleckner   clear();
29070f5bc99SReid Kleckner }
29170f5bc99SReid Kleckner 
292b9456a5eSDavid Majnemer static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S) {
293b9456a5eSDavid Majnemer   // Microsoft's linker seems to have trouble with symbol names longer than
294b9456a5eSDavid Majnemer   // 0xffd8 bytes.
295b9456a5eSDavid Majnemer   S = S.substr(0, 0xffd8);
296b9456a5eSDavid Majnemer   SmallString<32> NullTerminatedString(S);
297b9456a5eSDavid Majnemer   NullTerminatedString.push_back('\0');
298b9456a5eSDavid Majnemer   OS.EmitBytes(NullTerminatedString);
299b9456a5eSDavid Majnemer }
300b9456a5eSDavid Majnemer 
301f3b9ba49SReid Kleckner void CodeViewDebug::emitTypeInformation() {
3022280f932SReid Kleckner   // Do nothing if we have no debug info or if no non-trivial types were emitted
3032280f932SReid Kleckner   // to TypeTable during codegen.
30476c9eb99SAmjad Aboud   NamedMDNode *CU_Nodes = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
305fbd7787dSReid Kleckner   if (!CU_Nodes)
306fbd7787dSReid Kleckner     return;
3072280f932SReid Kleckner   if (TypeTable.empty())
308fbd7787dSReid Kleckner     return;
309fbd7787dSReid Kleckner 
310f3b9ba49SReid Kleckner   // Start the .debug$T section with 0x4.
311dac21b43SReid Kleckner   OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());
3125d122f87SReid Kleckner   emitCodeViewMagicVersion();
313f3b9ba49SReid Kleckner 
314fbdbe9e2SReid Kleckner   SmallString<8> CommentPrefix;
315fbdbe9e2SReid Kleckner   if (OS.isVerboseAsm()) {
316fbdbe9e2SReid Kleckner     CommentPrefix += '\t';
317fbdbe9e2SReid Kleckner     CommentPrefix += Asm->MAI->getCommentString();
318fbdbe9e2SReid Kleckner     CommentPrefix += ' ';
319fbdbe9e2SReid Kleckner   }
320fbdbe9e2SReid Kleckner 
321fbdbe9e2SReid Kleckner   CVTypeDumper CVTD(nullptr, /*PrintRecordBytes=*/false);
3222280f932SReid Kleckner   TypeTable.ForEachRecord(
323fbdbe9e2SReid Kleckner       [&](TypeIndex Index, StringRef Record) {
324fbdbe9e2SReid Kleckner         if (OS.isVerboseAsm()) {
325fbdbe9e2SReid Kleckner           // Emit a block comment describing the type record for readability.
326fbdbe9e2SReid Kleckner           SmallString<512> CommentBlock;
327fbdbe9e2SReid Kleckner           raw_svector_ostream CommentOS(CommentBlock);
328fbdbe9e2SReid Kleckner           ScopedPrinter SP(CommentOS);
329fbdbe9e2SReid Kleckner           SP.setPrefix(CommentPrefix);
330fbdbe9e2SReid Kleckner           CVTD.setPrinter(&SP);
33101ee3daeSZachary Turner           Error EC = CVTD.dump({Record.bytes_begin(), Record.bytes_end()});
33201ee3daeSZachary Turner           assert(!EC && "produced malformed type record");
33301ee3daeSZachary Turner           consumeError(std::move(EC));
334fbdbe9e2SReid Kleckner           // emitRawComment will insert its own tab and comment string before
335fbdbe9e2SReid Kleckner           // the first line, so strip off our first one. It also prints its own
336fbdbe9e2SReid Kleckner           // newline.
337fbdbe9e2SReid Kleckner           OS.emitRawComment(
338fbdbe9e2SReid Kleckner               CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
339fbdbe9e2SReid Kleckner         }
340fbdbe9e2SReid Kleckner         OS.EmitBinaryData(Record);
3412280f932SReid Kleckner       });
342f3b9ba49SReid Kleckner }
343f3b9ba49SReid Kleckner 
3445d122f87SReid Kleckner void CodeViewDebug::emitInlineeLinesSubsection() {
3451fcd610cSReid Kleckner   if (InlinedSubprograms.empty())
3461fcd610cSReid Kleckner     return;
3471fcd610cSReid Kleckner 
3481fcd610cSReid Kleckner   OS.AddComment("Inlinee lines subsection");
3496f3406dfSReid Kleckner   MCSymbol *InlineEnd = beginCVSubsection(ModuleSubstreamKind::InlineeLines);
3501fcd610cSReid Kleckner 
3511fcd610cSReid Kleckner   // We don't provide any extra file info.
3521fcd610cSReid Kleckner   // FIXME: Find out if debuggers use this info.
35330579ec8SDavid Majnemer   OS.AddComment("Inlinee lines signature");
3541fcd610cSReid Kleckner   OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
3551fcd610cSReid Kleckner 
3561fcd610cSReid Kleckner   for (const DISubprogram *SP : InlinedSubprograms) {
35776c9eb99SAmjad Aboud     assert(TypeIndices.count({SP, nullptr}));
35876c9eb99SAmjad Aboud     TypeIndex InlineeIdx = TypeIndices[{SP, nullptr}];
3592280f932SReid Kleckner 
36030579ec8SDavid Majnemer     OS.AddBlankLine();
3611fcd610cSReid Kleckner     unsigned FileId = maybeRecordFile(SP->getFile());
3621fcd610cSReid Kleckner     OS.AddComment("Inlined function " + SP->getDisplayName() + " starts at " +
3631fcd610cSReid Kleckner                   SP->getFilename() + Twine(':') + Twine(SP->getLine()));
36430579ec8SDavid Majnemer     OS.AddBlankLine();
3651fcd610cSReid Kleckner     // The filechecksum table uses 8 byte entries for now, and file ids start at
3661fcd610cSReid Kleckner     // 1.
3671fcd610cSReid Kleckner     unsigned FileOffset = (FileId - 1) * 8;
36830579ec8SDavid Majnemer     OS.AddComment("Type index of inlined function");
3692280f932SReid Kleckner     OS.EmitIntValue(InlineeIdx.getIndex(), 4);
37030579ec8SDavid Majnemer     OS.AddComment("Offset into filechecksum table");
3711fcd610cSReid Kleckner     OS.EmitIntValue(FileOffset, 4);
37230579ec8SDavid Majnemer     OS.AddComment("Starting line number");
3731fcd610cSReid Kleckner     OS.EmitIntValue(SP->getLine(), 4);
3741fcd610cSReid Kleckner   }
3751fcd610cSReid Kleckner 
3766f3406dfSReid Kleckner   endCVSubsection(InlineEnd);
3771fcd610cSReid Kleckner }
3781fcd610cSReid Kleckner 
3791fcd610cSReid Kleckner void CodeViewDebug::collectInlineSiteChildren(
3801fcd610cSReid Kleckner     SmallVectorImpl<unsigned> &Children, const FunctionInfo &FI,
3811fcd610cSReid Kleckner     const InlineSite &Site) {
3821fcd610cSReid Kleckner   for (const DILocation *ChildSiteLoc : Site.ChildSites) {
3831fcd610cSReid Kleckner     auto I = FI.InlineSites.find(ChildSiteLoc);
3841fcd610cSReid Kleckner     const InlineSite &ChildSite = I->second;
3851fcd610cSReid Kleckner     Children.push_back(ChildSite.SiteFuncId);
3861fcd610cSReid Kleckner     collectInlineSiteChildren(Children, FI, ChildSite);
3871fcd610cSReid Kleckner   }
3881fcd610cSReid Kleckner }
3891fcd610cSReid Kleckner 
390f3b9ba49SReid Kleckner void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
391f3b9ba49SReid Kleckner                                         const DILocation *InlinedAt,
392f3b9ba49SReid Kleckner                                         const InlineSite &Site) {
393f9c275feSReid Kleckner   MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
394f9c275feSReid Kleckner            *InlineEnd = MMI->getContext().createTempSymbol();
395f3b9ba49SReid Kleckner 
39676c9eb99SAmjad Aboud   assert(TypeIndices.count({Site.Inlinee, nullptr}));
39776c9eb99SAmjad Aboud   TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];
398f3b9ba49SReid Kleckner 
399f3b9ba49SReid Kleckner   // SymbolRecord
400dac21b43SReid Kleckner   OS.AddComment("Record length");
401eb3bcdd2SReid Kleckner   OS.emitAbsoluteSymbolDiff(InlineEnd, InlineBegin, 2);   // RecordLength
402f3b9ba49SReid Kleckner   OS.EmitLabel(InlineBegin);
403dac21b43SReid Kleckner   OS.AddComment("Record kind: S_INLINESITE");
40463a2846eSZachary Turner   OS.EmitIntValue(SymbolKind::S_INLINESITE, 2); // RecordKind
405f3b9ba49SReid Kleckner 
406dac21b43SReid Kleckner   OS.AddComment("PtrParent");
407dac21b43SReid Kleckner   OS.EmitIntValue(0, 4);
408dac21b43SReid Kleckner   OS.AddComment("PtrEnd");
409dac21b43SReid Kleckner   OS.EmitIntValue(0, 4);
410dac21b43SReid Kleckner   OS.AddComment("Inlinee type index");
4112280f932SReid Kleckner   OS.EmitIntValue(InlineeIdx.getIndex(), 4);
412f3b9ba49SReid Kleckner 
4131fcd610cSReid Kleckner   unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
4141fcd610cSReid Kleckner   unsigned StartLineNum = Site.Inlinee->getLine();
4151fcd610cSReid Kleckner   SmallVector<unsigned, 3> SecondaryFuncIds;
4161fcd610cSReid Kleckner   collectInlineSiteChildren(SecondaryFuncIds, FI, Site);
4171fcd610cSReid Kleckner 
4181fcd610cSReid Kleckner   OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
419c9911f28SDavid Majnemer                                     FI.Begin, FI.End, SecondaryFuncIds);
420f3b9ba49SReid Kleckner 
421f3b9ba49SReid Kleckner   OS.EmitLabel(InlineEnd);
422f3b9ba49SReid Kleckner 
423f9c275feSReid Kleckner   for (const LocalVariable &Var : Site.InlinedLocals)
424f9c275feSReid Kleckner     emitLocalVariable(Var);
425f9c275feSReid Kleckner 
426f3b9ba49SReid Kleckner   // Recurse on child inlined call sites before closing the scope.
427f3b9ba49SReid Kleckner   for (const DILocation *ChildSite : Site.ChildSites) {
428f3b9ba49SReid Kleckner     auto I = FI.InlineSites.find(ChildSite);
429f3b9ba49SReid Kleckner     assert(I != FI.InlineSites.end() &&
430f3b9ba49SReid Kleckner            "child site not in function inline site map");
431f3b9ba49SReid Kleckner     emitInlinedCallSite(FI, ChildSite, I->second);
432f3b9ba49SReid Kleckner   }
433f3b9ba49SReid Kleckner 
434f3b9ba49SReid Kleckner   // Close the scope.
435dac21b43SReid Kleckner   OS.AddComment("Record length");
436dac21b43SReid Kleckner   OS.EmitIntValue(2, 2);                                  // RecordLength
437dac21b43SReid Kleckner   OS.AddComment("Record kind: S_INLINESITE_END");
43863a2846eSZachary Turner   OS.EmitIntValue(SymbolKind::S_INLINESITE_END, 2); // RecordKind
439f3b9ba49SReid Kleckner }
440f3b9ba49SReid Kleckner 
4415d122f87SReid Kleckner void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
4425d122f87SReid Kleckner   // If we have a symbol, it may be in a section that is COMDAT. If so, find the
4435d122f87SReid Kleckner   // comdat key. A section may be comdat because of -ffunction-sections or
4445d122f87SReid Kleckner   // because it is comdat in the IR.
4455d122f87SReid Kleckner   MCSectionCOFF *GVSec =
4465d122f87SReid Kleckner       GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->getSection()) : nullptr;
4475d122f87SReid Kleckner   const MCSymbol *KeySym = GVSec ? GVSec->getCOMDATSymbol() : nullptr;
4485d122f87SReid Kleckner 
4495d122f87SReid Kleckner   MCSectionCOFF *DebugSec = cast<MCSectionCOFF>(
4505d122f87SReid Kleckner       Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
4515d122f87SReid Kleckner   DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
4525d122f87SReid Kleckner 
4535d122f87SReid Kleckner   OS.SwitchSection(DebugSec);
4545d122f87SReid Kleckner 
4555d122f87SReid Kleckner   // Emit the magic version number if this is the first time we've switched to
4565d122f87SReid Kleckner   // this section.
4575d122f87SReid Kleckner   if (ComdatDebugSections.insert(DebugSec).second)
4585d122f87SReid Kleckner     emitCodeViewMagicVersion();
4595d122f87SReid Kleckner }
4605d122f87SReid Kleckner 
461ac945e27SReid Kleckner static const DISubprogram *getQualifiedNameComponents(
462ac945e27SReid Kleckner     const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
463ac945e27SReid Kleckner   const DISubprogram *ClosestSubprogram = nullptr;
464ac945e27SReid Kleckner   while (Scope != nullptr) {
465ac945e27SReid Kleckner     if (ClosestSubprogram == nullptr)
466ac945e27SReid Kleckner       ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
467ac945e27SReid Kleckner     StringRef ScopeName = Scope->getName();
468ac945e27SReid Kleckner     if (!ScopeName.empty())
469ac945e27SReid Kleckner       QualifiedNameComponents.push_back(ScopeName);
470ac945e27SReid Kleckner     Scope = Scope->getScope().resolve();
471ac945e27SReid Kleckner   }
472ac945e27SReid Kleckner   return ClosestSubprogram;
473ac945e27SReid Kleckner }
474ac945e27SReid Kleckner 
475ac945e27SReid Kleckner static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
476ac945e27SReid Kleckner                                     StringRef TypeName) {
477ac945e27SReid Kleckner   std::string FullyQualifiedName;
478ac945e27SReid Kleckner   for (StringRef QualifiedNameComponent : reverse(QualifiedNameComponents)) {
479ac945e27SReid Kleckner     FullyQualifiedName.append(QualifiedNameComponent);
480ac945e27SReid Kleckner     FullyQualifiedName.append("::");
481ac945e27SReid Kleckner   }
482ac945e27SReid Kleckner   FullyQualifiedName.append(TypeName);
483ac945e27SReid Kleckner   return FullyQualifiedName;
484ac945e27SReid Kleckner }
485ac945e27SReid Kleckner 
4862214ed89SReid Kleckner void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
4872214ed89SReid Kleckner                                              FunctionInfo &FI) {
48870f5bc99SReid Kleckner   // For each function there is a separate subsection
48970f5bc99SReid Kleckner   // which holds the PC to file:line table.
49070f5bc99SReid Kleckner   const MCSymbol *Fn = Asm->getSymbol(GV);
49170f5bc99SReid Kleckner   assert(Fn);
49270f5bc99SReid Kleckner 
4935d122f87SReid Kleckner   // Switch to the to a comdat section, if appropriate.
4945d122f87SReid Kleckner   switchToDebugSectionForSymbol(Fn);
4955d122f87SReid Kleckner 
496ac945e27SReid Kleckner   std::string FuncName;
4973128b10cSDavid Majnemer   auto *SP = GV->getSubprogram();
4983128b10cSDavid Majnemer   setCurrentSubprogram(SP);
499ac945e27SReid Kleckner 
500ac945e27SReid Kleckner   // If we have a display name, build the fully qualified name by walking the
501ac945e27SReid Kleckner   // chain of scopes.
502ac945e27SReid Kleckner   if (SP != nullptr && !SP->getDisplayName().empty()) {
503ac945e27SReid Kleckner     SmallVector<StringRef, 5> QualifiedNameComponents;
504ac945e27SReid Kleckner     getQualifiedNameComponents(SP->getScope().resolve(),
505ac945e27SReid Kleckner                                QualifiedNameComponents);
506ac945e27SReid Kleckner     FuncName = getQualifiedName(QualifiedNameComponents, SP->getDisplayName());
507ac945e27SReid Kleckner   }
50870f5bc99SReid Kleckner 
50970f5bc99SReid Kleckner   // If our DISubprogram name is empty, use the mangled name.
51070f5bc99SReid Kleckner   if (FuncName.empty())
51170f5bc99SReid Kleckner     FuncName = GlobalValue::getRealLinkageName(GV->getName());
51270f5bc99SReid Kleckner 
51370f5bc99SReid Kleckner   // Emit a symbol subsection, required by VS2012+ to find function boundaries.
514dac21b43SReid Kleckner   OS.AddComment("Symbol subsection for " + Twine(FuncName));
5156f3406dfSReid Kleckner   MCSymbol *SymbolsEnd = beginCVSubsection(ModuleSubstreamKind::Symbols);
51670f5bc99SReid Kleckner   {
517f9c275feSReid Kleckner     MCSymbol *ProcRecordBegin = MMI->getContext().createTempSymbol(),
518f9c275feSReid Kleckner              *ProcRecordEnd = MMI->getContext().createTempSymbol();
519dac21b43SReid Kleckner     OS.AddComment("Record length");
520eb3bcdd2SReid Kleckner     OS.emitAbsoluteSymbolDiff(ProcRecordEnd, ProcRecordBegin, 2);
521dac21b43SReid Kleckner     OS.EmitLabel(ProcRecordBegin);
52270f5bc99SReid Kleckner 
523dac21b43SReid Kleckner     OS.AddComment("Record kind: S_GPROC32_ID");
52463a2846eSZachary Turner     OS.EmitIntValue(unsigned(SymbolKind::S_GPROC32_ID), 2);
52570f5bc99SReid Kleckner 
52630579ec8SDavid Majnemer     // These fields are filled in by tools like CVPACK which run after the fact.
527dac21b43SReid Kleckner     OS.AddComment("PtrParent");
528dac21b43SReid Kleckner     OS.EmitIntValue(0, 4);
529dac21b43SReid Kleckner     OS.AddComment("PtrEnd");
530dac21b43SReid Kleckner     OS.EmitIntValue(0, 4);
531dac21b43SReid Kleckner     OS.AddComment("PtrNext");
532dac21b43SReid Kleckner     OS.EmitIntValue(0, 4);
53370f5bc99SReid Kleckner     // This is the important bit that tells the debugger where the function
53470f5bc99SReid Kleckner     // code is located and what's its size:
535dac21b43SReid Kleckner     OS.AddComment("Code size");
536eb3bcdd2SReid Kleckner     OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
537dac21b43SReid Kleckner     OS.AddComment("Offset after prologue");
538dac21b43SReid Kleckner     OS.EmitIntValue(0, 4);
539dac21b43SReid Kleckner     OS.AddComment("Offset before epilogue");
540dac21b43SReid Kleckner     OS.EmitIntValue(0, 4);
541dac21b43SReid Kleckner     OS.AddComment("Function type index");
54275c3ebfaSDavid Majnemer     OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4);
543dac21b43SReid Kleckner     OS.AddComment("Function section relative address");
544dac21b43SReid Kleckner     OS.EmitCOFFSecRel32(Fn);
545dac21b43SReid Kleckner     OS.AddComment("Function section index");
546dac21b43SReid Kleckner     OS.EmitCOFFSectionIndex(Fn);
547dac21b43SReid Kleckner     OS.AddComment("Flags");
548dac21b43SReid Kleckner     OS.EmitIntValue(0, 1);
54970f5bc99SReid Kleckner     // Emit the function display name as a null-terminated string.
550dac21b43SReid Kleckner     OS.AddComment("Function name");
5511256125fSDavid Majnemer     // Truncate the name so we won't overflow the record length field.
552b9456a5eSDavid Majnemer     emitNullTerminatedSymbolName(OS, FuncName);
553dac21b43SReid Kleckner     OS.EmitLabel(ProcRecordEnd);
55470f5bc99SReid Kleckner 
555f9c275feSReid Kleckner     for (const LocalVariable &Var : FI.Locals)
556f9c275feSReid Kleckner       emitLocalVariable(Var);
557f9c275feSReid Kleckner 
558f3b9ba49SReid Kleckner     // Emit inlined call site information. Only emit functions inlined directly
559f3b9ba49SReid Kleckner     // into the parent function. We'll emit the other sites recursively as part
560f3b9ba49SReid Kleckner     // of their parent inline site.
561f9c275feSReid Kleckner     for (const DILocation *InlinedAt : FI.ChildSites) {
562f9c275feSReid Kleckner       auto I = FI.InlineSites.find(InlinedAt);
563f9c275feSReid Kleckner       assert(I != FI.InlineSites.end() &&
564f9c275feSReid Kleckner              "child site not in function inline site map");
565f9c275feSReid Kleckner       emitInlinedCallSite(FI, InlinedAt, I->second);
566f3b9ba49SReid Kleckner     }
567f3b9ba49SReid Kleckner 
5683128b10cSDavid Majnemer     if (SP != nullptr)
5693128b10cSDavid Majnemer       emitDebugInfoForUDTs(LocalUDTs);
5703128b10cSDavid Majnemer 
57170f5bc99SReid Kleckner     // We're done with this function.
572dac21b43SReid Kleckner     OS.AddComment("Record length");
573dac21b43SReid Kleckner     OS.EmitIntValue(0x0002, 2);
574dac21b43SReid Kleckner     OS.AddComment("Record kind: S_PROC_ID_END");
57563a2846eSZachary Turner     OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2);
57670f5bc99SReid Kleckner   }
5776f3406dfSReid Kleckner   endCVSubsection(SymbolsEnd);
57870f5bc99SReid Kleckner 
5792214ed89SReid Kleckner   // We have an assembler directive that takes care of the whole line table.
580dac21b43SReid Kleckner   OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
58170f5bc99SReid Kleckner }
58270f5bc99SReid Kleckner 
583876330d5SReid Kleckner CodeViewDebug::LocalVarDefRange
584876330d5SReid Kleckner CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
585876330d5SReid Kleckner   LocalVarDefRange DR;
586c6a2f214SAaron Ballman   DR.InMemory = -1;
587876330d5SReid Kleckner   DR.DataOffset = Offset;
588876330d5SReid Kleckner   assert(DR.DataOffset == Offset && "truncation");
589876330d5SReid Kleckner   DR.StructOffset = 0;
590876330d5SReid Kleckner   DR.CVRegister = CVRegister;
591876330d5SReid Kleckner   return DR;
592876330d5SReid Kleckner }
593876330d5SReid Kleckner 
594876330d5SReid Kleckner CodeViewDebug::LocalVarDefRange
595876330d5SReid Kleckner CodeViewDebug::createDefRangeReg(uint16_t CVRegister) {
596876330d5SReid Kleckner   LocalVarDefRange DR;
597876330d5SReid Kleckner   DR.InMemory = 0;
598876330d5SReid Kleckner   DR.DataOffset = 0;
599876330d5SReid Kleckner   DR.StructOffset = 0;
600876330d5SReid Kleckner   DR.CVRegister = CVRegister;
601876330d5SReid Kleckner   return DR;
602876330d5SReid Kleckner }
603876330d5SReid Kleckner 
604876330d5SReid Kleckner void CodeViewDebug::collectVariableInfoFromMMITable(
605876330d5SReid Kleckner     DenseSet<InlinedVariable> &Processed) {
606876330d5SReid Kleckner   const TargetSubtargetInfo &TSI = Asm->MF->getSubtarget();
607876330d5SReid Kleckner   const TargetFrameLowering *TFI = TSI.getFrameLowering();
608876330d5SReid Kleckner   const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
609876330d5SReid Kleckner 
610876330d5SReid Kleckner   for (const MachineModuleInfo::VariableDbgInfo &VI :
611876330d5SReid Kleckner        MMI->getVariableDbgInfo()) {
612f9c275feSReid Kleckner     if (!VI.Var)
613f9c275feSReid Kleckner       continue;
614f9c275feSReid Kleckner     assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
615f9c275feSReid Kleckner            "Expected inlined-at fields to agree");
616f9c275feSReid Kleckner 
617876330d5SReid Kleckner     Processed.insert(InlinedVariable(VI.Var, VI.Loc->getInlinedAt()));
618f9c275feSReid Kleckner     LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
619f9c275feSReid Kleckner 
620f9c275feSReid Kleckner     // If variable scope is not found then skip this variable.
621f9c275feSReid Kleckner     if (!Scope)
622f9c275feSReid Kleckner       continue;
623f9c275feSReid Kleckner 
624f9c275feSReid Kleckner     // Get the frame register used and the offset.
625f9c275feSReid Kleckner     unsigned FrameReg = 0;
626876330d5SReid Kleckner     int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg);
627876330d5SReid Kleckner     uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);
628f9c275feSReid Kleckner 
629f9c275feSReid Kleckner     // Calculate the label ranges.
630876330d5SReid Kleckner     LocalVarDefRange DefRange = createDefRangeMem(CVReg, FrameOffset);
631f9c275feSReid Kleckner     for (const InsnRange &Range : Scope->getRanges()) {
632f9c275feSReid Kleckner       const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
633f9c275feSReid Kleckner       const MCSymbol *End = getLabelAfterInsn(Range.second);
634876330d5SReid Kleckner       End = End ? End : Asm->getFunctionEnd();
635876330d5SReid Kleckner       DefRange.Ranges.emplace_back(Begin, End);
636f9c275feSReid Kleckner     }
637f9c275feSReid Kleckner 
638876330d5SReid Kleckner     LocalVariable Var;
639876330d5SReid Kleckner     Var.DIVar = VI.Var;
640876330d5SReid Kleckner     Var.DefRanges.emplace_back(std::move(DefRange));
641876330d5SReid Kleckner     recordLocalVariable(std::move(Var), VI.Loc->getInlinedAt());
642f9c275feSReid Kleckner   }
643f9c275feSReid Kleckner }
644876330d5SReid Kleckner 
645876330d5SReid Kleckner void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
646876330d5SReid Kleckner   DenseSet<InlinedVariable> Processed;
647876330d5SReid Kleckner   // Grab the variable info that was squirreled away in the MMI side-table.
648876330d5SReid Kleckner   collectVariableInfoFromMMITable(Processed);
649876330d5SReid Kleckner 
650876330d5SReid Kleckner   const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();
651876330d5SReid Kleckner 
652876330d5SReid Kleckner   for (const auto &I : DbgValues) {
653876330d5SReid Kleckner     InlinedVariable IV = I.first;
654876330d5SReid Kleckner     if (Processed.count(IV))
655876330d5SReid Kleckner       continue;
656876330d5SReid Kleckner     const DILocalVariable *DIVar = IV.first;
657876330d5SReid Kleckner     const DILocation *InlinedAt = IV.second;
658876330d5SReid Kleckner 
659876330d5SReid Kleckner     // Instruction ranges, specifying where IV is accessible.
660876330d5SReid Kleckner     const auto &Ranges = I.second;
661876330d5SReid Kleckner 
662876330d5SReid Kleckner     LexicalScope *Scope = nullptr;
663876330d5SReid Kleckner     if (InlinedAt)
664876330d5SReid Kleckner       Scope = LScopes.findInlinedScope(DIVar->getScope(), InlinedAt);
665876330d5SReid Kleckner     else
666876330d5SReid Kleckner       Scope = LScopes.findLexicalScope(DIVar->getScope());
667876330d5SReid Kleckner     // If variable scope is not found then skip this variable.
668876330d5SReid Kleckner     if (!Scope)
669876330d5SReid Kleckner       continue;
670876330d5SReid Kleckner 
671876330d5SReid Kleckner     LocalVariable Var;
672876330d5SReid Kleckner     Var.DIVar = DIVar;
673876330d5SReid Kleckner 
674876330d5SReid Kleckner     // Calculate the definition ranges.
675876330d5SReid Kleckner     for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
676876330d5SReid Kleckner       const InsnRange &Range = *I;
677876330d5SReid Kleckner       const MachineInstr *DVInst = Range.first;
678876330d5SReid Kleckner       assert(DVInst->isDebugValue() && "Invalid History entry");
679876330d5SReid Kleckner       const DIExpression *DIExpr = DVInst->getDebugExpression();
680876330d5SReid Kleckner 
681876330d5SReid Kleckner       // Bail if there is a complex DWARF expression for now.
682876330d5SReid Kleckner       if (DIExpr && DIExpr->getNumElements() > 0)
683876330d5SReid Kleckner         continue;
684876330d5SReid Kleckner 
6859a593ee7SReid Kleckner       // Bail if operand 0 is not a valid register. This means the variable is a
6869a593ee7SReid Kleckner       // simple constant, or is described by a complex expression.
6879a593ee7SReid Kleckner       // FIXME: Find a way to represent constant variables, since they are
6889a593ee7SReid Kleckner       // relatively common.
6899a593ee7SReid Kleckner       unsigned Reg =
6909a593ee7SReid Kleckner           DVInst->getOperand(0).isReg() ? DVInst->getOperand(0).getReg() : 0;
6919a593ee7SReid Kleckner       if (Reg == 0)
6926e0d5f57SReid Kleckner         continue;
6936e0d5f57SReid Kleckner 
694876330d5SReid Kleckner       // Handle the two cases we can handle: indirect in memory and in register.
695876330d5SReid Kleckner       bool IsIndirect = DVInst->getOperand(1).isImm();
696876330d5SReid Kleckner       unsigned CVReg = TRI->getCodeViewRegNum(DVInst->getOperand(0).getReg());
697876330d5SReid Kleckner       {
698876330d5SReid Kleckner         LocalVarDefRange DefRange;
699876330d5SReid Kleckner         if (IsIndirect) {
700876330d5SReid Kleckner           int64_t Offset = DVInst->getOperand(1).getImm();
701876330d5SReid Kleckner           DefRange = createDefRangeMem(CVReg, Offset);
702876330d5SReid Kleckner         } else {
703876330d5SReid Kleckner           DefRange = createDefRangeReg(CVReg);
704876330d5SReid Kleckner         }
705876330d5SReid Kleckner         if (Var.DefRanges.empty() ||
706876330d5SReid Kleckner             Var.DefRanges.back().isDifferentLocation(DefRange)) {
707876330d5SReid Kleckner           Var.DefRanges.emplace_back(std::move(DefRange));
708876330d5SReid Kleckner         }
709876330d5SReid Kleckner       }
710876330d5SReid Kleckner 
711876330d5SReid Kleckner       // Compute the label range.
712876330d5SReid Kleckner       const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
713876330d5SReid Kleckner       const MCSymbol *End = getLabelAfterInsn(Range.second);
714876330d5SReid Kleckner       if (!End) {
715876330d5SReid Kleckner         if (std::next(I) != E)
716876330d5SReid Kleckner           End = getLabelBeforeInsn(std::next(I)->first);
717876330d5SReid Kleckner         else
718876330d5SReid Kleckner           End = Asm->getFunctionEnd();
719876330d5SReid Kleckner       }
720876330d5SReid Kleckner 
721876330d5SReid Kleckner       // If the last range end is our begin, just extend the last range.
722876330d5SReid Kleckner       // Otherwise make a new range.
723876330d5SReid Kleckner       SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &Ranges =
724876330d5SReid Kleckner           Var.DefRanges.back().Ranges;
725876330d5SReid Kleckner       if (!Ranges.empty() && Ranges.back().second == Begin)
726876330d5SReid Kleckner         Ranges.back().second = End;
727876330d5SReid Kleckner       else
728876330d5SReid Kleckner         Ranges.emplace_back(Begin, End);
729876330d5SReid Kleckner 
730876330d5SReid Kleckner       // FIXME: Do more range combining.
731876330d5SReid Kleckner     }
732876330d5SReid Kleckner 
733876330d5SReid Kleckner     recordLocalVariable(std::move(Var), InlinedAt);
734876330d5SReid Kleckner   }
735f9c275feSReid Kleckner }
736f9c275feSReid Kleckner 
73770f5bc99SReid Kleckner void CodeViewDebug::beginFunction(const MachineFunction *MF) {
73870f5bc99SReid Kleckner   assert(!CurFn && "Can't process two functions at once!");
73970f5bc99SReid Kleckner 
740f9c275feSReid Kleckner   if (!Asm || !MMI->hasDebugInfo())
74170f5bc99SReid Kleckner     return;
74270f5bc99SReid Kleckner 
743f9c275feSReid Kleckner   DebugHandlerBase::beginFunction(MF);
744f9c275feSReid Kleckner 
74570f5bc99SReid Kleckner   const Function *GV = MF->getFunction();
74670f5bc99SReid Kleckner   assert(FnDebugInfo.count(GV) == false);
74770f5bc99SReid Kleckner   CurFn = &FnDebugInfo[GV];
7482214ed89SReid Kleckner   CurFn->FuncId = NextFuncId++;
7491fcd610cSReid Kleckner   CurFn->Begin = Asm->getFunctionBegin();
75070f5bc99SReid Kleckner 
751f9c275feSReid Kleckner   // Find the end of the function prolog.  First known non-DBG_VALUE and
752f9c275feSReid Kleckner   // non-frame setup location marks the beginning of the function body.
75370f5bc99SReid Kleckner   // FIXME: is there a simpler a way to do this? Can we just search
75470f5bc99SReid Kleckner   // for the first instruction of the function, not the last of the prolog?
75570f5bc99SReid Kleckner   DebugLoc PrologEndLoc;
75670f5bc99SReid Kleckner   bool EmptyPrologue = true;
75770f5bc99SReid Kleckner   for (const auto &MBB : *MF) {
75870f5bc99SReid Kleckner     for (const auto &MI : MBB) {
759f9c275feSReid Kleckner       if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
760f9c275feSReid Kleckner           MI.getDebugLoc()) {
76170f5bc99SReid Kleckner         PrologEndLoc = MI.getDebugLoc();
76270f5bc99SReid Kleckner         break;
763f9c275feSReid Kleckner       } else if (!MI.isDebugValue()) {
76470f5bc99SReid Kleckner         EmptyPrologue = false;
76570f5bc99SReid Kleckner       }
76670f5bc99SReid Kleckner     }
767f9c275feSReid Kleckner   }
768f9c275feSReid Kleckner 
76970f5bc99SReid Kleckner   // Record beginning of function if we have a non-empty prologue.
77070f5bc99SReid Kleckner   if (PrologEndLoc && !EmptyPrologue) {
77170f5bc99SReid Kleckner     DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc();
77270f5bc99SReid Kleckner     maybeRecordLocation(FnStartDL, MF);
77370f5bc99SReid Kleckner   }
77470f5bc99SReid Kleckner }
77570f5bc99SReid Kleckner 
77676c9eb99SAmjad Aboud TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
7775acacbb0SReid Kleckner   // Generic dispatch for lowering an unknown type.
7785acacbb0SReid Kleckner   switch (Ty->getTag()) {
779f3c3c132SAdrian McCarthy   case dwarf::DW_TAG_array_type:
780f3c3c132SAdrian McCarthy     return lowerTypeArray(cast<DICompositeType>(Ty));
781d065e23dSDavid Majnemer   case dwarf::DW_TAG_typedef:
782d065e23dSDavid Majnemer     return lowerTypeAlias(cast<DIDerivedType>(Ty));
7835acacbb0SReid Kleckner   case dwarf::DW_TAG_base_type:
7845acacbb0SReid Kleckner     return lowerTypeBasic(cast<DIBasicType>(Ty));
7855acacbb0SReid Kleckner   case dwarf::DW_TAG_pointer_type:
7865acacbb0SReid Kleckner   case dwarf::DW_TAG_reference_type:
7875acacbb0SReid Kleckner   case dwarf::DW_TAG_rvalue_reference_type:
7885acacbb0SReid Kleckner     return lowerTypePointer(cast<DIDerivedType>(Ty));
7895acacbb0SReid Kleckner   case dwarf::DW_TAG_ptr_to_member_type:
7905acacbb0SReid Kleckner     return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
7915acacbb0SReid Kleckner   case dwarf::DW_TAG_const_type:
7925acacbb0SReid Kleckner   case dwarf::DW_TAG_volatile_type:
7935acacbb0SReid Kleckner     return lowerTypeModifier(cast<DIDerivedType>(Ty));
79475c3ebfaSDavid Majnemer   case dwarf::DW_TAG_subroutine_type:
79576c9eb99SAmjad Aboud     if (ClassTy)
79676c9eb99SAmjad Aboud       return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy);
79775c3ebfaSDavid Majnemer     return lowerTypeFunction(cast<DISubroutineType>(Ty));
798979cb888SDavid Majnemer   case dwarf::DW_TAG_enumeration_type:
799979cb888SDavid Majnemer     return lowerTypeEnum(cast<DICompositeType>(Ty));
800a8d57407SReid Kleckner   case dwarf::DW_TAG_class_type:
801a8d57407SReid Kleckner   case dwarf::DW_TAG_structure_type:
802a8d57407SReid Kleckner     return lowerTypeClass(cast<DICompositeType>(Ty));
803a8d57407SReid Kleckner   case dwarf::DW_TAG_union_type:
804a8d57407SReid Kleckner     return lowerTypeUnion(cast<DICompositeType>(Ty));
8055acacbb0SReid Kleckner   default:
8065acacbb0SReid Kleckner     // Use the null type index.
8075acacbb0SReid Kleckner     return TypeIndex();
8085acacbb0SReid Kleckner   }
8095acacbb0SReid Kleckner }
8105acacbb0SReid Kleckner 
811d065e23dSDavid Majnemer TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {
812d065e23dSDavid Majnemer   DITypeRef UnderlyingTypeRef = Ty->getBaseType();
813d065e23dSDavid Majnemer   TypeIndex UnderlyingTypeIndex = getTypeIndex(UnderlyingTypeRef);
8143128b10cSDavid Majnemer   StringRef TypeName = Ty->getName();
8153128b10cSDavid Majnemer 
8163128b10cSDavid Majnemer   SmallVector<StringRef, 5> QualifiedNameComponents;
8173128b10cSDavid Majnemer   const DISubprogram *ClosestSubprogram = getQualifiedNameComponents(
8183128b10cSDavid Majnemer       Ty->getScope().resolve(), QualifiedNameComponents);
8193128b10cSDavid Majnemer 
8203128b10cSDavid Majnemer   if (ClosestSubprogram == nullptr) {
8213128b10cSDavid Majnemer     std::string FullyQualifiedName =
8223128b10cSDavid Majnemer         getQualifiedName(QualifiedNameComponents, TypeName);
8233128b10cSDavid Majnemer     GlobalUDTs.emplace_back(std::move(FullyQualifiedName), UnderlyingTypeIndex);
8243128b10cSDavid Majnemer   } else if (ClosestSubprogram == CurrentSubprogram) {
8253128b10cSDavid Majnemer     std::string FullyQualifiedName =
8263128b10cSDavid Majnemer         getQualifiedName(QualifiedNameComponents, TypeName);
8273128b10cSDavid Majnemer     LocalUDTs.emplace_back(std::move(FullyQualifiedName), UnderlyingTypeIndex);
8283128b10cSDavid Majnemer   }
8293128b10cSDavid Majnemer   // TODO: What if the ClosestSubprogram is neither null or the current
8303128b10cSDavid Majnemer   // subprogram?  Currently, the UDT just gets dropped on the floor.
8313128b10cSDavid Majnemer   //
8323128b10cSDavid Majnemer   // The current behavior is not desirable.  To get maximal fidelity, we would
8333128b10cSDavid Majnemer   // need to perform all type translation before beginning emission of .debug$S
8343128b10cSDavid Majnemer   // and then make LocalUDTs a member of FunctionInfo
8353128b10cSDavid Majnemer 
836d065e23dSDavid Majnemer   if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
8373128b10cSDavid Majnemer       TypeName == "HRESULT")
838d065e23dSDavid Majnemer     return TypeIndex(SimpleTypeKind::HResult);
8398c46a4ceSDavid Majnemer   if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
8403128b10cSDavid Majnemer       TypeName == "wchar_t")
8418c46a4ceSDavid Majnemer     return TypeIndex(SimpleTypeKind::WideCharacter);
842d065e23dSDavid Majnemer   return UnderlyingTypeIndex;
843d065e23dSDavid Majnemer }
844d065e23dSDavid Majnemer 
845f3c3c132SAdrian McCarthy TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
846f3c3c132SAdrian McCarthy   DITypeRef ElementTypeRef = Ty->getBaseType();
847f3c3c132SAdrian McCarthy   TypeIndex ElementTypeIndex = getTypeIndex(ElementTypeRef);
848f3c3c132SAdrian McCarthy   // IndexType is size_t, which depends on the bitness of the target.
849f3c3c132SAdrian McCarthy   TypeIndex IndexType = Asm->MAI->getPointerSize() == 8
850f3c3c132SAdrian McCarthy                             ? TypeIndex(SimpleTypeKind::UInt64Quad)
851f3c3c132SAdrian McCarthy                             : TypeIndex(SimpleTypeKind::UInt32Long);
852f3c3c132SAdrian McCarthy   uint64_t Size = Ty->getSizeInBits() / 8;
853f3c3c132SAdrian McCarthy   ArrayRecord Record(ElementTypeIndex, IndexType, Size, Ty->getName());
854f3c3c132SAdrian McCarthy   return TypeTable.writeArray(Record);
855f3c3c132SAdrian McCarthy }
856f3c3c132SAdrian McCarthy 
8575acacbb0SReid Kleckner TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) {
8585acacbb0SReid Kleckner   TypeIndex Index;
8595acacbb0SReid Kleckner   dwarf::TypeKind Kind;
8605acacbb0SReid Kleckner   uint32_t ByteSize;
8615acacbb0SReid Kleckner 
8625acacbb0SReid Kleckner   Kind = static_cast<dwarf::TypeKind>(Ty->getEncoding());
863afefa673SDavid Majnemer   ByteSize = Ty->getSizeInBits() / 8;
8645acacbb0SReid Kleckner 
8655acacbb0SReid Kleckner   SimpleTypeKind STK = SimpleTypeKind::None;
8665acacbb0SReid Kleckner   switch (Kind) {
8675acacbb0SReid Kleckner   case dwarf::DW_ATE_address:
8685acacbb0SReid Kleckner     // FIXME: Translate
8695acacbb0SReid Kleckner     break;
8705acacbb0SReid Kleckner   case dwarf::DW_ATE_boolean:
8715acacbb0SReid Kleckner     switch (ByteSize) {
8725acacbb0SReid Kleckner     case 1:  STK = SimpleTypeKind::Boolean8;   break;
8735acacbb0SReid Kleckner     case 2:  STK = SimpleTypeKind::Boolean16;  break;
8745acacbb0SReid Kleckner     case 4:  STK = SimpleTypeKind::Boolean32;  break;
8755acacbb0SReid Kleckner     case 8:  STK = SimpleTypeKind::Boolean64;  break;
8761c2cb1ddSDavid Majnemer     case 16: STK = SimpleTypeKind::Boolean128; break;
8775acacbb0SReid Kleckner     }
8785acacbb0SReid Kleckner     break;
8795acacbb0SReid Kleckner   case dwarf::DW_ATE_complex_float:
8805acacbb0SReid Kleckner     switch (ByteSize) {
8811c2cb1ddSDavid Majnemer     case 2:  STK = SimpleTypeKind::Complex16;  break;
8825acacbb0SReid Kleckner     case 4:  STK = SimpleTypeKind::Complex32;  break;
8835acacbb0SReid Kleckner     case 8:  STK = SimpleTypeKind::Complex64;  break;
8845acacbb0SReid Kleckner     case 10: STK = SimpleTypeKind::Complex80;  break;
8855acacbb0SReid Kleckner     case 16: STK = SimpleTypeKind::Complex128; break;
8865acacbb0SReid Kleckner     }
8875acacbb0SReid Kleckner     break;
8885acacbb0SReid Kleckner   case dwarf::DW_ATE_float:
8895acacbb0SReid Kleckner     switch (ByteSize) {
8901c2cb1ddSDavid Majnemer     case 2:  STK = SimpleTypeKind::Float16;  break;
8915acacbb0SReid Kleckner     case 4:  STK = SimpleTypeKind::Float32;  break;
8925acacbb0SReid Kleckner     case 6:  STK = SimpleTypeKind::Float48;  break;
8935acacbb0SReid Kleckner     case 8:  STK = SimpleTypeKind::Float64;  break;
8945acacbb0SReid Kleckner     case 10: STK = SimpleTypeKind::Float80;  break;
8955acacbb0SReid Kleckner     case 16: STK = SimpleTypeKind::Float128; break;
8965acacbb0SReid Kleckner     }
8975acacbb0SReid Kleckner     break;
8985acacbb0SReid Kleckner   case dwarf::DW_ATE_signed:
8995acacbb0SReid Kleckner     switch (ByteSize) {
9005acacbb0SReid Kleckner     case 1:  STK = SimpleTypeKind::SByte;      break;
9015acacbb0SReid Kleckner     case 2:  STK = SimpleTypeKind::Int16Short; break;
9025acacbb0SReid Kleckner     case 4:  STK = SimpleTypeKind::Int32;      break;
9031c2cb1ddSDavid Majnemer     case 8:  STK = SimpleTypeKind::Int64Quad;  break;
9041c2cb1ddSDavid Majnemer     case 16: STK = SimpleTypeKind::Int128Oct;  break;
9055acacbb0SReid Kleckner     }
9065acacbb0SReid Kleckner     break;
9075acacbb0SReid Kleckner   case dwarf::DW_ATE_unsigned:
9085acacbb0SReid Kleckner     switch (ByteSize) {
9095acacbb0SReid Kleckner     case 1:  STK = SimpleTypeKind::Byte;        break;
9105acacbb0SReid Kleckner     case 2:  STK = SimpleTypeKind::UInt16Short; break;
9115acacbb0SReid Kleckner     case 4:  STK = SimpleTypeKind::UInt32;      break;
9121c2cb1ddSDavid Majnemer     case 8:  STK = SimpleTypeKind::UInt64Quad;  break;
9131c2cb1ddSDavid Majnemer     case 16: STK = SimpleTypeKind::UInt128Oct;  break;
9145acacbb0SReid Kleckner     }
9155acacbb0SReid Kleckner     break;
9165acacbb0SReid Kleckner   case dwarf::DW_ATE_UTF:
9175acacbb0SReid Kleckner     switch (ByteSize) {
9185acacbb0SReid Kleckner     case 2: STK = SimpleTypeKind::Character16; break;
9195acacbb0SReid Kleckner     case 4: STK = SimpleTypeKind::Character32; break;
9205acacbb0SReid Kleckner     }
9215acacbb0SReid Kleckner     break;
9225acacbb0SReid Kleckner   case dwarf::DW_ATE_signed_char:
9235acacbb0SReid Kleckner     if (ByteSize == 1)
9245acacbb0SReid Kleckner       STK = SimpleTypeKind::SignedCharacter;
9255acacbb0SReid Kleckner     break;
9265acacbb0SReid Kleckner   case dwarf::DW_ATE_unsigned_char:
9275acacbb0SReid Kleckner     if (ByteSize == 1)
9285acacbb0SReid Kleckner       STK = SimpleTypeKind::UnsignedCharacter;
9295acacbb0SReid Kleckner     break;
9305acacbb0SReid Kleckner   default:
9315acacbb0SReid Kleckner     break;
9325acacbb0SReid Kleckner   }
9335acacbb0SReid Kleckner 
9345acacbb0SReid Kleckner   // Apply some fixups based on the source-level type name.
9355acacbb0SReid Kleckner   if (STK == SimpleTypeKind::Int32 && Ty->getName() == "long int")
9365acacbb0SReid Kleckner     STK = SimpleTypeKind::Int32Long;
9375acacbb0SReid Kleckner   if (STK == SimpleTypeKind::UInt32 && Ty->getName() == "long unsigned int")
9385acacbb0SReid Kleckner     STK = SimpleTypeKind::UInt32Long;
9398c46a4ceSDavid Majnemer   if (STK == SimpleTypeKind::UInt16Short &&
9408c46a4ceSDavid Majnemer       (Ty->getName() == "wchar_t" || Ty->getName() == "__wchar_t"))
9415acacbb0SReid Kleckner     STK = SimpleTypeKind::WideCharacter;
9425acacbb0SReid Kleckner   if ((STK == SimpleTypeKind::SignedCharacter ||
9435acacbb0SReid Kleckner        STK == SimpleTypeKind::UnsignedCharacter) &&
9445acacbb0SReid Kleckner       Ty->getName() == "char")
9455acacbb0SReid Kleckner     STK = SimpleTypeKind::NarrowCharacter;
9465acacbb0SReid Kleckner 
9475acacbb0SReid Kleckner   return TypeIndex(STK);
9485acacbb0SReid Kleckner }
9495acacbb0SReid Kleckner 
9505acacbb0SReid Kleckner TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) {
9515acacbb0SReid Kleckner   TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
9525acacbb0SReid Kleckner 
95376c9eb99SAmjad Aboud   // While processing the type being pointed to it is possible we already
95476c9eb99SAmjad Aboud   // created this pointer type.  If so, we check here and return the existing
95576c9eb99SAmjad Aboud   // pointer type.
95676c9eb99SAmjad Aboud   auto I = TypeIndices.find({Ty, nullptr});
95776c9eb99SAmjad Aboud   if (I != TypeIndices.end())
95876c9eb99SAmjad Aboud     return I->second;
95976c9eb99SAmjad Aboud 
9605acacbb0SReid Kleckner   // Pointers to simple types can use SimpleTypeMode, rather than having a
9615acacbb0SReid Kleckner   // dedicated pointer type record.
9625acacbb0SReid Kleckner   if (PointeeTI.isSimple() &&
9635acacbb0SReid Kleckner       PointeeTI.getSimpleMode() == SimpleTypeMode::Direct &&
9645acacbb0SReid Kleckner       Ty->getTag() == dwarf::DW_TAG_pointer_type) {
9655acacbb0SReid Kleckner     SimpleTypeMode Mode = Ty->getSizeInBits() == 64
9665acacbb0SReid Kleckner                               ? SimpleTypeMode::NearPointer64
9675acacbb0SReid Kleckner                               : SimpleTypeMode::NearPointer32;
9685acacbb0SReid Kleckner     return TypeIndex(PointeeTI.getSimpleKind(), Mode);
9695acacbb0SReid Kleckner   }
9705acacbb0SReid Kleckner 
9715acacbb0SReid Kleckner   PointerKind PK =
9725acacbb0SReid Kleckner       Ty->getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
9735acacbb0SReid Kleckner   PointerMode PM = PointerMode::Pointer;
9745acacbb0SReid Kleckner   switch (Ty->getTag()) {
9755acacbb0SReid Kleckner   default: llvm_unreachable("not a pointer tag type");
9765acacbb0SReid Kleckner   case dwarf::DW_TAG_pointer_type:
9775acacbb0SReid Kleckner     PM = PointerMode::Pointer;
9785acacbb0SReid Kleckner     break;
9795acacbb0SReid Kleckner   case dwarf::DW_TAG_reference_type:
9805acacbb0SReid Kleckner     PM = PointerMode::LValueReference;
9815acacbb0SReid Kleckner     break;
9825acacbb0SReid Kleckner   case dwarf::DW_TAG_rvalue_reference_type:
9835acacbb0SReid Kleckner     PM = PointerMode::RValueReference;
9845acacbb0SReid Kleckner     break;
9855acacbb0SReid Kleckner   }
9865acacbb0SReid Kleckner   // FIXME: MSVC folds qualifiers into PointerOptions in the context of a method
9875acacbb0SReid Kleckner   // 'this' pointer, but not normal contexts. Figure out what we're supposed to
9885acacbb0SReid Kleckner   // do.
9895acacbb0SReid Kleckner   PointerOptions PO = PointerOptions::None;
9905acacbb0SReid Kleckner   PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
9915acacbb0SReid Kleckner   return TypeTable.writePointer(PR);
9925acacbb0SReid Kleckner }
9935acacbb0SReid Kleckner 
9946fa1546aSReid Kleckner static PointerToMemberRepresentation
9956fa1546aSReid Kleckner translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags) {
9966fa1546aSReid Kleckner   // SizeInBytes being zero generally implies that the member pointer type was
9976fa1546aSReid Kleckner   // incomplete, which can happen if it is part of a function prototype. In this
9986fa1546aSReid Kleckner   // case, use the unknown model instead of the general model.
999604105bbSReid Kleckner   if (IsPMF) {
1000604105bbSReid Kleckner     switch (Flags & DINode::FlagPtrToMemberRep) {
1001604105bbSReid Kleckner     case 0:
10026fa1546aSReid Kleckner       return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
10036fa1546aSReid Kleckner                               : PointerToMemberRepresentation::GeneralFunction;
1004604105bbSReid Kleckner     case DINode::FlagSingleInheritance:
1005604105bbSReid Kleckner       return PointerToMemberRepresentation::SingleInheritanceFunction;
1006604105bbSReid Kleckner     case DINode::FlagMultipleInheritance:
1007604105bbSReid Kleckner       return PointerToMemberRepresentation::MultipleInheritanceFunction;
1008604105bbSReid Kleckner     case DINode::FlagVirtualInheritance:
1009604105bbSReid Kleckner       return PointerToMemberRepresentation::VirtualInheritanceFunction;
1010604105bbSReid Kleckner     }
1011604105bbSReid Kleckner   } else {
1012604105bbSReid Kleckner     switch (Flags & DINode::FlagPtrToMemberRep) {
1013604105bbSReid Kleckner     case 0:
10146fa1546aSReid Kleckner       return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
10156fa1546aSReid Kleckner                               : PointerToMemberRepresentation::GeneralData;
1016604105bbSReid Kleckner     case DINode::FlagSingleInheritance:
1017604105bbSReid Kleckner       return PointerToMemberRepresentation::SingleInheritanceData;
1018604105bbSReid Kleckner     case DINode::FlagMultipleInheritance:
1019604105bbSReid Kleckner       return PointerToMemberRepresentation::MultipleInheritanceData;
1020604105bbSReid Kleckner     case DINode::FlagVirtualInheritance:
1021604105bbSReid Kleckner       return PointerToMemberRepresentation::VirtualInheritanceData;
1022604105bbSReid Kleckner     }
1023604105bbSReid Kleckner   }
1024604105bbSReid Kleckner   llvm_unreachable("invalid ptr to member representation");
1025604105bbSReid Kleckner }
1026604105bbSReid Kleckner 
10275acacbb0SReid Kleckner TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) {
10285acacbb0SReid Kleckner   assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
10295acacbb0SReid Kleckner   TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
103076c9eb99SAmjad Aboud   TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType());
10315acacbb0SReid Kleckner   PointerKind PK = Asm->MAI->getPointerSize() == 8 ? PointerKind::Near64
10325acacbb0SReid Kleckner                                                    : PointerKind::Near32;
1033604105bbSReid Kleckner   bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
1034604105bbSReid Kleckner   PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
10355acacbb0SReid Kleckner                          : PointerMode::PointerToDataMember;
10365acacbb0SReid Kleckner   PointerOptions PO = PointerOptions::None; // FIXME
10376fa1546aSReid Kleckner   assert(Ty->getSizeInBits() / 8 <= 0xff && "pointer size too big");
10386fa1546aSReid Kleckner   uint8_t SizeInBytes = Ty->getSizeInBits() / 8;
10396fa1546aSReid Kleckner   MemberPointerInfo MPI(
10406fa1546aSReid Kleckner       ClassTI, translatePtrToMemberRep(SizeInBytes, IsPMF, Ty->getFlags()));
1041604105bbSReid Kleckner   PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
10425acacbb0SReid Kleckner   return TypeTable.writePointer(PR);
10435acacbb0SReid Kleckner }
10445acacbb0SReid Kleckner 
1045de3d8b50SReid Kleckner /// Given a DWARF calling convention, get the CodeView equivalent. If we don't
1046de3d8b50SReid Kleckner /// have a translation, use the NearC convention.
1047de3d8b50SReid Kleckner static CallingConvention dwarfCCToCodeView(unsigned DwarfCC) {
1048de3d8b50SReid Kleckner   switch (DwarfCC) {
1049de3d8b50SReid Kleckner   case dwarf::DW_CC_normal:             return CallingConvention::NearC;
1050de3d8b50SReid Kleckner   case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;
1051de3d8b50SReid Kleckner   case dwarf::DW_CC_BORLAND_thiscall:   return CallingConvention::ThisCall;
1052de3d8b50SReid Kleckner   case dwarf::DW_CC_BORLAND_stdcall:    return CallingConvention::NearStdCall;
1053de3d8b50SReid Kleckner   case dwarf::DW_CC_BORLAND_pascal:     return CallingConvention::NearPascal;
1054de3d8b50SReid Kleckner   case dwarf::DW_CC_LLVM_vectorcall:    return CallingConvention::NearVector;
1055de3d8b50SReid Kleckner   }
1056de3d8b50SReid Kleckner   return CallingConvention::NearC;
1057de3d8b50SReid Kleckner }
1058de3d8b50SReid Kleckner 
10595acacbb0SReid Kleckner TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
10605acacbb0SReid Kleckner   ModifierOptions Mods = ModifierOptions::None;
10615acacbb0SReid Kleckner   bool IsModifier = true;
10625acacbb0SReid Kleckner   const DIType *BaseTy = Ty;
1063b9c80fd8SReid Kleckner   while (IsModifier && BaseTy) {
10645acacbb0SReid Kleckner     // FIXME: Need to add DWARF tag for __unaligned.
10655acacbb0SReid Kleckner     switch (BaseTy->getTag()) {
10665acacbb0SReid Kleckner     case dwarf::DW_TAG_const_type:
10675acacbb0SReid Kleckner       Mods |= ModifierOptions::Const;
10685acacbb0SReid Kleckner       break;
10695acacbb0SReid Kleckner     case dwarf::DW_TAG_volatile_type:
10705acacbb0SReid Kleckner       Mods |= ModifierOptions::Volatile;
10715acacbb0SReid Kleckner       break;
10725acacbb0SReid Kleckner     default:
10735acacbb0SReid Kleckner       IsModifier = false;
10745acacbb0SReid Kleckner       break;
10755acacbb0SReid Kleckner     }
10765acacbb0SReid Kleckner     if (IsModifier)
10775acacbb0SReid Kleckner       BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType().resolve();
10785acacbb0SReid Kleckner   }
10795acacbb0SReid Kleckner   TypeIndex ModifiedTI = getTypeIndex(BaseTy);
108076c9eb99SAmjad Aboud 
108176c9eb99SAmjad Aboud   // While processing the type being pointed to, it is possible we already
108276c9eb99SAmjad Aboud   // created this modifier type.  If so, we check here and return the existing
108376c9eb99SAmjad Aboud   // modifier type.
108476c9eb99SAmjad Aboud   auto I = TypeIndices.find({Ty, nullptr});
108576c9eb99SAmjad Aboud   if (I != TypeIndices.end())
108676c9eb99SAmjad Aboud     return I->second;
108776c9eb99SAmjad Aboud 
10885acacbb0SReid Kleckner   ModifierRecord MR(ModifiedTI, Mods);
10895acacbb0SReid Kleckner   return TypeTable.writeModifier(MR);
10905acacbb0SReid Kleckner }
10915acacbb0SReid Kleckner 
109275c3ebfaSDavid Majnemer TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
109375c3ebfaSDavid Majnemer   SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
109475c3ebfaSDavid Majnemer   for (DITypeRef ArgTypeRef : Ty->getTypeArray())
109575c3ebfaSDavid Majnemer     ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
109675c3ebfaSDavid Majnemer 
109775c3ebfaSDavid Majnemer   TypeIndex ReturnTypeIndex = TypeIndex::Void();
109875c3ebfaSDavid Majnemer   ArrayRef<TypeIndex> ArgTypeIndices = None;
109975c3ebfaSDavid Majnemer   if (!ReturnAndArgTypeIndices.empty()) {
110075c3ebfaSDavid Majnemer     auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices);
110175c3ebfaSDavid Majnemer     ReturnTypeIndex = ReturnAndArgTypesRef.front();
110275c3ebfaSDavid Majnemer     ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
110375c3ebfaSDavid Majnemer   }
110475c3ebfaSDavid Majnemer 
110575c3ebfaSDavid Majnemer   ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
110675c3ebfaSDavid Majnemer   TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
110775c3ebfaSDavid Majnemer 
1108de3d8b50SReid Kleckner   CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
1109de3d8b50SReid Kleckner 
1110de3d8b50SReid Kleckner   ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
1111de3d8b50SReid Kleckner                             ArgTypeIndices.size(), ArgListIndex);
111275c3ebfaSDavid Majnemer   return TypeTable.writeProcedure(Procedure);
111375c3ebfaSDavid Majnemer }
111475c3ebfaSDavid Majnemer 
111576c9eb99SAmjad Aboud TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
111676c9eb99SAmjad Aboud                                                  const DIType *ClassTy) {
111776c9eb99SAmjad Aboud   // Lower the containing class type.
111876c9eb99SAmjad Aboud   TypeIndex ClassType = getTypeIndex(ClassTy);
111976c9eb99SAmjad Aboud 
112076c9eb99SAmjad Aboud   // While processing the class type it is possible we already created this
112176c9eb99SAmjad Aboud   // member function.  If so, we check here and return the existing one.
112276c9eb99SAmjad Aboud   auto I = TypeIndices.find({Ty, ClassTy});
112376c9eb99SAmjad Aboud   if (I != TypeIndices.end())
112476c9eb99SAmjad Aboud     return I->second;
112576c9eb99SAmjad Aboud 
112676c9eb99SAmjad Aboud   SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
112776c9eb99SAmjad Aboud   for (DITypeRef ArgTypeRef : Ty->getTypeArray())
112876c9eb99SAmjad Aboud     ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
112976c9eb99SAmjad Aboud 
113076c9eb99SAmjad Aboud   TypeIndex ReturnTypeIndex = TypeIndex::Void();
113176c9eb99SAmjad Aboud   ArrayRef<TypeIndex> ArgTypeIndices = None;
113276c9eb99SAmjad Aboud   if (!ReturnAndArgTypeIndices.empty()) {
113376c9eb99SAmjad Aboud     auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices);
113476c9eb99SAmjad Aboud     ReturnTypeIndex = ReturnAndArgTypesRef.front();
113576c9eb99SAmjad Aboud     ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
113676c9eb99SAmjad Aboud   }
113776c9eb99SAmjad Aboud   TypeIndex ThisTypeIndex = TypeIndex::Void();
113876c9eb99SAmjad Aboud   if (!ArgTypeIndices.empty()) {
113976c9eb99SAmjad Aboud     ThisTypeIndex = ArgTypeIndices.front();
114076c9eb99SAmjad Aboud     ArgTypeIndices = ArgTypeIndices.drop_front();
114176c9eb99SAmjad Aboud   }
114276c9eb99SAmjad Aboud 
114376c9eb99SAmjad Aboud   ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
114476c9eb99SAmjad Aboud   TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
114576c9eb99SAmjad Aboud 
114676c9eb99SAmjad Aboud   CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
114776c9eb99SAmjad Aboud 
114876c9eb99SAmjad Aboud   // TODO: Need to use the correct values for:
114976c9eb99SAmjad Aboud   //       FunctionOptions
115076c9eb99SAmjad Aboud   //       ThisPointerAdjustment.
115176c9eb99SAmjad Aboud   TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord(
115276c9eb99SAmjad Aboud       ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None,
115376c9eb99SAmjad Aboud       ArgTypeIndices.size(), ArgListIndex, 0));
115476c9eb99SAmjad Aboud 
115576c9eb99SAmjad Aboud   return TI;
115676c9eb99SAmjad Aboud }
115776c9eb99SAmjad Aboud 
115876c9eb99SAmjad Aboud TypeIndex CodeViewDebug::lowerSubprogramType(const DISubprogram *SP) {
115976c9eb99SAmjad Aboud   auto ClassType = dyn_cast_or_null<DIType>(SP->getScope().resolve());
116076c9eb99SAmjad Aboud   TypeIndex TI = getTypeIndex(SP->getType(), ClassType);
116176c9eb99SAmjad Aboud 
116276c9eb99SAmjad Aboud   return TI;
116376c9eb99SAmjad Aboud }
116476c9eb99SAmjad Aboud 
116576c9eb99SAmjad Aboud static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags) {
116676c9eb99SAmjad Aboud   switch (Flags & DINode::FlagAccessibility) {
1167a8d57407SReid Kleckner   case DINode::FlagPrivate:   return MemberAccess::Private;
1168a8d57407SReid Kleckner   case DINode::FlagPublic:    return MemberAccess::Public;
1169a8d57407SReid Kleckner   case DINode::FlagProtected: return MemberAccess::Protected;
1170a8d57407SReid Kleckner   case 0:
1171a8d57407SReid Kleckner     // If there was no explicit access control, provide the default for the tag.
1172a8d57407SReid Kleckner     return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
1173a8d57407SReid Kleckner                                                  : MemberAccess::Public;
1174a8d57407SReid Kleckner   }
1175a8d57407SReid Kleckner   llvm_unreachable("access flags are exclusive");
1176a8d57407SReid Kleckner }
1177a8d57407SReid Kleckner 
117876c9eb99SAmjad Aboud static MethodOptions translateMethodOptionFlags(const DISubprogram *SP) {
117976c9eb99SAmjad Aboud   if (SP->isArtificial())
118076c9eb99SAmjad Aboud     return MethodOptions::CompilerGenerated;
118176c9eb99SAmjad Aboud 
118276c9eb99SAmjad Aboud   // FIXME: Handle other MethodOptions.
118376c9eb99SAmjad Aboud 
118476c9eb99SAmjad Aboud   return MethodOptions::None;
118576c9eb99SAmjad Aboud }
118676c9eb99SAmjad Aboud 
118776c9eb99SAmjad Aboud static MethodKind translateMethodKindFlags(const DISubprogram *SP,
118876c9eb99SAmjad Aboud                                            bool Introduced) {
118976c9eb99SAmjad Aboud   switch (SP->getVirtuality()) {
119076c9eb99SAmjad Aboud   case dwarf::DW_VIRTUALITY_none:
119176c9eb99SAmjad Aboud     break;
119276c9eb99SAmjad Aboud   case dwarf::DW_VIRTUALITY_virtual:
119376c9eb99SAmjad Aboud     return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
119476c9eb99SAmjad Aboud   case dwarf::DW_VIRTUALITY_pure_virtual:
119576c9eb99SAmjad Aboud     return Introduced ? MethodKind::PureIntroducingVirtual
119676c9eb99SAmjad Aboud                       : MethodKind::PureVirtual;
119776c9eb99SAmjad Aboud   default:
119876c9eb99SAmjad Aboud     llvm_unreachable("unhandled virtuality case");
119976c9eb99SAmjad Aboud   }
120076c9eb99SAmjad Aboud 
120176c9eb99SAmjad Aboud   // FIXME: Get Clang to mark DISubprogram as static and do something with it.
120276c9eb99SAmjad Aboud 
120376c9eb99SAmjad Aboud   return MethodKind::Vanilla;
120476c9eb99SAmjad Aboud }
120576c9eb99SAmjad Aboud 
1206a8d57407SReid Kleckner static TypeRecordKind getRecordKind(const DICompositeType *Ty) {
1207a8d57407SReid Kleckner   switch (Ty->getTag()) {
1208a8d57407SReid Kleckner   case dwarf::DW_TAG_class_type:     return TypeRecordKind::Class;
1209a8d57407SReid Kleckner   case dwarf::DW_TAG_structure_type: return TypeRecordKind::Struct;
1210a8d57407SReid Kleckner   }
1211a8d57407SReid Kleckner   llvm_unreachable("unexpected tag");
1212a8d57407SReid Kleckner }
1213a8d57407SReid Kleckner 
1214a8d57407SReid Kleckner /// Return the HasUniqueName option if it should be present in ClassOptions, or
1215a8d57407SReid Kleckner /// None otherwise.
1216a8d57407SReid Kleckner static ClassOptions getRecordUniqueNameOption(const DICompositeType *Ty) {
1217a8d57407SReid Kleckner   // MSVC always sets this flag now, even for local types. Clang doesn't always
1218a8d57407SReid Kleckner   // appear to give every type a linkage name, which may be problematic for us.
1219a8d57407SReid Kleckner   // FIXME: Investigate the consequences of not following them here.
1220a8d57407SReid Kleckner   return !Ty->getIdentifier().empty() ? ClassOptions::HasUniqueName
1221a8d57407SReid Kleckner                                       : ClassOptions::None;
1222a8d57407SReid Kleckner }
1223a8d57407SReid Kleckner 
1224979cb888SDavid Majnemer TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
1225979cb888SDavid Majnemer   ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
1226979cb888SDavid Majnemer   TypeIndex FTI;
1227da9548f9SDavid Majnemer   unsigned EnumeratorCount = 0;
1228979cb888SDavid Majnemer 
1229da9548f9SDavid Majnemer   if (Ty->isForwardDecl()) {
1230979cb888SDavid Majnemer     CO |= ClassOptions::ForwardReference;
1231da9548f9SDavid Majnemer   } else {
1232da9548f9SDavid Majnemer     FieldListRecordBuilder Fields;
1233da9548f9SDavid Majnemer     for (const DINode *Element : Ty->getElements()) {
1234da9548f9SDavid Majnemer       // We assume that the frontend provides all members in source declaration
1235da9548f9SDavid Majnemer       // order, which is what MSVC does.
1236da9548f9SDavid Majnemer       if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
1237da9548f9SDavid Majnemer         Fields.writeEnumerator(EnumeratorRecord(
1238da9548f9SDavid Majnemer             MemberAccess::Public, APSInt::getUnsigned(Enumerator->getValue()),
1239da9548f9SDavid Majnemer             Enumerator->getName()));
1240da9548f9SDavid Majnemer         EnumeratorCount++;
1241da9548f9SDavid Majnemer       }
1242da9548f9SDavid Majnemer     }
1243da9548f9SDavid Majnemer     FTI = TypeTable.writeFieldList(Fields);
1244da9548f9SDavid Majnemer   }
1245979cb888SDavid Majnemer 
1246da9548f9SDavid Majnemer   return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, Ty->getName(),
1247979cb888SDavid Majnemer                                         Ty->getIdentifier(),
1248979cb888SDavid Majnemer                                         getTypeIndex(Ty->getBaseType())));
1249979cb888SDavid Majnemer }
1250979cb888SDavid Majnemer 
125176c9eb99SAmjad Aboud //===----------------------------------------------------------------------===//
125276c9eb99SAmjad Aboud // ClassInfo
125376c9eb99SAmjad Aboud //===----------------------------------------------------------------------===//
125476c9eb99SAmjad Aboud 
125576c9eb99SAmjad Aboud struct llvm::ClassInfo {
125676c9eb99SAmjad Aboud   struct MemberInfo {
125776c9eb99SAmjad Aboud     const DIDerivedType *MemberTypeNode;
125876c9eb99SAmjad Aboud     unsigned BaseOffset;
125976c9eb99SAmjad Aboud   };
126076c9eb99SAmjad Aboud   // [MemberInfo]
126176c9eb99SAmjad Aboud   typedef std::vector<MemberInfo> MemberList;
126276c9eb99SAmjad Aboud 
126376c9eb99SAmjad Aboud   struct MethodInfo {
126476c9eb99SAmjad Aboud     const DISubprogram *Method;
126576c9eb99SAmjad Aboud     bool Introduced;
126676c9eb99SAmjad Aboud   };
126776c9eb99SAmjad Aboud   // [MethodInfo]
126876c9eb99SAmjad Aboud   typedef std::vector<MethodInfo> MethodsList;
126976c9eb99SAmjad Aboud   // MethodName -> MethodsList
127076c9eb99SAmjad Aboud   typedef MapVector<MDString *, MethodsList> MethodsMap;
127176c9eb99SAmjad Aboud 
127276c9eb99SAmjad Aboud   /// Direct members.
127376c9eb99SAmjad Aboud   MemberList Members;
127476c9eb99SAmjad Aboud   // Direct overloaded methods gathered by name.
127576c9eb99SAmjad Aboud   MethodsMap Methods;
127676c9eb99SAmjad Aboud };
127776c9eb99SAmjad Aboud 
127876c9eb99SAmjad Aboud void CodeViewDebug::clear() {
127976c9eb99SAmjad Aboud   assert(CurFn == nullptr);
128076c9eb99SAmjad Aboud   FileIdMap.clear();
128176c9eb99SAmjad Aboud   FnDebugInfo.clear();
128276c9eb99SAmjad Aboud   FileToFilepathMap.clear();
128376c9eb99SAmjad Aboud   LocalUDTs.clear();
128476c9eb99SAmjad Aboud   GlobalUDTs.clear();
128576c9eb99SAmjad Aboud   TypeIndices.clear();
128676c9eb99SAmjad Aboud   CompleteTypeIndices.clear();
128776c9eb99SAmjad Aboud   ClassInfoMap.clear();
128876c9eb99SAmjad Aboud }
128976c9eb99SAmjad Aboud 
129076c9eb99SAmjad Aboud void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
129176c9eb99SAmjad Aboud                                       const DIDerivedType *DDTy) {
129276c9eb99SAmjad Aboud   if (!DDTy->getName().empty()) {
129376c9eb99SAmjad Aboud     Info.Members.push_back({DDTy, 0});
129476c9eb99SAmjad Aboud     return;
129576c9eb99SAmjad Aboud   }
129676c9eb99SAmjad Aboud   // Member with no name, must be nested structure/union, collects its memebers
129776c9eb99SAmjad Aboud   assert((DDTy->getOffsetInBits() % 8) == 0 && "Unnamed bitfield member!");
129876c9eb99SAmjad Aboud   unsigned offset = DDTy->getOffsetInBits() / 8;
129976c9eb99SAmjad Aboud   const DIType *Ty = DDTy->getBaseType().resolve();
1300*9ff936cfSReid Kleckner   const DICompositeType *DCTy = cast<DICompositeType>(Ty);
130176c9eb99SAmjad Aboud   ClassInfo &NestedInfo = collectClassInfo(DCTy);
130276c9eb99SAmjad Aboud   ClassInfo::MemberList &Members = NestedInfo.Members;
130376c9eb99SAmjad Aboud   for (unsigned i = 0, e = Members.size(); i != e; ++i)
130476c9eb99SAmjad Aboud     Info.Members.push_back(
130576c9eb99SAmjad Aboud         {Members[i].MemberTypeNode, Members[i].BaseOffset + offset});
130676c9eb99SAmjad Aboud }
130776c9eb99SAmjad Aboud 
130876c9eb99SAmjad Aboud ClassInfo &CodeViewDebug::collectClassInfo(const DICompositeType *Ty) {
130976c9eb99SAmjad Aboud   auto Insertion = ClassInfoMap.insert({Ty, std::unique_ptr<ClassInfo>()});
1310*9ff936cfSReid Kleckner   ClassInfo *Info = nullptr;
1311*9ff936cfSReid Kleckner   {
1312*9ff936cfSReid Kleckner     std::unique_ptr<ClassInfo> &InfoEntry = Insertion.first->second;
131376c9eb99SAmjad Aboud     if (!Insertion.second)
1314*9ff936cfSReid Kleckner       return *InfoEntry;
1315*9ff936cfSReid Kleckner     InfoEntry.reset(new ClassInfo());
1316*9ff936cfSReid Kleckner     Info = InfoEntry.get();
1317*9ff936cfSReid Kleckner   }
131876c9eb99SAmjad Aboud 
131976c9eb99SAmjad Aboud   // Add elements to structure type.
132076c9eb99SAmjad Aboud   DINodeArray Elements = Ty->getElements();
132176c9eb99SAmjad Aboud   for (auto *Element : Elements) {
132276c9eb99SAmjad Aboud     // We assume that the frontend provides all members in source declaration
132376c9eb99SAmjad Aboud     // order, which is what MSVC does.
132476c9eb99SAmjad Aboud     if (!Element)
132576c9eb99SAmjad Aboud       continue;
132676c9eb99SAmjad Aboud     if (auto *SP = dyn_cast<DISubprogram>(Element)) {
132776c9eb99SAmjad Aboud       // Non-virtual methods does not need the introduced marker.
132876c9eb99SAmjad Aboud       // Set it to false.
132976c9eb99SAmjad Aboud       bool Introduced = false;
133076c9eb99SAmjad Aboud       Info->Methods[SP->getRawName()].push_back({SP, Introduced});
133176c9eb99SAmjad Aboud     } else if (auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
133276c9eb99SAmjad Aboud       if (DDTy->getTag() == dwarf::DW_TAG_member)
133376c9eb99SAmjad Aboud         collectMemberInfo(*Info, DDTy);
133476c9eb99SAmjad Aboud       else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {
133576c9eb99SAmjad Aboud         // FIXME: collect class info from inheritance.
133676c9eb99SAmjad Aboud       } else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
133776c9eb99SAmjad Aboud         // Ignore friend members. It appears that MSVC emitted info about
133876c9eb99SAmjad Aboud         // friends in the past, but modern versions do not.
133976c9eb99SAmjad Aboud       }
134076c9eb99SAmjad Aboud       // FIXME: Get Clang to emit function virtual table here and handle it.
134176c9eb99SAmjad Aboud       // FIXME: Get clang to emit nested types here and do something with
134276c9eb99SAmjad Aboud       // them.
134376c9eb99SAmjad Aboud     }
134476c9eb99SAmjad Aboud     // Skip other unrecognized kinds of elements.
134576c9eb99SAmjad Aboud   }
134676c9eb99SAmjad Aboud 
134776c9eb99SAmjad Aboud   return *Info;
134876c9eb99SAmjad Aboud }
134976c9eb99SAmjad Aboud 
1350a8d57407SReid Kleckner TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
1351a8d57407SReid Kleckner   // First, construct the forward decl.  Don't look into Ty to compute the
1352a8d57407SReid Kleckner   // forward decl options, since it might not be available in all TUs.
1353a8d57407SReid Kleckner   TypeRecordKind Kind = getRecordKind(Ty);
1354a8d57407SReid Kleckner   ClassOptions CO =
1355a8d57407SReid Kleckner       ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
1356a8d57407SReid Kleckner   TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord(
1357a8d57407SReid Kleckner       Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(),
1358a8d57407SReid Kleckner       TypeIndex(), TypeIndex(), 0, Ty->getName(), Ty->getIdentifier()));
1359a8d57407SReid Kleckner   return FwdDeclTI;
1360a8d57407SReid Kleckner }
1361a8d57407SReid Kleckner 
1362a8d57407SReid Kleckner TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
1363a8d57407SReid Kleckner   // Construct the field list and complete type record.
1364a8d57407SReid Kleckner   TypeRecordKind Kind = getRecordKind(Ty);
1365a8d57407SReid Kleckner   // FIXME: Other ClassOptions, like ContainsNestedClass and NestedClass.
1366a8d57407SReid Kleckner   ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
136776c9eb99SAmjad Aboud   TypeIndex FieldTI;
136876c9eb99SAmjad Aboud   TypeIndex VShapeTI;
1369a8d57407SReid Kleckner   unsigned FieldCount;
137076c9eb99SAmjad Aboud   std::tie(FieldTI, VShapeTI, FieldCount) = lowerRecordFieldList(Ty);
1371a8d57407SReid Kleckner 
1372a8d57407SReid Kleckner   uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
137376c9eb99SAmjad Aboud   return TypeTable.writeClass(ClassRecord(
137476c9eb99SAmjad Aboud       Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI,
137576c9eb99SAmjad Aboud       TypeIndex(), VShapeTI, SizeInBytes, Ty->getName(), Ty->getIdentifier()));
1376a8d57407SReid Kleckner   // FIXME: Make an LF_UDT_SRC_LINE record.
1377a8d57407SReid Kleckner }
1378a8d57407SReid Kleckner 
1379a8d57407SReid Kleckner TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
1380a8d57407SReid Kleckner   ClassOptions CO =
1381a8d57407SReid Kleckner       ClassOptions::ForwardReference | getRecordUniqueNameOption(Ty);
1382a8d57407SReid Kleckner   TypeIndex FwdDeclTI =
1383a8d57407SReid Kleckner       TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0,
1384a8d57407SReid Kleckner                                        Ty->getName(), Ty->getIdentifier()));
1385a8d57407SReid Kleckner   return FwdDeclTI;
1386a8d57407SReid Kleckner }
1387a8d57407SReid Kleckner 
1388a8d57407SReid Kleckner TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
1389a8d57407SReid Kleckner   ClassOptions CO = ClassOptions::None | getRecordUniqueNameOption(Ty);
139076c9eb99SAmjad Aboud   TypeIndex FieldTI;
1391a8d57407SReid Kleckner   unsigned FieldCount;
139276c9eb99SAmjad Aboud   std::tie(FieldTI, std::ignore, FieldCount) = lowerRecordFieldList(Ty);
1393a8d57407SReid Kleckner   uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
139476c9eb99SAmjad Aboud   return TypeTable.writeUnion(UnionRecord(FieldCount, CO, HfaKind::None,
139576c9eb99SAmjad Aboud                                           FieldTI, SizeInBytes, Ty->getName(),
1396a8d57407SReid Kleckner                                           Ty->getIdentifier()));
1397a8d57407SReid Kleckner   // FIXME: Make an LF_UDT_SRC_LINE record.
1398a8d57407SReid Kleckner }
1399a8d57407SReid Kleckner 
140076c9eb99SAmjad Aboud std::tuple<TypeIndex, TypeIndex, unsigned>
1401a8d57407SReid Kleckner CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
1402a8d57407SReid Kleckner   // Manually count members. MSVC appears to count everything that generates a
1403a8d57407SReid Kleckner   // field list record. Each individual overload in a method overload group
1404a8d57407SReid Kleckner   // contributes to this count, even though the overload group is a single field
1405a8d57407SReid Kleckner   // list record.
1406a8d57407SReid Kleckner   unsigned MemberCount = 0;
140776c9eb99SAmjad Aboud   ClassInfo &Info = collectClassInfo(Ty);
1408a8d57407SReid Kleckner   FieldListRecordBuilder Fields;
140976c9eb99SAmjad Aboud 
141076c9eb99SAmjad Aboud   // Create members.
141176c9eb99SAmjad Aboud   for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {
141276c9eb99SAmjad Aboud     const DIDerivedType *Member = MemberInfo.MemberTypeNode;
141376c9eb99SAmjad Aboud     TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
141476c9eb99SAmjad Aboud 
1415a8d57407SReid Kleckner     if (Member->isStaticMember()) {
1416a8d57407SReid Kleckner       Fields.writeStaticDataMember(StaticDataMemberRecord(
141776c9eb99SAmjad Aboud           translateAccessFlags(Ty->getTag(), Member->getFlags()),
141876c9eb99SAmjad Aboud           MemberBaseType, Member->getName()));
1419a8d57407SReid Kleckner       MemberCount++;
142076c9eb99SAmjad Aboud       continue;
1421a8d57407SReid Kleckner     }
1422a8d57407SReid Kleckner 
142376c9eb99SAmjad Aboud     uint64_t OffsetInBytes = MemberInfo.BaseOffset;
142476c9eb99SAmjad Aboud 
142576c9eb99SAmjad Aboud     // FIXME: Handle bitfield type memeber.
142676c9eb99SAmjad Aboud     OffsetInBytes += Member->getOffsetInBits() / 8;
142776c9eb99SAmjad Aboud 
142876c9eb99SAmjad Aboud     Fields.writeDataMember(
142976c9eb99SAmjad Aboud         DataMemberRecord(translateAccessFlags(Ty->getTag(), Member->getFlags()),
143076c9eb99SAmjad Aboud                          MemberBaseType, OffsetInBytes, Member->getName()));
143176c9eb99SAmjad Aboud     MemberCount++;
143276c9eb99SAmjad Aboud   }
143376c9eb99SAmjad Aboud 
143476c9eb99SAmjad Aboud   // Create methods
143576c9eb99SAmjad Aboud   for (auto &MethodItr : Info.Methods) {
143676c9eb99SAmjad Aboud     StringRef Name = MethodItr.first->getString();
143776c9eb99SAmjad Aboud 
143876c9eb99SAmjad Aboud     std::vector<OneMethodRecord> Methods;
143976c9eb99SAmjad Aboud     for (ClassInfo::MethodInfo &MethodInfo : MethodItr.second) {
144076c9eb99SAmjad Aboud       const DISubprogram *SP = MethodInfo.Method;
144176c9eb99SAmjad Aboud       bool Introduced = MethodInfo.Introduced;
144276c9eb99SAmjad Aboud 
144376c9eb99SAmjad Aboud       TypeIndex MethodType = getTypeIndex(SP->getType(), Ty);
144476c9eb99SAmjad Aboud 
144576c9eb99SAmjad Aboud       unsigned VFTableOffset = -1;
144676c9eb99SAmjad Aboud       if (Introduced)
144776c9eb99SAmjad Aboud         VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
144876c9eb99SAmjad Aboud 
144976c9eb99SAmjad Aboud       Methods.push_back(
145076c9eb99SAmjad Aboud           OneMethodRecord(MethodType, translateMethodKindFlags(SP, Introduced),
145176c9eb99SAmjad Aboud                           translateMethodOptionFlags(SP),
145276c9eb99SAmjad Aboud                           translateAccessFlags(Ty->getTag(), SP->getFlags()),
145376c9eb99SAmjad Aboud                           VFTableOffset, Name));
145476c9eb99SAmjad Aboud       MemberCount++;
145576c9eb99SAmjad Aboud     }
145676c9eb99SAmjad Aboud     assert(Methods.size() > 0 && "Empty methods map entry");
145776c9eb99SAmjad Aboud     if (Methods.size() == 1)
145876c9eb99SAmjad Aboud       Fields.writeOneMethod(Methods[0]);
145976c9eb99SAmjad Aboud     else {
146076c9eb99SAmjad Aboud       TypeIndex MethodList =
146176c9eb99SAmjad Aboud           TypeTable.writeMethodOverloadList(MethodOverloadListRecord(Methods));
146276c9eb99SAmjad Aboud       Fields.writeOverloadedMethod(
146376c9eb99SAmjad Aboud           OverloadedMethodRecord(Methods.size(), MethodList, Name));
146476c9eb99SAmjad Aboud     }
146576c9eb99SAmjad Aboud   }
146676c9eb99SAmjad Aboud   TypeIndex FieldTI = TypeTable.writeFieldList(Fields);
146776c9eb99SAmjad Aboud   return std::make_tuple(FieldTI, TypeIndex(), MemberCount);
146876c9eb99SAmjad Aboud }
146976c9eb99SAmjad Aboud 
147076c9eb99SAmjad Aboud TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
14715acacbb0SReid Kleckner   const DIType *Ty = TypeRef.resolve();
147276c9eb99SAmjad Aboud   const DIType *ClassTy = ClassTyRef.resolve();
14735acacbb0SReid Kleckner 
14745acacbb0SReid Kleckner   // The null DIType is the void type. Don't try to hash it.
14755acacbb0SReid Kleckner   if (!Ty)
14765acacbb0SReid Kleckner     return TypeIndex::Void();
14775acacbb0SReid Kleckner 
1478a8d57407SReid Kleckner   // Check if we've already translated this type. Don't try to do a
1479a8d57407SReid Kleckner   // get-or-create style insertion that caches the hash lookup across the
1480a8d57407SReid Kleckner   // lowerType call. It will update the TypeIndices map.
148176c9eb99SAmjad Aboud   auto I = TypeIndices.find({Ty, ClassTy});
14825acacbb0SReid Kleckner   if (I != TypeIndices.end())
14835acacbb0SReid Kleckner     return I->second;
14845acacbb0SReid Kleckner 
148576c9eb99SAmjad Aboud   TypeIndex TI = lowerType(Ty, ClassTy);
14865acacbb0SReid Kleckner 
148776c9eb99SAmjad Aboud   recordTypeIndexForDINode(Ty, TI, ClassTy);
1488a8d57407SReid Kleckner   return TI;
1489a8d57407SReid Kleckner }
1490a8d57407SReid Kleckner 
1491a8d57407SReid Kleckner TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
1492a8d57407SReid Kleckner   const DIType *Ty = TypeRef.resolve();
1493a8d57407SReid Kleckner 
1494a8d57407SReid Kleckner   // The null DIType is the void type. Don't try to hash it.
1495a8d57407SReid Kleckner   if (!Ty)
1496a8d57407SReid Kleckner     return TypeIndex::Void();
1497a8d57407SReid Kleckner 
1498a8d57407SReid Kleckner   // If this is a non-record type, the complete type index is the same as the
1499a8d57407SReid Kleckner   // normal type index. Just call getTypeIndex.
1500a8d57407SReid Kleckner   switch (Ty->getTag()) {
1501a8d57407SReid Kleckner   case dwarf::DW_TAG_class_type:
1502a8d57407SReid Kleckner   case dwarf::DW_TAG_structure_type:
1503a8d57407SReid Kleckner   case dwarf::DW_TAG_union_type:
1504a8d57407SReid Kleckner     break;
1505a8d57407SReid Kleckner   default:
1506a8d57407SReid Kleckner     return getTypeIndex(Ty);
1507a8d57407SReid Kleckner   }
1508a8d57407SReid Kleckner 
1509a8d57407SReid Kleckner   // Check if we've already translated the complete record type.  Lowering a
1510a8d57407SReid Kleckner   // complete type should never trigger lowering another complete type, so we
1511a8d57407SReid Kleckner   // can reuse the hash table lookup result.
1512a8d57407SReid Kleckner   const auto *CTy = cast<DICompositeType>(Ty);
1513a8d57407SReid Kleckner   auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});
1514a8d57407SReid Kleckner   if (!InsertResult.second)
1515a8d57407SReid Kleckner     return InsertResult.first->second;
1516a8d57407SReid Kleckner 
1517a8d57407SReid Kleckner   // Make sure the forward declaration is emitted first. It's unclear if this
1518a8d57407SReid Kleckner   // is necessary, but MSVC does it, and we should follow suit until we can show
1519a8d57407SReid Kleckner   // otherwise.
1520a8d57407SReid Kleckner   TypeIndex FwdDeclTI = getTypeIndex(CTy);
1521a8d57407SReid Kleckner 
1522a8d57407SReid Kleckner   // Just use the forward decl if we don't have complete type info. This might
1523a8d57407SReid Kleckner   // happen if the frontend is using modules and expects the complete definition
1524a8d57407SReid Kleckner   // to be emitted elsewhere.
1525a8d57407SReid Kleckner   if (CTy->isForwardDecl())
1526a8d57407SReid Kleckner     return FwdDeclTI;
1527a8d57407SReid Kleckner 
1528a8d57407SReid Kleckner   TypeIndex TI;
1529a8d57407SReid Kleckner   switch (CTy->getTag()) {
1530a8d57407SReid Kleckner   case dwarf::DW_TAG_class_type:
1531a8d57407SReid Kleckner   case dwarf::DW_TAG_structure_type:
1532a8d57407SReid Kleckner     TI = lowerCompleteTypeClass(CTy);
1533a8d57407SReid Kleckner     break;
1534a8d57407SReid Kleckner   case dwarf::DW_TAG_union_type:
1535a8d57407SReid Kleckner     TI = lowerCompleteTypeUnion(CTy);
1536a8d57407SReid Kleckner     break;
1537a8d57407SReid Kleckner   default:
1538a8d57407SReid Kleckner     llvm_unreachable("not a record");
1539a8d57407SReid Kleckner   }
1540a8d57407SReid Kleckner 
1541a8d57407SReid Kleckner   InsertResult.first->second = TI;
15425acacbb0SReid Kleckner   return TI;
15435acacbb0SReid Kleckner }
15445acacbb0SReid Kleckner 
1545f9c275feSReid Kleckner void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
1546f9c275feSReid Kleckner   // LocalSym record, see SymbolRecord.h for more info.
1547f9c275feSReid Kleckner   MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(),
1548f9c275feSReid Kleckner            *LocalEnd = MMI->getContext().createTempSymbol();
1549f9c275feSReid Kleckner   OS.AddComment("Record length");
1550f9c275feSReid Kleckner   OS.emitAbsoluteSymbolDiff(LocalEnd, LocalBegin, 2);
1551f9c275feSReid Kleckner   OS.EmitLabel(LocalBegin);
1552f9c275feSReid Kleckner 
1553f9c275feSReid Kleckner   OS.AddComment("Record kind: S_LOCAL");
155463a2846eSZachary Turner   OS.EmitIntValue(unsigned(SymbolKind::S_LOCAL), 2);
1555f9c275feSReid Kleckner 
155663a2846eSZachary Turner   LocalSymFlags Flags = LocalSymFlags::None;
1557f9c275feSReid Kleckner   if (Var.DIVar->isParameter())
155863a2846eSZachary Turner     Flags |= LocalSymFlags::IsParameter;
1559876330d5SReid Kleckner   if (Var.DefRanges.empty())
156063a2846eSZachary Turner     Flags |= LocalSymFlags::IsOptimizedOut;
1561f9c275feSReid Kleckner 
1562f9c275feSReid Kleckner   OS.AddComment("TypeIndex");
1563a8d57407SReid Kleckner   TypeIndex TI = getCompleteTypeIndex(Var.DIVar->getType());
15645acacbb0SReid Kleckner   OS.EmitIntValue(TI.getIndex(), 4);
1565f9c275feSReid Kleckner   OS.AddComment("Flags");
156663a2846eSZachary Turner   OS.EmitIntValue(static_cast<uint16_t>(Flags), 2);
15671256125fSDavid Majnemer   // Truncate the name so we won't overflow the record length field.
1568b9456a5eSDavid Majnemer   emitNullTerminatedSymbolName(OS, Var.DIVar->getName());
1569f9c275feSReid Kleckner   OS.EmitLabel(LocalEnd);
1570f9c275feSReid Kleckner 
1571876330d5SReid Kleckner   // Calculate the on disk prefix of the appropriate def range record. The
1572876330d5SReid Kleckner   // records and on disk formats are described in SymbolRecords.h. BytePrefix
1573876330d5SReid Kleckner   // should be big enough to hold all forms without memory allocation.
1574876330d5SReid Kleckner   SmallString<20> BytePrefix;
1575876330d5SReid Kleckner   for (const LocalVarDefRange &DefRange : Var.DefRanges) {
1576876330d5SReid Kleckner     BytePrefix.clear();
1577876330d5SReid Kleckner     // FIXME: Handle bitpieces.
1578876330d5SReid Kleckner     if (DefRange.StructOffset != 0)
1579876330d5SReid Kleckner       continue;
1580876330d5SReid Kleckner 
1581876330d5SReid Kleckner     if (DefRange.InMemory) {
1582a78ecd1eSZachary Turner       DefRangeRegisterRelSym Sym(DefRange.CVRegister, 0, DefRange.DataOffset, 0,
1583a78ecd1eSZachary Turner                                  0, 0, ArrayRef<LocalVariableAddrGap>());
1584f9c275feSReid Kleckner       ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
1585876330d5SReid Kleckner       BytePrefix +=
1586876330d5SReid Kleckner           StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
1587a78ecd1eSZachary Turner       BytePrefix +=
1588a78ecd1eSZachary Turner           StringRef(reinterpret_cast<const char *>(&Sym.Header),
1589a78ecd1eSZachary Turner                     sizeof(Sym.Header) - sizeof(LocalVariableAddrRange));
1590876330d5SReid Kleckner     } else {
1591876330d5SReid Kleckner       assert(DefRange.DataOffset == 0 && "unexpected offset into register");
1592a78ecd1eSZachary Turner       // Unclear what matters here.
1593a78ecd1eSZachary Turner       DefRangeRegisterSym Sym(DefRange.CVRegister, 0, 0, 0, 0,
1594a78ecd1eSZachary Turner                               ArrayRef<LocalVariableAddrGap>());
1595876330d5SReid Kleckner       ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER);
1596876330d5SReid Kleckner       BytePrefix +=
1597876330d5SReid Kleckner           StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
1598a78ecd1eSZachary Turner       BytePrefix +=
1599a78ecd1eSZachary Turner           StringRef(reinterpret_cast<const char *>(&Sym.Header),
1600a78ecd1eSZachary Turner                     sizeof(Sym.Header) - sizeof(LocalVariableAddrRange));
1601876330d5SReid Kleckner     }
1602876330d5SReid Kleckner     OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix);
1603876330d5SReid Kleckner   }
1604f9c275feSReid Kleckner }
1605f9c275feSReid Kleckner 
160670f5bc99SReid Kleckner void CodeViewDebug::endFunction(const MachineFunction *MF) {
160770f5bc99SReid Kleckner   if (!Asm || !CurFn)  // We haven't created any debug info for this function.
160870f5bc99SReid Kleckner     return;
160970f5bc99SReid Kleckner 
161070f5bc99SReid Kleckner   const Function *GV = MF->getFunction();
161170f5bc99SReid Kleckner   assert(FnDebugInfo.count(GV));
161270f5bc99SReid Kleckner   assert(CurFn == &FnDebugInfo[GV]);
161370f5bc99SReid Kleckner 
1614adebb937SPete Cooper   collectVariableInfo(GV->getSubprogram());
1615876330d5SReid Kleckner 
1616876330d5SReid Kleckner   DebugHandlerBase::endFunction(MF);
1617876330d5SReid Kleckner 
16182214ed89SReid Kleckner   // Don't emit anything if we don't have any line tables.
16192214ed89SReid Kleckner   if (!CurFn->HaveLineInfo) {
162070f5bc99SReid Kleckner     FnDebugInfo.erase(GV);
1621f9c275feSReid Kleckner     CurFn = nullptr;
1622f9c275feSReid Kleckner     return;
162370f5bc99SReid Kleckner   }
1624f9c275feSReid Kleckner 
1625f9c275feSReid Kleckner   CurFn->End = Asm->getFunctionEnd();
1626f9c275feSReid Kleckner 
162770f5bc99SReid Kleckner   CurFn = nullptr;
162870f5bc99SReid Kleckner }
162970f5bc99SReid Kleckner 
163070f5bc99SReid Kleckner void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
1631f9c275feSReid Kleckner   DebugHandlerBase::beginInstruction(MI);
1632f9c275feSReid Kleckner 
163370f5bc99SReid Kleckner   // Ignore DBG_VALUE locations and function prologue.
163470f5bc99SReid Kleckner   if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
163570f5bc99SReid Kleckner     return;
163670f5bc99SReid Kleckner   DebugLoc DL = MI->getDebugLoc();
163770f5bc99SReid Kleckner   if (DL == PrevInstLoc || !DL)
163870f5bc99SReid Kleckner     return;
163970f5bc99SReid Kleckner   maybeRecordLocation(DL, Asm->MF);
164070f5bc99SReid Kleckner }
16416f3406dfSReid Kleckner 
16426f3406dfSReid Kleckner MCSymbol *CodeViewDebug::beginCVSubsection(ModuleSubstreamKind Kind) {
16436f3406dfSReid Kleckner   MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),
16446f3406dfSReid Kleckner            *EndLabel = MMI->getContext().createTempSymbol();
16456f3406dfSReid Kleckner   OS.EmitIntValue(unsigned(Kind), 4);
16466f3406dfSReid Kleckner   OS.AddComment("Subsection size");
16476f3406dfSReid Kleckner   OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
16486f3406dfSReid Kleckner   OS.EmitLabel(BeginLabel);
16496f3406dfSReid Kleckner   return EndLabel;
16506f3406dfSReid Kleckner }
16516f3406dfSReid Kleckner 
16526f3406dfSReid Kleckner void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {
16536f3406dfSReid Kleckner   OS.EmitLabel(EndLabel);
16546f3406dfSReid Kleckner   // Every subsection must be aligned to a 4-byte boundary.
16556f3406dfSReid Kleckner   OS.EmitValueToAlignment(4);
16566f3406dfSReid Kleckner }
16576f3406dfSReid Kleckner 
16583128b10cSDavid Majnemer void CodeViewDebug::emitDebugInfoForUDTs(
16593128b10cSDavid Majnemer     ArrayRef<std::pair<std::string, TypeIndex>> UDTs) {
16603128b10cSDavid Majnemer   for (const std::pair<std::string, codeview::TypeIndex> &UDT : UDTs) {
16613128b10cSDavid Majnemer     MCSymbol *UDTRecordBegin = MMI->getContext().createTempSymbol(),
16623128b10cSDavid Majnemer              *UDTRecordEnd = MMI->getContext().createTempSymbol();
16633128b10cSDavid Majnemer     OS.AddComment("Record length");
16643128b10cSDavid Majnemer     OS.emitAbsoluteSymbolDiff(UDTRecordEnd, UDTRecordBegin, 2);
16653128b10cSDavid Majnemer     OS.EmitLabel(UDTRecordBegin);
16663128b10cSDavid Majnemer 
16673128b10cSDavid Majnemer     OS.AddComment("Record kind: S_UDT");
16683128b10cSDavid Majnemer     OS.EmitIntValue(unsigned(SymbolKind::S_UDT), 2);
16693128b10cSDavid Majnemer 
16703128b10cSDavid Majnemer     OS.AddComment("Type");
16713128b10cSDavid Majnemer     OS.EmitIntValue(UDT.second.getIndex(), 4);
16723128b10cSDavid Majnemer 
16733128b10cSDavid Majnemer     emitNullTerminatedSymbolName(OS, UDT.first);
16743128b10cSDavid Majnemer     OS.EmitLabel(UDTRecordEnd);
16753128b10cSDavid Majnemer   }
16763128b10cSDavid Majnemer }
16773128b10cSDavid Majnemer 
16786f3406dfSReid Kleckner void CodeViewDebug::emitDebugInfoForGlobals() {
16796f3406dfSReid Kleckner   NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
16806f3406dfSReid Kleckner   for (const MDNode *Node : CUs->operands()) {
16816f3406dfSReid Kleckner     const auto *CU = cast<DICompileUnit>(Node);
16826f3406dfSReid Kleckner 
16836f3406dfSReid Kleckner     // First, emit all globals that are not in a comdat in a single symbol
16846f3406dfSReid Kleckner     // substream. MSVC doesn't like it if the substream is empty, so only open
16856f3406dfSReid Kleckner     // it if we have at least one global to emit.
16866f3406dfSReid Kleckner     switchToDebugSectionForSymbol(nullptr);
16876f3406dfSReid Kleckner     MCSymbol *EndLabel = nullptr;
16886f3406dfSReid Kleckner     for (const DIGlobalVariable *G : CU->getGlobalVariables()) {
16896d1d2754SReid Kleckner       if (const auto *GV = dyn_cast_or_null<GlobalVariable>(G->getVariable())) {
1690577be0feSDavid Majnemer         if (!GV->hasComdat() && !GV->isDeclarationForLinker()) {
16916f3406dfSReid Kleckner           if (!EndLabel) {
16926f3406dfSReid Kleckner             OS.AddComment("Symbol subsection for globals");
16936f3406dfSReid Kleckner             EndLabel = beginCVSubsection(ModuleSubstreamKind::Symbols);
16946f3406dfSReid Kleckner           }
16956f3406dfSReid Kleckner           emitDebugInfoForGlobal(G, Asm->getSymbol(GV));
16966f3406dfSReid Kleckner         }
16976f3406dfSReid Kleckner       }
16986d1d2754SReid Kleckner     }
16996f3406dfSReid Kleckner     if (EndLabel)
17006f3406dfSReid Kleckner       endCVSubsection(EndLabel);
17016f3406dfSReid Kleckner 
17026f3406dfSReid Kleckner     // Second, emit each global that is in a comdat into its own .debug$S
17036f3406dfSReid Kleckner     // section along with its own symbol substream.
17046f3406dfSReid Kleckner     for (const DIGlobalVariable *G : CU->getGlobalVariables()) {
17056d1d2754SReid Kleckner       if (const auto *GV = dyn_cast_or_null<GlobalVariable>(G->getVariable())) {
17066f3406dfSReid Kleckner         if (GV->hasComdat()) {
17076f3406dfSReid Kleckner           MCSymbol *GVSym = Asm->getSymbol(GV);
17086f3406dfSReid Kleckner           OS.AddComment("Symbol subsection for " +
17096f3406dfSReid Kleckner                         Twine(GlobalValue::getRealLinkageName(GV->getName())));
17106f3406dfSReid Kleckner           switchToDebugSectionForSymbol(GVSym);
17116f3406dfSReid Kleckner           EndLabel = beginCVSubsection(ModuleSubstreamKind::Symbols);
17126f3406dfSReid Kleckner           emitDebugInfoForGlobal(G, GVSym);
17136f3406dfSReid Kleckner           endCVSubsection(EndLabel);
17146f3406dfSReid Kleckner         }
17156f3406dfSReid Kleckner       }
17166f3406dfSReid Kleckner     }
17176f3406dfSReid Kleckner   }
17186f3406dfSReid Kleckner }
17196f3406dfSReid Kleckner 
17206f3406dfSReid Kleckner void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
17216f3406dfSReid Kleckner                                            MCSymbol *GVSym) {
17226f3406dfSReid Kleckner   // DataSym record, see SymbolRecord.h for more info.
17236f3406dfSReid Kleckner   // FIXME: Thread local data, etc
17246f3406dfSReid Kleckner   MCSymbol *DataBegin = MMI->getContext().createTempSymbol(),
17256f3406dfSReid Kleckner            *DataEnd = MMI->getContext().createTempSymbol();
17266f3406dfSReid Kleckner   OS.AddComment("Record length");
17276f3406dfSReid Kleckner   OS.emitAbsoluteSymbolDiff(DataEnd, DataBegin, 2);
17286f3406dfSReid Kleckner   OS.EmitLabel(DataBegin);
17296f3406dfSReid Kleckner   OS.AddComment("Record kind: S_GDATA32");
17306f3406dfSReid Kleckner   OS.EmitIntValue(unsigned(SymbolKind::S_GDATA32), 2);
17316f3406dfSReid Kleckner   OS.AddComment("Type");
17326f3406dfSReid Kleckner   OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4);
17336f3406dfSReid Kleckner   OS.AddComment("DataOffset");
17346f3406dfSReid Kleckner   OS.EmitCOFFSecRel32(GVSym);
17356f3406dfSReid Kleckner   OS.AddComment("Segment");
17366f3406dfSReid Kleckner   OS.EmitCOFFSectionIndex(GVSym);
17376f3406dfSReid Kleckner   OS.AddComment("Name");
17386f3406dfSReid Kleckner   emitNullTerminatedSymbolName(OS, DIGV->getName());
17396f3406dfSReid Kleckner   OS.EmitLabel(DataEnd);
17406f3406dfSReid Kleckner }
1741