189cb50c9SDimitry Andric //===- DebugInlineeLinesSubsection.cpp ------------------------*- C++-*-===//
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"
1189cb50c9SDimitry Andric 
1289cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h"
1389cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
1489cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
1589cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
1689cb50c9SDimitry Andric 
1789cb50c9SDimitry Andric using namespace llvm;
1889cb50c9SDimitry Andric using namespace llvm::codeview;
1989cb50c9SDimitry Andric 
20*db17bf38SDimitry Andric Error VarStreamArrayExtractor<InlineeSourceLine>::
21*db17bf38SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) {
2289cb50c9SDimitry Andric   BinaryStreamReader Reader(Stream);
2389cb50c9SDimitry Andric 
2489cb50c9SDimitry Andric   if (auto EC = Reader.readObject(Item.Header))
2589cb50c9SDimitry Andric     return EC;
2689cb50c9SDimitry Andric 
2789cb50c9SDimitry Andric   if (HasExtraFiles) {
2889cb50c9SDimitry Andric     uint32_t ExtraFileCount;
2989cb50c9SDimitry Andric     if (auto EC = Reader.readInteger(ExtraFileCount))
3089cb50c9SDimitry Andric       return EC;
3189cb50c9SDimitry Andric     if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
3289cb50c9SDimitry Andric       return EC;
3389cb50c9SDimitry Andric   }
3489cb50c9SDimitry Andric 
3589cb50c9SDimitry Andric   Len = Reader.getOffset();
3689cb50c9SDimitry Andric   return Error::success();
3789cb50c9SDimitry Andric }
3889cb50c9SDimitry Andric 
3989cb50c9SDimitry Andric DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
4089cb50c9SDimitry Andric     : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
4189cb50c9SDimitry Andric 
4289cb50c9SDimitry Andric Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
4389cb50c9SDimitry Andric   if (auto EC = Reader.readEnum(Signature))
4489cb50c9SDimitry Andric     return EC;
4589cb50c9SDimitry Andric 
46*db17bf38SDimitry Andric   Lines.getExtractor().HasExtraFiles = hasExtraFiles();
47*db17bf38SDimitry Andric   if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining()))
4889cb50c9SDimitry Andric     return EC;
4989cb50c9SDimitry Andric 
5089cb50c9SDimitry Andric   assert(Reader.bytesRemaining() == 0);
5189cb50c9SDimitry Andric   return Error::success();
5289cb50c9SDimitry Andric }
5389cb50c9SDimitry Andric 
5489cb50c9SDimitry Andric bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
5589cb50c9SDimitry Andric   return Signature == InlineeLinesSignature::ExtraFiles;
5689cb50c9SDimitry Andric }
5789cb50c9SDimitry Andric 
5889cb50c9SDimitry Andric DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
5989cb50c9SDimitry Andric     DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
6089cb50c9SDimitry Andric     : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
6189cb50c9SDimitry Andric       HasExtraFiles(HasExtraFiles) {}
6289cb50c9SDimitry Andric 
6389cb50c9SDimitry Andric uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const {
6489cb50c9SDimitry Andric   // 4 bytes for the signature
6589cb50c9SDimitry Andric   uint32_t Size = sizeof(InlineeLinesSignature);
6689cb50c9SDimitry Andric 
6789cb50c9SDimitry Andric   // one header for each entry.
6889cb50c9SDimitry Andric   Size += Entries.size() * sizeof(InlineeSourceLineHeader);
6989cb50c9SDimitry Andric   if (HasExtraFiles) {
7089cb50c9SDimitry Andric     // If extra files are enabled, one count for each entry.
7189cb50c9SDimitry Andric     Size += Entries.size() * sizeof(uint32_t);
7289cb50c9SDimitry Andric 
7389cb50c9SDimitry Andric     // And one file id for each file.
7489cb50c9SDimitry Andric     Size += ExtraFileCount * sizeof(uint32_t);
7589cb50c9SDimitry Andric   }
7689cb50c9SDimitry Andric   assert(Size % 4 == 0);
7789cb50c9SDimitry Andric   return Size;
7889cb50c9SDimitry Andric }
7989cb50c9SDimitry Andric 
8089cb50c9SDimitry Andric Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const {
8189cb50c9SDimitry Andric   InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
8289cb50c9SDimitry Andric   if (HasExtraFiles)
8389cb50c9SDimitry Andric     Sig = InlineeLinesSignature::ExtraFiles;
8489cb50c9SDimitry Andric 
8589cb50c9SDimitry Andric   if (auto EC = Writer.writeEnum(Sig))
8689cb50c9SDimitry Andric     return EC;
8789cb50c9SDimitry Andric 
8889cb50c9SDimitry Andric   for (const auto &E : Entries) {
8989cb50c9SDimitry Andric     if (auto EC = Writer.writeObject(E.Header))
9089cb50c9SDimitry Andric       return EC;
9189cb50c9SDimitry Andric 
9289cb50c9SDimitry Andric     if (!HasExtraFiles)
9389cb50c9SDimitry Andric       continue;
9489cb50c9SDimitry Andric 
9589cb50c9SDimitry Andric     if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
9689cb50c9SDimitry Andric       return EC;
9789cb50c9SDimitry Andric     if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
9889cb50c9SDimitry Andric       return EC;
9989cb50c9SDimitry Andric   }
10089cb50c9SDimitry Andric 
10189cb50c9SDimitry Andric   return Error::success();
10289cb50c9SDimitry Andric }
10389cb50c9SDimitry Andric 
10489cb50c9SDimitry Andric void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
10589cb50c9SDimitry Andric   uint32_t Offset = Checksums.mapChecksumOffset(FileName);
10689cb50c9SDimitry Andric 
10789cb50c9SDimitry Andric   auto &Entry = Entries.back();
10889cb50c9SDimitry Andric   Entry.ExtraFiles.push_back(ulittle32_t(Offset));
10989cb50c9SDimitry Andric   ++ExtraFileCount;
11089cb50c9SDimitry Andric }
11189cb50c9SDimitry Andric 
11289cb50c9SDimitry Andric void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
11389cb50c9SDimitry Andric                                                 StringRef FileName,
11489cb50c9SDimitry Andric                                                 uint32_t SourceLine) {
11589cb50c9SDimitry Andric   uint32_t Offset = Checksums.mapChecksumOffset(FileName);
11689cb50c9SDimitry Andric 
11789cb50c9SDimitry Andric   Entries.emplace_back();
11889cb50c9SDimitry Andric   auto &Entry = Entries.back();
11989cb50c9SDimitry Andric   Entry.Header.FileID = Offset;
12089cb50c9SDimitry Andric   Entry.Header.SourceLineNum = SourceLine;
12189cb50c9SDimitry Andric   Entry.Header.Inlinee = FuncId;
12289cb50c9SDimitry Andric }
123