Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,352 @@
//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines common functions that both ASTReader and ASTWriter use.
//
//===----------------------------------------------------------------------===//
#include "ASTCommon.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
// Give ASTDeserializationListener's VTable a home.
ASTDeserializationListener::~ASTDeserializationListener() { }
serialization::TypeIdx
serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
unsigned ID = 0;
switch (BT->getKind()) {
case BuiltinType::Void:
ID = PREDEF_TYPE_VOID_ID;
break;
case BuiltinType::Bool:
ID = PREDEF_TYPE_BOOL_ID;
break;
case BuiltinType::Char_U:
ID = PREDEF_TYPE_CHAR_U_ID;
break;
case BuiltinType::UChar:
ID = PREDEF_TYPE_UCHAR_ID;
break;
case BuiltinType::UShort:
ID = PREDEF_TYPE_USHORT_ID;
break;
case BuiltinType::UInt:
ID = PREDEF_TYPE_UINT_ID;
break;
case BuiltinType::ULong:
ID = PREDEF_TYPE_ULONG_ID;
break;
case BuiltinType::ULongLong:
ID = PREDEF_TYPE_ULONGLONG_ID;
break;
case BuiltinType::UInt128:
ID = PREDEF_TYPE_UINT128_ID;
break;
case BuiltinType::Char_S:
ID = PREDEF_TYPE_CHAR_S_ID;
break;
case BuiltinType::SChar:
ID = PREDEF_TYPE_SCHAR_ID;
break;
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
ID = PREDEF_TYPE_WCHAR_ID;
break;
case BuiltinType::Short:
ID = PREDEF_TYPE_SHORT_ID;
break;
case BuiltinType::Int:
ID = PREDEF_TYPE_INT_ID;
break;
case BuiltinType::Long:
ID = PREDEF_TYPE_LONG_ID;
break;
case BuiltinType::LongLong:
ID = PREDEF_TYPE_LONGLONG_ID;
break;
case BuiltinType::Int128:
ID = PREDEF_TYPE_INT128_ID;
break;
case BuiltinType::Half:
ID = PREDEF_TYPE_HALF_ID;
break;
case BuiltinType::Float:
ID = PREDEF_TYPE_FLOAT_ID;
break;
case BuiltinType::Double:
ID = PREDEF_TYPE_DOUBLE_ID;
break;
case BuiltinType::LongDouble:
ID = PREDEF_TYPE_LONGDOUBLE_ID;
break;
case BuiltinType::Float16:
ID = PREDEF_TYPE_FLOAT16_ID;
break;
case BuiltinType::Float128:
ID = PREDEF_TYPE_FLOAT128_ID;
break;
case BuiltinType::NullPtr:
ID = PREDEF_TYPE_NULLPTR_ID;
break;
case BuiltinType::Char16:
ID = PREDEF_TYPE_CHAR16_ID;
break;
case BuiltinType::Char32:
ID = PREDEF_TYPE_CHAR32_ID;
break;
case BuiltinType::Overload:
ID = PREDEF_TYPE_OVERLOAD_ID;
break;
case BuiltinType::BoundMember:
ID = PREDEF_TYPE_BOUND_MEMBER;
break;
case BuiltinType::PseudoObject:
ID = PREDEF_TYPE_PSEUDO_OBJECT;
break;
case BuiltinType::Dependent:
ID = PREDEF_TYPE_DEPENDENT_ID;
break;
case BuiltinType::UnknownAny:
ID = PREDEF_TYPE_UNKNOWN_ANY;
break;
case BuiltinType::ARCUnbridgedCast:
ID = PREDEF_TYPE_ARC_UNBRIDGED_CAST;
break;
case BuiltinType::ObjCId:
ID = PREDEF_TYPE_OBJC_ID;
break;
case BuiltinType::ObjCClass:
ID = PREDEF_TYPE_OBJC_CLASS;
break;
case BuiltinType::ObjCSel:
ID = PREDEF_TYPE_OBJC_SEL;
break;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
ID = PREDEF_TYPE_##Id##_ID; \
break;
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
ID = PREDEF_TYPE_SAMPLER_ID;
break;
case BuiltinType::OCLEvent:
ID = PREDEF_TYPE_EVENT_ID;
break;
case BuiltinType::OCLClkEvent:
ID = PREDEF_TYPE_CLK_EVENT_ID;
break;
case BuiltinType::OCLQueue:
ID = PREDEF_TYPE_QUEUE_ID;
break;
case BuiltinType::OCLReserveID:
ID = PREDEF_TYPE_RESERVE_ID_ID;
break;
case BuiltinType::BuiltinFn:
ID = PREDEF_TYPE_BUILTIN_FN;
break;
case BuiltinType::OMPArraySection:
ID = PREDEF_TYPE_OMP_ARRAY_SECTION;
break;
}
return TypeIdx(ID);
}
unsigned serialization::ComputeHash(Selector Sel) {
unsigned N = Sel.getNumArgs();
if (N == 0)
++N;
unsigned R = 5381;
for (unsigned I = 0; I != N; ++I)
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
R = llvm::HashString(II->getName(), R);
return R;
}
const DeclContext *
serialization::getDefinitiveDeclContext(const DeclContext *DC) {
switch (DC->getDeclKind()) {
// These entities may have multiple definitions.
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::Namespace:
case Decl::LinkageSpec:
case Decl::Export:
return nullptr;
// C/C++ tag types can only be defined in one place.
case Decl::Enum:
case Decl::Record:
if (const TagDecl *Def = cast<TagDecl>(DC)->getDefinition())
return Def;
return nullptr;
// FIXME: These can be defined in one place... except special member
// functions and out-of-line definitions.
case Decl::CXXRecord:
case Decl::ClassTemplateSpecialization:
case Decl::ClassTemplatePartialSpecialization:
return nullptr;
// Each function, method, and block declaration is its own DeclContext.
case Decl::Function:
case Decl::CXXMethod:
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXConversion:
case Decl::ObjCMethod:
case Decl::Block:
case Decl::Captured:
// Objective C categories, category implementations, and class
// implementations can only be defined in one place.
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCImplementation:
return DC;
case Decl::ObjCProtocol:
if (const ObjCProtocolDecl *Def
= cast<ObjCProtocolDecl>(DC)->getDefinition())
return Def;
return nullptr;
// FIXME: These are defined in one place, but properties in class extensions
// end up being back-patched into the main interface. See
// Sema::HandlePropertyInClassExtension for the offending code.
case Decl::ObjCInterface:
return nullptr;
default:
llvm_unreachable("Unhandled DeclContext in AST reader");
}
llvm_unreachable("Unhandled decl kind");
}
bool serialization::isRedeclarableDeclKind(unsigned Kind) {
switch (static_cast<Decl::Kind>(Kind)) {
case Decl::TranslationUnit:
case Decl::ExternCContext:
// Special case of a "merged" declaration.
return true;
case Decl::Namespace:
case Decl::NamespaceAlias:
case Decl::Typedef:
case Decl::TypeAlias:
case Decl::Enum:
case Decl::Record:
case Decl::CXXRecord:
case Decl::ClassTemplateSpecialization:
case Decl::ClassTemplatePartialSpecialization:
case Decl::VarTemplateSpecialization:
case Decl::VarTemplatePartialSpecialization:
case Decl::Function:
case Decl::CXXDeductionGuide:
case Decl::CXXMethod:
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXConversion:
case Decl::UsingShadow:
case Decl::ConstructorUsingShadow:
case Decl::Var:
case Decl::FunctionTemplate:
case Decl::ClassTemplate:
case Decl::VarTemplate:
case Decl::TypeAliasTemplate:
case Decl::ObjCProtocol:
case Decl::ObjCInterface:
case Decl::Empty:
return true;
// Never redeclarable.
case Decl::UsingDirective:
case Decl::Label:
case Decl::UnresolvedUsingTypename:
case Decl::TemplateTypeParm:
case Decl::EnumConstant:
case Decl::UnresolvedUsingValue:
case Decl::IndirectField:
case Decl::Field:
case Decl::MSProperty:
case Decl::ObjCIvar:
case Decl::ObjCAtDefsField:
case Decl::NonTypeTemplateParm:
case Decl::TemplateTemplateParm:
case Decl::Using:
case Decl::UsingPack:
case Decl::ObjCMethod:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCImplementation:
case Decl::ObjCProperty:
case Decl::ObjCCompatibleAlias:
case Decl::LinkageSpec:
case Decl::Export:
case Decl::ObjCPropertyImpl:
case Decl::PragmaComment:
case Decl::PragmaDetectMismatch:
case Decl::FileScopeAsm:
case Decl::AccessSpec:
case Decl::Friend:
case Decl::FriendTemplate:
case Decl::StaticAssert:
case Decl::Block:
case Decl::Captured:
case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPCapturedExpr:
case Decl::OMPDeclareReduction:
case Decl::BuiltinTemplate:
case Decl::Decomposition:
case Decl::Binding:
return false;
// These indirectly derive from Redeclarable<T> but are not actually
// redeclarable.
case Decl::ImplicitParam:
case Decl::ParmVar:
case Decl::ObjCTypeParam:
return false;
}
llvm_unreachable("Unhandled declaration kind");
}
bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) {
// Friend declarations in dependent contexts aren't anonymous in the usual
// sense, but they cannot be found by name lookup in their semantic context
// (or indeed in any context), so we treat them as anonymous.
//
// This doesn't apply to friend tag decls; Sema makes those available to name
// lookup in the surrounding context.
if (D->getFriendObjectKind() &&
D->getLexicalDeclContext()->isDependentContext() && !isa<TagDecl>(D)) {
// For function templates and class templates, the template is numbered and
// not its pattern.
if (auto *FD = dyn_cast<FunctionDecl>(D))
return !FD->getDescribedFunctionTemplate();
if (auto *RD = dyn_cast<CXXRecordDecl>(D))
return !RD->getDescribedClassTemplate();
return true;
}
// Otherwise, we only care about anonymous class members.
if (D->getDeclName() || !isa<CXXRecordDecl>(D->getLexicalDeclContext()))
return false;
return isa<TagDecl>(D) || isa<FieldDecl>(D);
}

