19df3605dSDimitry Andric //===- DebugInlineeLinesSubsection.cpp ------------------------------------===//
2a303c417SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a303c417SDimitry Andric //
7a303c417SDimitry Andric //===----------------------------------------------------------------------===//
8a303c417SDimitry Andric
9ee2f195dSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
109df3605dSDimitry Andric #include "llvm/ADT/ArrayRef.h"
119df3605dSDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
12ee2f195dSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
13145449b1SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
149df3605dSDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
159df3605dSDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
169df3605dSDimitry Andric #include "llvm/Support/Endian.h"
179df3605dSDimitry Andric #include "llvm/Support/Error.h"
189df3605dSDimitry Andric #include <cassert>
199df3605dSDimitry Andric #include <cstdint>
20a303c417SDimitry Andric
21a303c417SDimitry Andric using namespace llvm;
22a303c417SDimitry Andric using namespace llvm::codeview;
23a303c417SDimitry Andric
247ab83427SDimitry Andric Error VarStreamArrayExtractor<InlineeSourceLine>::
operator ()(BinaryStreamRef Stream,uint32_t & Len,InlineeSourceLine & Item)257ab83427SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) {
26a303c417SDimitry Andric BinaryStreamReader Reader(Stream);
27a303c417SDimitry Andric
28a303c417SDimitry Andric if (auto EC = Reader.readObject(Item.Header))
29a303c417SDimitry Andric return EC;
30a303c417SDimitry Andric
31148779dfSDimitry Andric if (HasExtraFiles) {
32a303c417SDimitry Andric uint32_t ExtraFileCount;
33a303c417SDimitry Andric if (auto EC = Reader.readInteger(ExtraFileCount))
34a303c417SDimitry Andric return EC;
35a303c417SDimitry Andric if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
36a303c417SDimitry Andric return EC;
37a303c417SDimitry Andric }
38a303c417SDimitry Andric
39a303c417SDimitry Andric Len = Reader.getOffset();
40a303c417SDimitry Andric return Error::success();
41a303c417SDimitry Andric }
42a303c417SDimitry Andric
DebugInlineeLinesSubsectionRef()43ee2f195dSDimitry Andric DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
44ee2f195dSDimitry Andric : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
45a303c417SDimitry Andric
initialize(BinaryStreamReader Reader)46ee2f195dSDimitry Andric Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
47a303c417SDimitry Andric if (auto EC = Reader.readEnum(Signature))
48a303c417SDimitry Andric return EC;
49a303c417SDimitry Andric
507ab83427SDimitry Andric Lines.getExtractor().HasExtraFiles = hasExtraFiles();
517ab83427SDimitry Andric if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining()))
52a303c417SDimitry Andric return EC;
53a303c417SDimitry Andric
54a303c417SDimitry Andric assert(Reader.bytesRemaining() == 0);
55a303c417SDimitry Andric return Error::success();
56a303c417SDimitry Andric }
57a303c417SDimitry Andric
hasExtraFiles() const58ee2f195dSDimitry Andric bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
59a303c417SDimitry Andric return Signature == InlineeLinesSignature::ExtraFiles;
60a303c417SDimitry Andric }
61a303c417SDimitry Andric
DebugInlineeLinesSubsection(DebugChecksumsSubsection & Checksums,bool HasExtraFiles)62ee2f195dSDimitry Andric DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
63ee2f195dSDimitry Andric DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
64ee2f195dSDimitry Andric : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
65ee2f195dSDimitry Andric HasExtraFiles(HasExtraFiles) {}
66a303c417SDimitry Andric
calculateSerializedSize() const67ee2f195dSDimitry Andric uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const {
68a303c417SDimitry Andric // 4 bytes for the signature
69a303c417SDimitry Andric uint32_t Size = sizeof(InlineeLinesSignature);
70a303c417SDimitry Andric
71a303c417SDimitry Andric // one header for each entry.
72a303c417SDimitry Andric Size += Entries.size() * sizeof(InlineeSourceLineHeader);
73a303c417SDimitry Andric if (HasExtraFiles) {
74a303c417SDimitry Andric // If extra files are enabled, one count for each entry.
75a303c417SDimitry Andric Size += Entries.size() * sizeof(uint32_t);
76a303c417SDimitry Andric
77a303c417SDimitry Andric // And one file id for each file.
78a303c417SDimitry Andric Size += ExtraFileCount * sizeof(uint32_t);
79a303c417SDimitry Andric }
80a303c417SDimitry Andric assert(Size % 4 == 0);
81a303c417SDimitry Andric return Size;
82a303c417SDimitry Andric }
83a303c417SDimitry Andric
commit(BinaryStreamWriter & Writer) const84ee2f195dSDimitry Andric Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const {
85a303c417SDimitry Andric InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
86a303c417SDimitry Andric if (HasExtraFiles)
87a303c417SDimitry Andric Sig = InlineeLinesSignature::ExtraFiles;
88a303c417SDimitry Andric
89a303c417SDimitry Andric if (auto EC = Writer.writeEnum(Sig))
90a303c417SDimitry Andric return EC;
91a303c417SDimitry Andric
92a303c417SDimitry Andric for (const auto &E : Entries) {
93a303c417SDimitry Andric if (auto EC = Writer.writeObject(E.Header))
94a303c417SDimitry Andric return EC;
95a303c417SDimitry Andric
96a303c417SDimitry Andric if (!HasExtraFiles)
97a303c417SDimitry Andric continue;
98a303c417SDimitry Andric
99a303c417SDimitry Andric if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
100a303c417SDimitry Andric return EC;
101e3b55780SDimitry Andric if (auto EC = Writer.writeArray(ArrayRef(E.ExtraFiles)))
102a303c417SDimitry Andric return EC;
103a303c417SDimitry Andric }
104a303c417SDimitry Andric
105a303c417SDimitry Andric return Error::success();
106a303c417SDimitry Andric }
107a303c417SDimitry Andric
addExtraFile(StringRef FileName)108ee2f195dSDimitry Andric void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
109148779dfSDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName);
110148779dfSDimitry Andric
111a303c417SDimitry Andric auto &Entry = Entries.back();
112148779dfSDimitry Andric Entry.ExtraFiles.push_back(ulittle32_t(Offset));
113a303c417SDimitry Andric ++ExtraFileCount;
114a303c417SDimitry Andric }
115a303c417SDimitry Andric
addInlineSite(TypeIndex FuncId,StringRef FileName,uint32_t SourceLine)116ee2f195dSDimitry Andric void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
117148779dfSDimitry Andric StringRef FileName,
118a303c417SDimitry Andric uint32_t SourceLine) {
119148779dfSDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName);
120148779dfSDimitry Andric
121a303c417SDimitry Andric Entries.emplace_back();
122a303c417SDimitry Andric auto &Entry = Entries.back();
123148779dfSDimitry Andric Entry.Header.FileID = Offset;
124a303c417SDimitry Andric Entry.Header.SourceLineNum = SourceLine;
125a303c417SDimitry Andric Entry.Header.Inlinee = FuncId;
126a303c417SDimitry Andric }
127