зеркало из https://github.com/microsoft/clang-1.git
Introduce the mechanism for building an AST on-disk hash table for name lookup inside a DeclContext but don't use it yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111635 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
eb3f04e60f
Коммит
5d26768e26
|
@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {
|
|||
Item *next;
|
||||
const uint32_t hash;
|
||||
|
||||
Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
|
||||
: key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
|
||||
Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
|
||||
Info &InfoObj)
|
||||
: key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
|
||||
};
|
||||
|
||||
class Bucket {
|
||||
|
@ -168,10 +169,17 @@ public:
|
|||
|
||||
void insert(typename Info::key_type_ref key,
|
||||
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;
|
||||
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) {
|
||||
|
@ -278,8 +286,8 @@ public:
|
|||
InfoPtr = &InfoObj;
|
||||
|
||||
using namespace io;
|
||||
const internal_key_type& iKey = Info::GetInternalKey(eKey);
|
||||
unsigned key_hash = Info::ComputeHash(iKey);
|
||||
const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
|
||||
unsigned key_hash = InfoObj.ComputeHash(iKey);
|
||||
|
||||
// Each bucket is just a 32-bit offset into the hash table file.
|
||||
unsigned idx = key_hash & (NumBuckets - 1);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/AST/Type.h"
|
||||
#include "llvm/Bitcode/BitCodes.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace clang {
|
||||
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
|
||||
/// file.
|
||||
typedef uint32_t IdentID;
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -315,6 +314,17 @@ private:
|
|||
/// ID = (I + 1) << FastQual::Width has already been loaded
|
||||
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.
|
||||
///
|
||||
/// When the pointer at index I is non-NULL, the declaration with ID
|
||||
|
@ -720,6 +730,16 @@ public:
|
|||
/// type.
|
||||
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
|
||||
/// building a new declaration.
|
||||
Decl *GetDecl(serialization::DeclID ID);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "clang/Serialization/ASTBitCodes.h"
|
||||
#include "clang/Serialization/ASTDeserializationListener.h"
|
||||
#include "clang/Sema/SemaConsumer.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
|
@ -50,24 +49,6 @@ class SourceManager;
|
|||
class SwitchCase;
|
||||
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.
|
||||
///
|
||||
/// The ASTWriter class produces a bitstream containing the serialized
|
||||
|
@ -146,8 +127,7 @@ private:
|
|||
/// allow for the const/volatile qualifiers.
|
||||
///
|
||||
/// Keys in the map never have const/volatile qualifiers.
|
||||
llvm::DenseMap<QualType, serialization::TypeIdx, UnsafeQualTypeDenseMapInfo>
|
||||
TypeIdxs;
|
||||
serialization::TypeIdxMap TypeIdxs;
|
||||
|
||||
/// \brief Offset of each type in the bitstream, indexed by
|
||||
/// the type's ID.
|
||||
|
@ -368,13 +348,13 @@ public:
|
|||
serialization::TypeID GetOrCreateTypeID(QualType T);
|
||||
|
||||
/// \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.
|
||||
serialization::TypeIdx GetOrCreateTypeIdx(QualType T);
|
||||
|
||||
/// \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.
|
||||
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
|
||||
|
|
|
@ -704,6 +704,148 @@ public:
|
|||
typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
|
||||
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) {
|
||||
Diag(diag::err_fe_pch_malformed) << Msg;
|
||||
}
|
||||
|
@ -2825,6 +2967,7 @@ QualType ASTReader::GetType(TypeID ID) {
|
|||
if (TypesLoaded[Index].isNull()) {
|
||||
TypesLoaded[Index] = ReadTypeRecord(Index);
|
||||
TypesLoaded[Index]->setFromAST();
|
||||
TypeIdxs[TypesLoaded[Index]] = TypeIdx::fromTypeID(ID);
|
||||
if (DeserializationListener)
|
||||
DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
|
||||
TypesLoaded[Index]);
|
||||
|
@ -2833,6 +2976,27 @@ QualType ASTReader::GetType(TypeID ID) {
|
|||
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
|
||||
ASTReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
|
||||
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.
|
||||
{
|
||||
OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
|
||||
ASTMethodPoolTrait Trait(*this);
|
||||
|
||||
// Create the on-disk hash table representation. We walk through every
|
||||
// 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.
|
||||
++NumTableEntries;
|
||||
}
|
||||
Generator.insert(S, Data);
|
||||
Generator.insert(S, Data, Trait);
|
||||
}
|
||||
|
||||
// Create the on-disk hash table in a buffer.
|
||||
|
@ -1877,6 +1878,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
|
|||
// strings.
|
||||
{
|
||||
OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
|
||||
ASTIdentifierTableTrait Trait(*this, PP);
|
||||
|
||||
// Look for any identifiers that were named while processing the
|
||||
// headers, but are otherwise not needed. We add these to the hash
|
||||
|
@ -1896,7 +1898,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
|
|||
ID != IDEnd; ++ID) {
|
||||
assert(ID->first && "NULL identifier in identifier table");
|
||||
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.
|
||||
|
@ -1939,6 +1941,127 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
|
|||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2587,7 +2710,7 @@ TypeID ASTWriter::GetOrCreateTypeID(QualType T) {
|
|||
std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
|
||||
}
|
||||
|
||||
TypeID ASTWriter::getTypeID(QualType T) {
|
||||
TypeID ASTWriter::getTypeID(QualType T) const {
|
||||
return MakeTypeID(T,
|
||||
std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
|
||||
}
|
||||
|
@ -2607,13 +2730,14 @@ TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) {
|
|||
return Idx;
|
||||
}
|
||||
|
||||
TypeIdx ASTWriter::getTypeIdx(QualType T) {
|
||||
TypeIdx ASTWriter::getTypeIdx(QualType T) const {
|
||||
if (T.isNull())
|
||||
return TypeIdx();
|
||||
assert(!T.getLocalFastQualifiers());
|
||||
|
||||
assert(TypeIdxs.find(T) != TypeIdxs.end() && "Type not emitted!");
|
||||
return TypeIdxs[T];
|
||||
TypeIdxMap::const_iterator I = TypeIdxs.find(T);
|
||||
assert(I != TypeIdxs.end() && "Type not emitted!");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
void ASTWriter::AddDeclRef(const Decl *D, RecordData &Record) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче