1*8c099fe0SZachary Turner //===- DebugInlineeLinesSubsection.cpp ------------------------*- C++-*-===//
2*8c099fe0SZachary Turner //
3*8c099fe0SZachary Turner //                     The LLVM Compiler Infrastructure
4*8c099fe0SZachary Turner //
5*8c099fe0SZachary Turner // This file is distributed under the University of Illinois Open Source
6*8c099fe0SZachary Turner // License. See LICENSE.TXT for details.
7*8c099fe0SZachary Turner //
8*8c099fe0SZachary Turner //===----------------------------------------------------------------------===//
9*8c099fe0SZachary Turner 
10*8c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
11*8c099fe0SZachary Turner 
12*8c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13*8c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
14*8c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
15*8c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/StringTable.h"
16*8c099fe0SZachary Turner 
17*8c099fe0SZachary Turner using namespace llvm;
18*8c099fe0SZachary Turner using namespace llvm::codeview;
19*8c099fe0SZachary Turner 
20*8c099fe0SZachary Turner Error VarStreamArrayExtractor<InlineeSourceLine>::extract(
21*8c099fe0SZachary Turner     BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item,
22*8c099fe0SZachary Turner     bool HasExtraFiles) {
23*8c099fe0SZachary Turner   BinaryStreamReader Reader(Stream);
24*8c099fe0SZachary Turner 
25*8c099fe0SZachary Turner   if (auto EC = Reader.readObject(Item.Header))
26*8c099fe0SZachary Turner     return EC;
27*8c099fe0SZachary Turner 
28*8c099fe0SZachary Turner   if (HasExtraFiles) {
29*8c099fe0SZachary Turner     uint32_t ExtraFileCount;
30*8c099fe0SZachary Turner     if (auto EC = Reader.readInteger(ExtraFileCount))
31*8c099fe0SZachary Turner       return EC;
32*8c099fe0SZachary Turner     if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
33*8c099fe0SZachary Turner       return EC;
34*8c099fe0SZachary Turner   }
35*8c099fe0SZachary Turner 
36*8c099fe0SZachary Turner   Len = Reader.getOffset();
37*8c099fe0SZachary Turner   return Error::success();
38*8c099fe0SZachary Turner }
39*8c099fe0SZachary Turner 
40*8c099fe0SZachary Turner DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
41*8c099fe0SZachary Turner     : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
42*8c099fe0SZachary Turner 
43*8c099fe0SZachary Turner Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
44*8c099fe0SZachary Turner   if (auto EC = Reader.readEnum(Signature))
45*8c099fe0SZachary Turner     return EC;
46*8c099fe0SZachary Turner 
47*8c099fe0SZachary Turner   if (auto EC =
48*8c099fe0SZachary Turner           Reader.readArray(Lines, Reader.bytesRemaining(), hasExtraFiles()))
49*8c099fe0SZachary Turner     return EC;
50*8c099fe0SZachary Turner 
51*8c099fe0SZachary Turner   assert(Reader.bytesRemaining() == 0);
52*8c099fe0SZachary Turner   return Error::success();
53*8c099fe0SZachary Turner }
54*8c099fe0SZachary Turner 
55*8c099fe0SZachary Turner bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
56*8c099fe0SZachary Turner   return Signature == InlineeLinesSignature::ExtraFiles;
57*8c099fe0SZachary Turner }
58*8c099fe0SZachary Turner 
59*8c099fe0SZachary Turner DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
60*8c099fe0SZachary Turner     DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
61*8c099fe0SZachary Turner     : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
62*8c099fe0SZachary Turner       HasExtraFiles(HasExtraFiles) {}
63*8c099fe0SZachary Turner 
64*8c099fe0SZachary Turner uint32_t DebugInlineeLinesSubsection::calculateSerializedLength() {
65*8c099fe0SZachary Turner   // 4 bytes for the signature
66*8c099fe0SZachary Turner   uint32_t Size = sizeof(InlineeLinesSignature);
67*8c099fe0SZachary Turner 
68*8c099fe0SZachary Turner   // one header for each entry.
69*8c099fe0SZachary Turner   Size += Entries.size() * sizeof(InlineeSourceLineHeader);
70*8c099fe0SZachary Turner   if (HasExtraFiles) {
71*8c099fe0SZachary Turner     // If extra files are enabled, one count for each entry.
72*8c099fe0SZachary Turner     Size += Entries.size() * sizeof(uint32_t);
73*8c099fe0SZachary Turner 
74*8c099fe0SZachary Turner     // And one file id for each file.
75*8c099fe0SZachary Turner     Size += ExtraFileCount * sizeof(uint32_t);
76*8c099fe0SZachary Turner   }
77*8c099fe0SZachary Turner   assert(Size % 4 == 0);
78*8c099fe0SZachary Turner   return Size;
79*8c099fe0SZachary Turner }
80*8c099fe0SZachary Turner 
81*8c099fe0SZachary Turner Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) {
82*8c099fe0SZachary Turner   InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
83*8c099fe0SZachary Turner   if (HasExtraFiles)
84*8c099fe0SZachary Turner     Sig = InlineeLinesSignature::ExtraFiles;
85*8c099fe0SZachary Turner 
86*8c099fe0SZachary Turner   if (auto EC = Writer.writeEnum(Sig))
87*8c099fe0SZachary Turner     return EC;
88*8c099fe0SZachary Turner 
89*8c099fe0SZachary Turner   for (const auto &E : Entries) {
90*8c099fe0SZachary Turner     if (auto EC = Writer.writeObject(E.Header))
91*8c099fe0SZachary Turner       return EC;
92*8c099fe0SZachary Turner 
93*8c099fe0SZachary Turner     if (!HasExtraFiles)
94*8c099fe0SZachary Turner       continue;
95*8c099fe0SZachary Turner 
96*8c099fe0SZachary Turner     if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
97*8c099fe0SZachary Turner       return EC;
98*8c099fe0SZachary Turner     if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
99*8c099fe0SZachary Turner       return EC;
100*8c099fe0SZachary Turner   }
101*8c099fe0SZachary Turner 
102*8c099fe0SZachary Turner   return Error::success();
103*8c099fe0SZachary Turner }
104*8c099fe0SZachary Turner 
105*8c099fe0SZachary Turner void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
106*8c099fe0SZachary Turner   uint32_t Offset = Checksums.mapChecksumOffset(FileName);
107*8c099fe0SZachary Turner 
108*8c099fe0SZachary Turner   auto &Entry = Entries.back();
109*8c099fe0SZachary Turner   Entry.ExtraFiles.push_back(ulittle32_t(Offset));
110*8c099fe0SZachary Turner   ++ExtraFileCount;
111*8c099fe0SZachary Turner }
112*8c099fe0SZachary Turner 
113*8c099fe0SZachary Turner void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
114*8c099fe0SZachary Turner                                                 StringRef FileName,
115*8c099fe0SZachary Turner                                                 uint32_t SourceLine) {
116*8c099fe0SZachary Turner   uint32_t Offset = Checksums.mapChecksumOffset(FileName);
117*8c099fe0SZachary Turner 
118*8c099fe0SZachary Turner   Entries.emplace_back();
119*8c099fe0SZachary Turner   auto &Entry = Entries.back();
120*8c099fe0SZachary Turner   Entry.Header.FileID = Offset;
121*8c099fe0SZachary Turner   Entry.Header.SourceLineNum = SourceLine;
122*8c099fe0SZachary Turner   Entry.Header.Inlinee = FuncId;
123*8c099fe0SZachary Turner }
124