aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/lib/DebugInfo/PDB/Native
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/lib/DebugInfo/PDB/Native
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/lib/DebugInfo/PDB/Native')
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp86
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp218
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleList.cpp279
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStream.cpp383
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp454
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/EnumTables.cpp37
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp494
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GlobalsStream.cpp181
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/Hash.cpp84
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/HashTable.cpp71
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStream.cpp131
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp82
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp65
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp144
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp126
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp60
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp54
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp121
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp42
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp43
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp41
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp70
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp101
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp143
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp177
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp51
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp48
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp734
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSession.cpp463
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp47
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp124
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp66
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp46
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp381
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp199
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp193
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp29
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp220
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp35
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFile.cpp508
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp355
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTable.cpp140
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp229
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PublicsStream.cpp101
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/RawError.cpp53
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolCache.cpp633
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolStream.cpp45
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiHashing.cpp129
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStream.cpp246
-rw-r--r--contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp214
50 files changed, 8976 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
new file mode 100644
index 0000000000..9755f2ca3b
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp
@@ -0,0 +1,86 @@
+//===- DbiModuleDescriptor.cpp - PDB module information -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+Error DbiModuleDescriptor::initialize(BinaryStreamRef Stream,
+ DbiModuleDescriptor &Info) {
+ BinaryStreamReader Reader(Stream);
+ if (auto EC = Reader.readObject(Info.Layout))
+ return EC;
+
+ if (auto EC = Reader.readCString(Info.ModuleName))
+ return EC;
+
+ if (auto EC = Reader.readCString(Info.ObjFileName))
+ return EC;
+ return Error::success();
+}
+
+bool DbiModuleDescriptor::hasECInfo() const {
+ return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0;
+}
+
+uint16_t DbiModuleDescriptor::getTypeServerIndex() const {
+ return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >>
+ ModInfoFlags::TypeServerIndexShift;
+}
+
+const SectionContrib &DbiModuleDescriptor::getSectionContrib() const {
+ return Layout->SC;
+}
+
+uint16_t DbiModuleDescriptor::getModuleStreamIndex() const {
+ return Layout->ModDiStream;
+}
+
+uint32_t DbiModuleDescriptor::getSymbolDebugInfoByteSize() const {
+ return Layout->SymBytes;
+}
+
+uint32_t DbiModuleDescriptor::getC11LineInfoByteSize() const {
+ return Layout->C11Bytes;
+}
+
+uint32_t DbiModuleDescriptor::getC13LineInfoByteSize() const {
+ return Layout->C13Bytes;
+}
+
+uint32_t DbiModuleDescriptor::getNumberOfFiles() const {
+ return Layout->NumFiles;
+}
+
+uint32_t DbiModuleDescriptor::getSourceFileNameIndex() const {
+ return Layout->SrcFileNameNI;
+}
+
+uint32_t DbiModuleDescriptor::getPdbFilePathNameIndex() const {
+ return Layout->PdbFilePathNI;
+}
+
+StringRef DbiModuleDescriptor::getModuleName() const { return ModuleName; }
+
+StringRef DbiModuleDescriptor::getObjFileName() const { return ObjFileName; }
+
+uint32_t DbiModuleDescriptor::getRecordLength() const {
+ uint32_t M = ModuleName.str().size() + 1;
+ uint32_t O = ObjFileName.str().size() + 1;
+ uint32_t Size = sizeof(ModuleInfoHeader) + M + O;
+ Size = alignTo(Size, 4);
+ return Size;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
new file mode 100644
index 0000000000..b6f11a942a
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -0,0 +1,218 @@
+//===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info Creation ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
+ uint32_t C13Size) {
+ uint32_t Size = sizeof(uint32_t); // Signature
+ Size += alignTo(SymbolByteSize, 4); // Symbol Data
+ Size += 0; // TODO: Layout.C11Bytes
+ Size += C13Size; // C13 Debug Info Size
+ Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
+ Size += 0; // GlobalRefs substream bytes
+ return Size;
+}
+
+DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
+ uint32_t ModIndex,
+ msf::MSFBuilder &Msf)
+ : MSF(Msf), ModuleName(std::string(ModuleName)) {
+ ::memset(&Layout, 0, sizeof(Layout));
+ Layout.Mod = ModIndex;
+}
+
+DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
+
+uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
+ return Layout.ModDiStream;
+}
+
+void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) {
+ ObjFileName = std::string(Name);
+}
+
+void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) {
+ PdbFilePathNI = NI;
+}
+
+void DbiModuleDescriptorBuilder::setFirstSectionContrib(
+ const SectionContrib &SC) {
+ Layout.SC = SC;
+}
+
+void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
+ // Defer to the bulk API. It does the same thing.
+ addSymbolsInBulk(Symbol.data());
+}
+
+void DbiModuleDescriptorBuilder::addSymbolsInBulk(
+ ArrayRef<uint8_t> BulkSymbols) {
+ // Do nothing for empty runs of symbols.
+ if (BulkSymbols.empty())
+ return;
+
+ Symbols.push_back(SymbolListWrapper(BulkSymbols));
+ // Symbols written to a PDB file are required to be 4 byte aligned. The same
+ // is not true of object files.
+ assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 &&
+ "Invalid Symbol alignment!");
+ SymbolByteSize += BulkSymbols.size();
+}
+
+void DbiModuleDescriptorBuilder::addUnmergedSymbols(void *SymSrc,
+ uint32_t SymLength) {
+ assert(SymLength > 0);
+ Symbols.push_back(SymbolListWrapper(SymSrc, SymLength));
+
+ // Symbols written to a PDB file are required to be 4 byte aligned. The same
+ // is not true of object files.
+ assert(SymLength % alignOf(CodeViewContainer::Pdb) == 0 &&
+ "Invalid Symbol alignment!");
+ SymbolByteSize += SymLength;
+}
+
+void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
+ SourceFiles.push_back(std::string(Path));
+}
+
+uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
+ uint32_t Result = 0;
+ for (const auto &Builder : C13Builders) {
+ Result += Builder.calculateSerializedLength();
+ }
+ return Result;
+}
+
+uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
+ uint32_t L = sizeof(Layout);
+ uint32_t M = ModuleName.size() + 1;
+ uint32_t O = ObjFileName.size() + 1;
+ return alignTo(L + M + O, sizeof(uint32_t));
+}
+
+void DbiModuleDescriptorBuilder::finalize() {
+ Layout.FileNameOffs = 0; // TODO: Fix this
+ Layout.Flags = 0; // TODO: Fix this
+ Layout.C11Bytes = 0;
+ Layout.C13Bytes = calculateC13DebugInfoSize();
+ (void)Layout.Mod; // Set in constructor
+ (void)Layout.ModDiStream; // Set in finalizeMsfLayout
+ Layout.NumFiles = SourceFiles.size();
+ Layout.PdbFilePathNI = PdbFilePathNI;
+ Layout.SrcFileNameNI = 0;
+
+ // This value includes both the signature field as well as the record bytes
+ // from the symbol stream.
+ Layout.SymBytes =
+ Layout.ModDiStream == kInvalidStreamIndex ? 0 : getNextSymbolOffset();
+}
+
+Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
+ this->Layout.ModDiStream = kInvalidStreamIndex;
+ uint32_t C13Size = calculateC13DebugInfoSize();
+ if (!C13Size && !SymbolByteSize)
+ return Error::success();
+ auto ExpectedSN =
+ MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
+ if (!ExpectedSN)
+ return ExpectedSN.takeError();
+ Layout.ModDiStream = *ExpectedSN;
+ return Error::success();
+}
+
+Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter) {
+ // We write the Modi record to the `ModiWriter`, but we additionally write its
+ // symbol stream to a brand new stream.
+ if (auto EC = ModiWriter.writeObject(Layout))
+ return EC;
+ if (auto EC = ModiWriter.writeCString(ModuleName))
+ return EC;
+ if (auto EC = ModiWriter.writeCString(ObjFileName))
+ return EC;
+ if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
+ return EC;
+ return Error::success();
+}
+
+Error DbiModuleDescriptorBuilder::commitSymbolStream(
+ const msf::MSFLayout &MsfLayout, WritableBinaryStreamRef MsfBuffer) {
+ if (Layout.ModDiStream == kInvalidStreamIndex)
+ return Error::success();
+
+ auto NS = WritableMappedBlockStream::createIndexedStream(
+ MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
+ WritableBinaryStreamRef Ref(*NS);
+ BinaryStreamWriter SymbolWriter(Ref);
+ // Write the symbols.
+ if (auto EC = SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
+ return EC;
+ for (const SymbolListWrapper &Sym : Symbols) {
+ if (Sym.NeedsToBeMerged) {
+ assert(MergeSymsCallback);
+ if (auto EC = MergeSymsCallback(MergeSymsCtx, Sym.SymPtr, SymbolWriter))
+ return EC;
+ } else {
+ if (auto EC = SymbolWriter.writeBytes(Sym.asArray()))
+ return EC;
+ }
+ }
+
+ // Apply the string table fixups.
+ auto SavedOffset = SymbolWriter.getOffset();
+ for (const StringTableFixup &Fixup : StringTableFixups) {
+ SymbolWriter.setOffset(Fixup.SymOffsetOfReference);
+ if (auto E = SymbolWriter.writeInteger<uint32_t>(Fixup.StrTabOffset))
+ return E;
+ }
+ SymbolWriter.setOffset(SavedOffset);
+
+ assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
+ "Invalid debug section alignment!");
+ // TODO: Write C11 Line data
+ for (const auto &Builder : C13Builders) {
+ if (auto EC = Builder.commit(SymbolWriter, CodeViewContainer::Pdb))
+ return EC;
+ }
+
+ // TODO: Figure out what GlobalRefs substream actually is and populate it.
+ if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
+ return EC;
+ if (SymbolWriter.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::stream_too_long);
+
+ return Error::success();
+}
+
+void DbiModuleDescriptorBuilder::addDebugSubsection(
+ std::shared_ptr<DebugSubsection> Subsection) {
+ assert(Subsection);
+ C13Builders.push_back(DebugSubsectionRecordBuilder(std::move(Subsection)));
+}
+
+void DbiModuleDescriptorBuilder::addDebugSubsection(
+ const DebugSubsectionRecord &SubsectionContents) {
+ C13Builders.push_back(DebugSubsectionRecordBuilder(SubsectionContents));
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleList.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleList.cpp
new file mode 100644
index 0000000000..5cf014e881
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiModuleList.cpp
@@ -0,0 +1,279 @@
+//===- DbiModuleList.cpp - PDB module information list --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+DbiModuleSourceFilesIterator::DbiModuleSourceFilesIterator(
+ const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei)
+ : Modules(&Modules), Modi(Modi), Filei(Filei) {
+ setValue();
+}
+
+bool DbiModuleSourceFilesIterator::
+operator==(const DbiModuleSourceFilesIterator &R) const {
+ // incompatible iterators are never equal
+ if (!isCompatible(R))
+ return false;
+
+ // If they're compatible, and they're both ends, then they're equal.
+ if (isEnd() && R.isEnd())
+ return true;
+
+ // If one is an end and the other is not, they're not equal.
+ if (isEnd() != R.isEnd())
+ return false;
+
+ // Now we know:
+ // - They're compatible
+ // - They're not *both* end iterators
+ // - Their endness is the same.
+ // Thus, they're compatible iterators pointing to a valid file on the same
+ // module. All we need to check are the file indices.
+ assert(Modules == R.Modules);
+ assert(Modi == R.Modi);
+ assert(!isEnd());
+ assert(!R.isEnd());
+
+ return (Filei == R.Filei);
+}
+
+bool DbiModuleSourceFilesIterator::
+operator<(const DbiModuleSourceFilesIterator &R) const {
+ assert(isCompatible(R));
+
+ // It's not sufficient to compare the file indices, because default
+ // constructed iterators could be equal to iterators with valid indices. To
+ // account for this, early-out if they're equal.
+ if (*this == R)
+ return false;
+
+ return Filei < R.Filei;
+}
+
+std::ptrdiff_t DbiModuleSourceFilesIterator::
+operator-(const DbiModuleSourceFilesIterator &R) const {
+ assert(isCompatible(R));
+ assert(!(*this < R));
+
+ // If they're both end iterators, the distance is 0.
+ if (isEnd() && R.isEnd())
+ return 0;
+
+ assert(!R.isEnd());
+
+ // At this point, R cannot be end, but *this can, which means that *this
+ // might be a universal end iterator with none of its fields set. So in that
+ // case have to rely on R as the authority to figure out how many files there
+ // are to compute the distance.
+ uint32_t Thisi = Filei;
+ if (isEnd()) {
+ uint32_t RealModi = R.Modi;
+ Thisi = R.Modules->getSourceFileCount(RealModi);
+ }
+
+ assert(Thisi >= R.Filei);
+ return Thisi - R.Filei;
+}
+
+DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
+operator+=(std::ptrdiff_t N) {
+ assert(!isEnd());
+
+ Filei += N;
+ assert(Filei <= Modules->getSourceFileCount(Modi));
+ setValue();
+ return *this;
+}
+
+DbiModuleSourceFilesIterator &DbiModuleSourceFilesIterator::
+operator-=(std::ptrdiff_t N) {
+ // Note that we can subtract from an end iterator, but not a universal end
+ // iterator.
+ assert(!isUniversalEnd());
+
+ assert(N <= Filei);
+
+ Filei -= N;
+ return *this;
+}
+
+void DbiModuleSourceFilesIterator::setValue() {
+ if (isEnd()) {
+ ThisValue = "";
+ return;
+ }
+
+ uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei;
+ auto ExpectedValue = Modules->getFileName(Off);
+ if (!ExpectedValue) {
+ consumeError(ExpectedValue.takeError());
+ Filei = Modules->getSourceFileCount(Modi);
+ } else
+ ThisValue = *ExpectedValue;
+}
+
+bool DbiModuleSourceFilesIterator::isEnd() const {
+ if (isUniversalEnd())
+ return true;
+
+ assert(Modules);
+ assert(Modi <= Modules->getModuleCount());
+ assert(Filei <= Modules->getSourceFileCount(Modi));
+
+ if (Modi == Modules->getModuleCount())
+ return true;
+ if (Filei == Modules->getSourceFileCount(Modi))
+ return true;
+ return false;
+}
+
+bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; }
+
+bool DbiModuleSourceFilesIterator::isCompatible(
+ const DbiModuleSourceFilesIterator &R) const {
+ // Universal iterators are compatible with any other iterator.
+ if (isUniversalEnd() || R.isUniversalEnd())
+ return true;
+
+ // At this point, neither iterator is a universal end iterator, although one
+ // or both might be non-universal end iterators. Regardless, the module index
+ // is valid, so they are compatible if and only if they refer to the same
+ // module.
+ return Modi == R.Modi;
+}
+
+Error DbiModuleList::initialize(BinaryStreamRef ModInfo,
+ BinaryStreamRef FileInfo) {
+ if (auto EC = initializeModInfo(ModInfo))
+ return EC;
+ if (auto EC = initializeFileInfo(FileInfo))
+ return EC;
+
+ return Error::success();
+}
+
+Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) {
+ ModInfoSubstream = ModInfo;
+
+ if (ModInfo.getLength() == 0)
+ return Error::success();
+
+ BinaryStreamReader Reader(ModInfo);
+
+ if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength()))
+ return EC;
+
+ return Error::success();
+}
+
+Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) {
+ FileInfoSubstream = FileInfo;
+
+ if (FileInfo.getLength() == 0)
+ return Error::success();
+
+ BinaryStreamReader FISR(FileInfo);
+ if (auto EC = FISR.readObject(FileInfoHeader))
+ return EC;
+
+ // First is an array of `NumModules` module indices. This does not seem to be
+ // used for anything meaningful, so we ignore it.
+ FixedStreamArray<support::ulittle16_t> ModuleIndices;
+ if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules))
+ return EC;
+ if (auto EC = FISR.readArray(ModFileCountArray, FileInfoHeader->NumModules))
+ return EC;
+
+ // Compute the real number of source files. We can't trust the value in
+ // `FileInfoHeader->NumSourceFiles` because it is a unit16, and the sum of all
+ // source file counts might be larger than a unit16. So we compute the real
+ // count by summing up the individual counts.
+ uint32_t NumSourceFiles = 0;
+ for (auto Count : ModFileCountArray)
+ NumSourceFiles += Count;
+
+ // In the reference implementation, this array is where the pointer documented
+ // at the definition of ModuleInfoHeader::FileNameOffs points to. Note that
+ // although the field in ModuleInfoHeader is ignored this array is not, as it
+ // is the authority on where each filename begins in the names buffer.
+ if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
+ return EC;
+
+ if (auto EC = FISR.readStreamRef(NamesBuffer))
+ return EC;
+
+ auto DescriptorIter = Descriptors.begin();
+ uint32_t NextFileIndex = 0;
+ ModuleInitialFileIndex.resize(FileInfoHeader->NumModules);
+ ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules);
+ for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) {
+ assert(DescriptorIter != Descriptors.end());
+ ModuleInitialFileIndex[I] = NextFileIndex;
+ ModuleDescriptorOffsets[I] = DescriptorIter.offset();
+
+ NextFileIndex += ModFileCountArray[I];
+ ++DescriptorIter;
+ }
+
+ assert(DescriptorIter == Descriptors.end());
+ assert(NextFileIndex == NumSourceFiles);
+
+ return Error::success();
+}
+
+uint32_t DbiModuleList::getModuleCount() const {
+ return FileInfoHeader->NumModules;
+}
+
+uint32_t DbiModuleList::getSourceFileCount() const {
+ return FileNameOffsets.size();
+}
+
+uint16_t DbiModuleList::getSourceFileCount(uint32_t Modi) const {
+ return ModFileCountArray[Modi];
+}
+
+DbiModuleDescriptor DbiModuleList::getModuleDescriptor(uint32_t Modi) const {
+ assert(Modi < getModuleCount());
+ uint32_t Offset = ModuleDescriptorOffsets[Modi];
+ auto Iter = Descriptors.at(Offset);
+ assert(Iter != Descriptors.end());
+ return *Iter;
+}
+
+iterator_range<DbiModuleSourceFilesIterator>
+DbiModuleList::source_files(uint32_t Modi) const {
+ return make_range<DbiModuleSourceFilesIterator>(
+ DbiModuleSourceFilesIterator(*this, Modi, 0),
+ DbiModuleSourceFilesIterator());
+}
+
+Expected<StringRef> DbiModuleList::getFileName(uint32_t Index) const {
+ BinaryStreamReader Names(NamesBuffer);
+ if (Index >= getSourceFileCount())
+ return make_error<RawError>(raw_error_code::index_out_of_bounds);
+
+ uint32_t FileOffset = FileNameOffsets[Index];
+ Names.setOffset(FileOffset);
+ StringRef Name;
+ if (auto EC = Names.readCString(Name))
+ return std::move(EC);
+ return Name;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStream.cpp
new file mode 100644
index 0000000000..4eb1680417
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStream.cpp
@@ -0,0 +1,383 @@
+//===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+template <typename ContribType>
+static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
+ BinaryStreamReader &Reader) {
+ if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
+ return make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "Invalid number of bytes of section contributions");
+
+ uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
+ if (auto EC = Reader.readArray(Output, Count))
+ return EC;
+ return Error::success();
+}
+
+DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
+ : Stream(std::move(Stream)), Header(nullptr) {}
+
+DbiStream::~DbiStream() = default;
+
+Error DbiStream::reload(PDBFile *Pdb) {
+ BinaryStreamReader Reader(*Stream);
+
+ if (Stream->getLength() < sizeof(DbiStreamHeader))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI Stream does not contain a header.");
+ if (auto EC = Reader.readObject(Header))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI Stream does not contain a header.");
+
+ if (Header->VersionSignature != -1)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid DBI version signature.");
+
+ // Require at least version 7, which should be present in all PDBs
+ // produced in the last decade and allows us to avoid having to
+ // special case all kinds of complicated arcane formats.
+ if (Header->VersionHeader < PdbDbiV70)
+ return make_error<RawError>(raw_error_code::feature_unsupported,
+ "Unsupported DBI version.");
+
+ if (Stream->getLength() !=
+ sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
+ Header->SecContrSubstreamSize + Header->SectionMapSize +
+ Header->FileInfoSize + Header->TypeServerSize +
+ Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI Length does not equal sum of substreams.");
+
+ // Only certain substreams are guaranteed to be aligned. Validate
+ // them here.
+ if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI MODI substream not aligned.");
+ if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
+ return make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "DBI section contribution substream not aligned.");
+ if (Header->SectionMapSize % sizeof(uint32_t) != 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI section map substream not aligned.");
+ if (Header->FileInfoSize % sizeof(uint32_t) != 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI file info substream not aligned.");
+ if (Header->TypeServerSize % sizeof(uint32_t) != 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "DBI type server substream not aligned.");
+
+ if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
+ return EC;
+
+ if (auto EC = Reader.readSubstream(SecContrSubstream,
+ Header->SecContrSubstreamSize))
+ return EC;
+ if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
+ return EC;
+ if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
+ return EC;
+ if (auto EC =
+ Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
+ return EC;
+ if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
+ return EC;
+ if (auto EC = Reader.readArray(
+ DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
+ return EC;
+
+ if (auto EC = Modules.initialize(ModiSubstream.StreamData,
+ FileInfoSubstream.StreamData))
+ return EC;
+
+ if (auto EC = initializeSectionContributionData())
+ return EC;
+ if (auto EC = initializeSectionHeadersData(Pdb))
+ return EC;
+ if (auto EC = initializeSectionMapData())
+ return EC;
+ if (auto EC = initializeOldFpoRecords(Pdb))
+ return EC;
+ if (auto EC = initializeNewFpoRecords(Pdb))
+ return EC;
+
+ if (Reader.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Found unexpected bytes in DBI Stream.");
+
+ if (!ECSubstream.empty()) {
+ BinaryStreamReader ECReader(ECSubstream.StreamData);
+ if (auto EC = ECNames.reload(ECReader))
+ return EC;
+ }
+
+ return Error::success();
+}
+
+PdbRaw_DbiVer DbiStream::getDbiVersion() const {
+ uint32_t Value = Header->VersionHeader;
+ return static_cast<PdbRaw_DbiVer>(Value);
+}
+
+uint32_t DbiStream::getAge() const { return Header->Age; }
+
+uint16_t DbiStream::getPublicSymbolStreamIndex() const {
+ return Header->PublicSymbolStreamIndex;
+}
+
+uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
+ return Header->GlobalSymbolStreamIndex;
+}
+
+uint16_t DbiStream::getFlags() const { return Header->Flags; }
+
+bool DbiStream::isIncrementallyLinked() const {
+ return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
+}
+
+bool DbiStream::hasCTypes() const {
+ return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
+}
+
+bool DbiStream::isStripped() const {
+ return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
+}
+
+uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
+
+uint16_t DbiStream::getBuildMajorVersion() const {
+ return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
+ DbiBuildNo::BuildMajorShift;
+}
+
+uint16_t DbiStream::getBuildMinorVersion() const {
+ return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
+ DbiBuildNo::BuildMinorShift;
+}
+
+uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
+
+uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
+
+uint32_t DbiStream::getSymRecordStreamIndex() const {
+ return Header->SymRecordStreamIndex;
+}
+
+PDB_Machine DbiStream::getMachineType() const {
+ uint16_t Machine = Header->MachineType;
+ return static_cast<PDB_Machine>(Machine);
+}
+
+FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
+ return SectionHeaders;
+}
+
+bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }
+
+FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {
+ return OldFpoRecords;
+}
+
+bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }
+
+const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {
+ return NewFpoRecords;
+}
+
+const DbiModuleList &DbiStream::modules() const { return Modules; }
+
+FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
+ return SectionMap;
+}
+
+void DbiStream::visitSectionContributions(
+ ISectionContribVisitor &Visitor) const {
+ if (!SectionContribs.empty()) {
+ assert(SectionContribVersion == DbiSecContribVer60);
+ for (auto &SC : SectionContribs)
+ Visitor.visit(SC);
+ } else if (!SectionContribs2.empty()) {
+ assert(SectionContribVersion == DbiSecContribV2);
+ for (auto &SC : SectionContribs2)
+ Visitor.visit(SC);
+ }
+}
+
+Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
+ return ECNames.getStringForID(NI);
+}
+
+Error DbiStream::initializeSectionContributionData() {
+ if (SecContrSubstream.empty())
+ return Error::success();
+
+ BinaryStreamReader SCReader(SecContrSubstream.StreamData);
+ if (auto EC = SCReader.readEnum(SectionContribVersion))
+ return EC;
+
+ if (SectionContribVersion == DbiSecContribVer60)
+ return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
+ if (SectionContribVersion == DbiSecContribV2)
+ return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
+
+ return make_error<RawError>(raw_error_code::feature_unsupported,
+ "Unsupported DBI Section Contribution version");
+}
+
+// Initializes this->SectionHeaders.
+Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
+ Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
+ createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);
+ if (auto EC = ExpectedStream.takeError())
+ return EC;
+
+ auto &SHS = *ExpectedStream;
+ if (!SHS)
+ return Error::success();
+
+ size_t StreamLen = SHS->getLength();
+ if (StreamLen % sizeof(object::coff_section))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Corrupted section header stream.");
+
+ size_t NumSections = StreamLen / sizeof(object::coff_section);
+ BinaryStreamReader Reader(*SHS);
+ if (auto EC = Reader.readArray(SectionHeaders, NumSections))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a bitmap.");
+
+ SectionHeaderStream = std::move(SHS);
+ return Error::success();
+}
+
+// Initializes this->Fpos.
+Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {
+ Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
+ createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);
+ if (auto EC = ExpectedStream.takeError())
+ return EC;
+
+ auto &FS = *ExpectedStream;
+ if (!FS)
+ return Error::success();
+
+ size_t StreamLen = FS->getLength();
+ if (StreamLen % sizeof(object::FpoData))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Corrupted Old FPO stream.");
+
+ size_t NumRecords = StreamLen / sizeof(object::FpoData);
+ BinaryStreamReader Reader(*FS);
+ if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Corrupted Old FPO stream.");
+ OldFpoStream = std::move(FS);
+ return Error::success();
+}
+
+Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {
+ Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
+ createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);
+ if (auto EC = ExpectedStream.takeError())
+ return EC;
+
+ auto &FS = *ExpectedStream;
+ if (!FS)
+ return Error::success();
+
+ if (auto EC = NewFpoRecords.initialize(*FS))
+ return EC;
+
+ NewFpoStream = std::move(FS);
+ return Error::success();
+}
+
+Expected<std::unique_ptr<msf::MappedBlockStream>>
+DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,
+ DbgHeaderType Type) const {
+ if (!Pdb)
+ return nullptr;
+
+ if (DbgStreams.empty())
+ return nullptr;
+
+ uint32_t StreamNum = getDebugStreamIndex(Type);
+
+ // This means there is no such stream.
+ if (StreamNum == kInvalidStreamIndex)
+ return nullptr;
+
+ return Pdb->safelyCreateIndexedStream(StreamNum);
+}
+
+BinarySubstreamRef DbiStream::getSectionContributionData() const {
+ return SecContrSubstream;
+}
+
+BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
+ return SecMapSubstream;
+}
+
+BinarySubstreamRef DbiStream::getModiSubstreamData() const {
+ return ModiSubstream;
+}
+
+BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
+ return FileInfoSubstream;
+}
+
+BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
+ return TypeServerMapSubstream;
+}
+
+BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
+
+Error DbiStream::initializeSectionMapData() {
+ if (SecMapSubstream.empty())
+ return Error::success();
+
+ BinaryStreamReader SMReader(SecMapSubstream.StreamData);
+ const SecMapHeader *Header;
+ if (auto EC = SMReader.readObject(Header))
+ return EC;
+ if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
+ return EC;
+ return Error::success();
+}
+
+uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
+ uint16_t T = static_cast<uint16_t>(Type);
+ if (T >= DbgStreams.size())
+ return kInvalidStreamIndex;
+ return DbgStreams[T];
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
new file mode 100644
index 0000000000..0584966a98
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -0,0 +1,454 @@
+//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Parallel.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf)
+ : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0),
+ PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86),
+ Header(nullptr) {}
+
+DbiStreamBuilder::~DbiStreamBuilder() {}
+
+void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
+
+void DbiStreamBuilder::setAge(uint32_t A) { Age = A; }
+
+void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; }
+
+void DbiStreamBuilder::setBuildNumber(uint8_t Major, uint8_t Minor) {
+ BuildNumber = (uint16_t(Major) << DbiBuildNo::BuildMajorShift) &
+ DbiBuildNo::BuildMajorMask;
+ BuildNumber |= (uint16_t(Minor) << DbiBuildNo::BuildMinorShift) &
+ DbiBuildNo::BuildMinorMask;
+ BuildNumber |= DbiBuildNo::NewVersionFormatMask;
+}
+
+void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; }
+
+void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; }
+
+void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
+
+void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
+
+void DbiStreamBuilder::setMachineType(COFF::MachineTypes M) {
+ // These enums are mirrors of each other, so we can just cast the value.
+ MachineType = static_cast<pdb::PDB_Machine>(static_cast<unsigned>(M));
+}
+
+void DbiStreamBuilder::setGlobalsStreamIndex(uint32_t Index) {
+ GlobalsStreamIndex = Index;
+}
+
+void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) {
+ SymRecordStreamIndex = Index;
+}
+
+void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
+ PublicsStreamIndex = Index;
+}
+
+void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) {
+ if (!NewFpoData.hasValue())
+ NewFpoData.emplace(false);
+
+ NewFpoData->addFrameData(FD);
+}
+
+void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) {
+ OldFpoData.push_back(FD);
+}
+
+Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
+ ArrayRef<uint8_t> Data) {
+ assert(Type != DbgHeaderType::NewFPO &&
+ "NewFPO data should be written via addFrameData()!");
+
+ DbgStreams[(int)Type].emplace();
+ DbgStreams[(int)Type]->Size = Data.size();
+ DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
+ return Writer.writeArray(Data);
+ };
+ return Error::success();
+}
+
+uint32_t DbiStreamBuilder::addECName(StringRef Name) {
+ return ECNamesBuilder.insert(Name);
+}
+
+uint32_t DbiStreamBuilder::calculateSerializedLength() const {
+ // For now we only support serializing the header.
+ return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() +
+ calculateModiSubstreamSize() + calculateSectionContribsStreamSize() +
+ calculateSectionMapStreamSize() + calculateDbgStreamsSize() +
+ ECNamesBuilder.calculateSerializedSize();
+}
+
+Expected<DbiModuleDescriptorBuilder &>
+DbiStreamBuilder::addModuleInfo(StringRef ModuleName) {
+ uint32_t Index = ModiList.size();
+ ModiList.push_back(
+ std::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf));
+ return *ModiList.back();
+}
+
+Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module,
+ StringRef File) {
+ uint32_t Index = SourceFileNames.size();
+ SourceFileNames.insert(std::make_pair(File, Index));
+ Module.addSourceFile(File);
+ return Error::success();
+}
+
+Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
+ auto NameIter = SourceFileNames.find(File);
+ if (NameIter == SourceFileNames.end())
+ return make_error<RawError>(raw_error_code::no_entry,
+ "The specified source file was not found");
+ return NameIter->getValue();
+}
+
+uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
+ uint32_t Size = 0;
+ for (const auto &M : ModiList)
+ Size += M->calculateSerializedLength();
+ return Size;
+}
+
+uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const {
+ if (SectionContribs.empty())
+ return 0;
+ return sizeof(enum PdbRaw_DbiSecContribVer) +
+ sizeof(SectionContribs[0]) * SectionContribs.size();
+}
+
+uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const {
+ if (SectionMap.empty())
+ return 0;
+ return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size();
+}
+
+uint32_t DbiStreamBuilder::calculateNamesOffset() const {
+ uint32_t Offset = 0;
+ Offset += sizeof(ulittle16_t); // NumModules
+ Offset += sizeof(ulittle16_t); // NumSourceFiles
+ Offset += ModiList.size() * sizeof(ulittle16_t); // ModIndices
+ Offset += ModiList.size() * sizeof(ulittle16_t); // ModFileCounts
+ uint32_t NumFileInfos = 0;
+ for (const auto &M : ModiList)
+ NumFileInfos += M->source_files().size();
+ Offset += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets
+ return Offset;
+}
+
+uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const {
+ uint32_t Size = calculateNamesOffset();
+ Size += calculateNamesBufferSize();
+ return alignTo(Size, sizeof(uint32_t));
+}
+
+uint32_t DbiStreamBuilder::calculateNamesBufferSize() const {
+ uint32_t Size = 0;
+ for (const auto &F : SourceFileNames) {
+ Size += F.getKeyLength() + 1; // Names[I];
+ }
+ return Size;
+}
+
+uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const {
+ return DbgStreams.size() * sizeof(uint16_t);
+}
+
+Error DbiStreamBuilder::generateFileInfoSubstream() {
+ uint32_t Size = calculateFileInfoSubstreamSize();
+ auto Data = Allocator.Allocate<uint8_t>(Size);
+ uint32_t NamesOffset = calculateNamesOffset();
+
+ FileInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size),
+ llvm::support::little);
+
+ WritableBinaryStreamRef MetadataBuffer =
+ WritableBinaryStreamRef(FileInfoBuffer).keep_front(NamesOffset);
+ BinaryStreamWriter MetadataWriter(MetadataBuffer);
+
+ uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModiList.size());
+ uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
+ if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules
+ return EC;
+ if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles
+ return EC;
+ for (uint16_t I = 0; I < ModiCount; ++I) {
+ if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices
+ return EC;
+ }
+ for (const auto &MI : ModiList) {
+ FileCount = static_cast<uint16_t>(MI->source_files().size());
+ if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts
+ return EC;
+ }
+
+ // Before writing the FileNameOffsets array, write the NamesBuffer array.
+ // A side effect of this is that this will actually compute the various
+ // file name offsets, so we can then go back and write the FileNameOffsets
+ // array to the other substream.
+ NamesBuffer = WritableBinaryStreamRef(FileInfoBuffer).drop_front(NamesOffset);
+ BinaryStreamWriter NameBufferWriter(NamesBuffer);
+ for (auto &Name : SourceFileNames) {
+ Name.second = NameBufferWriter.getOffset();
+ if (auto EC = NameBufferWriter.writeCString(Name.getKey()))
+ return EC;
+ }
+
+ for (const auto &MI : ModiList) {
+ for (StringRef Name : MI->source_files()) {
+ auto Result = SourceFileNames.find(Name);
+ if (Result == SourceFileNames.end())
+ return make_error<RawError>(raw_error_code::no_entry,
+ "The source file was not found.");
+ if (auto EC = MetadataWriter.writeInteger(Result->second))
+ return EC;
+ }
+ }
+
+ if (auto EC = NameBufferWriter.padToAlignment(sizeof(uint32_t)))
+ return EC;
+
+ if (NameBufferWriter.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "The names buffer contained unexpected data.");
+
+ if (MetadataWriter.bytesRemaining() > sizeof(uint32_t))
+ return make_error<RawError>(
+ raw_error_code::invalid_format,
+ "The metadata buffer contained unexpected data.");
+
+ return Error::success();
+}
+
+Error DbiStreamBuilder::finalize() {
+ if (Header)
+ return Error::success();
+
+ for (auto &MI : ModiList)
+ MI->finalize();
+
+ if (auto EC = generateFileInfoSubstream())
+ return EC;
+
+ DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>();
+ ::memset(H, 0, sizeof(DbiStreamHeader));
+ H->VersionHeader = *VerHeader;
+ H->VersionSignature = -1;
+ H->Age = Age;
+ H->BuildNumber = BuildNumber;
+ H->Flags = Flags;
+ H->PdbDllRbld = PdbDllRbld;
+ H->PdbDllVersion = PdbDllVersion;
+ H->MachineType = static_cast<uint16_t>(MachineType);
+
+ H->ECSubstreamSize = ECNamesBuilder.calculateSerializedSize();
+ H->FileInfoSize = FileInfoBuffer.getLength();
+ H->ModiSubstreamSize = calculateModiSubstreamSize();
+ H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t);
+ H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
+ H->SectionMapSize = calculateSectionMapStreamSize();
+ H->TypeServerSize = 0;
+ H->SymRecordStreamIndex = SymRecordStreamIndex;
+ H->PublicSymbolStreamIndex = PublicsStreamIndex;
+ H->MFCTypeServerIndex = 0; // Not sure what this is, but link.exe writes 0.
+ H->GlobalSymbolStreamIndex = GlobalsStreamIndex;
+
+ Header = H;
+ return Error::success();
+}
+
+Error DbiStreamBuilder::finalizeMsfLayout() {
+ if (NewFpoData.hasValue()) {
+ DbgStreams[(int)DbgHeaderType::NewFPO].emplace();
+ DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
+ NewFpoData->calculateSerializedSize();
+ DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
+ [this](BinaryStreamWriter &Writer) {
+ return NewFpoData->commit(Writer);
+ };
+ }
+
+ if (!OldFpoData.empty()) {
+ DbgStreams[(int)DbgHeaderType::FPO].emplace();
+ DbgStreams[(int)DbgHeaderType::FPO]->Size =
+ sizeof(object::FpoData) * OldFpoData.size();
+ DbgStreams[(int)DbgHeaderType::FPO]->WriteFn =
+ [this](BinaryStreamWriter &Writer) {
+ return Writer.writeArray(makeArrayRef(OldFpoData));
+ };
+ }
+
+ for (auto &S : DbgStreams) {
+ if (!S.hasValue())
+ continue;
+ auto ExpectedIndex = Msf.addStream(S->Size);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ S->StreamNumber = *ExpectedIndex;
+ }
+
+ for (auto &MI : ModiList) {
+ if (auto EC = MI->finalizeMsfLayout())
+ return EC;
+ }
+
+ uint32_t Length = calculateSerializedLength();
+ if (auto EC = Msf.setStreamSize(StreamDBI, Length))
+ return EC;
+ return Error::success();
+}
+
+static uint16_t toSecMapFlags(uint32_t Flags) {
+ uint16_t Ret = 0;
+ if (Flags & COFF::IMAGE_SCN_MEM_READ)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read);
+ if (Flags & COFF::IMAGE_SCN_MEM_WRITE)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write);
+ if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
+ if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT))
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit);
+
+ // This seems always 1.
+ Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector);
+
+ return Ret;
+}
+
+// Populate the Section Map from COFF section headers.
+//
+// A Section Map seem to be a copy of a COFF section list in other format.
+// I don't know why a PDB file contains both a COFF section header and
+// a Section Map, but it seems it must be present in a PDB.
+void DbiStreamBuilder::createSectionMap(
+ ArrayRef<llvm::object::coff_section> SecHdrs) {
+ int Idx = 0;
+
+ auto Add = [&]() -> SecMapEntry & {
+ SectionMap.emplace_back();
+ auto &Entry = SectionMap.back();
+ memset(&Entry, 0, sizeof(Entry));
+
+ Entry.Frame = Idx + 1;
+
+ // We don't know the meaning of these fields yet.
+ Entry.SecName = UINT16_MAX;
+ Entry.ClassName = UINT16_MAX;
+
+ return Entry;
+ };
+
+ for (auto &Hdr : SecHdrs) {
+ auto &Entry = Add();
+ Entry.Flags = toSecMapFlags(Hdr.Characteristics);
+ Entry.SecByteLength = Hdr.VirtualSize;
+ ++Idx;
+ }
+
+ // The last entry is for absolute symbols.
+ auto &Entry = Add();
+ Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) |
+ static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress);
+ Entry.SecByteLength = UINT32_MAX;
+}
+
+Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
+ WritableBinaryStreamRef MsfBuffer) {
+ if (auto EC = finalize())
+ return EC;
+
+ auto DbiS = WritableMappedBlockStream::createIndexedStream(
+ Layout, MsfBuffer, StreamDBI, Allocator);
+
+ BinaryStreamWriter Writer(*DbiS);
+ if (auto EC = Writer.writeObject(*Header))
+ return EC;
+
+ for (auto &M : ModiList) {
+ if (auto EC = M->commit(Writer))
+ return EC;
+ }
+
+ // Commit symbol streams. This is a lot of data, so do it in parallel.
+ if (auto EC = parallelForEachError(
+ ModiList, [&](std::unique_ptr<DbiModuleDescriptorBuilder> &M) {
+ return M->commitSymbolStream(Layout, MsfBuffer);
+ }))
+ return EC;
+
+ if (!SectionContribs.empty()) {
+ if (auto EC = Writer.writeEnum(DbiSecContribVer60))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs)))
+ return EC;
+ }
+
+ if (!SectionMap.empty()) {
+ ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size());
+ SecMapHeader SMHeader = {Size, Size};
+ if (auto EC = Writer.writeObject(SMHeader))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(SectionMap)))
+ return EC;
+ }
+
+ if (auto EC = Writer.writeStreamRef(FileInfoBuffer))
+ return EC;
+
+ if (auto EC = ECNamesBuilder.commit(Writer))
+ return EC;
+
+ for (auto &Stream : DbgStreams) {
+ uint16_t StreamNumber = kInvalidStreamIndex;
+ if (Stream.hasValue())
+ StreamNumber = Stream->StreamNumber;
+ if (auto EC = Writer.writeInteger(StreamNumber))
+ return EC;
+ }
+
+ for (auto &Stream : DbgStreams) {
+ if (!Stream.hasValue())
+ continue;
+ assert(Stream->StreamNumber != kInvalidStreamIndex);
+
+ auto WritableStream = WritableMappedBlockStream::createIndexedStream(
+ Layout, MsfBuffer, Stream->StreamNumber, Allocator);
+ BinaryStreamWriter DbgStreamWriter(*WritableStream);
+
+ if (auto EC = Stream->WriteFn(DbgStreamWriter))
+ return EC;
+ }
+
+ if (Writer.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Unexpected bytes found in DBI Stream");
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/EnumTables.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/EnumTables.cpp
new file mode 100644
index 0000000000..37192ba36a
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/EnumTables.cpp
@@ -0,0 +1,37 @@
+//===- EnumTables.cpp - Enum to string conversion tables --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+#define PDB_ENUM_CLASS_ENT(enum_class, enum) \
+ { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
+
+#define PDB_ENUM_ENT(ns, enum) \
+ { #enum, ns::enum }
+
+static const EnumEntry<uint16_t> OMFSegMapDescFlagNames[] = {
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, Read),
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, Write),
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, Execute),
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, AddressIs32Bit),
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, IsSelector),
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, IsAbsoluteAddress),
+ PDB_ENUM_CLASS_ENT(OMFSegDescFlags, IsGroup),
+};
+
+namespace llvm {
+namespace pdb {
+ArrayRef<EnumEntry<uint16_t>> getOMFSegMapDescFlagNames() {
+ return makeArrayRef(OMFSegMapDescFlagNames);
+}
+}
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
new file mode 100644
index 0000000000..9084e689d1
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp
@@ -0,0 +1,494 @@
+//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The data structures defined in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/Support/BinaryItemStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Parallel.h"
+#include "llvm/Support/xxhash.h"
+#include <algorithm>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::codeview;
+
+// Helper class for building the public and global PDB hash table buckets.
+struct llvm::pdb::GSIHashStreamBuilder {
+ // Sum of the size of all public or global records.
+ uint32_t RecordByteSize = 0;
+
+ std::vector<PSHashRecord> HashRecords;
+
+ // The hash bitmap has `ceil((IPHR_HASH + 1) / 32)` words in it. The
+ // reference implementation builds a hash table with IPHR_HASH buckets in it.
+ // The last bucket is used to link together free hash table cells in a linked
+ // list, but it is always empty in the compressed, on-disk format. However,
+ // the bitmap must have a bit for it.
+ std::array<support::ulittle32_t, (IPHR_HASH + 32) / 32> HashBitmap;
+
+ std::vector<support::ulittle32_t> HashBuckets;
+
+ uint32_t calculateSerializedLength() const;
+ Error commit(BinaryStreamWriter &Writer);
+
+ void finalizePublicBuckets();
+ void finalizeGlobalBuckets(uint32_t RecordZeroOffset);
+
+ // Assign public and global symbol records into hash table buckets.
+ // Modifies the list of records to store the bucket index, but does not
+ // change the order.
+ void finalizeBuckets(uint32_t RecordZeroOffset,
+ MutableArrayRef<BulkPublic> Globals);
+};
+
+// DenseMapInfo implementation for deduplicating symbol records.
+struct llvm::pdb::SymbolDenseMapInfo {
+ static inline CVSymbol getEmptyKey() {
+ static CVSymbol Empty;
+ return Empty;
+ }
+ static inline CVSymbol getTombstoneKey() {
+ static CVSymbol Tombstone(
+ DenseMapInfo<ArrayRef<uint8_t>>::getTombstoneKey());
+ return Tombstone;
+ }
+ static unsigned getHashValue(const CVSymbol &Val) {
+ return xxHash64(Val.RecordData);
+ }
+ static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS) {
+ return LHS.RecordData == RHS.RecordData;
+ }
+};
+
+namespace {
+LLVM_PACKED_START
+struct PublicSym32Layout {
+ RecordPrefix Prefix;
+ PublicSym32Header Pub;
+ // char Name[];
+};
+LLVM_PACKED_END
+} // namespace
+
+// Calculate how much memory this public needs when serialized.
+static uint32_t sizeOfPublic(const BulkPublic &Pub) {
+ uint32_t NameLen = Pub.NameLen;
+ NameLen = std::min(NameLen,
+ uint32_t(MaxRecordLength - sizeof(PublicSym32Layout) - 1));
+ return alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);
+}
+
+static CVSymbol serializePublic(uint8_t *Mem, const BulkPublic &Pub) {
+ // Assume the caller has allocated sizeOfPublic bytes.
+ uint32_t NameLen = std::min(
+ Pub.NameLen, uint32_t(MaxRecordLength - sizeof(PublicSym32Layout) - 1));
+ size_t Size = alignTo(sizeof(PublicSym32Layout) + NameLen + 1, 4);
+ assert(Size == sizeOfPublic(Pub));
+ auto *FixedMem = reinterpret_cast<PublicSym32Layout *>(Mem);
+ FixedMem->Prefix.RecordKind = static_cast<uint16_t>(codeview::S_PUB32);
+ FixedMem->Prefix.RecordLen = static_cast<uint16_t>(Size - 2);
+ FixedMem->Pub.Flags = Pub.Flags;
+ FixedMem->Pub.Offset = Pub.Offset;
+ FixedMem->Pub.Segment = Pub.Segment;
+ char *NameMem = reinterpret_cast<char *>(FixedMem + 1);
+ memcpy(NameMem, Pub.Name, NameLen);
+ // Zero the null terminator and remaining bytes.
+ memset(&NameMem[NameLen], 0, Size - sizeof(PublicSym32Layout) - NameLen);
+ return CVSymbol(makeArrayRef(reinterpret_cast<uint8_t *>(Mem), Size));
+}
+
+uint32_t GSIHashStreamBuilder::calculateSerializedLength() const {
+ uint32_t Size = sizeof(GSIHashHeader);
+ Size += HashRecords.size() * sizeof(PSHashRecord);
+ Size += HashBitmap.size() * sizeof(uint32_t);
+ Size += HashBuckets.size() * sizeof(uint32_t);
+ return Size;
+}
+
+Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) {
+ GSIHashHeader Header;
+ Header.VerSignature = GSIHashHeader::HdrSignature;
+ Header.VerHdr = GSIHashHeader::HdrVersion;
+ Header.HrSize = HashRecords.size() * sizeof(PSHashRecord);
+ Header.NumBuckets = HashBitmap.size() * 4 + HashBuckets.size() * 4;
+
+ if (auto EC = Writer.writeObject(Header))
+ return EC;
+
+ if (auto EC = Writer.writeArray(makeArrayRef(HashRecords)))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(HashBitmap)))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(HashBuckets)))
+ return EC;
+ return Error::success();
+}
+
+static bool isAsciiString(StringRef S) {
+ return llvm::all_of(S, [](char C) { return unsigned(C) < 0x80; });
+}
+
+// See `caseInsensitiveComparePchPchCchCch` in gsi.cpp
+static int gsiRecordCmp(StringRef S1, StringRef S2) {
+ size_t LS = S1.size();
+ size_t RS = S2.size();
+ // Shorter strings always compare less than longer strings.
+ if (LS != RS)
+ return (LS > RS) - (LS < RS);
+
+ // If either string contains non ascii characters, memcmp them.
+ if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2)))
+ return memcmp(S1.data(), S2.data(), LS);
+
+ // Both strings are ascii, perform a case-insensitive comparison.
+ return S1.compare_insensitive(S2.data());
+}
+
+void GSIStreamBuilder::finalizePublicBuckets() {
+ PSH->finalizeBuckets(0, Publics);
+}
+
+void GSIStreamBuilder::finalizeGlobalBuckets(uint32_t RecordZeroOffset) {
+ // Build up a list of globals to be bucketed. Use the BulkPublic data
+ // structure for this purpose, even though these are global records, not
+ // public records. Most of the same fields are required:
+ // - Name
+ // - NameLen
+ // - SymOffset
+ // - BucketIdx
+ // The dead fields are Offset, Segment, and Flags.
+ std::vector<BulkPublic> Records;
+ Records.resize(Globals.size());
+ uint32_t SymOffset = RecordZeroOffset;
+ for (size_t I = 0, E = Globals.size(); I < E; ++I) {
+ StringRef Name = getSymbolName(Globals[I]);
+ Records[I].Name = Name.data();
+ Records[I].NameLen = Name.size();
+ Records[I].SymOffset = SymOffset;
+ SymOffset += Globals[I].length();
+ }
+
+ GSH->finalizeBuckets(RecordZeroOffset, Records);
+}
+
+void GSIHashStreamBuilder::finalizeBuckets(
+ uint32_t RecordZeroOffset, MutableArrayRef<BulkPublic> Records) {
+ // Hash every name in parallel.
+ parallelForEachN(0, Records.size(), [&](size_t I) {
+ Records[I].setBucketIdx(hashStringV1(Records[I].Name) % IPHR_HASH);
+ });
+
+ // Count up the size of each bucket. Then, use an exclusive prefix sum to
+ // calculate the bucket start offsets. This is C++17 std::exclusive_scan, but
+ // we can't use it yet.
+ uint32_t BucketStarts[IPHR_HASH] = {0};
+ for (const BulkPublic &P : Records)
+ ++BucketStarts[P.BucketIdx];
+ uint32_t Sum = 0;
+ for (uint32_t &B : BucketStarts) {
+ uint32_t Size = B;
+ B = Sum;
+ Sum += Size;
+ }
+
+ // Place globals into the hash table in bucket order. When placing a global,
+ // update the bucket start. Every hash table slot should be filled. Always use
+ // a refcount of one for now.
+ HashRecords.resize(Records.size());
+ uint32_t BucketCursors[IPHR_HASH];
+ memcpy(BucketCursors, BucketStarts, sizeof(BucketCursors));
+ for (int I = 0, E = Records.size(); I < E; ++I) {
+ uint32_t HashIdx = BucketCursors[Records[I].BucketIdx]++;
+ HashRecords[HashIdx].Off = I;
+ HashRecords[HashIdx].CRef = 1;
+ }
+
+ // Within the buckets, sort each bucket by memcmp of the symbol's name. It's
+ // important that we use the same sorting algorithm as is used by the
+ // reference implementation to ensure that the search for a record within a
+ // bucket can properly early-out when it detects the record won't be found.
+ // The algorithm used here corresponds to the function
+ // caseInsensitiveComparePchPchCchCch in the reference implementation.
+ parallelForEachN(0, IPHR_HASH, [&](size_t I) {
+ auto B = HashRecords.begin() + BucketStarts[I];
+ auto E = HashRecords.begin() + BucketCursors[I];
+ if (B == E)
+ return;
+ auto BucketCmp = [Records](const PSHashRecord &LHash,
+ const PSHashRecord &RHash) {
+ const BulkPublic &L = Records[uint32_t(LHash.Off)];
+ const BulkPublic &R = Records[uint32_t(RHash.Off)];
+ assert(L.BucketIdx == R.BucketIdx);
+ int Cmp = gsiRecordCmp(L.getName(), R.getName());
+ if (Cmp != 0)
+ return Cmp < 0;
+ // This comparison is necessary to make the sorting stable in the presence
+ // of two static globals with the same name. The easiest way to observe
+ // this is with S_LDATA32 records.
+ return L.SymOffset < R.SymOffset;
+ };
+ llvm::sort(B, E, BucketCmp);
+
+ // After we are done sorting, replace the global indices with the stream
+ // offsets of each global. Add one when writing symbol offsets to disk.
+ // See GSI1::fixSymRecs.
+ for (PSHashRecord &HRec : make_range(B, E))
+ HRec.Off = Records[uint32_t(HRec.Off)].SymOffset + 1;
+ });
+
+ // For each non-empty bucket, push the bucket start offset into HashBuckets
+ // and set a bit in the hash bitmap.
+ for (uint32_t I = 0; I < HashBitmap.size(); ++I) {
+ uint32_t Word = 0;
+ for (uint32_t J = 0; J < 32; ++J) {
+ // Skip empty buckets.
+ uint32_t BucketIdx = I * 32 + J;
+ if (BucketIdx >= IPHR_HASH ||
+ BucketStarts[BucketIdx] == BucketCursors[BucketIdx])
+ continue;
+ Word |= (1U << J);
+
+ // Calculate what the offset of the first hash record in the chain would
+ // be if it were inflated to contain 32-bit pointers. On a 32-bit system,
+ // each record would be 12 bytes. See HROffsetCalc in gsi.h.
+ const int SizeOfHROffsetCalc = 12;
+ ulittle32_t ChainStartOff =
+ ulittle32_t(BucketStarts[BucketIdx] * SizeOfHROffsetCalc);
+ HashBuckets.push_back(ChainStartOff);
+ }
+ HashBitmap[I] = Word;
+ }
+}
+
+GSIStreamBuilder::GSIStreamBuilder(msf::MSFBuilder &Msf)
+ : Msf(Msf), PSH(std::make_unique<GSIHashStreamBuilder>()),
+ GSH(std::make_unique<GSIHashStreamBuilder>()) {}
+
+GSIStreamBuilder::~GSIStreamBuilder() {}
+
+uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const {
+ uint32_t Size = 0;
+ Size += sizeof(PublicsStreamHeader);
+ Size += PSH->calculateSerializedLength();
+ Size += Publics.size() * sizeof(uint32_t); // AddrMap
+ // FIXME: Add thunk map and section offsets for incremental linking.
+
+ return Size;
+}
+
+uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize() const {
+ return GSH->calculateSerializedLength();
+}
+
+Error GSIStreamBuilder::finalizeMsfLayout() {
+ // First we write public symbol records, then we write global symbol records.
+ finalizePublicBuckets();
+ finalizeGlobalBuckets(PSH->RecordByteSize);
+
+ Expected<uint32_t> Idx = Msf.addStream(calculateGlobalsHashStreamSize());
+ if (!Idx)
+ return Idx.takeError();
+ GlobalsStreamIndex = *Idx;
+
+ Idx = Msf.addStream(calculatePublicsHashStreamSize());
+ if (!Idx)
+ return Idx.takeError();
+ PublicsStreamIndex = *Idx;
+
+ uint32_t RecordBytes = PSH->RecordByteSize + GSH->RecordByteSize;
+
+ Idx = Msf.addStream(RecordBytes);
+ if (!Idx)
+ return Idx.takeError();
+ RecordStreamIndex = *Idx;
+ return Error::success();
+}
+
+void GSIStreamBuilder::addPublicSymbols(std::vector<BulkPublic> &&PublicsIn) {
+ assert(Publics.empty() && PSH->RecordByteSize == 0 &&
+ "publics can only be added once");
+ Publics = std::move(PublicsIn);
+
+ // Sort the symbols by name. PDBs contain lots of symbols, so use parallelism.
+ parallelSort(Publics, [](const BulkPublic &L, const BulkPublic &R) {
+ return L.getName() < R.getName();
+ });
+
+ // Assign offsets and calculate the length of the public symbol records.
+ uint32_t SymOffset = 0;
+ for (BulkPublic &Pub : Publics) {
+ Pub.SymOffset = SymOffset;
+ SymOffset += sizeOfPublic(Pub);
+ }
+
+ // Remember the length of the public stream records.
+ PSH->RecordByteSize = SymOffset;
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const ProcRefSym &Sym) {
+ serializeAndAddGlobal(Sym);
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const DataSym &Sym) {
+ serializeAndAddGlobal(Sym);
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const ConstantSym &Sym) {
+ serializeAndAddGlobal(Sym);
+}
+
+template <typename T>
+void GSIStreamBuilder::serializeAndAddGlobal(const T &Symbol) {
+ T Copy(Symbol);
+ addGlobalSymbol(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(),
+ CodeViewContainer::Pdb));
+}
+
+void GSIStreamBuilder::addGlobalSymbol(const codeview::CVSymbol &Symbol) {
+ // Ignore duplicate typedefs and constants.
+ if (Symbol.kind() == S_UDT || Symbol.kind() == S_CONSTANT) {
+ auto Iter = GlobalsSeen.insert(Symbol);
+ if (!Iter.second)
+ return;
+ }
+ GSH->RecordByteSize += Symbol.length();
+ Globals.push_back(Symbol);
+}
+
+// Serialize each public and write it.
+static Error writePublics(BinaryStreamWriter &Writer,
+ ArrayRef<BulkPublic> Publics) {
+ std::vector<uint8_t> Storage;
+ for (const BulkPublic &Pub : Publics) {
+ Storage.resize(sizeOfPublic(Pub));
+ serializePublic(Storage.data(), Pub);
+ if (Error E = Writer.writeBytes(Storage))
+ return E;
+ }
+ return Error::success();
+}
+
+static Error writeRecords(BinaryStreamWriter &Writer,
+ ArrayRef<CVSymbol> Records) {
+ BinaryItemStream<CVSymbol> ItemStream(support::endianness::little);
+ ItemStream.setItems(Records);
+ BinaryStreamRef RecordsRef(ItemStream);
+ return Writer.writeStreamRef(RecordsRef);
+}
+
+Error GSIStreamBuilder::commitSymbolRecordStream(
+ WritableBinaryStreamRef Stream) {
+ BinaryStreamWriter Writer(Stream);
+
+ // Write public symbol records first, followed by global symbol records. This
+ // must match the order that we assume in finalizeMsfLayout when computing
+ // PSHZero and GSHZero.
+ if (auto EC = writePublics(Writer, Publics))
+ return EC;
+ if (auto EC = writeRecords(Writer, Globals))
+ return EC;
+
+ return Error::success();
+}
+
+static std::vector<support::ulittle32_t>
+computeAddrMap(ArrayRef<BulkPublic> Publics) {
+ // Build a parallel vector of indices into the Publics vector, and sort it by
+ // address.
+ std::vector<ulittle32_t> PubAddrMap;
+ PubAddrMap.reserve(Publics.size());
+ for (int I = 0, E = Publics.size(); I < E; ++I)
+ PubAddrMap.push_back(ulittle32_t(I));
+
+ auto AddrCmp = [Publics](const ulittle32_t &LIdx, const ulittle32_t &RIdx) {
+ const BulkPublic &L = Publics[LIdx];
+ const BulkPublic &R = Publics[RIdx];
+ if (L.Segment != R.Segment)
+ return L.Segment < R.Segment;
+ if (L.Offset != R.Offset)
+ return L.Offset < R.Offset;
+ // parallelSort is unstable, so we have to do name comparison to ensure
+ // that two names for the same location come out in a deterministic order.
+ return L.getName() < R.getName();
+ };
+ parallelSort(PubAddrMap, AddrCmp);
+
+ // Rewrite the public symbol indices into symbol offsets.
+ for (ulittle32_t &Entry : PubAddrMap)
+ Entry = Publics[Entry].SymOffset;
+ return PubAddrMap;
+}
+
+Error GSIStreamBuilder::commitPublicsHashStream(
+ WritableBinaryStreamRef Stream) {
+ BinaryStreamWriter Writer(Stream);
+ PublicsStreamHeader Header;
+
+ // FIXME: Fill these in. They are for incremental linking.
+ Header.SymHash = PSH->calculateSerializedLength();
+ Header.AddrMap = Publics.size() * 4;
+ Header.NumThunks = 0;
+ Header.SizeOfThunk = 0;
+ Header.ISectThunkTable = 0;
+ memset(Header.Padding, 0, sizeof(Header.Padding));
+ Header.OffThunkTable = 0;
+ Header.NumSections = 0;
+ if (auto EC = Writer.writeObject(Header))
+ return EC;
+
+ if (auto EC = PSH->commit(Writer))
+ return EC;
+
+ std::vector<support::ulittle32_t> PubAddrMap = computeAddrMap(Publics);
+ assert(PubAddrMap.size() == Publics.size());
+ if (auto EC = Writer.writeArray(makeArrayRef(PubAddrMap)))
+ return EC;
+
+ return Error::success();
+}
+
+Error GSIStreamBuilder::commitGlobalsHashStream(
+ WritableBinaryStreamRef Stream) {
+ BinaryStreamWriter Writer(Stream);
+ return GSH->commit(Writer);
+}
+
+Error GSIStreamBuilder::commit(const msf::MSFLayout &Layout,
+ WritableBinaryStreamRef Buffer) {
+ auto GS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, getGlobalsStreamIndex(), Msf.getAllocator());
+ auto PS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, getPublicsStreamIndex(), Msf.getAllocator());
+ auto PRS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, getRecordStreamIndex(), Msf.getAllocator());
+
+ if (auto EC = commitSymbolRecordStream(*PRS))
+ return EC;
+ if (auto EC = commitGlobalsHashStream(*GS))
+ return EC;
+ if (auto EC = commitPublicsHashStream(*PS))
+ return EC;
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GlobalsStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
new file mode 100644
index 0000000000..f27d60f468
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/GlobalsStream.cpp
@@ -0,0 +1,181 @@
+//===- GlobalsStream.cpp - PDB Index of Symbols by Name ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The on-disk structores used in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+//
+// When you are reading the reference source code, you'd find the
+// information below useful.
+//
+// - ppdb1->m_fMinimalDbgInfo seems to be always true.
+// - SMALLBUCKETS macro is defined.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream)
+ : Stream(std::move(Stream)) {}
+
+GlobalsStream::~GlobalsStream() = default;
+
+Error GlobalsStream::reload() {
+ BinaryStreamReader Reader(*Stream);
+ if (auto E = GlobalsTable.read(Reader))
+ return E;
+ return Error::success();
+}
+
+std::vector<std::pair<uint32_t, codeview::CVSymbol>>
+GlobalsStream::findRecordsByName(StringRef Name,
+ const SymbolStream &Symbols) const {
+ std::vector<std::pair<uint32_t, codeview::CVSymbol>> Result;
+
+ // Hash the name to figure out which bucket this goes into.
+ size_t ExpandedBucketIndex = hashStringV1(Name) % IPHR_HASH;
+ int32_t CompressedBucketIndex = GlobalsTable.BucketMap[ExpandedBucketIndex];
+ if (CompressedBucketIndex == -1)
+ return Result;
+
+ uint32_t LastBucketIndex = GlobalsTable.HashBuckets.size() - 1;
+ uint32_t StartRecordIndex =
+ GlobalsTable.HashBuckets[CompressedBucketIndex] / 12;
+ uint32_t EndRecordIndex = 0;
+ if (LLVM_LIKELY(uint32_t(CompressedBucketIndex) < LastBucketIndex)) {
+ EndRecordIndex = GlobalsTable.HashBuckets[CompressedBucketIndex + 1];
+ } else {
+ // If this is the last bucket, it consists of all hash records until the end
+ // of the HashRecords array.
+ EndRecordIndex = GlobalsTable.HashRecords.size() * 12;
+ }
+
+ EndRecordIndex /= 12;
+
+ assert(EndRecordIndex <= GlobalsTable.HashRecords.size());
+ while (StartRecordIndex < EndRecordIndex) {
+ PSHashRecord PSH = GlobalsTable.HashRecords[StartRecordIndex];
+ uint32_t Off = PSH.Off - 1;
+ codeview::CVSymbol Record = Symbols.readRecord(Off);
+ if (codeview::getSymbolName(Record) == Name)
+ Result.push_back(std::make_pair(Off, std::move(Record)));
+ ++StartRecordIndex;
+ }
+ return Result;
+}
+
+static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
+ if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
+ return make_error<RawError>(
+ raw_error_code::feature_unsupported,
+ "Encountered unsupported globals stream version.");
+
+ return Error::success();
+}
+
+static Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
+ BinaryStreamReader &Reader) {
+ if (Reader.readObject(HashHdr))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Stream does not contain a GSIHashHeader.");
+
+ if (HashHdr->VerSignature != GSIHashHeader::HdrSignature)
+ return make_error<RawError>(
+ raw_error_code::feature_unsupported,
+ "GSIHashHeader signature (0xffffffff) not found.");
+
+ return Error::success();
+}
+
+static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
+ const GSIHashHeader *HashHdr,
+ BinaryStreamReader &Reader) {
+ if (auto EC = checkHashHdrVersion(HashHdr))
+ return EC;
+
+ // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
+ // Verify that we can read them all.
+ if (HashHdr->HrSize % sizeof(PSHashRecord))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid HR array size.");
+ uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
+ if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Error reading hash records."));
+
+ return Error::success();
+}
+
+static Error
+readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
+ FixedStreamArray<support::ulittle32_t> &HashBitmap,
+ const GSIHashHeader *HashHdr,
+ MutableArrayRef<int32_t> BucketMap,
+ BinaryStreamReader &Reader) {
+ if (auto EC = checkHashHdrVersion(HashHdr))
+ return EC;
+
+ // Before the actual hash buckets, there is a bitmap of length determined by
+ // IPHR_HASH.
+ size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
+ uint32_t NumBitmapEntries = BitmapSizeInBits / 32;
+ if (auto EC = Reader.readArray(HashBitmap, NumBitmapEntries))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a bitmap."));
+ uint32_t NumBuckets1 = 0;
+ uint32_t CompressedBucketIdx = 0;
+ for (uint32_t I = 0; I <= IPHR_HASH; ++I) {
+ uint8_t WordIdx = I / 32;
+ uint8_t BitIdx = I % 32;
+ bool IsSet = HashBitmap[WordIdx] & (1U << BitIdx);
+ if (IsSet) {
+ ++NumBuckets1;
+ BucketMap[I] = CompressedBucketIdx++;
+ } else {
+ BucketMap[I] = -1;
+ }
+ }
+
+ uint32_t NumBuckets = 0;
+ for (uint32_t B : HashBitmap)
+ NumBuckets += countPopulation(B);
+
+ // Hash buckets follow.
+ if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Hash buckets corrupted."));
+
+ return Error::success();
+}
+
+Error GSIHashTable::read(BinaryStreamReader &Reader) {
+ if (auto EC = readGSIHashHeader(HashHdr, Reader))
+ return EC;
+ if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
+ return EC;
+ if (HashHdr->HrSize > 0)
+ if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr,
+ BucketMap, Reader))
+ return EC;
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/Hash.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/Hash.cpp
new file mode 100644
index 0000000000..7fb6b4bd5d
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/Hash.cpp
@@ -0,0 +1,84 @@
+//===- Hash.cpp - PDB Hash Functions --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/CRC.h"
+#include "llvm/Support/Endian.h"
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::support;
+
+// Corresponds to `Hasher::lhashPbCb` in PDB/include/misc.h.
+// Used for name hash table and TPI/IPI hashes.
+uint32_t pdb::hashStringV1(StringRef Str) {
+ uint32_t Result = 0;
+ uint32_t Size = Str.size();
+
+ ArrayRef<ulittle32_t> Longs(reinterpret_cast<const ulittle32_t *>(Str.data()),
+ Size / 4);
+
+ for (auto Value : Longs)
+ Result ^= Value;
+
+ const uint8_t *Remainder = reinterpret_cast<const uint8_t *>(Longs.end());
+ uint32_t RemainderSize = Size % 4;
+
+ // Maximum of 3 bytes left. Hash a 2 byte word if possible, then hash the
+ // possibly remaining 1 byte.
+ if (RemainderSize >= 2) {
+ uint16_t Value = *reinterpret_cast<const ulittle16_t *>(Remainder);
+ Result ^= static_cast<uint32_t>(Value);
+ Remainder += 2;
+ RemainderSize -= 2;
+ }
+
+ // hash possible odd byte
+ if (RemainderSize == 1) {
+ Result ^= *(Remainder++);
+ }
+
+ const uint32_t toLowerMask = 0x20202020;
+ Result |= toLowerMask;
+ Result ^= (Result >> 11);
+
+ return Result ^ (Result >> 16);
+}
+
+// Corresponds to `HasherV2::HashULONG` in PDB/include/misc.h.
+// Used for name hash table.
+uint32_t pdb::hashStringV2(StringRef Str) {
+ uint32_t Hash = 0xb170a1bf;
+
+ ArrayRef<char> Buffer(Str.begin(), Str.end());
+
+ ArrayRef<ulittle32_t> Items(
+ reinterpret_cast<const ulittle32_t *>(Buffer.data()),
+ Buffer.size() / sizeof(ulittle32_t));
+ for (ulittle32_t Item : Items) {
+ Hash += Item;
+ Hash += (Hash << 10);
+ Hash ^= (Hash >> 6);
+ }
+ Buffer = Buffer.slice(Items.size() * sizeof(ulittle32_t));
+ for (uint8_t Item : Buffer) {
+ Hash += Item;
+ Hash += (Hash << 10);
+ Hash ^= (Hash >> 6);
+ }
+
+ return Hash * 1664525U + 1013904223U;
+}
+
+// Corresponds to `SigForPbCb` in langapi/shared/crc32.h.
+uint32_t pdb::hashBufferV8(ArrayRef<uint8_t> Buf) {
+ JamCRC JC(/*Init=*/0U);
+ JC.update(Buf);
+ return JC.getCRC();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/HashTable.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/HashTable.cpp
new file mode 100644
index 0000000000..dfdcdf1f4e
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/HashTable.cpp
@@ -0,0 +1,71 @@
+//===- HashTable.cpp - PDB Hash Table -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+Error llvm::pdb::readSparseBitVector(BinaryStreamReader &Stream,
+ SparseBitVector<> &V) {
+ uint32_t NumWords;
+ if (auto EC = Stream.readInteger(NumWords))
+ return joinErrors(
+ std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Expected hash table number of words"));
+
+ for (uint32_t I = 0; I != NumWords; ++I) {
+ uint32_t Word;
+ if (auto EC = Stream.readInteger(Word))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Expected hash table word"));
+ for (unsigned Idx = 0; Idx < 32; ++Idx)
+ if (Word & (1U << Idx))
+ V.set((I * 32) + Idx);
+ }
+ return Error::success();
+}
+
+Error llvm::pdb::writeSparseBitVector(BinaryStreamWriter &Writer,
+ SparseBitVector<> &Vec) {
+ constexpr int BitsPerWord = 8 * sizeof(uint32_t);
+
+ int ReqBits = Vec.find_last() + 1;
+ uint32_t ReqWords = alignTo(ReqBits, BitsPerWord) / BitsPerWord;
+ if (auto EC = Writer.writeInteger(ReqWords))
+ return joinErrors(
+ std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not write linear map number of words"));
+
+ uint32_t Idx = 0;
+ for (uint32_t I = 0; I != ReqWords; ++I) {
+ uint32_t Word = 0;
+ for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) {
+ if (Vec.test(Idx))
+ Word |= (1 << WordIdx);
+ }
+ if (auto EC = Writer.writeInteger(Word))
+ return joinErrors(std::move(EC), make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "Could not write linear map word"));
+ }
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStream.cpp
new file mode 100644
index 0000000000..f41bb32d69
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStream.cpp
@@ -0,0 +1,131 @@
+//===- InfoStream.cpp - PDB Info Stream (Stream 1) Access -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream)
+ : Stream(std::move(Stream)), Header(nullptr) {}
+
+Error InfoStream::reload() {
+ BinaryStreamReader Reader(*Stream);
+
+ if (auto EC = Reader.readObject(Header))
+ return joinErrors(
+ std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "PDB Stream does not contain a header."));
+
+ switch (Header->Version) {
+ case PdbImplVC70:
+ case PdbImplVC80:
+ case PdbImplVC110:
+ case PdbImplVC140:
+ break;
+ default:
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Unsupported PDB stream version.");
+ }
+
+ uint32_t Offset = Reader.getOffset();
+ if (auto EC = NamedStreams.load(Reader))
+ return EC;
+ uint32_t NewOffset = Reader.getOffset();
+ NamedStreamMapByteSize = NewOffset - Offset;
+
+ Reader.setOffset(Offset);
+ if (auto EC = Reader.readSubstream(SubNamedStreams, NamedStreamMapByteSize))
+ return EC;
+
+ bool Stop = false;
+ while (!Stop && !Reader.empty()) {
+ PdbRaw_FeatureSig Sig;
+ if (auto EC = Reader.readEnum(Sig))
+ return EC;
+ // Since this value comes from a file, it's possible we have some strange
+ // value which doesn't correspond to any value. We don't want to warn on
+ // -Wcovered-switch-default in this case, so switch on the integral value
+ // instead of the enumeration value.
+ switch (uint32_t(Sig)) {
+ case uint32_t(PdbRaw_FeatureSig::VC110):
+ // No other flags for VC110 PDB.
+ Stop = true;
+ LLVM_FALLTHROUGH;
+ case uint32_t(PdbRaw_FeatureSig::VC140):
+ Features |= PdbFeatureContainsIdStream;
+ break;
+ case uint32_t(PdbRaw_FeatureSig::NoTypeMerge):
+ Features |= PdbFeatureNoTypeMerging;
+ break;
+ case uint32_t(PdbRaw_FeatureSig::MinimalDebugInfo):
+ Features |= PdbFeatureMinimalDebugInfo;
+ break;
+ default:
+ continue;
+ }
+ FeatureSignatures.push_back(Sig);
+ }
+ return Error::success();
+}
+
+uint32_t InfoStream::getStreamSize() const { return Stream->getLength(); }
+
+Expected<uint32_t> InfoStream::getNamedStreamIndex(llvm::StringRef Name) const {
+ uint32_t Result;
+ if (!NamedStreams.get(Name, Result))
+ return make_error<RawError>(raw_error_code::no_stream);
+ return Result;
+}
+
+StringMap<uint32_t> InfoStream::named_streams() const {
+ return NamedStreams.entries();
+}
+
+bool InfoStream::containsIdStream() const {
+ return !!(Features & PdbFeatureContainsIdStream);
+}
+
+PdbRaw_ImplVer InfoStream::getVersion() const {
+ return static_cast<PdbRaw_ImplVer>(uint32_t(Header->Version));
+}
+
+uint32_t InfoStream::getSignature() const {
+ return uint32_t(Header->Signature);
+}
+
+uint32_t InfoStream::getAge() const { return uint32_t(Header->Age); }
+
+GUID InfoStream::getGuid() const { return Header->Guid; }
+
+uint32_t InfoStream::getNamedStreamMapByteSize() const {
+ return NamedStreamMapByteSize;
+}
+
+PdbRaw_Features InfoStream::getFeatures() const { return Features; }
+
+ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const {
+ return FeatureSignatures;
+}
+
+const NamedStreamMap &InfoStream::getNamedStreams() const {
+ return NamedStreams;
+}
+
+BinarySubstreamRef InfoStream::getNamedStreamsBuffer() const {
+ return SubNamedStreams;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
new file mode 100644
index 0000000000..42daa7cae7
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
@@ -0,0 +1,82 @@
+//===- InfoStreamBuilder.cpp - PDB Info Stream Creation ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf,
+ NamedStreamMap &NamedStreams)
+ : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Age(0),
+ NamedStreams(NamedStreams) {
+ ::memset(&Guid, 0, sizeof(Guid));
+}
+
+void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
+
+void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
+ Features.push_back(Sig);
+}
+
+void InfoStreamBuilder::setHashPDBContentsToGUID(bool B) {
+ HashPDBContentsToGUID = B;
+}
+
+void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
+
+void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; }
+
+void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
+
+
+Error InfoStreamBuilder::finalizeMsfLayout() {
+ uint32_t Length = sizeof(InfoStreamHeader) +
+ NamedStreams.calculateSerializedLength() +
+ (Features.size() + 1) * sizeof(uint32_t);
+ if (auto EC = Msf.setStreamSize(StreamPDB, Length))
+ return EC;
+ return Error::success();
+}
+
+Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
+ WritableBinaryStreamRef Buffer) const {
+ auto InfoS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, StreamPDB, Msf.getAllocator());
+ BinaryStreamWriter Writer(*InfoS);
+
+ InfoStreamHeader H;
+ // Leave the build id fields 0 so they can be set as the last step before
+ // committing the file to disk.
+ ::memset(&H, 0, sizeof(H));
+ H.Version = Ver;
+ if (auto EC = Writer.writeObject(H))
+ return EC;
+
+ if (auto EC = NamedStreams.commit(Writer))
+ return EC;
+ if (auto EC = Writer.writeInteger(0))
+ return EC;
+ for (auto E : Features) {
+ if (auto EC = Writer.writeEnum(E))
+ return EC;
+ }
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp
new file mode 100644
index 0000000000..3f4101db7b
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp
@@ -0,0 +1,65 @@
+//===- InjectedSourceStream.cpp - PDB Headerblock Stream Access -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h"
+
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+InjectedSourceStream::InjectedSourceStream(
+ std::unique_ptr<MappedBlockStream> Stream)
+ : Stream(std::move(Stream)) {}
+
+Error InjectedSourceStream::reload(const PDBStringTable &Strings) {
+ BinaryStreamReader Reader(*Stream);
+
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+
+ if (Header->Version !=
+ static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid headerblock header version");
+
+ if (auto EC = InjectedSourceTable.load(Reader))
+ return EC;
+
+ for (const auto& Entry : *this) {
+ if (Entry.second.Size != sizeof(SrcHeaderBlockEntry))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid headerbock entry size");
+ if (Entry.second.Version !=
+ static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid headerbock entry version");
+
+ // Check that all name references are valid.
+ auto Name = Strings.getStringForID(Entry.second.FileNI);
+ if (!Name)
+ return Name.takeError();
+ auto ObjName = Strings.getStringForID(Entry.second.ObjNI);
+ if (!ObjName)
+ return ObjName.takeError();
+ auto VName = Strings.getStringForID(Entry.second.VFileNI);
+ if (!VName)
+ return VName.takeError();
+ }
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
new file mode 100644
index 0000000000..1445f0bd9e
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp
@@ -0,0 +1,144 @@
+//===- ModuleDebugStream.cpp - PDB Module Info Stream Access --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+ModuleDebugStreamRef::ModuleDebugStreamRef(
+ const DbiModuleDescriptor &Module,
+ std::unique_ptr<MappedBlockStream> Stream)
+ : Mod(Module), Stream(std::move(Stream)) {}
+
+ModuleDebugStreamRef::~ModuleDebugStreamRef() = default;
+
+Error ModuleDebugStreamRef::reload() {
+ BinaryStreamReader Reader(*Stream);
+
+ if (Mod.getModuleStreamIndex() != llvm::pdb::kInvalidStreamIndex) {
+ if (Error E = reloadSerialize(Reader))
+ return E;
+ }
+ if (Reader.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Unexpected bytes in module stream.");
+ return Error::success();
+}
+
+Error ModuleDebugStreamRef::reloadSerialize(BinaryStreamReader &Reader) {
+ uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
+ uint32_t C11Size = Mod.getC11LineInfoByteSize();
+ uint32_t C13Size = Mod.getC13LineInfoByteSize();
+
+ if (C11Size > 0 && C13Size > 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Module has both C11 and C13 line info");
+
+ BinaryStreamRef S;
+
+ if (auto EC = Reader.readInteger(Signature))
+ return EC;
+ Reader.setOffset(0);
+ if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize))
+ return EC;
+ if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size))
+ return EC;
+ if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size))
+ return EC;
+
+ BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData);
+ if (auto EC = SymbolReader.readArray(
+ SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t)))
+ return EC;
+
+ BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);
+ if (auto EC = SubsectionsReader.readArray(Subsections,
+ SubsectionsReader.bytesRemaining()))
+ return EC;
+
+ uint32_t GlobalRefsSize;
+ if (auto EC = Reader.readInteger(GlobalRefsSize))
+ return EC;
+ if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize))
+ return EC;
+ return Error::success();
+}
+
+const codeview::CVSymbolArray
+ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const {
+ return limitSymbolArrayToScope(SymbolArray, ScopeBegin);
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const {
+ return SymbolsSubstream;
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const {
+ return C11LinesSubstream;
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const {
+ return C13LinesSubstream;
+}
+
+BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const {
+ return GlobalRefsSubstream;
+}
+
+iterator_range<codeview::CVSymbolArray::Iterator>
+ModuleDebugStreamRef::symbols(bool *HadError) const {
+ return make_range(SymbolArray.begin(HadError), SymbolArray.end());
+}
+
+CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const {
+ auto Iter = SymbolArray.at(Offset);
+ assert(Iter != SymbolArray.end());
+ return *Iter;
+}
+
+iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator>
+ModuleDebugStreamRef::subsections() const {
+ return make_range(Subsections.begin(), Subsections.end());
+}
+
+bool ModuleDebugStreamRef::hasDebugSubsections() const {
+ return !C13LinesSubstream.empty();
+}
+
+Error ModuleDebugStreamRef::commit() { return Error::success(); }
+
+Expected<codeview::DebugChecksumsSubsectionRef>
+ModuleDebugStreamRef::findChecksumsSubsection() const {
+ codeview::DebugChecksumsSubsectionRef Result;
+ for (const auto &SS : subsections()) {
+ if (SS.kind() != DebugSubsectionKind::FileChecksums)
+ continue;
+
+ if (auto EC = Result.initialize(SS.getRecordData()))
+ return std::move(EC);
+ return Result;
+ }
+ return Result;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
new file mode 100644
index 0000000000..1d873b87b3
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp
@@ -0,0 +1,126 @@
+//===- NamedStreamMap.cpp - PDB Named Stream Map --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <tuple>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NamedStreamMapTraits::NamedStreamMapTraits(NamedStreamMap &NS) : NS(&NS) {}
+
+uint16_t NamedStreamMapTraits::hashLookupKey(StringRef S) const {
+ // In the reference implementation, this uses
+ // HASH Hasher<ULONG*, USHORT*>::hashPbCb(PB pb, size_t cb, ULONG ulMod).
+ // Here, the type HASH is a typedef of unsigned short.
+ // ** It is not a bug that we truncate the result of hashStringV1, in fact
+ // it is a bug if we do not! **
+ // See NMTNI::hash() in the reference implementation.
+ return static_cast<uint16_t>(hashStringV1(S));
+}
+
+StringRef NamedStreamMapTraits::storageKeyToLookupKey(uint32_t Offset) const {
+ return NS->getString(Offset);
+}
+
+uint32_t NamedStreamMapTraits::lookupKeyToStorageKey(StringRef S) {
+ return NS->appendStringData(S);
+}
+
+NamedStreamMap::NamedStreamMap() : HashTraits(*this), OffsetIndexMap(1) {}
+
+Error NamedStreamMap::load(BinaryStreamReader &Stream) {
+ uint32_t StringBufferSize;
+ if (auto EC = Stream.readInteger(StringBufferSize))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Expected string buffer size"));
+
+ StringRef Buffer;
+ if (auto EC = Stream.readFixedString(Buffer, StringBufferSize))
+ return EC;
+ NamesBuffer.assign(Buffer.begin(), Buffer.end());
+
+ return OffsetIndexMap.load(Stream);
+}
+
+Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
+ // The first field is the number of bytes of string data.
+ if (auto EC = Writer.writeInteger<uint32_t>(NamesBuffer.size()))
+ return EC;
+
+ // Then the actual string data.
+ StringRef Data(NamesBuffer.data(), NamesBuffer.size());
+ if (auto EC = Writer.writeFixedString(Data))
+ return EC;
+
+ // And finally the Offset Index map.
+ if (auto EC = OffsetIndexMap.commit(Writer))
+ return EC;
+
+ return Error::success();
+}
+
+uint32_t NamedStreamMap::calculateSerializedLength() const {
+ return sizeof(uint32_t) // String data size
+ + NamesBuffer.size() // String data
+ + OffsetIndexMap.calculateSerializedLength(); // Offset Index Map
+}
+
+uint32_t NamedStreamMap::size() const { return OffsetIndexMap.size(); }
+
+StringRef NamedStreamMap::getString(uint32_t Offset) const {
+ assert(NamesBuffer.size() > Offset);
+ return StringRef(NamesBuffer.data() + Offset);
+}
+
+uint32_t NamedStreamMap::hashString(uint32_t Offset) const {
+ return hashStringV1(getString(Offset));
+}
+
+bool NamedStreamMap::get(StringRef Stream, uint32_t &StreamNo) const {
+ auto Iter = OffsetIndexMap.find_as(Stream, HashTraits);
+ if (Iter == OffsetIndexMap.end())
+ return false;
+ StreamNo = (*Iter).second;
+ return true;
+}
+
+StringMap<uint32_t> NamedStreamMap::entries() const {
+ StringMap<uint32_t> Result;
+ for (const auto &Entry : OffsetIndexMap) {
+ StringRef Stream(NamesBuffer.data() + Entry.first);
+ Result.try_emplace(Stream, Entry.second);
+ }
+ return Result;
+}
+
+uint32_t NamedStreamMap::appendStringData(StringRef S) {
+ uint32_t Offset = NamesBuffer.size();
+ llvm::append_range(NamesBuffer, S);
+ NamesBuffer.push_back('\0');
+ return Offset;
+}
+
+void NamedStreamMap::set(StringRef Stream, uint32_t StreamNo) {
+ OffsetIndexMap.set_as(Stream, support::ulittle32_t(StreamNo), HashTraits);
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
new file mode 100644
index 0000000000..7717f062ea
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp
@@ -0,0 +1,60 @@
+//===- NativeCompilandSymbol.cpp - Native impl for compilands ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+namespace llvm {
+namespace pdb {
+
+NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session,
+ SymIndexId SymbolId,
+ DbiModuleDescriptor MI)
+ : NativeRawSymbol(Session, PDB_SymType::Compiland, SymbolId), Module(MI) {}
+
+PDB_SymType NativeCompilandSymbol::getSymTag() const {
+ return PDB_SymType::Compiland;
+}
+
+void NativeCompilandSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "libraryName", getLibraryName(), Indent);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolField(OS, "editAndContinueEnabled", isEditAndContinueEnabled(),
+ Indent);
+}
+
+bool NativeCompilandSymbol::isEditAndContinueEnabled() const {
+ return Module.hasECInfo();
+}
+
+SymIndexId NativeCompilandSymbol::getLexicalParentId() const { return 0; }
+
+// The usage of getObjFileName for getLibraryName and getModuleName for getName
+// may seem backwards, but it is consistent with DIA, which is what this API
+// was modeled after. We may rename these methods later to try to eliminate
+// this potential confusion.
+
+std::string NativeCompilandSymbol::getLibraryName() const {
+ return std::string(Module.getObjFileName());
+}
+
+std::string NativeCompilandSymbol::getName() const {
+ return std::string(Module.getModuleName());
+}
+
+} // namespace pdb
+} // namespace llvm
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp
new file mode 100644
index 0000000000..54646867bc
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp
@@ -0,0 +1,54 @@
+//==- NativeEnumGlobals.cpp - Native Global Enumerator impl ------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumGlobals::NativeEnumGlobals(NativeSession &PDBSession,
+ std::vector<codeview::SymbolKind> Kinds)
+ : Index(0), Session(PDBSession) {
+ GlobalsStream &GS = cantFail(Session.getPDBFile().getPDBGlobalsStream());
+ SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
+ for (uint32_t Off : GS.getGlobalsTable()) {
+ CVSymbol S = SS.readRecord(Off);
+ if (!llvm::is_contained(Kinds, S.kind()))
+ continue;
+ MatchOffsets.push_back(Off);
+ }
+}
+
+uint32_t NativeEnumGlobals::getChildCount() const {
+ return static_cast<uint32_t>(MatchOffsets.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumGlobals::getChildAtIndex(uint32_t N) const {
+ if (N >= MatchOffsets.size())
+ return nullptr;
+
+ SymIndexId Id =
+ Session.getSymbolCache().getOrCreateGlobalSymbolByOffset(MatchOffsets[N]);
+ return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumGlobals::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumGlobals::reset() { Index = 0; }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp
new file mode 100644
index 0000000000..5e64122750
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp
@@ -0,0 +1,121 @@
+//==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
+
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+
+namespace llvm {
+namespace pdb {
+
+namespace {
+
+Expected<std::string> readStreamData(BinaryStream &Stream, uint64_t Limit) {
+ uint64_t Offset = 0, DataLength = std::min(Limit, Stream.getLength());
+ std::string Result;
+ Result.reserve(DataLength);
+ while (Offset < DataLength) {
+ ArrayRef<uint8_t> Data;
+ if (auto E = Stream.readLongestContiguousChunk(Offset, Data))
+ return std::move(E);
+ Data = Data.take_front(DataLength - Offset);
+ Offset += Data.size();
+ Result += toStringRef(Data);
+ }
+ return Result;
+}
+
+class NativeInjectedSource final : public IPDBInjectedSource {
+ const SrcHeaderBlockEntry &Entry;
+ const PDBStringTable &Strings;
+ PDBFile &File;
+
+public:
+ NativeInjectedSource(const SrcHeaderBlockEntry &Entry,
+ PDBFile &File, const PDBStringTable &Strings)
+ : Entry(Entry), Strings(Strings), File(File) {}
+
+ uint32_t getCrc32() const override { return Entry.CRC; }
+ uint64_t getCodeByteSize() const override { return Entry.FileSize; }
+
+ std::string getFileName() const override {
+ StringRef Ret = cantFail(Strings.getStringForID(Entry.FileNI),
+ "InjectedSourceStream should have rejected this");
+ return std::string(Ret);
+ }
+
+ std::string getObjectFileName() const override {
+ StringRef Ret = cantFail(Strings.getStringForID(Entry.ObjNI),
+ "InjectedSourceStream should have rejected this");
+ return std::string(Ret);
+ }
+
+ std::string getVirtualFileName() const override {
+ StringRef Ret = cantFail(Strings.getStringForID(Entry.VFileNI),
+ "InjectedSourceStream should have rejected this");
+ return std::string(Ret);
+ }
+
+ uint32_t getCompression() const override { return Entry.Compression; }
+
+ std::string getCode() const override {
+ // Get name of stream storing the data.
+ StringRef VName =
+ cantFail(Strings.getStringForID(Entry.VFileNI),
+ "InjectedSourceStream should have rejected this");
+ std::string StreamName = ("/src/files/" + VName).str();
+
+ // Find stream with that name and read its data.
+ // FIXME: Consider validating (or even loading) all this in
+ // InjectedSourceStream so that no error can happen here.
+ auto ExpectedFileStream = File.safelyCreateNamedStream(StreamName);
+ if (!ExpectedFileStream) {
+ consumeError(ExpectedFileStream.takeError());
+ return "(failed to open data stream)";
+ }
+
+ auto Data = readStreamData(**ExpectedFileStream, Entry.FileSize);
+ if (!Data) {
+ consumeError(Data.takeError());
+ return "(failed to read data)";
+ }
+ return *Data;
+ }
+};
+
+} // namespace
+
+NativeEnumInjectedSources::NativeEnumInjectedSources(
+ PDBFile &File, const InjectedSourceStream &IJS,
+ const PDBStringTable &Strings)
+ : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {}
+
+uint32_t NativeEnumInjectedSources::getChildCount() const {
+ return static_cast<uint32_t>(Stream.size());
+}
+
+std::unique_ptr<IPDBInjectedSource>
+NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const {
+ if (N >= getChildCount())
+ return nullptr;
+ return std::make_unique<NativeInjectedSource>(std::next(Stream.begin(), N)->second,
+ File, Strings);
+}
+
+std::unique_ptr<IPDBInjectedSource> NativeEnumInjectedSources::getNext() {
+ if (Cur == Stream.end())
+ return nullptr;
+ return std::make_unique<NativeInjectedSource>((Cur++)->second, File, Strings);
+}
+
+void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); }
+
+}
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp
new file mode 100644
index 0000000000..1e4b076463
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp
@@ -0,0 +1,42 @@
+//==- NativeEnumLineNumbers.cpp - Native Type Enumerator impl ----*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumLineNumbers::NativeEnumLineNumbers(
+ std::vector<NativeLineNumber> LineNums)
+ : Lines(std::move(LineNums)), Index(0) {}
+
+uint32_t NativeEnumLineNumbers::getChildCount() const {
+ return static_cast<uint32_t>(Lines.size());
+}
+
+std::unique_ptr<IPDBLineNumber>
+NativeEnumLineNumbers::getChildAtIndex(uint32_t N) const {
+ if (N >= getChildCount())
+ return nullptr;
+ return std::make_unique<NativeLineNumber>(Lines[N]);
+}
+
+std::unique_ptr<IPDBLineNumber> NativeEnumLineNumbers::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumLineNumbers::reset() { Index = 0; }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
new file mode 100644
index 0000000000..c6621924b5
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp
@@ -0,0 +1,43 @@
+//==- NativeEnumModules.cpp - Native Symbol Enumerator impl ------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+
+namespace llvm {
+namespace pdb {
+
+NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, uint32_t Index)
+ : Session(PDBSession), Index(Index) {}
+
+uint32_t NativeEnumModules::getChildCount() const {
+ return Session.getSymbolCache().getNumCompilands();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumModules::getChildAtIndex(uint32_t N) const {
+ return Session.getSymbolCache().getOrCreateCompiland(N);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() {
+ if (Index >= getChildCount())
+ return nullptr;
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumModules::reset() { Index = 0; }
+
+}
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
new file mode 100644
index 0000000000..feede1dbc9
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp
@@ -0,0 +1,41 @@
+//==- NativeEnumSymbols.cpp - Native Symbol Enumerator impl ------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumSymbols::NativeEnumSymbols(NativeSession &PDBSession,
+ std::vector<SymIndexId> Symbols)
+ : Symbols(std::move(Symbols)), Index(0), Session(PDBSession) {}
+
+uint32_t NativeEnumSymbols::getChildCount() const {
+ return static_cast<uint32_t>(Symbols.size());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumSymbols::getChildAtIndex(uint32_t N) const {
+ if (N < Symbols.size()) {
+ return Session.getSymbolCache().getSymbolById(Symbols[N]);
+ }
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumSymbols::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumSymbols::reset() { Index = 0; }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
new file mode 100644
index 0000000000..2524e10cb6
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp
@@ -0,0 +1,70 @@
+//==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
+ LazyRandomTypeCollection &Types,
+ std::vector<codeview::TypeLeafKind> Kinds)
+ : Index(0), Session(PDBSession) {
+ Optional<TypeIndex> TI = Types.getFirst();
+ while (TI) {
+ CVType CVT = Types.getType(*TI);
+ TypeLeafKind K = CVT.kind();
+ if (llvm::is_contained(Kinds, K)) {
+ // Don't add forward refs, we'll find those later while enumerating.
+ if (!isUdtForwardRef(CVT))
+ Matches.push_back(*TI);
+ } else if (K == TypeLeafKind::LF_MODIFIER) {
+ TypeIndex ModifiedTI = getModifiedType(CVT);
+ if (!ModifiedTI.isSimple()) {
+ CVType UnmodifiedCVT = Types.getType(ModifiedTI);
+ // LF_MODIFIERs point to forward refs, but don't worry about that
+ // here. We're pushing the TypeIndex of the LF_MODIFIER itself,
+ // so we'll worry about resolving forward refs later.
+ if (llvm::is_contained(Kinds, UnmodifiedCVT.kind()))
+ Matches.push_back(*TI);
+ }
+ }
+ TI = Types.getNext(*TI);
+ }
+}
+
+NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession,
+ std::vector<codeview::TypeIndex> Indices)
+ : Matches(std::move(Indices)), Index(0), Session(PDBSession) {}
+
+uint32_t NativeEnumTypes::getChildCount() const {
+ return static_cast<uint32_t>(Matches.size());
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumTypes::getChildAtIndex(uint32_t N) const {
+ if (N < Matches.size()) {
+ SymIndexId Id = Session.getSymbolCache().findSymbolByTypeIndex(Matches[N]);
+ return Session.getSymbolCache().getSymbolById(Id);
+ }
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() {
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumTypes::reset() { Index = 0; }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
new file mode 100644
index 0000000000..895f894315
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
@@ -0,0 +1,101 @@
+//===- NativeExeSymbol.cpp - native impl for PDBSymbolExe -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+static DbiStream *getDbiStreamPtr(NativeSession &Session) {
+ Expected<DbiStream &> DbiS = Session.getPDBFile().getPDBDbiStream();
+ if (DbiS)
+ return &DbiS.get();
+
+ consumeError(DbiS.takeError());
+ return nullptr;
+}
+
+NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId)
+ : NativeRawSymbol(Session, PDB_SymType::Exe, SymbolId),
+ Dbi(getDbiStreamPtr(Session)) {}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeExeSymbol::findChildren(PDB_SymType Type) const {
+ switch (Type) {
+ case PDB_SymType::Compiland: {
+ return std::unique_ptr<IPDBEnumSymbols>(new NativeEnumModules(Session));
+ break;
+ }
+ case PDB_SymType::ArrayType:
+ return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ARRAY);
+ case PDB_SymType::Enum:
+ return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM);
+ case PDB_SymType::PointerType:
+ return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER);
+ case PDB_SymType::UDT:
+ return Session.getSymbolCache().createTypeEnumerator(
+ {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION,
+ codeview::LF_INTERFACE});
+ case PDB_SymType::VTableShape:
+ return Session.getSymbolCache().createTypeEnumerator(codeview::LF_VTSHAPE);
+ case PDB_SymType::FunctionSig:
+ return Session.getSymbolCache().createTypeEnumerator(
+ {codeview::LF_PROCEDURE, codeview::LF_MFUNCTION});
+ case PDB_SymType::Typedef:
+ return Session.getSymbolCache().createGlobalsEnumerator(codeview::S_UDT);
+
+ default:
+ break;
+ }
+ return nullptr;
+}
+
+uint32_t NativeExeSymbol::getAge() const {
+ auto IS = Session.getPDBFile().getPDBInfoStream();
+ if (IS)
+ return IS->getAge();
+ consumeError(IS.takeError());
+ return 0;
+}
+
+std::string NativeExeSymbol::getSymbolsFileName() const {
+ return std::string(Session.getPDBFile().getFilePath());
+}
+
+codeview::GUID NativeExeSymbol::getGuid() const {
+ auto IS = Session.getPDBFile().getPDBInfoStream();
+ if (IS)
+ return IS->getGuid();
+ consumeError(IS.takeError());
+ return codeview::GUID{{0}};
+}
+
+bool NativeExeSymbol::hasCTypes() const {
+ auto Dbi = Session.getPDBFile().getPDBDbiStream();
+ if (Dbi)
+ return Dbi->hasCTypes();
+ consumeError(Dbi.takeError());
+ return false;
+}
+
+bool NativeExeSymbol::hasPrivateSymbols() const {
+ auto Dbi = Session.getPDBFile().getPDBDbiStream();
+ if (Dbi)
+ return !Dbi->isStripped();
+ consumeError(Dbi.takeError());
+ return false;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
new file mode 100644
index 0000000000..7f3b35c297
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
@@ -0,0 +1,143 @@
+//===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
+ SymIndexId Id,
+ const codeview::ProcSym &Sym,
+ uint32_t Offset)
+ : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym),
+ RecordOffset(Offset) {}
+
+NativeFunctionSymbol::~NativeFunctionSymbol() {}
+
+void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
+ dumpSymbolField(OS, "section", getAddressSection(), Indent);
+}
+
+uint32_t NativeFunctionSymbol::getAddressOffset() const {
+ return Sym.CodeOffset;
+}
+
+uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
+std::string NativeFunctionSymbol::getName() const {
+ return std::string(Sym.Name);
+}
+
+uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
+
+uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
+ return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
+}
+
+uint64_t NativeFunctionSymbol::getVirtualAddress() const {
+ return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
+}
+
+static bool inlineSiteContainsAddress(InlineSiteSym &IS,
+ uint32_t OffsetInFunc) {
+ // Returns true if inline site contains the offset.
+ bool Found = false;
+ uint32_t CodeOffset = 0;
+ for (auto &Annot : IS.annotations()) {
+ switch (Annot.OpCode) {
+ case BinaryAnnotationsOpCode::CodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+ CodeOffset += Annot.U1;
+ if (OffsetInFunc >= CodeOffset)
+ Found = true;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ CodeOffset += Annot.U1;
+ if (Found && OffsetInFunc < CodeOffset)
+ return true;
+ Found = false;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+ CodeOffset += Annot.U2;
+ if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1)
+ return true;
+ Found = false;
+ break;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const {
+ uint16_t Modi;
+ if (!Session.moduleIndexForVA(VA, Modi))
+ return nullptr;
+
+ Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
+ if (!ModS) {
+ consumeError(ModS.takeError());
+ return nullptr;
+ }
+ CVSymbolArray Syms = ModS->getSymbolArray();
+
+ // Search for inline sites. There should be one matching top level inline
+ // site. Then search in its nested inline sites.
+ std::vector<SymIndexId> Frames;
+ uint32_t CodeOffset = VA - getVirtualAddress();
+ auto Start = Syms.at(RecordOffset);
+ auto End = Syms.at(Sym.End);
+ while (Start != End) {
+ bool Found = false;
+ // Find matching inline site within Start and End.
+ for (; Start != End; ++Start) {
+ if (Start->kind() != S_INLINESITE)
+ continue;
+
+ InlineSiteSym IS =
+ cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start));
+ if (inlineSiteContainsAddress(IS, CodeOffset)) {
+ // Insert frames in reverse order.
+ SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol(
+ IS, getVirtualAddress(), Modi, Start.offset());
+ Frames.insert(Frames.begin(), Id);
+
+ // Update offsets to search within this inline site.
+ ++Start;
+ End = Syms.at(IS.End);
+ Found = true;
+ break;
+ }
+
+ Start = Syms.at(IS.End);
+ if (Start == End)
+ break;
+ }
+
+ if (!Found)
+ break;
+ }
+
+ return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames));
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
new file mode 100644
index 0000000000..8314353c38
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp
@@ -0,0 +1,177 @@
+//===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeInlineSiteSymbol::NativeInlineSiteSymbol(
+ NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym,
+ uint64_t ParentAddr)
+ : NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym),
+ ParentAddr(ParentAddr) {}
+
+NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {}
+
+void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+}
+
+static Optional<InlineeSourceLine>
+findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) {
+ for (const auto &SS : ModS.getSubsectionsArray()) {
+ if (SS.kind() != DebugSubsectionKind::InlineeLines)
+ continue;
+
+ DebugInlineeLinesSubsectionRef InlineeLines;
+ BinaryStreamReader Reader(SS.getRecordData());
+ if (auto EC = InlineeLines.initialize(Reader)) {
+ consumeError(std::move(EC));
+ continue;
+ }
+
+ for (const InlineeSourceLine &Line : InlineeLines)
+ if (Line.Header->Inlinee == Id)
+ return Line;
+ }
+ return None;
+}
+
+std::string NativeInlineSiteSymbol::getName() const {
+ auto Tpi = Session.getPDBFile().getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return "";
+ }
+ auto Ipi = Session.getPDBFile().getPDBIpiStream();
+ if (!Ipi) {
+ consumeError(Ipi.takeError());
+ return "";
+ }
+
+ LazyRandomTypeCollection &Types = Tpi->typeCollection();
+ LazyRandomTypeCollection &Ids = Ipi->typeCollection();
+ CVType InlineeType = Ids.getType(Sym.Inlinee);
+ std::string QualifiedName;
+ if (InlineeType.kind() == LF_MFUNC_ID) {
+ MemberFuncIdRecord MFRecord;
+ cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType,
+ MFRecord));
+ TypeIndex ClassTy = MFRecord.getClassType();
+ QualifiedName.append(std::string(Types.getTypeName(ClassTy)));
+ QualifiedName.append("::");
+ } else if (InlineeType.kind() == LF_FUNC_ID) {
+ FuncIdRecord FRecord;
+ cantFail(
+ TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord));
+ TypeIndex ParentScope = FRecord.getParentScope();
+ if (!ParentScope.isNoneType()) {
+ QualifiedName.append(std::string(Ids.getTypeName(ParentScope)));
+ QualifiedName.append("::");
+ }
+ }
+
+ QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee)));
+ return QualifiedName;
+}
+
+void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc,
+ uint32_t &LineOffset,
+ uint32_t &FileOffset) const {
+ LineOffset = 0;
+ FileOffset = 0;
+ uint32_t CodeOffset = 0;
+ for (const auto &Annot : Sym.annotations()) {
+ switch (Annot.OpCode) {
+ case BinaryAnnotationsOpCode::CodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeLength:
+ CodeOffset += Annot.U1;
+ break;
+ case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
+ CodeOffset += Annot.U2;
+ break;
+ case BinaryAnnotationsOpCode::ChangeLineOffset:
+ case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
+ CodeOffset += Annot.U1;
+ LineOffset += Annot.S1;
+ break;
+ case BinaryAnnotationsOpCode::ChangeFile:
+ FileOffset = Annot.U1;
+ break;
+ default:
+ break;
+ }
+
+ if (CodeOffset >= OffsetInFunc)
+ return;
+ }
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA,
+ uint32_t Length) const {
+ uint16_t Modi;
+ if (!Session.moduleIndexForVA(VA, Modi))
+ return nullptr;
+
+ Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi);
+ if (!ModS) {
+ consumeError(ModS.takeError());
+ return nullptr;
+ }
+
+ Expected<DebugChecksumsSubsectionRef> Checksums =
+ ModS->findChecksumsSubsection();
+ if (!Checksums) {
+ consumeError(Checksums.takeError());
+ return nullptr;
+ }
+
+ // Get the line number offset and source file offset.
+ uint32_t SrcLineOffset;
+ uint32_t SrcFileOffset;
+ getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset);
+
+ // Get line info from inlinee line table.
+ Optional<InlineeSourceLine> Inlinee =
+ findInlineeByTypeIndex(Sym.Inlinee, ModS.get());
+
+ if (!Inlinee)
+ return nullptr;
+
+ uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset;
+ uint32_t SrcCol = 0; // Inline sites don't seem to have column info.
+ uint32_t FileChecksumOffset =
+ (SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset;
+
+ auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset);
+ uint32_t SrcFileId =
+ Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter);
+
+ uint32_t LineSect, LineOff;
+ Session.addressForVA(VA, LineSect, LineOff);
+ NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length,
+ SrcFileId, Modi);
+ auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId);
+ std::vector<NativeLineNumber> Lines{LineNum};
+
+ return std::make_unique<NativeEnumLineNumbers>(std::move(Lines));
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp
new file mode 100644
index 0000000000..155ed0cdb8
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp
@@ -0,0 +1,51 @@
+//===- NativeLineNumber.cpp - Native line number implementation -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeLineNumber::NativeLineNumber(const NativeSession &Session,
+ const codeview::LineInfo Line,
+ uint32_t ColumnNumber, uint32_t Section,
+ uint32_t Offset, uint32_t Length,
+ uint32_t SrcFileId, uint32_t CompilandId)
+ : Session(Session), Line(Line), ColumnNumber(ColumnNumber),
+ Section(Section), Offset(Offset), Length(Length), SrcFileId(SrcFileId),
+ CompilandId(CompilandId) {}
+
+uint32_t NativeLineNumber::getLineNumber() const { return Line.getStartLine(); }
+
+uint32_t NativeLineNumber::getLineNumberEnd() const {
+ return Line.getEndLine();
+}
+
+uint32_t NativeLineNumber::getColumnNumber() const { return ColumnNumber; }
+
+uint32_t NativeLineNumber::getColumnNumberEnd() const { return 0; }
+
+uint32_t NativeLineNumber::getAddressSection() const { return Section; }
+
+uint32_t NativeLineNumber::getAddressOffset() const { return Offset; }
+
+uint32_t NativeLineNumber::getRelativeVirtualAddress() const {
+ return Session.getRVAFromSectOffset(Section, Offset);
+}
+
+uint64_t NativeLineNumber::getVirtualAddress() const {
+ return Session.getVAFromSectOffset(Section, Offset);
+}
+
+uint32_t NativeLineNumber::getLength() const { return Length; }
+
+uint32_t NativeLineNumber::getSourceFileId() const { return SrcFileId; }
+
+uint32_t NativeLineNumber::getCompilandId() const { return CompilandId; }
+
+bool NativeLineNumber::isStatement() const { return Line.isStatement(); }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
new file mode 100644
index 0000000000..1265e688b8
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
@@ -0,0 +1,48 @@
+//===- NativePublicSymbol.cpp - info about public symbols -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativePublicSymbol::NativePublicSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::PublicSym32 &Sym)
+ : NativeRawSymbol(Session, PDB_SymType::PublicSymbol, Id), Sym(Sym) {}
+
+NativePublicSymbol::~NativePublicSymbol() {}
+
+void NativePublicSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
+ dumpSymbolField(OS, "section", getAddressSection(), Indent);
+}
+
+uint32_t NativePublicSymbol::getAddressOffset() const { return Sym.Offset; }
+
+uint32_t NativePublicSymbol::getAddressSection() const { return Sym.Segment; }
+
+std::string NativePublicSymbol::getName() const {
+ return std::string(Sym.Name);
+}
+
+uint32_t NativePublicSymbol::getRelativeVirtualAddress() const {
+ return Session.getRVAFromSectOffset(Sym.Segment, Sym.Offset);
+}
+
+uint64_t NativePublicSymbol::getVirtualAddress() const {
+ return Session.getVAFromSectOffset(Sym.Segment, Sym.Offset);
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
new file mode 100644
index 0000000000..2ad552470b
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -0,0 +1,734 @@
+//===- NativeRawSymbol.cpp - Native implementation of IPDBRawSymbol -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag,
+ SymIndexId SymbolId)
+ : Session(PDBSession), Tag(Tag), SymbolId(SymbolId) {}
+
+void NativeRawSymbol::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ dumpSymbolIdField(OS, "symIndexId", SymbolId, Indent, Session,
+ PdbSymbolIdField::SymIndexId, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "symTag", Tag, Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildren(PDB_SymType Type) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint64_t VA) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint32_t RVA) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByAddr(uint32_t Section,
+ uint32_t Offset) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const {
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLines() const {
+ return std::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const {
+ return std::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const {
+ return std::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const {
+ return std::make_unique<NullEnumerator<IPDBLineNumber>>();
+}
+
+void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const {
+ bytes.clear();
+}
+
+PDB_MemberAccess NativeRawSymbol::getAccess() const {
+ return PDB_MemberAccess::Private;
+}
+
+uint32_t NativeRawSymbol::getAddressOffset() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getAddressSection() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getAge() const {
+ return 0;
+}
+
+SymIndexId NativeRawSymbol::getArrayIndexTypeId() const { return 0; }
+
+void NativeRawSymbol::getBackEndVersion(VersionInfo &Version) const {
+ Version.Major = 0;
+ Version.Minor = 0;
+ Version.Build = 0;
+ Version.QFE = 0;
+}
+
+uint32_t NativeRawSymbol::getBaseDataOffset() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getBaseDataSlot() const {
+ return 0;
+}
+
+SymIndexId NativeRawSymbol::getBaseSymbolId() const { return 0; }
+
+PDB_BuiltinType NativeRawSymbol::getBuiltinType() const {
+ return PDB_BuiltinType::None;
+}
+
+uint32_t NativeRawSymbol::getBitPosition() const {
+ return 0;
+}
+
+PDB_CallingConv NativeRawSymbol::getCallingConvention() const {
+ return PDB_CallingConv::FarStdCall;
+}
+
+SymIndexId NativeRawSymbol::getClassParentId() const { return 0; }
+
+std::string NativeRawSymbol::getCompilerName() const {
+ return {};
+}
+
+uint32_t NativeRawSymbol::getCount() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getCountLiveRanges() const {
+ return 0;
+}
+
+void NativeRawSymbol::getFrontEndVersion(VersionInfo &Version) const {
+ Version.Major = 0;
+ Version.Minor = 0;
+ Version.Build = 0;
+ Version.QFE = 0;
+}
+
+PDB_Lang NativeRawSymbol::getLanguage() const {
+ return PDB_Lang::Cobol;
+}
+
+SymIndexId NativeRawSymbol::getLexicalParentId() const { return 0; }
+
+std::string NativeRawSymbol::getLibraryName() const {
+ return {};
+}
+
+uint32_t NativeRawSymbol::getLiveRangeStartAddressOffset() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getLiveRangeStartAddressSection() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getLiveRangeStartRelativeVirtualAddress() const {
+ return 0;
+}
+
+codeview::RegisterId NativeRawSymbol::getLocalBasePointerRegisterId() const {
+ return codeview::RegisterId::EAX;
+}
+
+SymIndexId NativeRawSymbol::getLowerBoundId() const { return 0; }
+
+uint32_t NativeRawSymbol::getMemorySpaceKind() const {
+ return 0;
+}
+
+std::string NativeRawSymbol::getName() const {
+ return {};
+}
+
+uint32_t NativeRawSymbol::getNumberOfAcceleratorPointerTags() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfColumns() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfModifiers() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfRegisterIndices() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getNumberOfRows() const {
+ return 0;
+}
+
+std::string NativeRawSymbol::getObjectFileName() const {
+ return {};
+}
+
+uint32_t NativeRawSymbol::getOemId() const {
+ return 0;
+}
+
+SymIndexId NativeRawSymbol::getOemSymbolId() const { return 0; }
+
+uint32_t NativeRawSymbol::getOffsetInUdt() const {
+ return 0;
+}
+
+PDB_Cpu NativeRawSymbol::getPlatform() const {
+ return PDB_Cpu::Intel8080;
+}
+
+uint32_t NativeRawSymbol::getRank() const {
+ return 0;
+}
+
+codeview::RegisterId NativeRawSymbol::getRegisterId() const {
+ return codeview::RegisterId::EAX;
+}
+
+uint32_t NativeRawSymbol::getRegisterType() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getRelativeVirtualAddress() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getSamplerSlot() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getSignature() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getSizeInUdt() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getSlot() const {
+ return 0;
+}
+
+std::string NativeRawSymbol::getSourceFileName() const {
+ return {};
+}
+
+std::unique_ptr<IPDBLineNumber>
+NativeRawSymbol::getSrcLineOnTypeDefn() const {
+ return nullptr;
+}
+
+uint32_t NativeRawSymbol::getStride() const {
+ return 0;
+}
+
+SymIndexId NativeRawSymbol::getSubTypeId() const { return 0; }
+
+std::string NativeRawSymbol::getSymbolsFileName() const { return {}; }
+
+SymIndexId NativeRawSymbol::getSymIndexId() const { return SymbolId; }
+
+uint32_t NativeRawSymbol::getTargetOffset() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getTargetRelativeVirtualAddress() const {
+ return 0;
+}
+
+uint64_t NativeRawSymbol::getTargetVirtualAddress() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getTargetSection() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getTextureSlot() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getTimeStamp() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getToken() const {
+ return 0;
+}
+
+SymIndexId NativeRawSymbol::getTypeId() const { return 0; }
+
+uint32_t NativeRawSymbol::getUavSlot() const {
+ return 0;
+}
+
+std::string NativeRawSymbol::getUndecoratedName() const {
+ return {};
+}
+
+std::string NativeRawSymbol::getUndecoratedNameEx(
+ PDB_UndnameFlags Flags) const {
+ return {};
+}
+
+SymIndexId NativeRawSymbol::getUnmodifiedTypeId() const { return 0; }
+
+SymIndexId NativeRawSymbol::getUpperBoundId() const { return 0; }
+
+Variant NativeRawSymbol::getValue() const {
+ return Variant();
+}
+
+uint32_t NativeRawSymbol::getVirtualBaseDispIndex() const {
+ return 0;
+}
+
+uint32_t NativeRawSymbol::getVirtualBaseOffset() const {
+ return 0;
+}
+
+SymIndexId NativeRawSymbol::getVirtualTableShapeId() const { return 0; }
+
+std::unique_ptr<PDBSymbolTypeBuiltin>
+NativeRawSymbol::getVirtualBaseTableType() const {
+ return nullptr;
+}
+
+PDB_DataKind NativeRawSymbol::getDataKind() const {
+ return PDB_DataKind::Unknown;
+}
+
+PDB_SymType NativeRawSymbol::getSymTag() const { return Tag; }
+
+codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; }
+
+int32_t NativeRawSymbol::getOffset() const {
+ return 0;
+}
+
+int32_t NativeRawSymbol::getThisAdjust() const {
+ return 0;
+}
+
+int32_t NativeRawSymbol::getVirtualBasePointerOffset() const {
+ return 0;
+}
+
+PDB_LocType NativeRawSymbol::getLocationType() const {
+ return PDB_LocType::Null;
+}
+
+PDB_Machine NativeRawSymbol::getMachineType() const {
+ return PDB_Machine::Invalid;
+}
+
+codeview::ThunkOrdinal NativeRawSymbol::getThunkOrdinal() const {
+ return codeview::ThunkOrdinal::Standard;
+}
+
+uint64_t NativeRawSymbol::getLength() const {
+ return 0;
+}
+
+uint64_t NativeRawSymbol::getLiveRangeLength() const {
+ return 0;
+}
+
+uint64_t NativeRawSymbol::getVirtualAddress() const {
+ return 0;
+}
+
+PDB_UdtType NativeRawSymbol::getUdtKind() const {
+ return PDB_UdtType::Struct;
+}
+
+bool NativeRawSymbol::hasConstructor() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasCustomCallingConvention() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasFarReturn() const {
+ return false;
+}
+
+bool NativeRawSymbol::isCode() const {
+ return false;
+}
+
+bool NativeRawSymbol::isCompilerGenerated() const {
+ return false;
+}
+
+bool NativeRawSymbol::isConstType() const {
+ return false;
+}
+
+bool NativeRawSymbol::isEditAndContinueEnabled() const {
+ return false;
+}
+
+bool NativeRawSymbol::isFunction() const {
+ return false;
+}
+
+bool NativeRawSymbol::getAddressTaken() const {
+ return false;
+}
+
+bool NativeRawSymbol::getNoStackOrdering() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasAlloca() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasAssignmentOperator() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasCTypes() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasCastOperator() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasDebugInfo() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasEH() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasEHa() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasInlAsm() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasInlineAttribute() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasInterruptReturn() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasFramePointer() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasLongJump() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasManagedCode() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasNestedTypes() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasNoInlineAttribute() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasNoReturnAttribute() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasOptimizedCodeDebugInfo() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasOverloadedOperator() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasSEH() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasSecurityChecks() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasSetJump() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasStrictGSCheck() const {
+ return false;
+}
+
+bool NativeRawSymbol::isAcceleratorGroupSharedLocal() const {
+ return false;
+}
+
+bool NativeRawSymbol::isAcceleratorPointerTagLiveRange() const {
+ return false;
+}
+
+bool NativeRawSymbol::isAcceleratorStubFunction() const {
+ return false;
+}
+
+bool NativeRawSymbol::isAggregated() const {
+ return false;
+}
+
+bool NativeRawSymbol::isIntroVirtualFunction() const {
+ return false;
+}
+
+bool NativeRawSymbol::isCVTCIL() const {
+ return false;
+}
+
+bool NativeRawSymbol::isConstructorVirtualBase() const {
+ return false;
+}
+
+bool NativeRawSymbol::isCxxReturnUdt() const {
+ return false;
+}
+
+bool NativeRawSymbol::isDataAligned() const {
+ return false;
+}
+
+bool NativeRawSymbol::isHLSLData() const {
+ return false;
+}
+
+bool NativeRawSymbol::isHotpatchable() const {
+ return false;
+}
+
+bool NativeRawSymbol::isIndirectVirtualBaseClass() const {
+ return false;
+}
+
+bool NativeRawSymbol::isInterfaceUdt() const {
+ return false;
+}
+
+bool NativeRawSymbol::isIntrinsic() const {
+ return false;
+}
+
+bool NativeRawSymbol::isLTCG() const {
+ return false;
+}
+
+bool NativeRawSymbol::isLocationControlFlowDependent() const {
+ return false;
+}
+
+bool NativeRawSymbol::isMSILNetmodule() const {
+ return false;
+}
+
+bool NativeRawSymbol::isMatrixRowMajor() const {
+ return false;
+}
+
+bool NativeRawSymbol::isManagedCode() const {
+ return false;
+}
+
+bool NativeRawSymbol::isMSILCode() const {
+ return false;
+}
+
+bool NativeRawSymbol::isMultipleInheritance() const {
+ return false;
+}
+
+bool NativeRawSymbol::isNaked() const {
+ return false;
+}
+
+bool NativeRawSymbol::isNested() const {
+ return false;
+}
+
+bool NativeRawSymbol::isOptimizedAway() const {
+ return false;
+}
+
+bool NativeRawSymbol::isPacked() const {
+ return false;
+}
+
+bool NativeRawSymbol::isPointerBasedOnSymbolValue() const {
+ return false;
+}
+
+bool NativeRawSymbol::isPointerToDataMember() const {
+ return false;
+}
+
+bool NativeRawSymbol::isPointerToMemberFunction() const {
+ return false;
+}
+
+bool NativeRawSymbol::isPureVirtual() const {
+ return false;
+}
+
+bool NativeRawSymbol::isRValueReference() const {
+ return false;
+}
+
+bool NativeRawSymbol::isRefUdt() const {
+ return false;
+}
+
+bool NativeRawSymbol::isReference() const {
+ return false;
+}
+
+bool NativeRawSymbol::isRestrictedType() const {
+ return false;
+}
+
+bool NativeRawSymbol::isReturnValue() const {
+ return false;
+}
+
+bool NativeRawSymbol::isSafeBuffers() const {
+ return false;
+}
+
+bool NativeRawSymbol::isScoped() const {
+ return false;
+}
+
+bool NativeRawSymbol::isSdl() const {
+ return false;
+}
+
+bool NativeRawSymbol::isSingleInheritance() const {
+ return false;
+}
+
+bool NativeRawSymbol::isSplitted() const {
+ return false;
+}
+
+bool NativeRawSymbol::isStatic() const {
+ return false;
+}
+
+bool NativeRawSymbol::hasPrivateSymbols() const {
+ return false;
+}
+
+bool NativeRawSymbol::isUnalignedType() const {
+ return false;
+}
+
+bool NativeRawSymbol::isUnreached() const {
+ return false;
+}
+
+bool NativeRawSymbol::isValueUdt() const {
+ return false;
+}
+
+bool NativeRawSymbol::isVirtual() const {
+ return false;
+}
+
+bool NativeRawSymbol::isVirtualBaseClass() const {
+ return false;
+}
+
+bool NativeRawSymbol::isVirtualInheritance() const {
+ return false;
+}
+
+bool NativeRawSymbol::isVolatileType() const {
+ return false;
+}
+
+bool NativeRawSymbol::wasInlined() const {
+ return false;
+}
+
+std::string NativeRawSymbol::getUnused() const {
+ return {};
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSession.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSession.cpp
new file mode 100644
index 0000000000..7212a0e650
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -0,0 +1,463 @@
+//===- NativeSession.cpp - Native implementation of IPDBSession -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+static DbiStream *getDbiStreamPtr(PDBFile &File) {
+ Expected<DbiStream &> DbiS = File.getPDBDbiStream();
+ if (DbiS)
+ return &DbiS.get();
+
+ consumeError(DbiS.takeError());
+ return nullptr;
+}
+
+NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
+ std::unique_ptr<BumpPtrAllocator> Allocator)
+ : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
+ Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {}
+
+NativeSession::~NativeSession() = default;
+
+Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,
+ std::unique_ptr<IPDBSession> &Session) {
+ StringRef Path = Buffer->getBufferIdentifier();
+ auto Stream = std::make_unique<MemoryBufferByteStream>(
+ std::move(Buffer), llvm::support::little);
+
+ auto Allocator = std::make_unique<BumpPtrAllocator>();
+ auto File = std::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
+ if (auto EC = File->parseFileHeaders())
+ return EC;
+ if (auto EC = File->parseStreamData())
+ return EC;
+
+ Session =
+ std::make_unique<NativeSession>(std::move(File), std::move(Allocator));
+
+ return Error::success();
+}
+
+static Expected<std::unique_ptr<PDBFile>>
+loadPdbFile(StringRef PdbPath, std::unique_ptr<BumpPtrAllocator> &Allocator) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
+ MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
+ /*RequiresNullTerminator=*/false);
+ if (!ErrorOrBuffer)
+ return make_error<RawError>(ErrorOrBuffer.getError());
+ std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
+
+ PdbPath = Buffer->getBufferIdentifier();
+ file_magic Magic;
+ auto EC = identify_magic(PdbPath, Magic);
+ if (EC || Magic != file_magic::pdb)
+ return make_error<RawError>(EC);
+
+ auto Stream = std::make_unique<MemoryBufferByteStream>(std::move(Buffer),
+ llvm::support::little);
+
+ auto File = std::make_unique<PDBFile>(PdbPath, std::move(Stream), *Allocator);
+ if (auto EC = File->parseFileHeaders())
+ return std::move(EC);
+
+ if (auto EC = File->parseStreamData())
+ return std::move(EC);
+
+ return std::move(File);
+}
+
+Error NativeSession::createFromPdbPath(StringRef PdbPath,
+ std::unique_ptr<IPDBSession> &Session) {
+ auto Allocator = std::make_unique<BumpPtrAllocator>();
+ auto PdbFile = loadPdbFile(PdbPath, Allocator);
+ if (!PdbFile)
+ return PdbFile.takeError();
+
+ Session = std::make_unique<NativeSession>(std::move(PdbFile.get()),
+ std::move(Allocator));
+ return Error::success();
+}
+
+static Expected<std::string> getPdbPathFromExe(StringRef ExePath) {
+ Expected<object::OwningBinary<object::Binary>> BinaryFile =
+ object::createBinary(ExePath);
+ if (!BinaryFile)
+ return BinaryFile.takeError();
+
+ const object::COFFObjectFile *ObjFile =
+ dyn_cast<object::COFFObjectFile>(BinaryFile->getBinary());
+ if (!ObjFile)
+ return make_error<RawError>(raw_error_code::invalid_format);
+
+ StringRef PdbPath;
+ const llvm::codeview::DebugInfo *PdbInfo = nullptr;
+ if (Error E = ObjFile->getDebugPDBInfo(PdbInfo, PdbPath))
+ return std::move(E);
+
+ return std::string(PdbPath);
+}
+
+Error NativeSession::createFromExe(StringRef ExePath,
+ std::unique_ptr<IPDBSession> &Session) {
+ Expected<std::string> PdbPath = getPdbPathFromExe(ExePath);
+ if (!PdbPath)
+ return PdbPath.takeError();
+
+ file_magic Magic;
+ auto EC = identify_magic(PdbPath.get(), Magic);
+ if (EC || Magic != file_magic::pdb)
+ return make_error<RawError>(EC);
+
+ auto Allocator = std::make_unique<BumpPtrAllocator>();
+ auto File = loadPdbFile(PdbPath.get(), Allocator);
+ if (!File)
+ return File.takeError();
+
+ Session = std::make_unique<NativeSession>(std::move(File.get()),
+ std::move(Allocator));
+
+ return Error::success();
+}
+
+Expected<std::string>
+NativeSession::searchForPdb(const PdbSearchOptions &Opts) {
+ Expected<std::string> PathOrErr = getPdbPathFromExe(Opts.ExePath);
+ if (!PathOrErr)
+ return PathOrErr.takeError();
+ StringRef PathFromExe = PathOrErr.get();
+ sys::path::Style Style = PathFromExe.startswith("/")
+ ? sys::path::Style::posix
+ : sys::path::Style::windows;
+ StringRef PdbName = sys::path::filename(PathFromExe, Style);
+
+ // Check if pdb exists in the executable directory.
+ SmallString<128> PdbPath = StringRef(Opts.ExePath);
+ sys::path::remove_filename(PdbPath);
+ sys::path::append(PdbPath, PdbName);
+
+ auto Allocator = std::make_unique<BumpPtrAllocator>();
+
+ if (auto File = loadPdbFile(PdbPath, Allocator))
+ return std::string(PdbPath);
+ else
+ consumeError(File.takeError());
+
+ // Check path that was in the executable.
+ if (auto File = loadPdbFile(PathFromExe, Allocator))
+ return std::string(PathFromExe);
+ else
+ return File.takeError();
+
+ return make_error<RawError>("PDB not found");
+}
+
+uint64_t NativeSession::getLoadAddress() const { return LoadAddress; }
+
+bool NativeSession::setLoadAddress(uint64_t Address) {
+ LoadAddress = Address;
+ return true;
+}
+
+std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
+ return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::getSymbolById(SymIndexId SymbolId) const {
+ return Cache.getSymbolById(SymbolId);
+}
+
+bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
+ uint32_t &Offset) const {
+ uint32_t RVA = VA - getLoadAddress();
+ return addressForRVA(RVA, Section, Offset);
+}
+
+bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
+ uint32_t &Offset) const {
+ Section = 0;
+ Offset = 0;
+
+ auto Dbi = Pdb->getPDBDbiStream();
+ if (!Dbi)
+ return false;
+
+ if ((int32_t)RVA < 0)
+ return true;
+
+ Offset = RVA;
+ for (; Section < Dbi->getSectionHeaders().size(); ++Section) {
+ auto &Sec = Dbi->getSectionHeaders()[Section];
+ if (RVA < Sec.VirtualAddress)
+ return true;
+ Offset = RVA - Sec.VirtualAddress;
+ }
+ return true;
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) {
+ uint32_t Section;
+ uint32_t Offset;
+ addressForVA(Address, Section, Offset);
+ return findSymbolBySectOffset(Section, Offset, Type);
+}
+
+std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
+ PDB_SymType Type) {
+ uint32_t Section;
+ uint32_t Offset;
+ addressForRVA(RVA, Section, Offset);
+ return findSymbolBySectOffset(Section, Offset, Type);
+}
+
+std::unique_ptr<PDBSymbol>
+NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+ PDB_SymType Type) {
+ if (AddrToModuleIndex.empty())
+ parseSectionContribs();
+
+ return Cache.findSymbolBySectOffset(Sect, Offset, Type);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
+ const IPDBSourceFile &File) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersByAddress(uint64_t Address,
+ uint32_t Length) const {
+ return Cache.findLineNumbersByVA(Address, Length);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
+ return Cache.findLineNumbersByVA(getLoadAddress() + RVA, Length);
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
+ uint32_t Length) const {
+ uint64_t VA = getVAFromSectOffset(Section, Offset);
+ return Cache.findLineNumbersByVA(VA, Length);
+}
+
+std::unique_ptr<IPDBEnumSourceFiles>
+NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
+ StringRef Pattern,
+ PDB_NameSearchFlags Flags) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBSourceFile>
+NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
+ StringRef Pattern,
+ PDB_NameSearchFlags Flags) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+NativeSession::findCompilandsForSourceFile(StringRef Pattern,
+ PDB_NameSearchFlags Flags) const {
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+NativeSession::findOneCompilandForSourceFile(StringRef Pattern,
+ PDB_NameSearchFlags Flags) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
+ const PDBSymbolCompiland &Compiland) const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBSourceFile>
+NativeSession::getSourceFileById(uint32_t FileId) const {
+ return Cache.getSourceFileById(FileId);
+}
+
+std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumInjectedSources>
+NativeSession::getInjectedSources() const {
+ auto ISS = Pdb->getInjectedSourceStream();
+ if (!ISS) {
+ consumeError(ISS.takeError());
+ return nullptr;
+ }
+ auto Strings = Pdb->getStringTable();
+ if (!Strings) {
+ consumeError(Strings.takeError());
+ return nullptr;
+ }
+ return std::make_unique<NativeEnumInjectedSources>(*Pdb, *ISS, *Strings);
+}
+
+std::unique_ptr<IPDBEnumSectionContribs>
+NativeSession::getSectionContribs() const {
+ return nullptr;
+}
+
+std::unique_ptr<IPDBEnumFrameData>
+NativeSession::getFrameData() const {
+ return nullptr;
+}
+
+void NativeSession::initializeExeSymbol() {
+ if (ExeSymbol == 0)
+ ExeSymbol = Cache.createSymbol<NativeExeSymbol>();
+}
+
+NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
+ const_cast<NativeSession &>(*this).initializeExeSymbol();
+
+ return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
+}
+
+uint32_t NativeSession::getRVAFromSectOffset(uint32_t Section,
+ uint32_t Offset) const {
+ if (Section <= 0)
+ return 0;
+
+ auto Dbi = getDbiStreamPtr(*Pdb);
+ if (!Dbi)
+ return 0;
+
+ uint32_t MaxSection = Dbi->getSectionHeaders().size();
+ if (Section > MaxSection + 1)
+ Section = MaxSection + 1;
+ auto &Sec = Dbi->getSectionHeaders()[Section - 1];
+ return Sec.VirtualAddress + Offset;
+}
+
+uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
+ uint32_t Offset) const {
+ return LoadAddress + getRVAFromSectOffset(Section, Offset);
+}
+
+bool NativeSession::moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const {
+ ModuleIndex = 0;
+ auto Iter = AddrToModuleIndex.find(VA);
+ if (Iter == AddrToModuleIndex.end())
+ return false;
+ ModuleIndex = Iter.value();
+ return true;
+}
+
+bool NativeSession::moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
+ uint16_t &ModuleIndex) const {
+ ModuleIndex = 0;
+ auto Iter = AddrToModuleIndex.find(getVAFromSectOffset(Sect, Offset));
+ if (Iter == AddrToModuleIndex.end())
+ return false;
+ ModuleIndex = Iter.value();
+ return true;
+}
+
+void NativeSession::parseSectionContribs() {
+ auto Dbi = Pdb->getPDBDbiStream();
+ if (!Dbi)
+ return;
+
+ class Visitor : public ISectionContribVisitor {
+ NativeSession &Session;
+ IMap &AddrMap;
+
+ public:
+ Visitor(NativeSession &Session, IMap &AddrMap)
+ : Session(Session), AddrMap(AddrMap) {}
+ void visit(const SectionContrib &C) override {
+ if (C.Size == 0)
+ return;
+
+ uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
+ uint64_t End = VA + C.Size;
+
+ // Ignore overlapping sections based on the assumption that a valid
+ // PDB file should not have overlaps.
+ if (!AddrMap.overlaps(VA, End))
+ AddrMap.insert(VA, End, C.Imod);
+ }
+ void visit(const SectionContrib2 &C) override { visit(C.Base); }
+ };
+
+ Visitor V(*this, AddrToModuleIndex);
+ Dbi->visitSectionContributions(V);
+}
+
+Expected<ModuleDebugStreamRef>
+NativeSession::getModuleDebugStream(uint32_t Index) const {
+ auto *Dbi = getDbiStreamPtr(*Pdb);
+ assert(Dbi && "Dbi stream not present");
+
+ DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
+
+ uint16_t ModiStream = Modi.getModuleStreamIndex();
+ if (ModiStream == kInvalidStreamIndex)
+ return make_error<RawError>("Module stream not present");
+
+ std::unique_ptr<msf::MappedBlockStream> ModStreamData =
+ Pdb->createIndexedStream(ModiStream);
+
+ ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+ if (auto EC = ModS.reload())
+ return std::move(EC);
+
+ return std::move(ModS);
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp
new file mode 100644
index 0000000000..fd813dee6b
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp
@@ -0,0 +1,47 @@
+//===- NativeSourceFile.cpp - Native line number implementation -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeSourceFile::NativeSourceFile(NativeSession &Session, uint32_t FileId,
+ const codeview::FileChecksumEntry &Checksum)
+ : Session(Session), FileId(FileId), Checksum(Checksum) {}
+
+std::string NativeSourceFile::getFileName() const {
+ auto ST = Session.getPDBFile().getStringTable();
+ if (!ST) {
+ consumeError(ST.takeError());
+ return "";
+ }
+ auto FileName = ST->getStringTable().getString(Checksum.FileNameOffset);
+ if (!FileName) {
+ consumeError(FileName.takeError());
+ return "";
+ }
+
+ return std::string(FileName.get());
+}
+
+uint32_t NativeSourceFile::getUniqueId() const { return FileId; }
+
+std::string NativeSourceFile::getChecksum() const {
+ return toStringRef(Checksum.Checksum).str();
+}
+
+PDB_Checksum NativeSourceFile::getChecksumType() const {
+ return static_cast<PDB_Checksum>(Checksum.Kind);
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+NativeSourceFile::getCompilands() const {
+ return nullptr;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
new file mode 100644
index 0000000000..e5f1dcaf80
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp
@@ -0,0 +1,124 @@
+//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeSymbolEnumerator::NativeSymbolEnumerator(
+ NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent,
+ codeview::EnumeratorRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent),
+ Record(std::move(Record)) {}
+
+NativeSymbolEnumerator::~NativeSymbolEnumerator() {}
+
+void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
+ PdbSymbolIdField::ClassParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolIdField(OS, "lexicalParentId", getLexicalParentId(), Indent,
+ Session, PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "dataKind", getDataKind(), Indent);
+ dumpSymbolField(OS, "locationType", getLocationType(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+ dumpSymbolField(OS, "value", getValue(), Indent);
+}
+
+SymIndexId NativeSymbolEnumerator::getClassParentId() const {
+ return Parent.getSymIndexId();
+}
+
+SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; }
+
+std::string NativeSymbolEnumerator::getName() const {
+ return std::string(Record.Name);
+}
+
+SymIndexId NativeSymbolEnumerator::getTypeId() const {
+ return Parent.getTypeId();
+}
+
+PDB_DataKind NativeSymbolEnumerator::getDataKind() const {
+ return PDB_DataKind::Constant;
+}
+
+PDB_LocType NativeSymbolEnumerator::getLocationType() const {
+ return PDB_LocType::Constant;
+}
+
+bool NativeSymbolEnumerator::isConstType() const { return false; }
+
+bool NativeSymbolEnumerator::isVolatileType() const { return false; }
+
+bool NativeSymbolEnumerator::isUnalignedType() const { return false; }
+
+Variant NativeSymbolEnumerator::getValue() const {
+ const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType();
+
+ switch (BT.getBuiltinType()) {
+ case PDB_BuiltinType::Int:
+ case PDB_BuiltinType::Long:
+ case PDB_BuiltinType::Char: {
+ assert(Record.Value.isSignedIntN(BT.getLength() * 8));
+ int64_t N = Record.Value.getSExtValue();
+ switch (BT.getLength()) {
+ case 1:
+ return Variant{static_cast<int8_t>(N)};
+ case 2:
+ return Variant{static_cast<int16_t>(N)};
+ case 4:
+ return Variant{static_cast<int32_t>(N)};
+ case 8:
+ return Variant{static_cast<int64_t>(N)};
+ }
+ break;
+ }
+ case PDB_BuiltinType::UInt:
+ case PDB_BuiltinType::ULong: {
+ assert(Record.Value.isIntN(BT.getLength() * 8));
+ uint64_t U = Record.Value.getZExtValue();
+ switch (BT.getLength()) {
+ case 1:
+ return Variant{static_cast<uint8_t>(U)};
+ case 2:
+ return Variant{static_cast<uint16_t>(U)};
+ case 4:
+ return Variant{static_cast<uint32_t>(U)};
+ case 8:
+ return Variant{static_cast<uint64_t>(U)};
+ }
+ break;
+ }
+ case PDB_BuiltinType::Bool: {
+ assert(Record.Value.isIntN(BT.getLength() * 8));
+ uint64_t U = Record.Value.getZExtValue();
+ return Variant{static_cast<bool>(U)};
+ }
+ default:
+ assert(false && "Invalid enumeration type");
+ break;
+ }
+
+ return Variant{Record.Value.getSExtValue()};
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
new file mode 100644
index 0000000000..63ac9fae0e
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp
@@ -0,0 +1,66 @@
+//===- NativeTypeArray.cpp - info about arrays ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeArray::NativeTypeArray(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI,
+ codeview::ArrayRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::ArrayType, Id), Record(Record),
+ Index(TI) {}
+NativeTypeArray::~NativeTypeArray() {}
+
+void NativeTypeArray::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolField(OS, "arrayIndexTypeId", getArrayIndexTypeId(), Indent);
+ dumpSymbolIdField(OS, "elementTypeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "count", getCount(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+SymIndexId NativeTypeArray::getArrayIndexTypeId() const {
+ return Session.getSymbolCache().findSymbolByTypeIndex(Record.getIndexType());
+}
+
+bool NativeTypeArray::isConstType() const { return false; }
+
+bool NativeTypeArray::isUnalignedType() const { return false; }
+
+bool NativeTypeArray::isVolatileType() const { return false; }
+
+uint32_t NativeTypeArray::getCount() const {
+ NativeRawSymbol &Element =
+ Session.getSymbolCache().getNativeSymbolById(getTypeId());
+ return getLength() / Element.getLength();
+}
+
+SymIndexId NativeTypeArray::getTypeId() const {
+ return Session.getSymbolCache().findSymbolByTypeIndex(
+ Record.getElementType());
+}
+
+uint64_t NativeTypeArray::getLength() const { return Record.Size; }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
new file mode 100644
index 0000000000..a08663aa91
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp
@@ -0,0 +1,46 @@
+//===- NativeTypeBuiltin.cpp -------------------------------------- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id,
+ ModifierOptions Mods, PDB_BuiltinType T,
+ uint64_t L)
+ : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id),
+ Session(PDBSession), Mods(Mods), Type(T), Length(L) {}
+
+NativeTypeBuiltin::~NativeTypeBuiltin() {}
+
+void NativeTypeBuiltin::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {}
+
+PDB_SymType NativeTypeBuiltin::getSymTag() const {
+ return PDB_SymType::BuiltinType;
+}
+
+PDB_BuiltinType NativeTypeBuiltin::getBuiltinType() const { return Type; }
+
+bool NativeTypeBuiltin::isConstType() const {
+ return (Mods & ModifierOptions::Const) != ModifierOptions::None;
+}
+
+uint64_t NativeTypeBuiltin::getLength() const { return Length; }
+
+bool NativeTypeBuiltin::isUnalignedType() const {
+ return (Mods & ModifierOptions::Unaligned) != ModifierOptions::None;
+}
+
+bool NativeTypeBuiltin::isVolatileType() const {
+ return (Mods & ModifierOptions::Volatile) != ModifierOptions::None;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
new file mode 100644
index 0000000000..aaec3a5e7c
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp
@@ -0,0 +1,381 @@
+//===- NativeTypeEnum.cpp - info about enum type ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+#include "llvm/Support/FormatVariadic.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+// Yea, this is a pretty terrible class name. But if we have an enum:
+//
+// enum Foo {
+// A,
+// B
+// };
+//
+// then A and B are the "enumerators" of the "enum" Foo. And we need
+// to enumerate them.
+class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks {
+public:
+ NativeEnumEnumEnumerators(NativeSession &Session,
+ const NativeTypeEnum &ClassParent);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+
+private:
+ Error visitKnownMember(CVMemberRecord &CVM,
+ EnumeratorRecord &Record) override;
+ Error visitKnownMember(CVMemberRecord &CVM,
+ ListContinuationRecord &Record) override;
+
+ NativeSession &Session;
+ const NativeTypeEnum &ClassParent;
+ std::vector<EnumeratorRecord> Enumerators;
+ Optional<TypeIndex> ContinuationIndex;
+ uint32_t Index = 0;
+};
+} // namespace
+
+NativeEnumEnumEnumerators::NativeEnumEnumEnumerators(
+ NativeSession &Session, const NativeTypeEnum &ClassParent)
+ : Session(Session), ClassParent(ClassParent) {
+ TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+ LazyRandomTypeCollection &Types = Tpi.typeCollection();
+
+ ContinuationIndex = ClassParent.getEnumRecord().FieldList;
+ while (ContinuationIndex) {
+ CVType FieldList = Types.getType(*ContinuationIndex);
+ assert(FieldList.kind() == LF_FIELDLIST);
+ ContinuationIndex.reset();
+ cantFail(visitMemberRecordStream(FieldList.data(), *this));
+ }
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM,
+ EnumeratorRecord &Record) {
+ Enumerators.push_back(Record);
+ return Error::success();
+}
+
+Error NativeEnumEnumEnumerators::visitKnownMember(
+ CVMemberRecord &CVM, ListContinuationRecord &Record) {
+ ContinuationIndex = Record.ContinuationIndex;
+ return Error::success();
+}
+
+uint32_t NativeEnumEnumEnumerators::getChildCount() const {
+ return Enumerators.size();
+}
+
+std::unique_ptr<PDBSymbol>
+NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const {
+ if (Index >= getChildCount())
+ return nullptr;
+
+ SymIndexId Id = Session.getSymbolCache()
+ .getOrCreateFieldListMember<NativeSymbolEnumerator>(
+ ClassParent.getEnumRecord().FieldList, Index,
+ ClassParent, Enumerators[Index]);
+ return Session.getSymbolCache().getSymbolById(Id);
+}
+
+std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() {
+ if (Index >= getChildCount())
+ return nullptr;
+
+ return getChildAtIndex(Index++);
+}
+
+void NativeEnumEnumEnumerators::reset() { Index = 0; }
+
+NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
+ TypeIndex Index, EnumRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index),
+ Record(std::move(Record)) {}
+
+NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id,
+ NativeTypeEnum &UnmodifiedType,
+ codeview::ModifierRecord Modifier)
+ : NativeRawSymbol(Session, PDB_SymType::Enum, Id),
+ UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeEnum::~NativeTypeEnum() {}
+
+void NativeTypeEnum::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()),
+ Indent);
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ if (Modifiers.hasValue())
+ dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+ Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
+ dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
+ dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
+ dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
+ dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
+ dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
+ dumpSymbolField(OS, "nested", isNested(), Indent);
+ dumpSymbolField(OS, "packed", isPacked(), Indent);
+ dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
+ dumpSymbolField(OS, "scoped", isScoped(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeTypeEnum::findChildren(PDB_SymType Type) const {
+ if (Type != PDB_SymType::Data)
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+
+ const NativeTypeEnum *ClassParent = nullptr;
+ if (!Modifiers)
+ ClassParent = this;
+ else
+ ClassParent = UnmodifiedType;
+ return std::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent);
+}
+
+PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; }
+
+PDB_BuiltinType NativeTypeEnum::getBuiltinType() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getBuiltinType();
+
+ Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType());
+
+ codeview::TypeIndex Underlying = Record->getUnderlyingType();
+
+ // This indicates a corrupt record.
+ if (!Underlying.isSimple() ||
+ Underlying.getSimpleMode() != SimpleTypeMode::Direct) {
+ return PDB_BuiltinType::None;
+ }
+
+ switch (Underlying.getSimpleKind()) {
+ case SimpleTypeKind::Boolean128:
+ case SimpleTypeKind::Boolean64:
+ case SimpleTypeKind::Boolean32:
+ case SimpleTypeKind::Boolean16:
+ case SimpleTypeKind::Boolean8:
+ return PDB_BuiltinType::Bool;
+ case SimpleTypeKind::NarrowCharacter:
+ case SimpleTypeKind::UnsignedCharacter:
+ case SimpleTypeKind::SignedCharacter:
+ return PDB_BuiltinType::Char;
+ case SimpleTypeKind::WideCharacter:
+ return PDB_BuiltinType::WCharT;
+ case SimpleTypeKind::Character16:
+ return PDB_BuiltinType::Char16;
+ case SimpleTypeKind::Character32:
+ return PDB_BuiltinType::Char32;
+ case SimpleTypeKind::Int128:
+ case SimpleTypeKind::Int128Oct:
+ case SimpleTypeKind::Int16:
+ case SimpleTypeKind::Int16Short:
+ case SimpleTypeKind::Int32:
+ case SimpleTypeKind::Int32Long:
+ case SimpleTypeKind::Int64:
+ case SimpleTypeKind::Int64Quad:
+ return PDB_BuiltinType::Int;
+ case SimpleTypeKind::UInt128:
+ case SimpleTypeKind::UInt128Oct:
+ case SimpleTypeKind::UInt16:
+ case SimpleTypeKind::UInt16Short:
+ case SimpleTypeKind::UInt32:
+ case SimpleTypeKind::UInt32Long:
+ case SimpleTypeKind::UInt64:
+ case SimpleTypeKind::UInt64Quad:
+ return PDB_BuiltinType::UInt;
+ case SimpleTypeKind::HResult:
+ return PDB_BuiltinType::HResult;
+ case SimpleTypeKind::Complex16:
+ case SimpleTypeKind::Complex32:
+ case SimpleTypeKind::Complex32PartialPrecision:
+ case SimpleTypeKind::Complex64:
+ case SimpleTypeKind::Complex80:
+ case SimpleTypeKind::Complex128:
+ return PDB_BuiltinType::Complex;
+ case SimpleTypeKind::Float16:
+ case SimpleTypeKind::Float32:
+ case SimpleTypeKind::Float32PartialPrecision:
+ case SimpleTypeKind::Float48:
+ case SimpleTypeKind::Float64:
+ case SimpleTypeKind::Float80:
+ case SimpleTypeKind::Float128:
+ return PDB_BuiltinType::Float;
+ default:
+ return PDB_BuiltinType::None;
+ }
+ llvm_unreachable("Unreachable");
+}
+
+SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const {
+ return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0;
+}
+
+bool NativeTypeEnum::hasConstructor() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasConstructor();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasConstructorOrDestructor);
+}
+
+bool NativeTypeEnum::hasAssignmentOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasAssignmentOperator();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasOverloadedAssignmentOperator);
+}
+
+bool NativeTypeEnum::hasNestedTypes() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasNestedTypes();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::ContainsNestedClass);
+}
+
+bool NativeTypeEnum::isIntrinsic() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isIntrinsic();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic);
+}
+
+bool NativeTypeEnum::hasCastOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasCastOperator();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasConversionOperator);
+}
+
+uint64_t NativeTypeEnum::getLength() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getLength();
+
+ const auto Id = Session.getSymbolCache().findSymbolByTypeIndex(
+ Record->getUnderlyingType());
+ const auto UnderlyingType =
+ Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id);
+ return UnderlyingType ? UnderlyingType->getLength() : 0;
+}
+
+std::string NativeTypeEnum::getName() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getName();
+
+ return std::string(Record->getName());
+}
+
+bool NativeTypeEnum::isNested() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isNested();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Nested);
+}
+
+bool NativeTypeEnum::hasOverloadedOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasOverloadedOperator();
+
+ return bool(Record->getOptions() &
+ codeview::ClassOptions::HasOverloadedOperator);
+}
+
+bool NativeTypeEnum::isPacked() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isPacked();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Packed);
+}
+
+bool NativeTypeEnum::isScoped() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isScoped();
+
+ return bool(Record->getOptions() & codeview::ClassOptions::Scoped);
+}
+
+SymIndexId NativeTypeEnum::getTypeId() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getTypeId();
+
+ return Session.getSymbolCache().findSymbolByTypeIndex(
+ Record->getUnderlyingType());
+}
+
+bool NativeTypeEnum::isRefUdt() const { return false; }
+
+bool NativeTypeEnum::isValueUdt() const { return false; }
+
+bool NativeTypeEnum::isInterfaceUdt() const { return false; }
+
+bool NativeTypeEnum::isConstType() const {
+ if (!Modifiers)
+ return false;
+ return ((Modifiers->getModifiers() & ModifierOptions::Const) !=
+ ModifierOptions::None);
+}
+
+bool NativeTypeEnum::isVolatileType() const {
+ if (!Modifiers)
+ return false;
+ return ((Modifiers->getModifiers() & ModifierOptions::Volatile) !=
+ ModifierOptions::None);
+}
+
+bool NativeTypeEnum::isUnalignedType() const {
+ if (!Modifiers)
+ return false;
+ return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) !=
+ ModifierOptions::None);
+}
+
+const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getUnderlyingBuiltinType();
+
+ return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>(
+ getTypeId());
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
new file mode 100644
index 0000000000..f98a4c3043
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp
@@ -0,0 +1,199 @@
+//===- NativeTypeFunctionSig.cpp - info about function signature -*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+// This is kind of a silly class, hence why we keep it private to the file.
+// It's only purpose is to wrap the real type record. I guess this is so that
+// we can have the lexical parent point to the function instead of the global
+// scope.
+class NativeTypeFunctionArg : public NativeRawSymbol {
+public:
+ NativeTypeFunctionArg(NativeSession &Session,
+ std::unique_ptr<PDBSymbol> RealType)
+ : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0),
+ RealType(std::move(RealType)) {}
+
+ void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const override {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ }
+
+ SymIndexId getTypeId() const override { return RealType->getSymIndexId(); }
+
+ std::unique_ptr<PDBSymbol> RealType;
+};
+
+class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> {
+public:
+ NativeEnumFunctionArgs(NativeSession &Session,
+ std::unique_ptr<NativeEnumTypes> TypeEnumerator)
+ : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {}
+
+ uint32_t getChildCount() const override {
+ return TypeEnumerator->getChildCount();
+ }
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
+ return wrap(TypeEnumerator->getChildAtIndex(Index));
+ }
+ std::unique_ptr<PDBSymbol> getNext() override {
+ return wrap(TypeEnumerator->getNext());
+ }
+
+ void reset() override { TypeEnumerator->reset(); }
+
+private:
+ std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const {
+ if (!S)
+ return nullptr;
+ auto NTFA = std::make_unique<NativeTypeFunctionArg>(Session, std::move(S));
+ return PDBSymbol::create(Session, std::move(NTFA));
+ }
+ NativeSession &Session;
+ std::unique_ptr<NativeEnumTypes> TypeEnumerator;
+};
+} // namespace
+
+NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session,
+ SymIndexId Id,
+ codeview::TypeIndex Index,
+ codeview::ProcedureRecord Proc)
+ : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
+ Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {}
+
+NativeTypeFunctionSig::NativeTypeFunctionSig(
+ NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index,
+ codeview::MemberFunctionRecord MemberFunc)
+ : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
+ MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {}
+
+void NativeTypeFunctionSig::initialize() {
+ if (IsMemberFunction) {
+ ClassParentId =
+ Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType);
+ initializeArgList(MemberFunc.ArgumentList);
+ } else {
+ initializeArgList(Proc.ArgumentList);
+ }
+}
+
+NativeTypeFunctionSig::~NativeTypeFunctionSig() {}
+
+void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) {
+ TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
+ CVType CVT = Tpi.typeCollection().getType(ArgListTI);
+
+ cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(CVT, ArgList));
+}
+
+void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+
+ dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent);
+ dumpSymbolField(OS, "count", getCount(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ if (IsMemberFunction)
+ dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent);
+ dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(),
+ Indent);
+ dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+NativeTypeFunctionSig::findChildren(PDB_SymType Type) const {
+ if (Type != PDB_SymType::FunctionArg)
+ return std::make_unique<NullEnumerator<PDBSymbol>>();
+
+ auto NET = std::make_unique<NativeEnumTypes>(Session,
+ /* copy */ ArgList.ArgIndices);
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumFunctionArgs(Session, std::move(NET)));
+}
+
+SymIndexId NativeTypeFunctionSig::getClassParentId() const {
+ if (!IsMemberFunction)
+ return 0;
+
+ return ClassParentId;
+}
+
+PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const {
+ return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv;
+}
+
+uint32_t NativeTypeFunctionSig::getCount() const {
+ return IsMemberFunction ? (1 + MemberFunc.getParameterCount())
+ : Proc.getParameterCount();
+}
+
+SymIndexId NativeTypeFunctionSig::getTypeId() const {
+ TypeIndex ReturnTI =
+ IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType();
+
+ SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI);
+ return Result;
+}
+
+int32_t NativeTypeFunctionSig::getThisAdjust() const {
+ return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0;
+}
+
+bool NativeTypeFunctionSig::hasConstructor() const {
+ if (!IsMemberFunction)
+ return false;
+
+ return (MemberFunc.getOptions() & FunctionOptions::Constructor) !=
+ FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isConstType() const { return false; }
+
+bool NativeTypeFunctionSig::isConstructorVirtualBase() const {
+ if (!IsMemberFunction)
+ return false;
+
+ return (MemberFunc.getOptions() &
+ FunctionOptions::ConstructorWithVirtualBases) !=
+ FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isCxxReturnUdt() const {
+ FunctionOptions Options =
+ IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions();
+ return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None;
+}
+
+bool NativeTypeFunctionSig::isUnalignedType() const { return false; }
+
+bool NativeTypeFunctionSig::isVolatileType() const { return false; }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
new file mode 100644
index 0000000000..32dcfc2359
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp
@@ -0,0 +1,193 @@
+//===- NativeTypePointer.cpp - info about pointer type ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI)
+ : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI) {
+ assert(TI.isSimple());
+ assert(TI.getSimpleMode() != SimpleTypeMode::Direct);
+}
+
+NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI,
+ codeview::PointerRecord Record)
+ : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI),
+ Record(std::move(Record)) {}
+
+NativeTypePointer::~NativeTypePointer() {}
+
+void NativeTypePointer::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ if (isMemberPointer()) {
+ dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
+ PdbSymbolIdField::ClassParent, ShowIdFields,
+ RecurseIdFields);
+ }
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "isPointerToDataMember", isPointerToDataMember(), Indent);
+ dumpSymbolField(OS, "isPointerToMemberFunction", isPointerToMemberFunction(),
+ Indent);
+ dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent);
+ dumpSymbolField(OS, "reference", isReference(), Indent);
+ dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent);
+ if (isMemberPointer()) {
+ if (isSingleInheritance())
+ dumpSymbolField(OS, "isSingleInheritance", 1, Indent);
+ else if (isMultipleInheritance())
+ dumpSymbolField(OS, "isMultipleInheritance", 1, Indent);
+ else if (isVirtualInheritance())
+ dumpSymbolField(OS, "isVirtualInheritance", 1, Indent);
+ }
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+SymIndexId NativeTypePointer::getClassParentId() const {
+ if (!isMemberPointer())
+ return 0;
+
+ assert(Record);
+ const MemberPointerInfo &MPI = Record->getMemberInfo();
+ return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType);
+}
+
+uint64_t NativeTypePointer::getLength() const {
+ if (Record)
+ return Record->getSize();
+
+ switch (TI.getSimpleMode()) {
+ case SimpleTypeMode::NearPointer:
+ case SimpleTypeMode::FarPointer:
+ case SimpleTypeMode::HugePointer:
+ return 2;
+ case SimpleTypeMode::NearPointer32:
+ case SimpleTypeMode::FarPointer32:
+ return 4;
+ case SimpleTypeMode::NearPointer64:
+ return 8;
+ case SimpleTypeMode::NearPointer128:
+ return 16;
+ default:
+ assert(false && "invalid simple type mode!");
+ }
+ return 0;
+}
+
+SymIndexId NativeTypePointer::getTypeId() const {
+ // This is the pointee SymIndexId.
+ TypeIndex Referent = Record ? Record->ReferentType : TI.makeDirect();
+
+ return Session.getSymbolCache().findSymbolByTypeIndex(Referent);
+}
+
+bool NativeTypePointer::isReference() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::LValueReference;
+}
+
+bool NativeTypePointer::isRValueReference() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::RValueReference;
+}
+
+bool NativeTypePointer::isPointerToDataMember() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::PointerToDataMember;
+}
+
+bool NativeTypePointer::isPointerToMemberFunction() const {
+ if (!Record)
+ return false;
+ return Record->getMode() == PointerMode::PointerToMemberFunction;
+}
+
+bool NativeTypePointer::isConstType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Const) != PointerOptions::None;
+}
+
+bool NativeTypePointer::isRestrictedType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Restrict) !=
+ PointerOptions::None;
+}
+
+bool NativeTypePointer::isVolatileType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Volatile) !=
+ PointerOptions::None;
+}
+
+bool NativeTypePointer::isUnalignedType() const {
+ if (!Record)
+ return false;
+ return (Record->getOptions() & PointerOptions::Unaligned) !=
+ PointerOptions::None;
+}
+
+static inline bool isInheritanceKind(const MemberPointerInfo &MPI,
+ PointerToMemberRepresentation P1,
+ PointerToMemberRepresentation P2) {
+ return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2);
+}
+
+bool NativeTypePointer::isSingleInheritance() const {
+ if (!isMemberPointer())
+ return false;
+ return isInheritanceKind(
+ Record->getMemberInfo(),
+ PointerToMemberRepresentation::SingleInheritanceData,
+ PointerToMemberRepresentation::SingleInheritanceFunction);
+}
+
+bool NativeTypePointer::isMultipleInheritance() const {
+ if (!isMemberPointer())
+ return false;
+ return isInheritanceKind(
+ Record->getMemberInfo(),
+ PointerToMemberRepresentation::MultipleInheritanceData,
+ PointerToMemberRepresentation::MultipleInheritanceFunction);
+}
+
+bool NativeTypePointer::isVirtualInheritance() const {
+ if (!isMemberPointer())
+ return false;
+ return isInheritanceKind(
+ Record->getMemberInfo(),
+ PointerToMemberRepresentation::VirtualInheritanceData,
+ PointerToMemberRepresentation::VirtualInheritanceFunction);
+}
+
+bool NativeTypePointer::isMemberPointer() const {
+ return isPointerToDataMember() || isPointerToMemberFunction();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp
new file mode 100644
index 0000000000..72964a9e0d
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp
@@ -0,0 +1,29 @@
+#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeTypedef::NativeTypeTypedef(NativeSession &Session, SymIndexId Id,
+ codeview::UDTSym Typedef)
+ : NativeRawSymbol(Session, PDB_SymType::Typedef, Id),
+ Record(std::move(Typedef)) {}
+
+NativeTypeTypedef::~NativeTypeTypedef() {}
+
+void NativeTypeTypedef::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
+ PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
+}
+
+std::string NativeTypeTypedef::getName() const {
+ return std::string(Record.Name);
+}
+
+SymIndexId NativeTypeTypedef::getTypeId() const {
+ return Session.getSymbolCache().findSymbolByTypeIndex(Record.Type);
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
new file mode 100644
index 0000000000..917ec14e58
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp
@@ -0,0 +1,220 @@
+//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+#include <cassert>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI, codeview::ClassRecord CR)
+ : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+ Class(std::move(CR)), Tag(Class.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI, codeview::UnionRecord UR)
+ : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI),
+ Union(std::move(UR)), Tag(Union.getPointer()) {}
+
+NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id,
+ NativeTypeUDT &UnmodifiedType,
+ codeview::ModifierRecord Modifier)
+ : NativeRawSymbol(Session, PDB_SymType::UDT, Id),
+ UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {}
+
+NativeTypeUDT::~NativeTypeUDT() {}
+
+void NativeTypeUDT::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolField(OS, "name", getName(), Indent);
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ if (Modifiers.hasValue())
+ dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent,
+ Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields,
+ RecurseIdFields);
+ if (getUdtKind() != PDB_UdtType::Union)
+ dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(),
+ Indent);
+ dumpSymbolField(OS, "length", getLength(), Indent);
+ dumpSymbolField(OS, "udtKind", getUdtKind(), Indent);
+ dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent);
+ dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent);
+ dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent);
+ dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent);
+ dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent);
+ dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent);
+ dumpSymbolField(OS, "nested", isNested(), Indent);
+ dumpSymbolField(OS, "packed", isPacked(), Indent);
+ dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent);
+ dumpSymbolField(OS, "scoped", isScoped(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+std::string NativeTypeUDT::getName() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getName();
+
+ return std::string(Tag->getName());
+}
+
+SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; }
+
+SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getSymIndexId();
+
+ return 0;
+}
+
+SymIndexId NativeTypeUDT::getVirtualTableShapeId() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getVirtualTableShapeId();
+
+ if (Class)
+ return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape);
+
+ return 0;
+}
+
+uint64_t NativeTypeUDT::getLength() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getLength();
+
+ if (Class)
+ return Class->getSize();
+
+ return Union->getSize();
+}
+
+PDB_UdtType NativeTypeUDT::getUdtKind() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->getUdtKind();
+
+ switch (Tag->Kind) {
+ case TypeRecordKind::Class:
+ return PDB_UdtType::Class;
+ case TypeRecordKind::Union:
+ return PDB_UdtType::Union;
+ case TypeRecordKind::Struct:
+ return PDB_UdtType::Struct;
+ case TypeRecordKind::Interface:
+ return PDB_UdtType::Interface;
+ default:
+ llvm_unreachable("Unexpected udt kind");
+ }
+}
+
+bool NativeTypeUDT::hasConstructor() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasConstructor();
+
+ return (Tag->Options & ClassOptions::HasConstructorOrDestructor) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::isConstType() const {
+ if (!Modifiers)
+ return false;
+ return (Modifiers->Modifiers & ModifierOptions::Const) !=
+ ModifierOptions::None;
+}
+
+bool NativeTypeUDT::hasAssignmentOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasAssignmentOperator();
+
+ return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasCastOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasCastOperator();
+
+ return (Tag->Options & ClassOptions::HasConversionOperator) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasNestedTypes() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasNestedTypes();
+
+ return (Tag->Options & ClassOptions::ContainsNestedClass) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::hasOverloadedOperator() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->hasOverloadedOperator();
+
+ return (Tag->Options & ClassOptions::HasOverloadedOperator) !=
+ ClassOptions::None;
+}
+
+bool NativeTypeUDT::isInterfaceUdt() const { return false; }
+
+bool NativeTypeUDT::isIntrinsic() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isIntrinsic();
+
+ return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isNested() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isNested();
+
+ return (Tag->Options & ClassOptions::Nested) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isPacked() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isPacked();
+
+ return (Tag->Options & ClassOptions::Packed) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isRefUdt() const { return false; }
+
+bool NativeTypeUDT::isScoped() const {
+ if (UnmodifiedType)
+ return UnmodifiedType->isScoped();
+
+ return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None;
+}
+
+bool NativeTypeUDT::isValueUdt() const { return false; }
+
+bool NativeTypeUDT::isUnalignedType() const {
+ if (!Modifiers)
+ return false;
+ return (Modifiers->Modifiers & ModifierOptions::Unaligned) !=
+ ModifierOptions::None;
+}
+
+bool NativeTypeUDT::isVolatileType() const {
+ if (!Modifiers)
+ return false;
+ return (Modifiers->Modifiers & ModifierOptions::Volatile) !=
+ ModifierOptions::None;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
new file mode 100644
index 0000000000..837fe19ec8
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp
@@ -0,0 +1,35 @@
+#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+// Create a pointer record for a non-simple type.
+NativeTypeVTShape::NativeTypeVTShape(NativeSession &Session, SymIndexId Id,
+ codeview::TypeIndex TI,
+ codeview::VFTableShapeRecord SR)
+ : NativeRawSymbol(Session, PDB_SymType::VTableShape, Id), TI(TI),
+ Record(std::move(SR)) {}
+
+NativeTypeVTShape::~NativeTypeVTShape() {}
+
+void NativeTypeVTShape::dump(raw_ostream &OS, int Indent,
+ PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const {
+ NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+
+ dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
+ PdbSymbolIdField::LexicalParent, ShowIdFields,
+ RecurseIdFields);
+ dumpSymbolField(OS, "count", getCount(), Indent);
+ dumpSymbolField(OS, "constType", isConstType(), Indent);
+ dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
+ dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
+}
+
+bool NativeTypeVTShape::isConstType() const { return false; }
+
+bool NativeTypeVTShape::isVolatileType() const { return false; }
+
+bool NativeTypeVTShape::isUnalignedType() const { return false; }
+
+uint32_t NativeTypeVTShape::getCount() const { return Record.Slots.size(); }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFile.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFile.cpp
new file mode 100644
index 0000000000..5c61530c47
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -0,0 +1,508 @@
+//===- PDBFile.cpp - Low level interface to a PDB file ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+namespace {
+typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
+} // end anonymous namespace
+
+PDBFile::PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer,
+ BumpPtrAllocator &Allocator)
+ : FilePath(std::string(Path)), Allocator(Allocator),
+ Buffer(std::move(PdbFileBuffer)) {}
+
+PDBFile::~PDBFile() = default;
+
+StringRef PDBFile::getFilePath() const { return FilePath; }
+
+StringRef PDBFile::getFileDirectory() const {
+ return sys::path::parent_path(FilePath);
+}
+
+uint32_t PDBFile::getBlockSize() const { return ContainerLayout.SB->BlockSize; }
+
+uint32_t PDBFile::getFreeBlockMapBlock() const {
+ return ContainerLayout.SB->FreeBlockMapBlock;
+}
+
+uint32_t PDBFile::getBlockCount() const {
+ return ContainerLayout.SB->NumBlocks;
+}
+
+uint32_t PDBFile::getNumDirectoryBytes() const {
+ return ContainerLayout.SB->NumDirectoryBytes;
+}
+
+uint32_t PDBFile::getBlockMapIndex() const {
+ return ContainerLayout.SB->BlockMapAddr;
+}
+
+uint32_t PDBFile::getUnknown1() const { return ContainerLayout.SB->Unknown1; }
+
+uint32_t PDBFile::getNumDirectoryBlocks() const {
+ return msf::bytesToBlocks(ContainerLayout.SB->NumDirectoryBytes,
+ ContainerLayout.SB->BlockSize);
+}
+
+uint64_t PDBFile::getBlockMapOffset() const {
+ return (uint64_t)ContainerLayout.SB->BlockMapAddr *
+ ContainerLayout.SB->BlockSize;
+}
+
+uint32_t PDBFile::getNumStreams() const {
+ return ContainerLayout.StreamSizes.size();
+}
+
+uint32_t PDBFile::getMaxStreamSize() const {
+ return *std::max_element(ContainerLayout.StreamSizes.begin(),
+ ContainerLayout.StreamSizes.end());
+}
+
+uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
+ return ContainerLayout.StreamSizes[StreamIndex];
+}
+
+ArrayRef<support::ulittle32_t>
+PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
+ return ContainerLayout.StreamMap[StreamIndex];
+}
+
+uint64_t PDBFile::getFileSize() const { return Buffer->getLength(); }
+
+Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
+ uint32_t NumBytes) const {
+ uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
+
+ ArrayRef<uint8_t> Result;
+ if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result))
+ return std::move(EC);
+ return Result;
+}
+
+Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
+ ArrayRef<uint8_t> Data) const {
+ return make_error<RawError>(raw_error_code::not_writable,
+ "PDBFile is immutable");
+}
+
+Error PDBFile::parseFileHeaders() {
+ BinaryStreamReader Reader(*Buffer);
+
+ // Initialize SB.
+ const msf::SuperBlock *SB = nullptr;
+ if (auto EC = Reader.readObject(SB)) {
+ consumeError(std::move(EC));
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "MSF superblock is missing");
+ }
+
+ if (auto EC = msf::validateSuperBlock(*SB))
+ return EC;
+
+ if (Buffer->getLength() % SB->BlockSize != 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "File size is not a multiple of block size");
+ ContainerLayout.SB = SB;
+
+ // Initialize Free Page Map.
+ ContainerLayout.FreePageMap.resize(SB->NumBlocks);
+ // The Fpm exists either at block 1 or block 2 of the MSF. However, this
+ // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and
+ // thusly an equal number of total blocks in the file. For a block size
+ // of 4KiB (very common), this would yield 32KiB total blocks in file, for a
+ // maximum file size of 32KiB * 4KiB = 128MiB. Obviously this won't do, so
+ // the Fpm is split across the file at `getBlockSize()` intervals. As a
+ // result, every block whose index is of the form |{1,2} + getBlockSize() * k|
+ // for any non-negative integer k is an Fpm block. In theory, we only really
+ // need to reserve blocks of the form |{1,2} + getBlockSize() * 8 * k|, but
+ // current versions of the MSF format already expect the Fpm to be arranged
+ // at getBlockSize() intervals, so we have to be compatible.
+ // See the function fpmPn() for more information:
+ // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
+ auto FpmStream =
+ MappedBlockStream::createFpmStream(ContainerLayout, *Buffer, Allocator);
+ BinaryStreamReader FpmReader(*FpmStream);
+ ArrayRef<uint8_t> FpmBytes;
+ if (auto EC = FpmReader.readBytes(FpmBytes, FpmReader.bytesRemaining()))
+ return EC;
+ uint32_t BlocksRemaining = getBlockCount();
+ uint32_t BI = 0;
+ for (auto Byte : FpmBytes) {
+ uint32_t BlocksThisByte = std::min(BlocksRemaining, 8U);
+ for (uint32_t I = 0; I < BlocksThisByte; ++I) {
+ if (Byte & (1 << I))
+ ContainerLayout.FreePageMap[BI] = true;
+ --BlocksRemaining;
+ ++BI;
+ }
+ }
+
+ Reader.setOffset(getBlockMapOffset());
+ if (auto EC = Reader.readArray(ContainerLayout.DirectoryBlocks,
+ getNumDirectoryBlocks()))
+ return EC;
+
+ return Error::success();
+}
+
+Error PDBFile::parseStreamData() {
+ assert(ContainerLayout.SB);
+ if (DirectoryStream)
+ return Error::success();
+
+ uint32_t NumStreams = 0;
+
+ // Normally you can't use a MappedBlockStream without having fully parsed the
+ // PDB file, because it accesses the directory and various other things, which
+ // is exactly what we are attempting to parse. By specifying a custom
+ // subclass of IPDBStreamData which only accesses the fields that have already
+ // been parsed, we can avoid this and reuse MappedBlockStream.
+ auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer,
+ Allocator);
+ BinaryStreamReader Reader(*DS);
+ if (auto EC = Reader.readInteger(NumStreams))
+ return EC;
+
+ if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
+ return EC;
+ for (uint32_t I = 0; I < NumStreams; ++I) {
+ uint32_t StreamSize = getStreamByteSize(I);
+ // FIXME: What does StreamSize ~0U mean?
+ uint64_t NumExpectedStreamBlocks =
+ StreamSize == UINT32_MAX
+ ? 0
+ : msf::bytesToBlocks(StreamSize, ContainerLayout.SB->BlockSize);
+
+ // For convenience, we store the block array contiguously. This is because
+ // if someone calls setStreamMap(), it is more convenient to be able to call
+ // it with an ArrayRef instead of setting up a StreamRef. Since the
+ // DirectoryStream is cached in the class and thus lives for the life of the
+ // class, we can be guaranteed that readArray() will return a stable
+ // reference, even if it has to allocate from its internal pool.
+ ArrayRef<support::ulittle32_t> Blocks;
+ if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
+ return EC;
+ for (uint32_t Block : Blocks) {
+ uint64_t BlockEndOffset =
+ (uint64_t)(Block + 1) * ContainerLayout.SB->BlockSize;
+ if (BlockEndOffset > getFileSize())
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Stream block map is corrupt.");
+ }
+ ContainerLayout.StreamMap.push_back(Blocks);
+ }
+
+ // We should have read exactly SB->NumDirectoryBytes bytes.
+ assert(Reader.bytesRemaining() == 0);
+ DirectoryStream = std::move(DS);
+ return Error::success();
+}
+
+ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
+ return ContainerLayout.DirectoryBlocks;
+}
+
+std::unique_ptr<MappedBlockStream>
+PDBFile::createIndexedStream(uint16_t SN) const {
+ if (SN == kInvalidStreamIndex)
+ return nullptr;
+ return MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, SN,
+ Allocator);
+}
+
+MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const {
+ MSFStreamLayout Result;
+ auto Blocks = getStreamBlockList(StreamIdx);
+ Result.Blocks.assign(Blocks.begin(), Blocks.end());
+ Result.Length = getStreamByteSize(StreamIdx);
+ return Result;
+}
+
+msf::MSFStreamLayout PDBFile::getFpmStreamLayout() const {
+ return msf::getFpmStreamLayout(ContainerLayout);
+}
+
+Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
+ if (!Globals) {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return DbiS.takeError();
+
+ auto GlobalS =
+ safelyCreateIndexedStream(DbiS->getGlobalSymbolStreamIndex());
+ if (!GlobalS)
+ return GlobalS.takeError();
+ auto TempGlobals = std::make_unique<GlobalsStream>(std::move(*GlobalS));
+ if (auto EC = TempGlobals->reload())
+ return std::move(EC);
+ Globals = std::move(TempGlobals);
+ }
+ return *Globals;
+}
+
+Expected<InfoStream &> PDBFile::getPDBInfoStream() {
+ if (!Info) {
+ auto InfoS = safelyCreateIndexedStream(StreamPDB);
+ if (!InfoS)
+ return InfoS.takeError();
+ auto TempInfo = std::make_unique<InfoStream>(std::move(*InfoS));
+ if (auto EC = TempInfo->reload())
+ return std::move(EC);
+ Info = std::move(TempInfo);
+ }
+ return *Info;
+}
+
+Expected<DbiStream &> PDBFile::getPDBDbiStream() {
+ if (!Dbi) {
+ auto DbiS = safelyCreateIndexedStream(StreamDBI);
+ if (!DbiS)
+ return DbiS.takeError();
+ auto TempDbi = std::make_unique<DbiStream>(std::move(*DbiS));
+ if (auto EC = TempDbi->reload(this))
+ return std::move(EC);
+ Dbi = std::move(TempDbi);
+ }
+ return *Dbi;
+}
+
+Expected<TpiStream &> PDBFile::getPDBTpiStream() {
+ if (!Tpi) {
+ auto TpiS = safelyCreateIndexedStream(StreamTPI);
+ if (!TpiS)
+ return TpiS.takeError();
+ auto TempTpi = std::make_unique<TpiStream>(*this, std::move(*TpiS));
+ if (auto EC = TempTpi->reload())
+ return std::move(EC);
+ Tpi = std::move(TempTpi);
+ }
+ return *Tpi;
+}
+
+Expected<TpiStream &> PDBFile::getPDBIpiStream() {
+ if (!Ipi) {
+ if (!hasPDBIpiStream())
+ return make_error<RawError>(raw_error_code::no_stream);
+
+ auto IpiS = safelyCreateIndexedStream(StreamIPI);
+ if (!IpiS)
+ return IpiS.takeError();
+ auto TempIpi = std::make_unique<TpiStream>(*this, std::move(*IpiS));
+ if (auto EC = TempIpi->reload())
+ return std::move(EC);
+ Ipi = std::move(TempIpi);
+ }
+ return *Ipi;
+}
+
+Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
+ if (!Publics) {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return DbiS.takeError();
+
+ auto PublicS =
+ safelyCreateIndexedStream(DbiS->getPublicSymbolStreamIndex());
+ if (!PublicS)
+ return PublicS.takeError();
+ auto TempPublics = std::make_unique<PublicsStream>(std::move(*PublicS));
+ if (auto EC = TempPublics->reload())
+ return std::move(EC);
+ Publics = std::move(TempPublics);
+ }
+ return *Publics;
+}
+
+Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
+ if (!Symbols) {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return DbiS.takeError();
+
+ uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
+ auto SymbolS = safelyCreateIndexedStream(SymbolStreamNum);
+ if (!SymbolS)
+ return SymbolS.takeError();
+
+ auto TempSymbols = std::make_unique<SymbolStream>(std::move(*SymbolS));
+ if (auto EC = TempSymbols->reload())
+ return std::move(EC);
+ Symbols = std::move(TempSymbols);
+ }
+ return *Symbols;
+}
+
+Expected<PDBStringTable &> PDBFile::getStringTable() {
+ if (!Strings) {
+ auto NS = safelyCreateNamedStream("/names");
+ if (!NS)
+ return NS.takeError();
+
+ auto N = std::make_unique<PDBStringTable>();
+ BinaryStreamReader Reader(**NS);
+ if (auto EC = N->reload(Reader))
+ return std::move(EC);
+ assert(Reader.bytesRemaining() == 0);
+ StringTableStream = std::move(*NS);
+ Strings = std::move(N);
+ }
+ return *Strings;
+}
+
+Expected<InjectedSourceStream &> PDBFile::getInjectedSourceStream() {
+ if (!InjectedSources) {
+ auto IJS = safelyCreateNamedStream("/src/headerblock");
+ if (!IJS)
+ return IJS.takeError();
+
+ auto Strings = getStringTable();
+ if (!Strings)
+ return Strings.takeError();
+
+ auto IJ = std::make_unique<InjectedSourceStream>(std::move(*IJS));
+ if (auto EC = IJ->reload(*Strings))
+ return std::move(EC);
+ InjectedSources = std::move(IJ);
+ }
+ return *InjectedSources;
+}
+
+uint32_t PDBFile::getPointerSize() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return 0;
+ PDB_Machine Machine = DbiS->getMachineType();
+ if (Machine == PDB_Machine::Amd64)
+ return 8;
+ return 4;
+}
+
+bool PDBFile::hasPDBDbiStream() const {
+ return StreamDBI < getNumStreams() && getStreamByteSize(StreamDBI) > 0;
+}
+
+bool PDBFile::hasPDBGlobalsStream() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS) {
+ consumeError(DbiS.takeError());
+ return false;
+ }
+
+ return DbiS->getGlobalSymbolStreamIndex() < getNumStreams();
+}
+
+bool PDBFile::hasPDBInfoStream() const { return StreamPDB < getNumStreams(); }
+
+bool PDBFile::hasPDBIpiStream() const {
+ if (!hasPDBInfoStream())
+ return false;
+
+ if (StreamIPI >= getNumStreams())
+ return false;
+
+ auto &InfoStream = cantFail(const_cast<PDBFile *>(this)->getPDBInfoStream());
+ return InfoStream.containsIdStream();
+}
+
+bool PDBFile::hasPDBPublicsStream() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS) {
+ consumeError(DbiS.takeError());
+ return false;
+ }
+ return DbiS->getPublicSymbolStreamIndex() < getNumStreams();
+}
+
+bool PDBFile::hasPDBSymbolStream() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return false;
+ return DbiS->getSymRecordStreamIndex() < getNumStreams();
+}
+
+bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); }
+
+bool PDBFile::hasPDBStringTable() {
+ auto IS = getPDBInfoStream();
+ if (!IS)
+ return false;
+ Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex("/names");
+ if (!ExpectedNSI) {
+ consumeError(ExpectedNSI.takeError());
+ return false;
+ }
+ assert(*ExpectedNSI < getNumStreams());
+ return true;
+}
+
+bool PDBFile::hasPDBInjectedSourceStream() {
+ auto IS = getPDBInfoStream();
+ if (!IS)
+ return false;
+ Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex("/src/headerblock");
+ if (!ExpectedNSI) {
+ consumeError(ExpectedNSI.takeError());
+ return false;
+ }
+ assert(*ExpectedNSI < getNumStreams());
+ return true;
+}
+
+/// Wrapper around MappedBlockStream::createIndexedStream() that checks if a
+/// stream with that index actually exists. If it does not, the return value
+/// will have an MSFError with code msf_error_code::no_stream. Else, the return
+/// value will contain the stream returned by createIndexedStream().
+Expected<std::unique_ptr<MappedBlockStream>>
+PDBFile::safelyCreateIndexedStream(uint32_t StreamIndex) const {
+ if (StreamIndex >= getNumStreams())
+ // This rejects kInvalidStreamIndex with an error as well.
+ return make_error<RawError>(raw_error_code::no_stream);
+ return createIndexedStream(StreamIndex);
+}
+
+Expected<std::unique_ptr<MappedBlockStream>>
+PDBFile::safelyCreateNamedStream(StringRef Name) {
+ auto IS = getPDBInfoStream();
+ if (!IS)
+ return IS.takeError();
+
+ Expected<uint32_t> ExpectedNSI = IS->getNamedStreamIndex(Name);
+ if (!ExpectedNSI)
+ return ExpectedNSI.takeError();
+ uint32_t NameStreamIndex = *ExpectedNSI;
+
+ return safelyCreateIndexedStream(NameStreamIndex);
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
new file mode 100644
index 0000000000..f33125474e
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -0,0 +1,355 @@
+//===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/CRC.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/xxhash.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
+ : Allocator(Allocator), InjectedSourceHashTraits(Strings),
+ InjectedSourceTable(2) {}
+
+PDBFileBuilder::~PDBFileBuilder() {}
+
+Error PDBFileBuilder::initialize(uint32_t BlockSize) {
+ auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
+ if (!ExpectedMsf)
+ return ExpectedMsf.takeError();
+ Msf = std::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
+ return Error::success();
+}
+
+MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
+
+InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
+ if (!Info)
+ Info = std::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
+ return *Info;
+}
+
+DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
+ if (!Dbi)
+ Dbi = std::make_unique<DbiStreamBuilder>(*Msf);
+ return *Dbi;
+}
+
+TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
+ if (!Tpi)
+ Tpi = std::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
+ return *Tpi;
+}
+
+TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
+ if (!Ipi)
+ Ipi = std::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
+ return *Ipi;
+}
+
+PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
+ return Strings;
+}
+
+GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
+ if (!Gsi)
+ Gsi = std::make_unique<GSIStreamBuilder>(*Msf);
+ return *Gsi;
+}
+
+Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
+ uint32_t Size) {
+ auto ExpectedStream = Msf->addStream(Size);
+ if (ExpectedStream)
+ NamedStreams.set(Name, *ExpectedStream);
+ return ExpectedStream;
+}
+
+Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) {
+ Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size());
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ assert(NamedStreamData.count(*ExpectedIndex) == 0);
+ NamedStreamData[*ExpectedIndex] = std::string(Data);
+ return Error::success();
+}
+
+void PDBFileBuilder::addInjectedSource(StringRef Name,
+ std::unique_ptr<MemoryBuffer> Buffer) {
+ // Stream names must be exact matches, since they get looked up in a hash
+ // table and the hash value is dependent on the exact contents of the string.
+ // link.exe lowercases a path and converts / to \, so we must do the same.
+ SmallString<64> VName;
+ sys::path::native(Name.lower(), VName, sys::path::Style::windows_backslash);
+
+ uint32_t NI = getStringTableBuilder().insert(Name);
+ uint32_t VNI = getStringTableBuilder().insert(VName);
+
+ InjectedSourceDescriptor Desc;
+ Desc.Content = std::move(Buffer);
+ Desc.NameIndex = NI;
+ Desc.VNameIndex = VNI;
+ Desc.StreamName = "/src/files/";
+
+ Desc.StreamName += VName;
+
+ InjectedSources.push_back(std::move(Desc));
+}
+
+Error PDBFileBuilder::finalizeMsfLayout() {
+
+ if (Ipi && Ipi->getRecordCount() > 0) {
+ // In theory newer PDBs always have an ID stream, but by saying that we're
+ // only going to *really* have an ID stream if there is at least one ID
+ // record, we leave open the opportunity to test older PDBs such as those
+ // that don't have an ID stream.
+ auto &Info = getInfoBuilder();
+ Info.addFeature(PdbRaw_FeatureSig::VC140);
+ }
+
+ uint32_t StringsLen = Strings.calculateSerializedSize();
+
+ Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
+ if (!SN)
+ return SN.takeError();
+
+ if (Gsi) {
+ if (auto EC = Gsi->finalizeMsfLayout())
+ return EC;
+ if (Dbi) {
+ Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
+ Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
+ Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIndex());
+ }
+ }
+ if (Tpi) {
+ if (auto EC = Tpi->finalizeMsfLayout())
+ return EC;
+ }
+ if (Dbi) {
+ if (auto EC = Dbi->finalizeMsfLayout())
+ return EC;
+ }
+ SN = allocateNamedStream("/names", StringsLen);
+ if (!SN)
+ return SN.takeError();
+
+ if (Ipi) {
+ if (auto EC = Ipi->finalizeMsfLayout())
+ return EC;
+ }
+
+ // Do this last, since it relies on the named stream map being complete, and
+ // that can be updated by previous steps in the finalization.
+ if (Info) {
+ if (auto EC = Info->finalizeMsfLayout())
+ return EC;
+ }
+
+ if (!InjectedSources.empty()) {
+ for (const auto &IS : InjectedSources) {
+ JamCRC CRC(0);
+ CRC.update(arrayRefFromStringRef(IS.Content->getBuffer()));
+
+ SrcHeaderBlockEntry Entry;
+ ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
+ Entry.Size = sizeof(SrcHeaderBlockEntry);
+ Entry.FileSize = IS.Content->getBufferSize();
+ Entry.FileNI = IS.NameIndex;
+ Entry.VFileNI = IS.VNameIndex;
+ Entry.ObjNI = 1;
+ Entry.IsVirtual = 0;
+ Entry.Version =
+ static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+ Entry.CRC = CRC.getCRC();
+ StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex);
+ InjectedSourceTable.set_as(VName, std::move(Entry),
+ InjectedSourceHashTraits);
+ }
+
+ uint32_t SrcHeaderBlockSize =
+ sizeof(SrcHeaderBlockHeader) +
+ InjectedSourceTable.calculateSerializedLength();
+ SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
+ if (!SN)
+ return SN.takeError();
+ for (const auto &IS : InjectedSources) {
+ SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
+ if (!SN)
+ return SN.takeError();
+ }
+ }
+
+ // Do this last, since it relies on the named stream map being complete, and
+ // that can be updated by previous steps in the finalization.
+ if (Info) {
+ if (auto EC = Info->finalizeMsfLayout())
+ return EC;
+ }
+
+ return Error::success();
+}
+
+Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
+ uint32_t SN = 0;
+ if (!NamedStreams.get(Name, SN))
+ return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
+ return SN;
+}
+
+void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
+ const msf::MSFLayout &Layout) {
+ assert(!InjectedSourceTable.empty());
+
+ uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock"));
+ auto Stream = WritableMappedBlockStream::createIndexedStream(
+ Layout, MsfBuffer, SN, Allocator);
+ BinaryStreamWriter Writer(*Stream);
+
+ SrcHeaderBlockHeader Header;
+ ::memset(&Header, 0, sizeof(Header));
+ Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+ Header.Size = Writer.bytesRemaining();
+
+ cantFail(Writer.writeObject(Header));
+ cantFail(InjectedSourceTable.commit(Writer));
+
+ assert(Writer.bytesRemaining() == 0);
+}
+
+void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
+ const msf::MSFLayout &Layout) {
+ if (InjectedSourceTable.empty())
+ return;
+
+ commitSrcHeaderBlock(MsfBuffer, Layout);
+
+ for (const auto &IS : InjectedSources) {
+ uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName));
+
+ auto SourceStream = WritableMappedBlockStream::createIndexedStream(
+ Layout, MsfBuffer, SN, Allocator);
+ BinaryStreamWriter SourceWriter(*SourceStream);
+ assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
+ cantFail(SourceWriter.writeBytes(
+ arrayRefFromStringRef(IS.Content->getBuffer())));
+ }
+}
+
+Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
+ assert(!Filename.empty());
+ if (auto EC = finalizeMsfLayout())
+ return EC;
+
+ MSFLayout Layout;
+ Expected<FileBufferByteStream> ExpectedMsfBuffer =
+ Msf->commit(Filename, Layout);
+ if (!ExpectedMsfBuffer)
+ return ExpectedMsfBuffer.takeError();
+ FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
+
+ auto ExpectedSN = getNamedStreamIndex("/names");
+ if (!ExpectedSN)
+ return ExpectedSN.takeError();
+
+ auto NS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, *ExpectedSN, Allocator);
+ BinaryStreamWriter NSWriter(*NS);
+ if (auto EC = Strings.commit(NSWriter))
+ return EC;
+
+ for (const auto &NSE : NamedStreamData) {
+ if (NSE.second.empty())
+ continue;
+
+ auto NS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, NSE.first, Allocator);
+ BinaryStreamWriter NSW(*NS);
+ if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second)))
+ return EC;
+ }
+
+ if (Info) {
+ if (auto EC = Info->commit(Layout, Buffer))
+ return EC;
+ }
+
+ if (Dbi) {
+ if (auto EC = Dbi->commit(Layout, Buffer))
+ return EC;
+ }
+
+ if (Tpi) {
+ if (auto EC = Tpi->commit(Layout, Buffer))
+ return EC;
+ }
+
+ if (Ipi) {
+ if (auto EC = Ipi->commit(Layout, Buffer))
+ return EC;
+ }
+
+ if (Gsi) {
+ if (auto EC = Gsi->commit(Layout, Buffer))
+ return EC;
+ }
+
+ auto InfoStreamBlocks = Layout.StreamMap[StreamPDB];
+ assert(!InfoStreamBlocks.empty());
+ uint64_t InfoStreamFileOffset =
+ blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
+ InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
+ Buffer.getBufferStart() + InfoStreamFileOffset);
+
+ commitInjectedSources(Buffer, Layout);
+
+ // Set the build id at the very end, after every other byte of the PDB
+ // has been written.
+ if (Info->hashPDBContentsToGUID()) {
+ // Compute a hash of all sections of the output file.
+ uint64_t Digest =
+ xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()});
+
+ H->Age = 1;
+
+ memcpy(H->Guid.Guid, &Digest, 8);
+ // xxhash only gives us 8 bytes, so put some fixed data in the other half.
+ memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
+
+ // Put the hash in the Signature field too.
+ H->Signature = static_cast<uint32_t>(Digest);
+
+ // Return GUID to caller.
+ memcpy(Guid, H->Guid.Guid, 16);
+ } else {
+ H->Age = Info->getAge();
+ H->Guid = Info->getGuid();
+ Optional<uint32_t> Sig = Info->getSignature();
+ H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
+ }
+
+ return Buffer.commit();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
new file mode 100644
index 0000000000..2be1656e06
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
@@ -0,0 +1,140 @@
+//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; }
+uint32_t PDBStringTable::getNameCount() const { return NameCount; }
+uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }
+uint32_t PDBStringTable::getSignature() const { return Header->Signature; }
+
+Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {
+ if (auto EC = Reader.readObject(Header))
+ return EC;
+
+ if (Header->Signature != PDBStringTableSignature)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid hash table signature");
+ if (Header->HashVersion != 1 && Header->HashVersion != 2)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Unsupported hash version");
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
+ BinaryStreamRef Stream;
+ if (auto EC = Reader.readStreamRef(Stream))
+ return EC;
+
+ if (auto EC = Strings.initialize(Stream)) {
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid hash table byte length"));
+ }
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+const codeview::DebugStringTableSubsectionRef &
+PDBStringTable::getStringTable() const {
+ return Strings;
+}
+
+Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {
+ const support::ulittle32_t *HashCount;
+ if (auto EC = Reader.readObject(HashCount))
+ return EC;
+
+ if (auto EC = Reader.readArray(IDs, *HashCount)) {
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read bucket array"));
+ }
+
+ return Error::success();
+}
+
+Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {
+ if (auto EC = Reader.readInteger(NameCount))
+ return EC;
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTable::reload(BinaryStreamReader &Reader) {
+
+ BinaryStreamReader SectionReader;
+
+ std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));
+ if (auto EC = readHeader(SectionReader))
+ return EC;
+
+ std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);
+ if (auto EC = readStrings(SectionReader))
+ return EC;
+
+ // We don't know how long the hash table is until we parse it, so let the
+ // function responsible for doing that figure it out.
+ if (auto EC = readHashTable(Reader))
+ return EC;
+
+ std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));
+ if (auto EC = readEpilogue(SectionReader))
+ return EC;
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {
+ return Strings.getString(ID);
+}
+
+Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {
+ uint32_t Hash =
+ (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);
+ size_t Count = IDs.size();
+ uint32_t Start = Hash % Count;
+ for (size_t I = 0; I < Count; ++I) {
+ // The hash is just a starting point for the search, but if it
+ // doesn't work we should find the string no matter what, because
+ // we iterate the entire array.
+ uint32_t Index = (Start + I) % Count;
+
+ // If we find 0, it means the item isn't in the hash table.
+ uint32_t ID = IDs[Index];
+ if (ID == 0)
+ return make_error<RawError>(raw_error_code::no_entry);
+ auto ExpectedStr = getStringForID(ID);
+ if (!ExpectedStr)
+ return ExpectedStr.takeError();
+
+ if (*ExpectedStr == Str)
+ return ID;
+ }
+ return make_error<RawError>(raw_error_code::no_entry);
+}
+
+FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {
+ return IDs;
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
new file mode 100644
index 0000000000..f7f36901e4
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
@@ -0,0 +1,229 @@
+//===- PDBStringTableBuilder.cpp - PDB String Table -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+
+#include <map>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::support::endian;
+using namespace llvm::pdb;
+
+StringTableHashTraits::StringTableHashTraits(PDBStringTableBuilder &Table)
+ : Table(&Table) {}
+
+uint32_t StringTableHashTraits::hashLookupKey(StringRef S) const {
+ // The reference implementation doesn't include code for /src/headerblock
+ // handling, but it can only read natvis entries lld's PDB files if
+ // this hash function truncates the hash to 16 bit.
+ // PDB/include/misc.h in the reference implementation has a hashSz() function
+ // that returns an unsigned short, that seems what's being used for
+ // /src/headerblock.
+ return static_cast<uint16_t>(Table->getIdForString(S));
+}
+
+StringRef StringTableHashTraits::storageKeyToLookupKey(uint32_t Offset) const {
+ return Table->getStringForId(Offset);
+}
+
+uint32_t StringTableHashTraits::lookupKeyToStorageKey(StringRef S) {
+ return Table->insert(S);
+}
+
+uint32_t PDBStringTableBuilder::insert(StringRef S) {
+ return Strings.insert(S);
+}
+
+uint32_t PDBStringTableBuilder::getIdForString(StringRef S) const {
+ return Strings.getIdForString(S);
+}
+
+StringRef PDBStringTableBuilder::getStringForId(uint32_t Id) const {
+ return Strings.getStringForId(Id);
+}
+
+static uint32_t computeBucketCount(uint32_t NumStrings) {
+ // This is a precomputed list of Buckets given the specified number of
+ // strings. Matching the reference algorithm exactly is not strictly
+ // necessary for correctness, but it helps when comparing LLD's PDBs with
+ // Microsoft's PDBs so as to eliminate superfluous differences.
+ // The reference implementation does (in nmt.h, NMT::grow()):
+ // unsigned StringCount = 0;
+ // unsigned BucketCount = 1;
+ // fn insert() {
+ // ++StringCount;
+ // if (BucketCount * 3 / 4 < StringCount)
+ // BucketCount = BucketCount * 3 / 2 + 1;
+ // }
+ // This list contains all StringCount, BucketCount pairs where BucketCount was
+ // just incremented. It ends before the first BucketCount entry where
+ // BucketCount * 3 would overflow a 32-bit unsigned int.
+ static std::map<uint32_t, uint32_t> StringsToBuckets = {
+ {0, 1},
+ {1, 2},
+ {2, 4},
+ {4, 7},
+ {6, 11},
+ {9, 17},
+ {13, 26},
+ {20, 40},
+ {31, 61},
+ {46, 92},
+ {70, 139},
+ {105, 209},
+ {157, 314},
+ {236, 472},
+ {355, 709},
+ {532, 1064},
+ {799, 1597},
+ {1198, 2396},
+ {1798, 3595},
+ {2697, 5393},
+ {4045, 8090},
+ {6068, 12136},
+ {9103, 18205},
+ {13654, 27308},
+ {20482, 40963},
+ {30723, 61445},
+ {46084, 92168},
+ {69127, 138253},
+ {103690, 207380},
+ {155536, 311071},
+ {233304, 466607},
+ {349956, 699911},
+ {524934, 1049867},
+ {787401, 1574801},
+ {1181101, 2362202},
+ {1771652, 3543304},
+ {2657479, 5314957},
+ {3986218, 7972436},
+ {5979328, 11958655},
+ {8968992, 17937983},
+ {13453488, 26906975},
+ {20180232, 40360463},
+ {30270348, 60540695},
+ {45405522, 90811043},
+ {68108283, 136216565},
+ {102162424, 204324848},
+ {153243637, 306487273},
+ {229865455, 459730910},
+ {344798183, 689596366},
+ {517197275, 1034394550},
+ {775795913, 1551591826},
+ {1163693870, 2327387740}};
+ auto Entry = StringsToBuckets.lower_bound(NumStrings);
+ assert(Entry != StringsToBuckets.end());
+ return Entry->second;
+}
+
+uint32_t PDBStringTableBuilder::calculateHashTableSize() const {
+ uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field.
+ Size += sizeof(uint32_t) * computeBucketCount(Strings.size());
+
+ return Size;
+}
+
+uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
+ uint32_t Size = 0;
+ Size += sizeof(PDBStringTableHeader);
+ Size += Strings.calculateSerializedSize();
+ Size += calculateHashTableSize();
+ Size += sizeof(uint32_t); // The /names stream ends with the string count.
+ return Size;
+}
+
+void PDBStringTableBuilder::setStrings(
+ const codeview::DebugStringTableSubsection &Strings) {
+ this->Strings = Strings;
+}
+
+Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
+ // Write a header
+ PDBStringTableHeader H;
+ H.Signature = PDBStringTableSignature;
+ H.HashVersion = 1;
+ H.ByteSize = Strings.calculateSerializedSize();
+ if (auto EC = Writer.writeObject(H))
+ return EC;
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const {
+ if (auto EC = Strings.commit(Writer))
+ return EC;
+
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
+ // Write a hash table.
+ uint32_t BucketCount = computeBucketCount(Strings.size());
+ if (auto EC = Writer.writeInteger(BucketCount))
+ return EC;
+ std::vector<ulittle32_t> Buckets(BucketCount);
+
+ for (auto &Pair : Strings) {
+ StringRef S = Pair.getKey();
+ uint32_t Offset = Pair.getValue();
+ uint32_t Hash = hashStringV1(S);
+
+ for (uint32_t I = 0; I != BucketCount; ++I) {
+ uint32_t Slot = (Hash + I) % BucketCount;
+ if (Buckets[Slot] != 0)
+ continue;
+ Buckets[Slot] = Offset;
+ break;
+ }
+ }
+
+ if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
+ return EC;
+
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const {
+ if (auto EC = Writer.writeInteger<uint32_t>(Strings.size()))
+ return EC;
+ assert(Writer.bytesRemaining() == 0);
+ return Error::success();
+}
+
+Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
+ BinaryStreamWriter SectionWriter;
+
+ std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader));
+ if (auto EC = writeHeader(SectionWriter))
+ return EC;
+
+ std::tie(SectionWriter, Writer) =
+ Writer.split(Strings.calculateSerializedSize());
+ if (auto EC = writeStrings(SectionWriter))
+ return EC;
+
+ std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize());
+ if (auto EC = writeHashTable(SectionWriter))
+ return EC;
+
+ std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t));
+ if (auto EC = writeEpilogue(SectionWriter))
+ return EC;
+
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PublicsStream.cpp
new file mode 100644
index 0000000000..a33bf03bf8
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/PublicsStream.cpp
@@ -0,0 +1,101 @@
+//===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The data structures defined in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+//
+// When you are reading the reference source code, you'd find the
+// information below useful.
+//
+// - ppdb1->m_fMinimalDbgInfo seems to be always true.
+// - SMALLBUCKETS macro is defined.
+//
+// The reference doesn't compile, so I learned just by reading code.
+// It's not guaranteed to be correct.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+PublicsStream::PublicsStream(std::unique_ptr<MappedBlockStream> Stream)
+ : Stream(std::move(Stream)) {}
+
+PublicsStream::~PublicsStream() = default;
+
+uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
+uint16_t PublicsStream::getThunkTableSection() const {
+ return Header->ISectThunkTable;
+}
+uint32_t PublicsStream::getThunkTableOffset() const {
+ return Header->OffThunkTable;
+}
+
+// Publics stream contains fixed-size headers and a serialized hash table.
+// This implementation is not complete yet. It reads till the end of the
+// stream so that we verify the stream is at least not corrupted. However,
+// we skip over the hash table which we believe contains information about
+// public symbols.
+Error PublicsStream::reload() {
+ BinaryStreamReader Reader(*Stream);
+
+ // Check stream size.
+ if (Reader.bytesRemaining() <
+ sizeof(PublicsStreamHeader) + sizeof(GSIHashHeader))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Publics Stream does not contain a header.");
+
+ // Read PSGSIHDR struct.
+ if (Reader.readObject(Header))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Publics Stream does not contain a header.");
+
+ // Read the hash table.
+ if (auto E = PublicsTable.read(Reader))
+ return E;
+
+ // Something called "address map" follows.
+ uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
+ if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read an address map."));
+
+ // Something called "thunk map" follows.
+ if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a thunk map."));
+
+ // Something called "section map" follows.
+ if (Reader.bytesRemaining() > 0) {
+ if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a section map."));
+ }
+
+ if (Reader.bytesRemaining() > 0)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Corrupted publics stream.");
+ return Error::success();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/RawError.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/RawError.cpp
new file mode 100644
index 0000000000..ed6cf08396
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/RawError.cpp
@@ -0,0 +1,53 @@
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+namespace {
+// FIXME: This class is only here to support the transition to llvm::Error. It
+// will be removed once this transition is complete. Clients should prefer to
+// deal with the Error value directly, rather than converting to error_code.
+class RawErrorCategory : public std::error_category {
+public:
+ const char *name() const noexcept override { return "llvm.pdb.raw"; }
+ std::string message(int Condition) const override {
+ switch (static_cast<raw_error_code>(Condition)) {
+ case raw_error_code::unspecified:
+ return "An unknown error has occurred.";
+ case raw_error_code::feature_unsupported:
+ return "The feature is unsupported by the implementation.";
+ case raw_error_code::invalid_format:
+ return "The record is in an unexpected format.";
+ case raw_error_code::corrupt_file:
+ return "The PDB file is corrupt.";
+ case raw_error_code::insufficient_buffer:
+ return "The buffer is not large enough to read the requested number of "
+ "bytes.";
+ case raw_error_code::no_stream:
+ return "The specified stream could not be loaded.";
+ case raw_error_code::index_out_of_bounds:
+ return "The specified item does not exist in the array.";
+ case raw_error_code::invalid_block_address:
+ return "The specified block address is not valid.";
+ case raw_error_code::duplicate_entry:
+ return "The entry already exists.";
+ case raw_error_code::no_entry:
+ return "The entry does not exist.";
+ case raw_error_code::not_writable:
+ return "The PDB does not support writing.";
+ case raw_error_code::stream_too_long:
+ return "The stream was longer than expected.";
+ case raw_error_code::invalid_tpi_hash:
+ return "The Type record has an invalid hash value.";
+ }
+ llvm_unreachable("Unrecognized raw_error_code");
+ }
+};
+} // namespace
+
+static llvm::ManagedStatic<RawErrorCategory> RawCategory;
+const std::error_category &llvm::pdb::RawErrCategory() { return *RawCategory; }
+
+char RawError::ID;
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolCache.cpp
new file mode 100644
index 0000000000..f9e6701447
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -0,0 +1,633 @@
+#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
+
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
+// to instantiate a NativeBuiltinSymbol for that type.
+static const struct BuiltinTypeEntry {
+ codeview::SimpleTypeKind Kind;
+ PDB_BuiltinType Type;
+ uint32_t Size;
+} BuiltinTypes[] = {
+ {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
+ {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
+ {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
+ {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
+ {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
+ {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
+ {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
+ {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
+ {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
+ {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
+ {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
+ {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
+ {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
+ {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
+ {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
+ {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
+ {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
+ {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
+ {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
+ {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
+ {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
+ // This table can be grown as necessary, but these are the only types we've
+ // needed so far.
+};
+
+SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
+ : Session(Session), Dbi(Dbi) {
+ // Id 0 is reserved for the invalid symbol.
+ Cache.push_back(nullptr);
+ SourceFiles.push_back(nullptr);
+
+ if (Dbi)
+ Compilands.resize(Dbi->modules().getModuleCount());
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
+ return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
+ auto Tpi = Session.getPDBFile().getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return nullptr;
+ }
+ auto &Types = Tpi->typeCollection();
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumTypes(Session, Types, std::move(Kinds)));
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new NativeEnumGlobals(Session, {Kind}));
+}
+
+SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
+ ModifierOptions Mods) const {
+ if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
+ return createSymbol<NativeTypePointer>(Index);
+
+ const auto Kind = Index.getSimpleKind();
+ const auto It =
+ llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) {
+ return Builtin.Kind == Kind;
+ });
+ if (It == std::end(BuiltinTypes))
+ return 0;
+ return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
+}
+
+SymIndexId
+SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
+ codeview::CVType CVT) const {
+ ModifierRecord Record;
+ if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
+ consumeError(std::move(EC));
+ return 0;
+ }
+
+ if (Record.ModifiedType.isSimple())
+ return createSimpleType(Record.ModifiedType, Record.Modifiers);
+
+ // Make sure we create and cache a record for the unmodified type.
+ SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
+ NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
+
+ switch (UnmodifiedNRS.getSymTag()) {
+ case PDB_SymType::Enum:
+ return createSymbol<NativeTypeEnum>(
+ static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
+ case PDB_SymType::UDT:
+ return createSymbol<NativeTypeUDT>(
+ static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
+ default:
+ // No other types can be modified. (LF_POINTER, for example, records
+ // its modifiers a different way.
+ assert(false && "Invalid LF_MODIFIER record");
+ break;
+ }
+ return 0;
+}
+
+SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
+ // First see if it's already in our cache.
+ const auto Entry = TypeIndexToSymbolId.find(Index);
+ if (Entry != TypeIndexToSymbolId.end())
+ return Entry->second;
+
+ // Symbols for built-in types are created on the fly.
+ if (Index.isSimple()) {
+ SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
+ assert(TypeIndexToSymbolId.count(Index) == 0);
+ TypeIndexToSymbolId[Index] = Result;
+ return Result;
+ }
+
+ // We need to instantiate and cache the desired type symbol.
+ auto Tpi = Session.getPDBFile().getPDBTpiStream();
+ if (!Tpi) {
+ consumeError(Tpi.takeError());
+ return 0;
+ }
+ codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
+ codeview::CVType CVT = Types.getType(Index);
+
+ if (isUdtForwardRef(CVT)) {
+ Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
+
+ if (!EFD)
+ consumeError(EFD.takeError());
+ else if (*EFD != Index) {
+ assert(!isUdtForwardRef(Types.getType(*EFD)));
+ SymIndexId Result = findSymbolByTypeIndex(*EFD);
+ // Record a mapping from ForwardRef -> SymIndex of complete type so that
+ // we'll take the fast path next time.
+ assert(TypeIndexToSymbolId.count(Index) == 0);
+ TypeIndexToSymbolId[Index] = Result;
+ return Result;
+ }
+ }
+
+ // At this point if we still have a forward ref udt it means the full decl was
+ // not in the PDB. We just have to deal with it and use the forward ref.
+ SymIndexId Id = 0;
+ switch (CVT.kind()) {
+ case codeview::LF_ENUM:
+ Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
+ break;
+ case codeview::LF_ARRAY:
+ Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
+ std::move(CVT));
+ break;
+ case codeview::LF_CLASS:
+ case codeview::LF_STRUCTURE:
+ case codeview::LF_INTERFACE:
+ Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
+ break;
+ case codeview::LF_UNION:
+ Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
+ break;
+ case codeview::LF_POINTER:
+ Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
+ std::move(CVT));
+ break;
+ case codeview::LF_MODIFIER:
+ Id = createSymbolForModifiedType(Index, std::move(CVT));
+ break;
+ case codeview::LF_PROCEDURE:
+ Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
+ Index, std::move(CVT));
+ break;
+ case codeview::LF_MFUNCTION:
+ Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
+ Index, std::move(CVT));
+ break;
+ case codeview::LF_VTSHAPE:
+ Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
+ Index, std::move(CVT));
+ break;
+ default:
+ Id = createSymbolPlaceholder();
+ break;
+ }
+ if (Id != 0) {
+ assert(TypeIndexToSymbolId.count(Index) == 0);
+ TypeIndexToSymbolId[Index] = Id;
+ }
+ return Id;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::getSymbolById(SymIndexId SymbolId) const {
+ assert(SymbolId < Cache.size());
+
+ // Id 0 is reserved.
+ if (SymbolId == 0 || SymbolId >= Cache.size())
+ return nullptr;
+
+ // Make sure to handle the case where we've inserted a placeholder symbol
+ // for types we don't yet support.
+ NativeRawSymbol *NRS = Cache[SymbolId].get();
+ if (!NRS)
+ return nullptr;
+
+ return PDBSymbol::create(Session, *NRS);
+}
+
+NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
+ return *Cache[SymbolId];
+}
+
+uint32_t SymbolCache::getNumCompilands() const {
+ if (!Dbi)
+ return 0;
+
+ return Dbi->modules().getModuleCount();
+}
+
+SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
+ auto Iter = GlobalOffsetToSymbolId.find(Offset);
+ if (Iter != GlobalOffsetToSymbolId.end())
+ return Iter->second;
+
+ SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
+ CVSymbol CVS = SS.readRecord(Offset);
+ SymIndexId Id = 0;
+ switch (CVS.kind()) {
+ case SymbolKind::S_UDT: {
+ UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
+ Id = createSymbol<NativeTypeTypedef>(std::move(US));
+ break;
+ }
+ default:
+ Id = createSymbolPlaceholder();
+ break;
+ }
+ if (Id != 0) {
+ assert(GlobalOffsetToSymbolId.count(Offset) == 0);
+ GlobalOffsetToSymbolId[Offset] = Id;
+ }
+
+ return Id;
+}
+
+SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
+ uint64_t ParentAddr,
+ uint16_t Modi,
+ uint32_t RecordOffset) const {
+ auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
+ if (Iter != SymTabOffsetToSymbolId.end())
+ return Iter->second;
+
+ SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
+ SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
+ return Id;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+ PDB_SymType Type) {
+ switch (Type) {
+ case PDB_SymType::Function:
+ return findFunctionSymbolBySectOffset(Sect, Offset);
+ case PDB_SymType::PublicSymbol:
+ return findPublicSymbolBySectOffset(Sect, Offset);
+ case PDB_SymType::Compiland: {
+ uint16_t Modi;
+ if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
+ return nullptr;
+ return getOrCreateCompiland(Modi);
+ }
+ case PDB_SymType::None: {
+ // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
+ // only uses it to find the symbol length.
+ if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
+ return Sym;
+ return nullptr;
+ }
+ default:
+ return nullptr;
+ }
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
+ auto Iter = AddressToSymbolId.find({Sect, Offset});
+ if (Iter != AddressToSymbolId.end())
+ return getSymbolById(Iter->second);
+
+ if (!Dbi)
+ return nullptr;
+
+ uint16_t Modi;
+ if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
+ return nullptr;
+
+ Expected<ModuleDebugStreamRef> ExpectedModS =
+ Session.getModuleDebugStream(Modi);
+ if (!ExpectedModS) {
+ consumeError(ExpectedModS.takeError());
+ return nullptr;
+ }
+ CVSymbolArray Syms = ExpectedModS->getSymbolArray();
+
+ // Search for the symbol in this module.
+ for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
+ if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
+ continue;
+ auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
+ if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
+ Offset < PS.CodeOffset + PS.CodeSize) {
+ // Check if the symbol is already cached.
+ auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
+ if (Found != AddressToSymbolId.end())
+ return getSymbolById(Found->second);
+
+ // Otherwise, create a new symbol.
+ SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
+ AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
+ return getSymbolById(Id);
+ }
+
+ // Jump to the end of this ProcSym.
+ I = Syms.at(PS.End);
+ }
+ return nullptr;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
+ auto Iter = AddressToPublicSymId.find({Sect, Offset});
+ if (Iter != AddressToPublicSymId.end())
+ return getSymbolById(Iter->second);
+
+ auto Publics = Session.getPDBFile().getPDBPublicsStream();
+ if (!Publics)
+ return nullptr;
+
+ auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
+ if (!ExpectedSyms)
+ return nullptr;
+ BinaryStreamRef SymStream =
+ ExpectedSyms->getSymbolArray().getUnderlyingStream();
+
+ // Use binary search to find the first public symbol with an address greater
+ // than or equal to Sect, Offset.
+ auto AddrMap = Publics->getAddressMap();
+ auto First = AddrMap.begin();
+ auto It = AddrMap.begin();
+ size_t Count = AddrMap.size();
+ size_t Half;
+ while (Count > 0) {
+ It = First;
+ Half = Count / 2;
+ It += Half;
+ Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
+ if (!Sym) {
+ consumeError(Sym.takeError());
+ return nullptr;
+ }
+
+ auto PS =
+ cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
+ if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
+ First = ++It;
+ Count -= Half + 1;
+ } else
+ Count = Half;
+ }
+ if (It == AddrMap.begin())
+ return nullptr;
+ --It;
+
+ Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
+ if (!Sym) {
+ consumeError(Sym.takeError());
+ return nullptr;
+ }
+
+ // Check if the symbol is already cached.
+ auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
+ auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
+ if (Found != AddressToPublicSymId.end())
+ return getSymbolById(Found->second);
+
+ // Otherwise, create a new symbol.
+ SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
+ AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});
+ return getSymbolById(Id);
+}
+
+std::vector<SymbolCache::LineTableEntry>
+SymbolCache::findLineTable(uint16_t Modi) const {
+ // Check if this module has already been added.
+ auto LineTableIter = LineTable.find(Modi);
+ if (LineTableIter != LineTable.end())
+ return LineTableIter->second;
+
+ std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
+
+ // If there is an error or there are no lines, just return the
+ // empty vector.
+ Expected<ModuleDebugStreamRef> ExpectedModS =
+ Session.getModuleDebugStream(Modi);
+ if (!ExpectedModS) {
+ consumeError(ExpectedModS.takeError());
+ return ModuleLineTable;
+ }
+
+ std::vector<std::vector<LineTableEntry>> EntryList;
+ for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
+ if (SS.kind() != DebugSubsectionKind::Lines)
+ continue;
+
+ DebugLinesSubsectionRef Lines;
+ BinaryStreamReader Reader(SS.getRecordData());
+ if (auto EC = Lines.initialize(Reader)) {
+ consumeError(std::move(EC));
+ continue;
+ }
+
+ uint32_t RelocSegment = Lines.header()->RelocSegment;
+ uint32_t RelocOffset = Lines.header()->RelocOffset;
+ for (const LineColumnEntry &Group : Lines) {
+ if (Group.LineNumbers.empty())
+ continue;
+
+ std::vector<LineTableEntry> Entries;
+
+ // If there are column numbers, then they should be in a parallel stream
+ // to the line numbers.
+ auto ColIt = Group.Columns.begin();
+ auto ColsEnd = Group.Columns.end();
+
+ // Add a line to mark the beginning of this section.
+ uint64_t StartAddr =
+ Session.getVAFromSectOffset(RelocSegment, RelocOffset);
+ LineInfo FirstLine(Group.LineNumbers.front().Flags);
+ uint32_t ColNum =
+ (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
+ Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});
+
+ for (const LineNumberEntry &LN : Group.LineNumbers) {
+ uint64_t VA =
+ Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
+ LineInfo Line(LN.Flags);
+ ColNum = 0;
+
+ if (Lines.hasColumnInfo() && ColIt != ColsEnd) {
+ ColNum = ColIt->StartColumn;
+ ++ColIt;
+ }
+ Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});
+ }
+
+ // Add a terminal entry line to mark the end of this subsection.
+ uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;
+ LineInfo LastLine(Group.LineNumbers.back().Flags);
+ ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
+ Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});
+
+ EntryList.push_back(Entries);
+ }
+ }
+
+ // Sort EntryList, and add flattened contents to the line table.
+ llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,
+ const std::vector<LineTableEntry> &RHS) {
+ return LHS[0].Addr < RHS[0].Addr;
+ });
+ for (std::vector<LineTableEntry> &I : EntryList)
+ llvm::append_range(ModuleLineTable, I);
+
+ return ModuleLineTable;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
+ uint16_t Modi;
+ if (!Session.moduleIndexForVA(VA, Modi))
+ return nullptr;
+
+ std::vector<LineTableEntry> Lines = findLineTable(Modi);
+ if (Lines.empty())
+ return nullptr;
+
+ // Find the first line in the line table whose address is not greater than
+ // the one we are searching for.
+ auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
+ return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
+ });
+
+ // Try to back up if we've gone too far.
+ if (LineIter == Lines.end() || LineIter->Addr > VA) {
+ if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
+ return nullptr;
+ --LineIter;
+ }
+
+ Expected<ModuleDebugStreamRef> ExpectedModS =
+ Session.getModuleDebugStream(Modi);
+ if (!ExpectedModS) {
+ consumeError(ExpectedModS.takeError());
+ return nullptr;
+ }
+ Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
+ ExpectedModS->findChecksumsSubsection();
+ if (!ExpectedChecksums) {
+ consumeError(ExpectedChecksums.takeError());
+ return nullptr;
+ }
+
+ // Populate a vector of NativeLineNumbers that have addresses in the given
+ // address range.
+ std::vector<NativeLineNumber> LineNumbers;
+ while (LineIter != Lines.end()) {
+ if (LineIter->IsTerminalEntry) {
+ ++LineIter;
+ continue;
+ }
+
+ // If the line is still within the address range, create a NativeLineNumber
+ // and add to the list.
+ if (LineIter->Addr > VA + Length)
+ break;
+
+ uint32_t LineSect, LineOff;
+ Session.addressForVA(LineIter->Addr, LineSect, LineOff);
+ uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
+ auto ChecksumIter =
+ ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
+ uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
+ NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,
+ LineSect, LineOff, LineLength, SrcFileId, Modi);
+ LineNumbers.push_back(LineNum);
+ ++LineIter;
+ }
+ return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
+}
+
+std::unique_ptr<PDBSymbolCompiland>
+SymbolCache::getOrCreateCompiland(uint32_t Index) {
+ if (!Dbi)
+ return nullptr;
+
+ if (Index >= Compilands.size())
+ return nullptr;
+
+ if (Compilands[Index] == 0) {
+ const DbiModuleList &Modules = Dbi->modules();
+ Compilands[Index] =
+ createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
+ }
+
+ return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
+}
+
+std::unique_ptr<IPDBSourceFile>
+SymbolCache::getSourceFileById(SymIndexId FileId) const {
+ assert(FileId < SourceFiles.size());
+
+ // Id 0 is reserved.
+ if (FileId == 0)
+ return nullptr;
+
+ return std::unique_ptr<NativeSourceFile>(
+ new NativeSourceFile(*SourceFiles[FileId].get()));
+}
+
+SymIndexId
+SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
+ auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
+ if (Iter != FileNameOffsetToId.end())
+ return Iter->second;
+
+ SymIndexId Id = SourceFiles.size();
+ auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
+ SourceFiles.push_back(std::move(SrcFile));
+ FileNameOffsetToId[Checksums.FileNameOffset] = Id;
+ return Id;
+}
+
+
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolStream.cpp
new file mode 100644
index 0000000000..003840b6e6
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/SymbolStream.cpp
@@ -0,0 +1,45 @@
+//===- SymbolStream.cpp - PDB Symbol Stream Access ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::support;
+using namespace llvm::pdb;
+
+SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream)
+ : Stream(std::move(Stream)) {}
+
+SymbolStream::~SymbolStream() {}
+
+Error SymbolStream::reload() {
+ BinaryStreamReader Reader(*Stream);
+
+ if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength()))
+ return EC;
+
+ return Error::success();
+}
+
+iterator_range<codeview::CVSymbolArray::Iterator>
+SymbolStream::getSymbols(bool *HadError) const {
+ return llvm::make_range(SymbolRecords.begin(HadError), SymbolRecords.end());
+}
+
+Error SymbolStream::commit() { return Error::success(); }
+
+codeview::CVSymbol SymbolStream::readRecord(uint32_t Offset) const {
+ return *SymbolRecords.at(Offset);
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiHashing.cpp
new file mode 100644
index 0000000000..b71b2b1581
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -0,0 +1,129 @@
+//===- TpiHashing.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/Support/CRC.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+// Corresponds to `fUDTAnon`.
+static bool isAnonymous(StringRef Name) {
+ return Name == "<unnamed-tag>" || Name == "__unnamed" ||
+ Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
+}
+
+// Computes the hash for a user-defined type record. This could be a struct,
+// class, union, or enum.
+static uint32_t getHashForUdt(const TagRecord &Rec,
+ ArrayRef<uint8_t> FullRecord) {
+ ClassOptions Opts = Rec.getOptions();
+ bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
+ bool Scoped = bool(Opts & ClassOptions::Scoped);
+ bool HasUniqueName = bool(Opts & ClassOptions::HasUniqueName);
+ bool IsAnon = HasUniqueName && isAnonymous(Rec.getName());
+
+ if (!ForwardRef && !Scoped && !IsAnon)
+ return hashStringV1(Rec.getName());
+ if (!ForwardRef && HasUniqueName && !IsAnon)
+ return hashStringV1(Rec.getUniqueName());
+ return hashBufferV8(FullRecord);
+}
+
+template <typename T>
+static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
+ T Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+ return getHashForUdt(Deserialized, Rec.data());
+}
+
+template <typename T>
+static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
+ T Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+
+ ClassOptions Opts = Deserialized.getOptions();
+
+ bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
+
+ uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
+
+ // If we don't have a forward ref we can't compute the hash of it from the
+ // full record because it requires hashing the entire buffer.
+ if (!ForwardRef)
+ return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
+
+ bool Scoped = bool(Opts & ClassOptions::Scoped);
+
+ StringRef NameToHash =
+ Scoped ? Deserialized.getUniqueName() : Deserialized.getName();
+ uint32_t FullHash = hashStringV1(NameToHash);
+ return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
+}
+
+template <typename T>
+static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
+ T Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+ char Buf[4];
+ support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
+ return hashStringV1(StringRef(Buf, 4));
+}
+
+Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {
+ switch (Type.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ return getTagRecordHashForUdt<ClassRecord>(Type);
+ case LF_UNION:
+ return getTagRecordHashForUdt<UnionRecord>(Type);
+ case LF_ENUM:
+ return getTagRecordHashForUdt<EnumRecord>(Type);
+ default:
+ assert(false && "Type is not a tag record!");
+ }
+ return make_error<StringError>("Invalid record type",
+ inconvertibleErrorCode());
+}
+
+Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
+ switch (Rec.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ return getHashForUdt<ClassRecord>(Rec);
+ case LF_UNION:
+ return getHashForUdt<UnionRecord>(Rec);
+ case LF_ENUM:
+ return getHashForUdt<EnumRecord>(Rec);
+
+ case LF_UDT_SRC_LINE:
+ return getSourceLineHash<UdtSourceLineRecord>(Rec);
+ case LF_UDT_MOD_SRC_LINE:
+ return getSourceLineHash<UdtModSourceLineRecord>(Rec);
+
+ default:
+ break;
+ }
+
+ // Run CRC32 over the bytes. This corresponds to `hashBufv8`.
+ JamCRC JC(/*Init=*/0U);
+ JC.update(Rec.data());
+ return JC.getCRC();
+}
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStream.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStream.cpp
new file mode 100644
index 0000000000..ac19db03fa
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -0,0 +1,246 @@
+//===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/Hash.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::support;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+TpiStream::TpiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
+ : Pdb(File), Stream(std::move(Stream)) {}
+
+TpiStream::~TpiStream() = default;
+
+Error TpiStream::reload() {
+ BinaryStreamReader Reader(*Stream);
+
+ if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "TPI Stream does not contain a header.");
+
+ if (Reader.readObject(Header))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "TPI Stream does not contain a header.");
+
+ if (Header->Version != PdbTpiV80)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Unsupported TPI Version.");
+
+ if (Header->HeaderSize != sizeof(TpiStreamHeader))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Corrupt TPI Header size.");
+
+ if (Header->HashKeySize != sizeof(ulittle32_t))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "TPI Stream expected 4 byte hash key size.");
+
+ if (Header->NumHashBuckets < MinTpiHashBuckets ||
+ Header->NumHashBuckets > MaxTpiHashBuckets)
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "TPI Stream Invalid number of hash buckets.");
+
+ // The actual type records themselves come from this stream
+ if (auto EC =
+ Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes))
+ return EC;
+
+ BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData);
+ if (auto EC =
+ RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))
+ return EC;
+
+ // Hash indices, hash values, etc come from the hash stream.
+ if (Header->HashStreamIndex != kInvalidStreamIndex) {
+ auto HS = Pdb.safelyCreateIndexedStream(Header->HashStreamIndex);
+ if (!HS) {
+ consumeError(HS.takeError());
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid TPI hash stream index.");
+ }
+ BinaryStreamReader HSR(**HS);
+
+ // There should be a hash value for every type record, or no hashes at all.
+ uint32_t NumHashValues =
+ Header->HashValueBuffer.Length / sizeof(ulittle32_t);
+ if (NumHashValues != getNumTypeRecords() && NumHashValues != 0)
+ return make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "TPI hash count does not match with the number of type records.");
+ HSR.setOffset(Header->HashValueBuffer.Off);
+ if (auto EC = HSR.readArray(HashValues, NumHashValues))
+ return EC;
+
+ HSR.setOffset(Header->IndexOffsetBuffer.Off);
+ uint32_t NumTypeIndexOffsets =
+ Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
+ if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
+ return EC;
+
+ if (Header->HashAdjBuffer.Length > 0) {
+ HSR.setOffset(Header->HashAdjBuffer.Off);
+ if (auto EC = HashAdjusters.load(HSR))
+ return EC;
+ }
+
+ HashStream = std::move(*HS);
+ }
+
+ Types = std::make_unique<LazyRandomTypeCollection>(
+ TypeRecords, getNumTypeRecords(), getTypeIndexOffsets());
+ return Error::success();
+}
+
+PdbRaw_TpiVer TpiStream::getTpiVersion() const {
+ uint32_t Value = Header->Version;
+ return static_cast<PdbRaw_TpiVer>(Value);
+}
+
+uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
+
+uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
+
+uint32_t TpiStream::getNumTypeRecords() const {
+ return TypeIndexEnd() - TypeIndexBegin();
+}
+
+uint16_t TpiStream::getTypeHashStreamIndex() const {
+ return Header->HashStreamIndex;
+}
+
+uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
+ return Header->HashAuxStreamIndex;
+}
+
+uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }
+uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
+
+void TpiStream::buildHashMap() {
+ if (!HashMap.empty())
+ return;
+ if (HashValues.empty())
+ return;
+
+ HashMap.resize(Header->NumHashBuckets);
+
+ TypeIndex TIB{Header->TypeIndexBegin};
+ TypeIndex TIE{Header->TypeIndexEnd};
+ while (TIB < TIE) {
+ uint32_t HV = HashValues[TIB.toArrayIndex()];
+ HashMap[HV].push_back(TIB++);
+ }
+}
+
+std::vector<TypeIndex> TpiStream::findRecordsByName(StringRef Name) const {
+ if (!supportsTypeLookup())
+ const_cast<TpiStream*>(this)->buildHashMap();
+
+ uint32_t Bucket = hashStringV1(Name) % Header->NumHashBuckets;
+ if (Bucket > HashMap.size())
+ return {};
+
+ std::vector<TypeIndex> Result;
+ for (TypeIndex TI : HashMap[Bucket]) {
+ std::string ThisName = computeTypeName(*Types, TI);
+ if (ThisName == Name)
+ Result.push_back(TI);
+ }
+ return Result;
+}
+
+bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
+
+Expected<TypeIndex>
+TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {
+ if (!supportsTypeLookup())
+ const_cast<TpiStream*>(this)->buildHashMap();
+
+ CVType F = Types->getType(ForwardRefTI);
+ if (!isUdtForwardRef(F))
+ return ForwardRefTI;
+
+ Expected<TagRecordHash> ForwardTRH = hashTagRecord(F);
+ if (!ForwardTRH)
+ return ForwardTRH.takeError();
+
+ uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets;
+
+ for (TypeIndex TI : HashMap[BucketIdx]) {
+ CVType CVT = Types->getType(TI);
+ if (CVT.kind() != F.kind())
+ continue;
+
+ Expected<TagRecordHash> FullTRH = hashTagRecord(CVT);
+ if (!FullTRH)
+ return FullTRH.takeError();
+ if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash)
+ continue;
+ TagRecord &ForwardTR = ForwardTRH->getRecord();
+ TagRecord &FullTR = FullTRH->getRecord();
+
+ if (!ForwardTR.hasUniqueName()) {
+ if (ForwardTR.getName() == FullTR.getName())
+ return TI;
+ continue;
+ }
+
+ if (!FullTR.hasUniqueName())
+ continue;
+ if (ForwardTR.getUniqueName() == FullTR.getUniqueName())
+ return TI;
+ }
+ return ForwardRefTI;
+}
+
+codeview::CVType TpiStream::getType(codeview::TypeIndex Index) {
+ assert(!Index.isSimple());
+ return Types->getType(Index);
+}
+
+BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {
+ return TypeRecordsSubstream;
+}
+
+FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const {
+ return HashValues;
+}
+
+FixedStreamArray<TypeIndexOffset> TpiStream::getTypeIndexOffsets() const {
+ return TypeIndexOffsets;
+}
+
+HashTable<support::ulittle32_t> &TpiStream::getHashAdjusters() {
+ return HashAdjusters;
+}
+
+CVTypeRange TpiStream::types(bool *HadError) const {
+ return make_range(TypeRecords.begin(HadError), TypeRecords.end());
+}
+
+Error TpiStream::commit() { return Error::success(); }
diff --git a/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
new file mode 100644
index 0000000000..5f4f497690
--- /dev/null
+++ b/contrib/libs/llvm14/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
@@ -0,0 +1,214 @@
+//===- TpiStreamBuilder.cpp - -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+#include <numeric>
+
+using namespace llvm;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+using namespace llvm::support;
+
+TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
+ : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
+}
+
+TpiStreamBuilder::~TpiStreamBuilder() = default;
+
+void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
+ VerHeader = Version;
+}
+
+void TpiStreamBuilder::updateTypeIndexOffsets(ArrayRef<uint16_t> Sizes) {
+ // If we just crossed an 8KB threshold, add a type index offset.
+ for (uint16_t Size : Sizes) {
+ size_t NewSize = TypeRecordBytes + Size;
+ constexpr size_t EightKB = 8 * 1024;
+ if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecordCount == 0) {
+ TypeIndexOffsets.push_back(
+ {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex +
+ TypeRecordCount),
+ ulittle32_t(TypeRecordBytes)});
+ }
+ ++TypeRecordCount;
+ TypeRecordBytes = NewSize;
+ }
+}
+
+void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
+ Optional<uint32_t> Hash) {
+ assert(((Record.size() & 3) == 0) &&
+ "The type record's size is not a multiple of 4 bytes which will "
+ "cause misalignment in the output TPI stream!");
+ assert(Record.size() <= codeview::MaxRecordLength);
+ uint16_t OneSize = (uint16_t)Record.size();
+ updateTypeIndexOffsets(makeArrayRef(&OneSize, 1));
+
+ TypeRecBuffers.push_back(Record);
+ // FIXME: Require it.
+ if (Hash)
+ TypeHashes.push_back(*Hash);
+}
+
+void TpiStreamBuilder::addTypeRecords(ArrayRef<uint8_t> Types,
+ ArrayRef<uint16_t> Sizes,
+ ArrayRef<uint32_t> Hashes) {
+ // Ignore empty type buffers. There should be no hashes or sizes in this case.
+ if (Types.empty()) {
+ assert(Sizes.empty() && Hashes.empty());
+ return;
+ }
+
+ assert(((Types.size() & 3) == 0) &&
+ "The type record's size is not a multiple of 4 bytes which will "
+ "cause misalignment in the output TPI stream!");
+ assert(Sizes.size() == Hashes.size() && "sizes and hashes should be in sync");
+ assert(std::accumulate(Sizes.begin(), Sizes.end(), 0U) == Types.size() &&
+ "sizes of type records should sum to the size of the types");
+ updateTypeIndexOffsets(Sizes);
+
+ TypeRecBuffers.push_back(Types);
+ llvm::append_range(TypeHashes, Hashes);
+}
+
+Error TpiStreamBuilder::finalize() {
+ if (Header)
+ return Error::success();
+
+ TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
+
+ H->Version = VerHeader;
+ H->HeaderSize = sizeof(TpiStreamHeader);
+ H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
+ H->TypeIndexEnd = H->TypeIndexBegin + TypeRecordCount;
+ H->TypeRecordBytes = TypeRecordBytes;
+
+ H->HashStreamIndex = HashStreamIndex;
+ H->HashAuxStreamIndex = kInvalidStreamIndex;
+ H->HashKeySize = sizeof(ulittle32_t);
+ H->NumHashBuckets = MaxTpiHashBuckets - 1;
+
+ // Recall that hash values go into a completely different stream identified by
+ // the `HashStreamIndex` field of the `TpiStreamHeader`. Therefore, the data
+ // begins at offset 0 of this independent stream.
+ H->HashValueBuffer.Off = 0;
+ H->HashValueBuffer.Length = calculateHashBufferSize();
+
+ // We never write any adjustments into our PDBs, so this is usually some
+ // offset with zero length.
+ H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length;
+ H->HashAdjBuffer.Length = 0;
+
+ H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length;
+ H->IndexOffsetBuffer.Length = calculateIndexOffsetSize();
+
+ Header = H;
+ return Error::success();
+}
+
+uint32_t TpiStreamBuilder::calculateSerializedLength() {
+ return sizeof(TpiStreamHeader) + TypeRecordBytes;
+}
+
+uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
+ assert((TypeRecordCount == TypeHashes.size() || TypeHashes.empty()) &&
+ "either all or no type records should have hashes");
+ return TypeHashes.size() * sizeof(ulittle32_t);
+}
+
+uint32_t TpiStreamBuilder::calculateIndexOffsetSize() const {
+ return TypeIndexOffsets.size() * sizeof(codeview::TypeIndexOffset);
+}
+
+Error TpiStreamBuilder::finalizeMsfLayout() {
+ uint32_t Length = calculateSerializedLength();
+ if (auto EC = Msf.setStreamSize(Idx, Length))
+ return EC;
+
+ uint32_t HashStreamSize =
+ calculateHashBufferSize() + calculateIndexOffsetSize();
+
+ if (HashStreamSize == 0)
+ return Error::success();
+
+ auto ExpectedIndex = Msf.addStream(HashStreamSize);
+ if (!ExpectedIndex)
+ return ExpectedIndex.takeError();
+ HashStreamIndex = *ExpectedIndex;
+ if (!TypeHashes.empty()) {
+ ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size());
+ MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size());
+ for (uint32_t I = 0; I < TypeHashes.size(); ++I) {
+ HashBuffer[I] = TypeHashes[I] % (MaxTpiHashBuckets - 1);
+ }
+ ArrayRef<uint8_t> Bytes(
+ reinterpret_cast<const uint8_t *>(HashBuffer.data()),
+ calculateHashBufferSize());
+ HashValueStream =
+ std::make_unique<BinaryByteStream>(Bytes, llvm::support::little);
+ }
+ return Error::success();
+}
+
+Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
+ WritableBinaryStreamRef Buffer) {
+ if (auto EC = finalize())
+ return EC;
+
+ auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
+ Idx, Allocator);
+
+ BinaryStreamWriter Writer(*InfoS);
+ if (auto EC = Writer.writeObject(*Header))
+ return EC;
+
+ for (auto Rec : TypeRecBuffers) {
+ assert(!Rec.empty() && "Attempting to write an empty type record shifts "
+ "all offsets in the TPI stream!");
+ assert(((Rec.size() & 3) == 0) &&
+ "The type record's size is not a multiple of 4 bytes which will "
+ "cause misalignment in the output TPI stream!");
+ if (auto EC = Writer.writeBytes(Rec))
+ return EC;
+ }
+
+ if (HashStreamIndex != kInvalidStreamIndex) {
+ auto HVS = WritableMappedBlockStream::createIndexedStream(
+ Layout, Buffer, HashStreamIndex, Allocator);
+ BinaryStreamWriter HW(*HVS);
+ if (HashValueStream) {
+ if (auto EC = HW.writeStreamRef(*HashValueStream))
+ return EC;
+ }
+
+ for (auto &IndexOffset : TypeIndexOffsets) {
+ if (auto EC = HW.writeObject(IndexOffset))
+ return EC;
+ }
+ }
+
+ return Error::success();
+}