1*a580b014SDimitry Andric //===- DebugInlineeLinesSubsection.cpp ------------------------------------===//
289cb50c9SDimitry Andric //
389cb50c9SDimitry Andric // The LLVM Compiler Infrastructure
489cb50c9SDimitry Andric //
589cb50c9SDimitry Andric // This file is distributed under the University of Illinois Open Source
689cb50c9SDimitry Andric // License. See LICENSE.TXT for details.
789cb50c9SDimitry Andric //
889cb50c9SDimitry Andric //===----------------------------------------------------------------------===//
989cb50c9SDimitry Andric
1089cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
11*a580b014SDimitry Andric #include "llvm/ADT/ArrayRef.h"
12*a580b014SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
1389cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
14*a580b014SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
15*a580b014SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
16*a580b014SDimitry Andric #include "llvm/Support/Endian.h"
17*a580b014SDimitry Andric #include "llvm/Support/Error.h"
18*a580b014SDimitry Andric #include <cassert>
19*a580b014SDimitry Andric #include <cstdint>
2089cb50c9SDimitry Andric
2189cb50c9SDimitry Andric using namespace llvm;
2289cb50c9SDimitry Andric using namespace llvm::codeview;
2389cb50c9SDimitry Andric
24db17bf38SDimitry Andric Error VarStreamArrayExtractor<InlineeSourceLine>::
operator ()(BinaryStreamRef Stream,uint32_t & Len,InlineeSourceLine & Item)25db17bf38SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) {
2689cb50c9SDimitry Andric BinaryStreamReader Reader(Stream);
2789cb50c9SDimitry Andric
2889cb50c9SDimitry Andric if (auto EC = Reader.readObject(Item.Header))
2989cb50c9SDimitry Andric return EC;
3089cb50c9SDimitry Andric
3189cb50c9SDimitry Andric if (HasExtraFiles) {
3289cb50c9SDimitry Andric uint32_t ExtraFileCount;
3389cb50c9SDimitry Andric if (auto EC = Reader.readInteger(ExtraFileCount))
3489cb50c9SDimitry Andric return EC;
3589cb50c9SDimitry Andric if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
3689cb50c9SDimitry Andric return EC;
3789cb50c9SDimitry Andric }
3889cb50c9SDimitry Andric
3989cb50c9SDimitry Andric Len = Reader.getOffset();
4089cb50c9SDimitry Andric return Error::success();
4189cb50c9SDimitry Andric }
4289cb50c9SDimitry Andric
DebugInlineeLinesSubsectionRef()4389cb50c9SDimitry Andric DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
4489cb50c9SDimitry Andric : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
4589cb50c9SDimitry Andric
initialize(BinaryStreamReader Reader)4689cb50c9SDimitry Andric Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
4789cb50c9SDimitry Andric if (auto EC = Reader.readEnum(Signature))
4889cb50c9SDimitry Andric return EC;
4989cb50c9SDimitry Andric
50db17bf38SDimitry Andric Lines.getExtractor().HasExtraFiles = hasExtraFiles();
51db17bf38SDimitry Andric if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining()))
5289cb50c9SDimitry Andric return EC;
5389cb50c9SDimitry Andric
5489cb50c9SDimitry Andric assert(Reader.bytesRemaining() == 0);
5589cb50c9SDimitry Andric return Error::success();
5689cb50c9SDimitry Andric }
5789cb50c9SDimitry Andric
hasExtraFiles() const5889cb50c9SDimitry Andric bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
5989cb50c9SDimitry Andric return Signature == InlineeLinesSignature::ExtraFiles;
6089cb50c9SDimitry Andric }
6189cb50c9SDimitry Andric
DebugInlineeLinesSubsection(DebugChecksumsSubsection & Checksums,bool HasExtraFiles)6289cb50c9SDimitry Andric DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
6389cb50c9SDimitry Andric DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
6489cb50c9SDimitry Andric : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
6589cb50c9SDimitry Andric HasExtraFiles(HasExtraFiles) {}
6689cb50c9SDimitry Andric
calculateSerializedSize() const6789cb50c9SDimitry Andric uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const {
6889cb50c9SDimitry Andric // 4 bytes for the signature
6989cb50c9SDimitry Andric uint32_t Size = sizeof(InlineeLinesSignature);
7089cb50c9SDimitry Andric
7189cb50c9SDimitry Andric // one header for each entry.
7289cb50c9SDimitry Andric Size += Entries.size() * sizeof(InlineeSourceLineHeader);
7389cb50c9SDimitry Andric if (HasExtraFiles) {
7489cb50c9SDimitry Andric // If extra files are enabled, one count for each entry.
7589cb50c9SDimitry Andric Size += Entries.size() * sizeof(uint32_t);
7689cb50c9SDimitry Andric
7789cb50c9SDimitry Andric // And one file id for each file.
7889cb50c9SDimitry Andric Size += ExtraFileCount * sizeof(uint32_t);
7989cb50c9SDimitry Andric }
8089cb50c9SDimitry Andric assert(Size % 4 == 0);
8189cb50c9SDimitry Andric return Size;
8289cb50c9SDimitry Andric }
8389cb50c9SDimitry Andric
commit(BinaryStreamWriter & Writer) const8489cb50c9SDimitry Andric Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const {
8589cb50c9SDimitry Andric InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
8689cb50c9SDimitry Andric if (HasExtraFiles)
8789cb50c9SDimitry Andric Sig = InlineeLinesSignature::ExtraFiles;
8889cb50c9SDimitry Andric
8989cb50c9SDimitry Andric if (auto EC = Writer.writeEnum(Sig))
9089cb50c9SDimitry Andric return EC;
9189cb50c9SDimitry Andric
9289cb50c9SDimitry Andric for (const auto &E : Entries) {
9389cb50c9SDimitry Andric if (auto EC = Writer.writeObject(E.Header))
9489cb50c9SDimitry Andric return EC;
9589cb50c9SDimitry Andric
9689cb50c9SDimitry Andric if (!HasExtraFiles)
9789cb50c9SDimitry Andric continue;
9889cb50c9SDimitry Andric
9989cb50c9SDimitry Andric if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
10089cb50c9SDimitry Andric return EC;
10189cb50c9SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
10289cb50c9SDimitry Andric return EC;
10389cb50c9SDimitry Andric }
10489cb50c9SDimitry Andric
10589cb50c9SDimitry Andric return Error::success();
10689cb50c9SDimitry Andric }
10789cb50c9SDimitry Andric
addExtraFile(StringRef FileName)10889cb50c9SDimitry Andric void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
10989cb50c9SDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName);
11089cb50c9SDimitry Andric
11189cb50c9SDimitry Andric auto &Entry = Entries.back();
11289cb50c9SDimitry Andric Entry.ExtraFiles.push_back(ulittle32_t(Offset));
11389cb50c9SDimitry Andric ++ExtraFileCount;
11489cb50c9SDimitry Andric }
11589cb50c9SDimitry Andric
addInlineSite(TypeIndex FuncId,StringRef FileName,uint32_t SourceLine)11689cb50c9SDimitry Andric void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
11789cb50c9SDimitry Andric StringRef FileName,
11889cb50c9SDimitry Andric uint32_t SourceLine) {
11989cb50c9SDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName);
12089cb50c9SDimitry Andric
12189cb50c9SDimitry Andric Entries.emplace_back();
12289cb50c9SDimitry Andric auto &Entry = Entries.back();
12389cb50c9SDimitry Andric Entry.Header.FileID = Offset;
12489cb50c9SDimitry Andric Entry.Header.SourceLineNum = SourceLine;
12589cb50c9SDimitry Andric Entry.Header.Inlinee = FuncId;
12689cb50c9SDimitry Andric }
127