18456b16eSEugene Zelenko //===- DebugCrossImpSubsection.cpp ----------------------------------------===//
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"
118456b16eSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
12349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13349c18f8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
148456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamReader.h"
158456b16eSEugene Zelenko #include "llvm/Support/BinaryStreamWriter.h"
168456b16eSEugene Zelenko #include "llvm/Support/Endian.h"
178456b16eSEugene Zelenko #include "llvm/Support/Error.h"
188456b16eSEugene Zelenko #include <algorithm>
198456b16eSEugene Zelenko #include <cstdint>
208456b16eSEugene Zelenko #include <utility>
218456b16eSEugene Zelenko #include <vector>
22349c18f8SZachary Turner 
23349c18f8SZachary Turner using namespace llvm;
24349c18f8SZachary Turner using namespace llvm::codeview;
25349c18f8SZachary Turner 
267e62cd17SZachary Turner Error VarStreamArrayExtractor<CrossModuleImportItem>::
277e62cd17SZachary Turner operator()(BinaryStreamRef Stream, uint32_t &Len,
28349c18f8SZachary Turner            codeview::CrossModuleImportItem &Item) {
29349c18f8SZachary Turner   BinaryStreamReader Reader(Stream);
30349c18f8SZachary Turner   if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
31349c18f8SZachary Turner     return make_error<CodeViewError>(
32349c18f8SZachary Turner         cv_error_code::insufficient_buffer,
33349c18f8SZachary Turner         "Not enough bytes for a Cross Module Import Header!");
34349c18f8SZachary Turner   if (auto EC = Reader.readObject(Item.Header))
35349c18f8SZachary Turner     return EC;
36349c18f8SZachary Turner   if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
37349c18f8SZachary Turner     return make_error<CodeViewError>(
38349c18f8SZachary Turner         cv_error_code::insufficient_buffer,
39349c18f8SZachary Turner         "Not enough to read specified number of Cross Module References!");
40349c18f8SZachary Turner   if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
41349c18f8SZachary Turner     return EC;
42349c18f8SZachary Turner   return Error::success();
43349c18f8SZachary Turner }
44349c18f8SZachary Turner 
45349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(
46349c18f8SZachary Turner     BinaryStreamReader Reader) {
47349c18f8SZachary Turner   return Reader.readArray(References, Reader.bytesRemaining());
48349c18f8SZachary Turner }
49349c18f8SZachary Turner 
50349c18f8SZachary Turner Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
51349c18f8SZachary Turner   BinaryStreamReader Reader(Stream);
52349c18f8SZachary Turner   return initialize(Reader);
53349c18f8SZachary Turner }
54349c18f8SZachary Turner 
55349c18f8SZachary Turner void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
56349c18f8SZachary Turner                                                   uint32_t ImportId) {
57349c18f8SZachary Turner   Strings.insert(Module);
58349c18f8SZachary Turner   std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
59349c18f8SZachary Turner   auto Result = Mappings.insert(std::make_pair(Module, Targets));
60349c18f8SZachary Turner   if (!Result.second)
61349c18f8SZachary Turner     Result.first->getValue().push_back(Targets[0]);
62349c18f8SZachary Turner }
63349c18f8SZachary Turner 
64349c18f8SZachary Turner uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
65349c18f8SZachary Turner   uint32_t Size = 0;
66349c18f8SZachary Turner   for (const auto &Item : Mappings) {
67349c18f8SZachary Turner     Size += sizeof(CrossModuleImport);
68349c18f8SZachary Turner     Size += sizeof(support::ulittle32_t) * Item.second.size();
69349c18f8SZachary Turner   }
70349c18f8SZachary Turner   return Size;
71349c18f8SZachary Turner }
72349c18f8SZachary Turner 
73349c18f8SZachary Turner Error DebugCrossModuleImportsSubsection::commit(
74349c18f8SZachary Turner     BinaryStreamWriter &Writer) const {
75349c18f8SZachary Turner   using T = decltype(&*Mappings.begin());
76349c18f8SZachary Turner   std::vector<T> Ids;
77349c18f8SZachary Turner   Ids.reserve(Mappings.size());
78349c18f8SZachary Turner 
79349c18f8SZachary Turner   for (const auto &M : Mappings)
80349c18f8SZachary Turner     Ids.push_back(&M);
81349c18f8SZachary Turner 
82349c18f8SZachary Turner   std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) {
83*71d36ad9SZachary Turner     return Strings.getIdForString(L1->getKey()) <
84*71d36ad9SZachary Turner            Strings.getIdForString(L2->getKey());
85349c18f8SZachary Turner   });
86349c18f8SZachary Turner 
87349c18f8SZachary Turner   for (const auto &Item : Ids) {
88349c18f8SZachary Turner     CrossModuleImport Imp;
89*71d36ad9SZachary Turner     Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey());
90349c18f8SZachary Turner     Imp.Count = Item->getValue().size();
91349c18f8SZachary Turner     if (auto EC = Writer.writeObject(Imp))
92349c18f8SZachary Turner       return EC;
93349c18f8SZachary Turner     if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
94349c18f8SZachary Turner       return EC;
95349c18f8SZachary Turner   }
96349c18f8SZachary Turner   return Error::success();
97349c18f8SZachary Turner }
98