[Support] Replace HashString with djbHash.

This removes the HashString function from StringExtraces and replaces
its uses with calls to djbHash from DJB.h

This is *almost* NFC. While the algorithm is identical, the djbHash
implementation in StringExtras used 0 as its seed while the
implementation in DJB uses 5381. The latter has been shown to result in
less collisions and improved avalanching.

https://reviews.llvm.org/D43615
(cherry picked from commit 77f7f965bc9499a9ae768a296ca5a1f7347d1d2c)

llvm-svn: 326081
This commit is contained in:
Jonas Devlieghere 2018-02-26 11:30:13 +00:00
parent b84e158df7
commit b9ad175935
11 changed files with 210 additions and 221 deletions

View File

@ -35,9 +35,9 @@
#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h" #include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSet.h"
#include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Host.h" #include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h" #include "llvm/Support/Mutex.h"
@ -185,7 +185,7 @@ static std::atomic<unsigned> ActiveASTUnitObjects;
ASTUnit::ASTUnit(bool _MainFileIsAST) ASTUnit::ASTUnit(bool _MainFileIsAST)
: Reader(nullptr), HadModuleLoaderFatalFailure(false), : Reader(nullptr), HadModuleLoaderFatalFailure(false),
OnlyLocalDecls(false), CaptureDiagnostics(false), OnlyLocalDecls(false), CaptureDiagnostics(false),
MainFileIsAST(_MainFileIsAST), MainFileIsAST(_MainFileIsAST),
TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")), TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
OwnsRemappedFileBuffers(true), OwnsRemappedFileBuffers(true),
NumStoredDiagnosticsFromDriver(0), NumStoredDiagnosticsFromDriver(0),
@ -196,7 +196,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
CompletionCacheTopLevelHashValue(0), CompletionCacheTopLevelHashValue(0),
PreambleTopLevelHashValue(0), PreambleTopLevelHashValue(0),
CurrentTopLevelHashValue(0), CurrentTopLevelHashValue(0),
UnsafeToFree(false) { UnsafeToFree(false) {
if (getenv("LIBCLANG_OBJTRACKING")) if (getenv("LIBCLANG_OBJTRACKING"))
fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects); fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);
} }
@ -219,8 +219,8 @@ ASTUnit::~ASTUnit() {
delete RB.second; delete RB.second;
} }
ClearCachedCompletionResults(); ClearCachedCompletionResults();
if (getenv("LIBCLANG_OBJTRACKING")) if (getenv("LIBCLANG_OBJTRACKING"))
fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects); fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);
} }
@ -229,20 +229,20 @@ void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
this->PP = std::move(PP); this->PP = std::move(PP);
} }
/// \brief Determine the set of code-completion contexts in which this /// \brief Determine the set of code-completion contexts in which this
/// declaration should be shown. /// declaration should be shown.
static unsigned getDeclShowContexts(const NamedDecl *ND, static unsigned getDeclShowContexts(const NamedDecl *ND,
const LangOptions &LangOpts, const LangOptions &LangOpts,
bool &IsNestedNameSpecifier) { bool &IsNestedNameSpecifier) {
IsNestedNameSpecifier = false; IsNestedNameSpecifier = false;
if (isa<UsingShadowDecl>(ND)) if (isa<UsingShadowDecl>(ND))
ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl()); ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
if (!ND) if (!ND)
return 0; return 0;
uint64_t Contexts = 0; uint64_t Contexts = 0;
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) || isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||
isa<TypeAliasTemplateDecl>(ND)) { isa<TypeAliasTemplateDecl>(ND)) {
// Types can appear in these contexts. // Types can appear in these contexts.
@ -257,12 +257,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
// In C++, types can appear in expressions contexts (for functional casts). // In C++, types can appear in expressions contexts (for functional casts).
if (LangOpts.CPlusPlus) if (LangOpts.CPlusPlus)
Contexts |= (1LL << CodeCompletionContext::CCC_Expression); Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
// In Objective-C, message sends can send interfaces. In Objective-C++, // In Objective-C, message sends can send interfaces. In Objective-C++,
// all types are available due to functional casts. // all types are available due to functional casts.
if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
// In Objective-C, you can only be a subclass of another Objective-C class // In Objective-C, you can only be a subclass of another Objective-C class
if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
// Objective-C interfaces can be used in a class property expression. // Objective-C interfaces can be used in a class property expression.
@ -274,7 +274,7 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
// Deal with tag names. // Deal with tag names.
if (isa<EnumDecl>(ND)) { if (isa<EnumDecl>(ND)) {
Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag); Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);
// Part of the nested-name-specifier in C++0x. // Part of the nested-name-specifier in C++0x.
if (LangOpts.CPlusPlus11) if (LangOpts.CPlusPlus11)
IsNestedNameSpecifier = true; IsNestedNameSpecifier = true;
@ -283,7 +283,7 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag); Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
else else
Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag); Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
if (LangOpts.CPlusPlus) if (LangOpts.CPlusPlus)
IsNestedNameSpecifier = true; IsNestedNameSpecifier = true;
} else if (isa<ClassTemplateDecl>(ND)) } else if (isa<ClassTemplateDecl>(ND))
@ -300,24 +300,24 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName); Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);
} else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
Contexts = (1LL << CodeCompletionContext::CCC_Namespace); Contexts = (1LL << CodeCompletionContext::CCC_Namespace);
// Part of the nested-name-specifier. // Part of the nested-name-specifier.
IsNestedNameSpecifier = true; IsNestedNameSpecifier = true;
} }
return Contexts; return Contexts;
} }
void ASTUnit::CacheCodeCompletionResults() { void ASTUnit::CacheCodeCompletionResults() {
if (!TheSema) if (!TheSema)
return; return;
SimpleTimer Timer(WantTiming); SimpleTimer Timer(WantTiming);
Timer.setOutput("Cache global code completions for " + getMainFileName()); Timer.setOutput("Cache global code completions for " + getMainFileName());
// Clear out the previous results. // Clear out the previous results.
ClearCachedCompletionResults(); ClearCachedCompletionResults();
// Gather the set of global code completions. // Gather the set of global code completions.
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
SmallVector<Result, 8> Results; SmallVector<Result, 8> Results;
@ -325,7 +325,7 @@ void ASTUnit::CacheCodeCompletionResults() {
CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator); CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);
TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator,
CCTUInfo, Results); CCTUInfo, Results);
// Translate global code completions into cached completions. // Translate global code completions into cached completions.
llvm::DenseMap<CanQualType, unsigned> CompletionTypes; llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel); CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
@ -344,7 +344,7 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedResult.Kind = R.CursorKind; CachedResult.Kind = R.CursorKind;
CachedResult.Availability = R.Availability; CachedResult.Availability = R.Availability;
// Keep track of the type of this completion in an ASTContext-agnostic // Keep track of the type of this completion in an ASTContext-agnostic
// way. // way.
QualType UsageType = getDeclUsageType(*Ctx, R.Declaration); QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);
if (UsageType.isNull()) { if (UsageType.isNull()) {
@ -356,7 +356,7 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType); CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
// Determine whether we have already seen this type. If so, we save // Determine whether we have already seen this type. If so, we save
// ourselves the work of formatting the type string by using the // ourselves the work of formatting the type string by using the
// temporary, CanQualType-based hash table to find the associated value. // temporary, CanQualType-based hash table to find the associated value.
unsigned &TypeValue = CompletionTypes[CanUsageType]; unsigned &TypeValue = CompletionTypes[CanUsageType];
if (TypeValue == 0) { if (TypeValue == 0) {
@ -364,12 +364,12 @@ void ASTUnit::CacheCodeCompletionResults() {
CachedCompletionTypes[QualType(CanUsageType).getAsString()] CachedCompletionTypes[QualType(CanUsageType).getAsString()]
= TypeValue; = TypeValue;
} }
CachedResult.Type = TypeValue; CachedResult.Type = TypeValue;
} }
CachedCompletionResults.push_back(CachedResult); CachedCompletionResults.push_back(CachedResult);
/// Handle nested-name-specifiers in C++. /// Handle nested-name-specifiers in C++.
if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier && if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&
!R.StartsNestedNameSpecifier) { !R.StartsNestedNameSpecifier) {
@ -392,10 +392,10 @@ void ASTUnit::CacheCodeCompletionResults() {
isa<NamespaceAliasDecl>(R.Declaration)) isa<NamespaceAliasDecl>(R.Declaration))
NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace); NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
if (unsigned RemainingContexts if (unsigned RemainingContexts
= NNSContexts & ~CachedResult.ShowInContexts) { = NNSContexts & ~CachedResult.ShowInContexts) {
// If there any contexts where this completion can be a // If there any contexts where this completion can be a
// nested-name-specifier but isn't already an option, create a // nested-name-specifier but isn't already an option, create a
// nested-name-specifier completion. // nested-name-specifier completion.
R.StartsNestedNameSpecifier = true; R.StartsNestedNameSpecifier = true;
CachedResult.Completion = R.CreateCodeCompletionString( CachedResult.Completion = R.CreateCodeCompletionString(
@ -410,13 +410,13 @@ void ASTUnit::CacheCodeCompletionResults() {
} }
break; break;
} }
case Result::RK_Keyword: case Result::RK_Keyword:
case Result::RK_Pattern: case Result::RK_Pattern:
// Ignore keywords and patterns; we don't care, since they are so // Ignore keywords and patterns; we don't care, since they are so
// easily regenerated. // easily regenerated.
break; break;
case Result::RK_Macro: { case Result::RK_Macro: {
CachedCodeCompletionResult CachedResult; CachedCodeCompletionResult CachedResult;
CachedResult.Completion = R.CreateCodeCompletionString( CachedResult.Completion = R.CreateCodeCompletionString(
@ -446,7 +446,7 @@ void ASTUnit::CacheCodeCompletionResults() {
} }
} }
} }
// Save the current top-level hash value. // Save the current top-level hash value.
CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue; CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
} }
@ -486,10 +486,10 @@ public:
bool AllowCompatibleDifferences) override { bool AllowCompatibleDifferences) override {
if (InitializedLanguage) if (InitializedLanguage)
return false; return false;
LangOpt = LangOpts; LangOpt = LangOpts;
InitializedLanguage = true; InitializedLanguage = true;
updated(); updated();
return false; return false;
} }
@ -798,14 +798,14 @@ namespace {
/// \brief Add the given macro to the hash of all top-level entities. /// \brief Add the given macro to the hash of all top-level entities.
void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) { void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash); Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);
} }
/// \brief Preprocessor callback class that updates a hash value with the names /// \brief Preprocessor callback class that updates a hash value with the names
/// of all macros that have been defined by the translation unit. /// of all macros that have been defined by the translation unit.
class MacroDefinitionTrackerPPCallbacks : public PPCallbacks { class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
unsigned &Hash; unsigned &Hash;
public: public:
explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { } explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
@ -819,11 +819,11 @@ public:
void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
if (!D) if (!D)
return; return;
DeclContext *DC = D->getDeclContext(); DeclContext *DC = D->getDeclContext();
if (!DC) if (!DC)
return; return;
if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit())) if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
return; return;
@ -834,16 +834,16 @@ void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
if (!EnumD->isScoped()) { if (!EnumD->isScoped()) {
for (const auto *EI : EnumD->enumerators()) { for (const auto *EI : EnumD->enumerators()) {
if (EI->getIdentifier()) if (EI->getIdentifier())
Hash = llvm::HashString(EI->getIdentifier()->getName(), Hash); Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);
} }
} }
} }
if (ND->getIdentifier()) if (ND->getIdentifier())
Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash); Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);
else if (DeclarationName Name = ND->getDeclName()) { else if (DeclarationName Name = ND->getDeclName()) {
std::string NameStr = Name.getAsString(); std::string NameStr = Name.getAsString();
Hash = llvm::HashString(NameStr, Hash); Hash = llvm::djbHash(NameStr, Hash);
} }
return; return;
} }
@ -851,7 +851,7 @@ void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D)) { if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D)) {
if (Module *Mod = ImportD->getImportedModule()) { if (Module *Mod = ImportD->getImportedModule()) {
std::string ModName = Mod->getFullModuleName(); std::string ModName = Mod->getFullModuleName();
Hash = llvm::HashString(ModName, Hash); Hash = llvm::djbHash(ModName, Hash);
} }
return; return;
} }
@ -860,7 +860,7 @@ void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
class TopLevelDeclTrackerConsumer : public ASTConsumer { class TopLevelDeclTrackerConsumer : public ASTConsumer {
ASTUnit &Unit; ASTUnit &Unit;
unsigned &Hash; unsigned &Hash;
public: public:
TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash) TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
: Unit(_Unit), Hash(Hash) { : Unit(_Unit), Hash(Hash) {
@ -933,7 +933,7 @@ public:
bool hasCodeCompletionSupport() const override { return false; } bool hasCodeCompletionSupport() const override { return false; }
TranslationUnitKind getTranslationUnitKind() override { TranslationUnitKind getTranslationUnitKind() override {
return Unit.getTranslationUnitKind(); return Unit.getTranslationUnitKind();
} }
}; };
@ -1052,11 +1052,11 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
Clang->setInvocation(CCInvocation); Clang->setInvocation(CCInvocation);
OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics that would // Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped. // otherwise be dropped.
Clang->setDiagnostics(&getDiagnostics()); Clang->setDiagnostics(&getDiagnostics());
// Create the target instance. // Create the target instance.
Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
@ -1068,7 +1068,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// FIXME: We shouldn't need to do this, the target should be immutable once // FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere. // created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts()); Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 && assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!"); "Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@ -1097,10 +1097,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Create a file manager object to provide access to and cache the filesystem. // Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(&getFileManager()); Clang->setFileManager(&getFileManager());
// Create the source manager. // Create the source manager.
Clang->setSourceManager(&getSourceManager()); Clang->setSourceManager(&getSourceManager());
// If the main file has been overridden due to the use of a preamble, // If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble. // make that override happen and introduce the preamble.
if (OverrideMainBuffer) { if (OverrideMainBuffer) {
@ -1135,7 +1135,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
goto error; goto error;
transferASTDataFromCompilerInstance(*Clang); transferASTDataFromCompilerInstance(*Clang);
Act->EndSourceFile(); Act->EndSourceFile();
FailedParseDiagnostics.clear(); FailedParseDiagnostics.clear();
@ -1204,10 +1204,10 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
/// the source file. /// the source file.
/// ///
/// This routine will compute the preamble of the main source file. If a /// This routine will compute the preamble of the main source file. If a
/// non-trivial preamble is found, it will precompile that preamble into a /// non-trivial preamble is found, it will precompile that preamble into a
/// precompiled header so that the precompiled preamble can be used to reduce /// precompiled header so that the precompiled preamble can be used to reduce
/// reparsing time. If a precompiled preamble has already been constructed, /// reparsing time. If a precompiled preamble has already been constructed,
/// this routine will determine if it is still valid and, if so, avoid /// this routine will determine if it is still valid and, if so, avoid
/// rebuilding the precompiled preamble. /// rebuilding the precompiled preamble.
/// ///
/// \param AllowRebuild When true (the default), this routine is /// \param AllowRebuild When true (the default), this routine is
@ -1442,7 +1442,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
if (!AST) if (!AST)
return nullptr; return nullptr;
} }
if (!ResourceFilesPath.empty()) { if (!ResourceFilesPath.empty()) {
// Override the resources path. // Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
@ -1478,11 +1478,11 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
Clang->setInvocation(std::move(CI)); Clang->setInvocation(std::move(CI));
AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics that would // Set up diagnostics, capturing any diagnostics that would
// otherwise be dropped. // otherwise be dropped.
Clang->setDiagnostics(&AST->getDiagnostics()); Clang->setDiagnostics(&AST->getDiagnostics());
// Create the target instance. // Create the target instance.
Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
@ -1494,7 +1494,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// FIXME: We shouldn't need to do this, the target should be immutable once // FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere. // created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts()); Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 && assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!"); "Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@ -1512,7 +1512,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// Create a file manager object to provide access to and cache the filesystem. // Create a file manager object to provide access to and cache the filesystem.
Clang->setFileManager(&AST->getFileManager()); Clang->setFileManager(&AST->getFileManager());
// Create the source manager. // Create the source manager.
Clang->setSourceManager(&AST->getSourceManager()); Clang->setSourceManager(&AST->getSourceManager());
@ -1558,7 +1558,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
// Steal the created target, context, and preprocessor. // Steal the created target, context, and preprocessor.
AST->transferASTDataFromCompilerInstance(*Clang); AST->transferASTDataFromCompilerInstance(*Clang);
Act->EndSourceFile(); Act->EndSourceFile();
if (OwnAST) if (OwnAST)
@ -1623,7 +1623,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
AST->FileSystemOpts = FileMgr->getFileSystemOpts(); AST->FileSystemOpts = FileMgr->getFileSystemOpts();
AST->FileMgr = FileMgr; AST->FileMgr = FileMgr;
AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->UserFilesAreVolatile = UserFilesAreVolatile;
// Recover resources if we crash before exiting this method. // Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
ASTUnitCleanup(AST.get()); ASTUnitCleanup(AST.get());
@ -1676,7 +1676,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
PPOpts.SingleFileParseMode = SingleFileParse; PPOpts.SingleFileParseMode = SingleFileParse;
// Override the resources path. // Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
@ -1745,7 +1745,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
} }
clearFileLevelDecls(); clearFileLevelDecls();
SimpleTimer ParsingTimer(WantTiming); SimpleTimer ParsingTimer(WantTiming);
ParsingTimer.setOutput("Reparsing " + getMainFileName()); ParsingTimer.setOutput("Reparsing " + getMainFileName());
@ -1779,7 +1779,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
bool Result = bool Result =
Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
// If we're caching global code-completion results, and the top-level // If we're caching global code-completion results, and the top-level
// declarations have changed, clear out the code-completion cache. // declarations have changed, clear out the code-completion cache.
if (!Result && ShouldCacheCodeCompletionResults && if (!Result && ShouldCacheCodeCompletionResults &&
CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue) CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
@ -1788,7 +1788,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// We now need to clear out the completion info related to this translation // We now need to clear out the completion info related to this translation
// unit; it'll be recreated if necessary. // unit; it'll be recreated if necessary.
CCTUInfo.reset(); CCTUInfo.reset();
return Result; return Result;
} }
@ -1812,21 +1812,21 @@ void ASTUnit::ResetForParse() {
namespace { namespace {
/// \brief Code completion consumer that combines the cached code-completion /// \brief Code completion consumer that combines the cached code-completion
/// results from an ASTUnit with the code-completion results provided to it, /// results from an ASTUnit with the code-completion results provided to it,
/// then passes the result on to /// then passes the result on to
class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer { class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
uint64_t NormalContexts; uint64_t NormalContexts;
ASTUnit &AST; ASTUnit &AST;
CodeCompleteConsumer &Next; CodeCompleteConsumer &Next;
public: public:
AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
const CodeCompleteOptions &CodeCompleteOpts) const CodeCompleteOptions &CodeCompleteOpts)
: CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()), : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()),
AST(AST), Next(Next) AST(AST), Next(Next)
{ {
// Compute the set of contexts in which we will look when we don't have // Compute the set of contexts in which we will look when we don't have
// any information about the specific context. // any information about the specific context.
NormalContexts NormalContexts
= (1LL << CodeCompletionContext::CCC_TopLevel) = (1LL << CodeCompletionContext::CCC_TopLevel)
| (1LL << CodeCompletionContext::CCC_ObjCInterface) | (1LL << CodeCompletionContext::CCC_ObjCInterface)
| (1LL << CodeCompletionContext::CCC_ObjCImplementation) | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
@ -1895,13 +1895,13 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
case CodeCompletionContext::CCC_ParenthesizedExpression: case CodeCompletionContext::CCC_ParenthesizedExpression:
case CodeCompletionContext::CCC_ObjCInterfaceName: case CodeCompletionContext::CCC_ObjCInterfaceName:
break; break;
case CodeCompletionContext::CCC_EnumTag: case CodeCompletionContext::CCC_EnumTag:
case CodeCompletionContext::CCC_UnionTag: case CodeCompletionContext::CCC_UnionTag:
case CodeCompletionContext::CCC_ClassOrStructTag: case CodeCompletionContext::CCC_ClassOrStructTag:
OnlyTagNames = true; OnlyTagNames = true;
break; break;
case CodeCompletionContext::CCC_ObjCProtocolName: case CodeCompletionContext::CCC_ObjCProtocolName:
case CodeCompletionContext::CCC_MacroName: case CodeCompletionContext::CCC_MacroName:
case CodeCompletionContext::CCC_MacroNameUse: case CodeCompletionContext::CCC_MacroNameUse:
@ -1919,12 +1919,12 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
// be hidden. // be hidden.
return; return;
} }
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
for (unsigned I = 0; I != NumResults; ++I) { for (unsigned I = 0; I != NumResults; ++I) {
if (Results[I].Kind != Result::RK_Declaration) if (Results[I].Kind != Result::RK_Declaration)
continue; continue;
unsigned IDNS unsigned IDNS
= Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace(); = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
@ -1932,17 +1932,17 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
if (OnlyTagNames) if (OnlyTagNames)
Hiding = (IDNS & Decl::IDNS_Tag); Hiding = (IDNS & Decl::IDNS_Tag);
else { else {
unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
Decl::IDNS_Namespace | Decl::IDNS_Ordinary | Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
Decl::IDNS_NonMemberOperator); Decl::IDNS_NonMemberOperator);
if (Ctx.getLangOpts().CPlusPlus) if (Ctx.getLangOpts().CPlusPlus)
HiddenIDNS |= Decl::IDNS_Tag; HiddenIDNS |= Decl::IDNS_Tag;
Hiding = (IDNS & HiddenIDNS); Hiding = (IDNS & HiddenIDNS);
} }
if (!Hiding) if (!Hiding)
continue; continue;
DeclarationName Name = Results[I].Declaration->getDeclName(); DeclarationName Name = Results[I].Declaration->getDeclName();
if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo()) if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
HiddenNames.insert(Identifier->getName()); HiddenNames.insert(Identifier->getName());
@ -1954,7 +1954,7 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
CodeCompletionContext Context, CodeCompletionContext Context,
CodeCompletionResult *Results, CodeCompletionResult *Results,
unsigned NumResults) { unsigned NumResults) {
// Merge the results we were given with the results we cached. // Merge the results we were given with the results we cached.
bool AddedResult = false; bool AddedResult = false;
uint64_t InContexts = uint64_t InContexts =
@ -1964,29 +1964,29 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames; llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
typedef CodeCompletionResult Result; typedef CodeCompletionResult Result;
SmallVector<Result, 8> AllResults; SmallVector<Result, 8> AllResults;
for (ASTUnit::cached_completion_iterator for (ASTUnit::cached_completion_iterator
C = AST.cached_completion_begin(), C = AST.cached_completion_begin(),
CEnd = AST.cached_completion_end(); CEnd = AST.cached_completion_end();
C != CEnd; ++C) { C != CEnd; ++C) {
// If the context we are in matches any of the contexts we are // If the context we are in matches any of the contexts we are
// interested in, we'll add this result. // interested in, we'll add this result.
if ((C->ShowInContexts & InContexts) == 0) if ((C->ShowInContexts & InContexts) == 0)
continue; continue;
// If we haven't added any results previously, do so now. // If we haven't added any results previously, do so now.
if (!AddedResult) { if (!AddedResult) {
CalculateHiddenNames(Context, Results, NumResults, S.Context, CalculateHiddenNames(Context, Results, NumResults, S.Context,
HiddenNames); HiddenNames);
AllResults.insert(AllResults.end(), Results, Results + NumResults); AllResults.insert(AllResults.end(), Results, Results + NumResults);
AddedResult = true; AddedResult = true;
} }
// Determine whether this global completion result is hidden by a local // Determine whether this global completion result is hidden by a local
// completion result. If so, skip it. // completion result. If so, skip it.
if (C->Kind != CXCursor_MacroDefinition && if (C->Kind != CXCursor_MacroDefinition &&
HiddenNames.count(C->Completion->getTypedText())) HiddenNames.count(C->Completion->getTypedText()))
continue; continue;
// Adjust priority based on similar type classes. // Adjust priority based on similar type classes.
unsigned Priority = C->Priority; unsigned Priority = C->Priority;
CodeCompletionString *Completion = C->Completion; CodeCompletionString *Completion = C->Completion;
@ -1994,7 +1994,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
if (C->Kind == CXCursor_MacroDefinition) { if (C->Kind == CXCursor_MacroDefinition) {
Priority = getMacroUsagePriority(C->Completion->getTypedText(), Priority = getMacroUsagePriority(C->Completion->getTypedText(),
S.getLangOpts(), S.getLangOpts(),
Context.getPreferredType()->isAnyPointerType()); Context.getPreferredType()->isAnyPointerType());
} else if (C->Type) { } else if (C->Type) {
CanQualType Expected CanQualType Expected
= S.Context.getCanonicalType( = S.Context.getCanonicalType(
@ -2013,7 +2013,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
} }
} }
} }
// Adjust the completion string, if required. // Adjust the completion string, if required.
if (C->Kind == CXCursor_MacroDefinition && if (C->Kind == CXCursor_MacroDefinition &&
Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
@ -2025,18 +2025,18 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
Priority = CCP_CodePattern; Priority = CCP_CodePattern;
Completion = Builder.TakeString(); Completion = Builder.TakeString();
} }
AllResults.push_back(Result(Completion, Priority, C->Kind, AllResults.push_back(Result(Completion, Priority, C->Kind,
C->Availability)); C->Availability));
} }
// If we did not add any cached completion results, just forward the // If we did not add any cached completion results, just forward the
// results we were given to the next consumer. // results we were given to the next consumer.
if (!AddedResult) { if (!AddedResult) {
Next.ProcessCodeCompleteResults(S, Context, Results, NumResults); Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
return; return;
} }
Next.ProcessCodeCompleteResults(S, Context, AllResults.data(), Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
AllResults.size()); AllResults.size());
} }
@ -2093,11 +2093,11 @@ void ASTUnit::CodeComplete(
auto &Inv = *CCInvocation; auto &Inv = *CCInvocation;
Clang->setInvocation(std::move(CCInvocation)); Clang->setInvocation(std::move(CCInvocation));
OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile();
// Set up diagnostics, capturing any diagnostics produced. // Set up diagnostics, capturing any diagnostics produced.
Clang->setDiagnostics(&Diag); Clang->setDiagnostics(&Diag);
CaptureDroppedDiagnostics Capture(true, CaptureDroppedDiagnostics Capture(true,
Clang->getDiagnostics(), Clang->getDiagnostics(),
&StoredDiagnostics, nullptr); &StoredDiagnostics, nullptr);
ProcessWarningOptions(Diag, Inv.getDiagnosticOpts()); ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());
@ -2108,13 +2108,13 @@ void ASTUnit::CodeComplete(
Clang->setInvocation(nullptr); Clang->setInvocation(nullptr);
return; return;
} }
// Inform the target of the language options. // Inform the target of the language options.
// //
// FIXME: We shouldn't need to do this, the target should be immutable once // FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere. // created. This complexity should be lifted elsewhere.
Clang->getTarget().adjust(Clang->getLangOpts()); Clang->getTarget().adjust(Clang->getLangOpts());
assert(Clang->getFrontendOpts().Inputs.size() == 1 && assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!"); "Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@ -2123,7 +2123,7 @@ void ASTUnit::CodeComplete(
assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
InputKind::LLVM_IR && InputKind::LLVM_IR &&
"IR inputs not support here!"); "IR inputs not support here!");
// Use the source and file managers that we were given. // Use the source and file managers that we were given.
Clang->setFileManager(&FileMgr); Clang->setFileManager(&FileMgr);
Clang->setSourceManager(&SourceMgr); Clang->setSourceManager(&SourceMgr);
@ -2210,7 +2210,7 @@ bool ASTUnit::Save(StringRef File) {
if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath)) if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath))
return true; return true;
// FIXME: Can we somehow regenerate the stat cache here, or do we need to // FIXME: Can we somehow regenerate the stat cache here, or do we need to
// unconditionally create a stat cache when we parse the file? // unconditionally create a stat cache when we parse the file?
llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true); llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
@ -2313,7 +2313,7 @@ void ASTUnit::TranslateStoredDiagnostics(
FH.RemoveRange = CharSourceRange::getCharRange(BL, EL); FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
} }
Result.push_back(StoredDiagnostic(SD.Level, SD.ID, Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
SD.Message, Loc, Ranges, FixIts)); SD.Message, Loc, Ranges, FixIts));
} }
Result.swap(Out); Result.swap(Out);
@ -2321,7 +2321,7 @@ void ASTUnit::TranslateStoredDiagnostics(
void ASTUnit::addFileLevelDecl(Decl *D) { void ASTUnit::addFileLevelDecl(Decl *D) {
assert(D); assert(D);
// We only care about local declarations. // We only care about local declarations.
if (D->isFromASTFile()) if (D->isFromASTFile())
return; return;
@ -2398,7 +2398,7 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first()); std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first());
if (EndIt != LocDecls.end()) if (EndIt != LocDecls.end())
++EndIt; ++EndIt;
for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt) for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)
Decls.push_back(DIt->second); Decls.push_back(DIt->second);
} }
@ -2463,10 +2463,10 @@ bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {
FileID FID; FileID FID;
if (SourceMgr) if (SourceMgr)
FID = SourceMgr->getPreambleFileID(); FID = SourceMgr->getPreambleFileID();
if (Loc.isInvalid() || FID.isInvalid()) if (Loc.isInvalid() || FID.isInvalid())
return false; return false;
return SourceMgr->isInFileID(Loc, FID); return SourceMgr->isInFileID(Loc, FID);
} }
@ -2474,10 +2474,10 @@ bool ASTUnit::isInMainFileID(SourceLocation Loc) const {
FileID FID; FileID FID;
if (SourceMgr) if (SourceMgr)
FID = SourceMgr->getMainFileID(); FID = SourceMgr->getMainFileID();
if (Loc.isInvalid() || FID.isInvalid()) if (Loc.isInvalid() || FID.isInvalid())
return false; return false;
return SourceMgr->isInFileID(Loc, FID); return SourceMgr->isInFileID(Loc, FID);
} }
@ -2485,7 +2485,7 @@ SourceLocation ASTUnit::getEndOfPreambleFileID() const {
FileID FID; FileID FID;
if (SourceMgr) if (SourceMgr)
FID = SourceMgr->getPreambleFileID(); FID = SourceMgr->getPreambleFileID();
if (FID.isInvalid()) if (FID.isInvalid())
return SourceLocation(); return SourceLocation();
@ -2496,10 +2496,10 @@ SourceLocation ASTUnit::getStartOfMainFileID() const {
FileID FID; FileID FID;
if (SourceMgr) if (SourceMgr)
FID = SourceMgr->getMainFileID(); FID = SourceMgr->getMainFileID();
if (FID.isInvalid()) if (FID.isInvalid())
return SourceLocation(); return SourceLocation();
return SourceMgr->getLocForStartOfFile(FID); return SourceMgr->getLocForStartOfFile(FID);
} }

