1349c18f8SZachary Turner //===- DebugCrossImpSubsection.cpp ------------------------------*- C++ -*-===//
2349c18f8SZachary Turner //
3349c18f8SZachary Turner //                     The LLVM Compiler Infrastructure
4349c18f8SZachary Turner //
5349c18f8SZachary Turner // This file is distributed under the University of Illinois Open Source
6349c18f8SZachary Turner // License. See LICENSE.TXT for details.
7349c18f8SZachary Turner //
8349c18f8SZachary Turner //===----------------------------------------------------------------------===//
9349c18f8SZachary Turner 
10349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
11349c18f8SZachary Turner 
12349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
14349c18f8SZachary Turner 
15349c18f8SZachary Turner using namespace llvm;
16349c18f8SZachary Turner using namespace llvm::codeview;
17349c18f8SZachary Turner 
18349c18f8SZachary Turner namespace llvm {
19*7e62cd17SZachary Turner Error VarStreamArrayExtractor<CrossModuleImportItem>::
20*7e62cd17SZachary Turner operator()(BinaryStreamRef Stream, uint32_t &Len,
21349c18f8SZachary Turner            codeview::CrossModuleImportItem &Item) {
22349c18f8SZachary Turner   BinaryStreamReader Reader(Stream);
23349c18f8SZachary Turner   if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
24349c18f8SZachary Turner     return make_error<CodeViewError>(
25349c18f8SZachary Turner         cv_error_code::insufficient_buffer,
26349c18f8SZachary Turner         "Not enough bytes for a Cross Module Import Header!");
27349c18f8SZachary Turner   if (auto EC = Reader.readObject(Item.Header))
28349c18f8SZachary Turner     return EC;
29349c18f8SZachary Turner   if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
30349c18f8SZachary Turner     return make_error<CodeViewError>(
31349c18f8SZachary Turner         cv_error_code::insufficient_buffer,
32349c18f8SZachary Turner         "Not enough to read specified number of Cross Module References!");
33349c18f8SZachary Turner   if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
34349c18f8SZachary Turner     return EC;
35349c18f8SZachary Turner   return Error::success();
36349c18f8SZachary Turner }
37349c18f8SZachary Turner }
38349c18f8SZachary Turner 
39349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(
40349c18f8SZachary Turner     BinaryStreamReader Reader) {
41349c18f8SZachary Turner   return Reader.readArray(References, Reader.bytesRemaining());
42349c18f8SZachary Turner }
43349c18f8SZachary Turner 
44349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
45349c18f8SZachary Turner   BinaryStreamReader Reader(Stream);
46349c18f8SZachary Turner   return initialize(Reader);
47349c18f8SZachary Turner }
48349c18f8SZachary Turner 
49349c18f8SZachary Turner void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
50349c18f8SZachary Turner                                                   uint32_t ImportId) {
51349c18f8SZachary Turner   Strings.insert(Module);
52349c18f8SZachary Turner   std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
53349c18f8SZachary Turner   auto Result = Mappings.insert(std::make_pair(Module, Targets));
54349c18f8SZachary Turner   if (!Result.second)
55349c18f8SZachary Turner     Result.first->getValue().push_back(Targets[0]);
56349c18f8SZachary Turner }
57349c18f8SZachary Turner 
58349c18f8SZachary Turner uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
59349c18f8SZachary Turner   uint32_t Size = 0;
60349c18f8SZachary Turner   for (const auto &Item : Mappings) {
61349c18f8SZachary Turner     Size += sizeof(CrossModuleImport);
62349c18f8SZachary Turner     Size += sizeof(support::ulittle32_t) * Item.second.size();
63349c18f8SZachary Turner   }
64349c18f8SZachary Turner   return Size;
65349c18f8SZachary Turner }
66349c18f8SZachary Turner 
67349c18f8SZachary Turner Error DebugCrossModuleImportsSubsection::commit(
68349c18f8SZachary Turner     BinaryStreamWriter &Writer) const {
69349c18f8SZachary Turner   using T = decltype(&*Mappings.begin());
70349c18f8SZachary Turner   std::vector<T> Ids;
71349c18f8SZachary Turner   Ids.reserve(Mappings.size());
72349c18f8SZachary Turner 
73349c18f8SZachary Turner   for (const auto &M : Mappings)
74349c18f8SZachary Turner     Ids.push_back(&M);
75349c18f8SZachary Turner 
76349c18f8SZachary Turner   std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) {
77349c18f8SZachary Turner     return Strings.getStringId(L1->getKey()) <
78349c18f8SZachary Turner            Strings.getStringId(L2->getKey());
79349c18f8SZachary Turner   });
80349c18f8SZachary Turner 
81349c18f8SZachary Turner   for (const auto &Item : Ids) {
82349c18f8SZachary Turner     CrossModuleImport Imp;
83349c18f8SZachary Turner     Imp.ModuleNameOffset = Strings.getStringId(Item->getKey());
84349c18f8SZachary Turner     Imp.Count = Item->getValue().size();
85349c18f8SZachary Turner     if (auto EC = Writer.writeObject(Imp))
86349c18f8SZachary Turner       return EC;
87349c18f8SZachary Turner     if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
88349c18f8SZachary Turner       return EC;
89349c18f8SZachary Turner   }
90349c18f8SZachary Turner   return Error::success();
91349c18f8SZachary Turner }
92