diff options
author | Zachary Turner <zturner@google.com> | 2017-12-13 22:33:58 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2017-12-13 22:33:58 +0000 |
commit | 5c7c640d1d60198c97aeff2283352adc98c5c9f3 (patch) | |
tree | 16fb00c009040ed4347931661bc5469ef4a03bd0 /lib/DebugInfo | |
parent | 9d2ef8532ff8987b63d321067d785e2236fcbe28 (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.txt | 1 | ||||
-rw-r--r-- | lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp | 127 |
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; +} |