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