1a580b014SDimitry Andric //===- DebugStringTableSubsection.cpp - CodeView String Table -------------===//
289cb50c9SDimitry Andric //
389cb50c9SDimitry Andric //                     The LLVM Compiler Infrastructure
489cb50c9SDimitry Andric //
589cb50c9SDimitry Andric // This file is distributed under the University of Illinois Open Source
689cb50c9SDimitry Andric // License. See LICENSE.TXT for details.
789cb50c9SDimitry Andric //
889cb50c9SDimitry Andric //===----------------------------------------------------------------------===//
989cb50c9SDimitry Andric 
1089cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
11a580b014SDimitry Andric #include "llvm/ADT/StringRef.h"
12a580b014SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
1389cb50c9SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
1489cb50c9SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
15a580b014SDimitry Andric #include "llvm/Support/Error.h"
16a580b014SDimitry Andric #include <algorithm>
17a580b014SDimitry Andric #include <cassert>
18a580b014SDimitry Andric #include <cstdint>
1989cb50c9SDimitry Andric 
2089cb50c9SDimitry Andric using namespace llvm;
2189cb50c9SDimitry Andric using namespace llvm::codeview;
2289cb50c9SDimitry Andric 
DebugStringTableSubsectionRef()2389cb50c9SDimitry Andric DebugStringTableSubsectionRef::DebugStringTableSubsectionRef()
2489cb50c9SDimitry Andric     : DebugSubsectionRef(DebugSubsectionKind::StringTable) {}
2589cb50c9SDimitry Andric 
initialize(BinaryStreamRef Contents)2689cb50c9SDimitry Andric Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) {
2789cb50c9SDimitry Andric   Stream = Contents;
2889cb50c9SDimitry Andric   return Error::success();
2989cb50c9SDimitry Andric }
30a580b014SDimitry Andric 
initialize(BinaryStreamReader & Reader)31db17bf38SDimitry Andric Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
32db17bf38SDimitry Andric   return Reader.readStreamRef(Stream);
33db17bf38SDimitry Andric }
3489cb50c9SDimitry Andric 
3589cb50c9SDimitry Andric Expected<StringRef>
getString(uint32_t Offset) const3689cb50c9SDimitry Andric DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
3789cb50c9SDimitry Andric   BinaryStreamReader Reader(Stream);
3889cb50c9SDimitry Andric   Reader.setOffset(Offset);
3989cb50c9SDimitry Andric   StringRef Result;
4089cb50c9SDimitry Andric   if (auto EC = Reader.readCString(Result))
4189cb50c9SDimitry Andric     return std::move(EC);
4289cb50c9SDimitry Andric   return Result;
4389cb50c9SDimitry Andric }
4489cb50c9SDimitry Andric 
DebugStringTableSubsection()4589cb50c9SDimitry Andric DebugStringTableSubsection::DebugStringTableSubsection()
4689cb50c9SDimitry Andric     : DebugSubsection(DebugSubsectionKind::StringTable) {}
4789cb50c9SDimitry Andric 
insert(StringRef S)4889cb50c9SDimitry Andric uint32_t DebugStringTableSubsection::insert(StringRef S) {
494ba319b5SDimitry Andric   auto P = StringToId.insert({S, StringSize});
5089cb50c9SDimitry Andric 
5189cb50c9SDimitry Andric   // If a given string didn't exist in the string table, we want to increment
524ba319b5SDimitry Andric   // the string table size and insert it into the reverse lookup.
534ba319b5SDimitry Andric   if (P.second) {
544ba319b5SDimitry Andric     IdToString.insert({P.first->getValue(), P.first->getKey()});
5589cb50c9SDimitry Andric     StringSize += S.size() + 1; // +1 for '\0'
564ba319b5SDimitry Andric   }
574ba319b5SDimitry Andric 
5889cb50c9SDimitry Andric   return P.first->second;
5989cb50c9SDimitry Andric }
6089cb50c9SDimitry Andric 
calculateSerializedSize() const6189cb50c9SDimitry Andric uint32_t DebugStringTableSubsection::calculateSerializedSize() const {
6289cb50c9SDimitry Andric   return StringSize;
6389cb50c9SDimitry Andric }
6489cb50c9SDimitry Andric 
commit(BinaryStreamWriter & Writer) const6589cb50c9SDimitry Andric Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
66db17bf38SDimitry Andric   uint32_t Begin = Writer.getOffset();
67db17bf38SDimitry Andric   uint32_t End = Begin + StringSize;
6889cb50c9SDimitry Andric 
6924d58133SDimitry Andric   // Write a null string at the beginning.
7024d58133SDimitry Andric   if (auto EC = Writer.writeCString(StringRef()))
7124d58133SDimitry Andric     return EC;
7224d58133SDimitry Andric 
734ba319b5SDimitry Andric   for (auto &Pair : StringToId) {
7489cb50c9SDimitry Andric     StringRef S = Pair.getKey();
75db17bf38SDimitry Andric     uint32_t Offset = Begin + Pair.getValue();
7689cb50c9SDimitry Andric     Writer.setOffset(Offset);
7789cb50c9SDimitry Andric     if (auto EC = Writer.writeCString(S))
7889cb50c9SDimitry Andric       return EC;
79db17bf38SDimitry Andric     assert(Writer.getOffset() <= End);
8089cb50c9SDimitry Andric   }
8189cb50c9SDimitry Andric 
82db17bf38SDimitry Andric   Writer.setOffset(End);
8324d58133SDimitry Andric   assert((End - Begin) == StringSize);
8489cb50c9SDimitry Andric   return Error::success();
8589cb50c9SDimitry Andric }
8689cb50c9SDimitry Andric 
size() const874ba319b5SDimitry Andric uint32_t DebugStringTableSubsection::size() const { return StringToId.size(); }
8889cb50c9SDimitry Andric 
sortedIds() const894ba319b5SDimitry Andric std::vector<uint32_t> DebugStringTableSubsection::sortedIds() const {
904ba319b5SDimitry Andric   std::vector<uint32_t> Result;
914ba319b5SDimitry Andric   Result.reserve(IdToString.size());
924ba319b5SDimitry Andric   for (const auto &Entry : IdToString)
934ba319b5SDimitry Andric     Result.push_back(Entry.first);
94*b5893f02SDimitry Andric   llvm::sort(Result);
954ba319b5SDimitry Andric   return Result;
964ba319b5SDimitry Andric }
974ba319b5SDimitry Andric 
getIdForString(StringRef S) const984ba319b5SDimitry Andric uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const {
994ba319b5SDimitry Andric   auto Iter = StringToId.find(S);
1004ba319b5SDimitry Andric   assert(Iter != StringToId.end());
1014ba319b5SDimitry Andric   return Iter->second;
1024ba319b5SDimitry Andric }
1034ba319b5SDimitry Andric 
getStringForId(uint32_t Id) const1044ba319b5SDimitry Andric StringRef DebugStringTableSubsection::getStringForId(uint32_t Id) const {
1054ba319b5SDimitry Andric   auto Iter = IdToString.find(Id);
1064ba319b5SDimitry Andric   assert(Iter != IdToString.end());
1076d97bb29SDimitry Andric   return Iter->second;
10889cb50c9SDimitry Andric }
109