#ifndef LLVM_CODEGEN_ACCELTABLE_H
#define LLVM_CODEGEN_ACCELTABLE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Debug.h"
#include <cstdint>
#include <vector>
namespace llvm {
class AsmPrinter;
class DwarfCompileUnit;
class DwarfDebug;
class MCSymbol;
class raw_ostream;
class AccelTableData {
public:
virtual ~AccelTableData() = default;
bool operator<(const AccelTableData &Other) const {
return order() < Other.order();
}
#ifndef NDEBUG
virtual void print(raw_ostream &OS) const = 0;
#endif
protected:
virtual uint64_t order() const = 0;
};
class AccelTableBase {
public:
using HashFn = uint32_t(StringRef);
struct HashData {
DwarfStringPoolEntryRef Name;
uint32_t HashValue;
std::vector<AccelTableData *> Values;
MCSymbol *Sym;
HashData(DwarfStringPoolEntryRef Name, HashFn *Hash)
: Name(Name), HashValue(Hash(Name.getString())) {}
#ifndef NDEBUG
void print(raw_ostream &OS) const;
void dump() const { print(dbgs()); }
#endif
};
using HashList = std::vector<HashData *>;
using BucketList = std::vector<HashList>;
protected:
BumpPtrAllocator Allocator;
using StringEntries = StringMap<HashData, BumpPtrAllocator &>;
StringEntries Entries;
HashFn *Hash;
uint32_t BucketCount;
uint32_t UniqueHashCount;
HashList Hashes;
BucketList Buckets;
void computeBucketCount();
AccelTableBase(HashFn *Hash) : Entries(Allocator), Hash(Hash) {}
public:
void finalize(AsmPrinter *Asm, StringRef Prefix);
ArrayRef<HashList> getBuckets() const { return Buckets; }
uint32_t getBucketCount() const { return BucketCount; }
uint32_t getUniqueHashCount() const { return UniqueHashCount; }
uint32_t getUniqueNameCount() const { return Entries.size(); }
#ifndef NDEBUG
void print(raw_ostream &OS) const;
void dump() const { print(dbgs()); }
#endif
AccelTableBase(const AccelTableBase &) = delete;
void operator=(const AccelTableBase &) = delete;
};
template <typename DataT> class AccelTable : public AccelTableBase {
public:
AccelTable() : AccelTableBase(DataT::hash) {}
template <typename... Types>
void addName(DwarfStringPoolEntryRef Name, Types &&... Args);
};
template <typename AccelTableDataT>
template <typename... Types>
void AccelTable<AccelTableDataT>::addName(DwarfStringPoolEntryRef Name,
Types &&... Args) {
assert(Buckets.empty() && "Already finalized!");
auto Iter = Entries.try_emplace(Name.getString(), Name, Hash).first;
assert(Iter->second.Name == Name);
Iter->second.Values.push_back(
new (Allocator) AccelTableDataT(std::forward<Types>(Args)...));
}
class AppleAccelTableData : public AccelTableData {
public:
struct Atom {
const uint16_t Type;
const uint16_t Form;
constexpr Atom(uint16_t Type, uint16_t Form) : Type(Type), Form(Form) {}
#ifndef NDEBUG
void print(raw_ostream &OS) const;
void dump() const { print(dbgs()); }
#endif
};
virtual void emit(AsmPrinter *Asm) const = 0;
static uint32_t hash(StringRef Buffer) { return djbHash(Buffer); }
};
class DWARF5AccelTableData : public AccelTableData {
public:
static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
DWARF5AccelTableData(const DIE &Die) : Die(Die) {}
#ifndef NDEBUG
void print(raw_ostream &OS) const override;
#endif
const DIE &getDie() const { return Die; }
uint64_t getDieOffset() const { return Die.getOffset(); }
unsigned getDieTag() const { return Die.getTag(); }
protected:
const DIE &Die;
uint64_t order() const override { return Die.getOffset(); }
};
class DWARF5AccelTableStaticData : public AccelTableData {
public:
static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
DWARF5AccelTableStaticData(uint64_t DieOffset, unsigned DieTag,
unsigned CUIndex)
: DieOffset(DieOffset), DieTag(DieTag), CUIndex(CUIndex) {}
#ifndef NDEBUG
void print(raw_ostream &OS) const override;
#endif
uint64_t getDieOffset() const { return DieOffset; }
unsigned getDieTag() const { return DieTag; }
unsigned getCUIndex() const { return CUIndex; }
protected:
uint64_t DieOffset;
unsigned DieTag;
unsigned CUIndex;
uint64_t order() const override { return DieOffset; }
};
void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
StringRef Prefix, const MCSymbol *SecBegin,
ArrayRef<AppleAccelTableData::Atom> Atoms);
template <typename DataT>
void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents,
StringRef Prefix, const MCSymbol *SecBegin) {
static_assert(std::is_convertible<DataT *, AppleAccelTableData *>::value, "");
emitAppleAccelTableImpl(Asm, Contents, Prefix, SecBegin, DataT::Atoms);
}
void emitDWARF5AccelTable(AsmPrinter *Asm,
AccelTable<DWARF5AccelTableData> &Contents,
const DwarfDebug &DD,
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
void emitDWARF5AccelTable(
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
ArrayRef<MCSymbol *> CUs,
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
getCUIndexForEntry);
class AppleAccelTableOffsetData : public AppleAccelTableData {
public:
AppleAccelTableOffsetData(const DIE &D) : Die(D) {}
void emit(AsmPrinter *Asm) const override;
static constexpr Atom Atoms[] = {
Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
#ifndef NDEBUG
void print(raw_ostream &OS) const override;
#endif
protected:
uint64_t order() const override { return Die.getOffset(); }
const DIE &Die;
};
class AppleAccelTableTypeData : public AppleAccelTableOffsetData {
public:
AppleAccelTableTypeData(const DIE &D) : AppleAccelTableOffsetData(D) {}
void emit(AsmPrinter *Asm) const override;
static constexpr Atom Atoms[] = {
Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
#ifndef NDEBUG
void print(raw_ostream &OS) const override;
#endif
};
class AppleAccelTableStaticOffsetData : public AppleAccelTableData {
public:
AppleAccelTableStaticOffsetData(uint32_t Offset) : Offset(Offset) {}
void emit(AsmPrinter *Asm) const override;
static constexpr Atom Atoms[] = {
Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
#ifndef NDEBUG
void print(raw_ostream &OS) const override;
#endif
protected:
uint64_t order() const override { return Offset; }
uint32_t Offset;
};
class AppleAccelTableStaticTypeData : public AppleAccelTableStaticOffsetData {
public:
AppleAccelTableStaticTypeData(uint32_t Offset, uint16_t Tag,
bool ObjCClassIsImplementation,
uint32_t QualifiedNameHash)
: AppleAccelTableStaticOffsetData(Offset),
QualifiedNameHash(QualifiedNameHash), Tag(Tag),
ObjCClassIsImplementation(ObjCClassIsImplementation) {}
void emit(AsmPrinter *Asm) const override;
static constexpr Atom Atoms[] = {
Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)};
#ifndef NDEBUG
void print(raw_ostream &OS) const override;
#endif
protected:
uint64_t order() const override { return Offset; }
uint32_t QualifiedNameHash;
uint16_t Tag;
bool ObjCClassIsImplementation;
};
}
#endif