View File

@ -21,8 +21,8 @@
#include "clang/Lex/Lexer.h" #include "clang/Lex/Lexer.h"
#include "clang/Lex/PTHManager.h" #include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h" #include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/EndianStream.h" #include "llvm/Support/EndianStream.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
@ -128,7 +128,7 @@ public:
typedef unsigned offset_type; typedef unsigned offset_type;
static hash_value_type ComputeHash(PTHEntryKeyVariant V) { static hash_value_type ComputeHash(PTHEntryKeyVariant V) {
return llvm::HashString(V.getString()); return llvm::djbHash(V.getString());
} }
static std::pair<unsigned,unsigned> static std::pair<unsigned,unsigned>
@ -625,7 +625,7 @@ public:
typedef unsigned offset_type; typedef unsigned offset_type;
static hash_value_type ComputeHash(PTHIdKey* key) { static hash_value_type ComputeHash(PTHIdKey* key) {
return llvm::HashString(key->II->getName()); return llvm::djbHash(key->II->getName());
} }
static std::pair<unsigned,unsigned> static std::pair<unsigned,unsigned>

View File

@ -23,8 +23,8 @@
#include "clang/Lex/Preprocessor.h" #include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h" #include "clang/Lex/Token.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
@ -145,7 +145,7 @@ bool PTHLexer::LexEndOfFile(Token &Result) {
ParsingPreprocessorDirective = false; // Done parsing the "line". ParsingPreprocessorDirective = false; // Done parsing the "line".
return true; // Have a token. return true; // Have a token.
} }
assert(!LexingRawMode); assert(!LexingRawMode);
// If we are in a #if directive, emit an error. // If we are in a #if directive, emit an error.
@ -336,7 +336,7 @@ public:
using offset_type = unsigned; using offset_type = unsigned;
static hash_value_type ComputeHash(internal_key_type x) { static hash_value_type ComputeHash(internal_key_type x) {
return llvm::HashString(x.second); return llvm::djbHash(x.second);
} }
static std::pair<unsigned, unsigned> static std::pair<unsigned, unsigned>
@ -396,7 +396,7 @@ public:
} }
static hash_value_type ComputeHash(const internal_key_type& a) { static hash_value_type ComputeHash(const internal_key_type& a) {
return llvm::HashString(StringRef(a.first, a.second)); return llvm::djbHash(StringRef(a.first, a.second));
} }
// This hopefully will just get inlined and removed by the optimizer. // This hopefully will just get inlined and removed by the optimizer.

