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