View File

@ -0,0 +1,116 @@
//===- ASTCommon.h - Common stuff for ASTReader/ASTWriter -*- C++ -*-=========//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines common functions that both ASTReader and ASTWriter use.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H
#define LLVM_CLANG_LIB_SERIALIZATION_ASTCOMMON_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/Serialization/ASTBitCodes.h"
namespace clang {
namespace serialization {
enum DeclUpdateKind {
UPD_CXX_ADDED_IMPLICIT_MEMBER,
UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
UPD_CXX_ADDED_FUNCTION_DEFINITION,
UPD_CXX_ADDED_VAR_DEFINITION,
UPD_CXX_POINT_OF_INSTANTIATION,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT,
UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER,
UPD_CXX_RESOLVED_DTOR_DELETE,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
UPD_DECL_MARKED_USED,
UPD_MANGLING_NUMBER,
UPD_STATIC_LOCAL_NUMBER,
UPD_DECL_MARKED_OPENMP_THREADPRIVATE,
UPD_DECL_MARKED_OPENMP_DECLARETARGET,
UPD_DECL_EXPORTED,
UPD_ADDED_ATTR_TO_RECORD
};
TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
template <typename IdxForTypeTy>
TypeID MakeTypeID(ASTContext &Context, QualType T, IdxForTypeTy IdxForType) {
if (T.isNull())
return PREDEF_TYPE_NULL_ID;
unsigned FastQuals = T.getLocalFastQualifiers();
T.removeLocalFastQualifiers();
if (T.hasLocalNonFastQualifiers())
return IdxForType(T).asTypeID(FastQuals);
assert(!T.hasLocalQualifiers());
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
return TypeIdxFromBuiltin(BT).asTypeID(FastQuals);
if (T == Context.AutoDeductTy)
return TypeIdx(PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals);
if (T == Context.AutoRRefDeductTy)
return TypeIdx(PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals);
return IdxForType(T).asTypeID(FastQuals);
}
unsigned ComputeHash(Selector Sel);
/// \brief Retrieve the "definitive" declaration that provides all of the
/// visible entries for the given declaration context, if there is one.
///
/// The "definitive" declaration is the only place where we need to look to
/// find information about the declarations within the given declaration
/// context. For example, C++ and Objective-C classes, C structs/unions, and
/// Objective-C protocols, categories, and extensions are all defined in a
/// single place in the source code, so they have definitive declarations
/// associated with them. C++ namespaces, on the other hand, can have
/// multiple definitions.
const DeclContext *getDefinitiveDeclContext(const DeclContext *DC);
/// \brief Determine whether the given declaration kind is redeclarable.
bool isRedeclarableDeclKind(unsigned Kind);
/// \brief Determine whether the given declaration needs an anonymous
/// declaration number.
bool needsAnonymousDeclarationNumber(const NamedDecl *D);
/// \brief Visit each declaration within \c DC that needs an anonymous
/// declaration number and call \p Visit with the declaration and its number.
template<typename Fn> void numberAnonymousDeclsWithin(const DeclContext *DC,
Fn Visit) {
unsigned Index = 0;
for (Decl *LexicalD : DC->decls()) {
// For a friend decl, we care about the declaration within it, if any.
if (auto *FD = dyn_cast<FriendDecl>(LexicalD))
LexicalD = FD->getFriendDecl();
auto *ND = dyn_cast_or_null<NamedDecl>(LexicalD);
if (!ND || !needsAnonymousDeclarationNumber(ND))
continue;
Visit(ND, Index++);
}
}
} // namespace serialization
} // namespace clang
#endif