View File

@ -16,7 +16,7 @@
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/IdentifierTable.h"
#include "clang/Serialization/ASTDeserializationListener.h" #include "clang/Serialization/ASTDeserializationListener.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/Support/DJB.h"
using namespace clang; using namespace clang;
@ -171,7 +171,7 @@ unsigned serialization::ComputeHash(Selector Sel) {
unsigned R = 5381; unsigned R = 5381;
for (unsigned I = 0; I != N; ++I) for (unsigned I = 0; I != N; ++I)
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
R = llvm::HashString(II->getName(), R); R = llvm::djbHash(II->getName(), R);
return R; return R;
} }
@ -231,7 +231,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {
default: default:
llvm_unreachable("Unhandled DeclContext in AST reader"); llvm_unreachable("Unhandled DeclContext in AST reader");
} }
llvm_unreachable("Unhandled decl kind"); llvm_unreachable("Unhandled decl kind");
} }

View File

@ -106,6 +106,7 @@
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h" #include "llvm/Support/Compression.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -870,7 +871,7 @@ ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
} }
unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) { unsigned ASTIdentifierLookupTraitBase::ComputeHash(const internal_key_type& a) {
return llvm::HashString(a); return llvm::djbHash(a);
} }
std::pair<unsigned, unsigned> std::pair<unsigned, unsigned>
@ -3226,7 +3227,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
PP.getPreprocessingRecord()->SetExternalSource(*this); PP.getPreprocessingRecord()->SetExternalSource(*this);
F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord() F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord()
->allocateSkippedRanges(F.NumPreprocessedSkippedRanges); ->allocateSkippedRanges(F.NumPreprocessedSkippedRanges);
if (F.NumPreprocessedSkippedRanges > 0) if (F.NumPreprocessedSkippedRanges > 0)
GlobalSkippedRangeMap.insert( GlobalSkippedRangeMap.insert(
std::make_pair(F.BasePreprocessedSkippedRangeID, &F)); std::make_pair(F.BasePreprocessedSkippedRangeID, &F));

