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 
2389cb50c9SDimitry Andric DebugStringTableSubsectionRef::DebugStringTableSubsectionRef()
2489cb50c9SDimitry Andric     : DebugSubsectionRef(DebugSubsectionKind::StringTable) {}
2589cb50c9SDimitry Andric 
2689cb50c9SDimitry Andric Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) {
2789cb50c9SDimitry Andric   Stream = Contents;
2889cb50c9SDimitry Andric   return Error::success();
2989cb50c9SDimitry Andric }
30a580b014SDimitry Andric 
31db17bf38SDimitry Andric Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
32db17bf38SDimitry Andric   return Reader.readStreamRef(Stream);
33db17bf38SDimitry Andric }
3489cb50c9SDimitry Andric 
3589cb50c9SDimitry Andric Expected<StringRef>
3689cb50c9SDimitry 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 
4589cb50c9SDimitry Andric DebugStringTableSubsection::DebugStringTableSubsection()
4689cb50c9SDimitry Andric     : DebugSubsection(DebugSubsectionKind::StringTable) {}
4789cb50c9SDimitry Andric 
4889cb50c9SDimitry Andric uint32_t DebugStringTableSubsection::insert(StringRef S) {
4989cb50c9SDimitry Andric   auto P = Strings.insert({S, StringSize});
5089cb50c9SDimitry Andric 
5189cb50c9SDimitry Andric   // If a given string didn't exist in the string table, we want to increment
5289cb50c9SDimitry Andric   // the string table size.
5389cb50c9SDimitry Andric   if (P.second)
5489cb50c9SDimitry Andric     StringSize += S.size() + 1; // +1 for '\0'
5589cb50c9SDimitry Andric   return P.first->second;
5689cb50c9SDimitry Andric }
5789cb50c9SDimitry Andric 
5889cb50c9SDimitry Andric uint32_t DebugStringTableSubsection::calculateSerializedSize() const {
5989cb50c9SDimitry Andric   return StringSize;
6089cb50c9SDimitry Andric }
6189cb50c9SDimitry Andric 
6289cb50c9SDimitry Andric Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
63db17bf38SDimitry Andric   uint32_t Begin = Writer.getOffset();
64db17bf38SDimitry Andric   uint32_t End = Begin + StringSize;
6589cb50c9SDimitry Andric 
6624d58133SDimitry Andric   // Write a null string at the beginning.
6724d58133SDimitry Andric   if (auto EC = Writer.writeCString(StringRef()))
6824d58133SDimitry Andric     return EC;
6924d58133SDimitry Andric 
7089cb50c9SDimitry Andric   for (auto &Pair : Strings) {
7189cb50c9SDimitry Andric     StringRef S = Pair.getKey();
72db17bf38SDimitry Andric     uint32_t Offset = Begin + Pair.getValue();
7389cb50c9SDimitry Andric     Writer.setOffset(Offset);
7489cb50c9SDimitry Andric     if (auto EC = Writer.writeCString(S))
7589cb50c9SDimitry Andric       return EC;
76db17bf38SDimitry Andric     assert(Writer.getOffset() <= End);
7789cb50c9SDimitry Andric   }
7889cb50c9SDimitry Andric 
79db17bf38SDimitry Andric   Writer.setOffset(End);
8024d58133SDimitry Andric   assert((End - Begin) == StringSize);
8189cb50c9SDimitry Andric   return Error::success();
8289cb50c9SDimitry Andric }
8389cb50c9SDimitry Andric 
8489cb50c9SDimitry Andric uint32_t DebugStringTableSubsection::size() const { return Strings.size(); }
8589cb50c9SDimitry Andric 
8689cb50c9SDimitry Andric uint32_t DebugStringTableSubsection::getStringId(StringRef S) const {
876d97bb29SDimitry Andric   auto Iter = Strings.find(S);
886d97bb29SDimitry Andric   assert(Iter != Strings.end());
896d97bb29SDimitry Andric   return Iter->second;
9089cb50c9SDimitry Andric }
91