summaryrefslogtreecommitdiff
path: root/lib/DebugInfo
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2017-12-13 22:33:58 +0000
committerZachary Turner <zturner@google.com>2017-12-13 22:33:58 +0000
commit5c7c640d1d60198c97aeff2283352adc98c5c9f3 (patch)
tree16fb00c009040ed4347931661bc5469ef4a03bd0 /lib/DebugInfo
parent9d2ef8532ff8987b63d321067d785e2236fcbe28 (diff)
[CodeView] Teach clang to emit the .debug$H COFF section.
Currently this is an LLVM extension to the COFF spec which is experimental and intended to speed up linking. For now it is behind a hidden cl::opt flag, but in the future we can move it to a "real" cc1 flag and have the driver pass it through whenever it is appropriate. The patch to actually make use of this section in lld will come in a followup. Differential Revision: https://reviews.llvm.org/D40917 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320649 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp127
2 files changed, 128 insertions, 0 deletions
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt
index c3d79c0d6e6..0515788d85e 100644
--- a/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -19,6 +19,7 @@ add_llvm_library(LLVMDebugInfoCodeView
DebugSymbolsSubsection.cpp
EnumTables.cpp
Formatters.cpp
+ GlobalTypeTableBuilder.cpp
LazyRandomTypeCollection.cpp
Line.cpp
MergingTypeTableBuilder.cpp
diff --git a/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp b/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp
new file mode 100644
index 00000000000..3ecd684c1e3
--- /dev/null
+++ b/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp
@@ -0,0 +1,127 @@
+//===- GlobalTypeTableBuilder.cpp -----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+TypeIndex GlobalTypeTableBuilder::nextTypeIndex() const {
+ return TypeIndex::fromArrayIndex(SeenRecords.size());
+}
+
+GlobalTypeTableBuilder::GlobalTypeTableBuilder(BumpPtrAllocator &Storage)
+ : RecordStorage(Storage) {
+ SeenRecords.reserve(4096);
+}
+
+GlobalTypeTableBuilder::~GlobalTypeTableBuilder() = default;
+
+Optional<TypeIndex> GlobalTypeTableBuilder::getFirst() {
+ if (empty())
+ return None;
+
+ return TypeIndex(TypeIndex::FirstNonSimpleIndex);
+}
+
+Optional<TypeIndex> GlobalTypeTableBuilder::getNext(TypeIndex Prev) {
+ if (++Prev == nextTypeIndex())
+ return None;
+ return Prev;
+}
+
+CVType GlobalTypeTableBuilder::getType(TypeIndex Index) {
+ CVType Type;
+ Type.RecordData = SeenRecords[Index.toArrayIndex()];
+ const RecordPrefix *P =
+ reinterpret_cast<const RecordPrefix *>(Type.RecordData.data());
+ Type.Type = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
+ return Type;
+}
+
+StringRef GlobalTypeTableBuilder::getTypeName(TypeIndex Index) {
+ llvm_unreachable("Method not implemented");
+}
+
+bool GlobalTypeTableBuilder::contains(TypeIndex Index) {
+ if (Index.isSimple() || Index.isNoneType())
+ return false;
+
+ return Index.toArrayIndex() < SeenRecords.size();
+}
+
+uint32_t GlobalTypeTableBuilder::size() { return SeenRecords.size(); }
+
+uint32_t GlobalTypeTableBuilder::capacity() { return SeenRecords.size(); }
+
+ArrayRef<ArrayRef<uint8_t>> GlobalTypeTableBuilder::records() const {
+ return SeenRecords;
+}
+
+ArrayRef<GloballyHashedType> GlobalTypeTableBuilder::hashes() const {
+ return SeenHashes;
+}
+
+void GlobalTypeTableBuilder::reset() {
+ HashedRecords.clear();
+ SeenRecords.clear();
+}
+
+static inline ArrayRef<uint8_t> stabilize(BumpPtrAllocator &Alloc,
+ ArrayRef<uint8_t> Data) {
+ uint8_t *Stable = Alloc.Allocate<uint8_t>(Data.size());
+ memcpy(Stable, Data.data(), Data.size());
+ return makeArrayRef(Stable, Data.size());
+}
+
+TypeIndex GlobalTypeTableBuilder::insertRecordAs(GloballyHashedType Hash,
+ CreateRecord Create) {
+ auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex());
+
+ if (Result.second) {
+ ArrayRef<uint8_t> RecordData = stabilize(RecordStorage, Create());
+ SeenRecords.push_back(RecordData);
+ SeenHashes.push_back(Hash);
+ }
+
+ // Update the caller's copy of Record to point a stable copy.
+ return Result.first->second;
+}
+
+TypeIndex GlobalTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> Record) {
+ GloballyHashedType GHT =
+ GloballyHashedType::hashType(Record, SeenHashes, SeenHashes);
+ return insertRecordAs(GHT, [Record]() { return Record; });
+}
+
+TypeIndex
+GlobalTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) {
+ TypeIndex TI;
+ auto Fragments = Builder.end(nextTypeIndex());
+ assert(!Fragments.empty());
+ for (auto C : Fragments)
+ TI = insertRecordBytes(C.RecordData);
+ return TI;
+}