View File

@ -0,0 +1 @@
4ed822e04f6c8189744464721eea51f8d9810a05

View File

@ -0,0 +1 @@
efbaf92a849ae370dc54a0243f6b3e8ef8dd7a3f

View File

@ -0,0 +1,293 @@
//===- ASTReaderInternals.h - AST Reader Internals --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides internal definitions used in the AST reader.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#include "MultiOnDiskHashTable.h"
#include "clang/AST/DeclarationName.h"
#include "clang/Basic/LLVM.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/OnDiskHashTable.h"
#include <ctime>
#include <utility>
namespace clang {
class ASTReader;
class FileEntry;
struct HeaderFileInfo;
class HeaderSearch;
class IdentifierTable;
class ObjCMethodDecl;
namespace serialization {
class ModuleFile;
namespace reader {
/// \brief Class that performs name lookup into a DeclContext stored
/// in an AST file.
class ASTDeclContextNameLookupTrait {
ASTReader &Reader;
ModuleFile &F;
public:
// Maximum number of lookup tables we allow before condensing the tables.
static const int MaxTables = 4;
/// The lookup result is a list of global declaration IDs.
using data_type = SmallVector<DeclID, 4>;
struct data_type_builder {
data_type &Data;
llvm::DenseSet<DeclID> Found;
data_type_builder(data_type &D) : Data(D) {}
void insert(DeclID ID) {
// Just use a linear scan unless we have more than a few IDs.
if (Found.empty() && !Data.empty()) {
if (Data.size() <= 4) {
for (auto I : Found)
if (I == ID)
return;
Data.push_back(ID);
return;
}
// Switch to tracking found IDs in the set.
Found.insert(Data.begin(), Data.end());
}
if (Found.insert(ID).second)
Data.push_back(ID);
}
};
using hash_value_type = unsigned;
using offset_type = unsigned;
using file_type = ModuleFile *;
using external_key_type = DeclarationName;
using internal_key_type = DeclarationNameKey;
explicit ASTDeclContextNameLookupTrait(ASTReader &Reader, ModuleFile &F)
: Reader(Reader), F(F) {}
static bool EqualKey(const internal_key_type &a, const internal_key_type &b) {
return a == b;
}
static hash_value_type ComputeHash(const internal_key_type &Key) {
return Key.getHash();
}
static internal_key_type GetInternalKey(const external_key_type &Name) {
return Name;
}
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char *&d);
internal_key_type ReadKey(const unsigned char *d, unsigned);
void ReadDataInto(internal_key_type, const unsigned char *d,
unsigned DataLen, data_type_builder &Val);
static void MergeDataInto(const data_type &From, data_type_builder &To) {
To.Data.reserve(To.Data.size() + From.size());
for (DeclID ID : From)
To.insert(ID);
}
file_type ReadFileRef(const unsigned char *&d);
};
struct DeclContextLookupTable {
MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table;
};
/// \brief Base class for the trait describing the on-disk hash table for the
/// identifiers in an AST file.
///
/// This class is not useful by itself; rather, it provides common
/// functionality for accessing the on-disk hash table of identifiers
/// in an AST file. Different subclasses customize that functionality
/// based on what information they are interested in. Those subclasses
/// must provide the \c data_type type and the ReadData operation, only.
class ASTIdentifierLookupTraitBase {
public:
using external_key_type = StringRef;
using internal_key_type = StringRef;
using hash_value_type = unsigned;
using offset_type = unsigned;
static bool EqualKey(const internal_key_type& a, const internal_key_type& b) {
return a == b;
}
static hash_value_type ComputeHash(const internal_key_type& a);
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
// This hopefully will just get inlined and removed by the optimizer.
static const internal_key_type&
GetInternalKey(const external_key_type& x) { return x; }
// This hopefully will just get inlined and removed by the optimizer.
static const external_key_type&
GetExternalKey(const internal_key_type& x) { return x; }
static internal_key_type ReadKey(const unsigned char* d, unsigned n);
};
/// \brief Class that performs lookup for an identifier stored in an AST file.
class ASTIdentifierLookupTrait : public ASTIdentifierLookupTraitBase {
ASTReader &Reader;
ModuleFile &F;
// If we know the IdentifierInfo in advance, it is here and we will
// not build a new one. Used when deserializing information about an
// identifier that was constructed before the AST file was read.
IdentifierInfo *KnownII;
public:
using data_type = IdentifierInfo *;
ASTIdentifierLookupTrait(ASTReader &Reader, ModuleFile &F,
IdentifierInfo *II = nullptr)
: Reader(Reader), F(F), KnownII(II) {}
data_type ReadData(const internal_key_type& k,
const unsigned char* d,
unsigned DataLen);
IdentID ReadIdentifierID(const unsigned char *d);
ASTReader &getReader() const { return Reader; }
};
/// \brief The on-disk hash table used to contain information about
/// all of the identifiers in the program.
using ASTIdentifierLookupTable =
llvm::OnDiskIterableChainedHashTable<ASTIdentifierLookupTrait>;
/// \brief Class that performs lookup for a selector's entries in the global
/// method pool stored in an AST file.
class ASTSelectorLookupTrait {
ASTReader &Reader;
ModuleFile &F;
public:
struct data_type {
SelectorID ID;
unsigned InstanceBits;
unsigned FactoryBits;
bool InstanceHasMoreThanOneDecl;
bool FactoryHasMoreThanOneDecl;
SmallVector<ObjCMethodDecl *, 2> Instance;
SmallVector<ObjCMethodDecl *, 2> Factory;
};
using external_key_type = Selector;
using internal_key_type = external_key_type;
using hash_value_type = unsigned;
using offset_type = unsigned;
ASTSelectorLookupTrait(ASTReader &Reader, ModuleFile &F)
: Reader(Reader), F(F) {}
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
return a == b;
}
static hash_value_type ComputeHash(Selector Sel);
static const internal_key_type&
GetInternalKey(const external_key_type& x) { return x; }
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
internal_key_type ReadKey(const unsigned char* d, unsigned);
data_type ReadData(Selector, const unsigned char* d, unsigned DataLen);
};
/// \brief The on-disk hash table used for the global method pool.
using ASTSelectorLookupTable =
llvm::OnDiskChainedHashTable<ASTSelectorLookupTrait>;
/// \brief Trait class used to search the on-disk hash table containing all of
/// the header search information.
///
/// The on-disk hash table contains a mapping from each header path to
/// information about that header (how many times it has been included, its
/// controlling macro, etc.). Note that we actually hash based on the size
/// and mtime, and support "deep" comparisons of file names based on current
/// inode numbers, so that the search can cope with non-normalized path names
/// and symlinks.
class HeaderFileInfoTrait {
ASTReader &Reader;
ModuleFile &M;
HeaderSearch *HS;
const char *FrameworkStrings;
public:
using external_key_type = const FileEntry *;
struct internal_key_type {
off_t Size;
time_t ModTime;
StringRef Filename;
bool Imported;
};
using internal_key_ref = const internal_key_type &;
using data_type = HeaderFileInfo;
using hash_value_type = unsigned;
using offset_type = unsigned;
HeaderFileInfoTrait(ASTReader &Reader, ModuleFile &M, HeaderSearch *HS,
const char *FrameworkStrings)
: Reader(Reader), M(M), HS(HS), FrameworkStrings(FrameworkStrings) {}
static hash_value_type ComputeHash(internal_key_ref ikey);
internal_key_type GetInternalKey(const FileEntry *FE);
bool EqualKey(internal_key_ref a, internal_key_ref b);
static std::pair<unsigned, unsigned>
ReadKeyDataLength(const unsigned char*& d);
static internal_key_type ReadKey(const unsigned char *d, unsigned);
data_type ReadData(internal_key_ref,const unsigned char *d, unsigned DataLen);
};
/// \brief The on-disk hash table used for known header files.
using HeaderFileInfoLookupTable =
llvm::OnDiskChainedHashTable<HeaderFileInfoTrait>;
} // namespace reader
} // namespace serialization
} // namespace clang
#endif // LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H

