forked from OSchip/llvm-project
Introduce the mechanism for building an AST on-disk hash table for name lookup inside a DeclContext but don't use it yet.
llvm-svn: 111635
This commit is contained in:
parent
082e4613eb
commit
07347321c6
|
@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {
|
||||||
Item *next;
|
Item *next;
|
||||||
const uint32_t hash;
|
const uint32_t hash;
|
||||||
|
|
||||||
Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
|
Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
|
||||||
: key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
|
Info &InfoObj)
|
||||||
|
: key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Bucket {
|
class Bucket {
|
||||||
|
@ -168,10 +169,17 @@ public:
|
||||||
|
|
||||||
void insert(typename Info::key_type_ref key,
|
void insert(typename Info::key_type_ref key,
|
||||||
typename Info::data_type_ref data) {
|
typename Info::data_type_ref data) {
|
||||||
|
Info InfoObj;
|
||||||
|
insert(key, data, InfoObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(typename Info::key_type_ref key,
|
||||||
|
typename Info::data_type_ref data, Info &InfoObj) {
|
||||||
|
|
||||||
++NumEntries;
|
++NumEntries;
|
||||||
if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
|
if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
|
||||||
insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data));
|
insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data,
|
||||||
|
InfoObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
io::Offset Emit(llvm::raw_ostream &out) {
|
io::Offset Emit(llvm::raw_ostream &out) {
|
||||||
|
@ -278,8 +286,8 @@ public:
|
||||||
InfoPtr = &InfoObj;
|
InfoPtr = &InfoObj;
|
||||||
|
|
||||||
using namespace io;
|
using namespace io;
|
||||||
const internal_key_type& iKey = Info::GetInternalKey(eKey);
|
const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
|
||||||
unsigned key_hash = Info::ComputeHash(iKey);
|
unsigned key_hash = InfoObj.ComputeHash(iKey);
|
||||||
|
|
||||||
// Each bucket is just a 32-bit offset into the hash table file.
|
// Each bucket is just a 32-bit offset into the hash table file.
|
||||||
unsigned idx = key_hash & (NumBuckets - 1);
|
unsigned idx = key_hash & (NumBuckets - 1);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
#include "llvm/Bitcode/BitCodes.h"
|
#include "llvm/Bitcode/BitCodes.h"
|
||||||
#include "llvm/System/DataTypes.h"
|
#include "llvm/System/DataTypes.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
namespace serialization {
|
namespace serialization {
|
||||||
|
@ -81,6 +82,36 @@ namespace clang {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A structure for putting "fast"-unqualified QualTypes into a
|
||||||
|
/// DenseMap. This uses the standard pointer hash function.
|
||||||
|
struct UnsafeQualTypeDenseMapInfo {
|
||||||
|
static inline bool isEqual(QualType A, QualType B) { return A == B; }
|
||||||
|
static inline QualType getEmptyKey() {
|
||||||
|
return QualType::getFromOpaquePtr((void*) 1);
|
||||||
|
}
|
||||||
|
static inline QualType getTombstoneKey() {
|
||||||
|
return QualType::getFromOpaquePtr((void*) 2);
|
||||||
|
}
|
||||||
|
static inline unsigned getHashValue(QualType T) {
|
||||||
|
assert(!T.getLocalFastQualifiers() &&
|
||||||
|
"hash invalid for types with fast quals");
|
||||||
|
uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||||
|
return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Map that provides the ID numbers of each type within the
|
||||||
|
/// output stream, plus those deserialized from a chained PCH.
|
||||||
|
///
|
||||||
|
/// The ID numbers of types are consecutive (in order of discovery)
|
||||||
|
/// and start at 1. 0 is reserved for NULL. When types are actually
|
||||||
|
/// stored in the stream, the ID number is shifted by 2 bits to
|
||||||
|
/// allow for the const/volatile qualifiers.
|
||||||
|
///
|
||||||
|
/// Keys in the map never have const/volatile qualifiers.
|
||||||
|
typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo>
|
||||||
|
TypeIdxMap;
|
||||||
|
|
||||||
/// \brief An ID number that refers to an identifier in an AST
|
/// \brief An ID number that refers to an identifier in an AST
|
||||||
/// file.
|
/// file.
|
||||||
typedef uint32_t IdentID;
|
typedef uint32_t IdentID;
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "llvm/ADT/APFloat.h"
|
#include "llvm/ADT/APFloat.h"
|
||||||
#include "llvm/ADT/APInt.h"
|
#include "llvm/ADT/APInt.h"
|
||||||
#include "llvm/ADT/APSInt.h"
|
#include "llvm/ADT/APSInt.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
|
||||||
#include "llvm/ADT/OwningPtr.h"
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
@ -315,6 +314,17 @@ private:
|
||||||
/// ID = (I + 1) << FastQual::Width has already been loaded
|
/// ID = (I + 1) << FastQual::Width has already been loaded
|
||||||
std::vector<QualType> TypesLoaded;
|
std::vector<QualType> TypesLoaded;
|
||||||
|
|
||||||
|
/// \brief Map that provides the ID numbers of each type within the
|
||||||
|
/// output stream, plus those deserialized from a chained PCH.
|
||||||
|
///
|
||||||
|
/// The ID numbers of types are consecutive (in order of discovery)
|
||||||
|
/// and start at 1. 0 is reserved for NULL. When types are actually
|
||||||
|
/// stored in the stream, the ID number is shifted by 2 bits to
|
||||||
|
/// allow for the const/volatile qualifiers.
|
||||||
|
///
|
||||||
|
/// Keys in the map never have const/volatile qualifiers.
|
||||||
|
serialization::TypeIdxMap TypeIdxs;
|
||||||
|
|
||||||
/// \brief Declarations that have already been loaded from the chain.
|
/// \brief Declarations that have already been loaded from the chain.
|
||||||
///
|
///
|
||||||
/// When the pointer at index I is non-NULL, the declaration with ID
|
/// When the pointer at index I is non-NULL, the declaration with ID
|
||||||
|
@ -720,6 +730,16 @@ public:
|
||||||
/// type.
|
/// type.
|
||||||
QualType GetType(serialization::TypeID ID);
|
QualType GetType(serialization::TypeID ID);
|
||||||
|
|
||||||
|
/// \brief Returns the type ID associated with the given type.
|
||||||
|
/// If the type didn't come from the AST file the ID that is returned is
|
||||||
|
/// marked as "doesn't exist in AST".
|
||||||
|
serialization::TypeID GetTypeID(QualType T) const;
|
||||||
|
|
||||||
|
/// \brief Returns the type index associated with the given type.
|
||||||
|
/// If the type didn't come from the AST file the index that is returned is
|
||||||
|
/// marked as "doesn't exist in AST".
|
||||||
|
serialization::TypeIdx GetTypeIdx(QualType T) const;
|
||||||
|
|
||||||
/// \brief Resolve a declaration ID into a declaration, potentially
|
/// \brief Resolve a declaration ID into a declaration, potentially
|
||||||
/// building a new declaration.
|
/// building a new declaration.
|
||||||
Decl *GetDecl(serialization::DeclID ID);
|
Decl *GetDecl(serialization::DeclID ID);
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "clang/Serialization/ASTBitCodes.h"
|
#include "clang/Serialization/ASTBitCodes.h"
|
||||||
#include "clang/Serialization/ASTDeserializationListener.h"
|
#include "clang/Serialization/ASTDeserializationListener.h"
|
||||||
#include "clang/Sema/SemaConsumer.h"
|
#include "clang/Sema/SemaConsumer.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||||
|
@ -50,24 +49,6 @@ class SourceManager;
|
||||||
class SwitchCase;
|
class SwitchCase;
|
||||||
class TargetInfo;
|
class TargetInfo;
|
||||||
|
|
||||||
/// A structure for putting "fast"-unqualified QualTypes into a
|
|
||||||
/// DenseMap. This uses the standard pointer hash function.
|
|
||||||
struct UnsafeQualTypeDenseMapInfo {
|
|
||||||
static inline bool isEqual(QualType A, QualType B) { return A == B; }
|
|
||||||
static inline QualType getEmptyKey() {
|
|
||||||
return QualType::getFromOpaquePtr((void*) 1);
|
|
||||||
}
|
|
||||||
static inline QualType getTombstoneKey() {
|
|
||||||
return QualType::getFromOpaquePtr((void*) 2);
|
|
||||||
}
|
|
||||||
static inline unsigned getHashValue(QualType T) {
|
|
||||||
assert(!T.getLocalFastQualifiers() &&
|
|
||||||
"hash invalid for types with fast quals");
|
|
||||||
uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
|
||||||
return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief Writes an AST file containing the contents of a translation unit.
|
/// \brief Writes an AST file containing the contents of a translation unit.
|
||||||
///
|
///
|
||||||
/// The ASTWriter class produces a bitstream containing the serialized
|
/// The ASTWriter class produces a bitstream containing the serialized
|
||||||
|
@ -146,8 +127,7 @@ private:
|
||||||
/// allow for the const/volatile qualifiers.
|
/// allow for the const/volatile qualifiers.
|
||||||
///
|
///
|
||||||
/// Keys in the map never have const/volatile qualifiers.
|
/// Keys in the map never have const/volatile qualifiers.
|
||||||
llvm::DenseMap<QualType, serialization::TypeIdx, UnsafeQualTypeDenseMapInfo>
|
serialization::TypeIdxMap TypeIdxs;
|
||||||
TypeIdxs;
|
|
||||||
|
|
||||||
/// \brief Offset of each type in the bitstream, indexed by
|
/// \brief Offset of each type in the bitstream, indexed by
|
||||||
/// the type's ID.
|
/// the type's ID.
|
||||||
|
@ -368,13 +348,13 @@ public:
|
||||||
serialization::TypeID GetOrCreateTypeID(QualType T);
|
serialization::TypeID GetOrCreateTypeID(QualType T);
|
||||||
|
|
||||||
/// \brief Determine the type ID of an already-emitted type.
|
/// \brief Determine the type ID of an already-emitted type.
|
||||||
serialization::TypeID getTypeID(QualType T);
|
serialization::TypeID getTypeID(QualType T) const;
|
||||||
|
|
||||||
/// \brief Force a type to be emitted and get its index.
|
/// \brief Force a type to be emitted and get its index.
|
||||||
serialization::TypeIdx GetOrCreateTypeIdx(QualType T);
|
serialization::TypeIdx GetOrCreateTypeIdx(QualType T);
|
||||||
|
|
||||||
/// \brief Determine the type index of an already-emitted type.
|
/// \brief Determine the type index of an already-emitted type.
|
||||||
serialization::TypeIdx getTypeIdx(QualType T);
|
serialization::TypeIdx getTypeIdx(QualType T) const;
|
||||||
|
|
||||||
/// \brief Emits a reference to a declarator info.
|
/// \brief Emits a reference to a declarator info.
|
||||||
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
|
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
|
||||||
|
|
|
@ -704,6 +704,148 @@ public:
|
||||||
typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
|
typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
|
||||||
ASTIdentifierLookupTable;
|
ASTIdentifierLookupTable;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class ASTDeclContextNameLookupTrait {
|
||||||
|
ASTReader &Reader;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \brief Pair of begin/end iterators for DeclIDs.
|
||||||
|
typedef std::pair<DeclID *, DeclID *> data_type;
|
||||||
|
|
||||||
|
/// \brief Special internal key for declaration names.
|
||||||
|
/// The hash table creates keys for comparison; we do not create
|
||||||
|
/// a DeclarationName for the internal key to avoid deserializing types.
|
||||||
|
struct DeclNameKey {
|
||||||
|
DeclarationName::NameKind Kind;
|
||||||
|
uint64_t Data;
|
||||||
|
DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DeclarationName external_key_type;
|
||||||
|
typedef DeclNameKey internal_key_type;
|
||||||
|
|
||||||
|
explicit ASTDeclContextNameLookupTrait(ASTReader &Reader) : Reader(Reader) { }
|
||||||
|
|
||||||
|
static bool EqualKey(const internal_key_type& a,
|
||||||
|
const internal_key_type& b) {
|
||||||
|
return a.Kind == b.Kind && a.Data == b.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ComputeHash(const DeclNameKey &Key) const {
|
||||||
|
llvm::FoldingSetNodeID ID;
|
||||||
|
ID.AddInteger(Key.Kind);
|
||||||
|
|
||||||
|
switch (Key.Kind) {
|
||||||
|
case DeclarationName::Identifier:
|
||||||
|
case DeclarationName::CXXLiteralOperatorName:
|
||||||
|
ID.AddString(((IdentifierInfo*)Key.Data)->getName());
|
||||||
|
break;
|
||||||
|
case DeclarationName::ObjCZeroArgSelector:
|
||||||
|
case DeclarationName::ObjCOneArgSelector:
|
||||||
|
case DeclarationName::ObjCMultiArgSelector:
|
||||||
|
ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXConstructorName:
|
||||||
|
case DeclarationName::CXXDestructorName:
|
||||||
|
case DeclarationName::CXXConversionFunctionName:
|
||||||
|
ID.AddInteger((TypeID)Key.Data);
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXOperatorName:
|
||||||
|
ID.AddInteger((OverloadedOperatorKind)Key.Data);
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXUsingDirective:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ID.ComputeHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_key_type GetInternalKey(const external_key_type& Name) const {
|
||||||
|
DeclNameKey Key;
|
||||||
|
Key.Kind = Name.getNameKind();
|
||||||
|
switch (Name.getNameKind()) {
|
||||||
|
case DeclarationName::Identifier:
|
||||||
|
Key.Data = (uint64_t)Name.getAsIdentifierInfo();
|
||||||
|
break;
|
||||||
|
case DeclarationName::ObjCZeroArgSelector:
|
||||||
|
case DeclarationName::ObjCOneArgSelector:
|
||||||
|
case DeclarationName::ObjCMultiArgSelector:
|
||||||
|
Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXConstructorName:
|
||||||
|
case DeclarationName::CXXDestructorName:
|
||||||
|
case DeclarationName::CXXConversionFunctionName:
|
||||||
|
Key.Data = Reader.GetTypeID(Name.getCXXNameType());
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXOperatorName:
|
||||||
|
Key.Data = Name.getCXXOverloadedOperator();
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXLiteralOperatorName:
|
||||||
|
Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXUsingDirective:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::pair<unsigned, unsigned>
|
||||||
|
ReadKeyDataLength(const unsigned char*& d) {
|
||||||
|
using namespace clang::io;
|
||||||
|
unsigned KeyLen = ReadUnalignedLE16(d);
|
||||||
|
unsigned DataLen = ReadUnalignedLE16(d);
|
||||||
|
return std::make_pair(KeyLen, DataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_key_type ReadKey(const unsigned char* d, unsigned) {
|
||||||
|
using namespace clang::io;
|
||||||
|
|
||||||
|
DeclNameKey Key;
|
||||||
|
Key.Kind = (DeclarationName::NameKind)*d++;
|
||||||
|
switch (Key.Kind) {
|
||||||
|
case DeclarationName::Identifier:
|
||||||
|
Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
|
||||||
|
break;
|
||||||
|
case DeclarationName::ObjCZeroArgSelector:
|
||||||
|
case DeclarationName::ObjCOneArgSelector:
|
||||||
|
case DeclarationName::ObjCMultiArgSelector:
|
||||||
|
Key.Data =
|
||||||
|
(uint64_t)Reader.DecodeSelector(ReadUnalignedLE32(d)).getAsOpaquePtr();
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXConstructorName:
|
||||||
|
case DeclarationName::CXXDestructorName:
|
||||||
|
case DeclarationName::CXXConversionFunctionName:
|
||||||
|
Key.Data = ReadUnalignedLE32(d); // TypeID
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXOperatorName:
|
||||||
|
Key.Data = *d++; // OverloadedOperatorKind
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXLiteralOperatorName:
|
||||||
|
Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXUsingDirective:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_type ReadData(internal_key_type, const unsigned char* d,
|
||||||
|
unsigned DataLen) {
|
||||||
|
using namespace clang::io;
|
||||||
|
unsigned NumDecls = ReadUnalignedLE16(d);
|
||||||
|
DeclID *Start = (DeclID *)d;
|
||||||
|
return std::make_pair(Start, Start + NumDecls);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
|
||||||
|
typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
|
||||||
|
ASTDeclContextNameLookupTable;
|
||||||
|
|
||||||
void ASTReader::Error(const char *Msg) {
|
void ASTReader::Error(const char *Msg) {
|
||||||
Diag(diag::err_fe_pch_malformed) << Msg;
|
Diag(diag::err_fe_pch_malformed) << Msg;
|
||||||
}
|
}
|
||||||
|
@ -2825,6 +2967,7 @@ QualType ASTReader::GetType(TypeID ID) {
|
||||||
if (TypesLoaded[Index].isNull()) {
|
if (TypesLoaded[Index].isNull()) {
|
||||||
TypesLoaded[Index] = ReadTypeRecord(Index);
|
TypesLoaded[Index] = ReadTypeRecord(Index);
|
||||||
TypesLoaded[Index]->setFromAST();
|
TypesLoaded[Index]->setFromAST();
|
||||||
|
TypeIdxs[TypesLoaded[Index]] = TypeIdx::fromTypeID(ID);
|
||||||
if (DeserializationListener)
|
if (DeserializationListener)
|
||||||
DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
|
DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
|
||||||
TypesLoaded[Index]);
|
TypesLoaded[Index]);
|
||||||
|
@ -2833,6 +2976,27 @@ QualType ASTReader::GetType(TypeID ID) {
|
||||||
return TypesLoaded[Index].withFastQualifiers(FastQuals);
|
return TypesLoaded[Index].withFastQualifiers(FastQuals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeID ASTReader::GetTypeID(QualType T) const {
|
||||||
|
return MakeTypeID(T,
|
||||||
|
std::bind1st(std::mem_fun(&ASTReader::GetTypeIdx), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeIdx ASTReader::GetTypeIdx(QualType T) const {
|
||||||
|
if (T.isNull())
|
||||||
|
return TypeIdx();
|
||||||
|
assert(!T.getLocalFastQualifiers());
|
||||||
|
|
||||||
|
TypeIdxMap::const_iterator I = TypeIdxs.find(T);
|
||||||
|
// GetTypeIdx is mostly used for computing the hash of DeclarationNames and
|
||||||
|
// comparing keys of ASTDeclContextNameLookupTable.
|
||||||
|
// If the type didn't come from the AST file use a specially marked index
|
||||||
|
// so that any hash/key comparison fail since no such index is stored
|
||||||
|
// in a AST file.
|
||||||
|
if (I == TypeIdxs.end())
|
||||||
|
return TypeIdx(-1);
|
||||||
|
return I->second;
|
||||||
|
}
|
||||||
|
|
||||||
TemplateArgumentLocInfo
|
TemplateArgumentLocInfo
|
||||||
ASTReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
|
ASTReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
|
||||||
llvm::BitstreamCursor &DeclsCursor,
|
llvm::BitstreamCursor &DeclsCursor,
|
||||||
|
|
|
@ -1653,6 +1653,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
|
||||||
// Create and write out the blob that contains selectors and the method pool.
|
// Create and write out the blob that contains selectors and the method pool.
|
||||||
{
|
{
|
||||||
OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
|
OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
|
||||||
|
ASTMethodPoolTrait Trait(*this);
|
||||||
|
|
||||||
// Create the on-disk hash table representation. We walk through every
|
// Create the on-disk hash table representation. We walk through every
|
||||||
// selector we've seen and look it up in the method pool.
|
// selector we've seen and look it up in the method pool.
|
||||||
|
@ -1692,7 +1693,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) {
|
||||||
// A new method pool entry.
|
// A new method pool entry.
|
||||||
++NumTableEntries;
|
++NumTableEntries;
|
||||||
}
|
}
|
||||||
Generator.insert(S, Data);
|
Generator.insert(S, Data, Trait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the on-disk hash table in a buffer.
|
// Create the on-disk hash table in a buffer.
|
||||||
|
@ -1877,6 +1878,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
|
||||||
// strings.
|
// strings.
|
||||||
{
|
{
|
||||||
OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
|
OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
|
||||||
|
ASTIdentifierTableTrait Trait(*this, PP);
|
||||||
|
|
||||||
// Look for any identifiers that were named while processing the
|
// Look for any identifiers that were named while processing the
|
||||||
// headers, but are otherwise not needed. We add these to the hash
|
// headers, but are otherwise not needed. We add these to the hash
|
||||||
|
@ -1896,7 +1898,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
|
||||||
ID != IDEnd; ++ID) {
|
ID != IDEnd; ++ID) {
|
||||||
assert(ID->first && "NULL identifier in identifier table");
|
assert(ID->first && "NULL identifier in identifier table");
|
||||||
if (!Chain || !ID->first->isFromAST())
|
if (!Chain || !ID->first->isFromAST())
|
||||||
Generator.insert(ID->first, ID->second);
|
Generator.insert(ID->first, ID->second, Trait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the on-disk hash table in a buffer.
|
// Create the on-disk hash table in a buffer.
|
||||||
|
@ -1939,6 +1941,127 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
|
||||||
IdentifierOffsets.size() * sizeof(uint32_t));
|
IdentifierOffsets.size() * sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// DeclContext's Name Lookup Table Serialization
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Trait used for the on-disk hash table used in the method pool.
|
||||||
|
class ASTDeclContextNameLookupTrait {
|
||||||
|
ASTWriter &Writer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef DeclarationName key_type;
|
||||||
|
typedef key_type key_type_ref;
|
||||||
|
|
||||||
|
typedef DeclContext::lookup_result data_type;
|
||||||
|
typedef const data_type& data_type_ref;
|
||||||
|
|
||||||
|
explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }
|
||||||
|
|
||||||
|
unsigned ComputeHash(DeclarationName Name) {
|
||||||
|
llvm::FoldingSetNodeID ID;
|
||||||
|
ID.AddInteger(Name.getNameKind());
|
||||||
|
|
||||||
|
switch (Name.getNameKind()) {
|
||||||
|
case DeclarationName::Identifier:
|
||||||
|
ID.AddString(Name.getAsIdentifierInfo()->getName());
|
||||||
|
break;
|
||||||
|
case DeclarationName::ObjCZeroArgSelector:
|
||||||
|
case DeclarationName::ObjCOneArgSelector:
|
||||||
|
case DeclarationName::ObjCMultiArgSelector:
|
||||||
|
ID.AddInteger(serialization::ComputeHash(Name.getObjCSelector()));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXConstructorName:
|
||||||
|
case DeclarationName::CXXDestructorName:
|
||||||
|
case DeclarationName::CXXConversionFunctionName:
|
||||||
|
ID.AddInteger(Writer.GetOrCreateTypeID(Name.getCXXNameType()));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXOperatorName:
|
||||||
|
ID.AddInteger(Name.getCXXOverloadedOperator());
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXLiteralOperatorName:
|
||||||
|
ID.AddString(Name.getCXXLiteralIdentifier()->getName());
|
||||||
|
case DeclarationName::CXXUsingDirective:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ID.ComputeHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<unsigned,unsigned>
|
||||||
|
EmitKeyDataLength(llvm::raw_ostream& Out, DeclarationName Name,
|
||||||
|
data_type_ref Lookup) {
|
||||||
|
unsigned KeyLen = 1;
|
||||||
|
switch (Name.getNameKind()) {
|
||||||
|
case DeclarationName::Identifier:
|
||||||
|
case DeclarationName::ObjCZeroArgSelector:
|
||||||
|
case DeclarationName::ObjCOneArgSelector:
|
||||||
|
case DeclarationName::ObjCMultiArgSelector:
|
||||||
|
case DeclarationName::CXXConstructorName:
|
||||||
|
case DeclarationName::CXXDestructorName:
|
||||||
|
case DeclarationName::CXXConversionFunctionName:
|
||||||
|
case DeclarationName::CXXLiteralOperatorName:
|
||||||
|
KeyLen += 4;
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXOperatorName:
|
||||||
|
KeyLen += 1;
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXUsingDirective:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clang::io::Emit16(Out, KeyLen);
|
||||||
|
|
||||||
|
// 2 bytes for num of decls and 4 for each DeclID.
|
||||||
|
unsigned DataLen = 2 + 4 * (Lookup.second - Lookup.first);
|
||||||
|
clang::io::Emit16(Out, DataLen);
|
||||||
|
|
||||||
|
return std::make_pair(KeyLen, DataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitKey(llvm::raw_ostream& Out, DeclarationName Name, unsigned) {
|
||||||
|
using namespace clang::io;
|
||||||
|
|
||||||
|
assert(Name.getNameKind() < 0x100 && "Invalid name kind ?");
|
||||||
|
Emit8(Out, Name.getNameKind());
|
||||||
|
switch (Name.getNameKind()) {
|
||||||
|
case DeclarationName::Identifier:
|
||||||
|
Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
|
||||||
|
break;
|
||||||
|
case DeclarationName::ObjCZeroArgSelector:
|
||||||
|
case DeclarationName::ObjCOneArgSelector:
|
||||||
|
case DeclarationName::ObjCMultiArgSelector:
|
||||||
|
Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector()));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXConstructorName:
|
||||||
|
case DeclarationName::CXXDestructorName:
|
||||||
|
case DeclarationName::CXXConversionFunctionName:
|
||||||
|
Emit32(Out, Writer.getTypeID(Name.getCXXNameType()));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXOperatorName:
|
||||||
|
assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?");
|
||||||
|
Emit8(Out, Name.getCXXOverloadedOperator());
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXLiteralOperatorName:
|
||||||
|
Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
|
||||||
|
break;
|
||||||
|
case DeclarationName::CXXUsingDirective:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitData(llvm::raw_ostream& Out, key_type_ref,
|
||||||
|
data_type Lookup, unsigned DataLen) {
|
||||||
|
uint64_t Start = Out.tell(); (void)Start;
|
||||||
|
clang::io::Emit16(Out, Lookup.second - Lookup.first);
|
||||||
|
for (; Lookup.first != Lookup.second; ++Lookup.first)
|
||||||
|
clang::io::Emit32(Out, Writer.GetDeclRef(*Lookup.first));
|
||||||
|
|
||||||
|
assert(Out.tell() - Start == DataLen && "Data length is wrong");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// General Serialization Routines
|
// General Serialization Routines
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -2587,7 +2710,7 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) {
|
||||||
std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
|
std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeID ASTWriter::getTypeID(QualType T) {
|
TypeID ASTWriter::getTypeID(QualType T) const {
|
||||||
return MakeTypeID(T,
|
return MakeTypeID(T,
|
||||||
std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
|
std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
|
||||||
}
|
}
|
||||||
|
@ -2607,13 +2730,14 @@ TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) {
|
||||||
return Idx;
|
return Idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeIdx ASTWriter::getTypeIdx(QualType T) {
|
TypeIdx ASTWriter::getTypeIdx(QualType T) const {
|
||||||
if (T.isNull())
|
if (T.isNull())
|
||||||
return TypeIdx();
|
return TypeIdx();
|
||||||
assert(!T.getLocalFastQualifiers());
|
assert(!T.getLocalFastQualifiers());
|
||||||
|
|
||||||
assert(TypeIdxs.find(T) != TypeIdxs.end() && "Type not emitted!");
|
TypeIdxMap::const_iterator I = TypeIdxs.find(T);
|
||||||
return TypeIdxs[T];
|
assert(I != TypeIdxs.end() && "Type not emitted!");
|
||||||
|
return I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTWriter::AddDeclRef(const Decl *D, RecordData &Record) {
|
void ASTWriter::AddDeclRef(const Decl *D, RecordData &Record) {
|
||||||
|
|
Loading…
Reference in New Issue