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