//
//===----------------------------------------------------------------------===//
+#include "DwarfAccelTable.h"
+#include "DwarfDebug.h"
+#include "DIE.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h"
-#include "DwarfAccelTable.h"
-#include "DwarfDebug.h"
-#include "DIE.h"
using namespace llvm;
const char *DwarfAccelTable::Atom::AtomTypeString(enum AtomType AT) {
switch (AT) {
- default: llvm_unreachable("invalid AtomType!");
case eAtomTypeNULL: return "eAtomTypeNULL";
case eAtomTypeDIEOffset: return "eAtomTypeDIEOffset";
case eAtomTypeCUOffset: return "eAtomTypeCUOffset";
case eAtomTypeNameFlags: return "eAtomTypeNameFlags";
case eAtomTypeTypeFlags: return "eAtomTypeTypeFlags";
}
+ llvm_unreachable("invalid AtomType!");
}
// The general case would need to have a less hard coded size for the
HeaderData(atom) {
}
+// The length of the header data is always going to be 4 + 4 + 4*NumAtoms.
+DwarfAccelTable::DwarfAccelTable(std::vector<DwarfAccelTable::Atom> &atomList) :
+ Header(8 + (atomList.size() * 4)),
+ HeaderData(atomList) {
+}
+
DwarfAccelTable::~DwarfAccelTable() {
- for (size_t i = 0, e = Data.size() ; i < e; ++i)
+ for (size_t i = 0, e = Data.size(); i < e; ++i)
delete Data[i];
+ for (StringMap<DataArray>::iterator
+ EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI)
+ for (DataArray::iterator DI = EI->second.begin(),
+ DE = EI->second.end(); DI != DE; ++DI)
+ delete (*DI);
}
-void DwarfAccelTable::AddName(StringRef Name, DIE* die) {
+void DwarfAccelTable::AddName(StringRef Name, DIE* die, char Flags) {
// If the string is in the list already then add this die to the list
// otherwise add a new one.
- DIEArray &DIEs = Entries[Name];
- DIEs.push_back(die);
+ DataArray &DIEs = Entries[Name];
+ DIEs.push_back(new HashDataContents(die, Flags));
}
void DwarfAccelTable::ComputeBucketCount(void) {
// First get the number of unique hashes.
- std::vector<uint32_t> uniques;
- uniques.resize(Data.size());
- for (size_t i = 0; i < Data.size(); ++i)
+ std::vector<uint32_t> uniques(Data.size());
+ for (size_t i = 0, e = Data.size(); i < e; ++i)
uniques[i] = Data[i]->HashValue;
- std::sort(uniques.begin(), uniques.end());
+ array_pod_sort(uniques.begin(), uniques.end());
std::vector<uint32_t>::iterator p =
std::unique(uniques.begin(), uniques.end());
uint32_t num = std::distance(uniques.begin(), p);
Header.hashes_count = num;
}
+namespace {
+ // DIESorter - comparison predicate that sorts DIEs by their offset.
+ struct DIESorter {
+ bool operator()(const struct DwarfAccelTable::HashDataContents *A,
+ const struct DwarfAccelTable::HashDataContents *B) const {
+ return A->Die->getOffset() < B->Die->getOffset();
+ }
+ };
+}
+
void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) {
// Create the individual hash data outputs.
- for (StringMap<DIEArray>::const_iterator
+ for (StringMap<DataArray>::iterator
EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
struct HashData *Entry = new HashData((*EI).getKeyData());
- for (DIEArray::const_iterator DI = (*EI).second.begin(),
- DE = (*EI).second.end();
+
+ // Unique the entries.
+ std::stable_sort(EI->second.begin(), EI->second.end(), DIESorter());
+ EI->second.erase(std::unique(EI->second.begin(), EI->second.end()),
+ EI->second.end());
+
+ for (DataArray::const_iterator DI = EI->second.begin(),
+ DE = EI->second.end();
DI != DE; ++DI)
- Entry->addOffset((*DI)->getOffset());
+ Entry->addData((*DI));
Data.push_back(Entry);
}
// Compute bucket contents and final ordering.
Buckets.resize(Header.bucket_count);
- for (size_t i = 0; i < Data.size(); ++i) {
+ for (size_t i = 0, e = Data.size(); i < e; ++i) {
uint32_t bucket = Data[i]->HashValue % Header.bucket_count;
Buckets[bucket].push_back(Data[i]);
Data[i]->Sym = Asm->GetTempSymbol(Prefix, i);
// like a list of numbers of how many elements are in each bucket.
void DwarfAccelTable::EmitBuckets(AsmPrinter *Asm) {
unsigned index = 0;
- for (size_t i = 0; i < Buckets.size(); ++i) {
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
Asm->OutStreamer.AddComment("Bucket " + Twine(i));
if (Buckets[i].size() != 0)
Asm->EmitInt32(index);
// Walk through the buckets and emit the individual hashes for each
// bucket.
void DwarfAccelTable::EmitHashes(AsmPrinter *Asm) {
- for (size_t i = 0; i < Buckets.size(); ++i) {
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
for (HashList::const_iterator HI = Buckets[i].begin(),
HE = Buckets[i].end(); HI != HE; ++HI) {
Asm->OutStreamer.AddComment("Hash in Bucket " + Twine(i));
// beginning of the section. The non-section symbol will be output later
// when we emit the actual data.
void DwarfAccelTable::EmitOffsets(AsmPrinter *Asm, MCSymbol *SecBegin) {
- for (size_t i = 0; i < Buckets.size(); ++i) {
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
for (HashList::const_iterator HI = Buckets[i].begin(),
HE = Buckets[i].end(); HI != HE; ++HI) {
Asm->OutStreamer.AddComment("Offset in Bucket " + Twine(i));
// Terminate each HashData bucket with 0.
void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) {
uint64_t PrevHash = UINT64_MAX;
- for (size_t i = 0; i < Buckets.size(); ++i) {
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
for (HashList::const_iterator HI = Buckets[i].begin(),
HE = Buckets[i].end(); HI != HE; ++HI) {
// Remember to emit the label for our offset.
Asm->EmitSectionOffset(D->getStringPoolEntry((*HI)->Str),
D->getStringPool());
Asm->OutStreamer.AddComment("Num DIEs");
- Asm->EmitInt32((*HI)->DIEOffsets.size());
- for (std::vector<uint32_t>::const_iterator
- DI = (*HI)->DIEOffsets.begin(), DE = (*HI)->DIEOffsets.end();
+ Asm->EmitInt32((*HI)->Data.size());
+ for (std::vector<struct HashDataContents*>::const_iterator
+ DI = (*HI)->Data.begin(), DE = (*HI)->Data.end();
DI != DE; ++DI) {
- Asm->EmitInt32((*DI));
+ // Emit the DIE offset
+ Asm->EmitInt32((*DI)->Die->getOffset());
+ // If we have multiple Atoms emit that info too.
+ // FIXME: A bit of a hack, we either emit only one atom or all info.
+ if (HeaderData.Atoms.size() > 1) {
+ Asm->EmitInt16((*DI)->Die->getTag());
+ Asm->EmitInt8((*DI)->Flags);
+ }
}
// Emit a 0 to terminate the data unless we have a hash collision.
if (PrevHash != (*HI)->HashValue)
HeaderData.print(O);
O << "Entries: \n";
- for (StringMap<DIEArray>::const_iterator
+ for (StringMap<DataArray>::const_iterator
EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
- O << "Name: " << (*EI).getKeyData() << "\n";
- for (DIEArray::const_iterator DI = (*EI).second.begin(),
- DE = (*EI).second.end();
+ O << "Name: " << EI->getKeyData() << "\n";
+ for (DataArray::const_iterator DI = EI->second.begin(),
+ DE = EI->second.end();
DI != DE; ++DI)
(*DI)->print(O);
}
O << "Buckets and Hashes: \n";
- for (size_t i = 0; i < Buckets.size(); ++i)
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i)
for (HashList::const_iterator HI = Buckets[i].begin(),
HE = Buckets[i].end(); HI != HE; ++HI)
(*HI)->print(O);