18456b16eSEugene Zelenko //===- DebugInlineeLinesSubsection.cpp ------------------------------------===//
28c099fe0SZachary Turner //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68c099fe0SZachary Turner //
78c099fe0SZachary Turner //===----------------------------------------------------------------------===//
88c099fe0SZachary Turner 
98c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
108456b16eSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
118456b16eSEugene Zelenko #include "llvm/DebugInfo/CodeView/CodeView.h"
128c099fe0SZachary Turner #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
138456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamReader.h"
148456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamWriter.h"
158456b16eSEugene Zelenko #include "llvm/Support/Endian.h"
168456b16eSEugene Zelenko #include "llvm/Support/Error.h"
178456b16eSEugene Zelenko #include <cassert>
188456b16eSEugene Zelenko #include <cstdint>
198c099fe0SZachary Turner 
208c099fe0SZachary Turner using namespace llvm;
218c099fe0SZachary Turner using namespace llvm::codeview;
228c099fe0SZachary Turner 
237e62cd17SZachary Turner Error VarStreamArrayExtractor<InlineeSourceLine>::
247e62cd17SZachary Turner operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) {
258c099fe0SZachary Turner   BinaryStreamReader Reader(Stream);
268c099fe0SZachary Turner 
278c099fe0SZachary Turner   if (auto EC = Reader.readObject(Item.Header))
288c099fe0SZachary Turner     return EC;
298c099fe0SZachary Turner 
308c099fe0SZachary Turner   if (HasExtraFiles) {
318c099fe0SZachary Turner     uint32_t ExtraFileCount;
328c099fe0SZachary Turner     if (auto EC = Reader.readInteger(ExtraFileCount))
338c099fe0SZachary Turner       return EC;
348c099fe0SZachary Turner     if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
358c099fe0SZachary Turner       return EC;
368c099fe0SZachary Turner   }
378c099fe0SZachary Turner 
388c099fe0SZachary Turner   Len = Reader.getOffset();
398c099fe0SZachary Turner   return Error::success();
408c099fe0SZachary Turner }
418c099fe0SZachary Turner 
428c099fe0SZachary Turner DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef()
438c099fe0SZachary Turner     : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {}
448c099fe0SZachary Turner 
458c099fe0SZachary Turner Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) {
468c099fe0SZachary Turner   if (auto EC = Reader.readEnum(Signature))
478c099fe0SZachary Turner     return EC;
488c099fe0SZachary Turner 
497e62cd17SZachary Turner   Lines.getExtractor().HasExtraFiles = hasExtraFiles();
507e62cd17SZachary Turner   if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining()))
518c099fe0SZachary Turner     return EC;
528c099fe0SZachary Turner 
538c099fe0SZachary Turner   assert(Reader.bytesRemaining() == 0);
548c099fe0SZachary Turner   return Error::success();
558c099fe0SZachary Turner }
568c099fe0SZachary Turner 
578c099fe0SZachary Turner bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const {
588c099fe0SZachary Turner   return Signature == InlineeLinesSignature::ExtraFiles;
598c099fe0SZachary Turner }
608c099fe0SZachary Turner 
618c099fe0SZachary Turner DebugInlineeLinesSubsection::DebugInlineeLinesSubsection(
628c099fe0SZachary Turner     DebugChecksumsSubsection &Checksums, bool HasExtraFiles)
638c099fe0SZachary Turner     : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums),
648c099fe0SZachary Turner       HasExtraFiles(HasExtraFiles) {}
658c099fe0SZachary Turner 
66591312c5SZachary Turner uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const {
678c099fe0SZachary Turner   // 4 bytes for the signature
688c099fe0SZachary Turner   uint32_t Size = sizeof(InlineeLinesSignature);
698c099fe0SZachary Turner 
708c099fe0SZachary Turner   // one header for each entry.
718c099fe0SZachary Turner   Size += Entries.size() * sizeof(InlineeSourceLineHeader);
728c099fe0SZachary Turner   if (HasExtraFiles) {
738c099fe0SZachary Turner     // If extra files are enabled, one count for each entry.
748c099fe0SZachary Turner     Size += Entries.size() * sizeof(uint32_t);
758c099fe0SZachary Turner 
768c099fe0SZachary Turner     // And one file id for each file.
778c099fe0SZachary Turner     Size += ExtraFileCount * sizeof(uint32_t);
788c099fe0SZachary Turner   }
798c099fe0SZachary Turner   assert(Size % 4 == 0);
808c099fe0SZachary Turner   return Size;
818c099fe0SZachary Turner }
828c099fe0SZachary Turner 
83591312c5SZachary Turner Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const {
848c099fe0SZachary Turner   InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
858c099fe0SZachary Turner   if (HasExtraFiles)
868c099fe0SZachary Turner     Sig = InlineeLinesSignature::ExtraFiles;
878c099fe0SZachary Turner 
888c099fe0SZachary Turner   if (auto EC = Writer.writeEnum(Sig))
898c099fe0SZachary Turner     return EC;
908c099fe0SZachary Turner 
918c099fe0SZachary Turner   for (const auto &E : Entries) {
928c099fe0SZachary Turner     if (auto EC = Writer.writeObject(E.Header))
938c099fe0SZachary Turner       return EC;
948c099fe0SZachary Turner 
958c099fe0SZachary Turner     if (!HasExtraFiles)
968c099fe0SZachary Turner       continue;
978c099fe0SZachary Turner 
988c099fe0SZachary Turner     if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
998c099fe0SZachary Turner       return EC;
1008c099fe0SZachary Turner     if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
1018c099fe0SZachary Turner       return EC;
1028c099fe0SZachary Turner   }
1038c099fe0SZachary Turner 
1048c099fe0SZachary Turner   return Error::success();
1058c099fe0SZachary Turner }
1068c099fe0SZachary Turner 
1078c099fe0SZachary Turner void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) {
1088c099fe0SZachary Turner   uint32_t Offset = Checksums.mapChecksumOffset(FileName);
1098c099fe0SZachary Turner 
1108c099fe0SZachary Turner   auto &Entry = Entries.back();
1118c099fe0SZachary Turner   Entry.ExtraFiles.push_back(ulittle32_t(Offset));
1128c099fe0SZachary Turner   ++ExtraFileCount;
1138c099fe0SZachary Turner }
1148c099fe0SZachary Turner 
1158c099fe0SZachary Turner void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId,
1168c099fe0SZachary Turner                                                 StringRef FileName,
1178c099fe0SZachary Turner                                                 uint32_t SourceLine) {
1188c099fe0SZachary Turner   uint32_t Offset = Checksums.mapChecksumOffset(FileName);
1198c099fe0SZachary Turner 
1208c099fe0SZachary Turner   Entries.emplace_back();
1218c099fe0SZachary Turner   auto &Entry = Entries.back();
1228c099fe0SZachary Turner   Entry.Header.FileID = Offset;
1238c099fe0SZachary Turner   Entry.Header.SourceLineNum = SourceLine;
1248c099fe0SZachary Turner   Entry.Header.Inlinee = FuncId;
1258c099fe0SZachary Turner }
126