View File

@ -82,13 +82,13 @@
#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Bitcode/BitCodes.h" #include "llvm/Bitcode/BitCodes.h"
#include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h" #include "llvm/Support/Compression.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h" #include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
@ -453,7 +453,7 @@ ASTTypeWriter::VisitDependentSizedExtVectorType(
Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR; Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
} }
void void
ASTTypeWriter::VisitDependentAddressSpaceType( ASTTypeWriter::VisitDependentAddressSpaceType(
const DependentAddressSpaceType *T) { const DependentAddressSpaceType *T) {
Record.AddTypeRef(T->getPointeeType()); Record.AddTypeRef(T->getPointeeType());
@ -661,7 +661,7 @@ void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(
SourceRange range = TL.getAttrOperandParensRange(); SourceRange range = TL.getAttrOperandParensRange();
Record.AddSourceLocation(range.getBegin()); Record.AddSourceLocation(range.getBegin());
Record.AddSourceLocation(range.getEnd()); Record.AddSourceLocation(range.getEnd());
Record.AddStmt(TL.getAttrExprOperand()); Record.AddStmt(TL.getAttrExprOperand());
} }
void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
@ -1294,7 +1294,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_PRAGMA_COMMENT); RECORD(DECL_PRAGMA_COMMENT);
RECORD(DECL_PRAGMA_DETECT_MISMATCH); RECORD(DECL_PRAGMA_DETECT_MISMATCH);
RECORD(DECL_OMP_DECLARE_REDUCTION); RECORD(DECL_OMP_DECLARE_REDUCTION);
// Statements and Exprs can occur in the Decls and Types block. // Statements and Exprs can occur in the Decls and Types block.
AddStmtsExprs(Stream, Record); AddStmtsExprs(Stream, Record);
@ -1445,7 +1445,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);
RecordData Record; RecordData Record;
// Metadata // Metadata
auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>(); auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>();
MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA)); MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA));
@ -1912,11 +1912,11 @@ namespace {
// Trait used for the on-disk hash table of header search information. // Trait used for the on-disk hash table of header search information.
class HeaderFileInfoTrait { class HeaderFileInfoTrait {
ASTWriter &Writer; ASTWriter &Writer;
// Keep track of the framework names we've used during serialization. // Keep track of the framework names we've used during serialization.
SmallVector<char, 128> FrameworkStringData; SmallVector<char, 128> FrameworkStringData;
llvm::StringMap<unsigned> FrameworkNameOffset; llvm::StringMap<unsigned> FrameworkNameOffset;
public: public:
HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {} HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {}
@ -1929,7 +1929,7 @@ namespace {
using UnresolvedModule = using UnresolvedModule =
llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>; llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;
struct data_type { struct data_type {
const HeaderFileInfo &HFI; const HeaderFileInfo &HFI;
ArrayRef<ModuleMap::KnownHeader> KnownHeaders; ArrayRef<ModuleMap::KnownHeader> KnownHeaders;
@ -1939,14 +1939,14 @@ namespace {
using hash_value_type = unsigned; using hash_value_type = unsigned;
using offset_type = unsigned; using offset_type = unsigned;
hash_value_type ComputeHash(key_type_ref key) { hash_value_type ComputeHash(key_type_ref key) {
// The hash is based only on size/time of the file, so that the reader can // The hash is based only on size/time of the file, so that the reader can
// match even when symlinking or excess path elements ("foo/../", "../") // match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key. // change the form of the name. However, complete path is still the key.
return llvm::hash_combine(key.Size, key.ModTime); return llvm::hash_combine(key.Size, key.ModTime);
} }
std::pair<unsigned, unsigned> std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) { EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
using namespace llvm::support; using namespace llvm::support;
@ -1981,14 +1981,14 @@ namespace {
endian::Writer<little> LE(Out); endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start; uint64_t Start = Out.tell(); (void)Start;
unsigned char Flags = (Data.HFI.isImport << 5) unsigned char Flags = (Data.HFI.isImport << 5)
| (Data.HFI.isPragmaOnce << 4) | (Data.HFI.isPragmaOnce << 4)
| (Data.HFI.DirInfo << 1) | (Data.HFI.DirInfo << 1)
| Data.HFI.IndexHeaderMapHeader; | Data.HFI.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags); LE.write<uint8_t>(Flags);
LE.write<uint16_t>(Data.HFI.NumIncludes); LE.write<uint16_t>(Data.HFI.NumIncludes);
if (!Data.HFI.ControllingMacro) if (!Data.HFI.ControllingMacro)
LE.write<uint32_t>(Data.HFI.ControllingMacroID); LE.write<uint32_t>(Data.HFI.ControllingMacroID);
else else
@ -2001,10 +2001,10 @@ namespace {
= FrameworkNameOffset.find(Data.HFI.Framework); = FrameworkNameOffset.find(Data.HFI.Framework);
if (Pos == FrameworkNameOffset.end()) { if (Pos == FrameworkNameOffset.end()) {
Offset = FrameworkStringData.size() + 1; Offset = FrameworkStringData.size() + 1;
FrameworkStringData.append(Data.HFI.Framework.begin(), FrameworkStringData.append(Data.HFI.Framework.begin(),
Data.HFI.Framework.end()); Data.HFI.Framework.end());
FrameworkStringData.push_back(0); FrameworkStringData.push_back(0);
FrameworkNameOffset[Data.HFI.Framework] = Offset; FrameworkNameOffset[Data.HFI.Framework] = Offset;
} else } else
Offset = Pos->second; Offset = Pos->second;
@ -2028,14 +2028,14 @@ namespace {
assert(Out.tell() - Start == DataLen && "Wrong data length"); assert(Out.tell() - Start == DataLen && "Wrong data length");
} }
const char *strings_begin() const { return FrameworkStringData.begin(); } const char *strings_begin() const { return FrameworkStringData.begin(); }
const char *strings_end() const { return FrameworkStringData.end(); } const char *strings_end() const { return FrameworkStringData.end(); }
}; };
} // namespace } // namespace
/// \brief Write the header search block for the list of files that /// \brief Write the header search block for the list of files that
/// ///
/// \param HS The header search structure to save. /// \param HS The header search structure to save.
void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
@ -2101,7 +2101,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
SmallVector<const FileEntry *, 16> FilesByUID; SmallVector<const FileEntry *, 16> FilesByUID;
HS.getFileMgr().GetUniqueIDMapping(FilesByUID); HS.getFileMgr().GetUniqueIDMapping(FilesByUID);
if (FilesByUID.size() > HS.header_file_size()) if (FilesByUID.size() > HS.header_file_size())
FilesByUID.resize(HS.header_file_size()); FilesByUID.resize(HS.header_file_size());
@ -2163,13 +2163,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
// Write the header search table // Write the header search table
RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset, RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,
NumHeaderSearchEntries, TableData.size()}; NumHeaderSearchEntries, TableData.size()};
TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end()); TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end());
Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData); Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);
// Free all of the strings we had to duplicate. // Free all of the strings we had to duplicate.
for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I) for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)
free(const_cast<char *>(SavedStrings[I])); free(const_cast<char *>(SavedStrings[I]));
@ -2269,7 +2269,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Record.push_back(InputFileIDs[Content->OrigEntry]); Record.push_back(InputFileIDs[Content->OrigEntry]);
Record.push_back(File.NumCreatedFIDs); Record.push_back(File.NumCreatedFIDs);
FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID);
if (FDI != FileDeclIDs.end()) { if (FDI != FileDeclIDs.end()) {
Record.push_back(FDI->second->FirstDeclIndex); Record.push_back(FDI->second->FirstDeclIndex);
@ -2278,9 +2278,9 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Record.push_back(0); Record.push_back(0);
Record.push_back(0); Record.push_back(0);
} }
Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record); Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);
if (Content->BufferOverridden || Content->IsTransient) if (Content->BufferOverridden || Content->IsTransient)
EmitBlob = true; EmitBlob = true;
} else { } else {
@ -2641,8 +2641,8 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
// If the preprocessor has a preprocessing record, emit it. // If the preprocessor has a preprocessing record, emit it.
unsigned NumPreprocessingRecords = 0; unsigned NumPreprocessingRecords = 0;
using namespace llvm; using namespace llvm;
// Set up the abbreviation for // Set up the abbreviation for
unsigned InclusionAbbrev = 0; unsigned InclusionAbbrev = 0;
{ {
auto Abbrev = std::make_shared<BitCodeAbbrev>(); auto Abbrev = std::make_shared<BitCodeAbbrev>();
@ -2654,15 +2654,15 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
} }
unsigned FirstPreprocessorEntityID unsigned FirstPreprocessorEntityID
= (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0) = (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0)
+ NUM_PREDEF_PP_ENTITY_IDS; + NUM_PREDEF_PP_ENTITY_IDS;
unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID; unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID;
RecordData Record; RecordData Record;
for (PreprocessingRecord::iterator E = PPRec.local_begin(), for (PreprocessingRecord::iterator E = PPRec.local_begin(),
EEnd = PPRec.local_end(); EEnd = PPRec.local_end();
E != EEnd; E != EEnd;
(void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) { (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) {
Record.clear(); Record.clear();
@ -2703,7 +2703,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer); Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
continue; continue;
} }
llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter"); llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
} }
Stream.ExitBlock(); Stream.ExitBlock();
@ -2783,14 +2783,14 @@ static unsigned getNumberOfModules(Module *Mod) {
for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); for (auto Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub) Sub != SubEnd; ++Sub)
ChildModules += getNumberOfModules(*Sub); ChildModules += getNumberOfModules(*Sub);
return ChildModules + 1; return ChildModules + 1;
} }
void ASTWriter::WriteSubmodules(Module *WritingModule) { void ASTWriter::WriteSubmodules(Module *WritingModule) {
// Enter the submodule description block. // Enter the submodule description block.
Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5); Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);
// Write the abbreviations needed for the submodules block. // Write the abbreviations needed for the submodules block.
using namespace llvm; using namespace llvm;
@ -2883,7 +2883,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
getNumberOfModules(WritingModule), getNumberOfModules(WritingModule),
FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS}; FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS};
Stream.EmitRecord(SUBMODULE_METADATA, Record); Stream.EmitRecord(SUBMODULE_METADATA, Record);
// Write all of the submodules. // Write all of the submodules.
std::queue<Module *> Q; std::queue<Module *> Q;
Q.push(WritingModule); Q.push(WritingModule);
@ -2959,7 +2959,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName()); Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, H->getName());
} }
// Emit the imports. // Emit the imports.
if (!Mod->Imports.empty()) { if (!Mod->Imports.empty()) {
RecordData Record; RecordData Record;
for (auto *I : Mod->Imports) for (auto *I : Mod->Imports)
@ -2967,7 +2967,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecord(SUBMODULE_IMPORTS, Record); Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
} }
// Emit the exports. // Emit the exports.
if (!Mod->Exports.empty()) { if (!Mod->Exports.empty()) {
RecordData Record; RecordData Record;
for (const auto &E : Mod->Exports) { for (const auto &E : Mod->Exports) {
@ -3017,12 +3017,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS}; RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS};
Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule); Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule);
} }
// Queue up the submodules of this module. // Queue up the submodules of this module.
for (auto *M : Mod->submodules()) for (auto *M : Mod->submodules())
Q.push(M); Q.push(M);
} }
Stream.ExitBlock(); Stream.ExitBlock();
assert((NextSubmoduleID - FirstSubmoduleID == assert((NextSubmoduleID - FirstSubmoduleID ==
@ -3061,7 +3061,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
unsigned &DiagStateID = DiagStateIDMap[State]; unsigned &DiagStateID = DiagStateIDMap[State];
Record.push_back(DiagStateID); Record.push_back(DiagStateID);
if (DiagStateID == 0) { if (DiagStateID == 0) {
DiagStateID = ++CurrID; DiagStateID = ++CurrID;
@ -3546,7 +3546,7 @@ class ASTIdentifierTableTrait {
bool IsModule; bool IsModule;
bool NeedDecls; bool NeedDecls;
ASTWriter::RecordData *InterestingIdentifierOffsets; ASTWriter::RecordData *InterestingIdentifierOffsets;
/// \brief Determines whether this is an "interesting" identifier that needs a /// \brief Determines whether this is an "interesting" identifier that needs a
/// full IdentifierInfo structure written into the hash table. Notably, this /// full IdentifierInfo structure written into the hash table. Notably, this
/// doesn't check whether the name has macros defined; use PublicMacroIterator /// doesn't check whether the name has macros defined; use PublicMacroIterator
@ -3582,7 +3582,7 @@ public:
bool needDecls() const { return NeedDecls; } bool needDecls() const { return NeedDecls; }
static hash_value_type ComputeHash(const IdentifierInfo* II) { static hash_value_type ComputeHash(const IdentifierInfo* II) {
return llvm::HashString(II->getName()); return llvm::djbHash(II->getName());
} }
bool isInterestingIdentifier(const IdentifierInfo *II) { bool isInterestingIdentifier(const IdentifierInfo *II) {
@ -3694,7 +3694,7 @@ public:
/// The identifier table consists of a blob containing string data /// The identifier table consists of a blob containing string data
/// (the actual identifiers themselves) and a separate "offsets" index /// (the actual identifiers themselves) and a separate "offsets" index
/// that maps identifier IDs to locations within the blob. /// that maps identifier IDs to locations within the blob.
void ASTWriter::WriteIdentifierTable(Preprocessor &PP, void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
IdentifierResolver &IdResolver, IdentifierResolver &IdResolver,
bool IsModule) { bool IsModule) {
using namespace llvm; using namespace llvm;
@ -4298,16 +4298,16 @@ void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
void ASTWriter::WriteObjCCategories() { void ASTWriter::WriteObjCCategories() {
SmallVector<ObjCCategoriesInfo, 2> CategoriesMap; SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
RecordData Categories; RecordData Categories;
for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) { for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {
unsigned Size = 0; unsigned Size = 0;
unsigned StartIndex = Categories.size(); unsigned StartIndex = Categories.size();
ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I]; ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];
// Allocate space for the size. // Allocate space for the size.
Categories.push_back(0); Categories.push_back(0);
// Add the categories. // Add the categories.
for (ObjCInterfaceDecl::known_categories_iterator for (ObjCInterfaceDecl::known_categories_iterator
Cat = Class->known_categories_begin(), Cat = Class->known_categories_begin(),
@ -4316,10 +4316,10 @@ void ASTWriter::WriteObjCCategories() {
assert(getDeclID(*Cat) != 0 && "Bogus category"); assert(getDeclID(*Cat) != 0 && "Bogus category");
AddDeclRef(*Cat, Categories); AddDeclRef(*Cat, Categories);
} }
// Update the size. // Update the size.
Categories[StartIndex] = Size; Categories[StartIndex] = Size;
// Record this interface -> category map. // Record this interface -> category map.
ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex }; ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };
CategoriesMap.push_back(CatInfo); CategoriesMap.push_back(CatInfo);
@ -4579,7 +4579,7 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef,
WritingAST = true; WritingAST = true;
ASTHasCompilerErrors = hasErrors; ASTHasCompilerErrors = hasErrors;
// Emit the file header. // Emit the file header.
Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'C', 8);
Stream.Emit((unsigned)'P', 8); Stream.Emit((unsigned)'P', 8);
@ -4627,7 +4627,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// Make sure that the AST reader knows to finalize itself. // Make sure that the AST reader knows to finalize itself.
if (Chain) if (Chain)
Chain->finalizeForWriting(); Chain->finalizeForWriting();
ASTContext &Context = SemaRef.Context; ASTContext &Context = SemaRef.Context;
Preprocessor &PP = SemaRef.PP; Preprocessor &PP = SemaRef.PP;
@ -4668,7 +4668,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// headers. // headers.
RecordData TentativeDefinitions; RecordData TentativeDefinitions;
AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions);
// Build a record containing all of the file scoped decls in this file. // Build a record containing all of the file scoped decls in this file.
RecordData UnusedFileScopedDecls; RecordData UnusedFileScopedDecls;
if (!isModule) if (!isModule)
@ -4789,7 +4789,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
} }
} }
auto Abv = std::make_shared<BitCodeAbbrev>(); auto Abv = std::make_shared<BitCodeAbbrev>();
Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
@ -4811,7 +4811,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// If we have any extern "C" names, write out a visible update for them. // If we have any extern "C" names, write out a visible update for them.
if (Context.ExternCContext) if (Context.ExternCContext)
WriteDeclContextVisibleUpdate(Context.ExternCContext); WriteDeclContextVisibleUpdate(Context.ExternCContext);
// If the translation unit has an anonymous namespace, and we don't already // If the translation unit has an anonymous namespace, and we don't already
// have an update block for it, write it as an update block. // have an update block for it, write it as an update block.
// FIXME: Why do we not do this if there's already an update block? // FIXME: Why do we not do this if there's already an update block?
@ -4900,7 +4900,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// declaration-id:i32 // declaration-id:i32
// c++-base-specifiers-id:i32 // c++-base-specifiers-id:i32
// type-id:i32) // type-id:i32)
// //
// module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule or // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule or
// MK_ExplicitModule, then the module-name is the module name. Otherwise, // MK_ExplicitModule, then the module-name is the module name. Otherwise,
// it is the module file name. // it is the module file name.
@ -4994,7 +4994,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteOpenCLExtensionDecls(SemaRef); WriteOpenCLExtensionDecls(SemaRef);
WriteCUDAPragmas(SemaRef); WriteCUDAPragmas(SemaRef);
// If we're emitting a module, write out the submodule information. // If we're emitting a module, write out the submodule information.
if (WritingModule) if (WritingModule)
WriteSubmodules(WritingModule); WriteSubmodules(WritingModule);
@ -5044,7 +5044,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// Write the record containing CUDA-specific declaration references. // Write the record containing CUDA-specific declaration references.
if (!CUDASpecialDeclRefs.empty()) if (!CUDASpecialDeclRefs.empty())
Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);
// Write the delegating constructors. // Write the delegating constructors.
if (!DelegatingCtorDecls.empty()) if (!DelegatingCtorDecls.empty())
Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);
@ -5347,7 +5347,7 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) {
MacroID ASTWriter::getMacroID(MacroInfo *MI) { MacroID ASTWriter::getMacroID(MacroInfo *MI) {
if (!MI || MI->isBuiltinMacro()) if (!MI || MI->isBuiltinMacro())
return 0; return 0;
assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!");
return MacroIDs[MI]; return MacroIDs[MI];
} }
@ -5491,12 +5491,12 @@ DeclID ASTWriter::GetDeclRef(const Decl *D) {
if (!D) { if (!D) {
return 0; return 0;
} }
// If D comes from an AST file, its declaration ID is already known and // If D comes from an AST file, its declaration ID is already known and
// fixed. // fixed.
if (D->isFromASTFile()) if (D->isFromASTFile())
return D->getGlobalID(); return D->getGlobalID();
assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer"); assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");
DeclID &ID = DeclIDs[D]; DeclID &ID = DeclIDs[D];
if (ID == 0) { if (ID == 0) {
@ -5818,7 +5818,7 @@ void ASTRecordWriter::AddTemplateName(TemplateName Name) {
AddTemplateName(subst->getReplacement()); AddTemplateName(subst->getReplacement());
break; break;
} }
case TemplateName::SubstTemplateTemplateParmPack: { case TemplateName::SubstTemplateTemplateParmPack: {
SubstTemplateTemplateParmPackStorage *SubstPack SubstTemplateTemplateParmPackStorage *SubstPack
= Name.getAsSubstTemplateTemplateParmPack(); = Name.getAsSubstTemplateTemplateParmPack();
@ -5918,7 +5918,7 @@ void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
Record->push_back(Base.getInheritConstructors()); Record->push_back(Base.getInheritConstructors());
AddTypeSourceInfo(Base.getTypeSourceInfo()); AddTypeSourceInfo(Base.getTypeSourceInfo());
AddSourceRange(Base.getSourceRange()); AddSourceRange(Base.getSourceRange());
AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc() AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
: SourceLocation()); : SourceLocation());
} }
@ -6052,9 +6052,9 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
AddUnresolvedSet(Data.Conversions.get(*Writer->Context)); AddUnresolvedSet(Data.Conversions.get(*Writer->Context));
AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context)); AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context));
// Data.Definition is the owning decl, no need to write it. // Data.Definition is the owning decl, no need to write it.
AddDeclRef(D->getFirstFriend()); AddDeclRef(D->getFirstFriend());
// Add lambda-specific data. // Add lambda-specific data.
if (Data.IsLambda) { if (Data.IsLambda) {
auto &Lambda = D->getLambdaData(); auto &Lambda = D->getLambdaData();
@ -6347,7 +6347,7 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
assert(!WritingAST && "Already writing the AST!"); assert(!WritingAST && "Already writing the AST!");
if (!IFD->isFromASTFile()) if (!IFD->isFromASTFile())
return; // Declaration not imported from PCH. return; // Declaration not imported from PCH.
assert(IFD->getDefinition() && "Category on a class without a definition?"); assert(IFD->getDefinition() && "Category on a class without a definition?");
ObjCClassesWithCategories.insert( ObjCClassesWithCategories.insert(
const_cast<ObjCInterfaceDecl *>(IFD->getDefinition())); const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));

View File

@ -21,9 +21,9 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h" #include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/LockFileManager.h" #include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
@ -81,7 +81,7 @@ public:
} }
static hash_value_type ComputeHash(const internal_key_type& a) { static hash_value_type ComputeHash(const internal_key_type& a) {
return llvm::HashString(a); return llvm::djbHash(a);
} }
static std::pair<unsigned, unsigned> static std::pair<unsigned, unsigned>
@ -289,7 +289,7 @@ void GlobalModuleIndex::getModuleDependencies(
bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) { bool GlobalModuleIndex::lookupIdentifier(StringRef Name, HitSet &Hits) {
Hits.clear(); Hits.clear();
// If there's no identifier index, there is nothing we can do. // If there's no identifier index, there is nothing we can do.
if (!IdentifierIndex) if (!IdentifierIndex)
return false; return false;
@ -413,7 +413,7 @@ namespace {
/// \brief A mapping from all interesting identifiers to the set of module /// \brief A mapping from all interesting identifiers to the set of module
/// files in which those identifiers are considered interesting. /// files in which those identifiers are considered interesting.
InterestingIdentifierMap InterestingIdentifiers; InterestingIdentifierMap InterestingIdentifiers;
/// \brief Write the block-info block for the global module index file. /// \brief Write the block-info block for the global module index file.
void emitBlockInfoBlock(llvm::BitstreamWriter &Stream); void emitBlockInfoBlock(llvm::BitstreamWriter &Stream);
@ -608,7 +608,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
// Skip the import location // Skip the import location
++Idx; ++Idx;
// Load stored size/modification time. // Load stored size/modification time.
off_t StoredSize = (off_t)Record[Idx++]; off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++]; time_t StoredModTime = (time_t)Record[Idx++];
@ -697,7 +697,7 @@ public:
typedef unsigned offset_type; typedef unsigned offset_type;
static hash_value_type ComputeHash(key_type_ref Key) { static hash_value_type ComputeHash(key_type_ref Key) {
return llvm::HashString(Key); return llvm::djbHash(Key);
} }
std::pair<unsigned,unsigned> std::pair<unsigned,unsigned>
@ -710,7 +710,7 @@ public:
LE.write<uint16_t>(DataLen); LE.write<uint16_t>(DataLen);
return std::make_pair(KeyLen, DataLen); return std::make_pair(KeyLen, DataLen);
} }
void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) {
Out.write(Key.data(), KeyLen); Out.write(Key.data(), KeyLen);
} }
@ -740,7 +740,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
} }
using namespace llvm; using namespace llvm;
// Emit the file header. // Emit the file header.
Stream.Emit((unsigned)'B', 8); Stream.Emit((unsigned)'B', 8);
Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'C', 8);
@ -789,7 +789,7 @@ bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
I != IEnd; ++I) { I != IEnd; ++I) {
Generator.insert(I->first(), I->second, Trait); Generator.insert(I->first(), I->second, Trait);
} }
// Create the on-disk hash table in a buffer. // Create the on-disk hash table in a buffer.
SmallString<4096> IdentifierTable; SmallString<4096> IdentifierTable;
uint32_t BucketOffset; uint32_t BucketOffset;
@ -902,7 +902,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
// Rename the newly-written index file to the proper name. // Rename the newly-written index file to the proper name.
if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) { if (llvm::sys::fs::rename(IndexTmpPath, IndexPath)) {
// Rename failed; just remove the // Rename failed; just remove the
llvm::sys::fs::remove(IndexTmpPath); llvm::sys::fs::remove(IndexTmpPath);
return EC_IOError; return EC_IOError;
} }

