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