1db17bf38SDimitry Andric //===- DebugCrossImpSubsection.cpp ------------------------------*- C++ -*-===//
2db17bf38SDimitry Andric //
3db17bf38SDimitry Andric //                     The LLVM Compiler Infrastructure
4db17bf38SDimitry Andric //
5db17bf38SDimitry Andric // This file is distributed under the University of Illinois Open Source
6db17bf38SDimitry Andric // License. See LICENSE.TXT for details.
7db17bf38SDimitry Andric //
8db17bf38SDimitry Andric //===----------------------------------------------------------------------===//
9db17bf38SDimitry Andric 
10db17bf38SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
11db17bf38SDimitry Andric 
12db17bf38SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13db17bf38SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
14db17bf38SDimitry Andric 
15db17bf38SDimitry Andric using namespace llvm;
16db17bf38SDimitry Andric using namespace llvm::codeview;
17db17bf38SDimitry Andric 
18db17bf38SDimitry Andric namespace llvm {
19db17bf38SDimitry Andric Error VarStreamArrayExtractor<CrossModuleImportItem>::
20db17bf38SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len,
21db17bf38SDimitry Andric            codeview::CrossModuleImportItem &Item) {
22db17bf38SDimitry Andric   BinaryStreamReader Reader(Stream);
23db17bf38SDimitry Andric   if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
24db17bf38SDimitry Andric     return make_error<CodeViewError>(
25db17bf38SDimitry Andric         cv_error_code::insufficient_buffer,
26db17bf38SDimitry Andric         "Not enough bytes for a Cross Module Import Header!");
27db17bf38SDimitry Andric   if (auto EC = Reader.readObject(Item.Header))
28db17bf38SDimitry Andric     return EC;
29db17bf38SDimitry Andric   if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
30db17bf38SDimitry Andric     return make_error<CodeViewError>(
31db17bf38SDimitry Andric         cv_error_code::insufficient_buffer,
32db17bf38SDimitry Andric         "Not enough to read specified number of Cross Module References!");
33db17bf38SDimitry Andric   if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
34db17bf38SDimitry Andric     return EC;
35db17bf38SDimitry Andric   return Error::success();
36db17bf38SDimitry Andric }
37db17bf38SDimitry Andric }
38db17bf38SDimitry Andric 
39db17bf38SDimitry Andric Error DebugCrossModuleImportsSubsectionRef::initialize(
40db17bf38SDimitry Andric     BinaryStreamReader Reader) {
41db17bf38SDimitry Andric   return Reader.readArray(References, Reader.bytesRemaining());
42db17bf38SDimitry Andric }
43db17bf38SDimitry Andric 
44db17bf38SDimitry Andric Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
45db17bf38SDimitry Andric   BinaryStreamReader Reader(Stream);
46db17bf38SDimitry Andric   return initialize(Reader);
47db17bf38SDimitry Andric }
48db17bf38SDimitry Andric 
49db17bf38SDimitry Andric void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
50db17bf38SDimitry Andric                                                   uint32_t ImportId) {
51db17bf38SDimitry Andric   Strings.insert(Module);
52db17bf38SDimitry Andric   std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
53db17bf38SDimitry Andric   auto Result = Mappings.insert(std::make_pair(Module, Targets));
54db17bf38SDimitry Andric   if (!Result.second)
55db17bf38SDimitry Andric     Result.first->getValue().push_back(Targets[0]);
56db17bf38SDimitry Andric }
57db17bf38SDimitry Andric 
58db17bf38SDimitry Andric uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
59db17bf38SDimitry Andric   uint32_t Size = 0;
60db17bf38SDimitry Andric   for (const auto &Item : Mappings) {
61db17bf38SDimitry Andric     Size += sizeof(CrossModuleImport);
62db17bf38SDimitry Andric     Size += sizeof(support::ulittle32_t) * Item.second.size();
63db17bf38SDimitry Andric   }
64db17bf38SDimitry Andric   return Size;
65db17bf38SDimitry Andric }
66db17bf38SDimitry Andric 
67db17bf38SDimitry Andric Error DebugCrossModuleImportsSubsection::commit(
68db17bf38SDimitry Andric     BinaryStreamWriter &Writer) const {
69db17bf38SDimitry Andric   using T = decltype(&*Mappings.begin());
70db17bf38SDimitry Andric   std::vector<T> Ids;
71db17bf38SDimitry Andric   Ids.reserve(Mappings.size());
72db17bf38SDimitry Andric 
73db17bf38SDimitry Andric   for (const auto &M : Mappings)
74db17bf38SDimitry Andric     Ids.push_back(&M);
75db17bf38SDimitry Andric 
76db17bf38SDimitry Andric   std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) {
77db17bf38SDimitry Andric     return Strings.getStringId(L1->getKey()) <
78db17bf38SDimitry Andric            Strings.getStringId(L2->getKey());
79db17bf38SDimitry Andric   });
80db17bf38SDimitry Andric 
81db17bf38SDimitry Andric   for (const auto &Item : Ids) {
82db17bf38SDimitry Andric     CrossModuleImport Imp;
83db17bf38SDimitry Andric     Imp.ModuleNameOffset = Strings.getStringId(Item->getKey());
84db17bf38SDimitry Andric     Imp.Count = Item->getValue().size();
85db17bf38SDimitry Andric     if (auto EC = Writer.writeObject(Imp))
86db17bf38SDimitry Andric       return EC;
87db17bf38SDimitry Andric     if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
88db17bf38SDimitry Andric       return EC;
89db17bf38SDimitry Andric   }
90db17bf38SDimitry Andric   return Error::success();
91db17bf38SDimitry Andric }
92