View File

@ -12,7 +12,7 @@
#include "lld/Common/LLVM.h" #include "lld/Common/LLVM.h"
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/Support/DJB.h"
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <vector> #include <vector>
@ -65,7 +65,7 @@ private:
static StringRef getEmptyKey() { return StringRef(); } static StringRef getEmptyKey() { return StringRef(); }
static StringRef getTombstoneKey() { return StringRef(" ", 1); } static StringRef getTombstoneKey() { return StringRef(" ", 1); }
static unsigned getHashValue(StringRef const val) { static unsigned getHashValue(StringRef const val) {
return llvm::HashString(val); return llvm::djbHash(val);
} }
static bool isEqual(StringRef const lhs, StringRef const rhs) { static bool isEqual(StringRef const lhs, StringRef const rhs) {
return lhs.equals(rhs); return lhs.equals(rhs);

View File

@ -11,10 +11,10 @@
#include "lldb/Utility/Stream.h" #include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator.h" // for iterator_facade_base #include "llvm/ADT/iterator.h" // for iterator_facade_base
#include "llvm/Support/Allocator.h" // for BumpPtrAllocator #include "llvm/Support/Allocator.h" // for BumpPtrAllocator
#include "llvm/Support/DJB.h" // for djbHash
#include "llvm/Support/FormatProviders.h" // for format_provider #include "llvm/Support/FormatProviders.h" // for format_provider
#include "llvm/Support/RWMutex.h" #include "llvm/Support/RWMutex.h"
#include "llvm/Support/Threading.h" #include "llvm/Support/Threading.h"
@ -171,7 +171,7 @@ public:
protected: protected:
uint8_t hash(const llvm::StringRef &s) const { uint8_t hash(const llvm::StringRef &s) const {
uint32_t h = llvm::HashString(s); uint32_t h = llvm::djbHash(s);
return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff; return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff;
} }

View File

@ -232,19 +232,6 @@ void SplitString(StringRef Source,
SmallVectorImpl<StringRef> &OutFragments, SmallVectorImpl<StringRef> &OutFragments,
StringRef Delimiters = " \t\n\v\f\r"); StringRef Delimiters = " \t\n\v\f\r");
/// HashString - Hash function for strings.
///
/// This is the Bernstein hash function.
//
// FIXME: Investigate whether a modified bernstein hash function performs
// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
// X*33+c -> X*33^c
inline unsigned HashString(StringRef Str, unsigned Result = 0) {
for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i)
Result = Result * 33 + (unsigned char)Str[i];
return Result;
}
/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th). /// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th).
inline StringRef getOrdinalSuffix(unsigned Val) { inline StringRef getOrdinalSuffix(unsigned Val) {
// It is critically important that we do this perfectly for // It is critically important that we do this perfectly for

View File

@ -14,6 +14,7 @@
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include <cassert> #include <cassert>
@ -32,7 +33,7 @@ static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
ItemSize = itemSize; ItemSize = itemSize;
// If a size is specified, initialize the table with that many buckets. // If a size is specified, initialize the table with that many buckets.
if (InitSize) { if (InitSize) {
// The table will grow when the number of entries reach 3/4 of the number of // The table will grow when the number of entries reach 3/4 of the number of
@ -41,7 +42,7 @@ StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
init(getMinBucketToReserveForEntries(InitSize)); init(getMinBucketToReserveForEntries(InitSize));
return; return;
} }
// Otherwise, initialize it with zero buckets to avoid the allocation. // Otherwise, initialize it with zero buckets to avoid the allocation.
TheTable = nullptr; TheTable = nullptr;
NumBuckets = 0; NumBuckets = 0;
@ -56,7 +57,7 @@ void StringMapImpl::init(unsigned InitSize) {
unsigned NewNumBuckets = InitSize ? InitSize : 16; unsigned NewNumBuckets = InitSize ? InitSize : 16;
NumItems = 0; NumItems = 0;
NumTombstones = 0; NumTombstones = 0;
TheTable = static_cast<StringMapEntryBase **>( TheTable = static_cast<StringMapEntryBase **>(
std::calloc(NewNumBuckets+1, std::calloc(NewNumBuckets+1,
sizeof(StringMapEntryBase **) + sizeof(unsigned))); sizeof(StringMapEntryBase **) + sizeof(unsigned)));
@ -82,7 +83,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
init(16); init(16);
HTSize = NumBuckets; HTSize = NumBuckets;
} }
unsigned FullHashValue = HashString(Name); unsigned FullHashValue = djbHash(Name);
unsigned BucketNo = FullHashValue & (HTSize-1); unsigned BucketNo = FullHashValue & (HTSize-1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
@ -98,11 +99,11 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
HashTable[FirstTombstone] = FullHashValue; HashTable[FirstTombstone] = FullHashValue;
return FirstTombstone; return FirstTombstone;
} }
HashTable[BucketNo] = FullHashValue; HashTable[BucketNo] = FullHashValue;
return BucketNo; return BucketNo;
} }
if (BucketItem == getTombstoneVal()) { if (BucketItem == getTombstoneVal()) {
// Skip over tombstones. However, remember the first one we see. // Skip over tombstones. However, remember the first one we see.
if (FirstTombstone == -1) FirstTombstone = BucketNo; if (FirstTombstone == -1) FirstTombstone = BucketNo;
@ -111,7 +112,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
// case here is that we are only looking at the buckets (for item info // case here is that we are only looking at the buckets (for item info
// being non-null and for the full hash value) not at the items. This // being non-null and for the full hash value) not at the items. This
// is important for cache locality. // is important for cache locality.
// Do the comparison like this because Name isn't necessarily // Do the comparison like this because Name isn't necessarily
// null-terminated! // null-terminated!
char *ItemStr = (char*)BucketItem+ItemSize; char *ItemStr = (char*)BucketItem+ItemSize;
@ -120,10 +121,10 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
return BucketNo; return BucketNo;
} }
} }
// Okay, we didn't find the item. Probe to the next bucket. // Okay, we didn't find the item. Probe to the next bucket.
BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
// Use quadratic probing, it has fewer clumping artifacts than linear // Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case. // probing and has good cache behavior in the common case.
++ProbeAmt; ++ProbeAmt;
@ -136,7 +137,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
int StringMapImpl::FindKey(StringRef Key) const { int StringMapImpl::FindKey(StringRef Key) const {
unsigned HTSize = NumBuckets; unsigned HTSize = NumBuckets;
if (HTSize == 0) return -1; // Really empty table? if (HTSize == 0) return -1; // Really empty table?
unsigned FullHashValue = HashString(Key); unsigned FullHashValue = djbHash(Key);
unsigned BucketNo = FullHashValue & (HTSize-1); unsigned BucketNo = FullHashValue & (HTSize-1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1); unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
@ -146,7 +147,7 @@ int StringMapImpl::FindKey(StringRef Key) const {
// If we found an empty bucket, this key isn't in the table yet, return. // If we found an empty bucket, this key isn't in the table yet, return.
if (LLVM_LIKELY(!BucketItem)) if (LLVM_LIKELY(!BucketItem))
return -1; return -1;
if (BucketItem == getTombstoneVal()) { if (BucketItem == getTombstoneVal()) {
// Ignore tombstones. // Ignore tombstones.
} else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) { } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
@ -154,7 +155,7 @@ int StringMapImpl::FindKey(StringRef Key) const {
// case here is that we are only looking at the buckets (for item info // case here is that we are only looking at the buckets (for item info
// being non-null and for the full hash value) not at the items. This // being non-null and for the full hash value) not at the items. This
// is important for cache locality. // is important for cache locality.
// Do the comparison like this because NameStart isn't necessarily // Do the comparison like this because NameStart isn't necessarily
// null-terminated! // null-terminated!
char *ItemStr = (char*)BucketItem+ItemSize; char *ItemStr = (char*)BucketItem+ItemSize;
@ -163,10 +164,10 @@ int StringMapImpl::FindKey(StringRef Key) const {
return BucketNo; return BucketNo;
} }
} }
// Okay, we didn't find the item. Probe to the next bucket. // Okay, we didn't find the item. Probe to the next bucket.
BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
// Use quadratic probing, it has fewer clumping artifacts than linear // Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case. // probing and has good cache behavior in the common case.
++ProbeAmt; ++ProbeAmt;
@ -187,7 +188,7 @@ void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) {
int Bucket = FindKey(Key); int Bucket = FindKey(Key);
if (Bucket == -1) return nullptr; if (Bucket == -1) return nullptr;
StringMapEntryBase *Result = TheTable[Bucket]; StringMapEntryBase *Result = TheTable[Bucket];
TheTable[Bucket] = getTombstoneVal(); TheTable[Bucket] = getTombstoneVal();
--NumItems; --NumItems;
@ -241,13 +242,13 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
NewBucketNo = NewBucket; NewBucketNo = NewBucket;
continue; continue;
} }
// Otherwise probe for a spot. // Otherwise probe for a spot.
unsigned ProbeSize = 1; unsigned ProbeSize = 1;
do { do {
NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
} while (NewTableArray[NewBucket]); } while (NewTableArray[NewBucket]);
// Finally found a slot. Fill it in. // Finally found a slot. Fill it in.
NewTableArray[NewBucket] = Bucket; NewTableArray[NewBucket] = Bucket;
NewHashArray[NewBucket] = FullHash; NewHashArray[NewBucket] = FullHash;
@ -255,9 +256,9 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
NewBucketNo = NewBucket; NewBucketNo = NewBucket;
} }
} }
free(TheTable); free(TheTable);
TheTable = NewTableArray; TheTable = NewTableArray;
NumBuckets = NewSize; NumBuckets = NewSize;
NumTombstones = 0; NumTombstones = 0;