summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-01-14 19:56:09 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-01-14 19:56:09 +0000
commite71ad5fbc2d616fafda7b18d6ce16d7b83086bc1 (patch)
tree472308e37d1ce5780d389325fa6d5756462ffb32 /gnu
parentdd108df16423a7a8bfc250e9cc68d0f273414c03 (diff)
Import LLVM 3.9.1 including clang and lld.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h30
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h109
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def3
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h79
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h74
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h8
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h14
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h21
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h25
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h21
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h14
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h5
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h4
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h64
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h33
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h28
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h4
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h3
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h5
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h222
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h9
-rw-r--r--gnu/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h30
-rw-r--r--gnu/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h19
-rw-r--r--gnu/llvm/include/llvm/Support/ELFRelocs/AMDGPU.def20
-rw-r--r--gnu/llvm/include/llvm/Support/ELFRelocs/BPF.def5
-rw-r--r--gnu/llvm/include/llvm/Support/MachO.def10
-rw-r--r--gnu/llvm/include/llvm/Transforms/Utils/MemorySSA.h189
-rw-r--r--gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp11
-rw-r--r--gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp30
-rw-r--r--gnu/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp367
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp158
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp399
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp57
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp25
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp60
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp86
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp39
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp10
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp76
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp64
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp308
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp130
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp82
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp8
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp56
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp8
-rw-r--r--gnu/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp228
-rw-r--r--gnu/llvm/lib/IR/AttributeSetNode.h22
-rw-r--r--gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp59
-rw-r--r--gnu/llvm/lib/Target/AArch64/AArch64SchedVulcan.td13
-rw-r--r--gnu/llvm/lib/Target/AMDGPU/AMDGPURuntimeMetadata.h203
-rw-r--r--gnu/llvm/lib/Target/NVPTX/NVPTXInferAddressSpaces.cpp3
-rw-r--r--gnu/llvm/lib/Transforms/Utils/MemorySSA.cpp1926
-rw-r--r--gnu/llvm/tools/clang/lib/CodeGen/CGCUDABuiltin.cpp6
-rw-r--r--gnu/llvm/tools/lld/COFF/Librarian.cpp39
-rw-r--r--gnu/llvm/tools/lld/COFF/ModuleDef.cpp12
-rw-r--r--gnu/llvm/tools/lld/include/lld/Core/Parallel.h69
-rw-r--r--gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp403
-rw-r--r--gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h16
-rw-r--r--gnu/llvm/tools/llvm-pdbdump/PdbYaml.cpp114
-rw-r--r--gnu/llvm/tools/llvm-pdbdump/PdbYaml.h84
-rw-r--r--gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp93
-rw-r--r--gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h4
-rw-r--r--gnu/llvm/unittests/DebugInfo/PDB/ErrorChecking.h10
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/MemorySSA.cpp270
65 files changed, 2344 insertions, 4252 deletions
diff --git a/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
index 8860ae42fc0..6affac801d4 100644
--- a/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
@@ -11,8 +11,8 @@
#define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -59,31 +59,29 @@ struct ColumnNumberEntry {
class ModuleSubstream {
public:
ModuleSubstream();
- ModuleSubstream(ModuleSubstreamKind Kind, msf::ReadableStreamRef Data);
- static Error initialize(msf::ReadableStreamRef Stream, ModuleSubstream &Info);
+ ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data);
+ static Error initialize(StreamRef Stream, ModuleSubstream &Info);
uint32_t getRecordLength() const;
ModuleSubstreamKind getSubstreamKind() const;
- msf::ReadableStreamRef getRecordData() const;
+ StreamRef getRecordData() const;
private:
ModuleSubstreamKind Kind;
- msf::ReadableStreamRef Data;
+ StreamRef Data;
};
-typedef msf::VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
-} // namespace codeview
-
-namespace msf {
-template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> {
- Error operator()(ReadableStreamRef Stream, uint32_t &Length,
- codeview::ModuleSubstream &Info) const {
- if (auto EC = codeview::ModuleSubstream::initialize(Stream, Info))
+template <> struct VarStreamArrayExtractor<ModuleSubstream> {
+ Error operator()(StreamRef Stream, uint32_t &Length,
+ ModuleSubstream &Info) const {
+ if (auto EC = ModuleSubstream::initialize(Stream, Info))
return EC;
Length = Info.getRecordLength();
return Error::success();
}
};
-} // namespace msf
-} // namespace llvm
+
+typedef VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
+}
+}
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
diff --git a/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h b/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
index f9927d66093..6df23090371 100644
--- a/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
+++ b/gnu/llvm/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
@@ -10,75 +10,28 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-#include <cstdint>
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
namespace llvm {
-
namespace codeview {
struct LineColumnEntry {
support::ulittle32_t NameIndex;
- msf::FixedStreamArray<LineNumberEntry> LineNumbers;
- msf::FixedStreamArray<ColumnNumberEntry> Columns;
+ FixedStreamArray<LineNumberEntry> LineNumbers;
+ FixedStreamArray<ColumnNumberEntry> Columns;
};
-struct FileChecksumEntry {
- uint32_t FileNameOffset; // Byte offset of filename in global stringtable.
- FileChecksumKind Kind; // The type of checksum.
- ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
-};
-
-typedef msf::VarStreamArray<LineColumnEntry> LineInfoArray;
-typedef msf::VarStreamArray<FileChecksumEntry> FileChecksumArray;
-
-class IModuleSubstreamVisitor {
+template <> class VarStreamArrayExtractor<LineColumnEntry> {
public:
- virtual ~IModuleSubstreamVisitor() = default;
+ VarStreamArrayExtractor(const LineSubstreamHeader *Header) : Header(Header) {}
- virtual Error visitUnknown(ModuleSubstreamKind Kind,
- msf::ReadableStreamRef Data) = 0;
- virtual Error visitSymbols(msf::ReadableStreamRef Data);
- virtual Error visitLines(msf::ReadableStreamRef Data,
- const LineSubstreamHeader *Header,
- const LineInfoArray &Lines);
- virtual Error visitStringTable(msf::ReadableStreamRef Data);
- virtual Error visitFileChecksums(msf::ReadableStreamRef Data,
- const FileChecksumArray &Checksums);
- virtual Error visitFrameData(msf::ReadableStreamRef Data);
- virtual Error visitInlineeLines(msf::ReadableStreamRef Data);
- virtual Error visitCrossScopeImports(msf::ReadableStreamRef Data);
- virtual Error visitCrossScopeExports(msf::ReadableStreamRef Data);
- virtual Error visitILLines(msf::ReadableStreamRef Data);
- virtual Error visitFuncMDTokenMap(msf::ReadableStreamRef Data);
- virtual Error visitTypeMDTokenMap(msf::ReadableStreamRef Data);
- virtual Error visitMergedAssemblyInput(msf::ReadableStreamRef Data);
- virtual Error visitCoffSymbolRVA(msf::ReadableStreamRef Data);
-};
-
-Error visitModuleSubstream(const ModuleSubstream &R,
- IModuleSubstreamVisitor &V);
-} // end namespace codeview
-
-namespace msf {
-
-template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> {
-public:
- VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header)
- : Header(Header) {}
-
- Error operator()(ReadableStreamRef Stream, uint32_t &Len,
- codeview::LineColumnEntry &Item) const {
- using namespace codeview;
+ Error operator()(StreamRef Stream, uint32_t &Len,
+ LineColumnEntry &Item) const {
const LineFileBlockHeader *BlockHeader;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(BlockHeader))
@@ -108,14 +61,19 @@ public:
}
private:
- const codeview::LineSubstreamHeader *Header;
+ const LineSubstreamHeader *Header;
};
-template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> {
+struct FileChecksumEntry {
+ uint32_t FileNameOffset; // Byte offset of filename in global stringtable.
+ FileChecksumKind Kind; // The type of checksum.
+ ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
+};
+
+template <> class VarStreamArrayExtractor<FileChecksumEntry> {
public:
- Error operator()(ReadableStreamRef Stream, uint32_t &Len,
- codeview::FileChecksumEntry &Item) const {
- using namespace codeview;
+ Error operator()(StreamRef Stream, uint32_t &Len,
+ FileChecksumEntry &Item) const {
const FileChecksum *Header;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Header))
@@ -129,8 +87,35 @@ public:
}
};
-} // end namespace msf
+typedef VarStreamArray<LineColumnEntry> LineInfoArray;
+typedef VarStreamArray<FileChecksumEntry> FileChecksumArray;
+
+class IModuleSubstreamVisitor {
+public:
+ virtual ~IModuleSubstreamVisitor() {}
+
+ virtual Error visitUnknown(ModuleSubstreamKind Kind, StreamRef Data) = 0;
+ virtual Error visitSymbols(StreamRef Data);
+ virtual Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
+ const LineInfoArray &Lines);
+ virtual Error visitStringTable(StreamRef Data);
+ virtual Error visitFileChecksums(StreamRef Data,
+ const FileChecksumArray &Checksums);
+ virtual Error visitFrameData(StreamRef Data);
+ virtual Error visitInlineeLines(StreamRef Data);
+ virtual Error visitCrossScopeImports(StreamRef Data);
+ virtual Error visitCrossScopeExports(StreamRef Data);
+ virtual Error visitILLines(StreamRef Data);
+ virtual Error visitFuncMDTokenMap(StreamRef Data);
+ virtual Error visitTypeMDTokenMap(StreamRef Data);
+ virtual Error visitMergedAssemblyInput(StreamRef Data);
+ virtual Error visitCoffSymbolRVA(StreamRef Data);
+};
+
+Error visitModuleSubstream(const ModuleSubstream &R,
+ IModuleSubstreamVisitor &V);
-} // end namespace llvm
+} // namespace codeview
+} // namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
diff --git a/gnu/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def b/gnu/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def
index c98dbac21a7..0959f4bf19c 100644
--- a/gnu/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def
+++ b/gnu/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def
@@ -43,8 +43,6 @@ TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure)
TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction)
TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList)
-TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList)
-
TYPE_RECORD(LF_ARRAY, 0x1503, Array)
TYPE_RECORD(LF_CLASS, 0x1504, Class)
TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class)
@@ -161,6 +159,7 @@ CV_TYPE(LF_OEM2, 0x1011)
CV_TYPE(LF_SKIP, 0x1200)
CV_TYPE(LF_DEFARG_ST, 0x1202)
+CV_TYPE(LF_FIELDLIST, 0x1203)
CV_TYPE(LF_DERIVED, 0x1204)
CV_TYPE(LF_DIMCONU, 0x1207)
CV_TYPE(LF_DIMCONLU, 0x1208)
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
index c97ca32ab43..6ab3c806755 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
@@ -11,10 +11,10 @@
#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@@ -36,8 +36,32 @@ class ISectionContribVisitor;
class DbiStream {
friend class DbiStreamBuilder;
+ struct HeaderInfo {
+ support::little32_t VersionSignature;
+ support::ulittle32_t VersionHeader;
+ support::ulittle32_t Age; // Should match InfoStream.
+ support::ulittle16_t GlobalSymbolStreamIndex; // Global symbol stream #
+ support::ulittle16_t BuildNumber; // See DbiBuildNo structure.
+ support::ulittle16_t PublicSymbolStreamIndex; // Public symbols stream #
+ support::ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
+ support::ulittle16_t SymRecordStreamIndex; // Symbol records stream #
+ support::ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
+ support::little32_t ModiSubstreamSize; // Size of module info stream
+ support::little32_t SecContrSubstreamSize; // Size of sec. contrib stream
+ support::little32_t SectionMapSize; // Size of sec. map substream
+ support::little32_t FileInfoSize; // Size of file info substream
+ support::little32_t TypeServerSize; // Size of type server map
+ support::ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
+ support::little32_t OptionalDbgHdrSize; // Size of DbgHeader info
+ support::little32_t ECSubstreamSize; // Size of EC stream (what is EC?)
+ support::ulittle16_t Flags; // See DbiFlags enum.
+ support::ulittle16_t MachineType; // See PDB_MachineType enum.
+
+ support::ulittle32_t Reserved; // Pad to 64 bytes
+ };
+
public:
- DbiStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
+ DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
~DbiStream();
Error reload();
@@ -62,6 +86,8 @@ public:
PDB_Machine getMachineType() const;
+ enum { InvalidStreamIndex = 0xffff };
+
/// If the given stream type is present, returns its stream index. If it is
/// not present, returns InvalidStreamIndex.
uint32_t getDebugStreamIndex(DbgHeaderType Type) const;
@@ -70,15 +96,16 @@ public:
Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
- msf::FixedStreamArray<object::coff_section> getSectionHeaders();
+ codeview::FixedStreamArray<object::coff_section> getSectionHeaders();
- msf::FixedStreamArray<object::FpoData> getFpoRecords();
+ codeview::FixedStreamArray<object::FpoData> getFpoRecords();
- msf::FixedStreamArray<SecMapEntry> getSectionMap() const;
+ codeview::FixedStreamArray<SecMapEntry> getSectionMap() const;
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
+ Error commit();
+
private:
- Error initializeModInfoArray();
Error initializeSectionContributionData();
Error initializeSectionHeadersData();
Error initializeSectionMapData();
@@ -86,35 +113,35 @@ private:
Error initializeFpoRecords();
PDBFile &Pdb;
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<MappedBlockStream> Stream;
std::vector<ModuleInfoEx> ModuleInfos;
NameHashTable ECNames;
- msf::ReadableStreamRef ModInfoSubstream;
- msf::ReadableStreamRef SecContrSubstream;
- msf::ReadableStreamRef SecMapSubstream;
- msf::ReadableStreamRef FileInfoSubstream;
- msf::ReadableStreamRef TypeServerMapSubstream;
- msf::ReadableStreamRef ECSubstream;
+ codeview::StreamRef ModInfoSubstream;
+ codeview::StreamRef SecContrSubstream;
+ codeview::StreamRef SecMapSubstream;
+ codeview::StreamRef FileInfoSubstream;
+ codeview::StreamRef TypeServerMapSubstream;
+ codeview::StreamRef ECSubstream;
- msf::ReadableStreamRef NamesBuffer;
+ codeview::StreamRef NamesBuffer;
- msf::FixedStreamArray<support::ulittle16_t> DbgStreams;
+ codeview::FixedStreamArray<support::ulittle16_t> DbgStreams;
PdbRaw_DbiSecContribVer SectionContribVersion;
- msf::FixedStreamArray<SectionContrib> SectionContribs;
- msf::FixedStreamArray<SectionContrib2> SectionContribs2;
- msf::FixedStreamArray<SecMapEntry> SectionMap;
- msf::FixedStreamArray<support::little32_t> FileNameOffsets;
+ codeview::FixedStreamArray<SectionContrib> SectionContribs;
+ codeview::FixedStreamArray<SectionContrib2> SectionContribs2;
+ codeview::FixedStreamArray<SecMapEntry> SectionMap;
+ codeview::FixedStreamArray<support::little32_t> FileNameOffsets;
- std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream;
- msf::FixedStreamArray<object::coff_section> SectionHeaders;
+ std::unique_ptr<MappedBlockStream> SectionHeaderStream;
+ codeview::FixedStreamArray<object::coff_section> SectionHeaders;
- std::unique_ptr<msf::MappedBlockStream> FpoStream;
- msf::FixedStreamArray<object::FpoData> FpoRecords;
+ std::unique_ptr<MappedBlockStream> FpoStream;
+ codeview::FixedStreamArray<object::FpoData> FpoRecords;
- const DbiStreamHeader *Header;
+ const HeaderInfo *Header;
};
}
}
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
index 99a3ac7fb1d..2c7350f3c3e 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
@@ -11,31 +11,20 @@
#define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAMBUILDER_H
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Error.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/Support/Endian.h"
namespace llvm {
-namespace msf {
-class MSFBuilder;
-}
-namespace object {
-struct coff_section;
-}
namespace pdb {
class DbiStream;
-struct DbiStreamHeader;
class PDBFile;
class DbiStreamBuilder {
public:
- DbiStreamBuilder(msf::MSFBuilder &Msf);
+ DbiStreamBuilder();
DbiStreamBuilder(const DbiStreamBuilder &) = delete;
DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete;
@@ -47,57 +36,12 @@ public:
void setPdbDllRbld(uint16_t R);
void setFlags(uint16_t F);
void setMachineType(PDB_Machine M);
- void setSectionContribs(ArrayRef<SectionContrib> SecMap);
- void setSectionMap(ArrayRef<SecMapEntry> SecMap);
-
- // Add given bytes as a new stream.
- Error addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data);
uint32_t calculateSerializedLength() const;
- Error addModuleInfo(StringRef ObjFile, StringRef Module);
- Error addModuleSourceFile(StringRef Module, StringRef File);
-
- Error finalizeMsfLayout();
-
- Error commit(const msf::MSFLayout &Layout,
- const msf::WritableStream &Buffer);
-
- // A helper function to create Section Contributions from COFF input
- // section headers.
- static std::vector<SectionContrib>
- createSectionContribs(ArrayRef<llvm::object::coff_section> SecHdrs);
-
- // A helper function to create a Section Map from a COFF section header.
- static std::vector<SecMapEntry>
- createSectionMap(ArrayRef<llvm::object::coff_section> SecHdrs);
+ Expected<std::unique_ptr<DbiStream>> build(PDBFile &File);
private:
- struct DebugStream {
- ArrayRef<uint8_t> Data;
- uint16_t StreamNumber = 0;
- };
-
- Error finalize();
- uint32_t calculateModiSubstreamSize() const;
- uint32_t calculateSectionContribsStreamSize() const;
- uint32_t calculateSectionMapStreamSize() const;
- uint32_t calculateFileInfoSubstreamSize() const;
- uint32_t calculateNamesBufferSize() const;
- uint32_t calculateDbgStreamsSize() const;
-
- Error generateModiSubstream();
- Error generateFileInfoSubstream();
-
- struct ModuleInfo {
- std::vector<StringRef> SourceFiles;
- StringRef Obj;
- StringRef Mod;
- };
-
- msf::MSFBuilder &Msf;
- BumpPtrAllocator &Allocator;
-
Optional<PdbRaw_DbiVer> VerHeader;
uint32_t Age;
uint16_t BuildNumber;
@@ -105,20 +49,6 @@ private:
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
-
- const DbiStreamHeader *Header;
-
- StringMap<std::unique_ptr<ModuleInfo>> ModuleInfos;
- std::vector<ModuleInfo *> ModuleInfoList;
-
- StringMap<uint32_t> SourceFileNames;
-
- msf::WritableStreamRef NamesBuffer;
- msf::MutableByteStream ModInfoBuffer;
- msf::MutableByteStream FileInfoBuffer;
- ArrayRef<SectionContrib> SectionContribs;
- ArrayRef<SecMapEntry> SectionMap;
- llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
};
}
}
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h
index fb00d6ad4bc..355a25a38ef 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h
@@ -12,19 +12,17 @@
namespace llvm {
namespace pdb {
-
struct SectionContrib;
struct SectionContrib2;
class ISectionContribVisitor {
public:
- virtual ~ISectionContribVisitor() = default;
+ virtual ~ISectionContribVisitor() {}
virtual void visit(const SectionContrib &C) = 0;
virtual void visit(const SectionContrib2 &C) = 0;
};
-
-} // end namespace pdb
-} // end namespace llvm
+} // namespace pdb
+} // namespace llvm
#endif // LLVM_DEBUGINFO_PDB_RAW_ISECTIONCONTRIBVISITOR_H
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
index 6b8b94ff1a3..1980bec7153 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
@@ -11,8 +11,8 @@
#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
#include "llvm/ADT/StringMap.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
@@ -27,10 +27,18 @@ class PDBFile;
class InfoStream {
friend class InfoStreamBuilder;
+ struct HeaderInfo {
+ support::ulittle32_t Version;
+ support::ulittle32_t Signature;
+ support::ulittle32_t Age;
+ PDB_UniqueId Guid;
+ };
+
public:
- InfoStream(std::unique_ptr<msf::MappedBlockStream> Stream);
+ InfoStream(std::unique_ptr<MappedBlockStream> Stream);
Error reload();
+ Error commit();
PdbRaw_ImplVer getVersion() const;
uint32_t getSignature() const;
@@ -41,7 +49,7 @@ public:
iterator_range<StringMapConstIterator<uint32_t>> named_streams() const;
private:
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<MappedBlockStream> Stream;
// PDB file format version. We only support VC70. See the enumeration
// `PdbRaw_ImplVer` for the other possible values.
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
index cb60b1eb69b..e9869bb2786 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
@@ -19,16 +19,12 @@
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
namespace llvm {
-namespace msf {
-class MSFBuilder;
-class StreamWriter;
-}
namespace pdb {
class PDBFile;
class InfoStreamBuilder {
public:
- InfoStreamBuilder(msf::MSFBuilder &Msf);
+ InfoStreamBuilder();
InfoStreamBuilder(const InfoStreamBuilder &) = delete;
InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete;
@@ -41,18 +37,13 @@ public:
uint32_t calculateSerializedLength() const;
- Error finalizeMsfLayout();
-
- Error commit(const msf::MSFLayout &Layout,
- const msf::WritableStream &Buffer) const;
+ Expected<std::unique_ptr<InfoStream>> build(PDBFile &File);
private:
- msf::MSFBuilder &Msf;
-
- PdbRaw_ImplVer Ver;
- uint32_t Sig;
- uint32_t Age;
- PDB_UniqueId Guid;
+ Optional<PdbRaw_ImplVer> Ver;
+ Optional<uint32_t> Sig;
+ Optional<uint32_t> Age;
+ Optional<PDB_UniqueId> Guid;
NameMapBuilder NamedStreams;
};
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
index bf5cf53b331..b8da0bfabf3 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
@@ -11,26 +11,24 @@
#define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
-#include "llvm/Support/Error.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include <cstdint>
#include <vector>
namespace llvm {
-
namespace pdb {
class ModInfo {
- friend class DbiStreamBuilder;
+private:
+ struct FileLayout;
public:
ModInfo();
ModInfo(const ModInfo &Info);
~ModInfo();
- static Error initialize(msf::ReadableStreamRef Stream, ModInfo &Info);
+ static Error initialize(codeview::StreamRef Stream, ModInfo &Info);
bool hasECInfo() const;
uint16_t getTypeServerIndex() const;
@@ -50,12 +48,13 @@ public:
private:
StringRef ModuleName;
StringRef ObjFileName;
- const ModuleInfoHeader *Layout = nullptr;
+ const FileLayout *Layout;
};
struct ModuleInfoEx {
ModuleInfoEx(const ModInfo &Info) : Info(Info) {}
- ModuleInfoEx(const ModuleInfoEx &Ex) = default;
+ ModuleInfoEx(const ModuleInfoEx &Ex)
+ : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {}
ModInfo Info;
std::vector<StringRef> SourceFiles;
@@ -63,10 +62,9 @@ struct ModuleInfoEx {
} // end namespace pdb
-namespace msf {
-
+namespace codeview {
template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
- Error operator()(ReadableStreamRef Stream, uint32_t &Length,
+ Error operator()(StreamRef Stream, uint32_t &Length,
pdb::ModInfo &Info) const {
if (auto EC = pdb::ModInfo::initialize(Stream, Info))
return EC;
@@ -74,8 +72,7 @@ template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
return Error::success();
}
};
-
-} // end namespace msf
+}
} // end namespace llvm
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h
index d5e7a6830d8..d22962cc1e2 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h
@@ -13,10 +13,10 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -26,14 +26,11 @@ class ModInfo;
class ModStream {
public:
- ModStream(const ModInfo &Module,
- std::unique_ptr<msf::MappedBlockStream> Stream);
+ ModStream(const ModInfo &Module, std::unique_ptr<MappedBlockStream> Stream);
~ModStream();
Error reload();
- uint32_t signature() const { return Signature; }
-
iterator_range<codeview::CVSymbolArray::Iterator>
symbols(bool *HadError) const;
@@ -45,14 +42,12 @@ public:
private:
const ModInfo &Mod;
- uint32_t Signature;
-
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<MappedBlockStream> Stream;
codeview::CVSymbolArray SymbolsSubstream;
- msf::ReadableStreamRef LinesSubstream;
- msf::ReadableStreamRef C13LinesSubstream;
- msf::ReadableStreamRef GlobalRefsSubstream;
+ codeview::StreamRef LinesSubstream;
+ codeview::StreamRef C13LinesSubstream;
+ codeview::StreamRef GlobalRefsSubstream;
codeview::ModuleSubstreamArray LineInfo;
};
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h
index 00d022d4d8e..c9e060a3a70 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h
@@ -12,15 +12,15 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
-namespace msf {
+namespace codeview {
class StreamReader;
}
namespace pdb {
@@ -29,7 +29,7 @@ class NameHashTable {
public:
NameHashTable();
- Error load(msf::StreamReader &Stream);
+ Error load(codeview::StreamReader &Stream);
uint32_t getNameCount() const { return NameCount; }
uint32_t getHashVersion() const { return HashVersion; }
@@ -38,11 +38,11 @@ public:
StringRef getStringForID(uint32_t ID) const;
uint32_t getIDForString(StringRef Str) const;
- msf::FixedStreamArray<support::ulittle32_t> name_ids() const;
+ codeview::FixedStreamArray<support::ulittle32_t> name_ids() const;
private:
- msf::ReadableStreamRef NamesBuffer;
- msf::FixedStreamArray<support::ulittle32_t> IDs;
+ codeview::StreamRef NamesBuffer;
+ codeview::FixedStreamArray<support::ulittle32_t> IDs;
uint32_t Signature;
uint32_t HashVersion;
uint32_t NameCount;
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h
index de1163bc307..8a9b0d187ac 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMap.h
@@ -16,7 +16,7 @@
#include <cstdint>
namespace llvm {
-namespace msf {
+namespace codeview {
class StreamReader;
class StreamWriter;
}
@@ -28,7 +28,8 @@ class NameMap {
public:
NameMap();
- Error load(msf::StreamReader &Stream);
+ Error load(codeview::StreamReader &Stream);
+ Error commit(codeview::StreamWriter &Writer);
bool tryGetValue(StringRef Name, uint32_t &Value) const;
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
index f5244ac2180..bf49bfd9bf2 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
@@ -17,9 +17,6 @@
#include <memory>
namespace llvm {
-namespace msf {
-class StreamWriter;
-}
namespace pdb {
class NameMap;
@@ -30,7 +27,6 @@ public:
void addMapping(StringRef Name, uint32_t Mapping);
Expected<std::unique_ptr<NameMap>> build();
- Error commit(msf::StreamWriter &Writer) const;
uint32_t calculateSerializedLength() const;
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
index 29f5b2163d8..f4d7eb47d3b 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
@@ -11,10 +11,10 @@
#define LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/DebugInfo/MSF/IMSFFile.h"
-#include "llvm/DebugInfo/MSF/MSFCommon.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -24,26 +24,25 @@
namespace llvm {
-namespace msf {
-class MappedBlockStream;
+namespace codeview {
+class StreamInterface;
}
namespace pdb {
class DbiStream;
-class GlobalsStream;
class InfoStream;
+class MappedBlockStream;
class NameHashTable;
class PDBFileBuilder;
class PublicsStream;
class SymbolStream;
class TpiStream;
-class PDBFile : public msf::IMSFFile {
+class PDBFile : public IPDBFile {
friend PDBFileBuilder;
public:
- PDBFile(std::unique_ptr<msf::ReadableStream> PdbFileBuffer,
- BumpPtrAllocator &Allocator);
+ explicit PDBFile(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer);
~PDBFile() override;
uint32_t getFreeBlockMapBlock() const;
@@ -67,18 +66,11 @@ public:
Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
ArrayRef<uint8_t> Data) const override;
- ArrayRef<uint32_t> getFpmPages() const { return FpmPages; }
-
- ArrayRef<support::ulittle32_t> getStreamSizes() const {
- return ContainerLayout.StreamSizes;
- }
+ ArrayRef<support::ulittle32_t> getStreamSizes() const { return StreamSizes; }
ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const {
- return ContainerLayout.StreamMap;
+ return StreamMap;
}
- const msf::MSFLayout &getMsfLayout() const { return ContainerLayout; }
- const msf::ReadableStream &getMsfBuffer() const { return *Buffer; }
-
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
Error parseFileHeaders();
@@ -86,45 +78,33 @@ public:
Expected<InfoStream &> getPDBInfoStream();
Expected<DbiStream &> getPDBDbiStream();
- Expected<GlobalsStream &> getPDBGlobalsStream();
Expected<TpiStream &> getPDBTpiStream();
Expected<TpiStream &> getPDBIpiStream();
Expected<PublicsStream &> getPDBPublicsStream();
Expected<SymbolStream &> getPDBSymbolStream();
Expected<NameHashTable &> getStringTable();
- BumpPtrAllocator &getAllocator() { return Allocator; }
-
- bool hasPDBDbiStream() const;
- bool hasPDBGlobalsStream();
- bool hasPDBInfoStream();
- bool hasPDBIpiStream() const;
- bool hasPDBPublicsStream();
- bool hasPDBSymbolStream();
- bool hasPDBTpiStream() const;
- bool hasStringTable();
-
- private:
- Expected<std::unique_ptr<msf::MappedBlockStream>> safelyCreateIndexedStream(
- const msf::MSFLayout &Layout, const msf::ReadableStream &MsfData,
- uint32_t StreamIndex) const;
+ Error commit();
- BumpPtrAllocator &Allocator;
+private:
+ Error setSuperBlock(const msf::SuperBlock *Block);
- std::unique_ptr<msf::ReadableStream> Buffer;
+ BumpPtrAllocator Allocator;
- std::vector<uint32_t> FpmPages;
- msf::MSFLayout ContainerLayout;
+ std::unique_ptr<codeview::StreamInterface> Buffer;
+ const msf::SuperBlock *SB;
+ ArrayRef<support::ulittle32_t> StreamSizes;
+ ArrayRef<support::ulittle32_t> DirectoryBlocks;
+ std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
- std::unique_ptr<GlobalsStream> Globals;
std::unique_ptr<InfoStream> Info;
std::unique_ptr<DbiStream> Dbi;
std::unique_ptr<TpiStream> Tpi;
std::unique_ptr<TpiStream> Ipi;
std::unique_ptr<PublicsStream> Publics;
std::unique_ptr<SymbolStream> Symbols;
- std::unique_ptr<msf::MappedBlockStream> DirectoryStream;
- std::unique_ptr<msf::MappedBlockStream> StringTableStream;
+ std::unique_ptr<MappedBlockStream> DirectoryStream;
+ std::unique_ptr<MappedBlockStream> StringTableStream;
std::unique_ptr<NameHashTable> StringTable;
};
}
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
index 27fc4b53b64..47c755b4326 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
@@ -13,50 +13,45 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
+#include "llvm/DebugInfo/PDB/Raw/MsfBuilder.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+
#include <memory>
#include <vector>
namespace llvm {
-namespace msf {
-class MSFBuilder;
+namespace codeview {
+class StreamInterface;
}
namespace pdb {
class DbiStreamBuilder;
class InfoStreamBuilder;
-class TpiStreamBuilder;
+class PDBFile;
class PDBFileBuilder {
public:
- explicit PDBFileBuilder(BumpPtrAllocator &Allocator);
+ explicit PDBFileBuilder(
+ std::unique_ptr<codeview::StreamInterface> FileBuffer);
PDBFileBuilder(const PDBFileBuilder &) = delete;
PDBFileBuilder &operator=(const PDBFileBuilder &) = delete;
- Error initialize(uint32_t BlockSize);
+ Error initialize(const msf::SuperBlock &Super);
- msf::MSFBuilder &getMsfBuilder();
+ MsfBuilder &getMsfBuilder();
InfoStreamBuilder &getInfoBuilder();
DbiStreamBuilder &getDbiBuilder();
- TpiStreamBuilder &getTpiBuilder();
- TpiStreamBuilder &getIpiBuilder();
- Error commit(StringRef Filename);
+ Expected<std::unique_ptr<PDBFile>> build();
private:
- Expected<msf::MSFLayout> finalizeMsfLayout() const;
-
- BumpPtrAllocator &Allocator;
-
- std::unique_ptr<msf::MSFBuilder> Msf;
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
- std::unique_ptr<TpiStreamBuilder> Tpi;
- std::unique_ptr<TpiStreamBuilder> Ipi;
+
+ std::unique_ptr<PDBFile> File;
+ std::unique_ptr<MsfBuilder> Msf;
};
}
}
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
index 577f2986ff2..f5bfb0ed60a 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
@@ -10,10 +10,10 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
@@ -22,14 +22,14 @@
namespace llvm {
namespace pdb {
class DbiStream;
-struct GSIHashHeader;
class PDBFile;
class PublicsStream {
+ struct GSIHashHeader;
struct HeaderInfo;
public:
- PublicsStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
+ PublicsStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
~PublicsStream();
Error reload();
@@ -38,16 +38,16 @@ public:
uint32_t getNumBuckets() const { return NumBuckets; }
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
- msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
+ codeview::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
return HashBuckets;
}
- msf::FixedStreamArray<support::ulittle32_t> getAddressMap() const {
+ codeview::FixedStreamArray<support::ulittle32_t> getAddressMap() const {
return AddressMap;
}
- msf::FixedStreamArray<support::ulittle32_t> getThunkMap() const {
+ codeview::FixedStreamArray<support::ulittle32_t> getThunkMap() const {
return ThunkMap;
}
- msf::FixedStreamArray<SectionOffset> getSectionOffsets() const {
+ codeview::FixedStreamArray<SectionOffset> getSectionOffsets() const {
return SectionOffsets;
}
@@ -56,14 +56,14 @@ public:
private:
PDBFile &Pdb;
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<MappedBlockStream> Stream;
uint32_t NumBuckets = 0;
ArrayRef<uint8_t> Bitmap;
- msf::FixedStreamArray<PSHashRecord> HashRecords;
- msf::FixedStreamArray<support::ulittle32_t> HashBuckets;
- msf::FixedStreamArray<support::ulittle32_t> AddressMap;
- msf::FixedStreamArray<support::ulittle32_t> ThunkMap;
- msf::FixedStreamArray<SectionOffset> SectionOffsets;
+ codeview::FixedStreamArray<PSHashRecord> HashRecords;
+ codeview::FixedStreamArray<support::ulittle32_t> HashBuckets;
+ codeview::FixedStreamArray<support::ulittle32_t> AddressMap;
+ codeview::FixedStreamArray<support::ulittle32_t> ThunkMap;
+ codeview::FixedStreamArray<SectionOffset> SectionOffsets;
const HeaderInfo *Header;
const GSIHashHeader *HashHdr;
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h
index af114ff5249..8daaf47882d 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawConstants.h
@@ -17,8 +17,6 @@
namespace llvm {
namespace pdb {
-const uint16_t kInvalidStreamIndex = 0xFFFF;
-
enum PdbRaw_ImplVer : uint32_t {
PdbImplVC2 = 19941610,
PdbImplVC4 = 19950623,
@@ -63,8 +61,6 @@ enum SpecialStream : uint32_t {
StreamTPI = 2,
StreamDBI = 3,
StreamIPI = 4,
-
- kSpecialStreamCount
};
enum class DbgHeaderType : uint16_t {
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h
index f96b8066bbe..b0687cddbf4 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawError.h
@@ -19,14 +19,11 @@ namespace pdb {
enum class raw_error_code {
unspecified = 1,
feature_unsupported,
- invalid_format,
corrupt_file,
insufficient_buffer,
no_stream,
index_out_of_bounds,
invalid_block_address,
- duplicate_entry,
- no_entry,
not_writable,
invalid_tpi_hash,
};
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h
index 5a6c469fcc8..73d281eab1a 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawSession.h
@@ -12,7 +12,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -21,8 +20,7 @@ class PDBFile;
class RawSession : public IPDBSession {
public:
- RawSession(std::unique_ptr<PDBFile> PdbFile,
- std::unique_ptr<BumpPtrAllocator> Allocator);
+ explicit RawSession(std::unique_ptr<PDBFile> PdbFile);
~RawSession() override;
static Error createFromPdb(StringRef Path,
@@ -70,7 +68,6 @@ public:
private:
std::unique_ptr<PDBFile> Pdb;
- std::unique_ptr<BumpPtrAllocator> Allocator;
};
}
}
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
index d404b3994db..afcfe9405c0 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
@@ -80,228 +80,6 @@ struct TypeIndexOffset {
support::ulittle32_t Offset;
};
-/// Some of the values are stored in bitfields. Since this needs to be portable
-/// across compilers and architectures (big / little endian in particular) we
-/// can't use the actual structures below, but must instead do the shifting
-/// and masking ourselves. The struct definitions are provided for reference.
-struct DbiFlags {
- /// uint16_t IncrementalLinking : 1; // True if linked incrementally
- /// uint16_t IsStripped : 1; // True if private symbols were
- /// stripped.
- /// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes.
- /// uint16_t Reserved : 13;
- static const uint16_t FlagIncrementalMask = 0x0001;
- static const uint16_t FlagStrippedMask = 0x0002;
- static const uint16_t FlagHasCTypesMask = 0x0004;
-};
-
-struct DbiBuildNo {
- /// uint16_t MinorVersion : 8;
- /// uint16_t MajorVersion : 7;
- /// uint16_t NewVersionFormat : 1;
- static const uint16_t BuildMinorMask = 0x00FF;
- static const uint16_t BuildMinorShift = 0;
-
- static const uint16_t BuildMajorMask = 0x7F00;
- static const uint16_t BuildMajorShift = 8;
-};
-
-/// The fixed size header that appears at the beginning of the DBI Stream.
-struct DbiStreamHeader {
- support::little32_t VersionSignature;
- support::ulittle32_t VersionHeader;
-
- /// How "old" is this DBI Stream. Should match the age of the PDB InfoStream.
- support::ulittle32_t Age;
-
- /// Global symbol stream #
- support::ulittle16_t GlobalSymbolStreamIndex;
-
- /// See DbiBuildNo structure.
- support::ulittle16_t BuildNumber;
-
- /// Public symbols stream #
- support::ulittle16_t PublicSymbolStreamIndex;
-
- /// version of mspdbNNN.dll
- support::ulittle16_t PdbDllVersion;
-
- /// Symbol records stream #
- support::ulittle16_t SymRecordStreamIndex;
-
- /// rbld number of mspdbNNN.dll
- support::ulittle16_t PdbDllRbld;
-
- /// Size of module info stream
- support::little32_t ModiSubstreamSize;
-
- /// Size of sec. contrib stream
- support::little32_t SecContrSubstreamSize;
-
- /// Size of sec. map substream
- support::little32_t SectionMapSize;
-
- /// Size of file info substream
- support::little32_t FileInfoSize;
-
- /// Size of type server map
- support::little32_t TypeServerSize;
-
- /// Index of MFC Type Server
- support::ulittle32_t MFCTypeServerIndex;
-
- /// Size of DbgHeader info
- support::little32_t OptionalDbgHdrSize;
-
- /// Size of EC stream (what is EC?)
- support::little32_t ECSubstreamSize;
-
- /// See DbiFlags enum.
- support::ulittle16_t Flags;
-
- /// See PDB_MachineType enum.
- support::ulittle16_t MachineType;
-
- /// Pad to 64 bytes
- support::ulittle32_t Reserved;
-};
-static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
-
-struct SectionContribEntry {
- support::ulittle16_t Section;
- char Padding1[2];
- support::little32_t Offset;
- support::little32_t Size;
- support::ulittle32_t Characteristics;
- support::ulittle16_t ModuleIndex;
- char Padding2[2];
- support::ulittle32_t DataCrc;
- support::ulittle32_t RelocCrc;
-};
-
-/// The header preceeding the File Info Substream of the DBI stream.
-struct FileInfoSubstreamHeader {
- /// Total # of modules, should match number of records in the ModuleInfo
- /// substream.
- support::ulittle16_t NumModules;
-
- /// Total # of source files. This value is not accurate because PDB actually
- /// supports more than 64k source files, so we ignore it and compute the value
- /// from other stream fields.
- support::ulittle16_t NumSourceFiles;
-
- /// Following this header the File Info Substream is laid out as follows:
- /// ulittle16_t ModIndices[NumModules];
- /// ulittle16_t ModFileCounts[NumModules];
- /// ulittle32_t FileNameOffsets[NumSourceFiles];
- /// char Names[][NumSourceFiles];
- /// with the caveat that `NumSourceFiles` cannot be trusted, so
- /// it is computed by summing the `ModFileCounts` array.
-};
-
-struct ModInfoFlags {
- /// uint16_t fWritten : 1; // True if ModInfo is dirty
- /// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?)
- /// uint16_t unused : 6; // Reserved
- /// uint16_t iTSM : 8; // Type Server Index for this module
- static const uint16_t HasECFlagMask = 0x2;
-
- static const uint16_t TypeServerIndexMask = 0xFF00;
- static const uint16_t TypeServerIndexShift = 8;
-};
-
-/// The header preceeding each entry in the Module Info substream of the DBI
-/// stream.
-struct ModuleInfoHeader {
- /// Currently opened module. This field is a pointer in the reference
- /// implementation, but that won't work on 64-bit systems, and anyway it
- /// doesn't make sense to read a pointer from a file. For now it is unused,
- /// so just ignore it.
- support::ulittle32_t Mod;
-
- /// First section contribution of this module.
- SectionContribEntry SC;
-
- /// See ModInfoFlags definition.
- support::ulittle16_t Flags;
-
- /// Stream Number of module debug info
- support::ulittle16_t ModDiStream;
-
- /// Size of local symbol debug info in above stream
- support::ulittle32_t SymBytes;
-
- /// Size of line number debug info in above stream
- support::ulittle32_t LineBytes;
-
- /// Size of C13 line number info in above stream
- support::ulittle32_t C13Bytes;
-
- /// Number of files contributing to this module
- support::ulittle16_t NumFiles;
-
- /// Padding so the next field is 4-byte aligned.
- char Padding1[2];
-
- /// Array of [0..NumFiles) DBI name buffer offsets. This field is a pointer
- /// in the reference implementation, but as with `Mod`, we ignore it for now
- /// since it is unused.
- support::ulittle32_t FileNameOffs;
-
- /// Name Index for src file name
- support::ulittle32_t SrcFileNameNI;
-
- /// Name Index for path to compiler PDB
- support::ulittle32_t PdbFilePathNI;
-
- /// Following this header are two zero terminated strings.
- /// char ModuleName[];
- /// char ObjFileName[];
-};
-
-/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but
-/// is abstracted here for the purposes of non-Windows platforms that don't have
-/// the GUID structure defined.
-struct PDB_UniqueId {
- uint8_t Guid[16];
-};
-
-// The header preceeding the global TPI stream.
-// This corresponds to `HDR` in PDB/dbi/tpi.h.
-struct TpiStreamHeader {
- struct EmbeddedBuf {
- support::little32_t Off;
- support::ulittle32_t Length;
- };
-
- support::ulittle32_t Version;
- support::ulittle32_t HeaderSize;
- support::ulittle32_t TypeIndexBegin;
- support::ulittle32_t TypeIndexEnd;
- support::ulittle32_t TypeRecordBytes;
-
- // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
- support::ulittle16_t HashStreamIndex;
- support::ulittle16_t HashAuxStreamIndex;
- support::ulittle32_t HashKeySize;
- support::ulittle32_t NumHashBuckets;
-
- EmbeddedBuf HashValueBuffer;
- EmbeddedBuf IndexOffsetBuffer;
- EmbeddedBuf HashAdjBuffer;
-};
-
-const uint32_t MinTpiHashBuckets = 0x1000;
-const uint32_t MaxTpiHashBuckets = 0x40000;
-
-/// The header preceeding the global PDB Stream (Stream 1)
-struct InfoStreamHeader {
- support::ulittle32_t Version;
- support::ulittle32_t Signature;
- support::ulittle32_t Age;
- PDB_UniqueId Guid;
-};
-
} // namespace pdb
} // namespace llvm
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
index 41d5e6ad64a..685a23411a3 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
@@ -10,20 +10,19 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBSYMBOLSTREAM_H
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/Support/Error.h"
namespace llvm {
-namespace msf {
-class MappedBlockStream;
-}
namespace pdb {
class PDBFile;
class SymbolStream {
public:
- SymbolStream(std::unique_ptr<msf::MappedBlockStream> Stream);
+ SymbolStream(std::unique_ptr<MappedBlockStream> Stream);
~SymbolStream();
Error reload();
@@ -34,7 +33,7 @@ public:
private:
codeview::CVSymbolArray SymbolRecords;
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<MappedBlockStream> Stream;
};
}
}
diff --git a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
index de21abe4c81..4f36d70aabe 100644
--- a/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
+++ b/gnu/llvm/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
@@ -10,9 +10,11 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamRef.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
#include "llvm/Support/raw_ostream.h"
@@ -20,18 +22,14 @@
#include "llvm/Support/Error.h"
namespace llvm {
-namespace msf {
-class MappedBlockStream;
-}
namespace pdb {
class PDBFile;
class TpiStream {
- friend class TpiStreamBuilder;
+ struct HeaderInfo;
public:
- TpiStream(const PDBFile &File,
- std::unique_ptr<msf::MappedBlockStream> Stream);
+ TpiStream(const PDBFile &File, std::unique_ptr<MappedBlockStream> Stream);
~TpiStream();
Error reload();
@@ -45,9 +43,9 @@ public:
uint32_t getHashKeySize() const;
uint32_t NumHashBuckets() const;
- msf::FixedStreamArray<support::ulittle32_t> getHashValues() const;
- msf::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
- msf::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const;
+ codeview::FixedStreamArray<support::ulittle32_t> getHashValues() const;
+ codeview::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
+ codeview::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const;
iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const;
@@ -57,16 +55,16 @@ private:
Error verifyHashValues();
const PDBFile &Pdb;
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<MappedBlockStream> Stream;
codeview::CVTypeArray TypeRecords;
- std::unique_ptr<msf::ReadableStream> HashStream;
- msf::FixedStreamArray<support::ulittle32_t> HashValues;
- msf::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
- msf::FixedStreamArray<TypeIndexOffset> HashAdjustments;
+ std::unique_ptr<MappedBlockStream> HashStream;
+ codeview::FixedStreamArray<support::ulittle32_t> HashValues;
+ codeview::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
+ codeview::FixedStreamArray<TypeIndexOffset> HashAdjustments;
- const TpiStreamHeader *Header;
+ const HeaderInfo *Header;
};
}
}
diff --git a/gnu/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/gnu/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h
index 6205927039d..d021fb29427 100644
--- a/gnu/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h
+++ b/gnu/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h
@@ -50,11 +50,11 @@ public:
llvm_unreachable("not implemented");
return 0;
}
- basic_symbol_iterator symbol_begin() const override {
+ basic_symbol_iterator symbol_begin_impl() const override {
llvm_unreachable("not implemented");
return basic_symbol_iterator(BasicSymbolRef());
}
- basic_symbol_iterator symbol_end() const override {
+ basic_symbol_iterator symbol_end_impl() const override {
llvm_unreachable("not implemented");
return basic_symbol_iterator(BasicSymbolRef());
}
@@ -79,18 +79,25 @@ public:
static ErrorOr<MemoryBufferRef>
findBitcodeInMemBuffer(MemoryBufferRef Object);
+ /// \brief Looks for summary sections in the given memory buffer,
+ /// returns true if found, else false.
+ static bool hasGlobalValueSummaryInMemBuffer(
+ MemoryBufferRef Object,
+ const DiagnosticHandlerFunction &DiagnosticHandler);
+
/// \brief Parse module summary index in the given memory buffer.
/// Return new ModuleSummaryIndexObjectFile instance containing parsed module
/// summary/index.
- static Expected<std::unique_ptr<ModuleSummaryIndexObjectFile>>
- create(MemoryBufferRef Object);
+ static ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>>
+ create(MemoryBufferRef Object,
+ const DiagnosticHandlerFunction &DiagnosticHandler);
};
}
/// Parse the module summary index out of an IR file and return the module
/// summary index object if found, or nullptr if not.
-Expected<std::unique_ptr<ModuleSummaryIndex>>
-getModuleSummaryIndexForFile(StringRef Path);
+ErrorOr<std::unique_ptr<ModuleSummaryIndex>> getModuleSummaryIndexForFile(
+ StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler);
}
#endif
diff --git a/gnu/llvm/include/llvm/Support/ELFRelocs/AMDGPU.def b/gnu/llvm/include/llvm/Support/ELFRelocs/AMDGPU.def
index c66f88d14ec..c1e6797fdb0 100644
--- a/gnu/llvm/include/llvm/Support/ELFRelocs/AMDGPU.def
+++ b/gnu/llvm/include/llvm/Support/ELFRelocs/AMDGPU.def
@@ -2,15 +2,11 @@
#error "ELF_RELOC must be defined"
#endif
-ELF_RELOC(R_AMDGPU_NONE, 0)
-ELF_RELOC(R_AMDGPU_ABS32_LO, 1)
-ELF_RELOC(R_AMDGPU_ABS32_HI, 2)
-ELF_RELOC(R_AMDGPU_ABS64, 3)
-ELF_RELOC(R_AMDGPU_REL32, 4)
-ELF_RELOC(R_AMDGPU_REL64, 5)
-ELF_RELOC(R_AMDGPU_ABS32, 6)
-ELF_RELOC(R_AMDGPU_GOTPCREL, 7)
-ELF_RELOC(R_AMDGPU_GOTPCREL32_LO, 8)
-ELF_RELOC(R_AMDGPU_GOTPCREL32_HI, 9)
-ELF_RELOC(R_AMDGPU_REL32_LO, 10)
-ELF_RELOC(R_AMDGPU_REL32_HI, 11)
+ELF_RELOC(R_AMDGPU_NONE, 0)
+ELF_RELOC(R_AMDGPU_ABS32_LO, 1)
+ELF_RELOC(R_AMDGPU_ABS32_HI, 2)
+ELF_RELOC(R_AMDGPU_ABS64, 3)
+ELF_RELOC(R_AMDGPU_REL32, 4)
+ELF_RELOC(R_AMDGPU_REL64, 5)
+ELF_RELOC(R_AMDGPU_ABS32, 6)
+ELF_RELOC(R_AMDGPU_GOTPCREL, 7)
diff --git a/gnu/llvm/include/llvm/Support/ELFRelocs/BPF.def b/gnu/llvm/include/llvm/Support/ELFRelocs/BPF.def
index 5dd7f70b696..868974d683c 100644
--- a/gnu/llvm/include/llvm/Support/ELFRelocs/BPF.def
+++ b/gnu/llvm/include/llvm/Support/ELFRelocs/BPF.def
@@ -4,5 +4,6 @@
// No relocation
ELF_RELOC(R_BPF_NONE, 0)
-ELF_RELOC(R_BPF_64_64, 1)
-ELF_RELOC(R_BPF_64_32, 10)
+// Map index in "maps" section to file descriptor
+// within ld_64 instruction.
+ELF_RELOC(R_BPF_MAP_FD, 1)
diff --git a/gnu/llvm/include/llvm/Support/MachO.def b/gnu/llvm/include/llvm/Support/MachO.def
index 57522897d0f..9ca6440dd82 100644
--- a/gnu/llvm/include/llvm/Support/MachO.def
+++ b/gnu/llvm/include/llvm/Support/MachO.def
@@ -15,37 +15,27 @@
HANDLE_LOAD_COMMAND(LC_SEGMENT, 0x00000001u, segment_command)
HANDLE_LOAD_COMMAND(LC_SYMTAB, 0x00000002u, symtab_command)
-// LC_SYMSEG is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_SYMSEG, 0x00000003u, symseg_command)
HANDLE_LOAD_COMMAND(LC_THREAD, 0x00000004u, thread_command)
HANDLE_LOAD_COMMAND(LC_UNIXTHREAD, 0x00000005u, thread_command)
-// LC_LOADFVMLIB is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_LOADFVMLIB, 0x00000006u, fvmlib_command)
-// LC_IDFVMLIB is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_IDFVMLIB, 0x00000007u, fvmlib_command)
-// LC_IDENT is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_IDENT, 0x00000008u, ident_command)
-// LC_FVMFILE is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_FVMFILE, 0x00000009u, fvmfile_command)
-// LC_PREPAGE is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_PREPAGE, 0x0000000Au, load_command)
HANDLE_LOAD_COMMAND(LC_DYSYMTAB, 0x0000000Bu, dysymtab_command)
HANDLE_LOAD_COMMAND(LC_LOAD_DYLIB, 0x0000000Cu, dylib_command)
HANDLE_LOAD_COMMAND(LC_ID_DYLIB, 0x0000000Du, dylib_command)
HANDLE_LOAD_COMMAND(LC_LOAD_DYLINKER, 0x0000000Eu, dylinker_command)
HANDLE_LOAD_COMMAND(LC_ID_DYLINKER, 0x0000000Fu, dylinker_command)
-// LC_PREBOUND_DYLIB is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_PREBOUND_DYLIB, 0x00000010u, prebound_dylib_command)
HANDLE_LOAD_COMMAND(LC_ROUTINES, 0x00000011u, routines_command)
HANDLE_LOAD_COMMAND(LC_SUB_FRAMEWORK, 0x00000012u, sub_framework_command)
HANDLE_LOAD_COMMAND(LC_SUB_UMBRELLA, 0x00000013u, sub_umbrella_command)
HANDLE_LOAD_COMMAND(LC_SUB_CLIENT, 0x00000014u, sub_client_command)
HANDLE_LOAD_COMMAND(LC_SUB_LIBRARY, 0x00000015u, sub_library_command)
-// LC_TWOLEVEL_HINTS is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_TWOLEVEL_HINTS, 0x00000016u, twolevel_hints_command)
-// LC_PREBIND_CKSUM is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_PREBIND_CKSUM, 0x00000017u, prebind_cksum_command)
-// LC_LOAD_WEAK_DYLIB is obsolete and no longer supported.
HANDLE_LOAD_COMMAND(LC_LOAD_WEAK_DYLIB, 0x80000018u, dylib_command)
HANDLE_LOAD_COMMAND(LC_SEGMENT_64, 0x00000019u, segment_command_64)
HANDLE_LOAD_COMMAND(LC_ROUTINES_64, 0x0000001Au, routines_command_64)
diff --git a/gnu/llvm/include/llvm/Transforms/Utils/MemorySSA.h b/gnu/llvm/include/llvm/Transforms/Utils/MemorySSA.h
index 408c6a157cd..befc34cb80f 100644
--- a/gnu/llvm/include/llvm/Transforms/Utils/MemorySSA.h
+++ b/gnu/llvm/include/llvm/Transforms/Utils/MemorySSA.h
@@ -110,11 +110,6 @@ class Instruction;
class MemoryAccess;
class LLVMContext;
class raw_ostream;
-enum {
- // Used to signify what the default invalid ID is for MemoryAccess's
- // getID()
- INVALID_MEMORYACCESS_ID = 0
-};
template <class T> class memoryaccess_def_iterator_base;
using memoryaccess_def_iterator = memoryaccess_def_iterator_base<MemoryAccess>;
@@ -162,8 +157,7 @@ protected:
friend class MemoryDef;
friend class MemoryPhi;
- /// \brief Used for debugging and tracking things about MemoryAccesses.
- /// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
+ /// \brief Used internally to give IDs to MemoryAccesses for printing
virtual unsigned getID() const = 0;
MemoryAccess(LLVMContext &C, unsigned Vty, BasicBlock *BB,
@@ -176,6 +170,25 @@ private:
BasicBlock *Block;
};
+template <>
+struct ilist_traits<MemoryAccess> : public ilist_default_traits<MemoryAccess> {
+ /// See details of the instruction class for why this trick works
+ // FIXME: This downcast is UB. See llvm.org/PR26753.
+ LLVM_NO_SANITIZE("object-size")
+ MemoryAccess *createSentinel() const {
+ return static_cast<MemoryAccess *>(&Sentinel);
+ }
+
+ static void destroySentinel(MemoryAccess *) {}
+
+ MemoryAccess *provideInitialHead() const { return createSentinel(); }
+ MemoryAccess *ensureHead(MemoryAccess *) const { return createSentinel(); }
+ static void noteHead(MemoryAccess *, MemoryAccess *) {}
+
+private:
+ mutable ilist_half_node<MemoryAccess> Sentinel;
+};
+
inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
MA.print(OS);
return OS;
@@ -241,7 +254,7 @@ public:
void *operator new(size_t s) { return User::operator new(s, 1); }
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
- : MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB), OptimizedID(0) {}
+ : MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB) {}
static inline bool classof(const MemoryUse *) { return true; }
static inline bool classof(const Value *MA) {
@@ -249,18 +262,6 @@ public:
}
void print(raw_ostream &OS) const override;
- void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
- if (Optimized)
- OptimizedID = DMA->getID();
- MemoryUseOrDef::setDefiningAccess(DMA);
- }
- bool isOptimized() const {
- return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
- }
- /// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
- /// be rewalked by the walker if necessary.
- /// This really should only be called by tests.
- void resetOptimized() { OptimizedID = INVALID_MEMORYACCESS_ID; }
protected:
friend class MemorySSA;
@@ -268,9 +269,6 @@ protected:
unsigned getID() const override {
llvm_unreachable("MemoryUses do not have IDs");
}
-
-private:
- unsigned int OptimizedID;
};
template <>
@@ -309,6 +307,8 @@ public:
protected:
friend class MemorySSA;
+ // For debugging only. This gets used to give memory accesses pretty numbers
+ // when printing them out
unsigned getID() const override { return ID; }
private:
@@ -387,14 +387,6 @@ public:
return block_begin() + getNumOperands();
}
- iterator_range<block_iterator> blocks() {
- return make_range(block_begin(), block_end());
- }
-
- iterator_range<const_block_iterator> blocks() const {
- return make_range(block_begin(), block_end());
- }
-
op_range incoming_values() { return operands(); }
const_op_range incoming_values() const { return operands(); }
@@ -473,6 +465,8 @@ protected:
User::allocHungoffUses(N, /* IsPhi */ true);
}
+ /// For debugging only. This gets used to give memory accesses pretty numbers
+ /// when printing them out
unsigned getID() const final { return ID; }
private:
@@ -500,6 +494,7 @@ class MemorySSAWalker;
class MemorySSA {
public:
MemorySSA(Function &, AliasAnalysis *, DominatorTree *);
+ MemorySSA(MemorySSA &&);
~MemorySSA();
MemorySSAWalker *getWalker();
@@ -508,7 +503,7 @@ public:
/// access associated with it. If passed a basic block gets the memory phi
/// node that exists for that block, if there is one. Otherwise, this will get
/// a MemoryUseOrDef.
- MemoryUseOrDef *getMemoryAccess(const Instruction *) const;
+ MemoryAccess *getMemoryAccess(const Value *) const;
MemoryPhi *getMemoryAccess(const BasicBlock *BB) const;
void dump() const;
@@ -535,12 +530,11 @@ public:
///
/// This list is not modifiable by the user.
const AccessList *getBlockAccesses(const BasicBlock *BB) const {
- return getWritableBlockAccesses(BB);
+ auto It = PerBlockAccesses.find(BB);
+ return It == PerBlockAccesses.end() ? nullptr : It->second.get();
}
- /// \brief Create an empty MemoryPhi in MemorySSA for a given basic block.
- /// Only one MemoryPhi for a block exists at a time, so this function will
- /// assert if you try to create one where it already exists.
+ /// \brief Create an empty MemoryPhi in MemorySSA
MemoryPhi *createMemoryPhi(BasicBlock *BB);
enum InsertionPlace { Beginning, End };
@@ -556,8 +550,6 @@ public:
/// will be placed. The caller is expected to keep ordering the same as
/// instructions.
/// It will return the new MemoryAccess.
- /// Note: If a MemoryAccess already exists for I, this function will make it
- /// inaccessible and it *must* have removeMemoryAccess called on it.
MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
const BasicBlock *BB,
InsertionPlace Point);
@@ -569,23 +561,12 @@ public:
/// used to replace an existing memory instruction. It will *not* create PHI
/// nodes, or verify the clobbering definition. The clobbering definition
/// must be non-null.
- /// Note: If a MemoryAccess already exists for I, this function will make it
- /// inaccessible and it *must* have removeMemoryAccess called on it.
- MemoryUseOrDef *createMemoryAccessBefore(Instruction *I,
- MemoryAccess *Definition,
- MemoryUseOrDef *InsertPt);
- MemoryUseOrDef *createMemoryAccessAfter(Instruction *I,
- MemoryAccess *Definition,
- MemoryAccess *InsertPt);
-
- // \brief Splice \p What to just before \p Where.
- //
- // In order to be efficient, the following conditions must be met:
- // - \p Where dominates \p What,
- // - All memory accesses in [\p Where, \p What) are no-alias with \p What.
- //
- // TODO: relax the MemoryDef requirement on Where.
- void spliceMemoryAccessAbove(MemoryDef *Where, MemoryUseOrDef *What);
+ MemoryAccess *createMemoryAccessBefore(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt);
+ MemoryAccess *createMemoryAccessAfter(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt);
/// \brief Remove a MemoryAccess from MemorySSA, including updating all
/// definitions and uses.
@@ -599,14 +580,6 @@ public:
/// whether MemoryAccess \p A dominates MemoryAccess \p B.
bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const;
- /// \brief Given two memory accesses in potentially different blocks,
- /// determine whether MemoryAccess \p A dominates MemoryAccess \p B.
- bool dominates(const MemoryAccess *A, const MemoryAccess *B) const;
-
- /// \brief Given a MemoryAccess and a Use, determine whether MemoryAccess \p A
- /// dominates Use \p B.
- bool dominates(const MemoryAccess *A, const Use &B) const;
-
/// \brief Verify that MemorySSA is self consistent (IE definitions dominate
/// all uses, uses appear in the right places). This is used by unit tests.
void verifyMemorySSA() const;
@@ -619,20 +592,9 @@ protected:
void verifyDomination(Function &F) const;
void verifyOrdering(Function &F) const;
- // This is used by the use optimizer class
- AccessList *getWritableBlockAccesses(const BasicBlock *BB) const {
- auto It = PerBlockAccesses.find(BB);
- return It == PerBlockAccesses.end() ? nullptr : It->second.get();
- }
-
private:
class CachingWalker;
- class OptimizeUses;
-
- CachingWalker *getWalkerImpl();
void buildMemorySSA();
- void optimizeUses();
-
void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
@@ -646,14 +608,10 @@ private:
MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace);
void removeFromLookups(MemoryAccess *);
- void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &,
- const DenseMap<const BasicBlock *, unsigned int> &);
MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *);
void renamePass(DomTreeNode *, MemoryAccess *IncomingVal,
SmallPtrSet<BasicBlock *, 16> &Visited);
AccessList *getOrCreateAccessList(const BasicBlock *);
- void renumberBlock(const BasicBlock *) const;
-
AliasAnalysis *AA;
DominatorTree *DT;
Function &F;
@@ -663,12 +621,6 @@ private:
AccessMap PerBlockAccesses;
std::unique_ptr<MemoryAccess> LiveOnEntryDef;
- // Domination mappings
- // Note that the numbering is local to a block, even though the map is
- // global.
- mutable SmallPtrSet<const BasicBlock *, 16> BlockNumberingValid;
- mutable DenseMap<const MemoryAccess *, unsigned long> BlockNumbering;
-
// Memory SSA building info
std::unique_ptr<CachingWalker> Walker;
unsigned NextID;
@@ -689,20 +641,12 @@ public:
///
class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> {
friend AnalysisInfoMixin<MemorySSAAnalysis>;
- static AnalysisKey Key;
+ static char PassID;
public:
- // Wrap MemorySSA result to ensure address stability of internal MemorySSA
- // pointers after construction. Use a wrapper class instead of plain
- // unique_ptr<MemorySSA> to avoid build breakage on MSVC.
- struct Result {
- Result(std::unique_ptr<MemorySSA> &&MSSA) : MSSA(std::move(MSSA)) {}
- MemorySSA &getMSSA() { return *MSSA.get(); }
+ typedef MemorySSA Result;
- std::unique_ptr<MemorySSA> MSSA;
- };
-
- Result run(Function &F, FunctionAnalysisManager &AM);
+ MemorySSA run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Printer pass for \c MemorySSA.
@@ -711,12 +655,12 @@ class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> {
public:
explicit MemorySSAPrinterPass(raw_ostream &OS) : OS(OS) {}
- PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Verifier pass for \c MemorySSA.
struct MemorySSAVerifierPass : PassInfoMixin<MemorySSAVerifierPass> {
- PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
/// \brief Legacy analysis pass which computes \c MemorySSA.
@@ -771,7 +715,7 @@ public:
/// store %a
/// } else {
/// 2 = MemoryDef(liveOnEntry)
- /// store %b
+ /// store %b
/// }
/// 3 = MemoryPhi(2, 1)
/// MemoryUse(3)
@@ -779,15 +723,7 @@ public:
///
/// calling this API on load(%a) will return the MemoryPhi, not the MemoryDef
/// in the if (a) branch.
- MemoryAccess *getClobberingMemoryAccess(const Instruction *I) {
- MemoryAccess *MA = MSSA->getMemoryAccess(I);
- assert(MA && "Handed an instruction that MemorySSA doesn't recognize?");
- return getClobberingMemoryAccess(MA);
- }
-
- /// Does the same thing as getClobberingMemoryAccess(const Instruction *I),
- /// but takes a MemoryAccess instead of an Instruction.
- virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) = 0;
+ virtual MemoryAccess *getClobberingMemoryAccess(const Instruction *) = 0;
/// \brief Given a potentially clobbering memory access and a new location,
/// calling this will give you the nearest dominating clobbering MemoryAccess
@@ -801,7 +737,7 @@ public:
/// will return that MemoryDef, whereas the above would return the clobber
/// starting from the use side of the memory def.
virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
- const MemoryLocation &) = 0;
+ MemoryLocation &) = 0;
/// \brief Given a memory access, invalidate anything this walker knows about
/// that access.
@@ -810,8 +746,6 @@ public:
/// the walker it uses or returns.
virtual void invalidateInfo(MemoryAccess *) {}
- virtual void verify(const MemorySSA *MSSA) { assert(MSSA == this->MSSA); }
-
protected:
friend class MemorySSA; // For updating MSSA pointer in MemorySSA move
// constructor.
@@ -822,12 +756,9 @@ protected:
/// simply returns the links as they were constructed by the builder.
class DoNothingMemorySSAWalker final : public MemorySSAWalker {
public:
- // Keep the overrides below from hiding the Instruction overload of
- // getClobberingMemoryAccess.
- using MemorySSAWalker::getClobberingMemoryAccess;
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
+ MemoryAccess *getClobberingMemoryAccess(const Instruction *) override;
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
- const MemoryLocation &) override;
+ MemoryLocation &) override;
};
using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>;
@@ -906,21 +837,29 @@ inline const_memoryaccess_def_iterator MemoryAccess::defs_end() const {
/// \brief GraphTraits for a MemoryAccess, which walks defs in the normal case,
/// and uses in the inverse case.
template <> struct GraphTraits<MemoryAccess *> {
- using NodeRef = MemoryAccess *;
+ using NodeType = MemoryAccess;
using ChildIteratorType = memoryaccess_def_iterator;
- static NodeRef getEntryNode(NodeRef N) { return N; }
- static ChildIteratorType child_begin(NodeRef N) { return N->defs_begin(); }
- static ChildIteratorType child_end(NodeRef N) { return N->defs_end(); }
+ static NodeType *getEntryNode(NodeType *N) { return N; }
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ return N->defs_begin();
+ }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return N->defs_end();
+ }
};
template <> struct GraphTraits<Inverse<MemoryAccess *>> {
- using NodeRef = MemoryAccess *;
+ using NodeType = MemoryAccess;
using ChildIteratorType = MemoryAccess::iterator;
- static NodeRef getEntryNode(NodeRef N) { return N; }
- static ChildIteratorType child_begin(NodeRef N) { return N->user_begin(); }
- static ChildIteratorType child_end(NodeRef N) { return N->user_end(); }
+ static NodeType *getEntryNode(NodeType *N) { return N; }
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ return N->user_begin();
+ }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return N->user_end();
+ }
};
/// \brief Provide an iterator that walks defs, giving both the memory access,
@@ -1005,10 +944,6 @@ inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) {
inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); }
-// Return true when MD may alias MU, return false otherwise.
-bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
- AliasAnalysis &AA);
-
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
diff --git a/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp b/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
index 768ebaa1c98..2e31ed6b5b7 100644
--- a/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
+++ b/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstream.cpp
@@ -9,20 +9,17 @@
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::msf;
ModuleSubstream::ModuleSubstream() : Kind(ModuleSubstreamKind::None) {}
-ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind,
- ReadableStreamRef Data)
+ModuleSubstream::ModuleSubstream(ModuleSubstreamKind Kind, StreamRef Data)
: Kind(Kind), Data(Data) {}
-Error ModuleSubstream::initialize(ReadableStreamRef Stream,
- ModuleSubstream &Info) {
+Error ModuleSubstream::initialize(StreamRef Stream, ModuleSubstream &Info) {
const ModuleSubsectionHeader *Header;
StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Header))
@@ -42,4 +39,4 @@ uint32_t ModuleSubstream::getRecordLength() const {
ModuleSubstreamKind ModuleSubstream::getSubstreamKind() const { return Kind; }
-ReadableStreamRef ModuleSubstream::getRecordData() const { return Data; }
+StreamRef ModuleSubstream::getRecordData() const { return Data; }
diff --git a/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp b/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
index 52479327798..6f237ee67fe 100644
--- a/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
+++ b/gnu/llvm/lib/DebugInfo/CodeView/ModuleSubstreamVisitor.cpp
@@ -8,54 +8,50 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::msf;
-Error IModuleSubstreamVisitor::visitSymbols(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitSymbols(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::Symbols, Data);
}
-Error IModuleSubstreamVisitor::visitLines(ReadableStreamRef Data,
+Error IModuleSubstreamVisitor::visitLines(StreamRef Data,
const LineSubstreamHeader *Header,
const LineInfoArray &Lines) {
return visitUnknown(ModuleSubstreamKind::Lines, Data);
}
-Error IModuleSubstreamVisitor::visitStringTable(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitStringTable(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::StringTable, Data);
}
Error IModuleSubstreamVisitor::visitFileChecksums(
- ReadableStreamRef Data, const FileChecksumArray &Checksums) {
+ StreamRef Data, const FileChecksumArray &Checksums) {
return visitUnknown(ModuleSubstreamKind::FileChecksums, Data);
}
-Error IModuleSubstreamVisitor::visitFrameData(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitFrameData(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::FrameData, Data);
}
-Error IModuleSubstreamVisitor::visitInlineeLines(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitInlineeLines(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::InlineeLines, Data);
}
-Error IModuleSubstreamVisitor::visitCrossScopeImports(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitCrossScopeImports(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CrossScopeExports, Data);
}
-Error IModuleSubstreamVisitor::visitCrossScopeExports(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitCrossScopeExports(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CrossScopeImports, Data);
}
-Error IModuleSubstreamVisitor::visitILLines(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitILLines(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::ILLines, Data);
}
-Error IModuleSubstreamVisitor::visitFuncMDTokenMap(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitFuncMDTokenMap(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::FuncMDTokenMap, Data);
}
-Error IModuleSubstreamVisitor::visitTypeMDTokenMap(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitTypeMDTokenMap(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::TypeMDTokenMap, Data);
}
-Error IModuleSubstreamVisitor::visitMergedAssemblyInput(
- ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitMergedAssemblyInput(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::MergedAssemblyInput, Data);
}
-Error IModuleSubstreamVisitor::visitCoffSymbolRVA(ReadableStreamRef Data) {
+Error IModuleSubstreamVisitor::visitCoffSymbolRVA(StreamRef Data) {
return visitUnknown(ModuleSubstreamKind::CoffSymbolRVA, Data);
}
diff --git a/gnu/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp b/gnu/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
index b951c068ca8..f63371e8c14 100644
--- a/gnu/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
+++ b/gnu/llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
@@ -8,15 +8,374 @@
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
using namespace llvm;
using namespace llvm::codeview;
//===----------------------------------------------------------------------===//
+// Type record deserialization
+//===----------------------------------------------------------------------===//
+
+ErrorOr<MemberPointerInfo>
+MemberPointerInfo::deserialize(ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ TypeIndex T = L->ClassType;
+ uint16_t R = L->Representation;
+ PointerToMemberRepresentation PMR =
+ static_cast<PointerToMemberRepresentation>(R);
+ return MemberPointerInfo(T, PMR);
+}
+
+ErrorOr<ModifierRecord> ModifierRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ TypeIndex M = L->ModifiedType;
+ uint16_t O = L->Modifiers;
+ ModifierOptions MO = static_cast<ModifierOptions>(O);
+ return ModifierRecord(M, MO);
+}
+
+ErrorOr<ProcedureRecord> ProcedureRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+ return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
+ L->NumParameters, L->ArgListType);
+}
+
+ErrorOr<MemberFunctionRecord>
+MemberFunctionRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L);
+ return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
+ L->CallConv, L->Options, L->NumParameters,
+ L->ArgListType, L->ThisAdjustment);
+}
+
+ErrorOr<MemberFuncIdRecord>
+MemberFuncIdRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return MemberFuncIdRecord(L->ClassType, L->FunctionType, Name);
+}
+
+ErrorOr<ArgListRecord> ArgListRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ if (Kind != TypeRecordKind::StringList && Kind != TypeRecordKind::ArgList)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ const Layout *L = nullptr;
+ ArrayRef<TypeIndex> Indices;
+ CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
+ return ArgListRecord(Kind, Indices);
+}
+
+ErrorOr<PointerRecord> PointerRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ PointerKind PtrKind = L->getPtrKind();
+ PointerMode Mode = L->getPtrMode();
+ uint32_t Opts = L->Attrs;
+ PointerOptions Options = static_cast<PointerOptions>(Opts);
+ uint8_t Size = L->getPtrSize();
+
+ if (L->isPointerToMember()) {
+ auto E = MemberPointerInfo::deserialize(Data);
+ if (E.getError())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E);
+ }
+
+ return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size);
+}
+
+ErrorOr<NestedTypeRecord>
+NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return NestedTypeRecord(L->Type, Name);
+}
+
+ErrorOr<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ uint64_t Size;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name);
+ return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
+}
+
+ErrorOr<ClassRecord> ClassRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ uint64_t Size = 0;
+ StringRef Name;
+ StringRef UniqueName;
+ uint16_t Props;
+ const Layout *L = nullptr;
+
+ CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
+ CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
+
+ Props = L->Properties;
+ uint16_t WrtValue = (Props & WinRTKindMask) >> WinRTKindShift;
+ WindowsRTClassKind WRT = static_cast<WindowsRTClassKind>(WrtValue);
+ uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
+ HfaKind Hfa = static_cast<HfaKind>(HfaMask);
+
+ ClassOptions Options = static_cast<ClassOptions>(Props);
+ return ClassRecord(Kind, L->MemberCount, Options, Hfa, WRT, L->FieldList,
+ L->DerivedFrom, L->VShape, Size, Name, UniqueName);
+}
+
+ErrorOr<UnionRecord> UnionRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ uint64_t Size = 0;
+ StringRef Name;
+ StringRef UniqueName;
+ uint16_t Props;
+
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Size), Name,
+ CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
+
+ Props = L->Properties;
+
+ uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
+ HfaKind Hfa = static_cast<HfaKind>(HfaMask);
+ ClassOptions Options = static_cast<ClassOptions>(Props);
+ return UnionRecord(L->MemberCount, Options, Hfa, L->FieldList, Size, Name,
+ UniqueName);
+}
+
+ErrorOr<EnumRecord> EnumRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ StringRef UniqueName;
+ CV_DESERIALIZE(Data, L, Name,
+ CV_CONDITIONAL_FIELD(UniqueName, L->hasUniqueName()));
+
+ uint16_t P = L->Properties;
+ ClassOptions Options = static_cast<ClassOptions>(P);
+ return EnumRecord(L->NumEnumerators, Options, L->FieldListType, Name,
+ UniqueName, L->UnderlyingType);
+}
+
+ErrorOr<BitFieldRecord> BitFieldRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L);
+ return BitFieldRecord(L->Type, L->BitSize, L->BitOffset);
+}
+
+ErrorOr<VFTableShapeRecord>
+VFTableShapeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ std::vector<VFTableSlotKind> Slots;
+ uint16_t Count = L->VFEntryCount;
+ while (Count > 0) {
+ if (Data.empty())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ // Process up to 2 nibbles at a time (if there are at least 2 remaining)
+ uint8_t Value = Data[0] & 0x0F;
+ Slots.push_back(static_cast<VFTableSlotKind>(Value));
+ if (--Count > 0) {
+ Value = (Data[0] & 0xF0) >> 4;
+ Slots.push_back(static_cast<VFTableSlotKind>(Value));
+ --Count;
+ }
+ Data = Data.slice(1);
+ }
+
+ return VFTableShapeRecord(Slots);
+}
+
+ErrorOr<TypeServer2Record>
+TypeServer2Record::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
+}
+
+ErrorOr<StringIdRecord> StringIdRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return StringIdRecord(L->id, Name);
+}
+
+ErrorOr<FuncIdRecord> FuncIdRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
+}
+
+ErrorOr<UdtSourceLineRecord>
+UdtSourceLineRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L);
+ return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
+}
+
+ErrorOr<BuildInfoRecord> BuildInfoRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ ArrayRef<TypeIndex> Indices;
+ CV_DESERIALIZE(Data, L, CV_ARRAY_FIELD_N(Indices, L->NumArgs));
+ return BuildInfoRecord(Indices);
+}
+
+ErrorOr<VFTableRecord> VFTableRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ std::vector<StringRef> Names;
+ CV_DESERIALIZE(Data, L, Name, CV_ARRAY_FIELD_TAIL(Names));
+ return VFTableRecord(L->CompleteClass, L->OverriddenVFTable, L->VFPtrOffset,
+ Name, Names);
+}
+
+ErrorOr<OneMethodRecord> OneMethodRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ int32_t VFTableOffset = -1;
+
+ CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(VFTableOffset,
+ L->Attrs.isIntroducedVirtual()),
+ Name);
+
+ MethodOptions Options = L->Attrs.getFlags();
+ MethodKind MethKind = L->Attrs.getMethodKind();
+ MemberAccess Access = L->Attrs.getAccess();
+ OneMethodRecord Method(L->Type, MethKind, Options, Access, VFTableOffset,
+ Name);
+ // Validate the vftable offset.
+ if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ return Method;
+}
+
+ErrorOr<MethodOverloadListRecord>
+MethodOverloadListRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ std::vector<OneMethodRecord> Methods;
+ while (!Data.empty()) {
+ const Layout *L = nullptr;
+ int32_t VFTableOffset = -1;
+ CV_DESERIALIZE(Data, L, CV_CONDITIONAL_FIELD(
+ VFTableOffset, L->Attrs.isIntroducedVirtual()));
+
+ MethodOptions Options = L->Attrs.getFlags();
+ MethodKind MethKind = L->Attrs.getMethodKind();
+ MemberAccess Access = L->Attrs.getAccess();
+
+ Methods.emplace_back(L->Type, MethKind, Options, Access, VFTableOffset,
+ StringRef());
+
+ // Validate the vftable offset.
+ auto &Method = Methods.back();
+ if (Method.isIntroducingVirtual() && Method.getVFTableOffset() < 0)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ }
+ return MethodOverloadListRecord(Methods);
+}
+
+ErrorOr<OverloadedMethodRecord>
+OverloadedMethodRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
+}
+
+ErrorOr<DataMemberRecord>
+DataMemberRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ uint64_t Offset;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), Name);
+ return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
+}
+
+ErrorOr<StaticDataMemberRecord>
+StaticDataMemberRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Name);
+ return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
+}
+
+ErrorOr<EnumeratorRecord>
+EnumeratorRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ APSInt Value;
+ StringRef Name;
+ CV_DESERIALIZE(Data, L, Value, Name);
+ return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
+}
+
+ErrorOr<VFPtrRecord> VFPtrRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+ return VFPtrRecord(L->Type);
+}
+
+ErrorOr<BaseClassRecord> BaseClassRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ uint64_t Offset;
+ CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset));
+ return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
+}
+
+ErrorOr<VirtualBaseClassRecord>
+VirtualBaseClassRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ uint64_t Offset;
+ uint64_t Index;
+ CV_DESERIALIZE(Data, L, CV_NUMERIC_FIELD(Offset), CV_NUMERIC_FIELD(Index));
+ return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType, L->VBPtrType,
+ Offset, Index);
+}
+
+ErrorOr<ListContinuationRecord>
+ListContinuationRecord::deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ CV_DESERIALIZE(Data, L);
+ return ListContinuationRecord(L->ContinuationIndex);
+}
+
+//===----------------------------------------------------------------------===//
// Type index remapping
//===----------------------------------------------------------------------===//
@@ -78,7 +437,7 @@ bool PointerRecord::remapTypeIndices(ArrayRef<TypeIndex> IndexMap) {
bool Success = true;
Success &= remapIndex(IndexMap, ReferentType);
if (isPointerToMember())
- Success &= MemberInfo->remapTypeIndices(IndexMap);
+ Success &= MemberInfo.remapTypeIndices(IndexMap);
return Success;
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
index 4f4a0cf6578..3c0586c728f 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
+
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
@@ -22,17 +22,49 @@
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
#include "llvm/Object/COFF.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;
+namespace {
+// Some of the values are stored in bitfields. Since this needs to be portable
+// across compilers and architectures (big / little endian in particular) we
+// can't use the actual structures below, but must instead do the shifting
+// and masking ourselves. The struct definitions are provided for reference.
+
+// struct DbiFlags {
+// uint16_t IncrementalLinking : 1; // True if linked incrementally
+// uint16_t IsStripped : 1; // True if private symbols were stripped.
+// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes.
+// uint16_t Reserved : 13;
+//};
+const uint16_t FlagIncrementalMask = 0x0001;
+const uint16_t FlagStrippedMask = 0x0002;
+const uint16_t FlagHasCTypesMask = 0x0004;
+
+// struct DbiBuildNo {
+// uint16_t MinorVersion : 8;
+// uint16_t MajorVersion : 7;
+// uint16_t NewVersionFormat : 1;
+//};
+const uint16_t BuildMinorMask = 0x00FF;
+const uint16_t BuildMinorShift = 0;
+
+const uint16_t BuildMajorMask = 0x7F00;
+const uint16_t BuildMajorShift = 8;
+
+struct FileInfoSubstreamHeader {
+ ulittle16_t NumModules; // Total # of modules, should match number of
+ // records in the ModuleInfo substream.
+ ulittle16_t NumSourceFiles; // Total # of source files. This value is not
+ // accurate because PDB actually supports more
+ // than 64k source files, so we ignore it and
+ // compute the value from other stream fields.
+};
+}
+
template <typename ContribType>
static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
StreamReader &Reader) {
@@ -49,14 +81,15 @@ static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)), Header(nullptr) {
+ static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!");
}
-DbiStream::~DbiStream() = default;
+DbiStream::~DbiStream() {}
Error DbiStream::reload() {
StreamReader Reader(*Stream);
- if (Stream->getLength() < sizeof(DbiStreamHeader))
+ if (Stream->getLength() < sizeof(HeaderInfo))
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI Stream does not contain a header.");
if (auto EC = Reader.readObject(Header))
@@ -83,7 +116,7 @@ Error DbiStream::reload() {
"DBI Age does not match PDB Age.");
if (Stream->getLength() !=
- sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
+ sizeof(HeaderInfo) + Header->ModiSubstreamSize +
Header->SecContrSubstreamSize + Header->SectionMapSize +
Header->FileInfoSize + Header->TypeServerSize +
Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
@@ -109,11 +142,14 @@ Error DbiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"DBI type server substream not aligned.");
- if (auto EC =
- Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
- return EC;
- if (auto EC = initializeModInfoArray())
+ // Since each ModInfo in the stream is a variable length, we have to iterate
+ // them to know how many there actually are.
+ VarStreamArray<ModInfo> ModInfoArray;
+ if (auto EC = Reader.readArray(ModInfoArray, Header->ModiSubstreamSize))
return EC;
+ for (auto &Info : ModInfoArray) {
+ ModuleInfos.emplace_back(Info);
+ }
if (auto EC = Reader.readStreamRef(SecContrSubstream,
Header->SecContrSubstreamSize))
@@ -173,27 +209,25 @@ uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
uint16_t DbiStream::getFlags() const { return Header->Flags; }
bool DbiStream::isIncrementallyLinked() const {
- return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
+ return (Header->Flags & FlagIncrementalMask) != 0;
}
bool DbiStream::hasCTypes() const {
- return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
+ return (Header->Flags & FlagHasCTypesMask) != 0;
}
bool DbiStream::isStripped() const {
- return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
+ return (Header->Flags & FlagStrippedMask) != 0;
}
uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
uint16_t DbiStream::getBuildMajorVersion() const {
- return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
- DbiBuildNo::BuildMajorShift;
+ return (Header->BuildNumber & BuildMajorMask) >> BuildMajorShift;
}
uint16_t DbiStream::getBuildMinorVersion() const {
- return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
- DbiBuildNo::BuildMinorShift;
+ return (Header->BuildNumber & BuildMinorMask) >> BuildMinorShift;
}
uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
@@ -209,20 +243,21 @@ PDB_Machine DbiStream::getMachineType() const {
return static_cast<PDB_Machine>(Machine);
}
-msf::FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
+codeview::FixedStreamArray<object::coff_section>
+DbiStream::getSectionHeaders() {
return SectionHeaders;
}
-msf::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
+codeview::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
return FpoRecords;
}
ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
-msf::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
+codeview::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
return SectionMap;
}
-void DbiStream::visitSectionContributions(
+void llvm::pdb::DbiStream::visitSectionContributions(
ISectionContribVisitor &Visitor) const {
if (SectionContribVersion == DbiSecContribVer60) {
for (auto &SC : SectionContribs)
@@ -250,24 +285,6 @@ Error DbiStream::initializeSectionContributionData() {
"Unsupported DBI Section Contribution version");
}
-Error DbiStream::initializeModInfoArray() {
- if (ModInfoSubstream.getLength() == 0)
- return Error::success();
-
- // Since each ModInfo in the stream is a variable length, we have to iterate
- // them to know how many there actually are.
- StreamReader Reader(ModInfoSubstream);
-
- VarStreamArray<ModInfo> ModInfoArray;
- if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
- return EC;
- for (auto &Info : ModInfoArray) {
- ModuleInfos.emplace_back(Info);
- }
-
- return Error::success();
-}
-
// Initializes this->SectionHeaders.
Error DbiStream::initializeSectionHeadersData() {
if (DbgStreams.size() == 0)
@@ -277,21 +294,22 @@ Error DbiStream::initializeSectionHeadersData() {
if (StreamNum >= Pdb.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
- auto SHS = MappedBlockStream::createIndexedStream(
- Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
+ auto SHS = MappedBlockStream::createIndexedStream(StreamNum, Pdb);
+ if (!SHS)
+ return SHS.takeError();
- size_t StreamLen = SHS->getLength();
+ 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);
- msf::StreamReader Reader(*SHS);
+ codeview::StreamReader 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);
+ SectionHeaderStream = std::move(*SHS);
return Error::success();
}
@@ -303,26 +321,27 @@ Error DbiStream::initializeFpoRecords() {
uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
// This means there is no FPO data.
- if (StreamNum == kInvalidStreamIndex)
+ if (StreamNum == InvalidStreamIndex)
return Error::success();
if (StreamNum >= Pdb.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
- auto FS = MappedBlockStream::createIndexedStream(
- Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
+ auto FS = MappedBlockStream::createIndexedStream(StreamNum, Pdb);
+ if (!FS)
+ return FS.takeError();
- size_t StreamLen = FS->getLength();
+ size_t StreamLen = (*FS)->getLength();
if (StreamLen % sizeof(object::FpoData))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupted New FPO stream.");
size_t NumRecords = StreamLen / sizeof(object::FpoData);
- msf::StreamReader Reader(*FS);
+ codeview::StreamReader Reader(**FS);
if (auto EC = Reader.readArray(FpoRecords, NumRecords))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupted New FPO stream.");
- FpoStream = std::move(FS);
+ FpoStream = std::move(*FS);
return Error::success();
}
@@ -340,6 +359,18 @@ Error DbiStream::initializeSectionMapData() {
}
Error DbiStream::initializeFileInfo() {
+ // The layout of the FileInfoSubstream is like this:
+ // struct {
+ // ulittle16_t NumModules;
+ // ulittle16_t NumSourceFiles;
+ // ulittle16_t ModIndices[NumModules];
+ // ulittle16_t ModFileCounts[NumModules];
+ // ulittle32_t FileNameOffsets[NumSourceFiles];
+ // char Names[][NumSourceFiles];
+ // };
+ // with the caveat that `NumSourceFiles` cannot be trusted, so
+ // it is computed by summing `ModFileCounts`.
+ //
if (FileInfoSubstream.getLength() == 0)
return Error::success();
@@ -406,10 +437,7 @@ Error DbiStream::initializeFileInfo() {
}
uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
- uint16_t T = static_cast<uint16_t>(Type);
- if (T >= DbgStreams.size())
- return kInvalidStreamIndex;
- return DbgStreams[T];
+ return DbgStreams[static_cast<uint16_t>(Type)];
}
Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
@@ -424,3 +452,11 @@ Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
return std::move(EC);
return Name;
}
+
+Error DbiStream::commit() {
+ StreamWriter Writer(*Stream);
+ if (auto EC = Writer.writeObject(*Header))
+ return EC;
+
+ return Error::success();
+}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
index 1d5b8d693b1..34ff8ae3a90 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/DbiStreamBuilder.cpp
@@ -9,28 +9,18 @@
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/MSF/MSFBuilder.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Support/COFF.h"
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::msf;
using namespace llvm::pdb;
-namespace {
-class ModiSubstreamBuilder {};
-}
-
-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), DbgStreams((int)DbgHeaderType::Max) {}
+DbiStreamBuilder::DbiStreamBuilder()
+ : Age(1), BuildNumber(0), PdbDllVersion(0), PdbDllRbld(0), Flags(0),
+ MachineType(PDB_Machine::x86) {}
void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
@@ -46,207 +36,24 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
-void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) {
- SectionContribs = Arr;
-}
-
-void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
- SectionMap = SecMap;
-}
-
-Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
- ArrayRef<uint8_t> Data) {
- if (DbgStreams[(int)Type].StreamNumber)
- return make_error<RawError>(raw_error_code::duplicate_entry,
- "The specified stream type already exists");
- auto ExpectedIndex = Msf.addStream(Data.size());
- if (!ExpectedIndex)
- return ExpectedIndex.takeError();
- uint32_t Index = std::move(*ExpectedIndex);
- DbgStreams[(int)Type].Data = Data;
- DbgStreams[(int)Type].StreamNumber = Index;
- return Error::success();
-}
-
uint32_t DbiStreamBuilder::calculateSerializedLength() const {
// For now we only support serializing the header.
- return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() +
- calculateModiSubstreamSize() + calculateSectionContribsStreamSize() +
- calculateSectionMapStreamSize() + calculateDbgStreamsSize();
-}
-
-Error DbiStreamBuilder::addModuleInfo(StringRef ObjFile, StringRef Module) {
- auto Entry = llvm::make_unique<ModuleInfo>();
- ModuleInfo *M = Entry.get();
- Entry->Mod = Module;
- Entry->Obj = ObjFile;
- auto Result = ModuleInfos.insert(std::make_pair(Module, std::move(Entry)));
- if (!Result.second)
- return make_error<RawError>(raw_error_code::duplicate_entry,
- "The specified module already exists");
- ModuleInfoList.push_back(M);
- return Error::success();
-}
-
-Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) {
- auto ModIter = ModuleInfos.find(Module);
- if (ModIter == ModuleInfos.end())
- return make_error<RawError>(raw_error_code::no_entry,
- "The specified module was not found");
- uint32_t Index = SourceFileNames.size();
- SourceFileNames.insert(std::make_pair(File, Index));
- auto &ModEntry = *ModIter;
- ModEntry.second->SourceFiles.push_back(File);
- return Error::success();
-}
-
-uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
- uint32_t Size = 0;
- for (const auto &M : ModuleInfoList) {
- Size += sizeof(ModuleInfoHeader);
- Size += M->Mod.size() + 1;
- Size += M->Obj.size() + 1;
- }
- return alignTo(Size, sizeof(uint32_t));
-}
-
-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::calculateFileInfoSubstreamSize() const {
- uint32_t Size = 0;
- Size += sizeof(ulittle16_t); // NumModules
- Size += sizeof(ulittle16_t); // NumSourceFiles
- Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices
- Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts
- uint32_t NumFileInfos = 0;
- for (const auto &M : ModuleInfoList)
- NumFileInfos += M->SourceFiles.size();
- Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets
- 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::generateModiSubstream() {
- uint32_t Size = calculateModiSubstreamSize();
- auto Data = Allocator.Allocate<uint8_t>(Size);
-
- ModInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
-
- StreamWriter ModiWriter(ModInfoBuffer);
- for (const auto &M : ModuleInfoList) {
- ModuleInfoHeader Layout = {};
- Layout.ModDiStream = kInvalidStreamIndex;
- Layout.NumFiles = M->SourceFiles.size();
- if (auto EC = ModiWriter.writeObject(Layout))
- return EC;
- if (auto EC = ModiWriter.writeZeroString(M->Mod))
- return EC;
- if (auto EC = ModiWriter.writeZeroString(M->Obj))
- return EC;
- }
- if (ModiWriter.bytesRemaining() > sizeof(uint32_t))
- return make_error<RawError>(raw_error_code::invalid_format,
- "Unexpected bytes in Modi Stream Data");
- return Error::success();
-}
-
-Error DbiStreamBuilder::generateFileInfoSubstream() {
- uint32_t Size = calculateFileInfoSubstreamSize();
- uint32_t NameSize = calculateNamesBufferSize();
- auto Data = Allocator.Allocate<uint8_t>(Size);
- uint32_t NamesOffset = Size - NameSize;
-
- FileInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size));
-
- WritableStreamRef MetadataBuffer =
- WritableStreamRef(FileInfoBuffer).keep_front(NamesOffset);
- StreamWriter MetadataWriter(MetadataBuffer);
-
- uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.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 : ModuleInfoList) {
- FileCount = static_cast<uint16_t>(MI->SourceFiles.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 = WritableStreamRef(FileInfoBuffer).drop_front(NamesOffset);
- StreamWriter NameBufferWriter(NamesBuffer);
- for (auto &Name : SourceFileNames) {
- Name.second = NameBufferWriter.getOffset();
- if (auto EC = NameBufferWriter.writeZeroString(Name.getKey()))
- return EC;
- }
-
- for (const auto MI : ModuleInfoList) {
- for (StringRef Name : MI->SourceFiles) {
- 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 (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();
-
- DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>();
-
- if (auto EC = generateModiSubstream())
- return EC;
- if (auto EC = generateFileInfoSubstream())
- return EC;
-
+ return sizeof(DbiStream::HeaderInfo);
+}
+
+Expected<std::unique_ptr<DbiStream>> DbiStreamBuilder::build(PDBFile &File) {
+ if (!VerHeader.hasValue())
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Missing DBI Stream Version");
+
+ auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, File);
+ if (!DbiS)
+ return DbiS.takeError();
+ auto DS = std::move(*DbiS);
+ DbiStream::HeaderInfo *H =
+ static_cast<DbiStream::HeaderInfo *>(DS->getAllocator().Allocate(
+ sizeof(DbiStream::HeaderInfo),
+ llvm::AlignOf<DbiStream::HeaderInfo>::Alignment));
H->VersionHeader = *VerHeader;
H->VersionSignature = -1;
H->Age = Age;
@@ -257,156 +64,18 @@ Error DbiStreamBuilder::finalize() {
H->MachineType = static_cast<uint16_t>(MachineType);
H->ECSubstreamSize = 0;
- H->FileInfoSize = FileInfoBuffer.getLength();
- H->ModiSubstreamSize = ModInfoBuffer.getLength();
- H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t);
- H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
- H->SectionMapSize = calculateSectionMapStreamSize();
+ H->FileInfoSize = 0;
+ H->ModiSubstreamSize = 0;
+ H->OptionalDbgHdrSize = 0;
+ H->SecContrSubstreamSize = 0;
+ H->SectionMapSize = 0;
H->TypeServerSize = 0;
- H->SymRecordStreamIndex = kInvalidStreamIndex;
- H->PublicSymbolStreamIndex = kInvalidStreamIndex;
- H->MFCTypeServerIndex = kInvalidStreamIndex;
- H->GlobalSymbolStreamIndex = kInvalidStreamIndex;
-
- Header = H;
- return Error::success();
-}
-
-Error DbiStreamBuilder::finalizeMsfLayout() {
- 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_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;
-}
-
-// A utility function to create Section Contributions
-// for a given input sections.
-std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs(
- ArrayRef<object::coff_section> SecHdrs) {
- std::vector<SectionContrib> Ret;
-
- // Create a SectionContrib for each input section.
- for (auto &Sec : SecHdrs) {
- Ret.emplace_back();
- auto &Entry = Ret.back();
- memset(&Entry, 0, sizeof(Entry));
-
- Entry.Off = Sec.PointerToRawData;
- Entry.Size = Sec.SizeOfRawData;
- Entry.Characteristics = Sec.Characteristics;
- }
- return Ret;
-}
-
-// A utility function to create a Section Map for a given list of COFF sections.
-//
-// 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.
-std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap(
- ArrayRef<llvm::object::coff_section> SecHdrs) {
- std::vector<SecMapEntry> Ret;
- int Idx = 0;
-
- auto Add = [&]() -> SecMapEntry & {
- Ret.emplace_back();
- auto &Entry = Ret.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;
-
- return Ret;
-}
-
-Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
- const msf::WritableStream &Buffer) {
- if (auto EC = finalize())
- return EC;
-
- auto InfoS =
- WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI);
-
- StreamWriter Writer(*InfoS);
- if (auto EC = Writer.writeObject(*Header))
- return EC;
-
- if (auto EC = Writer.writeStreamRef(ModInfoBuffer))
- return EC;
-
- if (!SectionContribs.empty()) {
- if (auto EC = Writer.writeEnum(DbiSecContribVer60))
- return EC;
- if (auto EC = Writer.writeArray(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(SectionMap))
- return EC;
- }
-
- if (auto EC = Writer.writeStreamRef(FileInfoBuffer))
- return EC;
-
- for (auto &Stream : DbgStreams)
- if (auto EC = Writer.writeInteger(Stream.StreamNumber))
- return EC;
-
- for (auto &Stream : DbgStreams) {
- if (Stream.StreamNumber == kInvalidStreamIndex)
- continue;
- auto WritableStream = WritableMappedBlockStream::createIndexedStream(
- Layout, Buffer, Stream.StreamNumber);
- StreamWriter DbgStreamWriter(*WritableStream);
- if (auto EC = DbgStreamWriter.writeArray(Stream.Data))
- return EC;
- }
-
- if (Writer.bytesRemaining() > 0)
- return make_error<RawError>(raw_error_code::invalid_format,
- "Unexpected bytes found in DBI Stream");
- return Error::success();
+ H->SymRecordStreamIndex = DbiStream::InvalidStreamIndex;
+ H->PublicSymbolStreamIndex = DbiStream::InvalidStreamIndex;
+ H->MFCTypeServerIndex = DbiStream::InvalidStreamIndex;
+ H->GlobalSymbolStreamIndex = DbiStream::InvalidStreamIndex;
+
+ auto Dbi = llvm::make_unique<DbiStream>(File, std::move(DS));
+ Dbi->Header = H;
+ return std::move(Dbi);
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp
index b9f685ec69d..23cb55786d7 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/Hash.cpp
@@ -11,7 +11,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/JamCRC.h"
using namespace llvm;
using namespace llvm::support;
@@ -74,13 +73,59 @@ uint32_t pdb::hashStringV2(StringRef Str) {
Hash ^= (Hash >> 6);
}
- return Hash * 1664525U + 1013904223U;
+ return Hash * 1664525L + 1013904223L;
}
+static const uint32_t V8HashTable[] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
+ 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
+ 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
+ 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
+ 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
+ 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
+ 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
+ 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+ 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
+ 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
+ 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
+ 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
+ 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
+ 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
+ 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
+ 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
+ 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
+ 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
+ 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
+ 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
+ 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
+ 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
+};
+
// Corresponds to `SigForPbCb` in langapi/shared/crc32.h.
uint32_t pdb::hashBufferV8(ArrayRef<uint8_t> Buf) {
- JamCRC JC(/*Init=*/0U);
- JC.update(makeArrayRef<char>(reinterpret_cast<const char *>(Buf.data()),
- Buf.size()));
- return JC.getCRC();
+ uint32_t Hash = 0;
+ for (uint8_t Byte : Buf)
+ Hash = (Hash >> 8) ^ V8HashTable[(Hash & 0xff) ^ Byte];
+ return Hash;
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
index f19535d1180..c33a764587c 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStream.cpp
@@ -10,25 +10,24 @@
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::msf;
using namespace llvm::pdb;
InfoStream::InfoStream(std::unique_ptr<MappedBlockStream> Stream)
: Stream(std::move(Stream)) {}
Error InfoStream::reload() {
- StreamReader Reader(*Stream);
+ codeview::StreamReader Reader(*Stream);
- const InfoStreamHeader *H;
+ const HeaderInfo *H;
if (auto EC = Reader.readObject(H))
return joinErrors(
std::move(EC),
@@ -75,3 +74,17 @@ uint32_t InfoStream::getSignature() const { return Signature; }
uint32_t InfoStream::getAge() const { return Age; }
PDB_UniqueId InfoStream::getGuid() const { return Guid; }
+
+Error InfoStream::commit() {
+ StreamWriter Writer(*Stream);
+
+ HeaderInfo H;
+ H.Age = Age;
+ H.Signature = Signature;
+ H.Version = Version;
+ H.Guid = Guid;
+ if (auto EC = Writer.writeObject(H))
+ return EC;
+
+ return NamedStreams.commit(Writer);
+}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
index 73fbf853b4f..7be9cc32db9 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/InfoStreamBuilder.cpp
@@ -9,20 +9,16 @@
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
-#include "llvm/DebugInfo/MSF/MSFBuilder.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::msf;
using namespace llvm::pdb;
-InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf)
- : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Sig(-1), Age(0) {}
+InfoStreamBuilder::InfoStreamBuilder() {}
void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
@@ -37,29 +33,35 @@ NameMapBuilder &InfoStreamBuilder::getNamedStreamsBuilder() {
}
uint32_t InfoStreamBuilder::calculateSerializedLength() const {
- return sizeof(InfoStreamHeader) + NamedStreams.calculateSerializedLength();
+ return sizeof(InfoStream::HeaderInfo) +
+ NamedStreams.calculateSerializedLength();
}
-Error InfoStreamBuilder::finalizeMsfLayout() {
- uint32_t Length = calculateSerializedLength();
- if (auto EC = Msf.setStreamSize(StreamPDB, Length))
- return EC;
- return Error::success();
-}
-
-Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
- const msf::WritableStream &Buffer) const {
- auto InfoS =
- WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamPDB);
- StreamWriter Writer(*InfoS);
-
- InfoStreamHeader H;
- H.Age = Age;
- H.Signature = Sig;
- H.Version = Ver;
- H.Guid = Guid;
- if (auto EC = Writer.writeObject(H))
- return EC;
+Expected<std::unique_ptr<InfoStream>> InfoStreamBuilder::build(PDBFile &File) {
+ if (!Ver.hasValue())
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Missing PDB Stream Version");
+ if (!Sig.hasValue())
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Missing PDB Stream Signature");
+ if (!Age.hasValue())
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Missing PDB Stream Age");
+ if (!Guid.hasValue())
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Missing PDB Stream Guid");
- return NamedStreams.commit(Writer);
+ auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, File);
+ if (!InfoS)
+ return InfoS.takeError();
+ auto Info = llvm::make_unique<InfoStream>(std::move(*InfoS));
+ Info->Version = *Ver;
+ Info->Signature = *Sig;
+ Info->Age = *Age;
+ Info->Guid = *Guid;
+ auto NS = NamedStreams.build();
+ if (!NS)
+ return NS.takeError();
+ Info->NamedStreams = **NS;
+ return std::move(Info);
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
index b34d7700d03..bae135f77bc 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp
@@ -7,27 +7,76 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/MathExtras.h"
-#include <cstdint>
using namespace llvm;
-using namespace llvm::msf;
using namespace llvm::pdb;
using namespace llvm::support;
-ModInfo::ModInfo() = default;
-
-ModInfo::ModInfo(const ModInfo &Info) = default;
-
-ModInfo::~ModInfo() = default;
+namespace {
+
+struct SCBytes {
+ ulittle16_t Section;
+ char Padding1[2];
+ little32_t Offset;
+ little32_t Size;
+ ulittle32_t Characteristics;
+ ulittle16_t ModuleIndex;
+ char Padding2[2];
+ ulittle32_t DataCrc;
+ ulittle32_t RelocCrc;
+};
+
+// struct Flags {
+// uint16_t fWritten : 1; // True if ModInfo is dirty
+// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?)
+// uint16_t unused : 6; // Reserved
+// uint16_t iTSM : 8; // Type Server Index for this module
+//};
+const uint16_t HasECFlagMask = 0x2;
+
+const uint16_t TypeServerIndexMask = 0xFF00;
+const uint16_t TypeServerIndexShift = 8;
+}
-Error ModInfo::initialize(ReadableStreamRef Stream, ModInfo &Info) {
- StreamReader Reader(Stream);
+struct ModInfo::FileLayout {
+ ulittle32_t Mod; // Currently opened module. This field is a
+ // pointer in the reference implementation, but
+ // that won't work on 64-bit systems, and anyway
+ // it doesn't make sense to read a pointer from a
+ // file. For now it is unused, so just ignore it.
+ SCBytes SC; // First section contribution of this module.
+ ulittle16_t Flags; // See Flags definition.
+ ulittle16_t ModDiStream; // Stream Number of module debug info
+ ulittle32_t SymBytes; // Size of local symbol debug info in above stream
+ ulittle32_t LineBytes; // Size of line number debug info in above stream
+ ulittle32_t C13Bytes; // Size of C13 line number info in above stream
+ ulittle16_t NumFiles; // Number of files contributing to this module
+ char Padding1[2]; // Padding so the next field is 4-byte aligned.
+ ulittle32_t FileNameOffs; // array of [0..NumFiles) DBI name buffer offsets.
+ // This field is a pointer in the reference
+ // implementation, but as with `Mod`, we ignore it
+ // for now since it is unused.
+ ulittle32_t SrcFileNameNI; // Name Index for src file name
+ ulittle32_t PdbFilePathNI; // Name Index for path to compiler PDB
+ // Null terminated Module name
+ // Null terminated Obj File Name
+};
+
+ModInfo::ModInfo() : Layout(nullptr) {}
+
+ModInfo::ModInfo(const ModInfo &Info)
+ : ModuleName(Info.ModuleName), ObjFileName(Info.ObjFileName),
+ Layout(Info.Layout) {}
+
+ModInfo::~ModInfo() {}
+
+Error ModInfo::initialize(codeview::StreamRef Stream, ModInfo &Info) {
+ codeview::StreamReader Reader(Stream);
if (auto EC = Reader.readObject(Info.Layout))
return EC;
@@ -39,13 +88,10 @@ Error ModInfo::initialize(ReadableStreamRef Stream, ModInfo &Info) {
return Error::success();
}
-bool ModInfo::hasECInfo() const {
- return (Layout->Flags & ModInfoFlags::HasECFlagMask) != 0;
-}
+bool ModInfo::hasECInfo() const { return (Layout->Flags & HasECFlagMask) != 0; }
uint16_t ModInfo::getTypeServerIndex() const {
- return (Layout->Flags & ModInfoFlags::TypeServerIndexMask) >>
- ModInfoFlags::TypeServerIndexShift;
+ return (Layout->Flags & TypeServerIndexMask) >> TypeServerIndexShift;
}
uint16_t ModInfo::getModuleStreamIndex() const { return Layout->ModDiStream; }
@@ -75,7 +121,7 @@ StringRef ModInfo::getObjFileName() const { return ObjFileName; }
uint32_t ModInfo::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);
+ uint32_t Size = sizeof(FileLayout) + M + O;
+ Size = llvm::alignTo(Size, 4);
return Size;
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp
index 0ffc5b7d44a..3415fcd4779 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp
@@ -7,43 +7,39 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
-#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
+
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cstdint>
using namespace llvm;
-using namespace llvm::msf;
using namespace llvm::pdb;
ModStream::ModStream(const ModInfo &Module,
std::unique_ptr<MappedBlockStream> Stream)
: Mod(Module), Stream(std::move(Stream)) {}
-ModStream::~ModStream() = default;
+ModStream::~ModStream() {}
Error ModStream::reload() {
- StreamReader Reader(*Stream);
+ codeview::StreamReader Reader(*Stream);
uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize();
uint32_t C11Size = Mod.getLineInfoByteSize();
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");
+ return llvm::make_error<RawError>(raw_error_code::corrupt_file,
+ "Module has both C11 and C13 line info");
- ReadableStreamRef S;
+ codeview::StreamRef S;
- if (auto EC = Reader.readInteger(Signature))
+ uint32_t SymbolSubstreamSig = 0;
+ if (auto EC = Reader.readInteger(SymbolSubstreamSig))
return EC;
if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4))
return EC;
@@ -53,7 +49,7 @@ Error ModStream::reload() {
if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size))
return EC;
- StreamReader LineReader(C13LinesSubstream);
+ codeview::StreamReader LineReader(C13LinesSubstream);
if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining()))
return EC;
@@ -63,8 +59,8 @@ Error ModStream::reload() {
if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize))
return EC;
if (Reader.bytesRemaining() > 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Unexpected bytes in module stream.");
+ return llvm::make_error<RawError>(raw_error_code::corrupt_file,
+ "Unexpected bytes in module stream.");
return Error::success();
}
@@ -73,13 +69,14 @@ iterator_range<codeview::CVSymbolArray::Iterator>
ModStream::symbols(bool *HadError) const {
// It's OK if the stream is empty.
if (SymbolsSubstream.getUnderlyingStream().getLength() == 0)
- return make_range(SymbolsSubstream.end(), SymbolsSubstream.end());
- return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end());
+ return llvm::make_range(SymbolsSubstream.end(), SymbolsSubstream.end());
+ return llvm::make_range(SymbolsSubstream.begin(HadError),
+ SymbolsSubstream.end());
}
iterator_range<codeview::ModuleSubstreamArray::Iterator>
ModStream::lines(bool *HadError) const {
- return make_range(LineInfo.begin(HadError), LineInfo.end());
+ return llvm::make_range(LineInfo.begin(HadError), LineInfo.end());
}
Error ModStream::commit() { return Error::success(); }
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp
index 84cccb354bd..ae4ebf27721 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/NameHashTable.cpp
@@ -10,19 +10,18 @@
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/Hash.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/Support/Endian.h"
using namespace llvm;
-using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {}
-Error NameHashTable::load(StreamReader &Stream) {
+Error NameHashTable::load(codeview::StreamReader &Stream) {
struct Header {
support::ulittle32_t Signature;
support::ulittle32_t HashVersion;
@@ -73,7 +72,7 @@ StringRef NameHashTable::getStringForID(uint32_t ID) const {
// the starting offset of the string we're looking for. So just seek into
// the desired offset and a read a null terminated stream from that offset.
StringRef Result;
- StreamReader NameReader(NamesBuffer);
+ codeview::StreamReader NameReader(NamesBuffer);
NameReader.setOffset(ID);
if (auto EC = NameReader.readZeroString(Result))
consumeError(std::move(EC));
@@ -99,6 +98,7 @@ uint32_t NameHashTable::getIDForString(StringRef Str) const {
return IDs[0];
}
-FixedStreamArray<support::ulittle32_t> NameHashTable::name_ids() const {
+codeview::FixedStreamArray<support::ulittle32_t>
+NameHashTable::name_ids() const {
return IDs;
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp
index 0f55f58da38..b8a4eb79a48 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMap.cpp
@@ -7,24 +7,20 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SparseBitVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
+#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cstdint>
using namespace llvm;
-using namespace llvm::msf;
+using namespace llvm::codeview;
using namespace llvm::pdb;
-NameMap::NameMap() = default;
+NameMap::NameMap() {}
+
+Error NameMap::load(codeview::StreamReader &Stream) {
-Error NameMap::load(StreamReader &Stream) {
// This is some sort of weird string-set/hash table encoded in the stream.
// It starts with the number of bytes in the table.
uint32_t NumberOfBytes;
@@ -149,9 +145,63 @@ Error NameMap::load(StreamReader &Stream) {
return Error::success();
}
+Error NameMap::commit(codeview::StreamWriter &Writer) {
+ // The first field is the number of bytes of string data. So add
+ // up the length of all strings plus a null terminator for each
+ // one.
+ uint32_t NumBytes = 0;
+ for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
+ NumBytes += B->getKeyLength() + 1;
+ }
+
+ if (auto EC = Writer.writeInteger(NumBytes)) // Number of bytes of string data
+ return EC;
+ // Now all of the string data itself.
+ for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
+ if (auto EC = Writer.writeZeroString(B->getKey()))
+ return EC;
+ }
+
+ if (auto EC = Writer.writeInteger(Mapping.size())) // Hash Size
+ return EC;
+
+ if (auto EC = Writer.writeInteger(Mapping.size())) // Max Number of Strings
+ return EC;
+
+ if (auto EC = Writer.writeInteger(Mapping.size())) // Num Present Words
+ return EC;
+
+ // For each entry in the mapping, write a bit mask which represents a bucket
+ // to store it in. We don't use this, so the value we write isn't important
+ // to us, it just has to be there.
+ for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
+ if (auto EC = Writer.writeInteger(1U))
+ return EC;
+ }
+
+ if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words
+ return EC;
+
+ // Mappings of each word.
+ uint32_t OffsetSoFar = 0;
+ for (auto B = Mapping.begin(), E = Mapping.end(); B != E; ++B) {
+ // This is a list of key value pairs where the key is the offset into the
+ // strings buffer, and the value is a stream number. Write each pair.
+ if (auto EC = Writer.writeInteger(OffsetSoFar))
+ return EC;
+
+ if (auto EC = Writer.writeInteger(B->second))
+ return EC;
+
+ OffsetSoFar += B->getKeyLength() + 1;
+ }
+
+ return Error::success();
+}
+
iterator_range<StringMapConstIterator<uint32_t>> NameMap::entries() const {
- return make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
- Mapping.end());
+ return llvm::make_range<StringMapConstIterator<uint32_t>>(Mapping.begin(),
+ Mapping.end());
}
bool NameMap::tryGetValue(StringRef Name, uint32_t &Value) const {
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
index f570d5931b0..41c6c2cd810 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/NameMapBuilder.cpp
@@ -7,19 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
-#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h"
+
+#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cstdint>
using namespace llvm;
using namespace llvm::pdb;
-NameMapBuilder::NameMapBuilder() = default;
+NameMapBuilder::NameMapBuilder() {}
void NameMapBuilder::addMapping(StringRef Name, uint32_t Mapping) {
StringDataBytes += Name.size() + 1;
@@ -52,57 +48,3 @@ uint32_t NameMapBuilder::calculateSerializedLength() const {
return TotalLength;
}
-
-Error NameMapBuilder::commit(msf::StreamWriter &Writer) const {
- // The first field is the number of bytes of string data. So add
- // up the length of all strings plus a null terminator for each
- // one.
- uint32_t NumBytes = 0;
- for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
- NumBytes += B->getKeyLength() + 1;
- }
-
- if (auto EC = Writer.writeInteger(NumBytes)) // Number of bytes of string data
- return EC;
- // Now all of the string data itself.
- for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
- if (auto EC = Writer.writeZeroString(B->getKey()))
- return EC;
- }
-
- if (auto EC = Writer.writeInteger(Map.size())) // Hash Size
- return EC;
-
- if (auto EC = Writer.writeInteger(Map.size())) // Max Number of Strings
- return EC;
-
- if (auto EC = Writer.writeInteger(Map.size())) // Num Present Words
- return EC;
-
- // For each entry in the mapping, write a bit mask which represents a bucket
- // to store it in. We don't use this, so the value we write isn't important
- // to us, it just has to be there.
- for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
- if (auto EC = Writer.writeInteger(1U))
- return EC;
- }
-
- if (auto EC = Writer.writeInteger(0U)) // Num Deleted Words
- return EC;
-
- // Mappings of each word.
- uint32_t OffsetSoFar = 0;
- for (auto B = Map.begin(), E = Map.end(); B != E; ++B) {
- // This is a list of key value pairs where the key is the offset into the
- // strings buffer, and the value is a stream number. Write each pair.
- if (auto EC = Writer.writeInteger(OffsetSoFar))
- return EC;
-
- if (auto EC = Writer.writeInteger(B->second))
- return EC;
-
- OffsetSoFar += B->getKeyLength() + 1;
- }
-
- return Error::success();
-}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
index 53491518b8c..95016753dc1 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
@@ -7,84 +7,68 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/MSFCommon.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamArray.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/MemoryBuffer.h"
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(std::unique_ptr<ReadableStream> PdbFileBuffer,
- BumpPtrAllocator &Allocator)
- : Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
+PDBFile::PDBFile(std::unique_ptr<StreamInterface> PdbFileBuffer)
+ : Buffer(std::move(PdbFileBuffer)), SB(nullptr) {}
-PDBFile::~PDBFile() = default;
+PDBFile::~PDBFile() {}
-uint32_t PDBFile::getBlockSize() const { return ContainerLayout.SB->BlockSize; }
+uint32_t PDBFile::getBlockSize() const { return SB->BlockSize; }
-uint32_t PDBFile::getFreeBlockMapBlock() const {
- return ContainerLayout.SB->FreeBlockMapBlock;
-}
+uint32_t PDBFile::getFreeBlockMapBlock() const { return SB->FreeBlockMapBlock; }
-uint32_t PDBFile::getBlockCount() const {
- return ContainerLayout.SB->NumBlocks;
-}
+uint32_t PDBFile::getBlockCount() const { return SB->NumBlocks; }
-uint32_t PDBFile::getNumDirectoryBytes() const {
- return ContainerLayout.SB->NumDirectoryBytes;
-}
+uint32_t PDBFile::getNumDirectoryBytes() const { return SB->NumDirectoryBytes; }
-uint32_t PDBFile::getBlockMapIndex() const {
- return ContainerLayout.SB->BlockMapAddr;
-}
+uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; }
-uint32_t PDBFile::getUnknown1() const { return ContainerLayout.SB->Unknown1; }
+uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; }
uint32_t PDBFile::getNumDirectoryBlocks() const {
- return msf::bytesToBlocks(ContainerLayout.SB->NumDirectoryBytes,
- ContainerLayout.SB->BlockSize);
+ return msf::bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
}
uint64_t PDBFile::getBlockMapOffset() const {
- return (uint64_t)ContainerLayout.SB->BlockMapAddr *
- ContainerLayout.SB->BlockSize;
+ return (uint64_t)SB->BlockMapAddr * SB->BlockSize;
}
-uint32_t PDBFile::getNumStreams() const {
- return ContainerLayout.StreamSizes.size();
-}
+uint32_t PDBFile::getNumStreams() const { return StreamSizes.size(); }
uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
- return ContainerLayout.StreamSizes[StreamIndex];
+ return StreamSizes[StreamIndex];
}
ArrayRef<support::ulittle32_t>
PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
- return ContainerLayout.StreamMap[StreamIndex];
+ return StreamMap[StreamIndex];
}
uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
@@ -101,72 +85,41 @@ Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
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");
+ if (Offset >= getBlockSize())
+ return make_error<RawError>(
+ raw_error_code::invalid_block_address,
+ "setBlockData attempted to write out of block bounds.");
+ if (Data.size() > getBlockSize() - Offset)
+ return make_error<RawError>(
+ raw_error_code::invalid_block_address,
+ "setBlockData attempted to write out of block bounds.");
+
+ uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
+ StreamBlockOffset += Offset;
+ return Buffer->writeBytes(StreamBlockOffset, Data);
}
Error PDBFile::parseFileHeaders() {
StreamReader 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,
"Does not contain superblock");
}
- 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);
- StreamReader FpmReader(*FpmStream);
- ArrayRef<uint8_t> FpmBytes;
- if (auto EC = FpmReader.readBytes(FpmBytes,
- msf::getFullFpmByteSize(ContainerLayout)))
+ if (auto EC = setSuperBlock(SB))
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()))
+ if (auto EC = Reader.readArray(DirectoryBlocks, getNumDirectoryBlocks()))
return EC;
return Error::success();
}
Error PDBFile::parseStreamData() {
- assert(ContainerLayout.SB);
+ assert(SB);
if (DirectoryStream)
return Error::success();
@@ -177,20 +130,21 @@ Error PDBFile::parseStreamData() {
// 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);
- StreamReader Reader(*DS);
+ auto DS = MappedBlockStream::createDirectoryStream(*this);
+ if (!DS)
+ return DS.takeError();
+ StreamReader Reader(**DS);
if (auto EC = Reader.readInteger(NumStreams))
return EC;
- if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
+ if (auto EC = Reader.readArray(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);
+ StreamSize == UINT32_MAX ? 0 : msf::bytesToBlocks(StreamSize,
+ 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
@@ -202,46 +156,29 @@ Error PDBFile::parseStreamData() {
if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
return EC;
for (uint32_t Block : Blocks) {
- uint64_t BlockEndOffset =
- (uint64_t)(Block + 1) * ContainerLayout.SB->BlockSize;
+ uint64_t BlockEndOffset = (uint64_t)(Block + 1) * SB->BlockSize;
if (BlockEndOffset > getFileSize())
return make_error<RawError>(raw_error_code::corrupt_file,
"Stream block map is corrupt.");
}
- ContainerLayout.StreamMap.push_back(Blocks);
+ StreamMap.push_back(Blocks);
}
// We should have read exactly SB->NumDirectoryBytes bytes.
assert(Reader.bytesRemaining() == 0);
- DirectoryStream = std::move(DS);
+ DirectoryStream = std::move(*DS);
return Error::success();
}
-ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
- return ContainerLayout.DirectoryBlocks;
-}
-
-Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
- if (!Globals) {
- auto DbiS = getPDBDbiStream();
- if (!DbiS)
- return DbiS.takeError();
-
- auto GlobalS = safelyCreateIndexedStream(
- ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex());
- if (!GlobalS) return GlobalS.takeError();
- auto TempGlobals = llvm::make_unique<GlobalsStream>(std::move(*GlobalS));
- if (auto EC = TempGlobals->reload())
- return std::move(EC);
- Globals = std::move(TempGlobals);
- }
- return *Globals;
+llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
+ return DirectoryBlocks;
}
Expected<InfoStream &> PDBFile::getPDBInfoStream() {
if (!Info) {
- auto InfoS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamPDB);
- if (!InfoS) return InfoS.takeError();
+ auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
+ if (!InfoS)
+ return InfoS.takeError();
auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS));
if (auto EC = TempInfo->reload())
return std::move(EC);
@@ -252,8 +189,9 @@ Expected<InfoStream &> PDBFile::getPDBInfoStream() {
Expected<DbiStream &> PDBFile::getPDBDbiStream() {
if (!Dbi) {
- auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI);
- if (!DbiS) return DbiS.takeError();
+ auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, *this);
+ if (!DbiS)
+ return DbiS.takeError();
auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
if (auto EC = TempDbi->reload())
return std::move(EC);
@@ -264,8 +202,9 @@ Expected<DbiStream &> PDBFile::getPDBDbiStream() {
Expected<TpiStream &> PDBFile::getPDBTpiStream() {
if (!Tpi) {
- auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamTPI);
- if (!TpiS) return TpiS.takeError();
+ auto TpiS = MappedBlockStream::createIndexedStream(StreamTPI, *this);
+ if (!TpiS)
+ return TpiS.takeError();
auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS));
if (auto EC = TempTpi->reload())
return std::move(EC);
@@ -276,8 +215,9 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() {
Expected<TpiStream &> PDBFile::getPDBIpiStream() {
if (!Ipi) {
- auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI);
- if (!IpiS) return IpiS.takeError();
+ auto IpiS = MappedBlockStream::createIndexedStream(StreamIPI, *this);
+ if (!IpiS)
+ return IpiS.takeError();
auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS));
if (auto EC = TempIpi->reload())
return std::move(EC);
@@ -292,9 +232,12 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
if (!DbiS)
return DbiS.takeError();
- auto PublicS = safelyCreateIndexedStream(
- ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex());
- if (!PublicS) return PublicS.takeError();
+ uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
+
+ auto PublicS =
+ MappedBlockStream::createIndexedStream(PublicsStreamNum, *this);
+ if (!PublicS)
+ return PublicS.takeError();
auto TempPublics =
llvm::make_unique<PublicsStream>(*this, std::move(*PublicS));
if (auto EC = TempPublics->reload())
@@ -311,10 +254,11 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
return DbiS.takeError();
uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
- auto SymbolS =
- safelyCreateIndexedStream(ContainerLayout, *Buffer, SymbolStreamNum);
- if (!SymbolS) return SymbolS.takeError();
+ auto SymbolS =
+ MappedBlockStream::createIndexedStream(SymbolStreamNum, *this);
+ if (!SymbolS)
+ return SymbolS.takeError();
auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS));
if (auto EC = TempSymbols->reload())
return std::move(EC);
@@ -331,9 +275,14 @@ Expected<NameHashTable &> PDBFile::getStringTable() {
uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
- auto NS =
- safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex);
- if (!NS) return NS.takeError();
+ if (NameStreamIndex == 0)
+ return make_error<RawError>(raw_error_code::no_stream);
+ if (NameStreamIndex >= getNumStreams())
+ return make_error<RawError>(raw_error_code::no_stream);
+
+ auto NS = MappedBlockStream::createIndexedStream(NameStreamIndex, *this);
+ if (!NS)
+ return NS.takeError();
StreamReader Reader(**NS);
auto N = llvm::make_unique<NameHashTable>();
@@ -345,47 +294,72 @@ Expected<NameHashTable &> PDBFile::getStringTable() {
return *StringTable;
}
-bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); }
+Error PDBFile::setSuperBlock(const msf::SuperBlock *Block) {
+ if (auto EC = msf::validateSuperBlock(*Block))
+ 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");
-bool PDBFile::hasPDBGlobalsStream() {
- auto DbiS = getPDBDbiStream();
- if (!DbiS) return false;
- return DbiS->getGlobalSymbolStreamIndex() < getNumStreams();
+ SB = Block;
+ return Error::success();
}
-bool PDBFile::hasPDBInfoStream() { return StreamPDB < getNumStreams(); }
+Error PDBFile::commit() {
+ StreamWriter Writer(*Buffer);
-bool PDBFile::hasPDBIpiStream() const { return StreamIPI < getNumStreams(); }
+ if (auto EC = Writer.writeObject(*SB))
+ return EC;
+ Writer.setOffset(getBlockMapOffset());
+ if (auto EC = Writer.writeArray(DirectoryBlocks))
+ return EC;
-bool PDBFile::hasPDBPublicsStream() {
- auto DbiS = getPDBDbiStream();
- if (!DbiS) return false;
- return DbiS->getPublicSymbolStreamIndex() < getNumStreams();
-}
+ auto DS = MappedBlockStream::createDirectoryStream(*this);
+ if (!DS)
+ return DS.takeError();
+ auto DirStream = std::move(*DS);
+ StreamWriter DW(*DirStream);
+ if (auto EC = DW.writeInteger(this->getNumStreams()))
+ return EC;
-bool PDBFile::hasPDBSymbolStream() {
- auto DbiS = getPDBDbiStream();
- if (!DbiS) return false;
- return DbiS->getSymRecordStreamIndex() < getNumStreams();
-}
+ if (auto EC = DW.writeArray(StreamSizes))
+ return EC;
-bool PDBFile::hasPDBTpiStream() const { return StreamTPI < getNumStreams(); }
+ for (const auto &Blocks : StreamMap) {
+ if (auto EC = DW.writeArray(Blocks))
+ return EC;
+ }
-bool PDBFile::hasStringTable() {
- auto IS = getPDBInfoStream();
- if (!IS) return false;
- return IS->getNamedStreamIndex("/names") < getNumStreams();
-}
+ if (Info) {
+ if (auto EC = Info->commit())
+ return EC;
+ }
+
+ if (Dbi) {
+ if (auto EC = Dbi->commit())
+ return EC;
+ }
+
+ if (Symbols) {
+ if (auto EC = Symbols->commit())
+ return EC;
+ }
+
+ if (Publics) {
+ if (auto EC = Publics->commit())
+ return EC;
+ }
+
+ if (Tpi) {
+ if (auto EC = Tpi->commit())
+ return EC;
+ }
+
+ if (Ipi) {
+ if (auto EC = Ipi->commit())
+ return EC;
+ }
-/// 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(
- const MSFLayout &Layout, const ReadableStream &MsfData,
- uint32_t StreamIndex) const {
- if (StreamIndex >= getNumStreams())
- return make_error<RawError>(raw_error_code::no_stream);
- return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex);
+ return Buffer->commit();
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
index 6fec0e32a8a..9063fd62d29 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/PDBFileBuilder.cpp
@@ -11,138 +11,92 @@
#include "llvm/ADT/BitVector.h"
-#include "llvm/DebugInfo/MSF/MSFBuilder.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
-#include "llvm/DebugInfo/PDB/GenericError.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
+#include "llvm/DebugInfo/CodeView/StreamWriter.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.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) {}
+PDBFileBuilder::PDBFileBuilder(
+ std::unique_ptr<codeview::StreamInterface> FileBuffer)
+ : File(llvm::make_unique<PDBFile>(std::move(FileBuffer))) {}
-Error PDBFileBuilder::initialize(uint32_t BlockSize) {
- auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
+Error PDBFileBuilder::initialize(const msf::SuperBlock &Super) {
+ auto ExpectedMsf =
+ MsfBuilder::create(File->Allocator, Super.BlockSize, Super.NumBlocks);
if (!ExpectedMsf)
return ExpectedMsf.takeError();
- Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
+
+ auto &MsfResult = *ExpectedMsf;
+ if (auto EC = MsfResult.setBlockMapAddr(Super.BlockMapAddr))
+ return EC;
+ Msf = llvm::make_unique<MsfBuilder>(std::move(MsfResult));
+ Msf->setFreePageMap(Super.FreeBlockMapBlock);
+ Msf->setUnknown1(Super.Unknown1);
return Error::success();
}
-MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
+MsfBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
if (!Info)
- Info = llvm::make_unique<InfoStreamBuilder>(*Msf);
+ Info = llvm::make_unique<InfoStreamBuilder>();
return *Info;
}
DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
if (!Dbi)
- Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
+ Dbi = llvm::make_unique<DbiStreamBuilder>();
return *Dbi;
}
-TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
- if (!Tpi)
- Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
- return *Tpi;
-}
-
-TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
- if (!Ipi)
- Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
- return *Ipi;
-}
-
-Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() const {
+Expected<std::unique_ptr<PDBFile>> PDBFileBuilder::build() {
if (Info) {
- if (auto EC = Info->finalizeMsfLayout())
+ uint32_t Length = Info->calculateSerializedLength();
+ if (auto EC = Msf->setStreamSize(StreamPDB, Length))
return std::move(EC);
}
if (Dbi) {
- if (auto EC = Dbi->finalizeMsfLayout())
+ uint32_t Length = Dbi->calculateSerializedLength();
+ if (auto EC = Msf->setStreamSize(StreamDBI, Length))
return std::move(EC);
}
- if (Tpi) {
- if (auto EC = Tpi->finalizeMsfLayout())
- return std::move(EC);
- }
- if (Ipi) {
- if (auto EC = Ipi->finalizeMsfLayout())
- return std::move(EC);
- }
-
- return Msf->build();
-}
-Error PDBFileBuilder::commit(StringRef Filename) {
- auto ExpectedLayout = finalizeMsfLayout();
+ auto ExpectedLayout = Msf->build();
if (!ExpectedLayout)
return ExpectedLayout.takeError();
- auto &Layout = *ExpectedLayout;
- uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
- auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
- if (OutFileOrError.getError())
- return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
- Filename);
- FileBufferByteStream Buffer(std::move(*OutFileOrError));
- StreamWriter Writer(Buffer);
-
- if (auto EC = Writer.writeObject(*Layout.SB))
- return EC;
- uint32_t BlockMapOffset =
- msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
- Writer.setOffset(BlockMapOffset);
- if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
- return EC;
-
- auto DirStream =
- WritableMappedBlockStream::createDirectoryStream(Layout, Buffer);
- StreamWriter DW(*DirStream);
- if (auto EC =
- DW.writeInteger(static_cast<uint32_t>(Layout.StreamSizes.size())))
- return EC;
-
- if (auto EC = DW.writeArray(Layout.StreamSizes))
- return EC;
-
- for (const auto &Blocks : Layout.StreamMap) {
- if (auto EC = DW.writeArray(Blocks))
- return EC;
- }
+ const msf::Layout &L = *ExpectedLayout;
+ File->StreamMap = L.StreamMap;
+ File->StreamSizes = L.StreamSizes;
+ File->DirectoryBlocks = L.DirectoryBlocks;
+ File->SB = L.SB;
if (Info) {
- if (auto EC = Info->commit(Layout, Buffer))
- return EC;
+ auto ExpectedInfo = Info->build(*File);
+ if (!ExpectedInfo)
+ return ExpectedInfo.takeError();
+ File->Info = std::move(*ExpectedInfo);
}
if (Dbi) {
- if (auto EC = Dbi->commit(Layout, Buffer))
- return EC;
+ auto ExpectedDbi = Dbi->build(*File);
+ if (!ExpectedDbi)
+ return ExpectedDbi.takeError();
+ File->Dbi = std::move(*ExpectedDbi);
}
- if (Tpi) {
- if (auto EC = Tpi->commit(Layout, Buffer))
- return EC;
- }
-
- if (Ipi) {
- if (auto EC = Ipi->commit(Layout, Buffer))
- return EC;
- }
+ if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
+ return llvm::make_error<RawError>(
+ raw_error_code::corrupt_file,
+ "PDB Stream Age doesn't match Dbi Stream Age!");
- return Buffer.commit();
+ return std::move(File);
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
index b31f605a078..af3d2d026b4 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
@@ -22,25 +22,30 @@
//
//===----------------------------------------------------------------------===//
-#include "GSI.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
+
+#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cstdint>
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
using namespace llvm;
-using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
+
+static const unsigned IPHR_HASH = 4096;
+
// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStream::HeaderInfo {
@@ -54,11 +59,23 @@ struct PublicsStream::HeaderInfo {
ulittle32_t NumSections;
};
+// This is GSIHashHdr.
+struct PublicsStream::GSIHashHeader {
+ enum : unsigned {
+ HdrSignature = ~0U,
+ HdrVersion = 0xeffe0000 + 19990810,
+ };
+ ulittle32_t VerSignature;
+ ulittle32_t VerHdr;
+ ulittle32_t HrSize;
+ ulittle32_t NumBuckets;
+};
+
PublicsStream::PublicsStream(PDBFile &File,
std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)) {}
-PublicsStream::~PublicsStream() = default;
+PublicsStream::~PublicsStream() {}
uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
@@ -69,7 +86,7 @@ uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }
// we skip over the hash table which we believe contains information about
// public symbols.
Error PublicsStream::reload() {
- StreamReader Reader(*Stream);
+ codeview::StreamReader Reader(*Stream);
// Check stream size.
if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
@@ -81,15 +98,40 @@ Error PublicsStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
- if (auto EC = readGSIHashHeader(HashHdr, Reader))
- return EC;
+ if (Reader.readObject(HashHdr))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Publics Stream does not contain a header.");
- if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
- return EC;
+ // An array of HashRecord follows. Read them.
+ 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,
+ "Could not read an HR array"));
- if (auto EC = readGSIHashBuckets(HashBuckets, HashHdr, Reader))
- return EC;
- NumBuckets = HashBuckets.size();
+ // A bitmap of a fixed length follows.
+ size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
+ uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
+ if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a bitmap."));
+ for (uint8_t B : Bitmap)
+ NumBuckets += countPopulation(B);
+
+ // We don't yet understand the following data structures completely,
+ // but we at least know the types and sizes. Here we are trying
+ // to read the stream till end so that we at least can detect
+ // corrupted streams.
+
+ // 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."));
// Something called "address map" follows.
uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
@@ -121,7 +163,7 @@ PublicsStream::getSymbols(bool *HadError) const {
auto SymbolS = Pdb.getPDBSymbolStream();
if (SymbolS.takeError()) {
codeview::CVSymbolArray::Iterator Iter;
- return make_range(Iter, Iter);
+ return llvm::make_range(Iter, Iter);
}
SymbolStream &SS = SymbolS.get();
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp
index f4a5057509e..eb169f70e11 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/RawError.cpp
@@ -11,7 +11,7 @@ namespace {
// 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"; }
+ const char *name() const LLVM_NOEXCEPT override { return "llvm.pdb.raw"; }
std::string message(int Condition) const override {
switch (static_cast<raw_error_code>(Condition)) {
@@ -19,8 +19,6 @@ public:
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:
@@ -32,10 +30,6 @@ public:
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::invalid_tpi_hash:
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp
index cd3a2064c71..455d33140dd 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/RawSession.cpp
@@ -7,8 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
+
+#include "llvm/DebugInfo/CodeView/ByteStream.h"
+#include "llvm/DebugInfo/CodeView/StreamInterface.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
@@ -16,51 +18,59 @@
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
-#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
+
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <algorithm>
-#include <memory>
using namespace llvm;
-using namespace llvm::msf;
using namespace llvm::pdb;
-RawSession::RawSession(std::unique_ptr<PDBFile> PdbFile,
- std::unique_ptr<BumpPtrAllocator> Allocator)
- : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {}
+namespace {
+// We need a class which behaves like an immutable ByteStream, but whose data
+// is backed by an llvm::MemoryBuffer. It also needs to own the underlying
+// MemoryBuffer, so this simple adapter is a good way to achieve that.
+class InputByteStream : public codeview::ByteStream<false> {
+public:
+ explicit InputByteStream(std::unique_ptr<MemoryBuffer> Buffer)
+ : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(),
+ Buffer->getBuffer().bytes_end())),
+ MemBuffer(std::move(Buffer)) {}
+
+ std::unique_ptr<MemoryBuffer> MemBuffer;
+};
+}
+
+RawSession::RawSession(std::unique_ptr<PDBFile> PdbFile)
+ : Pdb(std::move(PdbFile)) {}
-RawSession::~RawSession() = default;
+RawSession::~RawSession() {}
Error RawSession::createFromPdb(StringRef Path,
std::unique_ptr<IPDBSession> &Session) {
+
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
/*RequiresNullTerminator=*/false);
if (!ErrorOrBuffer)
- return make_error<GenericError>(generic_error_code::invalid_path);
+ return llvm::make_error<GenericError>(generic_error_code::invalid_path);
std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
- auto Stream = llvm::make_unique<MemoryBufferByteStream>(std::move(Buffer));
+ auto Stream = llvm::make_unique<InputByteStream>(std::move(Buffer));
- auto Allocator = llvm::make_unique<BumpPtrAllocator>();
- auto File = llvm::make_unique<PDBFile>(std::move(Stream), *Allocator);
+ std::unique_ptr<PDBFile> File(new PDBFile(std::move(Stream)));
if (auto EC = File->parseFileHeaders())
return EC;
if (auto EC = File->parseStreamData())
return EC;
- Session =
- llvm::make_unique<RawSession>(std::move(File), std::move(Allocator));
+ Session.reset(new RawSession(std::move(File)));
return Error::success();
}
Error RawSession::createFromExe(StringRef Path,
std::unique_ptr<IPDBSession> &Session) {
- return make_error<RawError>(raw_error_code::feature_unsupported);
+ return llvm::make_error<RawError>(raw_error_code::feature_unsupported);
}
uint64_t RawSession::getLoadAddress() const { return 0; }
@@ -93,26 +103,26 @@ RawSession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
std::unique_ptr<IPDBEnumSourceFiles>
RawSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
- StringRef Pattern,
+ llvm::StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
std::unique_ptr<IPDBSourceFile>
RawSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
- StringRef Pattern,
+ llvm::StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
-RawSession::findCompilandsForSourceFile(StringRef Pattern,
+RawSession::findCompilandsForSourceFile(llvm::StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
std::unique_ptr<PDBSymbolCompiland>
-RawSession::findOneCompilandForSourceFile(StringRef Pattern,
+RawSession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
PDB_NameSearchFlags Flags) const {
return nullptr;
}
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp
index 2f3ac3497f3..41b2a64bfb1 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/SymbolStream.cpp
@@ -10,9 +10,10 @@
#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
@@ -20,7 +21,6 @@
#include "llvm/Support/Endian.h"
using namespace llvm;
-using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
@@ -30,7 +30,7 @@ SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream)
SymbolStream::~SymbolStream() {}
Error SymbolStream::reload() {
- StreamReader Reader(*Stream);
+ codeview::StreamReader Reader(*Stream);
if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength()))
return EC;
diff --git a/gnu/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp b/gnu/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
index a1167cd9845..5617e57ccf6 100644
--- a/gnu/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
+++ b/gnu/llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
@@ -7,55 +7,155 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/iterator_range.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/StreamReader.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Raw/Hash.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiStream.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;
+namespace {
+const uint32_t MinHashBuckets = 0x1000;
+const uint32_t MaxHashBuckets = 0x40000;
+}
+
+// This corresponds to `HDR` in PDB/dbi/tpi.h.
+struct TpiStream::HeaderInfo {
+ struct EmbeddedBuf {
+ little32_t Off;
+ ulittle32_t Length;
+ };
+
+ ulittle32_t Version;
+ ulittle32_t HeaderSize;
+ ulittle32_t TypeIndexBegin;
+ ulittle32_t TypeIndexEnd;
+ ulittle32_t TypeRecordBytes;
+
+ // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
+ ulittle16_t HashStreamIndex;
+ ulittle16_t HashAuxStreamIndex;
+ ulittle32_t HashKeySize;
+ ulittle32_t NumHashBuckets;
+
+ EmbeddedBuf HashValueBuffer;
+ EmbeddedBuf IndexOffsetBuffer;
+ EmbeddedBuf HashAdjBuffer;
+};
+
TpiStream::TpiStream(const PDBFile &File,
std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)) {}
-TpiStream::~TpiStream() = default;
+TpiStream::~TpiStream() {}
+
+// Corresponds to `fUDTAnon`.
+template <typename T> static bool isAnonymous(T &Rec) {
+ StringRef Name = Rec.getName();
+ return Name == "<unnamed-tag>" || Name == "__unnamed" ||
+ Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
+}
+
+// Computes a hash for a given TPI record.
+template <typename T>
+static uint32_t getTpiHash(T &Rec, const CVRecord<TypeLeafKind> &RawRec) {
+ auto Opts = static_cast<uint16_t>(Rec.getOptions());
+
+ bool ForwardRef =
+ Opts & static_cast<uint16_t>(ClassOptions::ForwardReference);
+ bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped);
+ bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName);
+ bool IsAnon = UniqueName && isAnonymous(Rec);
+
+ if (!ForwardRef && !Scoped && !IsAnon)
+ return hashStringV1(Rec.getName());
+ if (!ForwardRef && UniqueName && !IsAnon)
+ return hashStringV1(Rec.getUniqueName());
+ return hashBufferV8(RawRec.RawData);
+}
+
+namespace {
+class TpiHashVerifier : public TypeVisitorCallbacks {
+public:
+ TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
+ uint32_t NumHashBuckets)
+ : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
+
+ Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
+ return verifySourceLine(Rec);
+ }
+
+ Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
+ return verifySourceLine(Rec);
+ }
+
+ Error visitClass(ClassRecord &Rec) override { return verify(Rec); }
+ Error visitEnum(EnumRecord &Rec) override { return verify(Rec); }
+ Error visitUnion(UnionRecord &Rec) override { return verify(Rec); }
+
+ Error visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) override {
+ ++Index;
+ RawRecord = &Rec;
+ return Error::success();
+ }
+
+private:
+ template <typename T> Error verify(T &Rec) {
+ uint32_t Hash = getTpiHash(Rec, *RawRecord);
+ if (Hash % NumHashBuckets != HashValues[Index])
+ return errorInvalidHash();
+ return Error::success();
+ }
+
+ template <typename T> Error verifySourceLine(T &Rec) {
+ char Buf[4];
+ support::endian::write32le(Buf, Rec.getUDT().getIndex());
+ uint32_t Hash = hashStringV1(StringRef(Buf, 4));
+ if (Hash % NumHashBuckets != HashValues[Index])
+ return errorInvalidHash();
+ return Error::success();
+ }
+
+ Error errorInvalidHash() {
+ return make_error<RawError>(
+ raw_error_code::invalid_tpi_hash,
+ "Type index is 0x" + utohexstr(TypeIndex::FirstNonSimpleIndex + Index));
+ }
+
+ FixedStreamArray<support::ulittle32_t> HashValues;
+ const CVRecord<TypeLeafKind> *RawRecord;
+ uint32_t NumHashBuckets;
+ uint32_t Index = -1;
+};
+}
// Verifies that a given type record matches with a given hash value.
// Currently we only verify SRC_LINE records.
Error TpiStream::verifyHashValues() {
TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
- TypeDeserializer Deserializer;
-
- TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Verifier);
-
- CVTypeVisitor Visitor(Pipeline);
+ CVTypeVisitor Visitor(Verifier);
return Visitor.visitTypeStream(TypeRecords);
}
Error TpiStream::reload() {
StreamReader Reader(*Stream);
- if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
+ if (Reader.bytesRemaining() < sizeof(HeaderInfo))
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream does not contain a header.");
@@ -67,7 +167,7 @@ Error TpiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"Unsupported TPI Version.");
- if (Header->HeaderSize != sizeof(TpiStreamHeader))
+ if (Header->HeaderSize != sizeof(HeaderInfo))
return make_error<RawError>(raw_error_code::corrupt_file,
"Corrupt TPI Header size.");
@@ -75,8 +175,8 @@ Error TpiStream::reload() {
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream expected 4 byte hash key size.");
- if (Header->NumHashBuckets < MinTpiHashBuckets ||
- Header->NumHashBuckets > MaxTpiHashBuckets)
+ if (Header->NumHashBuckets < MinHashBuckets ||
+ Header->NumHashBuckets > MaxHashBuckets)
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI Stream Invalid number of hash buckets.");
@@ -85,47 +185,43 @@ Error TpiStream::reload() {
return EC;
// Hash indices, hash values, etc come from the hash stream.
- if (Header->HashStreamIndex != kInvalidStreamIndex) {
- if (Header->HashStreamIndex >= Pdb.getNumStreams())
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid TPI hash stream index.");
-
- auto HS = MappedBlockStream::createIndexedStream(
- Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
- StreamReader HSR(*HS);
-
- uint32_t NumHashValues =
- Header->HashValueBuffer.Length / sizeof(ulittle32_t);
- if (NumHashValues != NumTypeRecords())
- 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;
- std::vector<ulittle32_t> HashValueList;
- for (auto I : HashValues)
- HashValueList.push_back(I);
-
- HSR.setOffset(Header->IndexOffsetBuffer.Off);
- uint32_t NumTypeIndexOffsets =
- Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
- if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
- return EC;
-
- HSR.setOffset(Header->HashAdjBuffer.Off);
- uint32_t NumHashAdjustments =
- Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
- if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
- return EC;
-
- HashStream = std::move(HS);
-
- // TPI hash table is a parallel array for the type records.
- // Verify that the hash values match with type records.
- if (auto EC = verifyHashValues())
- return EC;
- }
+ if (Header->HashStreamIndex >= Pdb.getNumStreams())
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid TPI hash stream index.");
+
+ auto HS =
+ MappedBlockStream::createIndexedStream(Header->HashStreamIndex, Pdb);
+ if (!HS)
+ return HS.takeError();
+ StreamReader HSR(**HS);
+
+ uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t);
+ if (NumHashValues != NumTypeRecords())
+ 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;
+
+ HSR.setOffset(Header->HashAdjBuffer.Off);
+ uint32_t NumHashAdjustments =
+ Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
+ if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
+ return EC;
+
+ HashStream = std::move(*HS);
+
+ // TPI hash table is a parallel array for the type records.
+ // Verify that the hash values match with type records.
+ if (auto EC = verifyHashValues())
+ return EC;
return Error::success();
}
@@ -171,7 +267,7 @@ TpiStream::getHashAdjustments() const {
iterator_range<CVTypeArray::Iterator>
TpiStream::types(bool *HadError) const {
- return make_range(TypeRecords.begin(HadError), TypeRecords.end());
+ return llvm::make_range(TypeRecords.begin(HadError), TypeRecords.end());
}
Error TpiStream::commit() { return Error::success(); }
diff --git a/gnu/llvm/lib/IR/AttributeSetNode.h b/gnu/llvm/lib/IR/AttributeSetNode.h
index 23ce3713c20..fab1ed51e4d 100644
--- a/gnu/llvm/lib/IR/AttributeSetNode.h
+++ b/gnu/llvm/lib/IR/AttributeSetNode.h
@@ -15,17 +15,10 @@
#ifndef LLVM_IR_ATTRIBUTESETNODE_H
#define LLVM_IR_ATTRIBUTESETNODE_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Attributes.h"
#include "llvm/Support/TrailingObjects.h"
-#include <algorithm>
#include <climits>
-#include <cstdint>
-#include <string>
-#include <utility>
namespace llvm {
@@ -56,11 +49,10 @@ class AttributeSetNode final
}
}
-public:
- // AttributesSetNode is uniqued, these should not be available.
+ // AttributesSetNode is uniqued, these should not be publicly available.
+ void operator=(const AttributeSetNode &) = delete;
AttributeSetNode(const AttributeSetNode &) = delete;
- AttributeSetNode &operator=(const AttributeSetNode &) = delete;
-
+public:
void operator delete(void *p) { ::operator delete(p); }
static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
@@ -96,11 +88,11 @@ public:
Profile(ID, makeArrayRef(begin(), end()));
}
static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
- for (const auto &Attr : AttrList)
- Attr.Profile(ID);
+ for (unsigned I = 0, E = AttrList.size(); I != E; ++I)
+ AttrList[I].Profile(ID);
}
};
-} // end namespace llvm
+} // end llvm namespace
-#endif // LLVM_IR_ATTRIBUTESETNODE_H
+#endif
diff --git a/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp b/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp
index 11ace84b9ce..e6b1040d8f5 100644
--- a/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp
+++ b/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp
@@ -13,7 +13,7 @@
#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/ObjectFile.h"
@@ -22,12 +22,6 @@
using namespace llvm;
using namespace object;
-static llvm::cl::opt<bool> IgnoreEmptyThinLTOIndexFile(
- "ignore-empty-index-file", llvm::cl::ZeroOrMore,
- llvm::cl::desc(
- "Ignore an empty index file and perform non-ThinLTO compilation"),
- llvm::cl::init(false));
-
ModuleSummaryIndexObjectFile::ModuleSummaryIndexObjectFile(
MemoryBufferRef Object, std::unique_ptr<ModuleSummaryIndex> I)
: SymbolicFile(Binary::ID_ModuleSummaryIndex, Object), Index(std::move(I)) {
@@ -73,42 +67,59 @@ ModuleSummaryIndexObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
}
}
+// Looks for module summary index in the given memory buffer.
+// returns true if found, else false.
+bool ModuleSummaryIndexObjectFile::hasGlobalValueSummaryInMemBuffer(
+ MemoryBufferRef Object,
+ const DiagnosticHandlerFunction &DiagnosticHandler) {
+ ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
+ if (!BCOrErr)
+ return false;
+
+ return hasGlobalValueSummary(BCOrErr.get(), DiagnosticHandler);
+}
+
// Parse module summary index in the given memory buffer.
// Return new ModuleSummaryIndexObjectFile instance containing parsed
// module summary/index.
-Expected<std::unique_ptr<ModuleSummaryIndexObjectFile>>
-ModuleSummaryIndexObjectFile::create(MemoryBufferRef Object) {
+ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>>
+ModuleSummaryIndexObjectFile::create(
+ MemoryBufferRef Object,
+ const DiagnosticHandlerFunction &DiagnosticHandler) {
+ std::unique_ptr<ModuleSummaryIndex> Index;
+
ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
if (!BCOrErr)
- return errorCodeToError(BCOrErr.getError());
+ return BCOrErr.getError();
- Expected<std::unique_ptr<ModuleSummaryIndex>> IOrErr =
- getModuleSummaryIndex(BCOrErr.get());
+ ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IOrErr =
+ getModuleSummaryIndex(BCOrErr.get(), DiagnosticHandler);
- if (!IOrErr)
- return IOrErr.takeError();
+ if (std::error_code EC = IOrErr.getError())
+ return EC;
+
+ Index = std::move(IOrErr.get());
- std::unique_ptr<ModuleSummaryIndex> Index = std::move(IOrErr.get());
return llvm::make_unique<ModuleSummaryIndexObjectFile>(Object,
std::move(Index));
}
// Parse the module summary index out of an IR file and return the summary
// index object if found, or nullptr if not.
-Expected<std::unique_ptr<ModuleSummaryIndex>>
-llvm::getModuleSummaryIndexForFile(StringRef Path) {
+ErrorOr<std::unique_ptr<ModuleSummaryIndex>> llvm::getModuleSummaryIndexForFile(
+ StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFileOrSTDIN(Path);
std::error_code EC = FileOrErr.getError();
if (EC)
- return errorCodeToError(EC);
+ return EC;
MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef();
- if (IgnoreEmptyThinLTOIndexFile && !BufferRef.getBufferSize())
- return nullptr;
- Expected<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
- object::ModuleSummaryIndexObjectFile::create(BufferRef);
- if (!ObjOrErr)
- return ObjOrErr.takeError();
+ ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
+ object::ModuleSummaryIndexObjectFile::create(BufferRef,
+ DiagnosticHandler);
+ EC = ObjOrErr.getError();
+ if (EC)
+ return EC;
object::ModuleSummaryIndexObjectFile &Obj = **ObjOrErr;
return Obj.takeIndex();
diff --git a/gnu/llvm/lib/Target/AArch64/AArch64SchedVulcan.td b/gnu/llvm/lib/Target/AArch64/AArch64SchedVulcan.td
index 35a40c314bf..0aa2462eba8 100644
--- a/gnu/llvm/lib/Target/AArch64/AArch64SchedVulcan.td
+++ b/gnu/llvm/lib/Target/AArch64/AArch64SchedVulcan.td
@@ -49,12 +49,15 @@ def VulcanP5 : ProcResource<1>;
let SchedModel = VulcanModel in {
-// Define groups for the functional units on each issue port. Each group
-// created will be used by a WriteRes later on.
+// Define groups for the functional units on each
+// issue port. Each group created will be used
+// by a WriteRes later on.
//
-// NOTE: Some groups only contain one member. This is a way to create names for
-// the various functional units that share a single issue port. For example,
-// "VulcanI1" for ALU ops on port 1 and "VulcanF1" for FP ops on port 1.
+// NOTE: Some groups only contain one member. This
+// is a way to create names for the various functional
+// units that share a single issue port. For example,
+// "VulcanI1" for ALU ops on port 1 and "VulcanF1" for
+// FP ops on port 1.
// Integer divide and multiply micro-ops only on port 1.
def VulcanI1 : ProcResGroup<[VulcanP1]>;
diff --git a/gnu/llvm/lib/Target/AMDGPU/AMDGPURuntimeMetadata.h b/gnu/llvm/lib/Target/AMDGPU/AMDGPURuntimeMetadata.h
index ecd2ac72bf1..40f63943450 100644
--- a/gnu/llvm/lib/Target/AMDGPU/AMDGPURuntimeMetadata.h
+++ b/gnu/llvm/lib/Target/AMDGPU/AMDGPURuntimeMetadata.h
@@ -13,13 +13,18 @@
///
/// Runtime requests certain information (metadata) about kernels to be able
/// to execute the kernels and answer the queries about the kernels.
-/// The metadata is represented as a note element in the .note ELF section of a
-/// binary (code object). The desc field of the note element is a YAML string
-/// consisting of key-value pairs. Each key is a string. Each value can be
-/// an integer, a string, or an YAML sequence. There are 3 levels of YAML maps.
-/// At the beginning of the YAML string is the module level YAML map. A
-/// kernel-level YAML map is in the amd.Kernels sequence. A
-/// kernel-argument-level map is in the amd.Args sequence.
+/// The metadata is represented as a byte stream in an ELF section of a
+/// binary (code object). The byte stream consists of key-value pairs.
+/// Each key is an 8 bit unsigned integer. Each value can be an integer,
+/// a string, or a stream of key-value pairs. There are 3 levels of key-value
+/// pair streams. At the beginning of the ELF section is the top level
+/// key-value pair stream. A kernel-level key-value pair stream starts after
+/// encountering KeyKernelBegin and ends immediately before encountering
+/// KeyKernelEnd. A kernel-argument-level key-value pair stream starts
+/// after encountering KeyArgBegin and ends immediately before encountering
+/// KeyArgEnd. A kernel-level key-value pair stream can only appear in a top
+/// level key-value pair stream. A kernel-argument-level key-value pair stream
+/// can only appear in a kernel-level key-value pair stream.
///
/// The format should be kept backward compatible. New enum values and bit
/// fields should be appended at the end. It is suggested to bump up the
@@ -32,64 +37,77 @@
#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPURUNTIMEMETADATA_H
#define LLVM_LIB_TARGET_AMDGPU_AMDGPURUNTIMEMETADATA_H
-#include <cstdint>
-#include <vector>
-#include <string>
+#include <stdint.h>
namespace AMDGPU {
namespace RuntimeMD {
// Version and revision of runtime metadata
- const unsigned char MDVersion = 2;
+ const unsigned char MDVersion = 1;
const unsigned char MDRevision = 0;
- // Name of keys for runtime metadata.
- namespace KeyName {
- const char MDVersion[] = "amd.MDVersion"; // Runtime metadata version
- const char Language[] = "amd.Language"; // Language
- const char LanguageVersion[] = "amd.LanguageVersion"; // Language version
- const char Kernels[] = "amd.Kernels"; // Kernels
- const char KernelName[] = "amd.KernelName"; // Kernel name
- const char Args[] = "amd.Args"; // Kernel arguments
- const char ArgSize[] = "amd.ArgSize"; // Kernel arg size
- const char ArgAlign[] = "amd.ArgAlign"; // Kernel arg alignment
- const char ArgTypeName[] = "amd.ArgTypeName"; // Kernel type name
- const char ArgName[] = "amd.ArgName"; // Kernel name
- const char ArgKind[] = "amd.ArgKind"; // Kernel argument kind
- const char ArgValueType[] = "amd.ArgValueType"; // Kernel argument value type
- const char ArgAddrQual[] = "amd.ArgAddrQual"; // Kernel argument address qualifier
- const char ArgAccQual[] = "amd.ArgAccQual"; // Kernel argument access qualifier
- const char ArgIsConst[] = "amd.ArgIsConst"; // Kernel argument is const qualified
- const char ArgIsRestrict[] = "amd.ArgIsRestrict"; // Kernel argument is restrict qualified
- const char ArgIsVolatile[] = "amd.ArgIsVolatile"; // Kernel argument is volatile qualified
- const char ArgIsPipe[] = "amd.ArgIsPipe"; // Kernel argument is pipe qualified
- const char ReqdWorkGroupSize[] = "amd.ReqdWorkGroupSize"; // Required work group size
- const char WorkGroupSizeHint[] = "amd.WorkGroupSizeHint"; // Work group size hint
- const char VecTypeHint[] = "amd.VecTypeHint"; // Vector type hint
- const char KernelIndex[] = "amd.KernelIndex"; // Kernel index for device enqueue
- const char NoPartialWorkGroups[] = "amd.NoPartialWorkGroups"; // No partial work groups
- const char PrintfInfo[] = "amd.PrintfInfo"; // Prinf function call information
- const char ArgActualAcc[] = "amd.ArgActualAcc"; // The actual kernel argument access qualifier
- const char ArgPointeeAlign[] = "amd.ArgPointeeAlign"; // Alignment of pointee type
- }
+ // ELF section name containing runtime metadata
+ const char SectionName[] = ".AMDGPU.runtime_metadata";
+
+ // Enumeration values of keys in runtime metadata.
+ enum Key {
+ KeyNull = 0, // Place holder. Ignored when encountered
+ KeyMDVersion = 1, // Runtime metadata version
+ KeyLanguage = 2, // Language
+ KeyLanguageVersion = 3, // Language version
+ KeyKernelBegin = 4, // Beginning of kernel-level stream
+ KeyKernelEnd = 5, // End of kernel-level stream
+ KeyKernelName = 6, // Kernel name
+ KeyArgBegin = 7, // Beginning of kernel-arg-level stream
+ KeyArgEnd = 8, // End of kernel-arg-level stream
+ KeyArgSize = 9, // Kernel arg size
+ KeyArgAlign = 10, // Kernel arg alignment
+ KeyArgTypeName = 11, // Kernel type name
+ KeyArgName = 12, // Kernel name
+ KeyArgTypeKind = 13, // Kernel argument type kind
+ KeyArgValueType = 14, // Kernel argument value type
+ KeyArgAddrQual = 15, // Kernel argument address qualifier
+ KeyArgAccQual = 16, // Kernel argument access qualifier
+ KeyArgIsConst = 17, // Kernel argument is const qualified
+ KeyArgIsRestrict = 18, // Kernel argument is restrict qualified
+ KeyArgIsVolatile = 19, // Kernel argument is volatile qualified
+ KeyArgIsPipe = 20, // Kernel argument is pipe qualified
+ KeyReqdWorkGroupSize = 21, // Required work group size
+ KeyWorkGroupSizeHint = 22, // Work group size hint
+ KeyVecTypeHint = 23, // Vector type hint
+ KeyKernelIndex = 24, // Kernel index for device enqueue
+ KeySGPRs = 25, // Number of SGPRs
+ KeyVGPRs = 26, // Number of VGPRs
+ KeyMinWavesPerSIMD = 27, // Minimum number of waves per SIMD
+ KeyMaxWavesPerSIMD = 28, // Maximum number of waves per SIMD
+ KeyFlatWorkGroupSizeLimits = 29, // Flat work group size limits
+ KeyMaxWorkGroupSize = 30, // Maximum work group size
+ KeyNoPartialWorkGroups = 31, // No partial work groups
+ };
+
+ enum Language : uint8_t {
+ OpenCL_C = 0,
+ HCC = 1,
+ OpenMP = 2,
+ OpenCL_CPP = 3,
+};
+
+ enum LanguageVersion : uint16_t {
+ V100 = 100,
+ V110 = 110,
+ V120 = 120,
+ V200 = 200,
+ V210 = 210,
+ };
namespace KernelArg {
- enum Kind : uint8_t {
- ByValue = 0,
- GlobalBuffer = 1,
- DynamicSharedPointer = 2,
- Sampler = 3,
- Image = 4,
- Pipe = 5,
- Queue = 6,
- HiddenGlobalOffsetX = 7,
- HiddenGlobalOffsetY = 8,
- HiddenGlobalOffsetZ = 9,
- HiddenNone = 10,
- HiddenPrintfBuffer = 11,
- HiddenDefaultQueue = 12,
- HiddenCompletionAction = 13,
+ enum TypeKind : uint8_t {
+ Value = 0,
+ Pointer = 1,
+ Image = 2,
+ Sampler = 3,
+ Queue = 4,
};
enum ValueType : uint16_t {
@@ -107,86 +125,13 @@ namespace RuntimeMD {
F64 = 11,
};
- // Avoid using 'None' since it conflicts with a macro in X11 header file.
enum AccessQualifer : uint8_t {
- AccNone = 0,
+ None = 0,
ReadOnly = 1,
WriteOnly = 2,
ReadWrite = 3,
};
-
- enum AddressSpaceQualifer : uint8_t {
- Private = 0,
- Global = 1,
- Constant = 2,
- Local = 3,
- Generic = 4,
- Region = 5,
- };
} // namespace KernelArg
-
- // Invalid values are used to indicate an optional key should not be emitted.
- const uint8_t INVALID_ADDR_QUAL = 0xff;
- const uint8_t INVALID_ACC_QUAL = 0xff;
- const uint32_t INVALID_KERNEL_INDEX = ~0U;
-
- namespace KernelArg {
- // In-memory representation of kernel argument information.
- struct Metadata {
- uint32_t Size;
- uint32_t Align;
- uint32_t PointeeAlign;
- uint8_t Kind;
- uint16_t ValueType;
- std::string TypeName;
- std::string Name;
- uint8_t AddrQual;
- uint8_t AccQual;
- uint8_t IsVolatile;
- uint8_t IsConst;
- uint8_t IsRestrict;
- uint8_t IsPipe;
- Metadata() : Size(0), Align(0), PointeeAlign(0), Kind(0), ValueType(0),
- AddrQual(INVALID_ADDR_QUAL), AccQual(INVALID_ACC_QUAL), IsVolatile(0),
- IsConst(0), IsRestrict(0), IsPipe(0) {}
- };
- }
-
- namespace Kernel {
- // In-memory representation of kernel information.
- struct Metadata {
- std::string Name;
- std::string Language;
- std::vector<uint8_t> LanguageVersion;
- std::vector<uint32_t> ReqdWorkGroupSize;
- std::vector<uint32_t> WorkGroupSizeHint;
- std::string VecTypeHint;
- uint32_t KernelIndex;
- uint8_t NoPartialWorkGroups;
- std::vector<KernelArg::Metadata> Args;
- Metadata() : KernelIndex(INVALID_KERNEL_INDEX), NoPartialWorkGroups(0) {}
- };
- }
-
- namespace Program {
- // In-memory representation of program information.
- struct Metadata {
- std::vector<uint8_t> MDVersionSeq;
- std::vector<std::string> PrintfInfo;
- std::vector<Kernel::Metadata> Kernels;
-
- explicit Metadata(){}
-
- // Construct from an YAML string.
- explicit Metadata(const std::string &YAML);
-
- // Convert to YAML string.
- std::string toYAML();
-
- // Convert from YAML string.
- static Metadata fromYAML(const std::string &S);
- };
- }
} // namespace RuntimeMD
} // namespace AMDGPU
diff --git a/gnu/llvm/lib/Target/NVPTX/NVPTXInferAddressSpaces.cpp b/gnu/llvm/lib/Target/NVPTX/NVPTXInferAddressSpaces.cpp
index f4940c937a2..e451d273cf4 100644
--- a/gnu/llvm/lib/Target/NVPTX/NVPTXInferAddressSpaces.cpp
+++ b/gnu/llvm/lib/Target/NVPTX/NVPTXInferAddressSpaces.cpp
@@ -87,6 +87,9 @@
// Finally, it fixes the undef in %y' so that
// %y' = phi float addrspace(3)* [ %input, %y2' ]
//
+// TODO: This pass is experimental and not enabled by default. Users can turn it
+// on by setting the -nvptx-use-infer-addrspace flag of llc. We plan to replace
+// NVPTXNonFavorGenericAddrSpaces with this pass shortly.
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "nvptx-infer-addrspace"
diff --git a/gnu/llvm/lib/Transforms/Utils/MemorySSA.cpp b/gnu/llvm/lib/Transforms/Utils/MemorySSA.cpp
index 1ce4225f09c..8ba3cae43b1 100644
--- a/gnu/llvm/lib/Transforms/Utils/MemorySSA.cpp
+++ b/gnu/llvm/lib/Transforms/Utils/MemorySSA.cpp
@@ -17,7 +17,6 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
@@ -61,11 +60,6 @@ INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
INITIALIZE_PASS_END(MemorySSAPrinterLegacyPass, "print-memoryssa",
"Memory SSA Printer", false, false)
-static cl::opt<unsigned> MaxCheckLimit(
- "memssa-check-limit", cl::Hidden, cl::init(100),
- cl::desc("The maximum number of stores/phis MemorySSA"
- "will consider trying to walk past (default = 100)"));
-
static cl::opt<bool>
VerifyMemorySSA("verify-memoryssa", cl::init(false), cl::Hidden,
cl::desc("Verify MemorySSA in legacy printer pass."));
@@ -92,963 +86,7 @@ public:
OS << "; " << *MA << "\n";
}
};
-}
-
-namespace {
-/// Our current alias analysis API differentiates heavily between calls and
-/// non-calls, and functions called on one usually assert on the other.
-/// This class encapsulates the distinction to simplify other code that wants
-/// "Memory affecting instructions and related data" to use as a key.
-/// For example, this class is used as a densemap key in the use optimizer.
-class MemoryLocOrCall {
-public:
- MemoryLocOrCall() : IsCall(false) {}
- MemoryLocOrCall(MemoryUseOrDef *MUD)
- : MemoryLocOrCall(MUD->getMemoryInst()) {}
- MemoryLocOrCall(const MemoryUseOrDef *MUD)
- : MemoryLocOrCall(MUD->getMemoryInst()) {}
-
- MemoryLocOrCall(Instruction *Inst) {
- if (ImmutableCallSite(Inst)) {
- IsCall = true;
- CS = ImmutableCallSite(Inst);
- } else {
- IsCall = false;
- // There is no such thing as a memorylocation for a fence inst, and it is
- // unique in that regard.
- if (!isa<FenceInst>(Inst))
- Loc = MemoryLocation::get(Inst);
- }
- }
-
- explicit MemoryLocOrCall(const MemoryLocation &Loc)
- : IsCall(false), Loc(Loc) {}
-
- bool IsCall;
- ImmutableCallSite getCS() const {
- assert(IsCall);
- return CS;
- }
- MemoryLocation getLoc() const {
- assert(!IsCall);
- return Loc;
- }
-
- bool operator==(const MemoryLocOrCall &Other) const {
- if (IsCall != Other.IsCall)
- return false;
-
- if (IsCall)
- return CS.getCalledValue() == Other.CS.getCalledValue();
- return Loc == Other.Loc;
- }
-
-private:
- union {
- ImmutableCallSite CS;
- MemoryLocation Loc;
- };
-};
-}
-
-namespace llvm {
-template <> struct DenseMapInfo<MemoryLocOrCall> {
- static inline MemoryLocOrCall getEmptyKey() {
- return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getEmptyKey());
- }
- static inline MemoryLocOrCall getTombstoneKey() {
- return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getTombstoneKey());
- }
- static unsigned getHashValue(const MemoryLocOrCall &MLOC) {
- if (MLOC.IsCall)
- return hash_combine(MLOC.IsCall,
- DenseMapInfo<const Value *>::getHashValue(
- MLOC.getCS().getCalledValue()));
- return hash_combine(
- MLOC.IsCall, DenseMapInfo<MemoryLocation>::getHashValue(MLOC.getLoc()));
- }
- static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS) {
- return LHS == RHS;
- }
-};
-
-enum class Reorderability { Always, IfNoAlias, Never };
-
-/// This does one-way checks to see if Use could theoretically be hoisted above
-/// MayClobber. This will not check the other way around.
-///
-/// This assumes that, for the purposes of MemorySSA, Use comes directly after
-/// MayClobber, with no potentially clobbering operations in between them.
-/// (Where potentially clobbering ops are memory barriers, aliased stores, etc.)
-static Reorderability getLoadReorderability(const LoadInst *Use,
- const LoadInst *MayClobber) {
- bool VolatileUse = Use->isVolatile();
- bool VolatileClobber = MayClobber->isVolatile();
- // Volatile operations may never be reordered with other volatile operations.
- if (VolatileUse && VolatileClobber)
- return Reorderability::Never;
-
- // The lang ref allows reordering of volatile and non-volatile operations.
- // Whether an aliasing nonvolatile load and volatile load can be reordered,
- // though, is ambiguous. Because it may not be best to exploit this ambiguity,
- // we only allow volatile/non-volatile reordering if the volatile and
- // non-volatile operations don't alias.
- Reorderability Result = VolatileUse || VolatileClobber
- ? Reorderability::IfNoAlias
- : Reorderability::Always;
-
- // If a load is seq_cst, it cannot be moved above other loads. If its ordering
- // is weaker, it can be moved above other loads. We just need to be sure that
- // MayClobber isn't an acquire load, because loads can't be moved above
- // acquire loads.
- //
- // Note that this explicitly *does* allow the free reordering of monotonic (or
- // weaker) loads of the same address.
- bool SeqCstUse = Use->getOrdering() == AtomicOrdering::SequentiallyConsistent;
- bool MayClobberIsAcquire = isAtLeastOrStrongerThan(MayClobber->getOrdering(),
- AtomicOrdering::Acquire);
- if (SeqCstUse || MayClobberIsAcquire)
- return Reorderability::Never;
- return Result;
-}
-
-static bool instructionClobbersQuery(MemoryDef *MD,
- const MemoryLocation &UseLoc,
- const Instruction *UseInst,
- AliasAnalysis &AA) {
- Instruction *DefInst = MD->getMemoryInst();
- assert(DefInst && "Defining instruction not actually an instruction");
-
- if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(DefInst)) {
- // These intrinsics will show up as affecting memory, but they are just
- // markers.
- switch (II->getIntrinsicID()) {
- case Intrinsic::lifetime_start:
- case Intrinsic::lifetime_end:
- case Intrinsic::invariant_start:
- case Intrinsic::invariant_end:
- case Intrinsic::assume:
- return false;
- default:
- break;
- }
- }
-
- ImmutableCallSite UseCS(UseInst);
- if (UseCS) {
- ModRefInfo I = AA.getModRefInfo(DefInst, UseCS);
- return I != MRI_NoModRef;
- }
-
- if (auto *DefLoad = dyn_cast<LoadInst>(DefInst)) {
- if (auto *UseLoad = dyn_cast<LoadInst>(UseInst)) {
- switch (getLoadReorderability(UseLoad, DefLoad)) {
- case Reorderability::Always:
- return false;
- case Reorderability::Never:
- return true;
- case Reorderability::IfNoAlias:
- return !AA.isNoAlias(UseLoc, MemoryLocation::get(DefLoad));
- }
- }
- }
-
- return AA.getModRefInfo(DefInst, UseLoc) & MRI_Mod;
-}
-
-static bool instructionClobbersQuery(MemoryDef *MD, const MemoryUseOrDef *MU,
- const MemoryLocOrCall &UseMLOC,
- AliasAnalysis &AA) {
- // FIXME: This is a temporary hack to allow a single instructionClobbersQuery
- // to exist while MemoryLocOrCall is pushed through places.
- if (UseMLOC.IsCall)
- return instructionClobbersQuery(MD, MemoryLocation(), MU->getMemoryInst(),
- AA);
- return instructionClobbersQuery(MD, UseMLOC.getLoc(), MU->getMemoryInst(),
- AA);
-}
-
-// Return true when MD may alias MU, return false otherwise.
-bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
- AliasAnalysis &AA) {
- return instructionClobbersQuery(MD, MU, MemoryLocOrCall(MU), AA);
-}
-}
-
-namespace {
-struct UpwardsMemoryQuery {
- // True if our original query started off as a call
- bool IsCall;
- // The pointer location we started the query with. This will be empty if
- // IsCall is true.
- MemoryLocation StartingLoc;
- // This is the instruction we were querying about.
- const Instruction *Inst;
- // The MemoryAccess we actually got called with, used to test local domination
- const MemoryAccess *OriginalAccess;
-
- UpwardsMemoryQuery()
- : IsCall(false), Inst(nullptr), OriginalAccess(nullptr) {}
-
- UpwardsMemoryQuery(const Instruction *Inst, const MemoryAccess *Access)
- : IsCall(ImmutableCallSite(Inst)), Inst(Inst), OriginalAccess(Access) {
- if (!IsCall)
- StartingLoc = MemoryLocation::get(Inst);
- }
-};
-
-static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,
- AliasAnalysis &AA) {
- Instruction *Inst = MD->getMemoryInst();
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
- switch (II->getIntrinsicID()) {
- case Intrinsic::lifetime_start:
- case Intrinsic::lifetime_end:
- return AA.isMustAlias(MemoryLocation(II->getArgOperand(1)), Loc);
- default:
- return false;
- }
- }
- return false;
-}
-
-static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysis &AA,
- const Instruction *I) {
- // If the memory can't be changed, then loads of the memory can't be
- // clobbered.
- //
- // FIXME: We should handle invariant groups, as well. It's a bit harder,
- // because we need to pay close attention to invariant group barriers.
- return isa<LoadInst>(I) && (I->getMetadata(LLVMContext::MD_invariant_load) ||
- AA.pointsToConstantMemory(I));
-}
-
-/// Cache for our caching MemorySSA walker.
-class WalkerCache {
- DenseMap<ConstMemoryAccessPair, MemoryAccess *> Accesses;
- DenseMap<const MemoryAccess *, MemoryAccess *> Calls;
-
-public:
- MemoryAccess *lookup(const MemoryAccess *MA, const MemoryLocation &Loc,
- bool IsCall) const {
- ++NumClobberCacheLookups;
- MemoryAccess *R = IsCall ? Calls.lookup(MA) : Accesses.lookup({MA, Loc});
- if (R)
- ++NumClobberCacheHits;
- return R;
- }
-
- bool insert(const MemoryAccess *MA, MemoryAccess *To,
- const MemoryLocation &Loc, bool IsCall) {
- // This is fine for Phis, since there are times where we can't optimize
- // them. Making a def its own clobber is never correct, though.
- assert((MA != To || isa<MemoryPhi>(MA)) &&
- "Something can't clobber itself!");
-
- ++NumClobberCacheInserts;
- bool Inserted;
- if (IsCall)
- Inserted = Calls.insert({MA, To}).second;
- else
- Inserted = Accesses.insert({{MA, Loc}, To}).second;
-
- return Inserted;
- }
-
- bool remove(const MemoryAccess *MA, const MemoryLocation &Loc, bool IsCall) {
- return IsCall ? Calls.erase(MA) : Accesses.erase({MA, Loc});
- }
-
- void clear() {
- Accesses.clear();
- Calls.clear();
- }
-
- bool contains(const MemoryAccess *MA) const {
- for (auto &P : Accesses)
- if (P.first.first == MA || P.second == MA)
- return true;
- for (auto &P : Calls)
- if (P.first == MA || P.second == MA)
- return true;
- return false;
- }
-};
-
-/// Walks the defining uses of MemoryDefs. Stops after we hit something that has
-/// no defining use (e.g. a MemoryPhi or liveOnEntry). Note that, when comparing
-/// against a null def_chain_iterator, this will compare equal only after
-/// walking said Phi/liveOnEntry.
-struct def_chain_iterator
- : public iterator_facade_base<def_chain_iterator, std::forward_iterator_tag,
- MemoryAccess *> {
- def_chain_iterator() : MA(nullptr) {}
- def_chain_iterator(MemoryAccess *MA) : MA(MA) {}
-
- MemoryAccess *operator*() const { return MA; }
-
- def_chain_iterator &operator++() {
- // N.B. liveOnEntry has a null defining access.
- if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA))
- MA = MUD->getDefiningAccess();
- else
- MA = nullptr;
- return *this;
- }
-
- bool operator==(const def_chain_iterator &O) const { return MA == O.MA; }
-
-private:
- MemoryAccess *MA;
-};
-
-static iterator_range<def_chain_iterator>
-def_chain(MemoryAccess *MA, MemoryAccess *UpTo = nullptr) {
-#ifdef EXPENSIVE_CHECKS
- assert((!UpTo || find(def_chain(MA), UpTo) != def_chain_iterator()) &&
- "UpTo isn't in the def chain!");
-#endif
- return make_range(def_chain_iterator(MA), def_chain_iterator(UpTo));
-}
-
-/// Verifies that `Start` is clobbered by `ClobberAt`, and that nothing
-/// inbetween `Start` and `ClobberAt` can clobbers `Start`.
-///
-/// This is meant to be as simple and self-contained as possible. Because it
-/// uses no cache, etc., it can be relatively expensive.
-///
-/// \param Start The MemoryAccess that we want to walk from.
-/// \param ClobberAt A clobber for Start.
-/// \param StartLoc The MemoryLocation for Start.
-/// \param MSSA The MemorySSA isntance that Start and ClobberAt belong to.
-/// \param Query The UpwardsMemoryQuery we used for our search.
-/// \param AA The AliasAnalysis we used for our search.
-static void LLVM_ATTRIBUTE_UNUSED
-checkClobberSanity(MemoryAccess *Start, MemoryAccess *ClobberAt,
- const MemoryLocation &StartLoc, const MemorySSA &MSSA,
- const UpwardsMemoryQuery &Query, AliasAnalysis &AA) {
- assert(MSSA.dominates(ClobberAt, Start) && "Clobber doesn't dominate start?");
-
- if (MSSA.isLiveOnEntryDef(Start)) {
- assert(MSSA.isLiveOnEntryDef(ClobberAt) &&
- "liveOnEntry must clobber itself");
- return;
- }
-
- bool FoundClobber = false;
- DenseSet<MemoryAccessPair> VisitedPhis;
- SmallVector<MemoryAccessPair, 8> Worklist;
- Worklist.emplace_back(Start, StartLoc);
- // Walk all paths from Start to ClobberAt, while looking for clobbers. If one
- // is found, complain.
- while (!Worklist.empty()) {
- MemoryAccessPair MAP = Worklist.pop_back_val();
- // All we care about is that nothing from Start to ClobberAt clobbers Start.
- // We learn nothing from revisiting nodes.
- if (!VisitedPhis.insert(MAP).second)
- continue;
-
- for (MemoryAccess *MA : def_chain(MAP.first)) {
- if (MA == ClobberAt) {
- if (auto *MD = dyn_cast<MemoryDef>(MA)) {
- // instructionClobbersQuery isn't essentially free, so don't use `|=`,
- // since it won't let us short-circuit.
- //
- // Also, note that this can't be hoisted out of the `Worklist` loop,
- // since MD may only act as a clobber for 1 of N MemoryLocations.
- FoundClobber =
- FoundClobber || MSSA.isLiveOnEntryDef(MD) ||
- instructionClobbersQuery(MD, MAP.second, Query.Inst, AA);
- }
- break;
- }
-
- // We should never hit liveOnEntry, unless it's the clobber.
- assert(!MSSA.isLiveOnEntryDef(MA) && "Hit liveOnEntry before clobber?");
-
- if (auto *MD = dyn_cast<MemoryDef>(MA)) {
- (void)MD;
- assert(!instructionClobbersQuery(MD, MAP.second, Query.Inst, AA) &&
- "Found clobber before reaching ClobberAt!");
- continue;
- }
-
- assert(isa<MemoryPhi>(MA));
- Worklist.append(upward_defs_begin({MA, MAP.second}), upward_defs_end());
- }
- }
-
- // If ClobberAt is a MemoryPhi, we can assume something above it acted as a
- // clobber. Otherwise, `ClobberAt` should've acted as a clobber at some point.
- assert((isa<MemoryPhi>(ClobberAt) || FoundClobber) &&
- "ClobberAt never acted as a clobber");
-}
-
-/// Our algorithm for walking (and trying to optimize) clobbers, all wrapped up
-/// in one class.
-class ClobberWalker {
- /// Save a few bytes by using unsigned instead of size_t.
- using ListIndex = unsigned;
-
- /// Represents a span of contiguous MemoryDefs, potentially ending in a
- /// MemoryPhi.
- struct DefPath {
- MemoryLocation Loc;
- // Note that, because we always walk in reverse, Last will always dominate
- // First. Also note that First and Last are inclusive.
- MemoryAccess *First;
- MemoryAccess *Last;
- Optional<ListIndex> Previous;
-
- DefPath(const MemoryLocation &Loc, MemoryAccess *First, MemoryAccess *Last,
- Optional<ListIndex> Previous)
- : Loc(Loc), First(First), Last(Last), Previous(Previous) {}
-
- DefPath(const MemoryLocation &Loc, MemoryAccess *Init,
- Optional<ListIndex> Previous)
- : DefPath(Loc, Init, Init, Previous) {}
- };
-
- const MemorySSA &MSSA;
- AliasAnalysis &AA;
- DominatorTree &DT;
- WalkerCache &WC;
- UpwardsMemoryQuery *Query;
- bool UseCache;
-
- // Phi optimization bookkeeping
- SmallVector<DefPath, 32> Paths;
- DenseSet<ConstMemoryAccessPair> VisitedPhis;
- DenseMap<const BasicBlock *, MemoryAccess *> WalkTargetCache;
-
- void setUseCache(bool Use) { UseCache = Use; }
- bool shouldIgnoreCache() const {
- // UseCache will only be false when we're debugging, or when expensive
- // checks are enabled. In either case, we don't care deeply about speed.
- return LLVM_UNLIKELY(!UseCache);
- }
-
- void addCacheEntry(const MemoryAccess *What, MemoryAccess *To,
- const MemoryLocation &Loc) const {
-// EXPENSIVE_CHECKS because most of these queries are redundant.
-#ifdef EXPENSIVE_CHECKS
- assert(MSSA.dominates(To, What));
-#endif
- if (shouldIgnoreCache())
- return;
- WC.insert(What, To, Loc, Query->IsCall);
- }
-
- MemoryAccess *lookupCache(const MemoryAccess *MA, const MemoryLocation &Loc) {
- return shouldIgnoreCache() ? nullptr : WC.lookup(MA, Loc, Query->IsCall);
- }
-
- void cacheDefPath(const DefPath &DN, MemoryAccess *Target) const {
- if (shouldIgnoreCache())
- return;
-
- for (MemoryAccess *MA : def_chain(DN.First, DN.Last))
- addCacheEntry(MA, Target, DN.Loc);
-
- // DefPaths only express the path we walked. So, DN.Last could either be a
- // thing we want to cache, or not.
- if (DN.Last != Target)
- addCacheEntry(DN.Last, Target, DN.Loc);
- }
-
- /// Find the nearest def or phi that `From` can legally be optimized to.
- ///
- /// FIXME: Deduplicate this with MSSA::findDominatingDef. Ideally, MSSA should
- /// keep track of this information for us, and allow us O(1) lookups of this
- /// info.
- MemoryAccess *getWalkTarget(const MemoryPhi *From) {
- assert(From->getNumOperands() && "Phi with no operands?");
-
- BasicBlock *BB = From->getBlock();
- auto At = WalkTargetCache.find(BB);
- if (At != WalkTargetCache.end())
- return At->second;
-
- SmallVector<const BasicBlock *, 8> ToCache;
- ToCache.push_back(BB);
-
- MemoryAccess *Result = MSSA.getLiveOnEntryDef();
- DomTreeNode *Node = DT.getNode(BB);
- while ((Node = Node->getIDom())) {
- auto At = WalkTargetCache.find(BB);
- if (At != WalkTargetCache.end()) {
- Result = At->second;
- break;
- }
-
- auto *Accesses = MSSA.getBlockAccesses(Node->getBlock());
- if (Accesses) {
- auto Iter = find_if(reverse(*Accesses), [](const MemoryAccess &MA) {
- return !isa<MemoryUse>(MA);
- });
- if (Iter != Accesses->rend()) {
- Result = const_cast<MemoryAccess *>(&*Iter);
- break;
- }
- }
-
- ToCache.push_back(Node->getBlock());
- }
-
- for (const BasicBlock *BB : ToCache)
- WalkTargetCache.insert({BB, Result});
- return Result;
- }
-
- /// Result of calling walkToPhiOrClobber.
- struct UpwardsWalkResult {
- /// The "Result" of the walk. Either a clobber, the last thing we walked, or
- /// both.
- MemoryAccess *Result;
- bool IsKnownClobber;
- bool FromCache;
- };
-
- /// Walk to the next Phi or Clobber in the def chain starting at Desc.Last.
- /// This will update Desc.Last as it walks. It will (optionally) also stop at
- /// StopAt.
- ///
- /// This does not test for whether StopAt is a clobber
- UpwardsWalkResult walkToPhiOrClobber(DefPath &Desc,
- MemoryAccess *StopAt = nullptr) {
- assert(!isa<MemoryUse>(Desc.Last) && "Uses don't exist in my world");
-
- for (MemoryAccess *Current : def_chain(Desc.Last)) {
- Desc.Last = Current;
- if (Current == StopAt)
- return {Current, false, false};
-
- if (auto *MD = dyn_cast<MemoryDef>(Current))
- if (MSSA.isLiveOnEntryDef(MD) ||
- instructionClobbersQuery(MD, Desc.Loc, Query->Inst, AA))
- return {MD, true, false};
-
- // Cache checks must be done last, because if Current is a clobber, the
- // cache will contain the clobber for Current.
- if (MemoryAccess *MA = lookupCache(Current, Desc.Loc))
- return {MA, true, true};
- }
-
- assert(isa<MemoryPhi>(Desc.Last) &&
- "Ended at a non-clobber that's not a phi?");
- return {Desc.Last, false, false};
- }
-
- void addSearches(MemoryPhi *Phi, SmallVectorImpl<ListIndex> &PausedSearches,
- ListIndex PriorNode) {
- auto UpwardDefs = make_range(upward_defs_begin({Phi, Paths[PriorNode].Loc}),
- upward_defs_end());
- for (const MemoryAccessPair &P : UpwardDefs) {
- PausedSearches.push_back(Paths.size());
- Paths.emplace_back(P.second, P.first, PriorNode);
- }
- }
-
- /// Represents a search that terminated after finding a clobber. This clobber
- /// may or may not be present in the path of defs from LastNode..SearchStart,
- /// since it may have been retrieved from cache.
- struct TerminatedPath {
- MemoryAccess *Clobber;
- ListIndex LastNode;
- };
-
- /// Get an access that keeps us from optimizing to the given phi.
- ///
- /// PausedSearches is an array of indices into the Paths array. Its incoming
- /// value is the indices of searches that stopped at the last phi optimization
- /// target. It's left in an unspecified state.
- ///
- /// If this returns None, NewPaused is a vector of searches that terminated
- /// at StopWhere. Otherwise, NewPaused is left in an unspecified state.
- Optional<TerminatedPath>
- getBlockingAccess(MemoryAccess *StopWhere,
- SmallVectorImpl<ListIndex> &PausedSearches,
- SmallVectorImpl<ListIndex> &NewPaused,
- SmallVectorImpl<TerminatedPath> &Terminated) {
- assert(!PausedSearches.empty() && "No searches to continue?");
-
- // BFS vs DFS really doesn't make a difference here, so just do a DFS with
- // PausedSearches as our stack.
- while (!PausedSearches.empty()) {
- ListIndex PathIndex = PausedSearches.pop_back_val();
- DefPath &Node = Paths[PathIndex];
-
- // If we've already visited this path with this MemoryLocation, we don't
- // need to do so again.
- //
- // NOTE: That we just drop these paths on the ground makes caching
- // behavior sporadic. e.g. given a diamond:
- // A
- // B C
- // D
- //
- // ...If we walk D, B, A, C, we'll only cache the result of phi
- // optimization for A, B, and D; C will be skipped because it dies here.
- // This arguably isn't the worst thing ever, since:
- // - We generally query things in a top-down order, so if we got below D
- // without needing cache entries for {C, MemLoc}, then chances are
- // that those cache entries would end up ultimately unused.
- // - We still cache things for A, so C only needs to walk up a bit.
- // If this behavior becomes problematic, we can fix without a ton of extra
- // work.
- if (!VisitedPhis.insert({Node.Last, Node.Loc}).second)
- continue;
-
- UpwardsWalkResult Res = walkToPhiOrClobber(Node, /*StopAt=*/StopWhere);
- if (Res.IsKnownClobber) {
- assert(Res.Result != StopWhere || Res.FromCache);
- // If this wasn't a cache hit, we hit a clobber when walking. That's a
- // failure.
- TerminatedPath Term{Res.Result, PathIndex};
- if (!Res.FromCache || !MSSA.dominates(Res.Result, StopWhere))
- return Term;
-
- // Otherwise, it's a valid thing to potentially optimize to.
- Terminated.push_back(Term);
- continue;
- }
-
- if (Res.Result == StopWhere) {
- // We've hit our target. Save this path off for if we want to continue
- // walking.
- NewPaused.push_back(PathIndex);
- continue;
- }
-
- assert(!MSSA.isLiveOnEntryDef(Res.Result) && "liveOnEntry is a clobber");
- addSearches(cast<MemoryPhi>(Res.Result), PausedSearches, PathIndex);
- }
-
- return None;
- }
-
- template <typename T, typename Walker>
- struct generic_def_path_iterator
- : public iterator_facade_base<generic_def_path_iterator<T, Walker>,
- std::forward_iterator_tag, T *> {
- generic_def_path_iterator() : W(nullptr), N(None) {}
- generic_def_path_iterator(Walker *W, ListIndex N) : W(W), N(N) {}
-
- T &operator*() const { return curNode(); }
-
- generic_def_path_iterator &operator++() {
- N = curNode().Previous;
- return *this;
- }
-
- bool operator==(const generic_def_path_iterator &O) const {
- if (N.hasValue() != O.N.hasValue())
- return false;
- return !N.hasValue() || *N == *O.N;
- }
-
- private:
- T &curNode() const { return W->Paths[*N]; }
-
- Walker *W;
- Optional<ListIndex> N;
- };
-
- using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
- using const_def_path_iterator =
- generic_def_path_iterator<const DefPath, const ClobberWalker>;
-
- iterator_range<def_path_iterator> def_path(ListIndex From) {
- return make_range(def_path_iterator(this, From), def_path_iterator());
- }
-
- iterator_range<const_def_path_iterator> const_def_path(ListIndex From) const {
- return make_range(const_def_path_iterator(this, From),
- const_def_path_iterator());
- }
-
- struct OptznResult {
- /// The path that contains our result.
- TerminatedPath PrimaryClobber;
- /// The paths that we can legally cache back from, but that aren't
- /// necessarily the result of the Phi optimization.
- SmallVector<TerminatedPath, 4> OtherClobbers;
- };
-
- ListIndex defPathIndex(const DefPath &N) const {
- // The assert looks nicer if we don't need to do &N
- const DefPath *NP = &N;
- assert(!Paths.empty() && NP >= &Paths.front() && NP <= &Paths.back() &&
- "Out of bounds DefPath!");
- return NP - &Paths.front();
- }
-
- /// Try to optimize a phi as best as we can. Returns a SmallVector of Paths
- /// that act as legal clobbers. Note that this won't return *all* clobbers.
- ///
- /// Phi optimization algorithm tl;dr:
- /// - Find the earliest def/phi, A, we can optimize to
- /// - Find if all paths from the starting memory access ultimately reach A
- /// - If not, optimization isn't possible.
- /// - Otherwise, walk from A to another clobber or phi, A'.
- /// - If A' is a def, we're done.
- /// - If A' is a phi, try to optimize it.
- ///
- /// A path is a series of {MemoryAccess, MemoryLocation} pairs. A path
- /// terminates when a MemoryAccess that clobbers said MemoryLocation is found.
- OptznResult tryOptimizePhi(MemoryPhi *Phi, MemoryAccess *Start,
- const MemoryLocation &Loc) {
- assert(Paths.empty() && VisitedPhis.empty() &&
- "Reset the optimization state.");
-
- Paths.emplace_back(Loc, Start, Phi, None);
- // Stores how many "valid" optimization nodes we had prior to calling
- // addSearches/getBlockingAccess. Necessary for caching if we had a blocker.
- auto PriorPathsSize = Paths.size();
-
- SmallVector<ListIndex, 16> PausedSearches;
- SmallVector<ListIndex, 8> NewPaused;
- SmallVector<TerminatedPath, 4> TerminatedPaths;
-
- addSearches(Phi, PausedSearches, 0);
-
- // Moves the TerminatedPath with the "most dominated" Clobber to the end of
- // Paths.
- auto MoveDominatedPathToEnd = [&](SmallVectorImpl<TerminatedPath> &Paths) {
- assert(!Paths.empty() && "Need a path to move");
- auto Dom = Paths.begin();
- for (auto I = std::next(Dom), E = Paths.end(); I != E; ++I)
- if (!MSSA.dominates(I->Clobber, Dom->Clobber))
- Dom = I;
- auto Last = Paths.end() - 1;
- if (Last != Dom)
- std::iter_swap(Last, Dom);
- };
-
- MemoryPhi *Current = Phi;
- while (1) {
- assert(!MSSA.isLiveOnEntryDef(Current) &&
- "liveOnEntry wasn't treated as a clobber?");
-
- MemoryAccess *Target = getWalkTarget(Current);
- // If a TerminatedPath doesn't dominate Target, then it wasn't a legal
- // optimization for the prior phi.
- assert(all_of(TerminatedPaths, [&](const TerminatedPath &P) {
- return MSSA.dominates(P.Clobber, Target);
- }));
-
- // FIXME: This is broken, because the Blocker may be reported to be
- // liveOnEntry, and we'll happily wait for that to disappear (read: never)
- // For the moment, this is fine, since we do nothing with blocker info.
- if (Optional<TerminatedPath> Blocker = getBlockingAccess(
- Target, PausedSearches, NewPaused, TerminatedPaths)) {
- // Cache our work on the blocking node, since we know that's correct.
- cacheDefPath(Paths[Blocker->LastNode], Blocker->Clobber);
-
- // Find the node we started at. We can't search based on N->Last, since
- // we may have gone around a loop with a different MemoryLocation.
- auto Iter = find_if(def_path(Blocker->LastNode), [&](const DefPath &N) {
- return defPathIndex(N) < PriorPathsSize;
- });
- assert(Iter != def_path_iterator());
-
- DefPath &CurNode = *Iter;
- assert(CurNode.Last == Current);
-
- // Two things:
- // A. We can't reliably cache all of NewPaused back. Consider a case
- // where we have two paths in NewPaused; one of which can't optimize
- // above this phi, whereas the other can. If we cache the second path
- // back, we'll end up with suboptimal cache entries. We can handle
- // cases like this a bit better when we either try to find all
- // clobbers that block phi optimization, or when our cache starts
- // supporting unfinished searches.
- // B. We can't reliably cache TerminatedPaths back here without doing
- // extra checks; consider a case like:
- // T
- // / \
- // D C
- // \ /
- // S
- // Where T is our target, C is a node with a clobber on it, D is a
- // diamond (with a clobber *only* on the left or right node, N), and
- // S is our start. Say we walk to D, through the node opposite N
- // (read: ignoring the clobber), and see a cache entry in the top
- // node of D. That cache entry gets put into TerminatedPaths. We then
- // walk up to C (N is later in our worklist), find the clobber, and
- // quit. If we append TerminatedPaths to OtherClobbers, we'll cache
- // the bottom part of D to the cached clobber, ignoring the clobber
- // in N. Again, this problem goes away if we start tracking all
- // blockers for a given phi optimization.
- TerminatedPath Result{CurNode.Last, defPathIndex(CurNode)};
- return {Result, {}};
- }
-
- // If there's nothing left to search, then all paths led to valid clobbers
- // that we got from our cache; pick the nearest to the start, and allow
- // the rest to be cached back.
- if (NewPaused.empty()) {
- MoveDominatedPathToEnd(TerminatedPaths);
- TerminatedPath Result = TerminatedPaths.pop_back_val();
- return {Result, std::move(TerminatedPaths)};
- }
-
- MemoryAccess *DefChainEnd = nullptr;
- SmallVector<TerminatedPath, 4> Clobbers;
- for (ListIndex Paused : NewPaused) {
- UpwardsWalkResult WR = walkToPhiOrClobber(Paths[Paused]);
- if (WR.IsKnownClobber)
- Clobbers.push_back({WR.Result, Paused});
- else
- // Micro-opt: If we hit the end of the chain, save it.
- DefChainEnd = WR.Result;
- }
-
- if (!TerminatedPaths.empty()) {
- // If we couldn't find the dominating phi/liveOnEntry in the above loop,
- // do it now.
- if (!DefChainEnd)
- for (MemoryAccess *MA : def_chain(Target))
- DefChainEnd = MA;
-
- // If any of the terminated paths don't dominate the phi we'll try to
- // optimize, we need to figure out what they are and quit.
- const BasicBlock *ChainBB = DefChainEnd->getBlock();
- for (const TerminatedPath &TP : TerminatedPaths) {
- // Because we know that DefChainEnd is as "high" as we can go, we
- // don't need local dominance checks; BB dominance is sufficient.
- if (DT.dominates(ChainBB, TP.Clobber->getBlock()))
- Clobbers.push_back(TP);
- }
- }
-
- // If we have clobbers in the def chain, find the one closest to Current
- // and quit.
- if (!Clobbers.empty()) {
- MoveDominatedPathToEnd(Clobbers);
- TerminatedPath Result = Clobbers.pop_back_val();
- return {Result, std::move(Clobbers)};
- }
-
- assert(all_of(NewPaused,
- [&](ListIndex I) { return Paths[I].Last == DefChainEnd; }));
-
- // Because liveOnEntry is a clobber, this must be a phi.
- auto *DefChainPhi = cast<MemoryPhi>(DefChainEnd);
-
- PriorPathsSize = Paths.size();
- PausedSearches.clear();
- for (ListIndex I : NewPaused)
- addSearches(DefChainPhi, PausedSearches, I);
- NewPaused.clear();
-
- Current = DefChainPhi;
- }
- }
-
- /// Caches everything in an OptznResult.
- void cacheOptResult(const OptznResult &R) {
- if (R.OtherClobbers.empty()) {
- // If we're not going to be caching OtherClobbers, don't bother with
- // marking visited/etc.
- for (const DefPath &N : const_def_path(R.PrimaryClobber.LastNode))
- cacheDefPath(N, R.PrimaryClobber.Clobber);
- return;
- }
-
- // PrimaryClobber is our answer. If we can cache anything back, we need to
- // stop caching when we visit PrimaryClobber.
- SmallBitVector Visited(Paths.size());
- for (const DefPath &N : const_def_path(R.PrimaryClobber.LastNode)) {
- Visited[defPathIndex(N)] = true;
- cacheDefPath(N, R.PrimaryClobber.Clobber);
- }
-
- for (const TerminatedPath &P : R.OtherClobbers) {
- for (const DefPath &N : const_def_path(P.LastNode)) {
- ListIndex NIndex = defPathIndex(N);
- if (Visited[NIndex])
- break;
- Visited[NIndex] = true;
- cacheDefPath(N, P.Clobber);
- }
- }
- }
-
- void verifyOptResult(const OptznResult &R) const {
- assert(all_of(R.OtherClobbers, [&](const TerminatedPath &P) {
- return MSSA.dominates(P.Clobber, R.PrimaryClobber.Clobber);
- }));
- }
-
- void resetPhiOptznState() {
- Paths.clear();
- VisitedPhis.clear();
- }
-
-public:
- ClobberWalker(const MemorySSA &MSSA, AliasAnalysis &AA, DominatorTree &DT,
- WalkerCache &WC)
- : MSSA(MSSA), AA(AA), DT(DT), WC(WC), UseCache(true) {}
-
- void reset() { WalkTargetCache.clear(); }
-
- /// Finds the nearest clobber for the given query, optimizing phis if
- /// possible.
- MemoryAccess *findClobber(MemoryAccess *Start, UpwardsMemoryQuery &Q,
- bool UseWalkerCache = true) {
- setUseCache(UseWalkerCache);
- Query = &Q;
-
- MemoryAccess *Current = Start;
- // This walker pretends uses don't exist. If we're handed one, silently grab
- // its def. (This has the nice side-effect of ensuring we never cache uses)
- if (auto *MU = dyn_cast<MemoryUse>(Start))
- Current = MU->getDefiningAccess();
-
- DefPath FirstDesc(Q.StartingLoc, Current, Current, None);
- // Fast path for the overly-common case (no crazy phi optimization
- // necessary)
- UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc);
- MemoryAccess *Result;
- if (WalkResult.IsKnownClobber) {
- cacheDefPath(FirstDesc, WalkResult.Result);
- Result = WalkResult.Result;
- } else {
- OptznResult OptRes = tryOptimizePhi(cast<MemoryPhi>(FirstDesc.Last),
- Current, Q.StartingLoc);
- verifyOptResult(OptRes);
- cacheOptResult(OptRes);
- resetPhiOptznState();
- Result = OptRes.PrimaryClobber.Clobber;
- }
-
-#ifdef EXPENSIVE_CHECKS
- checkClobberSanity(Current, Result, Q.StartingLoc, MSSA, Q, AA);
-#endif
- return Result;
- }
-
- void verify(const MemorySSA *MSSA) { assert(MSSA == &this->MSSA); }
-};
-
-struct RenamePassData {
- DomTreeNode *DTN;
- DomTreeNode::const_iterator ChildIt;
- MemoryAccess *IncomingVal;
-
- RenamePassData(DomTreeNode *D, DomTreeNode::const_iterator It,
- MemoryAccess *M)
- : DTN(D), ChildIt(It), IncomingVal(M) {}
- void swap(RenamePassData &RHS) {
- std::swap(DTN, RHS.DTN);
- std::swap(ChildIt, RHS.ChildIt);
- std::swap(IncomingVal, RHS.IncomingVal);
- }
-};
-} // anonymous namespace
-namespace llvm {
/// \brief A MemorySSAWalker that does AA walks and caching of lookups to
/// disambiguate accesses.
///
@@ -1083,39 +121,59 @@ namespace llvm {
/// ret i32 %r
/// }
class MemorySSA::CachingWalker final : public MemorySSAWalker {
- WalkerCache Cache;
- ClobberWalker Walker;
- bool AutoResetWalker;
-
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, UpwardsMemoryQuery &);
- void verifyRemoved(MemoryAccess *);
-
public:
CachingWalker(MemorySSA *, AliasAnalysis *, DominatorTree *);
~CachingWalker() override;
- using MemorySSAWalker::getClobberingMemoryAccess;
- MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
+ MemoryAccess *getClobberingMemoryAccess(const Instruction *) override;
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
- const MemoryLocation &) override;
+ MemoryLocation &) override;
void invalidateInfo(MemoryAccess *) override;
- /// Whether we call resetClobberWalker() after each time we *actually* walk to
- /// answer a clobber query.
- void setAutoResetWalker(bool AutoReset) { AutoResetWalker = AutoReset; }
+protected:
+ struct UpwardsMemoryQuery;
+ MemoryAccess *doCacheLookup(const MemoryAccess *, const UpwardsMemoryQuery &,
+ const MemoryLocation &);
+
+ void doCacheInsert(const MemoryAccess *, MemoryAccess *,
+ const UpwardsMemoryQuery &, const MemoryLocation &);
- /// Drop the walker's persistent data structures. At the moment, this means
- /// "drop the walker's cache of BasicBlocks ->
- /// earliest-MemoryAccess-we-can-optimize-to". This is necessary if we're
- /// going to have DT updates, if we remove MemoryAccesses, etc.
- void resetClobberWalker() { Walker.reset(); }
+ void doCacheRemove(const MemoryAccess *, const UpwardsMemoryQuery &,
+ const MemoryLocation &);
- void verify(const MemorySSA *MSSA) override {
- MemorySSAWalker::verify(MSSA);
- Walker.verify(MSSA);
+private:
+ MemoryAccessPair UpwardsDFSWalk(MemoryAccess *, const MemoryLocation &,
+ UpwardsMemoryQuery &, bool);
+ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, UpwardsMemoryQuery &);
+ bool instructionClobbersQuery(const MemoryDef *, UpwardsMemoryQuery &,
+ const MemoryLocation &Loc) const;
+ void verifyRemoved(MemoryAccess *);
+ SmallDenseMap<ConstMemoryAccessPair, MemoryAccess *>
+ CachedUpwardsClobberingAccess;
+ DenseMap<const MemoryAccess *, MemoryAccess *> CachedUpwardsClobberingCall;
+ AliasAnalysis *AA;
+ DominatorTree *DT;
+};
+}
+
+namespace {
+struct RenamePassData {
+ DomTreeNode *DTN;
+ DomTreeNode::const_iterator ChildIt;
+ MemoryAccess *IncomingVal;
+
+ RenamePassData(DomTreeNode *D, DomTreeNode::const_iterator It,
+ MemoryAccess *M)
+ : DTN(D), ChildIt(It), IncomingVal(M) {}
+ void swap(RenamePassData &RHS) {
+ std::swap(DTN, RHS.DTN);
+ std::swap(ChildIt, RHS.ChildIt);
+ std::swap(IncomingVal, RHS.IncomingVal);
}
};
+}
+namespace llvm {
/// \brief Rename a single basic block into MemorySSA form.
/// Uses the standard SSA renaming algorithm.
/// \returns The new incoming value.
@@ -1126,13 +184,21 @@ MemoryAccess *MemorySSA::renameBlock(BasicBlock *BB,
if (It != PerBlockAccesses.end()) {
AccessList *Accesses = It->second.get();
for (MemoryAccess &L : *Accesses) {
- if (MemoryUseOrDef *MUD = dyn_cast<MemoryUseOrDef>(&L)) {
- if (MUD->getDefiningAccess() == nullptr)
- MUD->setDefiningAccess(IncomingVal);
- if (isa<MemoryDef>(&L))
- IncomingVal = &L;
- } else {
+ switch (L.getValueID()) {
+ case Value::MemoryUseVal:
+ cast<MemoryUse>(&L)->setDefiningAccess(IncomingVal);
+ break;
+ case Value::MemoryDefVal:
+ // We can't legally optimize defs, because we only allow single
+ // memory phis/uses on operations, and if we optimize these, we can
+ // end up with multiple reaching defs. Uses do not have this
+ // problem, since they do not produce a value
+ cast<MemoryDef>(&L)->setDefiningAccess(IncomingVal);
IncomingVal = &L;
+ break;
+ case Value::MemoryPhiVal:
+ IncomingVal = &L;
+ break;
}
}
}
@@ -1229,10 +295,21 @@ void MemorySSA::markUnreachableAsLiveOnEntry(BasicBlock *BB) {
MemorySSA::MemorySSA(Function &Func, AliasAnalysis *AA, DominatorTree *DT)
: AA(AA), DT(DT), F(Func), LiveOnEntryDef(nullptr), Walker(nullptr),
- NextID(INVALID_MEMORYACCESS_ID) {
+ NextID(0) {
buildMemorySSA();
}
+MemorySSA::MemorySSA(MemorySSA &&MSSA)
+ : AA(MSSA.AA), DT(MSSA.DT), F(MSSA.F),
+ ValueToMemoryAccess(std::move(MSSA.ValueToMemoryAccess)),
+ PerBlockAccesses(std::move(MSSA.PerBlockAccesses)),
+ LiveOnEntryDef(std::move(MSSA.LiveOnEntryDef)),
+ Walker(std::move(MSSA.Walker)), NextID(MSSA.NextID) {
+ // Update the Walker MSSA pointer so it doesn't point to the moved-from MSSA
+ // object any more.
+ Walker->MSSA = this;
+}
+
MemorySSA::~MemorySSA() {
// Drop all our references
for (const auto &Pair : PerBlockAccesses)
@@ -1248,245 +325,6 @@ MemorySSA::AccessList *MemorySSA::getOrCreateAccessList(const BasicBlock *BB) {
return Res.first->second.get();
}
-/// This class is a batch walker of all MemoryUse's in the program, and points
-/// their defining access at the thing that actually clobbers them. Because it
-/// is a batch walker that touches everything, it does not operate like the
-/// other walkers. This walker is basically performing a top-down SSA renaming
-/// pass, where the version stack is used as the cache. This enables it to be
-/// significantly more time and memory efficient than using the regular walker,
-/// which is walking bottom-up.
-class MemorySSA::OptimizeUses {
-public:
- OptimizeUses(MemorySSA *MSSA, MemorySSAWalker *Walker, AliasAnalysis *AA,
- DominatorTree *DT)
- : MSSA(MSSA), Walker(Walker), AA(AA), DT(DT) {
- Walker = MSSA->getWalker();
- }
-
- void optimizeUses();
-
-private:
- /// This represents where a given memorylocation is in the stack.
- struct MemlocStackInfo {
- // This essentially is keeping track of versions of the stack. Whenever
- // the stack changes due to pushes or pops, these versions increase.
- unsigned long StackEpoch;
- unsigned long PopEpoch;
- // This is the lower bound of places on the stack to check. It is equal to
- // the place the last stack walk ended.
- // Note: Correctness depends on this being initialized to 0, which densemap
- // does
- unsigned long LowerBound;
- const BasicBlock *LowerBoundBlock;
- // This is where the last walk for this memory location ended.
- unsigned long LastKill;
- bool LastKillValid;
- };
- void optimizeUsesInBlock(const BasicBlock *, unsigned long &, unsigned long &,
- SmallVectorImpl<MemoryAccess *> &,
- DenseMap<MemoryLocOrCall, MemlocStackInfo> &);
- MemorySSA *MSSA;
- MemorySSAWalker *Walker;
- AliasAnalysis *AA;
- DominatorTree *DT;
-};
-
-/// Optimize the uses in a given block This is basically the SSA renaming
-/// algorithm, with one caveat: We are able to use a single stack for all
-/// MemoryUses. This is because the set of *possible* reaching MemoryDefs is
-/// the same for every MemoryUse. The *actual* clobbering MemoryDef is just
-/// going to be some position in that stack of possible ones.
-///
-/// We track the stack positions that each MemoryLocation needs
-/// to check, and last ended at. This is because we only want to check the
-/// things that changed since last time. The same MemoryLocation should
-/// get clobbered by the same store (getModRefInfo does not use invariantness or
-/// things like this, and if they start, we can modify MemoryLocOrCall to
-/// include relevant data)
-void MemorySSA::OptimizeUses::optimizeUsesInBlock(
- const BasicBlock *BB, unsigned long &StackEpoch, unsigned long &PopEpoch,
- SmallVectorImpl<MemoryAccess *> &VersionStack,
- DenseMap<MemoryLocOrCall, MemlocStackInfo> &LocStackInfo) {
-
- /// If no accesses, nothing to do.
- MemorySSA::AccessList *Accesses = MSSA->getWritableBlockAccesses(BB);
- if (Accesses == nullptr)
- return;
-
- // Pop everything that doesn't dominate the current block off the stack,
- // increment the PopEpoch to account for this.
- while (!VersionStack.empty()) {
- BasicBlock *BackBlock = VersionStack.back()->getBlock();
- if (DT->dominates(BackBlock, BB))
- break;
- while (VersionStack.back()->getBlock() == BackBlock)
- VersionStack.pop_back();
- ++PopEpoch;
- }
- for (MemoryAccess &MA : *Accesses) {
- auto *MU = dyn_cast<MemoryUse>(&MA);
- if (!MU) {
- VersionStack.push_back(&MA);
- ++StackEpoch;
- continue;
- }
-
- if (isUseTriviallyOptimizableToLiveOnEntry(*AA, MU->getMemoryInst())) {
- MU->setDefiningAccess(MSSA->getLiveOnEntryDef(), true);
- continue;
- }
-
- MemoryLocOrCall UseMLOC(MU);
- auto &LocInfo = LocStackInfo[UseMLOC];
- // If the pop epoch changed, it means we've removed stuff from top of
- // stack due to changing blocks. We may have to reset the lower bound or
- // last kill info.
- if (LocInfo.PopEpoch != PopEpoch) {
- LocInfo.PopEpoch = PopEpoch;
- LocInfo.StackEpoch = StackEpoch;
- // If the lower bound was in something that no longer dominates us, we
- // have to reset it.
- // We can't simply track stack size, because the stack may have had
- // pushes/pops in the meantime.
- // XXX: This is non-optimal, but only is slower cases with heavily
- // branching dominator trees. To get the optimal number of queries would
- // be to make lowerbound and lastkill a per-loc stack, and pop it until
- // the top of that stack dominates us. This does not seem worth it ATM.
- // A much cheaper optimization would be to always explore the deepest
- // branch of the dominator tree first. This will guarantee this resets on
- // the smallest set of blocks.
- if (LocInfo.LowerBoundBlock && LocInfo.LowerBoundBlock != BB &&
- !DT->dominates(LocInfo.LowerBoundBlock, BB)) {
- // Reset the lower bound of things to check.
- // TODO: Some day we should be able to reset to last kill, rather than
- // 0.
- LocInfo.LowerBound = 0;
- LocInfo.LowerBoundBlock = VersionStack[0]->getBlock();
- LocInfo.LastKillValid = false;
- }
- } else if (LocInfo.StackEpoch != StackEpoch) {
- // If all that has changed is the StackEpoch, we only have to check the
- // new things on the stack, because we've checked everything before. In
- // this case, the lower bound of things to check remains the same.
- LocInfo.PopEpoch = PopEpoch;
- LocInfo.StackEpoch = StackEpoch;
- }
- if (!LocInfo.LastKillValid) {
- LocInfo.LastKill = VersionStack.size() - 1;
- LocInfo.LastKillValid = true;
- }
-
- // At this point, we should have corrected last kill and LowerBound to be
- // in bounds.
- assert(LocInfo.LowerBound < VersionStack.size() &&
- "Lower bound out of range");
- assert(LocInfo.LastKill < VersionStack.size() &&
- "Last kill info out of range");
- // In any case, the new upper bound is the top of the stack.
- unsigned long UpperBound = VersionStack.size() - 1;
-
- if (UpperBound - LocInfo.LowerBound > MaxCheckLimit) {
- DEBUG(dbgs() << "MemorySSA skipping optimization of " << *MU << " ("
- << *(MU->getMemoryInst()) << ")"
- << " because there are " << UpperBound - LocInfo.LowerBound
- << " stores to disambiguate\n");
- // Because we did not walk, LastKill is no longer valid, as this may
- // have been a kill.
- LocInfo.LastKillValid = false;
- continue;
- }
- bool FoundClobberResult = false;
- while (UpperBound > LocInfo.LowerBound) {
- if (isa<MemoryPhi>(VersionStack[UpperBound])) {
- // For phis, use the walker, see where we ended up, go there
- Instruction *UseInst = MU->getMemoryInst();
- MemoryAccess *Result = Walker->getClobberingMemoryAccess(UseInst);
- // We are guaranteed to find it or something is wrong
- while (VersionStack[UpperBound] != Result) {
- assert(UpperBound != 0);
- --UpperBound;
- }
- FoundClobberResult = true;
- break;
- }
-
- MemoryDef *MD = cast<MemoryDef>(VersionStack[UpperBound]);
- // If the lifetime of the pointer ends at this instruction, it's live on
- // entry.
- if (!UseMLOC.IsCall && lifetimeEndsAt(MD, UseMLOC.getLoc(), *AA)) {
- // Reset UpperBound to liveOnEntryDef's place in the stack
- UpperBound = 0;
- FoundClobberResult = true;
- break;
- }
- if (instructionClobbersQuery(MD, MU, UseMLOC, *AA)) {
- FoundClobberResult = true;
- break;
- }
- --UpperBound;
- }
- // At the end of this loop, UpperBound is either a clobber, or lower bound
- // PHI walking may cause it to be < LowerBound, and in fact, < LastKill.
- if (FoundClobberResult || UpperBound < LocInfo.LastKill) {
- MU->setDefiningAccess(VersionStack[UpperBound], true);
- // We were last killed now by where we got to
- LocInfo.LastKill = UpperBound;
- } else {
- // Otherwise, we checked all the new ones, and now we know we can get to
- // LastKill.
- MU->setDefiningAccess(VersionStack[LocInfo.LastKill], true);
- }
- LocInfo.LowerBound = VersionStack.size() - 1;
- LocInfo.LowerBoundBlock = BB;
- }
-}
-
-/// Optimize uses to point to their actual clobbering definitions.
-void MemorySSA::OptimizeUses::optimizeUses() {
-
- // We perform a non-recursive top-down dominator tree walk
- struct StackInfo {
- const DomTreeNode *Node;
- DomTreeNode::const_iterator Iter;
- };
-
- SmallVector<MemoryAccess *, 16> VersionStack;
- SmallVector<StackInfo, 16> DomTreeWorklist;
- DenseMap<MemoryLocOrCall, MemlocStackInfo> LocStackInfo;
- VersionStack.push_back(MSSA->getLiveOnEntryDef());
-
- unsigned long StackEpoch = 1;
- unsigned long PopEpoch = 1;
- for (const auto *DomNode : depth_first(DT->getRootNode()))
- optimizeUsesInBlock(DomNode->getBlock(), StackEpoch, PopEpoch, VersionStack,
- LocStackInfo);
-}
-
-void MemorySSA::placePHINodes(
- const SmallPtrSetImpl<BasicBlock *> &DefiningBlocks,
- const DenseMap<const BasicBlock *, unsigned int> &BBNumbers) {
- // Determine where our MemoryPhi's should go
- ForwardIDFCalculator IDFs(*DT);
- IDFs.setDefiningBlocks(DefiningBlocks);
- SmallVector<BasicBlock *, 32> IDFBlocks;
- IDFs.calculate(IDFBlocks);
-
- std::sort(IDFBlocks.begin(), IDFBlocks.end(),
- [&BBNumbers](const BasicBlock *A, const BasicBlock *B) {
- return BBNumbers.lookup(A) < BBNumbers.lookup(B);
- });
-
- // Now place MemoryPhi nodes.
- for (auto &BB : IDFBlocks) {
- // Insert phi node
- AccessList *Accesses = getOrCreateAccessList(BB);
- MemoryPhi *Phi = new MemoryPhi(BB->getContext(), BB, NextID++);
- ValueToMemoryAccess[BB] = Phi;
- // Phi's always are placed at the front of the block.
- Accesses->push_front(Phi);
- }
-}
-
void MemorySSA::buildMemorySSA() {
// We create an access to represent "live on entry", for things like
// arguments or users of globals, where the memory they use is defined before
@@ -1497,8 +335,6 @@ void MemorySSA::buildMemorySSA() {
BasicBlock &StartingPoint = F.getEntryBlock();
LiveOnEntryDef = make_unique<MemoryDef>(F.getContext(), nullptr, nullptr,
&StartingPoint, NextID++);
- DenseMap<const BasicBlock *, unsigned int> BBNumbers;
- unsigned NextBBNum = 0;
// We maintain lists of memory accesses per-block, trading memory for time. We
// could just look up the memory access for every possible instruction in the
@@ -1508,7 +344,6 @@ void MemorySSA::buildMemorySSA() {
// Go through each block, figure out where defs occur, and chain together all
// the accesses.
for (BasicBlock &B : F) {
- BBNumbers[&B] = NextBBNum++;
bool InsertIntoDef = false;
AccessList *Accesses = nullptr;
for (Instruction &I : B) {
@@ -1526,20 +361,81 @@ void MemorySSA::buildMemorySSA() {
if (Accesses)
DefUseBlocks.insert(&B);
}
- placePHINodes(DefiningBlocks, BBNumbers);
+
+ // Compute live-in.
+ // Live in is normally defined as "all the blocks on the path from each def to
+ // each of it's uses".
+ // MemoryDef's are implicit uses of previous state, so they are also uses.
+ // This means we don't really have def-only instructions. The only
+ // MemoryDef's that are not really uses are those that are of the LiveOnEntry
+ // variable (because LiveOnEntry can reach anywhere, and every def is a
+ // must-kill of LiveOnEntry).
+ // In theory, you could precisely compute live-in by using alias-analysis to
+ // disambiguate defs and uses to see which really pair up with which.
+ // In practice, this would be really expensive and difficult. So we simply
+ // assume all defs are also uses that need to be kept live.
+ // Because of this, the end result of this live-in computation will be "the
+ // entire set of basic blocks that reach any use".
+
+ SmallPtrSet<BasicBlock *, 32> LiveInBlocks;
+ SmallVector<BasicBlock *, 64> LiveInBlockWorklist(DefUseBlocks.begin(),
+ DefUseBlocks.end());
+ // Now that we have a set of blocks where a value is live-in, recursively add
+ // predecessors until we find the full region the value is live.
+ while (!LiveInBlockWorklist.empty()) {
+ BasicBlock *BB = LiveInBlockWorklist.pop_back_val();
+
+ // The block really is live in here, insert it into the set. If already in
+ // the set, then it has already been processed.
+ if (!LiveInBlocks.insert(BB).second)
+ continue;
+
+ // Since the value is live into BB, it is either defined in a predecessor or
+ // live into it to.
+ LiveInBlockWorklist.append(pred_begin(BB), pred_end(BB));
+ }
+
+ // Determine where our MemoryPhi's should go
+ ForwardIDFCalculator IDFs(*DT);
+ IDFs.setDefiningBlocks(DefiningBlocks);
+ IDFs.setLiveInBlocks(LiveInBlocks);
+ SmallVector<BasicBlock *, 32> IDFBlocks;
+ IDFs.calculate(IDFBlocks);
+
+ // Now place MemoryPhi nodes.
+ for (auto &BB : IDFBlocks) {
+ // Insert phi node
+ AccessList *Accesses = getOrCreateAccessList(BB);
+ MemoryPhi *Phi = new MemoryPhi(BB->getContext(), BB, NextID++);
+ ValueToMemoryAccess.insert(std::make_pair(BB, Phi));
+ // Phi's always are placed at the front of the block.
+ Accesses->push_front(Phi);
+ }
// Now do regular SSA renaming on the MemoryDef/MemoryUse. Visited will get
// filled in with all blocks.
SmallPtrSet<BasicBlock *, 16> Visited;
renamePass(DT->getRootNode(), LiveOnEntryDef.get(), Visited);
- CachingWalker *Walker = getWalkerImpl();
+ MemorySSAWalker *Walker = getWalker();
- // We're doing a batch of updates; don't drop useful caches between them.
- Walker->setAutoResetWalker(false);
- OptimizeUses(this, Walker, AA, DT).optimizeUses();
- Walker->setAutoResetWalker(true);
- Walker->resetClobberWalker();
+ // Now optimize the MemoryUse's defining access to point to the nearest
+ // dominating clobbering def.
+ // This ensures that MemoryUse's that are killed by the same store are
+ // immediate users of that store, one of the invariants we guarantee.
+ for (auto DomNode : depth_first(DT)) {
+ BasicBlock *BB = DomNode->getBlock();
+ auto AI = PerBlockAccesses.find(BB);
+ if (AI == PerBlockAccesses.end())
+ continue;
+ AccessList *Accesses = AI->second.get();
+ for (auto &MA : *Accesses) {
+ if (auto *MU = dyn_cast<MemoryUse>(&MA)) {
+ Instruction *Inst = MU->getMemoryInst();
+ MU->setDefiningAccess(Walker->getClobberingMemoryAccess(Inst));
+ }
+ }
+ }
// Mark the uses in unreachable blocks as live on entry, so that they go
// somewhere.
@@ -1548,9 +444,7 @@ void MemorySSA::buildMemorySSA() {
markUnreachableAsLiveOnEntry(&BB);
}
-MemorySSAWalker *MemorySSA::getWalker() { return getWalkerImpl(); }
-
-MemorySSA::CachingWalker *MemorySSA::getWalkerImpl() {
+MemorySSAWalker *MemorySSA::getWalker() {
if (Walker)
return Walker.get();
@@ -1562,10 +456,9 @@ MemoryPhi *MemorySSA::createMemoryPhi(BasicBlock *BB) {
assert(!getMemoryAccess(BB) && "MemoryPhi already exists for this BB");
AccessList *Accesses = getOrCreateAccessList(BB);
MemoryPhi *Phi = new MemoryPhi(BB->getContext(), BB, NextID++);
- ValueToMemoryAccess[BB] = Phi;
+ ValueToMemoryAccess.insert(std::make_pair(BB, Phi));
// Phi's always are placed at the front of the block.
Accesses->push_front(Phi);
- BlockNumberingValid.erase(BB);
return Phi;
}
@@ -1588,64 +481,39 @@ MemoryAccess *MemorySSA::createMemoryAccessInBB(Instruction *I,
auto *Accesses = getOrCreateAccessList(BB);
if (Point == Beginning) {
// It goes after any phi nodes
- auto AI = find_if(
- *Accesses, [](const MemoryAccess &MA) { return !isa<MemoryPhi>(MA); });
+ auto AI = std::find_if(
+ Accesses->begin(), Accesses->end(),
+ [](const MemoryAccess &MA) { return !isa<MemoryPhi>(MA); });
Accesses->insert(AI, NewAccess);
} else {
Accesses->push_back(NewAccess);
}
- BlockNumberingValid.erase(BB);
+
return NewAccess;
}
-
-MemoryUseOrDef *MemorySSA::createMemoryAccessBefore(Instruction *I,
- MemoryAccess *Definition,
- MemoryUseOrDef *InsertPt) {
+MemoryAccess *MemorySSA::createMemoryAccessBefore(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt) {
assert(I->getParent() == InsertPt->getBlock() &&
"New and old access must be in the same block");
MemoryUseOrDef *NewAccess = createDefinedAccess(I, Definition);
auto *Accesses = getOrCreateAccessList(InsertPt->getBlock());
Accesses->insert(AccessList::iterator(InsertPt), NewAccess);
- BlockNumberingValid.erase(InsertPt->getBlock());
return NewAccess;
}
-MemoryUseOrDef *MemorySSA::createMemoryAccessAfter(Instruction *I,
- MemoryAccess *Definition,
- MemoryAccess *InsertPt) {
+MemoryAccess *MemorySSA::createMemoryAccessAfter(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt) {
assert(I->getParent() == InsertPt->getBlock() &&
"New and old access must be in the same block");
MemoryUseOrDef *NewAccess = createDefinedAccess(I, Definition);
auto *Accesses = getOrCreateAccessList(InsertPt->getBlock());
Accesses->insertAfter(AccessList::iterator(InsertPt), NewAccess);
- BlockNumberingValid.erase(InsertPt->getBlock());
return NewAccess;
}
-void MemorySSA::spliceMemoryAccessAbove(MemoryDef *Where,
- MemoryUseOrDef *What) {
- assert(What != getLiveOnEntryDef() &&
- Where != getLiveOnEntryDef() && "Can't splice (above) LOE.");
- assert(dominates(Where, What) && "Only upwards splices are permitted.");
-
- if (Where == What)
- return;
- if (isa<MemoryDef>(What)) {
- // TODO: possibly use removeMemoryAccess' more efficient RAUW
- What->replaceAllUsesWith(What->getDefiningAccess());
- What->setDefiningAccess(Where->getDefiningAccess());
- Where->setDefiningAccess(What);
- }
- AccessList *Src = getWritableBlockAccesses(What->getBlock());
- AccessList *Dest = getWritableBlockAccesses(Where->getBlock());
- Dest->splice(AccessList::iterator(Where), *Src, What);
-
- BlockNumberingValid.erase(What->getBlock());
- if (What->getBlock() != Where->getBlock())
- BlockNumberingValid.erase(Where->getBlock());
-}
-
/// \brief Helper function to create new memory accesses
MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I) {
// The assume intrinsic has a control dependency which we model by claiming
@@ -1674,7 +542,7 @@ MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I) {
MUD = new MemoryDef(I->getContext(), nullptr, I, I->getParent(), NextID++);
else
MUD = new MemoryUse(I->getContext(), nullptr, I, I->getParent());
- ValueToMemoryAccess[I] = MUD;
+ ValueToMemoryAccess.insert(std::make_pair(I, MUD));
return MUD;
}
@@ -1743,7 +611,6 @@ static MemoryAccess *onlySingleValue(MemoryPhi *MP) {
void MemorySSA::removeFromLookups(MemoryAccess *MA) {
assert(MA->use_empty() &&
"Trying to remove memory access that still has uses");
- BlockNumbering.erase(MA);
if (MemoryUseOrDef *MUD = dyn_cast<MemoryUseOrDef>(MA))
MUD->setDefiningAccess(nullptr);
// Invalidate our walker's cache if necessary
@@ -1757,9 +624,7 @@ void MemorySSA::removeFromLookups(MemoryAccess *MA) {
} else {
MemoryInst = MA->getBlock();
}
- auto VMA = ValueToMemoryAccess.find(MemoryInst);
- if (VMA->second == MA)
- ValueToMemoryAccess.erase(VMA);
+ ValueToMemoryAccess.erase(MemoryInst);
auto AccessIt = PerBlockAccesses.find(MA->getBlock());
std::unique_ptr<AccessList> &Accesses = AccessIt->second;
@@ -1787,27 +652,8 @@ void MemorySSA::removeMemoryAccess(MemoryAccess *MA) {
}
// Re-point the uses at our defining access
- if (!MA->use_empty()) {
- // Reset optimized on users of this store, and reset the uses.
- // A few notes:
- // 1. This is a slightly modified version of RAUW to avoid walking the
- // uses twice here.
- // 2. If we wanted to be complete, we would have to reset the optimized
- // flags on users of phi nodes if doing the below makes a phi node have all
- // the same arguments. Instead, we prefer users to removeMemoryAccess those
- // phi nodes, because doing it here would be N^3.
- if (MA->hasValueHandle())
- ValueHandleBase::ValueIsRAUWd(MA, NewDefTarget);
- // Note: We assume MemorySSA is not used in metadata since it's not really
- // part of the IR.
-
- while (!MA->use_empty()) {
- Use &U = *MA->use_begin();
- if (MemoryUse *MU = dyn_cast<MemoryUse>(U.getUser()))
- MU->resetOptimized();
- U.set(NewDefTarget);
- }
- }
+ if (!MA->use_empty())
+ MA->replaceAllUsesWith(NewDefTarget);
// The call below to erase will destroy MA, so we can't change the order we
// are doing things here
@@ -1828,7 +674,6 @@ void MemorySSA::verifyMemorySSA() const {
verifyDefUses(F);
verifyDomination(F);
verifyOrdering(F);
- Walker->verify(this);
}
/// \brief Verify that the order and existence of MemoryAccesses matches the
@@ -1872,38 +717,70 @@ void MemorySSA::verifyOrdering(Function &F) const {
/// \brief Verify the domination properties of MemorySSA by checking that each
/// definition dominates all of its uses.
void MemorySSA::verifyDomination(Function &F) const {
-#ifndef NDEBUG
for (BasicBlock &B : F) {
// Phi nodes are attached to basic blocks
- if (MemoryPhi *MP = getMemoryAccess(&B))
- for (const Use &U : MP->uses())
- assert(dominates(MP, U) && "Memory PHI does not dominate it's uses");
+ if (MemoryPhi *MP = getMemoryAccess(&B)) {
+ for (User *U : MP->users()) {
+ BasicBlock *UseBlock;
+ // Phi operands are used on edges, we simulate the right domination by
+ // acting as if the use occurred at the end of the predecessor block.
+ if (MemoryPhi *P = dyn_cast<MemoryPhi>(U)) {
+ for (const auto &Arg : P->operands()) {
+ if (Arg == MP) {
+ UseBlock = P->getIncomingBlock(Arg);
+ break;
+ }
+ }
+ } else {
+ UseBlock = cast<MemoryAccess>(U)->getBlock();
+ }
+ (void)UseBlock;
+ assert(DT->dominates(MP->getBlock(), UseBlock) &&
+ "Memory PHI does not dominate it's uses");
+ }
+ }
for (Instruction &I : B) {
MemoryAccess *MD = dyn_cast_or_null<MemoryDef>(getMemoryAccess(&I));
if (!MD)
continue;
- for (const Use &U : MD->uses())
- assert(dominates(MD, U) && "Memory Def does not dominate it's uses");
+ for (User *U : MD->users()) {
+ BasicBlock *UseBlock;
+ (void)UseBlock;
+ // Things are allowed to flow to phi nodes over their predecessor edge.
+ if (auto *P = dyn_cast<MemoryPhi>(U)) {
+ for (const auto &Arg : P->operands()) {
+ if (Arg == MD) {
+ UseBlock = P->getIncomingBlock(Arg);
+ break;
+ }
+ }
+ } else {
+ UseBlock = cast<MemoryAccess>(U)->getBlock();
+ }
+ assert(DT->dominates(MD->getBlock(), UseBlock) &&
+ "Memory Def does not dominate it's uses");
+ }
}
}
-#endif
}
/// \brief Verify the def-use lists in MemorySSA, by verifying that \p Use
/// appears in the use list of \p Def.
-
+///
+/// llvm_unreachable is used instead of asserts because this may be called in
+/// a build without asserts. In that case, we don't want this to turn into a
+/// nop.
void MemorySSA::verifyUseInDefs(MemoryAccess *Def, MemoryAccess *Use) const {
-#ifndef NDEBUG
// The live on entry use may cause us to get a NULL def here
- if (!Def)
- assert(isLiveOnEntryDef(Use) &&
- "Null def but use not point to live on entry def");
- else
- assert(is_contained(Def->users(), Use) &&
- "Did not find use in def's use list");
-#endif
+ if (!Def) {
+ if (!isLiveOnEntryDef(Use))
+ llvm_unreachable("Null def but use not point to live on entry def");
+ } else if (std::find(Def->user_begin(), Def->user_end(), Use) ==
+ Def->user_end()) {
+ llvm_unreachable("Did not find use in def's use list");
+ }
}
/// \brief Verify the immediate use information, by walking all the memory
@@ -1921,35 +798,21 @@ void MemorySSA::verifyDefUses(Function &F) const {
}
for (Instruction &I : B) {
- if (MemoryUseOrDef *MA = getMemoryAccess(&I)) {
- verifyUseInDefs(MA->getDefiningAccess(), MA);
+ if (MemoryAccess *MA = getMemoryAccess(&I)) {
+ assert(isa<MemoryUseOrDef>(MA) &&
+ "Found a phi node not attached to a bb");
+ verifyUseInDefs(cast<MemoryUseOrDef>(MA)->getDefiningAccess(), MA);
}
}
}
}
-MemoryUseOrDef *MemorySSA::getMemoryAccess(const Instruction *I) const {
- return cast_or_null<MemoryUseOrDef>(ValueToMemoryAccess.lookup(I));
+MemoryAccess *MemorySSA::getMemoryAccess(const Value *I) const {
+ return ValueToMemoryAccess.lookup(I);
}
MemoryPhi *MemorySSA::getMemoryAccess(const BasicBlock *BB) const {
- return cast_or_null<MemoryPhi>(ValueToMemoryAccess.lookup(cast<Value>(BB)));
-}
-
-/// Perform a local numbering on blocks so that instruction ordering can be
-/// determined in constant time.
-/// TODO: We currently just number in order. If we numbered by N, we could
-/// allow at least N-1 sequences of insertBefore or insertAfter (and at least
-/// log2(N) sequences of mixed before and after) without needing to invalidate
-/// the numbering.
-void MemorySSA::renumberBlock(const BasicBlock *B) const {
- // The pre-increment ensures the numbers really start at 1.
- unsigned long CurrentNumber = 0;
- const AccessList *AL = getBlockAccesses(B);
- assert(AL != nullptr && "Asking to renumber an empty block");
- for (const auto &I : *AL)
- BlockNumbering[&I] = ++CurrentNumber;
- BlockNumberingValid.insert(B);
+ return cast_or_null<MemoryPhi>(getMemoryAccess((const Value *)BB));
}
/// \brief Determine, for two memory accesses in the same block,
@@ -1958,10 +821,9 @@ void MemorySSA::renumberBlock(const BasicBlock *B) const {
bool MemorySSA::locallyDominates(const MemoryAccess *Dominator,
const MemoryAccess *Dominatee) const {
- const BasicBlock *DominatorBlock = Dominator->getBlock();
-
- assert((DominatorBlock == Dominatee->getBlock()) &&
+ assert((Dominator->getBlock() == Dominatee->getBlock()) &&
"Asking for local domination when accesses are in different blocks!");
+
// A node dominates itself.
if (Dominatee == Dominator)
return true;
@@ -1976,42 +838,14 @@ bool MemorySSA::locallyDominates(const MemoryAccess *Dominator,
if (isLiveOnEntryDef(Dominator))
return true;
- if (!BlockNumberingValid.count(DominatorBlock))
- renumberBlock(DominatorBlock);
-
- unsigned long DominatorNum = BlockNumbering.lookup(Dominator);
- // All numbers start with 1
- assert(DominatorNum != 0 && "Block was not numbered properly");
- unsigned long DominateeNum = BlockNumbering.lookup(Dominatee);
- assert(DominateeNum != 0 && "Block was not numbered properly");
- return DominatorNum < DominateeNum;
-}
-
-bool MemorySSA::dominates(const MemoryAccess *Dominator,
- const MemoryAccess *Dominatee) const {
- if (Dominator == Dominatee)
- return true;
-
- if (isLiveOnEntryDef(Dominatee))
- return false;
-
- if (Dominator->getBlock() != Dominatee->getBlock())
- return DT->dominates(Dominator->getBlock(), Dominatee->getBlock());
- return locallyDominates(Dominator, Dominatee);
-}
+ // Get the access list for the block
+ const AccessList *AccessList = getBlockAccesses(Dominator->getBlock());
+ AccessList::const_reverse_iterator It(Dominator->getIterator());
-bool MemorySSA::dominates(const MemoryAccess *Dominator,
- const Use &Dominatee) const {
- if (MemoryPhi *MP = dyn_cast<MemoryPhi>(Dominatee.getUser())) {
- BasicBlock *UseBB = MP->getIncomingBlock(Dominatee);
- // The def must dominate the incoming block of the phi.
- if (UseBB != Dominator->getBlock())
- return DT->dominates(Dominator->getBlock(), UseBB);
- // If the UseBB and the DefBB are the same, compare locally.
- return locallyDominates(Dominator, cast<MemoryAccess>(Dominatee));
- }
- // If it's not a PHI node use, the normal dominates can already handle it.
- return dominates(Dominator, cast<MemoryAccess>(Dominatee.getUser()));
+ // If we hit the beginning of the access list before we hit dominatee, we must
+ // dominate it
+ return std::none_of(It, AccessList->rend(),
+ [&](const MemoryAccess &MA) { return &MA == Dominatee; });
}
const static char LiveOnEntryStr[] = "liveOnEntry";
@@ -2090,26 +924,25 @@ bool MemorySSAPrinterLegacyPass::runOnFunction(Function &F) {
return false;
}
-AnalysisKey MemorySSAAnalysis::Key;
+char MemorySSAAnalysis::PassID;
-MemorySSAAnalysis::Result MemorySSAAnalysis::run(Function &F,
- FunctionAnalysisManager &AM) {
+MemorySSA MemorySSAAnalysis::run(Function &F, AnalysisManager<Function> &AM) {
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
auto &AA = AM.getResult<AAManager>(F);
- return MemorySSAAnalysis::Result(make_unique<MemorySSA>(F, &AA, &DT));
+ return MemorySSA(F, &AA, &DT);
}
PreservedAnalyses MemorySSAPrinterPass::run(Function &F,
FunctionAnalysisManager &AM) {
OS << "MemorySSA for function: " << F.getName() << "\n";
- AM.getResult<MemorySSAAnalysis>(F).getMSSA().print(OS);
+ AM.getResult<MemorySSAAnalysis>(F).print(OS);
return PreservedAnalyses::all();
}
PreservedAnalyses MemorySSAVerifierPass::run(Function &F,
FunctionAnalysisManager &AM) {
- AM.getResult<MemorySSAAnalysis>(F).getMSSA().verifyMemorySSA();
+ AM.getResult<MemorySSAAnalysis>(F).verifyMemorySSA();
return PreservedAnalyses::all();
}
@@ -2145,11 +978,41 @@ MemorySSAWalker::MemorySSAWalker(MemorySSA *M) : MSSA(M) {}
MemorySSA::CachingWalker::CachingWalker(MemorySSA *M, AliasAnalysis *A,
DominatorTree *D)
- : MemorySSAWalker(M), Walker(*M, *A, *D, Cache), AutoResetWalker(true) {}
+ : MemorySSAWalker(M), AA(A), DT(D) {}
MemorySSA::CachingWalker::~CachingWalker() {}
+struct MemorySSA::CachingWalker::UpwardsMemoryQuery {
+ // True if we saw a phi whose predecessor was a backedge
+ bool SawBackedgePhi;
+ // True if our original query started off as a call
+ bool IsCall;
+ // The pointer location we started the query with. This will be empty if
+ // IsCall is true.
+ MemoryLocation StartingLoc;
+ // This is the instruction we were querying about.
+ const Instruction *Inst;
+ // Set of visited Instructions for this query.
+ DenseSet<MemoryAccessPair> Visited;
+ // Vector of visited call accesses for this query. This is separated out
+ // because you can always cache and lookup the result of call queries (IE when
+ // IsCall == true) for every call in the chain. The calls have no AA location
+ // associated with them with them, and thus, no context dependence.
+ SmallVector<const MemoryAccess *, 32> VisitedCalls;
+ // The MemoryAccess we actually got called with, used to test local domination
+ const MemoryAccess *OriginalAccess;
+
+ UpwardsMemoryQuery()
+ : SawBackedgePhi(false), IsCall(false), Inst(nullptr),
+ OriginalAccess(nullptr) {}
+
+ UpwardsMemoryQuery(const Instruction *Inst, const MemoryAccess *Access)
+ : SawBackedgePhi(false), IsCall(ImmutableCallSite(Inst)), Inst(Inst),
+ OriginalAccess(Access) {}
+};
+
void MemorySSA::CachingWalker::invalidateInfo(MemoryAccess *MA) {
+
// TODO: We can do much better cache invalidation with differently stored
// caches. For now, for MemoryUses, we simply remove them
// from the cache, and kill the entire call/non-call cache for everything
@@ -2163,38 +1026,220 @@ void MemorySSA::CachingWalker::invalidateInfo(MemoryAccess *MA) {
// itself.
if (MemoryUse *MU = dyn_cast<MemoryUse>(MA)) {
- UpwardsMemoryQuery Q(MU->getMemoryInst(), MU);
- Cache.remove(MU, Q.StartingLoc, Q.IsCall);
- MU->resetOptimized();
+ UpwardsMemoryQuery Q;
+ Instruction *I = MU->getMemoryInst();
+ Q.IsCall = bool(ImmutableCallSite(I));
+ Q.Inst = I;
+ if (!Q.IsCall)
+ Q.StartingLoc = MemoryLocation::get(I);
+ doCacheRemove(MA, Q, Q.StartingLoc);
} else {
// If it is not a use, the best we can do right now is destroy the cache.
- Cache.clear();
+ CachedUpwardsClobberingCall.clear();
+ CachedUpwardsClobberingAccess.clear();
}
#ifdef EXPENSIVE_CHECKS
+ // Run this only when expensive checks are enabled.
verifyRemoved(MA);
#endif
}
+void MemorySSA::CachingWalker::doCacheRemove(const MemoryAccess *M,
+ const UpwardsMemoryQuery &Q,
+ const MemoryLocation &Loc) {
+ if (Q.IsCall)
+ CachedUpwardsClobberingCall.erase(M);
+ else
+ CachedUpwardsClobberingAccess.erase({M, Loc});
+}
+
+void MemorySSA::CachingWalker::doCacheInsert(const MemoryAccess *M,
+ MemoryAccess *Result,
+ const UpwardsMemoryQuery &Q,
+ const MemoryLocation &Loc) {
+ // This is fine for Phis, since there are times where we can't optimize them.
+ // Making a def its own clobber is never correct, though.
+ assert((Result != M || isa<MemoryPhi>(M)) &&
+ "Something can't clobber itself!");
+ ++NumClobberCacheInserts;
+ if (Q.IsCall)
+ CachedUpwardsClobberingCall[M] = Result;
+ else
+ CachedUpwardsClobberingAccess[{M, Loc}] = Result;
+}
+
+MemoryAccess *
+MemorySSA::CachingWalker::doCacheLookup(const MemoryAccess *M,
+ const UpwardsMemoryQuery &Q,
+ const MemoryLocation &Loc) {
+ ++NumClobberCacheLookups;
+ MemoryAccess *Result;
+
+ if (Q.IsCall)
+ Result = CachedUpwardsClobberingCall.lookup(M);
+ else
+ Result = CachedUpwardsClobberingAccess.lookup({M, Loc});
+
+ if (Result)
+ ++NumClobberCacheHits;
+ return Result;
+}
+
+bool MemorySSA::CachingWalker::instructionClobbersQuery(
+ const MemoryDef *MD, UpwardsMemoryQuery &Q,
+ const MemoryLocation &Loc) const {
+ Instruction *DefMemoryInst = MD->getMemoryInst();
+ assert(DefMemoryInst && "Defining instruction not actually an instruction");
+
+ if (!Q.IsCall)
+ return AA->getModRefInfo(DefMemoryInst, Loc) & MRI_Mod;
+
+ // If this is a call, mark it for caching
+ if (ImmutableCallSite(DefMemoryInst))
+ Q.VisitedCalls.push_back(MD);
+ ModRefInfo I = AA->getModRefInfo(DefMemoryInst, ImmutableCallSite(Q.Inst));
+ return I != MRI_NoModRef;
+}
+
+MemoryAccessPair MemorySSA::CachingWalker::UpwardsDFSWalk(
+ MemoryAccess *StartingAccess, const MemoryLocation &Loc,
+ UpwardsMemoryQuery &Q, bool FollowingBackedge) {
+ MemoryAccess *ModifyingAccess = nullptr;
+
+ auto DFI = df_begin(StartingAccess);
+ for (auto DFE = df_end(StartingAccess); DFI != DFE;) {
+ MemoryAccess *CurrAccess = *DFI;
+ if (MSSA->isLiveOnEntryDef(CurrAccess))
+ return {CurrAccess, Loc};
+ // If this is a MemoryDef, check whether it clobbers our current query. This
+ // needs to be done before consulting the cache, because the cache reports
+ // the clobber for CurrAccess. If CurrAccess is a clobber for this query,
+ // and we ask the cache for information first, then we might skip this
+ // clobber, which is bad.
+ if (auto *MD = dyn_cast<MemoryDef>(CurrAccess)) {
+ // If we hit the top, stop following this path.
+ // While we can do lookups, we can't sanely do inserts here unless we were
+ // to track everything we saw along the way, since we don't know where we
+ // will stop.
+ if (instructionClobbersQuery(MD, Q, Loc)) {
+ ModifyingAccess = CurrAccess;
+ break;
+ }
+ }
+ if (auto CacheResult = doCacheLookup(CurrAccess, Q, Loc))
+ return {CacheResult, Loc};
+
+ // We need to know whether it is a phi so we can track backedges.
+ // Otherwise, walk all upward defs.
+ if (!isa<MemoryPhi>(CurrAccess)) {
+ ++DFI;
+ continue;
+ }
+
+#ifndef NDEBUG
+ // The loop below visits the phi's children for us. Because phis are the
+ // only things with multiple edges, skipping the children should always lead
+ // us to the end of the loop.
+ //
+ // Use a copy of DFI because skipChildren would kill our search stack, which
+ // would make caching anything on the way back impossible.
+ auto DFICopy = DFI;
+ assert(DFICopy.skipChildren() == DFE &&
+ "Skipping phi's children doesn't end the DFS?");
+#endif
+
+ const MemoryAccessPair PHIPair(CurrAccess, Loc);
+
+ // Don't try to optimize this phi again if we've already tried to do so.
+ if (!Q.Visited.insert(PHIPair).second) {
+ ModifyingAccess = CurrAccess;
+ break;
+ }
+
+ std::size_t InitialVisitedCallSize = Q.VisitedCalls.size();
+
+ // Recurse on PHI nodes, since we need to change locations.
+ // TODO: Allow graphtraits on pairs, which would turn this whole function
+ // into a normal single depth first walk.
+ MemoryAccess *FirstDef = nullptr;
+ for (auto MPI = upward_defs_begin(PHIPair), MPE = upward_defs_end();
+ MPI != MPE; ++MPI) {
+ bool Backedge =
+ !FollowingBackedge &&
+ DT->dominates(CurrAccess->getBlock(), MPI.getPhiArgBlock());
+
+ MemoryAccessPair CurrentPair =
+ UpwardsDFSWalk(MPI->first, MPI->second, Q, Backedge);
+ // All the phi arguments should reach the same point if we can bypass
+ // this phi. The alternative is that they hit this phi node, which
+ // means we can skip this argument.
+ if (FirstDef && CurrentPair.first != PHIPair.first &&
+ CurrentPair.first != FirstDef) {
+ ModifyingAccess = CurrAccess;
+ break;
+ }
+
+ if (!FirstDef)
+ FirstDef = CurrentPair.first;
+ }
+
+ // If we exited the loop early, go with the result it gave us.
+ if (!ModifyingAccess) {
+ assert(FirstDef && "Found a Phi with no upward defs?");
+ ModifyingAccess = FirstDef;
+ } else {
+ // If we can't optimize this Phi, then we can't safely cache any of the
+ // calls we visited when trying to optimize it. Wipe them out now.
+ Q.VisitedCalls.resize(InitialVisitedCallSize);
+ }
+ break;
+ }
+
+ if (!ModifyingAccess)
+ return {MSSA->getLiveOnEntryDef(), Q.StartingLoc};
+
+ const BasicBlock *OriginalBlock = StartingAccess->getBlock();
+ assert(DFI.getPathLength() > 0 && "We dropped our path?");
+ unsigned N = DFI.getPathLength();
+ // If we found a clobbering def, the last element in the path will be our
+ // clobber, so we don't want to cache that to itself. OTOH, if we optimized a
+ // phi, we can add the last thing in the path to the cache, since that won't
+ // be the result.
+ if (DFI.getPath(N - 1) == ModifyingAccess)
+ --N;
+ for (; N > 1; --N) {
+ MemoryAccess *CacheAccess = DFI.getPath(N - 1);
+ BasicBlock *CurrBlock = CacheAccess->getBlock();
+ if (!FollowingBackedge)
+ doCacheInsert(CacheAccess, ModifyingAccess, Q, Loc);
+ if (DT->dominates(CurrBlock, OriginalBlock) &&
+ (CurrBlock != OriginalBlock || !FollowingBackedge ||
+ MSSA->locallyDominates(CacheAccess, StartingAccess)))
+ break;
+ }
+
+ // Cache everything else on the way back. The caller should cache
+ // StartingAccess for us.
+ for (; N > 1; --N) {
+ MemoryAccess *CacheAccess = DFI.getPath(N - 1);
+ doCacheInsert(CacheAccess, ModifyingAccess, Q, Loc);
+ }
+
+ return {ModifyingAccess, Loc};
+}
+
/// \brief Walk the use-def chains starting at \p MA and find
/// the MemoryAccess that actually clobbers Loc.
///
/// \returns our clobbering memory access
MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess(
MemoryAccess *StartingAccess, UpwardsMemoryQuery &Q) {
- MemoryAccess *New = Walker.findClobber(StartingAccess, Q);
-#ifdef EXPENSIVE_CHECKS
- MemoryAccess *NewNoCache =
- Walker.findClobber(StartingAccess, Q, /*UseWalkerCache=*/false);
- assert(NewNoCache == New && "Cache made us hand back a different result?");
-#endif
- if (AutoResetWalker)
- resetClobberWalker();
- return New;
+ return UpwardsDFSWalk(StartingAccess, Q.StartingLoc, Q, false).first;
}
MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess(
- MemoryAccess *StartingAccess, const MemoryLocation &Loc) {
+ MemoryAccess *StartingAccess, MemoryLocation &Loc) {
if (isa<MemoryPhi>(StartingAccess))
return StartingAccess;
@@ -2212,10 +1257,10 @@ MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess(
UpwardsMemoryQuery Q;
Q.OriginalAccess = StartingUseOrDef;
Q.StartingLoc = Loc;
- Q.Inst = I;
+ Q.Inst = StartingUseOrDef->getMemoryInst();
Q.IsCall = false;
- if (auto *CacheResult = Cache.lookup(StartingUseOrDef, Loc, Q.IsCall))
+ if (auto CacheResult = doCacheLookup(StartingUseOrDef, Q, Q.StartingLoc))
return CacheResult;
// Unlike the other function, do not walk to the def of a def, because we are
@@ -2225,6 +1270,9 @@ MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess(
: StartingUseOrDef;
MemoryAccess *Clobber = getClobberingMemoryAccess(DefiningAccess, Q);
+ // Only cache this if it wouldn't make Clobber point to itself.
+ if (Clobber != StartingAccess)
+ doCacheInsert(Q.OriginalAccess, Clobber, Q, Q.StartingLoc);
DEBUG(dbgs() << "Starting Memory SSA clobber for " << *I << " is ");
DEBUG(dbgs() << *StartingUseOrDef << "\n");
DEBUG(dbgs() << "Final Memory SSA clobber for " << *I << " is ");
@@ -2233,38 +1281,28 @@ MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess(
}
MemoryAccess *
-MemorySSA::CachingWalker::getClobberingMemoryAccess(MemoryAccess *MA) {
- auto *StartingAccess = dyn_cast<MemoryUseOrDef>(MA);
- // If this is a MemoryPhi, we can't do anything.
- if (!StartingAccess)
- return MA;
-
- // If this is an already optimized use or def, return the optimized result.
- // Note: Currently, we do not store the optimized def result because we'd need
- // a separate field, since we can't use it as the defining access.
- if (MemoryUse *MU = dyn_cast<MemoryUse>(StartingAccess))
- if (MU->isOptimized())
- return MU->getDefiningAccess();
-
- const Instruction *I = StartingAccess->getMemoryInst();
- UpwardsMemoryQuery Q(I, StartingAccess);
+MemorySSA::CachingWalker::getClobberingMemoryAccess(const Instruction *I) {
+ // There should be no way to lookup an instruction and get a phi as the
+ // access, since we only map BB's to PHI's. So, this must be a use or def.
+ auto *StartingAccess = cast<MemoryUseOrDef>(MSSA->getMemoryAccess(I));
+
+ bool IsCall = bool(ImmutableCallSite(I));
+
// We can't sanely do anything with a fences, they conservatively
// clobber all memory, and have no locations to get pointers from to
// try to disambiguate.
- if (!Q.IsCall && I->isFenceLike())
+ if (!IsCall && I->isFenceLike())
return StartingAccess;
- if (auto *CacheResult = Cache.lookup(StartingAccess, Q.StartingLoc, Q.IsCall))
+ UpwardsMemoryQuery Q;
+ Q.OriginalAccess = StartingAccess;
+ Q.IsCall = IsCall;
+ if (!Q.IsCall)
+ Q.StartingLoc = MemoryLocation::get(I);
+ Q.Inst = I;
+ if (auto CacheResult = doCacheLookup(StartingAccess, Q, Q.StartingLoc))
return CacheResult;
- if (isUseTriviallyOptimizableToLiveOnEntry(*MSSA->AA, I)) {
- MemoryAccess *LiveOnEntry = MSSA->getLiveOnEntryDef();
- Cache.insert(StartingAccess, LiveOnEntry, Q.StartingLoc, Q.IsCall);
- if (MemoryUse *MU = dyn_cast<MemoryUse>(StartingAccess))
- MU->setDefiningAccess(LiveOnEntry, true);
- return LiveOnEntry;
- }
-
// Start with the thing we already think clobbers this location
MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess();
@@ -2274,32 +1312,50 @@ MemorySSA::CachingWalker::getClobberingMemoryAccess(MemoryAccess *MA) {
return DefiningAccess;
MemoryAccess *Result = getClobberingMemoryAccess(DefiningAccess, Q);
+ // DFS won't cache a result for DefiningAccess. So, if DefiningAccess isn't
+ // our clobber, be sure that it gets a cache entry, too.
+ if (Result != DefiningAccess)
+ doCacheInsert(DefiningAccess, Result, Q, Q.StartingLoc);
+ doCacheInsert(Q.OriginalAccess, Result, Q, Q.StartingLoc);
+ // TODO: When this implementation is more mature, we may want to figure out
+ // what this additional caching buys us. It's most likely A Good Thing.
+ if (Q.IsCall)
+ for (const MemoryAccess *MA : Q.VisitedCalls)
+ if (MA != Result)
+ doCacheInsert(MA, Result, Q, Q.StartingLoc);
+
DEBUG(dbgs() << "Starting Memory SSA clobber for " << *I << " is ");
DEBUG(dbgs() << *DefiningAccess << "\n");
DEBUG(dbgs() << "Final Memory SSA clobber for " << *I << " is ");
DEBUG(dbgs() << *Result << "\n");
- if (MemoryUse *MU = dyn_cast<MemoryUse>(StartingAccess))
- MU->setDefiningAccess(Result, true);
return Result;
}
// Verify that MA doesn't exist in any of the caches.
void MemorySSA::CachingWalker::verifyRemoved(MemoryAccess *MA) {
- assert(!Cache.contains(MA) && "Found removed MemoryAccess in cache.");
+#ifndef NDEBUG
+ for (auto &P : CachedUpwardsClobberingAccess)
+ assert(P.first.first != MA && P.second != MA &&
+ "Found removed MemoryAccess in cache.");
+ for (auto &P : CachedUpwardsClobberingCall)
+ assert(P.first != MA && P.second != MA &&
+ "Found removed MemoryAccess in cache.");
+#endif // !NDEBUG
}
MemoryAccess *
-DoNothingMemorySSAWalker::getClobberingMemoryAccess(MemoryAccess *MA) {
+DoNothingMemorySSAWalker::getClobberingMemoryAccess(const Instruction *I) {
+ MemoryAccess *MA = MSSA->getMemoryAccess(I);
if (auto *Use = dyn_cast<MemoryUseOrDef>(MA))
return Use->getDefiningAccess();
return MA;
}
MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
- MemoryAccess *StartingAccess, const MemoryLocation &) {
+ MemoryAccess *StartingAccess, MemoryLocation &) {
if (auto *Use = dyn_cast<MemoryUseOrDef>(StartingAccess))
return Use->getDefiningAccess();
return StartingAccess;
}
-} // namespace llvm
+}
diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDABuiltin.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCUDABuiltin.cpp
index 44dd003757a..ea3b888635c 100644
--- a/gnu/llvm/tools/clang/lib/CodeGen/CGCUDABuiltin.cpp
+++ b/gnu/llvm/tools/clang/lib/CodeGen/CGCUDABuiltin.cpp
@@ -99,12 +99,6 @@ CodeGenFunction::EmitCUDADevicePrintfCallExpr(const CallExpr *E,
llvm::SmallVector<llvm::Type *, 8> ArgTypes;
for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I)
ArgTypes.push_back(Args[I].RV.getScalarVal()->getType());
-
- // Using llvm::StructType is correct only because printf doesn't accept
- // aggregates. If we had to handle aggregates here, we'd have to manually
- // compute the offsets within the alloca -- we wouldn't be able to assume
- // that the alignment of the llvm type was the same as the alignment of the
- // clang type.
llvm::Type *AllocaTy = llvm::StructType::create(ArgTypes, "printf_args");
llvm::Value *Alloca = CreateTempAlloca(AllocaTy);
diff --git a/gnu/llvm/tools/lld/COFF/Librarian.cpp b/gnu/llvm/tools/lld/COFF/Librarian.cpp
index 4c597fad734..25fb4a87b3e 100644
--- a/gnu/llvm/tools/lld/COFF/Librarian.cpp
+++ b/gnu/llvm/tools/lld/COFF/Librarian.cpp
@@ -54,7 +54,7 @@ static uint16_t getImgRelRelocation() {
}
}
-template <class T> static void append(std::vector<uint8_t> &B, const T &Data) {
+template <class T> void append(std::vector<uint8_t> &B, const T &Data) {
size_t S = B.size();
B.resize(S + sizeof(T));
memcpy(&B[S], &Data, sizeof(T));
@@ -352,16 +352,15 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
static const uint32_t NumberOfSections = 2;
static const uint32_t NumberOfSymbols = 1;
- uint32_t VASize = is32bit() ? 4 : 8;
// COFF Header
coff_file_header Header{
u16(Config->Machine), u16(NumberOfSections), u32(0),
u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
// .idata$5
- VASize +
+ sizeof(export_address_table_entry) +
// .idata$4
- VASize),
+ sizeof(export_address_table_entry)),
u32(NumberOfSymbols), u16(0),
u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
};
@@ -372,40 +371,36 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
u32(0),
u32(0),
- u32(VASize),
+ u32(sizeof(export_address_table_entry)),
u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
u32(0),
u32(0),
u16(0),
u16(0),
- u32((is32bit() ? IMAGE_SCN_ALIGN_4BYTES : IMAGE_SCN_ALIGN_8BYTES) |
- IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
- IMAGE_SCN_MEM_WRITE)},
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
u32(0),
u32(0),
- u32(VASize),
+ u32(sizeof(export_address_table_entry)),
u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
- VASize),
+ sizeof(export_address_table_entry)),
u32(0),
u32(0),
u16(0),
u16(0),
- u32((is32bit() ? IMAGE_SCN_ALIGN_4BYTES : IMAGE_SCN_ALIGN_8BYTES) |
- IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
- IMAGE_SCN_MEM_WRITE)},
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
};
append(Buffer, SectionTable);
- // .idata$5, ILT
- append(Buffer, u32(0));
- if (!is32bit())
- append(Buffer, u32(0));
+ // .idata$5
+ static const export_address_table_entry ILT{u32(0)};
+ append(Buffer, ILT);
- // .idata$4, IAT
- append(Buffer, u32(0));
- if (!is32bit())
- append(Buffer, u32(0));
+ // .idata$4
+ static const export_address_table_entry IAT{u32(0)};
+ append(Buffer, IAT);
// Symbol Table
coff_symbol16 SymbolTable[NumberOfSymbols] = {
@@ -463,7 +458,7 @@ void lld::coff::writeImportLibrary() {
std::vector<NewArchiveMember> Members;
std::string Path = getImplibPath();
- std::string DLLName = sys::path::filename(Config->OutputFile);
+ std::string DLLName = llvm::sys::path::filename(Config->OutputFile);
ObjectFactory OF(DLLName);
std::vector<uint8_t> ImportDescriptor;
diff --git a/gnu/llvm/tools/lld/COFF/ModuleDef.cpp b/gnu/llvm/tools/lld/COFF/ModuleDef.cpp
index a273b6f535d..5e393f45d18 100644
--- a/gnu/llvm/tools/lld/COFF/ModuleDef.cpp
+++ b/gnu/llvm/tools/lld/COFF/ModuleDef.cpp
@@ -18,7 +18,6 @@
#include "Config.h"
#include "Error.h"
-#include "Memory.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/StringSaver.h"
@@ -114,7 +113,7 @@ private:
class Parser {
public:
- explicit Parser(StringRef S) : Lex(S) {}
+ explicit Parser(StringRef S, StringSaver *A) : Lex(S), Alloc(A) {}
void parse() {
do {
@@ -198,9 +197,9 @@ private:
if (Config->Machine == I386) {
if (!isDecorated(E.Name))
- E.Name = Saver.save("_" + E.Name);
+ E.Name = Alloc->save("_" + E.Name);
if (!E.ExtName.empty() && !isDecorated(E.ExtName))
- E.ExtName = Saver.save("_" + E.ExtName);
+ E.ExtName = Alloc->save("_" + E.ExtName);
}
for (;;) {
@@ -279,11 +278,14 @@ private:
Lexer Lex;
Token Tok;
std::vector<Token> Stack;
+ StringSaver *Alloc;
};
} // anonymous namespace
-void parseModuleDefs(MemoryBufferRef MB) { Parser(MB.getBuffer()).parse(); }
+void parseModuleDefs(MemoryBufferRef MB, StringSaver *Alloc) {
+ Parser(MB.getBuffer(), Alloc).parse();
+}
} // namespace coff
} // namespace lld
diff --git a/gnu/llvm/tools/lld/include/lld/Core/Parallel.h b/gnu/llvm/tools/lld/include/lld/Core/Parallel.h
index f241453a4d3..2dde97d9e3f 100644
--- a/gnu/llvm/tools/lld/include/lld/Core/Parallel.h
+++ b/gnu/llvm/tools/lld/include/lld/Core/Parallel.h
@@ -121,7 +121,7 @@ public:
// Spawn all but one of the threads in another thread as spawning threads
// can take a while.
std::thread([&, threadCount] {
- for (size_t i = 1; i < threadCount; ++i) {
+ for (std::size_t i = 1; i < threadCount; ++i) {
std::thread([=] {
work();
}).detach();
@@ -270,65 +270,26 @@ template <class T> void parallel_sort(T *start, T *end) {
}
#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
-template <class IterTy, class FuncTy>
-void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
- std::for_each(Begin, End, Fn);
-}
-
-template <class IndexTy, class FuncTy>
-void parallel_for(IndexTy Begin, IndexTy End, FuncTy Fn) {
- for (IndexTy I = Begin; I != End; ++I)
- Fn(I);
+template <class Iterator, class Func>
+void parallel_for_each(Iterator begin, Iterator end, Func func) {
+ std::for_each(begin, end, func);
}
#elif defined(_MSC_VER)
// Use ppl parallel_for_each on Windows.
-template <class IterTy, class FuncTy>
-void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
- concurrency::parallel_for_each(Begin, End, Fn);
-}
-
-template <class IndexTy, class FuncTy>
-void parallel_for(IndexTy Begin, IndexTy End, FuncTy Fn) {
- concurrency::parallel_for(Begin, End, Fn);
+template <class Iterator, class Func>
+void parallel_for_each(Iterator begin, Iterator end, Func func) {
+ concurrency::parallel_for_each(begin, end, func);
}
#else
-template <class IterTy, class FuncTy>
-void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
- // TaskGroup has a relatively high overhead, so we want to reduce
- // the number of spawn() calls. We'll create up to 1024 tasks here.
- // (Note that 1024 is an arbitrary number. This code probably needs
- // improving to take the number of available cores into account.)
- ptrdiff_t TaskSize = std::distance(Begin, End) / 1024;
- if (TaskSize == 0)
- TaskSize = 1;
-
- TaskGroup Tg;
- while (TaskSize <= std::distance(Begin, End)) {
- Tg.spawn([=, &Fn] { std::for_each(Begin, Begin + TaskSize, Fn); });
- Begin += TaskSize;
- }
- Tg.spawn([=, &Fn] { std::for_each(Begin, End, Fn); });
-}
-
-template <class IndexTy, class FuncTy>
-void parallel_for(IndexTy Begin, IndexTy End, FuncTy Fn) {
- ptrdiff_t TaskSize = (End - Begin) / 1024;
- if (TaskSize == 0)
- TaskSize = 1;
-
- TaskGroup Tg;
- IndexTy I = Begin;
- for (; I < End; I += TaskSize) {
- Tg.spawn([=, &Fn] {
- for (IndexTy J = I, E = I + TaskSize; J != E; ++J)
- Fn(J);
- });
- Begin += TaskSize;
+template <class Iterator, class Func>
+void parallel_for_each(Iterator begin, Iterator end, Func func) {
+ TaskGroup tg;
+ ptrdiff_t taskSize = 1024;
+ while (taskSize <= std::distance(begin, end)) {
+ tg.spawn([=, &func] { std::for_each(begin, begin + taskSize, func); });
+ begin += taskSize;
}
- Tg.spawn([=, &Fn] {
- for (IndexTy J = I; J < End; ++J)
- Fn(J);
- });
+ std::for_each(begin, end, func);
}
#endif
} // end namespace lld
diff --git a/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
index 629ba40b113..6d94295d126 100644
--- a/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
+++ b/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
@@ -10,22 +10,14 @@
#include "LLVMOutputStyle.h"
#include "llvm-pdbdump.h"
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
-#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/EnumTables.h"
-#include "llvm/DebugInfo/PDB/Raw/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
@@ -39,57 +31,15 @@
using namespace llvm;
using namespace llvm::codeview;
-using namespace llvm::msf;
using namespace llvm::pdb;
-namespace {
-struct PageStats {
- explicit PageStats(const BitVector &FreePages)
- : Upm(FreePages), ActualUsedPages(FreePages.size()),
- MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) {
- const_cast<BitVector &>(Upm).flip();
- // To calculate orphaned pages, we start with the set of pages that the
- // MSF thinks are used. Each time we find one that actually *is* used,
- // we unset it. Whichever bits remain set at the end are orphaned.
- OrphanedPages = Upm;
- }
-
- // The inverse of the MSF File's copy of the Fpm. The basis for which we
- // determine the allocation status of each page.
- const BitVector Upm;
-
- // Pages which are marked as used in the FPM and are used at least once.
- BitVector ActualUsedPages;
-
- // Pages which are marked as used in the FPM but are used more than once.
- BitVector MultiUsePages;
-
- // Pages which are marked as used in the FPM but are not used at all.
- BitVector OrphanedPages;
-
- // Pages which are marked free in the FPM but are used.
- BitVector UseAfterFreePages;
-};
-}
-
-static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) {
- if (Stats.Upm.test(UsedIndex)) {
- if (Stats.ActualUsedPages.test(UsedIndex))
- Stats.MultiUsePages.set(UsedIndex);
- Stats.ActualUsedPages.set(UsedIndex);
- Stats.OrphanedPages.reset(UsedIndex);
- } else {
- // The MSF doesn't think this page is used, but it is.
- Stats.UseAfterFreePages.set(UsedIndex);
- }
-}
-
static void printSectionOffset(llvm::raw_ostream &OS,
const SectionOffset &Off) {
OS << Off.Off << ", " << Off.Isect;
}
-LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {}
+LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
+ : File(File), P(outs()), TD(&P, false) {}
Error LLVMOutputStyle::dump() {
if (auto EC = dumpFileHeaders())
@@ -98,19 +48,16 @@ Error LLVMOutputStyle::dump() {
if (auto EC = dumpStreamSummary())
return EC;
- if (auto EC = dumpFreePageMap())
- return EC;
-
if (auto EC = dumpStreamBlocks())
return EC;
- if (auto EC = dumpBlockRanges())
+ if (auto EC = dumpStreamData())
return EC;
- if (auto EC = dumpStreamBytes())
+ if (auto EC = dumpInfoStream())
return EC;
- if (auto EC = dumpInfoStream())
+ if (auto EC = dumpNamedStream())
return EC;
if (auto EC = dumpTpiStream(StreamTPI))
@@ -128,9 +75,6 @@ Error LLVMOutputStyle::dump() {
if (auto EC = dumpSectionMap())
return EC;
- if (auto EC = dumpGlobalsStream())
- return EC;
-
if (auto EC = dumpPublicsStream())
return EC;
@@ -166,9 +110,9 @@ Error LLVMOutputStyle::dumpFileHeaders() {
return Error::success();
}
-void LLVMOutputStyle::discoverStreamPurposes() {
- if (!StreamPurposes.empty())
- return;
+Error LLVMOutputStyle::dumpStreamSummary() {
+ if (!opts::raw::DumpStreamSummary)
+ return Error::success();
// It's OK if we fail to load some of these streams, we still attempt to print
// what we can.
@@ -177,6 +121,7 @@ void LLVMOutputStyle::discoverStreamPurposes() {
auto Ipi = File.getPDBIpiStream();
auto Info = File.getPDBInfoStream();
+ ListScope L(P, "Streams");
uint32_t StreamCount = File.getNumStreams();
std::unordered_map<uint16_t, const ModuleInfoEx *> ModStreams;
std::unordered_map<uint16_t, std::string> NamedStreams;
@@ -193,8 +138,9 @@ void LLVMOutputStyle::discoverStreamPurposes() {
}
}
- StreamPurposes.resize(StreamCount);
for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ std::string Label("Stream ");
+ Label += to_string(StreamIdx);
std::string Value;
if (StreamIdx == OldMSFDirectory)
Value = "Old MSF Directory";
@@ -265,7 +211,11 @@ void LLVMOutputStyle::discoverStreamPurposes() {
Value = "???";
}
}
- StreamPurposes[StreamIdx] = Value;
+ Value = "[" + Value + "]";
+ Value =
+ Value + " (" + to_string(File.getStreamByteSize(StreamIdx)) + " bytes)";
+
+ P.printString(Label, Value);
}
// Consume errors from missing streams.
@@ -277,105 +227,11 @@ void LLVMOutputStyle::discoverStreamPurposes() {
consumeError(Ipi.takeError());
if (!Info)
consumeError(Info.takeError());
-}
-
-Error LLVMOutputStyle::dumpStreamSummary() {
- if (!opts::raw::DumpStreamSummary)
- return Error::success();
-
- discoverStreamPurposes();
-
- uint32_t StreamCount = File.getNumStreams();
-
- ListScope L(P, "Streams");
- for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
- std::string Label("Stream ");
- Label += to_string(StreamIdx);
-
- std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
- Value += to_string(File.getStreamByteSize(StreamIdx));
- Value += " bytes)";
-
- P.printString(Label, Value);
- }
P.flush();
return Error::success();
}
-Error LLVMOutputStyle::dumpFreePageMap() {
- if (!opts::raw::DumpPageStats)
- return Error::success();
-
- // Start with used pages instead of free pages because
- // the number of free pages is far larger than used pages.
- BitVector FPM = File.getMsfLayout().FreePageMap;
-
- PageStats PS(FPM);
-
- recordKnownUsedPage(PS, 0); // MSF Super Block
-
- uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout());
- uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout());
- for (uint32_t I = 0; I < NumSections; ++I) {
- uint32_t Fpm0 = 1 + BlocksPerSection * I;
- // 2 Fpm blocks spaced at `getBlockSize()` block intervals
- recordKnownUsedPage(PS, Fpm0);
- recordKnownUsedPage(PS, Fpm0 + 1);
- }
-
- recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table
-
- for (auto DB : File.getDirectoryBlockArray())
- recordKnownUsedPage(PS, DB);
-
- // Record pages used by streams. Note that pages for stream 0
- // are considered being unused because that's what MSVC tools do.
- // Stream 0 doesn't contain actual data, so it makes some sense,
- // though it's a bit confusing to us.
- for (auto &SE : File.getStreamMap().drop_front(1))
- for (auto &S : SE)
- recordKnownUsedPage(PS, S);
-
- dumpBitVector("Msf Free Pages", FPM);
- dumpBitVector("Orphaned Pages", PS.OrphanedPages);
- dumpBitVector("Multiply Used Pages", PS.MultiUsePages);
- dumpBitVector("Use After Free Pages", PS.UseAfterFreePages);
- return Error::success();
-}
-
-void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
- std::vector<uint32_t> Vec;
- for (uint32_t I = 0, E = V.size(); I != E; ++I)
- if (V[I])
- Vec.push_back(I);
- P.printList(Name, Vec);
-}
-
-Error LLVMOutputStyle::dumpGlobalsStream() {
- if (!opts::raw::DumpGlobals)
- return Error::success();
- if (!File.hasPDBGlobalsStream()) {
- P.printString("Globals Stream not present");
- return Error::success();
- }
-
- auto Globals = File.getPDBGlobalsStream();
- if (!Globals)
- return Globals.takeError();
- DictScope D(P, "Globals Stream");
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex());
- P.printNumber("Number of buckets", Globals->getNumBuckets());
- P.printList("Hash Buckets", Globals->getHashBuckets());
-
- return Error::success();
-}
-
Error LLVMOutputStyle::dumpStreamBlocks() {
if (!opts::raw::DumpStreamBlocks)
return Error::success();
@@ -391,64 +247,29 @@ Error LLVMOutputStyle::dumpStreamBlocks() {
return Error::success();
}
-Error LLVMOutputStyle::dumpBlockRanges() {
- if (!opts::raw::DumpBlockRange.hasValue())
- return Error::success();
- auto &R = *opts::raw::DumpBlockRange;
- uint32_t Max = R.Max.getValueOr(R.Min);
-
- if (Max < R.Min)
- return make_error<StringError>(
- "Invalid block range specified. Max < Min",
- std::make_error_code(std::errc::bad_address));
- if (Max >= File.getBlockCount())
- return make_error<StringError>(
- "Invalid block range specified. Requested block out of bounds",
- std::make_error_code(std::errc::bad_address));
-
- DictScope D(P, "Block Data");
- for (uint32_t I = R.Min; I <= Max; ++I) {
- auto ExpectedData = File.getBlockData(I, File.getBlockSize());
- if (!ExpectedData)
- return ExpectedData.takeError();
- std::string Label;
- llvm::raw_string_ostream S(Label);
- S << "Block " << I;
- S.flush();
- P.printBinaryBlock(Label, *ExpectedData);
- }
-
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpStreamBytes() {
- if (opts::raw::DumpStreamData.empty())
+Error LLVMOutputStyle::dumpStreamData() {
+ uint32_t StreamCount = File.getNumStreams();
+ StringRef DumpStreamStr = opts::raw::DumpStreamDataIdx;
+ uint32_t DumpStreamNum;
+ if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum))
return Error::success();
- discoverStreamPurposes();
-
- DictScope D(P, "Stream Data");
- for (uint32_t SI : opts::raw::DumpStreamData) {
- if (SI >= File.getNumStreams())
- return make_error<RawError>(raw_error_code::no_stream);
-
- auto S = MappedBlockStream::createIndexedStream(File.getMsfLayout(),
- File.getMsfBuffer(), SI);
- if (!S)
- continue;
- DictScope DD(P, "Stream");
-
- P.printNumber("Index", SI);
- P.printString("Type", StreamPurposes[SI]);
- P.printNumber("Size", S->getLength());
- auto Blocks = File.getMsfLayout().StreamMap[SI];
- P.printList("Blocks", Blocks);
-
- StreamReader R(*S);
- ArrayRef<uint8_t> StreamData;
- if (auto EC = R.readBytes(StreamData, S->getLength()))
+ if (DumpStreamNum >= StreamCount)
+ return make_error<RawError>(raw_error_code::no_stream);
+
+ auto S = MappedBlockStream::createIndexedStream(DumpStreamNum, File);
+ if (!S)
+ return S.takeError();
+ codeview::StreamReader R(**S);
+ while (R.bytesRemaining() > 0) {
+ ArrayRef<uint8_t> Data;
+ uint32_t BytesToReadInBlock = std::min(
+ R.bytesRemaining(), static_cast<uint32_t>(File.getBlockSize()));
+ if (auto EC = R.readBytes(Data, BytesToReadInBlock))
return EC;
- P.printBinaryBlock("Data", StreamData);
+ P.printBinaryBlock(
+ "Data",
+ StringRef(reinterpret_cast<const char *>(Data.begin()), Data.size()));
}
return Error::success();
}
@@ -456,10 +277,6 @@ Error LLVMOutputStyle::dumpStreamBytes() {
Error LLVMOutputStyle::dumpInfoStream() {
if (!opts::raw::DumpHeaders)
return Error::success();
- if (!File.hasPDBInfoStream()) {
- P.printString("PDB Stream not present");
- return Error::success();
- }
auto IS = File.getPDBInfoStream();
if (!IS)
return IS.takeError();
@@ -472,6 +289,49 @@ Error LLVMOutputStyle::dumpInfoStream() {
return Error::success();
}
+Error LLVMOutputStyle::dumpNamedStream() {
+ if (opts::raw::DumpStreamDataName.empty())
+ return Error::success();
+
+ auto IS = File.getPDBInfoStream();
+ if (!IS)
+ return IS.takeError();
+
+ uint32_t NameStreamIndex =
+ IS->getNamedStreamIndex(opts::raw::DumpStreamDataName);
+ if (NameStreamIndex == 0 || NameStreamIndex >= File.getNumStreams())
+ return make_error<RawError>(raw_error_code::no_stream);
+
+ if (NameStreamIndex != 0) {
+ std::string Name("Stream '");
+ Name += opts::raw::DumpStreamDataName;
+ Name += "'";
+ DictScope D(P, Name);
+ P.printNumber("Index", NameStreamIndex);
+
+ auto NameStream =
+ MappedBlockStream::createIndexedStream(NameStreamIndex, File);
+ if (!NameStream)
+ return NameStream.takeError();
+ codeview::StreamReader Reader(**NameStream);
+
+ NameHashTable NameTable;
+ if (auto EC = NameTable.load(Reader))
+ return EC;
+
+ P.printHex("Signature", NameTable.getSignature());
+ P.printNumber("Version", NameTable.getHashVersion());
+ P.printNumber("Name Count", NameTable.getNameCount());
+ ListScope L(P, "Names");
+ for (uint32_t ID : NameTable.name_ids()) {
+ StringRef Str = NameTable.getStringForID(ID);
+ if (!Str.empty())
+ P.printString(to_string(ID), Str);
+ }
+ }
+ return Error::success();
+}
+
static void printTypeIndexOffset(raw_ostream &OS,
const TypeIndexOffset &TIOff) {
OS << "{" << TIOff.Type.getIndex() << ", " << TIOff.Offset << "}";
@@ -498,19 +358,11 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
StringRef Label;
StringRef VerLabel;
if (StreamIdx == StreamTPI) {
- if (!File.hasPDBTpiStream()) {
- P.printString("Type Info Stream (TPI) not present");
- return Error::success();
- }
DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
DumpRecords = opts::raw::DumpTpiRecords;
Label = "Type Info Stream (TPI)";
VerLabel = "TPI Version";
} else if (StreamIdx == StreamIPI) {
- if (!File.hasPDBIpiStream()) {
- P.printString("Type Info Stream (IPI) not present");
- return Error::success();
- }
DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
DumpRecords = opts::raw::DumpIpiRecords;
Label = "Type Info Stream (IPI)";
@@ -524,7 +376,6 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
if (!Tpi)
return Tpi.takeError();
- CVTypeDumper Dumper(TypeDB);
if (DumpRecords || DumpRecordBytes) {
DictScope D(P, Label);
@@ -538,13 +389,12 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
DictScope DD(P, "");
if (DumpRecords) {
- TypeDumpVisitor TDV(TypeDB, &P, false);
- if (auto EC = Dumper.dump(Type, TDV))
+ if (auto EC = TD.dump(Type))
return EC;
}
if (DumpRecordBytes)
- P.printBinaryBlock("Bytes", Type.content());
+ P.printBinaryBlock("Bytes", Type.Data);
}
dumpTpiHash(P, *Tpi);
if (HadError)
@@ -552,23 +402,19 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
"TPI stream contained corrupt record");
} else if (opts::raw::DumpModuleSyms) {
// Even if the user doesn't want to dump type records, we still need to
- // iterate them in order to build the type database. So when they want to
- // dump symbols but not types, don't stick a dumper on the end, just build
- // the type database.
- TypeDatabaseVisitor DBV(TypeDB);
- TypeDeserializer Deserializer;
- TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(DBV);
-
- CVTypeVisitor Visitor(Pipeline);
+ // iterate them in order to build the list of types so that we can print
+ // them when dumping module symbols. So when they want to dump symbols
+ // but not types, use a null output stream.
+ ScopedPrinter *OldP = TD.getPrinter();
+ TD.setPrinter(nullptr);
bool HadError = false;
- for (auto Type : Tpi->types(&HadError)) {
- if (auto EC = Visitor.visitTypeRecord(Type))
+ for (auto &Type : Tpi->types(&HadError)) {
+ if (auto EC = TD.dump(Type))
return EC;
}
+ TD.setPrinter(OldP);
dumpTpiHash(P, *Tpi);
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
@@ -583,10 +429,6 @@ Error LLVMOutputStyle::dumpDbiStream() {
opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
if (!opts::raw::DumpHeaders && !DumpModules)
return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
auto DS = File.getPDBDbiStream();
if (!DS)
@@ -642,28 +484,24 @@ Error LLVMOutputStyle::dumpDbiStream() {
(opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) {
auto ModStreamData = MappedBlockStream::createIndexedStream(
- File.getMsfLayout(), File.getMsfBuffer(),
- Modi.Info.getModuleStreamIndex());
-
- ModStream ModS(Modi.Info, std::move(ModStreamData));
+ Modi.Info.getModuleStreamIndex(), File);
+ if (!ModStreamData)
+ return ModStreamData.takeError();
+ ModStream ModS(Modi.Info, std::move(*ModStreamData));
if (auto EC = ModS.reload())
return EC;
if (ShouldDumpSymbols) {
ListScope SS(P, "Symbols");
- codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
+ codeview::CVSymbolDumper SD(P, TD, nullptr, false);
bool HadError = false;
- for (auto S : ModS.symbols(&HadError)) {
- DictScope LL(P, "");
- if (opts::raw::DumpModuleSyms) {
- if (auto EC = SD.dump(S)) {
- llvm::consumeError(std::move(EC));
- HadError = true;
- break;
- }
- }
+ for (const auto &S : ModS.symbols(&HadError)) {
+ DictScope DD(P, "");
+
+ if (opts::raw::DumpModuleSyms)
+ SD.dump(S);
if (opts::raw::DumpSymRecordBytes)
- P.printBinaryBlock("Bytes", S.content());
+ P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
return make_error<RawError>(
@@ -679,7 +517,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
public:
RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {}
Error visitUnknown(ModuleSubstreamKind Kind,
- ReadableStreamRef Stream) override {
+ StreamRef Stream) override {
DictScope DD(P, "Unknown");
ArrayRef<uint8_t> Data;
StreamReader R(Stream);
@@ -692,7 +530,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
return Error::success();
}
Error
- visitFileChecksums(ReadableStreamRef Data,
+ visitFileChecksums(StreamRef Data,
const FileChecksumArray &Checksums) override {
DictScope DD(P, "FileChecksums");
for (const auto &C : Checksums) {
@@ -708,8 +546,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
return Error::success();
}
- Error visitLines(ReadableStreamRef Data,
- const LineSubstreamHeader *Header,
+ Error visitLines(StreamRef Data, const LineSubstreamHeader *Header,
const LineInfoArray &Lines) override {
DictScope DD(P, "Lines");
for (const auto &L : Lines) {
@@ -773,10 +610,6 @@ Error LLVMOutputStyle::dumpDbiStream() {
Error LLVMOutputStyle::dumpSectionContribs() {
if (!opts::raw::DumpSectionContribs)
return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
auto Dbi = File.getPDBDbiStream();
if (!Dbi)
@@ -824,10 +657,6 @@ Error LLVMOutputStyle::dumpSectionContribs() {
Error LLVMOutputStyle::dumpSectionMap() {
if (!opts::raw::DumpSectionMap)
return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
auto Dbi = File.getPDBDbiStream();
if (!Dbi)
@@ -837,6 +666,7 @@ Error LLVMOutputStyle::dumpSectionMap() {
for (auto &M : Dbi->getSectionMap()) {
DictScope D(P, "Entry");
P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
+ P.printNumber("Flags", M.Flags);
P.printNumber("Ovl", M.Ovl);
P.printNumber("Group", M.Group);
P.printNumber("Frame", M.Frame);
@@ -852,15 +682,11 @@ Error LLVMOutputStyle::dumpSectionMap() {
Error LLVMOutputStyle::dumpPublicsStream() {
if (!opts::raw::DumpPublics)
return Error::success();
- if (!File.hasPDBPublicsStream()) {
- P.printString("Publics Stream not present");
- return Error::success();
- }
+ DictScope D(P, "Publics Stream");
auto Publics = File.getPDBPublicsStream();
if (!Publics)
return Publics.takeError();
- DictScope D(P, "Publics Stream");
auto Dbi = File.getPDBDbiStream();
if (!Dbi)
@@ -876,17 +702,14 @@ Error LLVMOutputStyle::dumpPublicsStream() {
P.printList("Section Offsets", Publics->getSectionOffsets(),
printSectionOffset);
ListScope L(P, "Symbols");
- codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
+ codeview::CVSymbolDumper SD(P, TD, nullptr, false);
bool HadError = false;
for (auto S : Publics->getSymbols(&HadError)) {
DictScope DD(P, "");
- if (auto EC = SD.dump(S)) {
- HadError = true;
- break;
- }
+ SD.dump(S);
if (opts::raw::DumpSymRecordBytes)
- P.printBinaryBlock("Bytes", S.content());
+ P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
return make_error<RawError>(
@@ -899,10 +722,6 @@ Error LLVMOutputStyle::dumpPublicsStream() {
Error LLVMOutputStyle::dumpSectionHeaders() {
if (!opts::raw::DumpSectionHeaders)
return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
auto Dbi = File.getPDBDbiStream();
if (!Dbi)
@@ -932,10 +751,6 @@ Error LLVMOutputStyle::dumpSectionHeaders() {
Error LLVMOutputStyle::dumpFpoStream() {
if (!opts::raw::DumpFpo)
return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
auto Dbi = File.getPDBDbiStream();
if (!Dbi)
diff --git a/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h b/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
index 816d591f08f..77935d10220 100644
--- a/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
+++ b/gnu/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
@@ -12,11 +12,10 @@
#include "OutputStyle.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/Support/ScopedPrinter.h"
namespace llvm {
-class BitVector;
namespace pdb {
class LLVMOutputStyle : public OutputStyle {
public:
@@ -25,16 +24,12 @@ public:
Error dump() override;
private:
- void discoverStreamPurposes();
-
Error dumpFileHeaders();
Error dumpStreamSummary();
- Error dumpFreePageMap();
- Error dumpBlockRanges();
- Error dumpGlobalsStream();
- Error dumpStreamBytes();
Error dumpStreamBlocks();
+ Error dumpStreamData();
Error dumpInfoStream();
+ Error dumpNamedStream();
Error dumpTpiStream(uint32_t StreamIdx);
Error dumpDbiStream();
Error dumpSectionContribs();
@@ -43,14 +38,11 @@ private:
Error dumpSectionHeaders();
Error dumpFpoStream();
- void dumpBitVector(StringRef Name, const BitVector &V);
-
void flush();
PDBFile &File;
ScopedPrinter P;
- codeview::TypeDatabase TypeDB;
- std::vector<std::string> StreamPurposes;
+ codeview::CVTypeDumper TD;
};
}
}
diff --git a/gnu/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/gnu/llvm/tools/llvm-pdbdump/PdbYaml.cpp
index 34e0611e146..e83f24e8774 100644
--- a/gnu/llvm/tools/llvm-pdbdump/PdbYaml.cpp
+++ b/gnu/llvm/tools/llvm-pdbdump/PdbYaml.cpp
@@ -9,38 +9,16 @@
#include "PdbYaml.h"
-#include "YamlSerializationContext.h"
-#include "YamlSymbolDumper.h"
-#include "YamlTypeDumper.h"
-
-#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
-#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
-#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
-#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
-#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiHashing.h"
using namespace llvm;
+using namespace llvm::yaml;
using namespace llvm::pdb;
using namespace llvm::pdb::yaml;
-using namespace llvm::yaml;
-
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSymbolRecord)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord)
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
namespace llvm {
namespace yaml {
-
template <> struct ScalarTraits<llvm::pdb::PDB_UniqueId> {
static void output(const llvm::pdb::PDB_UniqueId &S, void *,
llvm::raw_ostream &OS) {
@@ -57,7 +35,7 @@ template <> struct ScalarTraits<llvm::pdb::PDB_UniqueId> {
Scalar[24] != '-')
return "GUID sections are not properly delineated with dashes";
- uint8_t *OutBuffer = S.Guid;
+ char *OutBuffer = S.Guid;
for (auto Iter = Scalar.begin(); Iter != Scalar.end();) {
if (*Iter == '-' || *Iter == '{' || *Iter == '}') {
++Iter;
@@ -123,16 +101,6 @@ template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_ImplVer> {
io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140);
}
};
-
-template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_TpiVer> {
- static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) {
- io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40);
- io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41);
- io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50);
- io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70);
- io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80);
- }
-};
}
}
@@ -142,11 +110,9 @@ void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
IO.mapOptional("StreamMap", Obj.StreamMap);
IO.mapOptional("PdbStream", Obj.PdbStream);
IO.mapOptional("DbiStream", Obj.DbiStream);
- IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Obj.Allocator);
- IO.mapOptionalWithContext("IpiStream", Obj.IpiStream, Obj.Allocator);
}
-void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
+void MappingTraits<MsfHeaders>::mapping(IO &IO, MsfHeaders &Obj) {
IO.mapRequired("SuperBlock", Obj.SuperBlock);
IO.mapRequired("NumDirectoryBlocks", Obj.NumDirectoryBlocks);
IO.mapRequired("DirectoryBlocks", Obj.DirectoryBlocks);
@@ -187,21 +153,6 @@ void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
IO.mapRequired("PdbDllRbld", Obj.PdbDllRbld);
IO.mapRequired("Flags", Obj.Flags);
IO.mapRequired("MachineType", Obj.MachineType);
- IO.mapOptional("Modules", Obj.ModInfos);
-}
-
-void MappingContextTraits<PdbTpiStream, BumpPtrAllocator>::mapping(
- IO &IO, pdb::yaml::PdbTpiStream &Obj, BumpPtrAllocator &Allocator) {
- // Create a single serialization context that will be passed through the
- // entire process of serializing / deserializing a Tpi Stream. This is
- // especially important when we are going from Pdb -> Yaml because we need
- // to maintain state in a TypeTableBuilder across mappings, and at the end of
- // the entire process, we need to have one TypeTableBuilder that has every
- // record.
- pdb::yaml::SerializationContext Context(IO, Allocator);
-
- IO.mapRequired("Version", Obj.Version);
- IO.mapRequired("Records", Obj.Records, Context);
}
void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
@@ -209,62 +160,3 @@ void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
IO.mapRequired("Name", Obj.StreamName);
IO.mapRequired("StreamNum", Obj.StreamNumber);
}
-
-void MappingTraits<PdbSymbolRecord>::mapping(IO &IO, PdbSymbolRecord &Obj) {
- codeview::SymbolVisitorCallbackPipeline Pipeline;
- codeview::SymbolDeserializer Deserializer(nullptr);
- codeview::yaml::YamlSymbolDumper Dumper(IO);
-
- if (IO.outputting()) {
- // For PDB to Yaml, deserialize into a high level record type, then dump it.
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Dumper);
- } else {
- return;
- }
-
- codeview::CVSymbolVisitor Visitor(Pipeline);
- consumeError(Visitor.visitSymbolRecord(Obj.Record));
-}
-
-void MappingTraits<PdbModiStream>::mapping(IO &IO, PdbModiStream &Obj) {
- IO.mapRequired("Signature", Obj.Signature);
- IO.mapRequired("Records", Obj.Symbols);
-}
-
-void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
- IO.mapRequired("Module", Obj.Mod);
- IO.mapRequired("ObjFile", Obj.Obj);
- IO.mapOptional("SourceFiles", Obj.SourceFiles);
- IO.mapOptional("Modi", Obj.Modi);
-}
-
-void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
- mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
- pdb::yaml::SerializationContext &Context) {
- codeview::TypeVisitorCallbackPipeline Pipeline;
- codeview::TypeDeserializer Deserializer;
- codeview::TypeSerializer Serializer(Context.Allocator);
- pdb::TpiHashUpdater Hasher;
-
- if (IO.outputting()) {
- // For PDB to Yaml, deserialize into a high level record type, then dump it.
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Context.Dumper);
- } else {
- // For Yaml to PDB, extract from the high level record type, then write it
- // to bytes.
-
- // This might be interpreted as a hack, but serializing FieldList
- // sub-records requires having access to the same serializer being used by
- // the FieldList itself.
- Context.ActiveSerializer = &Serializer;
- Pipeline.addCallbackToPipeline(Context.Dumper);
- Pipeline.addCallbackToPipeline(Serializer);
- Pipeline.addCallbackToPipeline(Hasher);
- }
-
- codeview::CVTypeVisitor Visitor(Pipeline);
- consumeError(Visitor.visitTypeRecord(Obj.Record));
- Context.ActiveSerializer = nullptr;
-}
diff --git a/gnu/llvm/tools/llvm-pdbdump/PdbYaml.h b/gnu/llvm/tools/llvm-pdbdump/PdbYaml.h
index 398186f16d7..a7389af2205 100644
--- a/gnu/llvm/tools/llvm-pdbdump/PdbYaml.h
+++ b/gnu/llvm/tools/llvm-pdbdump/PdbYaml.h
@@ -13,10 +13,8 @@
#include "OutputStyle.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/DebugInfo/PDB/Raw/MsfCommon.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/Support/Endian.h"
@@ -28,9 +26,7 @@ namespace llvm {
namespace pdb {
namespace yaml {
-struct SerializationContext;
-
-struct MSFHeaders {
+struct MsfHeaders {
msf::SuperBlock SuperBlock;
uint32_t NumDirectoryBlocks;
std::vector<uint32_t> DirectoryBlocks;
@@ -55,22 +51,6 @@ struct PdbInfoStream {
std::vector<NamedStreamMapping> NamedStreams;
};
-struct PdbSymbolRecord {
- codeview::CVSymbol Record;
-};
-
-struct PdbModiStream {
- uint32_t Signature;
- std::vector<PdbSymbolRecord> Symbols;
-};
-
-struct PdbDbiModuleInfo {
- StringRef Obj;
- StringRef Mod;
- std::vector<StringRef> SourceFiles;
- Optional<PdbModiStream> Modi;
-};
-
struct PdbDbiStream {
PdbRaw_DbiVer VerHeader;
uint32_t Age;
@@ -79,35 +59,14 @@ struct PdbDbiStream {
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
-
- std::vector<PdbDbiModuleInfo> ModInfos;
-};
-
-struct PdbTpiRecord {
- codeview::CVType Record;
-};
-
-struct PdbTpiFieldListRecord {
- codeview::CVMemberRecord Record;
-};
-
-struct PdbTpiStream {
- PdbRaw_TpiVer Version;
- std::vector<PdbTpiRecord> Records;
};
struct PdbObject {
- explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
-
- Optional<MSFHeaders> Headers;
+ Optional<MsfHeaders> Headers;
Optional<std::vector<uint32_t>> StreamSizes;
Optional<std::vector<StreamBlockList>> StreamMap;
Optional<PdbInfoStream> PdbStream;
Optional<PdbDbiStream> DbiStream;
- Optional<PdbTpiStream> TpiStream;
- Optional<PdbTpiStream> IpiStream;
-
- BumpPtrAllocator &Allocator;
};
}
}
@@ -120,12 +79,12 @@ template <> struct MappingTraits<pdb::yaml::PdbObject> {
static void mapping(IO &IO, pdb::yaml::PdbObject &Obj);
};
-template <> struct MappingTraits<pdb::yaml::MSFHeaders> {
- static void mapping(IO &IO, pdb::yaml::MSFHeaders &Obj);
+template <> struct MappingTraits<pdb::yaml::MsfHeaders> {
+ static void mapping(IO &IO, pdb::yaml::MsfHeaders &Obj);
};
-template <> struct MappingTraits<msf::SuperBlock> {
- static void mapping(IO &IO, msf::SuperBlock &SB);
+template <> struct MappingTraits<pdb::msf::SuperBlock> {
+ static void mapping(IO &IO, pdb::msf::SuperBlock &SB);
};
template <> struct MappingTraits<pdb::yaml::StreamBlockList> {
@@ -140,35 +99,14 @@ template <> struct MappingTraits<pdb::yaml::PdbDbiStream> {
static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj);
};
-template <>
-struct MappingContextTraits<pdb::yaml::PdbTpiStream, llvm::BumpPtrAllocator> {
- static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj,
- llvm::BumpPtrAllocator &Allocator);
-};
-
template <> struct MappingTraits<pdb::yaml::NamedStreamMapping> {
static void mapping(IO &IO, pdb::yaml::NamedStreamMapping &Obj);
};
-
-template <> struct MappingTraits<pdb::yaml::PdbSymbolRecord> {
- static void mapping(IO &IO, pdb::yaml::PdbSymbolRecord &Obj);
-};
-
-template <> struct MappingTraits<pdb::yaml::PdbModiStream> {
- static void mapping(IO &IO, pdb::yaml::PdbModiStream &Obj);
-};
-
-template <> struct MappingTraits<pdb::yaml::PdbDbiModuleInfo> {
- static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj);
-};
-
-template <>
-struct MappingContextTraits<pdb::yaml::PdbTpiRecord,
- pdb::yaml::SerializationContext> {
- static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
- pdb::yaml::SerializationContext &Context);
-};
}
}
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
+
#endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
diff --git a/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
index 3f2733d701a..a8b6202d5d1 100644
--- a/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
+++ b/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
@@ -12,29 +12,19 @@
#include "PdbYaml.h"
#include "llvm-pdbdump.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
-#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
using namespace llvm;
using namespace llvm::pdb;
-YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
- : File(File), Out(outs()), Obj(File.getAllocator()) {}
+YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) : File(File), Out(outs()) {}
Error YAMLOutputStyle::dump() {
if (opts::pdb2yaml::StreamDirectory)
opts::pdb2yaml::StreamMetadata = true;
- if (opts::pdb2yaml::DbiModuleSyms)
- opts::pdb2yaml::DbiModuleInfo = true;
- if (opts::pdb2yaml::DbiModuleSourceFileInfo)
- opts::pdb2yaml::DbiModuleInfo = true;
- if (opts::pdb2yaml::DbiModuleInfo)
- opts::pdb2yaml::DbiStream = true;
if (auto EC = dumpFileHeaders())
return EC;
@@ -51,12 +41,6 @@ Error YAMLOutputStyle::dump() {
if (auto EC = dumpDbiStream())
return EC;
- if (auto EC = dumpTpiStream())
- return EC;
-
- if (auto EC = dumpIpiStream())
- return EC;
-
flush();
return Error::success();
}
@@ -65,7 +49,7 @@ Error YAMLOutputStyle::dumpFileHeaders() {
if (opts::pdb2yaml::NoFileHeaders)
return Error::success();
- yaml::MSFHeaders Headers;
+ yaml::MsfHeaders Headers;
Obj.Headers.emplace();
Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();
Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();
@@ -149,79 +133,6 @@ Error YAMLOutputStyle::dumpDbiStream() {
Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
Obj.DbiStream->VerHeader = DS.getDbiVersion();
- if (opts::pdb2yaml::DbiModuleInfo) {
- for (const auto &MI : DS.modules()) {
- yaml::PdbDbiModuleInfo DMI;
- DMI.Mod = MI.Info.getModuleName();
- DMI.Obj = MI.Info.getObjFileName();
- if (opts::pdb2yaml::DbiModuleSourceFileInfo)
- DMI.SourceFiles = MI.SourceFiles;
-
- if (opts::pdb2yaml::DbiModuleSyms &&
- MI.Info.getModuleStreamIndex() != kInvalidStreamIndex) {
- DMI.Modi.emplace();
- auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
- File.getMsfLayout(), File.getMsfBuffer(),
- MI.Info.getModuleStreamIndex());
-
- pdb::ModStream ModS(MI.Info, std::move(ModStreamData));
- if (auto EC = ModS.reload())
- return EC;
-
- DMI.Modi->Signature = ModS.signature();
- bool HadError = false;
- for (auto &Sym : ModS.symbols(&HadError)) {
- pdb::yaml::PdbSymbolRecord Record{Sym};
- DMI.Modi->Symbols.push_back(Record);
- }
- }
- Obj.DbiStream->ModInfos.push_back(DMI);
- }
- }
- return Error::success();
-}
-
-Error YAMLOutputStyle::dumpTpiStream() {
- if (!opts::pdb2yaml::TpiStream)
- return Error::success();
-
- auto TpiS = File.getPDBTpiStream();
- if (!TpiS)
- return TpiS.takeError();
-
- auto &TS = TpiS.get();
- Obj.TpiStream.emplace();
- Obj.TpiStream->Version = TS.getTpiVersion();
- for (auto &Record : TS.types(nullptr)) {
- yaml::PdbTpiRecord R;
- // It's not necessary to set R.RecordData here. That only exists as a
- // way to have the `PdbTpiRecord` structure own the memory that `R.Record`
- // references. In the case of reading an existing PDB though, that memory
- // is owned by the backing stream.
- R.Record = Record;
- Obj.TpiStream->Records.push_back(R);
- }
-
- return Error::success();
-}
-
-Error YAMLOutputStyle::dumpIpiStream() {
- if (!opts::pdb2yaml::IpiStream)
- return Error::success();
-
- auto IpiS = File.getPDBIpiStream();
- if (!IpiS)
- return IpiS.takeError();
-
- auto &IS = IpiS.get();
- Obj.IpiStream.emplace();
- Obj.IpiStream->Version = IS.getTpiVersion();
- for (auto &Record : IS.types(nullptr)) {
- yaml::PdbTpiRecord R;
- R.Record = Record;
- Obj.IpiStream->Records.push_back(R);
- }
-
return Error::success();
}
diff --git a/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h b/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
index 3cd603a95b6..d36dfec5f25 100644
--- a/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
+++ b/gnu/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h
@@ -13,7 +13,7 @@
#include "OutputStyle.h"
#include "PdbYaml.h"
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/YAMLTraits.h"
@@ -31,8 +31,6 @@ private:
Error dumpStreamDirectory();
Error dumpPDBStream();
Error dumpDbiStream();
- Error dumpTpiStream();
- Error dumpIpiStream();
void flush();
diff --git a/gnu/llvm/unittests/DebugInfo/PDB/ErrorChecking.h b/gnu/llvm/unittests/DebugInfo/PDB/ErrorChecking.h
index 6d4a7de7834..da734a9b1b5 100644
--- a/gnu/llvm/unittests/DebugInfo/PDB/ErrorChecking.h
+++ b/gnu/llvm/unittests/DebugInfo/PDB/ErrorChecking.h
@@ -36,14 +36,6 @@
} \
}
-#define EXPECT_UNEXPECTED(Exp) \
- { \
- auto E = Exp.takeError(); \
- EXPECT_TRUE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- }
+#define EXPECT_UNEXPECTED(Exp) EXPECT_ERROR(Err)
#endif
diff --git a/gnu/llvm/unittests/Transforms/Utils/MemorySSA.cpp b/gnu/llvm/unittests/Transforms/Utils/MemorySSA.cpp
index 945fe32c316..c21121f7870 100644
--- a/gnu/llvm/unittests/Transforms/Utils/MemorySSA.cpp
+++ b/gnu/llvm/unittests/Transforms/Utils/MemorySSA.cpp
@@ -42,17 +42,14 @@ protected:
AssumptionCache AC;
AAResults AA;
BasicAAResult BAA;
- // We need to defer MSSA construction until AA is *entirely* set up, which
- // requires calling addAAResult. Hence, we just use a pointer here.
- std::unique_ptr<MemorySSA> MSSA;
+ MemorySSA MSSA;
MemorySSAWalker *Walker;
TestAnalyses(MemorySSATest &Test)
: DT(*Test.F), AC(*Test.F), AA(Test.TLI),
- BAA(Test.DL, Test.TLI, AC, &DT) {
+ BAA(Test.DL, Test.TLI, AC, &DT), MSSA(*Test.F, &AA, &DT) {
AA.addAAResult(BAA);
- MSSA = make_unique<MemorySSA>(*Test.F, &AA, &DT);
- Walker = MSSA->getWalker();
+ Walker = MSSA.getWalker();
}
};
@@ -68,10 +65,10 @@ public:
: M("MemorySSATest", C), B(C), DL(DLString), TLI(TLII), F(nullptr) {}
};
-TEST_F(MemorySSATest, CreateALoad) {
+TEST_F(MemorySSATest, CreateALoadAndPhi) {
// We create a diamond where there is a store on one side, and then after
- // building MemorySSA, create a load after the merge point, and use it to test
- // updating by creating an access for the load.
+ // running memory ssa, create a load after the merge point, and use it to test
+ // updating by creating an access for the load and a memoryphi.
F = Function::Create(
FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
GlobalValue::ExternalLinkage, "F", &M);
@@ -83,19 +80,23 @@ TEST_F(MemorySSATest, CreateALoad) {
B.CreateCondBr(B.getTrue(), Left, Right);
B.SetInsertPoint(Left);
Argument *PointerArg = &*F->arg_begin();
- B.CreateStore(B.getInt8(16), PointerArg);
+ StoreInst *StoreInst = B.CreateStore(B.getInt8(16), PointerArg);
BranchInst::Create(Merge, Left);
BranchInst::Create(Merge, Right);
setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
+ MemorySSA &MSSA = Analyses->MSSA;
// Add the load
B.SetInsertPoint(Merge);
LoadInst *LoadInst = B.CreateLoad(PointerArg);
+ // Should be no phi to start
+ EXPECT_EQ(MSSA.getMemoryAccess(Merge), nullptr);
- // MemoryPHI should already exist.
- MemoryPhi *MP = MSSA.getMemoryAccess(Merge);
- EXPECT_NE(MP, nullptr);
+ // Create the phi
+ MemoryPhi *MP = MSSA.createMemoryPhi(Merge);
+ MemoryDef *StoreAccess = cast<MemoryDef>(MSSA.getMemoryAccess(StoreInst));
+ MP->addIncoming(StoreAccess, Left);
+ MP->addIncoming(MSSA.getLiveOnEntryDef(), Right);
// Create the load memory acccess
MemoryUse *LoadAccess = cast<MemoryUse>(
@@ -105,41 +106,6 @@ TEST_F(MemorySSATest, CreateALoad) {
MSSA.verifyMemorySSA();
}
-TEST_F(MemorySSATest, MoveAStore) {
- // We create a diamond where there is a in the entry, a store on one side, and
- // a load at the end. After building MemorySSA, we test updating by moving
- // the store from the side block to the entry block.
- F = Function::Create(
- FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
- GlobalValue::ExternalLinkage, "F", &M);
- BasicBlock *Entry(BasicBlock::Create(C, "", F));
- BasicBlock *Left(BasicBlock::Create(C, "", F));
- BasicBlock *Right(BasicBlock::Create(C, "", F));
- BasicBlock *Merge(BasicBlock::Create(C, "", F));
- B.SetInsertPoint(Entry);
- Argument *PointerArg = &*F->arg_begin();
- StoreInst *EntryStore = B.CreateStore(B.getInt8(16), PointerArg);
- B.CreateCondBr(B.getTrue(), Left, Right);
- B.SetInsertPoint(Left);
- StoreInst *SideStore = B.CreateStore(B.getInt8(16), PointerArg);
- BranchInst::Create(Merge, Left);
- BranchInst::Create(Merge, Right);
- B.SetInsertPoint(Merge);
- B.CreateLoad(PointerArg);
- setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
-
- // Move the store
- SideStore->moveBefore(Entry->getTerminator());
- MemoryAccess *EntryStoreAccess = MSSA.getMemoryAccess(EntryStore);
- MemoryAccess *SideStoreAccess = MSSA.getMemoryAccess(SideStore);
- MemoryAccess *NewStoreAccess = MSSA.createMemoryAccessAfter(
- SideStore, EntryStoreAccess, EntryStoreAccess);
- EntryStoreAccess->replaceAllUsesWith(NewStoreAccess);
- MSSA.removeMemoryAccess(SideStoreAccess);
- MSSA.verifyMemorySSA();
-}
-
TEST_F(MemorySSATest, RemoveAPhi) {
// We create a diamond where there is a store on one side, and then a load
// after the merge point. This enables us to test a bunch of different
@@ -162,7 +128,7 @@ TEST_F(MemorySSATest, RemoveAPhi) {
LoadInst *LoadInst = B.CreateLoad(PointerArg);
setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
+ MemorySSA &MSSA = Analyses->MSSA;
// Before, the load will be a use of a phi<store, liveonentry>.
MemoryUse *LoadAccess = cast<MemoryUse>(MSSA.getMemoryAccess(LoadInst));
MemoryDef *StoreAccess = cast<MemoryDef>(MSSA.getMemoryAccess(StoreInst));
@@ -205,7 +171,7 @@ TEST_F(MemorySSATest, RemoveMemoryAccess) {
LoadInst *LoadInst = B.CreateLoad(PointerArg);
setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
+ MemorySSA &MSSA = Analyses->MSSA;
MemorySSAWalker *Walker = Analyses->Walker;
// Before, the load will be a use of a phi<store, liveonentry>. It should be
@@ -225,15 +191,9 @@ TEST_F(MemorySSATest, RemoveMemoryAccess) {
// but we should now get live on entry for the clobbering definition of the
// load, since it will walk past the phi node since every argument is the
// same.
- // XXX: This currently requires either removing the phi or resetting optimized
- // on the load
-
- EXPECT_FALSE(
- MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(LoadInst)));
- // If we reset optimized, we get live on entry.
- LoadAccess->resetOptimized();
EXPECT_TRUE(
MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(LoadInst)));
+
// The phi should now be a two entry phi with two live on entry defs.
for (const auto &Op : DefiningAccess->operands()) {
MemoryAccess *Operand = cast<MemoryAccess>(&*Op);
@@ -270,13 +230,14 @@ TEST_F(MemorySSATest, TestTripleStore) {
StoreInst *S3 = B.CreateStore(ConstantInt::get(Int8, 2), Alloca);
setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
+ MemorySSA &MSSA = Analyses->MSSA;
MemorySSAWalker *Walker = Analyses->Walker;
unsigned I = 0;
for (StoreInst *V : {S1, S2, S3}) {
// Everything should be clobbered by its defining access
- MemoryAccess *DefiningAccess = MSSA.getMemoryAccess(V)->getDefiningAccess();
+ MemoryAccess *DefiningAccess =
+ cast<MemoryUseOrDef>(MSSA.getMemoryAccess(V))->getDefiningAccess();
MemoryAccess *WalkerClobber = Walker->getClobberingMemoryAccess(V);
EXPECT_EQ(DefiningAccess, WalkerClobber)
<< "Store " << I << " doesn't have the correct clobbering access";
@@ -300,7 +261,7 @@ TEST_F(MemorySSATest, TestStoreAndLoad) {
Instruction *LI = B.CreateLoad(Alloca);
setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
+ MemorySSA &MSSA = Analyses->MSSA;
MemorySSAWalker *Walker = Analyses->Walker;
MemoryAccess *LoadClobber = Walker->getClobberingMemoryAccess(LI);
@@ -329,7 +290,7 @@ TEST_F(MemorySSATest, TestStoreDoubleQuery) {
StoreInst *SI = B.CreateStore(ConstantInt::get(Int8, 0), Alloca);
setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
+ MemorySSA &MSSA = Analyses->MSSA;
MemorySSAWalker *Walker = Analyses->Walker;
MemoryAccess *StoreAccess = MSSA.getMemoryAccess(SI);
@@ -347,188 +308,3 @@ TEST_F(MemorySSATest, TestStoreDoubleQuery) {
EXPECT_EQ(Clobber, StoreAccess);
EXPECT_TRUE(MSSA.isLiveOnEntryDef(LiveOnEntry));
}
-
-// Bug: During phi optimization, the walker wouldn't cache to the proper result
-// in the farthest-walked BB.
-//
-// Specifically, it would assume that whatever we walked to was a clobber.
-// "Whatever we walked to" isn't a clobber if we hit a cache entry.
-//
-// ...So, we need a test case that looks like:
-// A
-// / \
-// B |
-// \ /
-// C
-//
-// Where, when we try to optimize a thing in 'C', a blocker is found in 'B'.
-// The walk must determine that the blocker exists by using cache entries *while
-// walking* 'B'.
-TEST_F(MemorySSATest, PartialWalkerCacheWithPhis) {
- F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
- GlobalValue::ExternalLinkage, "F", &M);
- B.SetInsertPoint(BasicBlock::Create(C, "A", F));
- Type *Int8 = Type::getInt8Ty(C);
- Constant *One = ConstantInt::get(Int8, 1);
- Constant *Zero = ConstantInt::get(Int8, 0);
- Value *AllocA = B.CreateAlloca(Int8, One, "a");
- Value *AllocB = B.CreateAlloca(Int8, One, "b");
- BasicBlock *IfThen = BasicBlock::Create(C, "B", F);
- BasicBlock *IfEnd = BasicBlock::Create(C, "C", F);
-
- B.CreateCondBr(UndefValue::get(Type::getInt1Ty(C)), IfThen, IfEnd);
-
- B.SetInsertPoint(IfThen);
- Instruction *FirstStore = B.CreateStore(Zero, AllocA);
- B.CreateStore(Zero, AllocB);
- Instruction *ALoad0 = B.CreateLoad(AllocA, "");
- Instruction *BStore = B.CreateStore(Zero, AllocB);
- // Due to use optimization/etc. we make a store to A, which is removed after
- // we build MSSA. This helps keep the test case simple-ish.
- Instruction *KillStore = B.CreateStore(Zero, AllocA);
- Instruction *ALoad = B.CreateLoad(AllocA, "");
- B.CreateBr(IfEnd);
-
- B.SetInsertPoint(IfEnd);
- Instruction *BelowPhi = B.CreateStore(Zero, AllocA);
-
- setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
- MemorySSAWalker *Walker = Analyses->Walker;
-
- // Kill `KillStore`; it exists solely so that the load after it won't be
- // optimized to FirstStore.
- MSSA.removeMemoryAccess(MSSA.getMemoryAccess(KillStore));
- KillStore->eraseFromParent();
- auto *ALoadMA = cast<MemoryUse>(MSSA.getMemoryAccess(ALoad));
- EXPECT_EQ(ALoadMA->getDefiningAccess(), MSSA.getMemoryAccess(BStore));
-
- // Populate the cache for the store to AllocB directly after FirstStore. It
- // should point to something in block B (so something in D can't be optimized
- // to it).
- MemoryAccess *Load0Clobber = Walker->getClobberingMemoryAccess(ALoad0);
- EXPECT_EQ(MSSA.getMemoryAccess(FirstStore), Load0Clobber);
-
- // If the bug exists, this will introduce a bad cache entry for %a on BStore.
- // It will point to the store to %b after FirstStore. This only happens during
- // phi optimization.
- MemoryAccess *BottomClobber = Walker->getClobberingMemoryAccess(BelowPhi);
- MemoryAccess *Phi = MSSA.getMemoryAccess(IfEnd);
- EXPECT_EQ(BottomClobber, Phi);
-
- // This query will first check the cache for {%a, BStore}. It should point to
- // FirstStore, not to the store after FirstStore.
- MemoryAccess *UseClobber = Walker->getClobberingMemoryAccess(ALoad);
- EXPECT_EQ(UseClobber, MSSA.getMemoryAccess(FirstStore));
-}
-
-// Test that our walker properly handles loads with the invariant group
-// attribute. It's a bit hacky, since we add the invariant attribute *after*
-// building MSSA. Otherwise, the use optimizer will optimize it for us, which
-// isn't what we want.
-// FIXME: It may be easier/cleaner to just add an 'optimize uses?' flag to MSSA.
-TEST_F(MemorySSATest, WalkerInvariantLoadOpt) {
- F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
- GlobalValue::ExternalLinkage, "F", &M);
- B.SetInsertPoint(BasicBlock::Create(C, "", F));
- Type *Int8 = Type::getInt8Ty(C);
- Constant *One = ConstantInt::get(Int8, 1);
- Value *AllocA = B.CreateAlloca(Int8, One, "");
-
- Instruction *Store = B.CreateStore(One, AllocA);
- Instruction *Load = B.CreateLoad(AllocA);
-
- setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
- MemorySSAWalker *Walker = Analyses->Walker;
-
- auto *LoadMA = cast<MemoryUse>(MSSA.getMemoryAccess(Load));
- auto *StoreMA = cast<MemoryDef>(MSSA.getMemoryAccess(Store));
- EXPECT_EQ(LoadMA->getDefiningAccess(), StoreMA);
-
- // ...At the time of writing, no cache should exist for LoadMA. Be a bit
- // flexible to future changes.
- Walker->invalidateInfo(LoadMA);
- Load->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(C, {}));
-
- MemoryAccess *LoadClobber = Walker->getClobberingMemoryAccess(LoadMA);
- EXPECT_EQ(LoadClobber, MSSA.getLiveOnEntryDef());
-}
-
-// Test loads get reoptimized properly by the walker.
-TEST_F(MemorySSATest, WalkerReopt) {
- F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
- GlobalValue::ExternalLinkage, "F", &M);
- B.SetInsertPoint(BasicBlock::Create(C, "", F));
- Type *Int8 = Type::getInt8Ty(C);
- Value *AllocaA = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
- Instruction *SIA = B.CreateStore(ConstantInt::get(Int8, 0), AllocaA);
- Value *AllocaB = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "B");
- Instruction *SIB = B.CreateStore(ConstantInt::get(Int8, 0), AllocaB);
- Instruction *LIA = B.CreateLoad(AllocaA);
-
- setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
- MemorySSAWalker *Walker = Analyses->Walker;
-
- MemoryAccess *LoadClobber = Walker->getClobberingMemoryAccess(LIA);
- MemoryUse *LoadAccess = cast<MemoryUse>(MSSA.getMemoryAccess(LIA));
- EXPECT_EQ(LoadClobber, MSSA.getMemoryAccess(SIA));
- EXPECT_TRUE(MSSA.isLiveOnEntryDef(Walker->getClobberingMemoryAccess(SIA)));
- MSSA.removeMemoryAccess(LoadAccess);
-
- // Create the load memory access pointing to an unoptimized place.
- MemoryUse *NewLoadAccess = cast<MemoryUse>(MSSA.createMemoryAccessInBB(
- LIA, MSSA.getMemoryAccess(SIB), LIA->getParent(), MemorySSA::End));
- // This should it cause it to be optimized
- EXPECT_EQ(Walker->getClobberingMemoryAccess(NewLoadAccess), LoadClobber);
- EXPECT_EQ(NewLoadAccess->getDefiningAccess(), LoadClobber);
-}
-
-// Test out MemorySSA::spliceMemoryAccessAbove.
-TEST_F(MemorySSATest, SpliceAboveMemoryDef) {
- F = Function::Create(FunctionType::get(B.getVoidTy(), {}, false),
- GlobalValue::ExternalLinkage, "F", &M);
- B.SetInsertPoint(BasicBlock::Create(C, "", F));
-
- Type *Int8 = Type::getInt8Ty(C);
- Value *A = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "A");
- Value *B_ = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "B");
- Value *C = B.CreateAlloca(Int8, ConstantInt::get(Int8, 1), "C");
-
- StoreInst *StoreA0 = B.CreateStore(ConstantInt::get(Int8, 0), A);
- StoreInst *StoreB = B.CreateStore(ConstantInt::get(Int8, 0), B_);
- LoadInst *LoadB = B.CreateLoad(B_);
- StoreInst *StoreA1 = B.CreateStore(ConstantInt::get(Int8, 4), A);
- // splice this above StoreB
- StoreInst *StoreC = B.CreateStore(ConstantInt::get(Int8, 4), C);
- StoreInst *StoreA2 = B.CreateStore(ConstantInt::get(Int8, 4), A);
- LoadInst *LoadC = B.CreateLoad(C);
-
- setupAnalyses();
- MemorySSA &MSSA = *Analyses->MSSA;
- MemorySSAWalker &Walker = *Analyses->Walker;
-
- StoreC->moveBefore(StoreB);
- MSSA.spliceMemoryAccessAbove(cast<MemoryDef>(MSSA.getMemoryAccess(StoreB)),
- MSSA.getMemoryAccess(StoreC));
-
- MSSA.verifyMemorySSA();
-
- EXPECT_EQ(MSSA.getMemoryAccess(StoreB)->getDefiningAccess(),
- MSSA.getMemoryAccess(StoreC));
- EXPECT_EQ(MSSA.getMemoryAccess(StoreC)->getDefiningAccess(),
- MSSA.getMemoryAccess(StoreA0));
- EXPECT_EQ(MSSA.getMemoryAccess(StoreA2)->getDefiningAccess(),
- MSSA.getMemoryAccess(StoreA1));
- EXPECT_EQ(Walker.getClobberingMemoryAccess(LoadB),
- MSSA.getMemoryAccess(StoreB));
- EXPECT_EQ(Walker.getClobberingMemoryAccess(LoadC),
- MSSA.getMemoryAccess(StoreC));
-
- // exercise block numbering
- EXPECT_TRUE(MSSA.locallyDominates(MSSA.getMemoryAccess(StoreC),
- MSSA.getMemoryAccess(StoreB)));
- EXPECT_TRUE(MSSA.locallyDominates(MSSA.getMemoryAccess(StoreA1),
- MSSA.getMemoryAccess(StoreA2)));
-}