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"
1670f5bc99SReid Kleckner #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1770f5bc99SReid Kleckner #include "llvm/MC/MCExpr.h"
1870f5bc99SReid Kleckner #include "llvm/MC/MCSymbol.h"
1970f5bc99SReid Kleckner #include "llvm/Support/COFF.h"
2070f5bc99SReid Kleckner 
2170f5bc99SReid Kleckner using namespace llvm::codeview;
2270f5bc99SReid Kleckner 
2370f5bc99SReid Kleckner namespace llvm {
2470f5bc99SReid Kleckner 
25*9533af4fSReid Kleckner StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
26*9533af4fSReid Kleckner   std::string &Filepath = FileToFilepathMap[File];
2770f5bc99SReid Kleckner   if (!Filepath.empty())
2870f5bc99SReid Kleckner     return Filepath;
2970f5bc99SReid Kleckner 
30*9533af4fSReid Kleckner   StringRef Dir = File->getDirectory(), Filename = File->getFilename();
31*9533af4fSReid Kleckner 
3270f5bc99SReid Kleckner   // Clang emits directory and relative filename info into the IR, but CodeView
3370f5bc99SReid Kleckner   // operates on full paths.  We could change Clang to emit full paths too, but
3470f5bc99SReid Kleckner   // that would increase the IR size and probably not needed for other users.
3570f5bc99SReid Kleckner   // For now, just concatenate and canonicalize the path here.
3670f5bc99SReid Kleckner   if (Filename.find(':') == 1)
3770f5bc99SReid Kleckner     Filepath = Filename;
3870f5bc99SReid Kleckner   else
3970f5bc99SReid Kleckner     Filepath = (Dir + "\\" + Filename).str();
4070f5bc99SReid Kleckner 
4170f5bc99SReid Kleckner   // Canonicalize the path.  We have to do it textually because we may no longer
4270f5bc99SReid Kleckner   // have access the file in the filesystem.
4370f5bc99SReid Kleckner   // First, replace all slashes with backslashes.
4470f5bc99SReid Kleckner   std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
4570f5bc99SReid Kleckner 
4670f5bc99SReid Kleckner   // Remove all "\.\" with "\".
4770f5bc99SReid Kleckner   size_t Cursor = 0;
4870f5bc99SReid Kleckner   while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
4970f5bc99SReid Kleckner     Filepath.erase(Cursor, 2);
5070f5bc99SReid Kleckner 
5170f5bc99SReid Kleckner   // Replace all "\XXX\..\" with "\".  Don't try too hard though as the original
5270f5bc99SReid Kleckner   // path should be well-formatted, e.g. start with a drive letter, etc.
5370f5bc99SReid Kleckner   Cursor = 0;
5470f5bc99SReid Kleckner   while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
5570f5bc99SReid Kleckner     // Something's wrong if the path starts with "\..\", abort.
5670f5bc99SReid Kleckner     if (Cursor == 0)
5770f5bc99SReid Kleckner       break;
5870f5bc99SReid Kleckner 
5970f5bc99SReid Kleckner     size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
6070f5bc99SReid Kleckner     if (PrevSlash == std::string::npos)
6170f5bc99SReid Kleckner       // Something's wrong, abort.
6270f5bc99SReid Kleckner       break;
6370f5bc99SReid Kleckner 
6470f5bc99SReid Kleckner     Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
6570f5bc99SReid Kleckner     // The next ".." might be following the one we've just erased.
6670f5bc99SReid Kleckner     Cursor = PrevSlash;
6770f5bc99SReid Kleckner   }
6870f5bc99SReid Kleckner 
6970f5bc99SReid Kleckner   // Remove all duplicate backslashes.
7070f5bc99SReid Kleckner   Cursor = 0;
7170f5bc99SReid Kleckner   while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
7270f5bc99SReid Kleckner     Filepath.erase(Cursor, 1);
7370f5bc99SReid Kleckner 
7470f5bc99SReid Kleckner   return Filepath;
7570f5bc99SReid Kleckner }
7670f5bc99SReid Kleckner 
7770f5bc99SReid Kleckner void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
7870f5bc99SReid Kleckner                                         const MachineFunction *MF) {
79*9533af4fSReid Kleckner   // Skip this instruction if it has the same location as the previous one.
80*9533af4fSReid Kleckner   if (DL == CurFn->LastLoc)
81*9533af4fSReid Kleckner     return;
82*9533af4fSReid Kleckner 
83*9533af4fSReid Kleckner   const DIScope *Scope = DL.get()->getScope();
8470f5bc99SReid Kleckner   if (!Scope)
8570f5bc99SReid Kleckner     return;
86*9533af4fSReid Kleckner 
8770f5bc99SReid Kleckner   // Skip this line if it is longer than the maximum we can record.
88*9533af4fSReid Kleckner   if (DL.getLine() > COFF::CVL_MaxLineNumber)
8970f5bc99SReid Kleckner     return;
9070f5bc99SReid Kleckner 
91*9533af4fSReid Kleckner   CurFn->LastLoc = DL;
9270f5bc99SReid Kleckner 
9370f5bc99SReid Kleckner   MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol();
9470f5bc99SReid Kleckner   Asm->OutStreamer->EmitLabel(MCL);
9570f5bc99SReid Kleckner   CurFn->Instrs.push_back(MCL);
96*9533af4fSReid Kleckner   LabelsAndLocs[MCL] = DL;
9770f5bc99SReid Kleckner }
9870f5bc99SReid Kleckner 
9970f5bc99SReid Kleckner CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
10070f5bc99SReid Kleckner     : Asm(nullptr), CurFn(nullptr) {
10170f5bc99SReid Kleckner   MachineModuleInfo *MMI = AP->MMI;
10270f5bc99SReid Kleckner 
10370f5bc99SReid Kleckner   // If module doesn't have named metadata anchors or COFF debug section
10470f5bc99SReid Kleckner   // is not available, skip any debug info related stuff.
10570f5bc99SReid Kleckner   if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
10670f5bc99SReid Kleckner       !AP->getObjFileLowering().getCOFFDebugSymbolsSection())
10770f5bc99SReid Kleckner     return;
10870f5bc99SReid Kleckner 
10970f5bc99SReid Kleckner   // Tell MMI that we have debug info.
11070f5bc99SReid Kleckner   MMI->setDebugInfoAvailability(true);
11170f5bc99SReid Kleckner   Asm = AP;
11270f5bc99SReid Kleckner }
11370f5bc99SReid Kleckner 
11470f5bc99SReid Kleckner void CodeViewDebug::endModule() {
11570f5bc99SReid Kleckner   if (FnDebugInfo.empty())
11670f5bc99SReid Kleckner     return;
11770f5bc99SReid Kleckner 
11870f5bc99SReid Kleckner   // FIXME: For functions that are comdat, we should emit separate .debug$S
11970f5bc99SReid Kleckner   // sections that are comdat associative with the main function instead of
12070f5bc99SReid Kleckner   // having one big .debug$S section.
12170f5bc99SReid Kleckner   assert(Asm != nullptr);
12270f5bc99SReid Kleckner   Asm->OutStreamer->SwitchSection(
12370f5bc99SReid Kleckner       Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
12470f5bc99SReid Kleckner   Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
12570f5bc99SReid Kleckner 
12670f5bc99SReid Kleckner   // The COFF .debug$S section consists of several subsections, each starting
12770f5bc99SReid Kleckner   // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
12870f5bc99SReid Kleckner   // of the payload followed by the payload itself.  The subsections are 4-byte
12970f5bc99SReid Kleckner   // aligned.
13070f5bc99SReid Kleckner 
13170f5bc99SReid Kleckner   // Emit per-function debug information.  This code is extracted into a
13270f5bc99SReid Kleckner   // separate function for readability.
13370f5bc99SReid Kleckner   for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
13470f5bc99SReid Kleckner     emitDebugInfoForFunction(VisitedFunctions[I]);
13570f5bc99SReid Kleckner 
13670f5bc99SReid Kleckner   // This subsection holds a file index to offset in string table table.
13770f5bc99SReid Kleckner   Asm->OutStreamer->AddComment("File index to string table offset subsection");
13870f5bc99SReid Kleckner   Asm->EmitInt32(unsigned(ModuleSubstreamKind::FileChecksums));
13970f5bc99SReid Kleckner   size_t NumFilenames = FileNameRegistry.Infos.size();
14070f5bc99SReid Kleckner   Asm->EmitInt32(8 * NumFilenames);
14170f5bc99SReid Kleckner   for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
14270f5bc99SReid Kleckner     StringRef Filename = FileNameRegistry.Filenames[I];
14370f5bc99SReid Kleckner     // For each unique filename, just write its offset in the string table.
14470f5bc99SReid Kleckner     Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
14570f5bc99SReid Kleckner     // The function name offset is not followed by any additional data.
14670f5bc99SReid Kleckner     Asm->EmitInt32(0);
14770f5bc99SReid Kleckner   }
14870f5bc99SReid Kleckner 
14970f5bc99SReid Kleckner   // This subsection holds the string table.
15070f5bc99SReid Kleckner   Asm->OutStreamer->AddComment("String table");
15170f5bc99SReid Kleckner   Asm->EmitInt32(unsigned(ModuleSubstreamKind::StringTable));
15270f5bc99SReid Kleckner   Asm->EmitInt32(FileNameRegistry.LastOffset);
15370f5bc99SReid Kleckner   // The payload starts with a null character.
15470f5bc99SReid Kleckner   Asm->EmitInt8(0);
15570f5bc99SReid Kleckner 
15670f5bc99SReid Kleckner   for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
15770f5bc99SReid Kleckner     // Just emit unique filenames one by one, separated by a null character.
15870f5bc99SReid Kleckner     Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
15970f5bc99SReid Kleckner     Asm->EmitInt8(0);
16070f5bc99SReid Kleckner   }
16170f5bc99SReid Kleckner 
16270f5bc99SReid Kleckner   // No more subsections. Fill with zeros to align the end of the section by 4.
16370f5bc99SReid Kleckner   Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
16470f5bc99SReid Kleckner 
16570f5bc99SReid Kleckner   clear();
16670f5bc99SReid Kleckner }
16770f5bc99SReid Kleckner 
16870f5bc99SReid Kleckner static void EmitLabelDiff(MCStreamer &Streamer,
16970f5bc99SReid Kleckner                           const MCSymbol *From, const MCSymbol *To,
17070f5bc99SReid Kleckner                           unsigned int Size = 4) {
17170f5bc99SReid Kleckner   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
17270f5bc99SReid Kleckner   MCContext &Context = Streamer.getContext();
17370f5bc99SReid Kleckner   const MCExpr *FromRef = MCSymbolRefExpr::create(From, Variant, Context),
17470f5bc99SReid Kleckner                *ToRef   = MCSymbolRefExpr::create(To, Variant, Context);
17570f5bc99SReid Kleckner   const MCExpr *AddrDelta =
17670f5bc99SReid Kleckner       MCBinaryExpr::create(MCBinaryExpr::Sub, ToRef, FromRef, Context);
17770f5bc99SReid Kleckner   Streamer.EmitValue(AddrDelta, Size);
17870f5bc99SReid Kleckner }
17970f5bc99SReid Kleckner 
180*9533af4fSReid Kleckner static const DIFile *getFileFromLoc(DebugLoc DL) {
181*9533af4fSReid Kleckner   return DL.get()->getScope()->getFile();
182*9533af4fSReid Kleckner }
183*9533af4fSReid Kleckner 
18470f5bc99SReid Kleckner void CodeViewDebug::emitDebugInfoForFunction(const Function *GV) {
18570f5bc99SReid Kleckner   // For each function there is a separate subsection
18670f5bc99SReid Kleckner   // which holds the PC to file:line table.
18770f5bc99SReid Kleckner   const MCSymbol *Fn = Asm->getSymbol(GV);
18870f5bc99SReid Kleckner   assert(Fn);
18970f5bc99SReid Kleckner 
19070f5bc99SReid Kleckner   const FunctionInfo &FI = FnDebugInfo[GV];
19170f5bc99SReid Kleckner   if (FI.Instrs.empty())
19270f5bc99SReid Kleckner     return;
19370f5bc99SReid Kleckner   assert(FI.End && "Don't know where the function ends?");
19470f5bc99SReid Kleckner 
19570f5bc99SReid Kleckner   StringRef FuncName;
19670f5bc99SReid Kleckner   if (auto *SP = getDISubprogram(GV))
19770f5bc99SReid Kleckner     FuncName = SP->getDisplayName();
19870f5bc99SReid Kleckner 
19970f5bc99SReid Kleckner   // If our DISubprogram name is empty, use the mangled name.
20070f5bc99SReid Kleckner   if (FuncName.empty())
20170f5bc99SReid Kleckner     FuncName = GlobalValue::getRealLinkageName(GV->getName());
20270f5bc99SReid Kleckner 
20370f5bc99SReid Kleckner   // Emit a symbol subsection, required by VS2012+ to find function boundaries.
20470f5bc99SReid Kleckner   MCSymbol *SymbolsBegin = Asm->MMI->getContext().createTempSymbol(),
20570f5bc99SReid Kleckner            *SymbolsEnd = Asm->MMI->getContext().createTempSymbol();
20670f5bc99SReid Kleckner   Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName));
20770f5bc99SReid Kleckner   Asm->EmitInt32(unsigned(ModuleSubstreamKind::Symbols));
20870f5bc99SReid Kleckner   EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd);
20970f5bc99SReid Kleckner   Asm->OutStreamer->EmitLabel(SymbolsBegin);
21070f5bc99SReid Kleckner   {
21170f5bc99SReid Kleckner     MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().createTempSymbol(),
21270f5bc99SReid Kleckner              *ProcSegmentEnd = Asm->MMI->getContext().createTempSymbol();
21370f5bc99SReid Kleckner     EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2);
21470f5bc99SReid Kleckner     Asm->OutStreamer->EmitLabel(ProcSegmentBegin);
21570f5bc99SReid Kleckner 
21670f5bc99SReid Kleckner     Asm->EmitInt16(unsigned(SymbolRecordKind::S_GPROC32_ID));
21770f5bc99SReid Kleckner 
21870f5bc99SReid Kleckner     // Some bytes of this segment don't seem to be required for basic debugging,
21970f5bc99SReid Kleckner     // so just fill them with zeroes.
22070f5bc99SReid Kleckner     Asm->OutStreamer->EmitFill(12, 0);
22170f5bc99SReid Kleckner     // This is the important bit that tells the debugger where the function
22270f5bc99SReid Kleckner     // code is located and what's its size:
22370f5bc99SReid Kleckner     EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
22470f5bc99SReid Kleckner     Asm->OutStreamer->EmitFill(12, 0);
22570f5bc99SReid Kleckner     Asm->OutStreamer->EmitCOFFSecRel32(Fn);
22670f5bc99SReid Kleckner     Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
22770f5bc99SReid Kleckner     Asm->EmitInt8(0);
22870f5bc99SReid Kleckner     // Emit the function display name as a null-terminated string.
22970f5bc99SReid Kleckner     Asm->OutStreamer->EmitBytes(FuncName);
23070f5bc99SReid Kleckner     Asm->EmitInt8(0);
23170f5bc99SReid Kleckner     Asm->OutStreamer->EmitLabel(ProcSegmentEnd);
23270f5bc99SReid Kleckner 
23370f5bc99SReid Kleckner     // We're done with this function.
23470f5bc99SReid Kleckner     Asm->EmitInt16(0x0002);
23570f5bc99SReid Kleckner     Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END));
23670f5bc99SReid Kleckner   }
23770f5bc99SReid Kleckner   Asm->OutStreamer->EmitLabel(SymbolsEnd);
23870f5bc99SReid Kleckner   // Every subsection must be aligned to a 4-byte boundary.
23970f5bc99SReid Kleckner   Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
24070f5bc99SReid Kleckner 
24170f5bc99SReid Kleckner   // PCs/Instructions are grouped into segments sharing the same filename.
24270f5bc99SReid Kleckner   // Pre-calculate the lengths (in instructions) of these segments and store
24370f5bc99SReid Kleckner   // them in a map for convenience.  Each index in the map is the sequential
24470f5bc99SReid Kleckner   // number of the respective instruction that starts a new segment.
24570f5bc99SReid Kleckner   DenseMap<size_t, size_t> FilenameSegmentLengths;
24670f5bc99SReid Kleckner   size_t LastSegmentEnd = 0;
247*9533af4fSReid Kleckner   const DIFile *PrevFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[0]]);
24870f5bc99SReid Kleckner   for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
249*9533af4fSReid Kleckner     const DIFile *CurFile = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
250*9533af4fSReid Kleckner     if (PrevFile == CurFile)
25170f5bc99SReid Kleckner       continue;
25270f5bc99SReid Kleckner     FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
25370f5bc99SReid Kleckner     LastSegmentEnd = J;
254*9533af4fSReid Kleckner     PrevFile = CurFile;
25570f5bc99SReid Kleckner   }
25670f5bc99SReid Kleckner   FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
25770f5bc99SReid Kleckner 
25870f5bc99SReid Kleckner   // Emit a line table subsection, required to do PC-to-file:line lookup.
25970f5bc99SReid Kleckner   Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName));
26070f5bc99SReid Kleckner   Asm->EmitInt32(unsigned(ModuleSubstreamKind::Lines));
26170f5bc99SReid Kleckner   MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(),
26270f5bc99SReid Kleckner            *LineTableEnd = Asm->MMI->getContext().createTempSymbol();
26370f5bc99SReid Kleckner   EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd);
26470f5bc99SReid Kleckner   Asm->OutStreamer->EmitLabel(LineTableBegin);
26570f5bc99SReid Kleckner 
26670f5bc99SReid Kleckner   // Identify the function this subsection is for.
26770f5bc99SReid Kleckner   Asm->OutStreamer->EmitCOFFSecRel32(Fn);
26870f5bc99SReid Kleckner   Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
26970f5bc99SReid Kleckner   // Insert flags after a 16-bit section index.
27070f5bc99SReid Kleckner   Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS);
27170f5bc99SReid Kleckner 
27270f5bc99SReid Kleckner   // Length of the function's code, in bytes.
27370f5bc99SReid Kleckner   EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
27470f5bc99SReid Kleckner 
27570f5bc99SReid Kleckner   // PC-to-linenumber lookup table:
27670f5bc99SReid Kleckner   MCSymbol *FileSegmentEnd = nullptr;
27770f5bc99SReid Kleckner 
27870f5bc99SReid Kleckner   // The start of the last segment:
27970f5bc99SReid Kleckner   size_t LastSegmentStart = 0;
28070f5bc99SReid Kleckner 
28170f5bc99SReid Kleckner   auto FinishPreviousChunk = [&] {
28270f5bc99SReid Kleckner     if (!FileSegmentEnd)
28370f5bc99SReid Kleckner       return;
28470f5bc99SReid Kleckner     for (size_t ColSegI = LastSegmentStart,
28570f5bc99SReid Kleckner                 ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart];
28670f5bc99SReid Kleckner          ColSegI != ColSegEnd; ++ColSegI) {
287*9533af4fSReid Kleckner       unsigned ColumnNumber = LabelsAndLocs[FI.Instrs[ColSegI]].getCol();
288*9533af4fSReid Kleckner       // Truncate the column number if it is longer than the maximum we can
289*9533af4fSReid Kleckner       // record.
290*9533af4fSReid Kleckner       if (ColumnNumber > COFF::CVL_MaxColumnNumber)
291*9533af4fSReid Kleckner         ColumnNumber = 0;
29270f5bc99SReid Kleckner       Asm->EmitInt16(ColumnNumber); // Start column
29370f5bc99SReid Kleckner       Asm->EmitInt16(0);            // End column
29470f5bc99SReid Kleckner     }
29570f5bc99SReid Kleckner     Asm->OutStreamer->EmitLabel(FileSegmentEnd);
29670f5bc99SReid Kleckner   };
29770f5bc99SReid Kleckner 
29870f5bc99SReid Kleckner   for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
29970f5bc99SReid Kleckner     MCSymbol *Instr = FI.Instrs[J];
300*9533af4fSReid Kleckner     assert(LabelsAndLocs.count(Instr));
30170f5bc99SReid Kleckner 
30270f5bc99SReid Kleckner     if (FilenameSegmentLengths.count(J)) {
30370f5bc99SReid Kleckner       // We came to a beginning of a new filename segment.
30470f5bc99SReid Kleckner       FinishPreviousChunk();
305*9533af4fSReid Kleckner       const DIFile *File = getFileFromLoc(LabelsAndLocs[FI.Instrs[J]]);
306*9533af4fSReid Kleckner       StringRef CurFilename = getFullFilepath(File);
307*9533af4fSReid Kleckner       size_t IndexInFileTable = FileNameRegistry.add(CurFilename);
30870f5bc99SReid Kleckner       // Each segment starts with the offset of the filename
30970f5bc99SReid Kleckner       // in the string table.
31070f5bc99SReid Kleckner       Asm->OutStreamer->AddComment(
31170f5bc99SReid Kleckner           "Segment for file '" + Twine(CurFilename) + "' begins");
31270f5bc99SReid Kleckner       MCSymbol *FileSegmentBegin = Asm->MMI->getContext().createTempSymbol();
31370f5bc99SReid Kleckner       Asm->OutStreamer->EmitLabel(FileSegmentBegin);
314*9533af4fSReid Kleckner       Asm->EmitInt32(8 * IndexInFileTable);
31570f5bc99SReid Kleckner 
31670f5bc99SReid Kleckner       // Number of PC records in the lookup table.
31770f5bc99SReid Kleckner       size_t SegmentLength = FilenameSegmentLengths[J];
31870f5bc99SReid Kleckner       Asm->EmitInt32(SegmentLength);
31970f5bc99SReid Kleckner 
32070f5bc99SReid Kleckner       // Full size of the segment for this filename, including the prev two
32170f5bc99SReid Kleckner       // records.
32270f5bc99SReid Kleckner       FileSegmentEnd = Asm->MMI->getContext().createTempSymbol();
32370f5bc99SReid Kleckner       EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
32470f5bc99SReid Kleckner       LastSegmentStart = J;
32570f5bc99SReid Kleckner     }
32670f5bc99SReid Kleckner 
32770f5bc99SReid Kleckner     // The first PC with the given linenumber and the linenumber itself.
32870f5bc99SReid Kleckner     EmitLabelDiff(*Asm->OutStreamer, Fn, Instr);
329*9533af4fSReid Kleckner     uint32_t LineNumber = LabelsAndLocs[Instr].getLine();
33070f5bc99SReid Kleckner     assert(LineNumber <= COFF::CVL_MaxLineNumber);
33170f5bc99SReid Kleckner     uint32_t LineData = LineNumber | COFF::CVL_IsStatement;
33270f5bc99SReid Kleckner     Asm->EmitInt32(LineData);
33370f5bc99SReid Kleckner   }
33470f5bc99SReid Kleckner 
33570f5bc99SReid Kleckner   FinishPreviousChunk();
33670f5bc99SReid Kleckner   Asm->OutStreamer->EmitLabel(LineTableEnd);
33770f5bc99SReid Kleckner }
33870f5bc99SReid Kleckner 
33970f5bc99SReid Kleckner void CodeViewDebug::beginFunction(const MachineFunction *MF) {
34070f5bc99SReid Kleckner   assert(!CurFn && "Can't process two functions at once!");
34170f5bc99SReid Kleckner 
34270f5bc99SReid Kleckner   if (!Asm || !Asm->MMI->hasDebugInfo())
34370f5bc99SReid Kleckner     return;
34470f5bc99SReid Kleckner 
34570f5bc99SReid Kleckner   const Function *GV = MF->getFunction();
34670f5bc99SReid Kleckner   assert(FnDebugInfo.count(GV) == false);
34770f5bc99SReid Kleckner   VisitedFunctions.push_back(GV);
34870f5bc99SReid Kleckner   CurFn = &FnDebugInfo[GV];
34970f5bc99SReid Kleckner 
35070f5bc99SReid Kleckner   // Find the end of the function prolog.
35170f5bc99SReid Kleckner   // FIXME: is there a simpler a way to do this? Can we just search
35270f5bc99SReid Kleckner   // for the first instruction of the function, not the last of the prolog?
35370f5bc99SReid Kleckner   DebugLoc PrologEndLoc;
35470f5bc99SReid Kleckner   bool EmptyPrologue = true;
35570f5bc99SReid Kleckner   for (const auto &MBB : *MF) {
35670f5bc99SReid Kleckner     if (PrologEndLoc)
35770f5bc99SReid Kleckner       break;
35870f5bc99SReid Kleckner     for (const auto &MI : MBB) {
35970f5bc99SReid Kleckner       if (MI.isDebugValue())
36070f5bc99SReid Kleckner         continue;
36170f5bc99SReid Kleckner 
36270f5bc99SReid Kleckner       // First known non-DBG_VALUE and non-frame setup location marks
36370f5bc99SReid Kleckner       // the beginning of the function body.
36470f5bc99SReid Kleckner       // FIXME: do we need the first subcondition?
36570f5bc99SReid Kleckner       if (!MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) {
36670f5bc99SReid Kleckner         PrologEndLoc = MI.getDebugLoc();
36770f5bc99SReid Kleckner         break;
36870f5bc99SReid Kleckner       }
36970f5bc99SReid Kleckner       EmptyPrologue = false;
37070f5bc99SReid Kleckner     }
37170f5bc99SReid Kleckner   }
37270f5bc99SReid Kleckner   // Record beginning of function if we have a non-empty prologue.
37370f5bc99SReid Kleckner   if (PrologEndLoc && !EmptyPrologue) {
37470f5bc99SReid Kleckner     DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc();
37570f5bc99SReid Kleckner     maybeRecordLocation(FnStartDL, MF);
37670f5bc99SReid Kleckner   }
37770f5bc99SReid Kleckner }
37870f5bc99SReid Kleckner 
37970f5bc99SReid Kleckner void CodeViewDebug::endFunction(const MachineFunction *MF) {
38070f5bc99SReid Kleckner   if (!Asm || !CurFn)  // We haven't created any debug info for this function.
38170f5bc99SReid Kleckner     return;
38270f5bc99SReid Kleckner 
38370f5bc99SReid Kleckner   const Function *GV = MF->getFunction();
38470f5bc99SReid Kleckner   assert(FnDebugInfo.count(GV));
38570f5bc99SReid Kleckner   assert(CurFn == &FnDebugInfo[GV]);
38670f5bc99SReid Kleckner 
38770f5bc99SReid Kleckner   if (CurFn->Instrs.empty()) {
38870f5bc99SReid Kleckner     FnDebugInfo.erase(GV);
38970f5bc99SReid Kleckner     VisitedFunctions.pop_back();
39070f5bc99SReid Kleckner   } else {
39170f5bc99SReid Kleckner     CurFn->End = Asm->getFunctionEnd();
39270f5bc99SReid Kleckner   }
39370f5bc99SReid Kleckner   CurFn = nullptr;
39470f5bc99SReid Kleckner }
39570f5bc99SReid Kleckner 
39670f5bc99SReid Kleckner void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
39770f5bc99SReid Kleckner   // Ignore DBG_VALUE locations and function prologue.
39870f5bc99SReid Kleckner   if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
39970f5bc99SReid Kleckner     return;
40070f5bc99SReid Kleckner   DebugLoc DL = MI->getDebugLoc();
40170f5bc99SReid Kleckner   if (DL == PrevInstLoc || !DL)
40270f5bc99SReid Kleckner     return;
40370f5bc99SReid Kleckner   maybeRecordLocation(DL, Asm->MF);
40470f5bc99SReid Kleckner }
40570f5bc99SReid Kleckner }
406