View File

@ -0,0 +1 @@
6163b811c7691d4aa9a5422fe6f86b50f682a472

View File

@ -0,0 +1 @@
1e72ced2ee364bdee8e8f7c8d32e4ada1f590e68

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
set(LLVM_LINK_COMPONENTS
BitReader
Support
)
add_clang_library(clangSerialization
ASTCommon.cpp
ASTReader.cpp
ASTReaderDecl.cpp
ASTReaderStmt.cpp
ASTWriter.cpp
ASTWriterDecl.cpp
ASTWriterStmt.cpp
GeneratePCH.cpp
GlobalModuleIndex.cpp
Module.cpp
ModuleFileExtension.cpp
ModuleManager.cpp
ADDITIONAL_HEADERS
ASTCommon.h
ASTReaderInternals.h
LINK_LIBS
clangAST
clangBasic
clangLex
clangSema
)

View File

@ -0,0 +1,76 @@
//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PCHGenerator, which as a SemaConsumer that generates
// a PCH file.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/Bitcode/BitstreamWriter.h"
using namespace clang;
PCHGenerator::PCHGenerator(
const Preprocessor &PP, StringRef OutputFile, StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors, bool IncludeTimestamps)
: PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
Writer(Stream, this->Buffer->Data, PP.getPCMCache(), Extensions,
IncludeTimestamps),
AllowASTWithErrors(AllowASTWithErrors) {
this->Buffer->IsComplete = false;
}
PCHGenerator::~PCHGenerator() {
}
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
// Don't create a PCH if there were fatal failures during module loading.
if (PP.getModuleLoader().HadFatalFailure)
return;
bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
if (hasErrors && !AllowASTWithErrors)
return;
Module *Module = nullptr;
if (PP.getLangOpts().isCompilingModule()) {
Module = PP.getHeaderSearchInfo().lookupModule(
PP.getLangOpts().CurrentModule, /*AllowSearch*/ false);
if (!Module) {
assert(hasErrors && "emitting module but current module doesn't exist");
return;
}
}
// Emit the PCH file to the Buffer.
assert(SemaPtr && "No Sema?");
Buffer->Signature =
Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
// For serialization we are lenient if the errors were
// only warn-as-error kind.
PP.getDiagnostics().hasUncompilableErrorOccurred());
Buffer->IsComplete = true;
}
ASTMutationListener *PCHGenerator::GetASTMutationListener() {
return &Writer;
}
ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
return &Writer;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
//===--- Module.cpp - Module description ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Module class, which describes a module that has
// been loaded from an AST file.
//
//===----------------------------------------------------------------------===//
#include "clang/Serialization/Module.h"
#include "ASTReaderInternals.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace serialization;
using namespace reader;
ModuleFile::~ModuleFile() {
delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable);
delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
}
template<typename Key, typename Offset, unsigned InitialCapacity>
static void
dumpLocalRemap(StringRef Name,
const ContinuousRangeMap<Key, Offset, InitialCapacity> &Map) {
if (Map.begin() == Map.end())
return;
typedef ContinuousRangeMap<Key, Offset, InitialCapacity> MapType;
llvm::errs() << " " << Name << ":\n";
for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
I != IEnd; ++I) {
llvm::errs() << " " << I->first << " -> " << I->second << "\n";
}
}
LLVM_DUMP_METHOD void ModuleFile::dump() {
llvm::errs() << "\nModule: " << FileName << "\n";
if (!Imports.empty()) {
llvm::errs() << " Imports: ";
for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
if (I)
llvm::errs() << ", ";
llvm::errs() << Imports[I]->FileName;
}
llvm::errs() << "\n";
}
// Remapping tables.
llvm::errs() << " Base source location offset: " << SLocEntryBaseOffset
<< '\n';
dumpLocalRemap("Source location offset local -> global map", SLocRemap);
llvm::errs() << " Base identifier ID: " << BaseIdentifierID << '\n'
<< " Number of identifiers: " << LocalNumIdentifiers << '\n';
dumpLocalRemap("Identifier ID local -> global map", IdentifierRemap);
llvm::errs() << " Base macro ID: " << BaseMacroID << '\n'
<< " Number of macros: " << LocalNumMacros << '\n';
dumpLocalRemap("Macro ID local -> global map", MacroRemap);
llvm::errs() << " Base submodule ID: " << BaseSubmoduleID << '\n'
<< " Number of submodules: " << LocalNumSubmodules << '\n';
dumpLocalRemap("Submodule ID local -> global map", SubmoduleRemap);
llvm::errs() << " Base selector ID: " << BaseSelectorID << '\n'
<< " Number of selectors: " << LocalNumSelectors << '\n';
dumpLocalRemap("Selector ID local -> global map", SelectorRemap);
llvm::errs() << " Base preprocessed entity ID: " << BasePreprocessedEntityID
<< '\n'
<< " Number of preprocessed entities: "
<< NumPreprocessedEntities << '\n';
dumpLocalRemap("Preprocessed entity ID local -> global map",
PreprocessedEntityRemap);
llvm::errs() << " Base type index: " << BaseTypeIndex << '\n'
<< " Number of types: " << LocalNumTypes << '\n';
dumpLocalRemap("Type index local -> global map", TypeRemap);
llvm::errs() << " Base decl ID: " << BaseDeclID << '\n'
<< " Number of decls: " << LocalNumDecls << '\n';
dumpLocalRemap("Decl ID local -> global map", DeclRemap);
}

