diff options
author | Jonas Devlieghere <jonas@devlieghere.com> | 2018-01-29 14:52:41 +0000 |
---|---|---|
committer | Jonas Devlieghere <jonas@devlieghere.com> | 2018-01-29 14:52:41 +0000 |
commit | 855fc3bbcaf25938351a1493812765eb93c5c887 (patch) | |
tree | 41aff5a49d62994196890adc1801738e65d298ac /llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp | |
parent | e699dfaa7a9e7dd00fed4d39f7d6511782d03ba2 (diff) | |
download | llvm-855fc3bbcaf25938351a1493812765eb93c5c887.zip llvm-855fc3bbcaf25938351a1493812765eb93c5c887.tar.gz llvm-855fc3bbcaf25938351a1493812765eb93c5c887.tar.bz2 |
[NFC] Rename DwarfAccelTable and move header.
This patch renames DwarfAccelTable.{h,cpp} to AccelTable.{h,cpp} and
moves the header to the include dir so it is accessible by the
dsymutil implementation.
Differential revision: https://reviews.llvm.org/D42529
llvm-svn: 323654
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp new file mode 100644 index 0000000..026573b --- /dev/null +++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -0,0 +1,221 @@ +//===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing accelerator tables. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/AccelTable.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DIE.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <vector> + +using namespace llvm; + +void AppleAccelTableHeader::emit(AsmPrinter *Asm) { + // Emit Header. + Asm->OutStreamer->AddComment("Header Magic"); + Asm->EmitInt32(Header.Magic); + Asm->OutStreamer->AddComment("Header Version"); + Asm->EmitInt16(Header.Version); + Asm->OutStreamer->AddComment("Header Hash Function"); + Asm->EmitInt16(Header.HashFunction); + Asm->OutStreamer->AddComment("Header Bucket Count"); + Asm->EmitInt32(Header.BucketCount); + Asm->OutStreamer->AddComment("Header Hash Count"); + Asm->EmitInt32(Header.HashCount); + Asm->OutStreamer->AddComment("Header Data Length"); + Asm->EmitInt32(Header.HeaderDataLength); + + // Emit Header Data + Asm->OutStreamer->AddComment("HeaderData Die Offset Base"); + Asm->EmitInt32(HeaderData.DieOffsetBase); + Asm->OutStreamer->AddComment("HeaderData Atom Count"); + Asm->EmitInt32(HeaderData.Atoms.size()); + + for (size_t i = 0; i < HeaderData.Atoms.size(); i++) { + Atom A = HeaderData.Atoms[i]; + Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type)); + Asm->EmitInt16(A.Type); + Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form)); + Asm->EmitInt16(A.Form); + } +} + +void AppleAccelTableHeader::setBucketAndHashCount(uint32_t HashCount) { + if (HashCount > 1024) + Header.BucketCount = HashCount / 4; + else if (HashCount > 16) + Header.BucketCount = HashCount / 2; + else + Header.BucketCount = HashCount > 0 ? HashCount : 1; + + Header.HashCount = HashCount; +} + +constexpr AppleAccelTableHeader::Atom AppleAccelTableTypeData::Atoms[]; +constexpr AppleAccelTableHeader::Atom AppleAccelTableOffsetData::Atoms[]; + +void AppleAccelTableBase::emitHeader(AsmPrinter *Asm) { Header.emit(Asm); } + +void AppleAccelTableBase::emitBuckets(AsmPrinter *Asm) { + unsigned index = 0; + for (size_t i = 0, e = Buckets.size(); i < e; ++i) { + Asm->OutStreamer->AddComment("Bucket " + Twine(i)); + if (!Buckets[i].empty()) + Asm->EmitInt32(index); + else + Asm->EmitInt32(std::numeric_limits<uint32_t>::max()); + // Buckets point in the list of hashes, not to the data. Do not increment + // the index multiple times in case of hash collisions. + uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); + for (auto *HD : Buckets[i]) { + uint32_t HashValue = HD->HashValue; + if (PrevHash != HashValue) + ++index; + PrevHash = HashValue; + } + } +} + +void AppleAccelTableBase::emitHashes(AsmPrinter *Asm) { + uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); + unsigned BucketIdx = 0; + for (auto &Bucket : Buckets) { + for (auto &Hash : Bucket) { + uint32_t HashValue = Hash->HashValue; + if (PrevHash == HashValue) + continue; + Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx)); + Asm->EmitInt32(HashValue); + PrevHash = HashValue; + } + BucketIdx++; + } +} + +void AppleAccelTableBase::emitOffsets(AsmPrinter *Asm, + const MCSymbol *SecBegin) { + uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); + for (size_t i = 0, e = Buckets.size(); i < e; ++i) { + for (auto HI = Buckets[i].begin(), HE = Buckets[i].end(); HI != HE; ++HI) { + uint32_t HashValue = (*HI)->HashValue; + if (PrevHash == HashValue) + continue; + PrevHash = HashValue; + Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i)); + MCContext &Context = Asm->OutStreamer->getContext(); + const MCExpr *Sub = MCBinaryExpr::createSub( + MCSymbolRefExpr::create((*HI)->Sym, Context), + MCSymbolRefExpr::create(SecBegin, Context), Context); + Asm->OutStreamer->EmitValue(Sub, sizeof(uint32_t)); + } + } +} + +void AppleAccelTableBase::emitData(AsmPrinter *Asm) { + for (size_t i = 0, e = Buckets.size(); i < e; ++i) { + uint64_t PrevHash = std::numeric_limits<uint64_t>::max(); + for (auto &Hash : Buckets[i]) { + // Terminate the previous entry if there is no hash collision with the + // current one. + if (PrevHash != std::numeric_limits<uint64_t>::max() && + PrevHash != Hash->HashValue) + Asm->EmitInt32(0); + // Remember to emit the label for our offset. + Asm->OutStreamer->EmitLabel(Hash->Sym); + Asm->OutStreamer->AddComment(Hash->Str); + Asm->emitDwarfStringOffset(Hash->Data.Name); + Asm->OutStreamer->AddComment("Num DIEs"); + Asm->EmitInt32(Hash->Data.Values.size()); + for (const auto *V : Hash->Data.Values) { + V->emit(Asm); + } + PrevHash = Hash->HashValue; + } + // Emit the final end marker for the bucket. + if (!Buckets[i].empty()) + Asm->EmitInt32(0); + } +} + +void AppleAccelTableBase::computeBucketCount() { + // First get the number of unique hashes. + std::vector<uint32_t> uniques(Data.size()); + for (size_t i = 0, e = Data.size(); i < e; ++i) + uniques[i] = Data[i]->HashValue; + array_pod_sort(uniques.begin(), uniques.end()); + std::vector<uint32_t>::iterator p = + std::unique(uniques.begin(), uniques.end()); + + // Compute the hashes count and use it to set that together with the bucket + // count in the header. + Header.setBucketAndHashCount(std::distance(uniques.begin(), p)); +} + +void AppleAccelTableBase::finalizeTable(AsmPrinter *Asm, StringRef Prefix) { + // Create the individual hash data outputs. + Data.reserve(Entries.size()); + for (auto &E : Entries) { + // Unique the entries. + std::stable_sort(E.second.Values.begin(), E.second.Values.end(), + [](const AppleAccelTableData *A, + const AppleAccelTableData *B) { return *A < *B; }); + E.second.Values.erase( + std::unique(E.second.Values.begin(), E.second.Values.end()), + E.second.Values.end()); + + HashData *Entry = new (Allocator) HashData(E.first(), E.second); + Data.push_back(Entry); + } + + // Figure out how many buckets we need, then compute the bucket contents and + // the final ordering. We'll emit the hashes and offsets by doing a walk + // during the emission phase. We add temporary symbols to the data so that we + // can reference them during the offset later, we'll emit them when we emit + // the data. + computeBucketCount(); + + // Compute bucket contents and final ordering. + Buckets.resize(Header.getBucketCount()); + for (auto &D : Data) { + uint32_t bucket = D->HashValue % Header.getBucketCount(); + Buckets[bucket].push_back(D); + D->Sym = Asm->createTempSymbol(Prefix); + } + + // Sort the contents of the buckets by hash value so that hash collisions end + // up together. Stable sort makes testing easier and doesn't cost much more. + for (auto &Bucket : Buckets) + std::stable_sort(Bucket.begin(), Bucket.end(), + [](HashData *LHS, HashData *RHS) { + return LHS->HashValue < RHS->HashValue; + }); +} + +void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const { + Asm->EmitInt32(Die->getDebugSectionOffset()); +} + +void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const { + Asm->EmitInt32(Die->getDebugSectionOffset()); + Asm->EmitInt16(Die->getTag()); + Asm->EmitInt8(0); +} |