View File

@ -0,0 +1,21 @@
//===-- ModuleFileExtension.cpp - Module File Extensions ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/Hashing.h"
using namespace clang;
ModuleFileExtension::~ModuleFileExtension() { }
llvm::hash_code ModuleFileExtension::hashExtension(llvm::hash_code Code) const {
return Code;
}
ModuleFileExtensionWriter::~ModuleFileExtensionWriter() { }
ModuleFileExtensionReader::~ModuleFileExtensionReader() { }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,347 @@
//===- MultiOnDiskHashTable.h - Merged set of hash tables -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a hash table data structure suitable for incremental and
// distributed storage across a set of files.
//
// Multiple hash tables from different files are implicitly merged to improve
// performance, and on reload the merged table will override those from other
// files.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
#define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
#include <vector>
namespace clang {
namespace serialization {
/// \brief A collection of on-disk hash tables, merged when relevant for performance.
template<typename Info> class MultiOnDiskHashTable {
public:
/// A handle to a file, used when overriding tables.
using file_type = typename Info::file_type;
/// A pointer to an on-disk representation of the hash table.
using storage_type = const unsigned char *;
using external_key_type = typename Info::external_key_type;
using internal_key_type = typename Info::internal_key_type;
using data_type = typename Info::data_type;
using data_type_builder = typename Info::data_type_builder;
using hash_value_type = unsigned;
private:
/// The generator is permitted to read our merged table.
template<typename ReaderInfo, typename WriterInfo>
friend class MultiOnDiskHashTableGenerator;
/// \brief A hash table stored on disk.
struct OnDiskTable {
using HashTable = llvm::OnDiskIterableChainedHashTable<Info>;
file_type File;
HashTable Table;
OnDiskTable(file_type File, unsigned NumBuckets, unsigned NumEntries,
storage_type Buckets, storage_type Payload, storage_type Base,
const Info &InfoObj)
: File(File),
Table(NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj) {}
};
struct MergedTable {
std::vector<file_type> Files;
llvm::DenseMap<internal_key_type, data_type> Data;
};
using Table = llvm::PointerUnion<OnDiskTable *, MergedTable *>;
using TableVector = llvm::TinyPtrVector<void *>;
/// \brief The current set of on-disk and merged tables.
/// We manually store the opaque value of the Table because TinyPtrVector
/// can't cope with holding a PointerUnion directly.
/// There can be at most one MergedTable in this vector, and if present,
/// it is the first table.
TableVector Tables;
/// \brief Files corresponding to overridden tables that we've not yet
/// discarded.
llvm::TinyPtrVector<file_type> PendingOverrides;
struct AsOnDiskTable {
using result_type = OnDiskTable *;
result_type operator()(void *P) const {
return Table::getFromOpaqueValue(P).template get<OnDiskTable *>();
}
};
using table_iterator =
llvm::mapped_iterator<TableVector::iterator, AsOnDiskTable>;
using table_range = llvm::iterator_range<table_iterator>;
/// \brief The current set of on-disk tables.
table_range tables() {
auto Begin = Tables.begin(), End = Tables.end();
if (getMergedTable())
++Begin;
return llvm::make_range(llvm::map_iterator(Begin, AsOnDiskTable()),
llvm::map_iterator(End, AsOnDiskTable()));
}
MergedTable *getMergedTable() const {
// If we already have a merged table, it's the first one.
return Tables.empty() ? nullptr : Table::getFromOpaqueValue(*Tables.begin())
.template dyn_cast<MergedTable*>();
}
/// \brief Delete all our current on-disk tables.
void clear() {
for (auto *T : tables())
delete T;
if (auto *M = getMergedTable())
delete M;
Tables.clear();
}
void removeOverriddenTables() {
llvm::DenseSet<file_type> Files;
Files.insert(PendingOverrides.begin(), PendingOverrides.end());
// Explicitly capture Files to work around an MSVC 2015 rejects-valid bug.
auto ShouldRemove = [&Files](void *T) -> bool {
auto *ODT = Table::getFromOpaqueValue(T).template get<OnDiskTable *>();
bool Remove = Files.count(ODT->File);
if (Remove)
delete ODT;
return Remove;
};
Tables.erase(std::remove_if(tables().begin().getCurrent(), Tables.end(),
ShouldRemove),
Tables.end());
PendingOverrides.clear();
}
void condense() {
MergedTable *Merged = getMergedTable();
if (!Merged)
Merged = new MergedTable;
// Read in all the tables and merge them together.
// FIXME: Be smarter about which tables we merge.
for (auto *ODT : tables()) {
auto &HT = ODT->Table;
Info &InfoObj = HT.getInfoObj();
for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {
auto *LocalPtr = I.getItem();
// FIXME: Don't rely on the OnDiskHashTable format here.
auto L = InfoObj.ReadKeyDataLength(LocalPtr);
const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);
data_type_builder ValueBuilder(Merged->Data[Key]);
InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second,
ValueBuilder);
}
Merged->Files.push_back(ODT->File);
delete ODT;
}
Tables.clear();
Tables.push_back(Table(Merged).getOpaqueValue());
}
public:
MultiOnDiskHashTable() = default;
MultiOnDiskHashTable(MultiOnDiskHashTable &&O)
: Tables(std::move(O.Tables)),
PendingOverrides(std::move(O.PendingOverrides)) {
O.Tables.clear();
}
MultiOnDiskHashTable &operator=(MultiOnDiskHashTable &&O) {
if (&O == this)
return *this;
clear();
Tables = std::move(O.Tables);
O.Tables.clear();
PendingOverrides = std::move(O.PendingOverrides);
return *this;
}
~MultiOnDiskHashTable() { clear(); }
/// \brief Add the table \p Data loaded from file \p File.
void add(file_type File, storage_type Data, Info InfoObj = Info()) {
using namespace llvm::support;
storage_type Ptr = Data;
uint32_t BucketOffset = endian::readNext<uint32_t, little, unaligned>(Ptr);
// Read the list of overridden files.
uint32_t NumFiles = endian::readNext<uint32_t, little, unaligned>(Ptr);
// FIXME: Add a reserve() to TinyPtrVector so that we don't need to make
// an additional copy.
llvm::SmallVector<file_type, 16> OverriddenFiles;
OverriddenFiles.reserve(NumFiles);
for (/**/; NumFiles != 0; --NumFiles)
OverriddenFiles.push_back(InfoObj.ReadFileRef(Ptr));
PendingOverrides.insert(PendingOverrides.end(), OverriddenFiles.begin(),
OverriddenFiles.end());
// Read the OnDiskChainedHashTable header.
storage_type Buckets = Data + BucketOffset;
auto NumBucketsAndEntries =
OnDiskTable::HashTable::readNumBucketsAndEntries(Buckets);
// Register the table.
Table NewTable = new OnDiskTable(File, NumBucketsAndEntries.first,
NumBucketsAndEntries.second,
Buckets, Ptr, Data, std::move(InfoObj));
Tables.push_back(NewTable.getOpaqueValue());
}
/// \brief Find and read the lookup results for \p EKey.
data_type find(const external_key_type &EKey) {
data_type Result;
if (!PendingOverrides.empty())
removeOverriddenTables();
if (Tables.size() > static_cast<unsigned>(Info::MaxTables))
condense();
internal_key_type Key = Info::GetInternalKey(EKey);
auto KeyHash = Info::ComputeHash(Key);
if (MergedTable *M = getMergedTable()) {
auto It = M->Data.find(Key);
if (It != M->Data.end())
Result = It->second;
}
data_type_builder ResultBuilder(Result);
for (auto *ODT : tables()) {
auto &HT = ODT->Table;
auto It = HT.find_hashed(Key, KeyHash);
if (It != HT.end())
HT.getInfoObj().ReadDataInto(Key, It.getDataPtr(), It.getDataLen(),
ResultBuilder);
}
return Result;
}
/// \brief Read all the lookup results into a single value. This only makes
/// sense if merging values across keys is meaningful.
data_type findAll() {
data_type Result;
data_type_builder ResultBuilder(Result);
if (!PendingOverrides.empty())
removeOverriddenTables();
if (MergedTable *M = getMergedTable()) {
for (auto &KV : M->Data)
Info::MergeDataInto(KV.second, ResultBuilder);
}
for (auto *ODT : tables()) {
auto &HT = ODT->Table;
Info &InfoObj = HT.getInfoObj();
for (auto I = HT.data_begin(), E = HT.data_end(); I != E; ++I) {
auto *LocalPtr = I.getItem();
// FIXME: Don't rely on the OnDiskHashTable format here.
auto L = InfoObj.ReadKeyDataLength(LocalPtr);
const internal_key_type &Key = InfoObj.ReadKey(LocalPtr, L.first);
InfoObj.ReadDataInto(Key, LocalPtr + L.first, L.second, ResultBuilder);
}
}
return Result;
}
};
/// \brief Writer for the on-disk hash table.
template<typename ReaderInfo, typename WriterInfo>
class MultiOnDiskHashTableGenerator {
using BaseTable = MultiOnDiskHashTable<ReaderInfo>;
using Generator = llvm::OnDiskChainedHashTableGenerator<WriterInfo>;
Generator Gen;
public:
MultiOnDiskHashTableGenerator() : Gen() {}
void insert(typename WriterInfo::key_type_ref Key,
typename WriterInfo::data_type_ref Data, WriterInfo &Info) {
Gen.insert(Key, Data, Info);
}
void emit(llvm::SmallVectorImpl<char> &Out, WriterInfo &Info,
const BaseTable *Base) {
using namespace llvm::support;
llvm::raw_svector_ostream OutStream(Out);
// Write our header information.
{
endian::Writer<little> Writer(OutStream);
// Reserve four bytes for the bucket offset.
Writer.write<uint32_t>(0);
if (auto *Merged = Base ? Base->getMergedTable() : nullptr) {
// Write list of overridden files.
Writer.write<uint32_t>(Merged->Files.size());
for (const auto &F : Merged->Files)
Info.EmitFileRef(OutStream, F);
// Add all merged entries from Base to the generator.
for (auto &KV : Merged->Data) {
if (!Gen.contains(KV.first, Info))
Gen.insert(KV.first, Info.ImportData(KV.second), Info);
}
} else {
Writer.write<uint32_t>(0);
}
}
// Write the table itself.
uint32_t BucketOffset = Gen.Emit(OutStream, Info);
// Replace the first four bytes with the bucket offset.
endian::write32le(Out.data(), BucketOffset);
}
};
} // namespace serialization
} // namespace clang
#endif // LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H