Change std::string USR to uint64_t pseudorandom function (SipHash 64-bit)

This commit is contained in:
Fangrui Song 2018-01-12 22:13:08 -08:00
parent feb0249350
commit 14a213d407
12 changed files with 306 additions and 109 deletions

View File

@ -2,6 +2,8 @@
#include "clang_utils.h" #include "clang_utils.h"
#include <string.h>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@ -19,6 +21,19 @@ Range ResolveCXSourceRange(const CXSourceRange& range, CXFile* cx_file) {
Position((int16_t)end_line, (int16_t)end_column) /*end*/); Position((int16_t)end_line, (int16_t)end_column) /*end*/);
} }
uint64_t HashUSR(const char* usr) {
extern int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
uint8_t *out, const size_t outlen);
union {
uint64_t ret;
uint8_t out[8];
};
const uint8_t k[16] = {0xd0, 0xe5, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x52,
0x61, 0x79, 0xea, 0x70, 0xca, 0x70, 0xf0, 0x0d};
(void)siphash(reinterpret_cast<const uint8_t*>(usr), strlen(usr), k, out, 8);
return ret;
}
// TODO Place this global variable into config // TODO Place this global variable into config
int g_enable_comments; int g_enable_comments;
@ -45,6 +60,10 @@ std::string ClangType::get_usr() const {
return ClangCursor(clang_getTypeDeclaration(cx_type)).get_usr(); return ClangCursor(clang_getTypeDeclaration(cx_type)).get_usr();
} }
USR ClangType::get_usr_hash() const {
return ClangCursor(clang_getTypeDeclaration(cx_type)).get_usr_hash();
}
ClangType ClangType::get_canonical() const { ClangType ClangType::get_canonical() const {
return clang_getCanonicalType(cx_type); return clang_getCanonicalType(cx_type);
} }
@ -153,6 +172,13 @@ std::string ClangCursor::get_usr() const {
return ::ToString(clang_getCursorUSR(cx_cursor)); return ::ToString(clang_getCursorUSR(cx_cursor));
} }
USR ClangCursor::get_usr_hash() const {
CXString usr = clang_getCursorUSR(cx_cursor);
USR ret = HashUSR(clang_getCString(usr));
clang_disposeString(usr);
return ret;
}
bool ClangCursor::is_definition() const { bool ClangCursor::is_definition() const {
return clang_isCursorDefinition(cx_cursor); return clang_isCursorDefinition(cx_cursor);
} }

View File

@ -5,12 +5,17 @@
#include <clang-c/Index.h> #include <clang-c/Index.h>
#include <optional.h> #include <optional.h>
#include <array>
#include <string> #include <string>
#include <vector> #include <vector>
using USR = uint64_t;
Range ResolveCXSourceRange(const CXSourceRange& range, Range ResolveCXSourceRange(const CXSourceRange& range,
CXFile* cx_file = nullptr); CXFile* cx_file = nullptr);
USR HashUSR(const char* usr);
class ClangType { class ClangType {
public: public:
ClangType(); ClangType();
@ -24,6 +29,7 @@ class ClangType {
// ClangCursor is not defined so we have to return CXCursor // ClangCursor is not defined so we have to return CXCursor
CXCursor get_declaration() const; CXCursor get_declaration() const;
std::string get_usr() const; std::string get_usr() const;
USR get_usr_hash() const;
std::string get_spelling() const; std::string get_spelling() const;
ClangType get_canonical() const; ClangType get_canonical() const;
@ -54,6 +60,7 @@ class ClangCursor {
Range get_extent() const; Range get_extent() const;
std::string get_display_name() const; std::string get_display_name() const;
std::string get_usr() const; std::string get_usr() const;
USR get_usr_hash() const;
bool is_definition() const; bool is_definition() const;

View File

@ -1,5 +1,6 @@
#include "import_pipeline.h" #include "import_pipeline.h"
#include "clang_cursor.h" // HashUSR
#include "cache_manager.h" #include "cache_manager.h"
#include "config.h" #include "config.h"
#include "iindexer.h" #include "iindexer.h"
@ -621,8 +622,7 @@ bool QueryDb_ImportMain(Config* config,
WorkingFile* working_file = WorkingFile* working_file =
working_files->GetFileByFilename(updated_file.path); working_files->GetFileByFilename(updated_file.path);
if (working_file) { if (working_file) {
QueryFileId file_id = QueryFileId file_id = db->usr_to_file[LowerPathIfCaseInsensitive(working_file->filename)];
db->usr_to_file[LowerPathIfCaseInsensitive(working_file->filename)];
QueryFile* file = &db->files[file_id.id]; QueryFile* file = &db->files[file_id.id];
EmitSemanticHighlighting(db, semantic_cache, working_file, file); EmitSemanticHighlighting(db, semantic_cache, working_file, file);
} }

View File

@ -111,12 +111,11 @@ ClangSymbolKind GetSymbolKind(CXIdxEntityKind kind) {
// to export. If we do not capture the parameter type description for the // to export. If we do not capture the parameter type description for the
// constructor we will not be able to attribute the constructor call correctly. // constructor we will not be able to attribute the constructor call correctly.
struct ConstructorCache { struct ConstructorCache {
using Usr = std::string;
struct Constructor { struct Constructor {
Usr usr; USR usr;
std::vector<std::string> param_type_desc; std::vector<std::string> param_type_desc;
}; };
std::unordered_map<Usr, std::vector<Constructor>> constructors_; std::unordered_map<USR, std::vector<Constructor>> constructors_;
// This should be called whenever there is a constructor declaration. // This should be called whenever there is a constructor declaration.
void NotifyConstructor(ClangCursor ctor_cursor) { void NotifyConstructor(ClangCursor ctor_cursor) {
@ -129,22 +128,22 @@ struct ConstructorCache {
return type_desc; return type_desc;
}; };
Constructor ctor{ctor_cursor.get_usr(), build_type_desc(ctor_cursor)}; Constructor ctor{ctor_cursor.get_usr_hash(), build_type_desc(ctor_cursor)};
// Insert into |constructors_|. // Insert into |constructors_|.
std::string type_usr = ctor_cursor.get_semantic_parent().get_usr(); auto type_usr_hash = ctor_cursor.get_semantic_parent().get_usr_hash();
auto existing_ctors = constructors_.find(type_usr); auto existing_ctors = constructors_.find(type_usr_hash);
if (existing_ctors != constructors_.end()) { if (existing_ctors != constructors_.end()) {
existing_ctors->second.push_back(ctor); existing_ctors->second.push_back(ctor);
} else { } else {
constructors_[type_usr] = {ctor}; constructors_[type_usr_hash] = {ctor};
} }
} }
// Tries to lookup a constructor in |type_usr| that takes arguments most // Tries to lookup a constructor in |type_usr| that takes arguments most
// closely aligned to |param_type_desc|. // closely aligned to |param_type_desc|.
optional<std::string> TryFindConstructorUsr( optional<USR> TryFindConstructorUsr(
const std::string& type_usr, USR type_usr,
const std::vector<std::string>& param_type_desc) { const std::vector<std::string>& param_type_desc) {
auto count_matching_prefix_length = [](const char* a, const char* b) { auto count_matching_prefix_length = [](const char* a, const char* b) {
int matched = 0; int matched = 0;
@ -171,7 +170,7 @@ struct ConstructorCache {
if (ctors.empty()) if (ctors.empty())
return nullopt; return nullopt;
std::string best_usr; USR best_usr;
int best_score = INT_MIN; int best_score = INT_MIN;
// Scan constructors for the best possible match. // Scan constructors for the best possible match.
@ -192,7 +191,7 @@ struct ConstructorCache {
// Do prefix-based match on parameter type description. This works well in // Do prefix-based match on parameter type description. This works well in
// practice because clang appends qualifiers to the end of the type, ie, // practice because clang appends qualifiers to the end of the type, ie,
// |foo *&&| // |foo *&&|
for (int i = 0; for (size_t i = 0;
i < std::min(param_type_desc.size(), ctor.param_type_desc.size()); i < std::min(param_type_desc.size(), ctor.param_type_desc.size());
++i) { ++i) {
score += count_matching_prefix_length(param_type_desc[i].c_str(), score += count_matching_prefix_length(param_type_desc[i].c_str(),
@ -205,7 +204,6 @@ struct ConstructorCache {
} }
} }
assert(!best_usr.empty());
return best_usr; return best_usr;
} }
}; };
@ -397,9 +395,10 @@ optional<IndexTypeId> ResolveToDeclarationType(IndexFile* db,
ClangCursor cursor) { ClangCursor cursor) {
ClangCursor declaration = cursor.get_declaration(); ClangCursor declaration = cursor.get_declaration();
declaration = declaration.template_specialization_to_template_definition(); declaration = declaration.template_specialization_to_template_definition();
// TODO optimize
std::string usr = declaration.get_usr(); std::string usr = declaration.get_usr();
if (usr != "") if (usr.size())
return db->ToTypeId(usr); return db->ToTypeId(declaration.get_usr_hash());
return nullopt; return nullopt;
} }
@ -472,7 +471,7 @@ void OnIndexReference_Function(IndexFile* db,
} // namespace } // namespace
// static // static
int IndexFile::kCurrentVersion = 8; int IndexFile::kCurrentVersion = 9;
IndexFile::IndexFile(const std::string& path, IndexFile::IndexFile(const std::string& path,
const optional<std::string>& contents) const optional<std::string>& contents)
@ -488,7 +487,7 @@ IndexFile::IndexFile(const std::string& path,
} }
// TODO: Optimize for const char*? // TODO: Optimize for const char*?
IndexTypeId IndexFile::ToTypeId(const std::string& usr) { IndexTypeId IndexFile::ToTypeId(USR usr) {
auto it = id_cache.usr_to_type_id.find(usr); auto it = id_cache.usr_to_type_id.find(usr);
if (it != id_cache.usr_to_type_id.end()) if (it != id_cache.usr_to_type_id.end())
return it->second; return it->second;
@ -499,7 +498,7 @@ IndexTypeId IndexFile::ToTypeId(const std::string& usr) {
id_cache.type_id_to_usr[id] = usr; id_cache.type_id_to_usr[id] = usr;
return id; return id;
} }
IndexFuncId IndexFile::ToFuncId(const std::string& usr) { IndexFuncId IndexFile::ToFuncId(USR usr) {
auto it = id_cache.usr_to_func_id.find(usr); auto it = id_cache.usr_to_func_id.find(usr);
if (it != id_cache.usr_to_func_id.end()) if (it != id_cache.usr_to_func_id.end())
return it->second; return it->second;
@ -510,7 +509,7 @@ IndexFuncId IndexFile::ToFuncId(const std::string& usr) {
id_cache.func_id_to_usr[id] = usr; id_cache.func_id_to_usr[id] = usr;
return id; return id;
} }
IndexVarId IndexFile::ToVarId(const std::string& usr) { IndexVarId IndexFile::ToVarId(USR usr) {
auto it = id_cache.usr_to_var_id.find(usr); auto it = id_cache.usr_to_var_id.find(usr);
if (it != id_cache.usr_to_var_id.end()) if (it != id_cache.usr_to_var_id.end())
return it->second; return it->second;
@ -523,15 +522,15 @@ IndexVarId IndexFile::ToVarId(const std::string& usr) {
} }
IndexTypeId IndexFile::ToTypeId(const CXCursor& cursor) { IndexTypeId IndexFile::ToTypeId(const CXCursor& cursor) {
return ToTypeId(ClangCursor(cursor).get_usr()); return ToTypeId(ClangCursor(cursor).get_usr_hash());
} }
IndexFuncId IndexFile::ToFuncId(const CXCursor& cursor) { IndexFuncId IndexFile::ToFuncId(const CXCursor& cursor) {
return ToFuncId(ClangCursor(cursor).get_usr()); return ToFuncId(ClangCursor(cursor).get_usr_hash());
} }
IndexVarId IndexFile::ToVarId(const CXCursor& cursor) { IndexVarId IndexFile::ToVarId(const CXCursor& cursor) {
return ToVarId(ClangCursor(cursor).get_usr()); return ToVarId(ClangCursor(cursor).get_usr_hash());
} }
IndexType* IndexFile::Resolve(IndexTypeId id) { IndexType* IndexFile::Resolve(IndexTypeId id) {
@ -548,10 +547,7 @@ std::string IndexFile::ToString() {
return Serialize(SerializeFormat::Json, *this); return Serialize(SerializeFormat::Json, *this);
} }
IndexType::IndexType(IndexTypeId id, const std::string& usr) IndexType::IndexType(IndexTypeId id, USR usr) : usr(usr), id(id) {}
: usr(usr), id(id) {
assert(usr.size() > 0);
}
void RemoveItem(std::vector<Range>& ranges, Range to_remove) { void RemoveItem(std::vector<Range>& ranges, Range to_remove) {
auto it = std::find(ranges.begin(), ranges.end(), to_remove); auto it = std::find(ranges.begin(), ranges.end(), to_remove);
@ -741,14 +737,12 @@ void VisitDeclForTypeUsageVisitorHandler(ClangCursor cursor,
IndexFile* db = param->db; IndexFile* db = param->db;
std::string referenced_usr = std::string referenced_usr =
cursor.get_referenced() cursor.get_referenced().template_specialization_to_template_definition().get_usr();
.template_specialization_to_template_definition()
.get_usr();
// TODO: things in STL cause this to be empty. Figure out why and document it. // TODO: things in STL cause this to be empty. Figure out why and document it.
if (referenced_usr == "") if (referenced_usr == "")
return; return;
IndexTypeId ref_type_id = db->ToTypeId(referenced_usr); IndexTypeId ref_type_id = db->ToTypeId(HashUSR(referenced_usr.c_str()));
if (!param->initial_type) if (!param->initial_type)
param->initial_type = ref_type_id; param->initial_type = ref_type_id;
@ -960,19 +954,18 @@ ClangCursor::VisitResult AddDeclInitializerUsagesVisitor(ClangCursor cursor,
// different USR. // different USR.
// ClangCursor ref = // ClangCursor ref =
// cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr(); // cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr_hash();
// std::string ref_usr = // std::string ref_usr =
// cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr(); // cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr_hash();
std::string ref_usr = auto ref_usr = cursor.get_referenced()
cursor.get_referenced()
.template_specialization_to_template_definition() .template_specialization_to_template_definition()
.get_usr(); .get_usr();
// std::string ref_usr = ref.get_usr(); // std::string ref_usr = ref.get_usr_hash();
if (ref_usr == "") if (ref_usr == "")
break; break;
Range loc = cursor.get_spelling_range(); Range loc = cursor.get_spelling_range();
IndexVarId ref_id = db->ToVarId(ref_usr); IndexVarId ref_id = db->ToVarId(HashUSR(ref_usr.c_str()));
IndexVar* ref_def = db->Resolve(ref_id); IndexVar* ref_def = db->Resolve(ref_id);
UniqueAdd(ref_def->uses, loc); UniqueAdd(ref_def->uses, loc);
break; break;
@ -1018,11 +1011,11 @@ ClangCursor::VisitResult VisitMacroDefinitionAndExpansions(ClangCursor cursor,
// only real difference will be that we show 'callers' instead of 'refs' // only real difference will be that we show 'callers' instead of 'refs'
// (especially since macros cannot have overrides) // (especially since macros cannot have overrides)
std::string decl_usr; USR decl_usr;
if (cursor.get_kind() == CXCursor_MacroDefinition) if (cursor.get_kind() == CXCursor_MacroDefinition)
decl_usr = cursor.get_usr(); decl_usr = cursor.get_usr_hash();
else else
decl_usr = cursor.get_referenced().get_usr(); decl_usr = cursor.get_referenced().get_usr_hash();
IndexVarId var_id = db->ToVarId(decl_usr); IndexVarId var_id = db->ToVarId(decl_usr);
IndexVar* var_def = db->Resolve(var_id); IndexVar* var_def = db->Resolve(var_id);
@ -1069,7 +1062,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
case CXCursor_DeclRefExpr: { case CXCursor_DeclRefExpr: {
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor); ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) { if (ref_cursor.get_kind() == CXCursor_NonTypeTemplateParameter) {
IndexVar* ref_index = db->Resolve(db->ToVarId(ref_cursor.get_usr())); IndexVar* ref_index = db->Resolve(db->ToVarId(ref_cursor.get_usr_hash()));
if (ref_index->def.short_name.empty()) { if (ref_index->def.short_name.empty()) {
ref_index->def.definition_spelling = ref_cursor.get_spelling_range(); ref_index->def.definition_spelling = ref_cursor.get_spelling_range();
ref_index->def.definition_extent = ref_cursor.get_extent(); ref_index->def.definition_extent = ref_cursor.get_extent();
@ -1078,9 +1071,10 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
ref_index->uses.push_back(ref_cursor.get_spelling_range()); ref_index->uses.push_back(ref_cursor.get_spelling_range());
ClangType ref_type = clang_getCursorType(ref_cursor.cx_cursor); ClangType ref_type = clang_getCursorType(ref_cursor.cx_cursor);
// TODO optimize
if (ref_type.get_usr().size()) { if (ref_type.get_usr().size()) {
IndexType* ref_type_index = IndexType* ref_type_index =
db->Resolve(db->ToTypeId(ref_type.get_usr())); db->Resolve(db->ToTypeId(ref_type.get_usr_hash()));
// The cursor extent includes `type name`, not just `name`. There // The cursor extent includes `type name`, not just `name`. There
// seems no way to extract the spelling range of `type` and we do // seems no way to extract the spelling range of `type` and we do
// not want to do subtraction here. // not want to do subtraction here.
@ -1101,8 +1095,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
break; break;
case CXCursor_FunctionDecl: case CXCursor_FunctionDecl:
case CXCursor_FunctionTemplate: { case CXCursor_FunctionTemplate: {
std::string ref_usr = overloaded.get_usr(); IndexFuncId called_id = db->ToFuncId(overloaded.get_usr_hash());
IndexFuncId called_id = db->ToFuncId(ref_usr);
IndexFunc* called = db->Resolve(called_id); IndexFunc* called = db->Resolve(called_id);
OnIndexReference_Function(db, cursor.get_spelling_range(), OnIndexReference_Function(db, cursor.get_spelling_range(),
data->container, called_id, called, data->container, called_id, called,
@ -1116,7 +1109,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
case CXCursor_TemplateRef: { case CXCursor_TemplateRef: {
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor); ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
if (ref_cursor.get_kind() == CXCursor_TemplateTemplateParameter) { if (ref_cursor.get_kind() == CXCursor_TemplateTemplateParameter) {
IndexType* ref_index = db->Resolve(db->ToTypeId(ref_cursor.get_usr())); IndexType* ref_index = db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
// TODO It seems difficult to get references to template template // TODO It seems difficult to get references to template template
// parameters. // parameters.
// CXCursor_TemplateTemplateParameter can be visited by visiting // CXCursor_TemplateTemplateParameter can be visited by visiting
@ -1136,7 +1129,7 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
case CXCursor_TypeRef: { case CXCursor_TypeRef: {
ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor); ClangCursor ref_cursor = clang_getCursorReferenced(cursor.cx_cursor);
if (ref_cursor.get_kind() == CXCursor_TemplateTypeParameter) { if (ref_cursor.get_kind() == CXCursor_TemplateTypeParameter) {
IndexType* ref_index = db->Resolve(db->ToTypeId(ref_cursor.get_usr())); IndexType* ref_index = db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
// TODO It seems difficult to get a FunctionTemplate's template // TODO It seems difficult to get a FunctionTemplate's template
// parameters. // parameters.
// CXCursor_TemplateTypeParameter can be visited by visiting // CXCursor_TemplateTypeParameter can be visited by visiting
@ -1271,9 +1264,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
decl_cursor.template_specialization_to_template_definition()) decl_cursor.template_specialization_to_template_definition())
break; break;
std::string decl_usr = decl_cursor.get_usr(); IndexVarId var_id = db->ToVarId(HashUSR(decl->entityInfo->USR));
IndexVarId var_id = db->ToVarId(decl->entityInfo->USR);
IndexVar* var = db->Resolve(var_id); IndexVar* var = db->Resolve(var_id);
// TODO: Eventually run with this if. Right now I want to iron out bugs // TODO: Eventually run with this if. Right now I want to iron out bugs
@ -1471,7 +1462,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
ClangCursor parent = ClangCursor parent =
ClangCursor(overridden[i]) ClangCursor(overridden[i])
.template_specialization_to_template_definition(); .template_specialization_to_template_definition();
IndexFuncId parent_id = db->ToFuncId(parent.get_usr()); IndexFuncId parent_id = db->ToFuncId(parent.get_usr_hash());
IndexFunc* parent_def = db->Resolve(parent_id); IndexFunc* parent_def = db->Resolve(parent_id);
func = db->Resolve(func_id); // ToFuncId invalidated func_def func = db->Resolve(func_id); // ToFuncId invalidated func_def
@ -1493,7 +1484,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
optional<IndexTypeId> alias_of = AddDeclTypeUsages( optional<IndexTypeId> alias_of = AddDeclTypeUsages(
db, decl->cursor, decl->semanticContainer, decl->lexicalContainer); db, decl->cursor, decl->semanticContainer, decl->lexicalContainer);
IndexTypeId type_id = db->ToTypeId(decl->entityInfo->USR); IndexTypeId type_id = db->ToTypeId(HashUSR(decl->entityInfo->USR));
IndexType* type = db->Resolve(type_id); IndexType* type = db->Resolve(type_id);
if (alias_of) if (alias_of)
@ -1545,7 +1536,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
ClangCursor decl_cursor = decl->cursor; ClangCursor decl_cursor = decl->cursor;
Range decl_loc_spelling = decl_cursor.get_spelling_range(); Range decl_loc_spelling = decl_cursor.get_spelling_range();
IndexTypeId type_id = db->ToTypeId(decl->entityInfo->USR); IndexTypeId type_id = db->ToTypeId(HashUSR(decl->entityInfo->USR));
IndexType* type = db->Resolve(type_id); IndexType* type = db->Resolve(type_id);
// TODO: Eventually run with this if. Right now I want to iron out bugs // TODO: Eventually run with this if. Right now I want to iron out bugs
@ -1632,7 +1623,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
<< std::endl; << std::endl;
if (decl->lexicalContainer) if (decl->lexicalContainer)
std::cerr << " lexicalContainer = " std::cerr << " lexicalContainer = "
<< ClangCursor(decl->lexicalContainer->cursor).get_usr() << ClangCursor(decl->lexicalContainer->cursor).get_usr_hash()
<< std::endl; << std::endl;
break; break;
} }
@ -1688,7 +1679,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
ClangCursor referenced = ref->referencedEntity->cursor; ClangCursor referenced = ref->referencedEntity->cursor;
referenced = referenced.template_specialization_to_template_definition(); referenced = referenced.template_specialization_to_template_definition();
IndexVarId var_id = db->ToVarId(referenced.get_usr()); IndexVarId var_id = db->ToVarId(referenced.get_usr_hash());
IndexVar* var = db->Resolve(var_id); IndexVar* var = db->Resolve(var_id);
// Lambda paramaters are not processed by OnIndexDeclaration and // Lambda paramaters are not processed by OnIndexDeclaration and
// may not have a short_name yet. Note that we only process the lambda // may not have a short_name yet. Note that we only process the lambda
@ -1735,7 +1726,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
ClangCursor ref_cursor(ref->cursor); ClangCursor ref_cursor(ref->cursor);
Range loc = ref_cursor.get_spelling_range(); Range loc = ref_cursor.get_spelling_range();
IndexFuncId called_id = db->ToFuncId(ref->referencedEntity->USR); IndexFuncId called_id = db->ToFuncId(HashUSR(ref->referencedEntity->USR));
IndexFunc* called = db->Resolve(called_id); IndexFunc* called = db->Resolve(called_id);
// libclang doesn't provide a nice api to check if the given function // libclang doesn't provide a nice api to check if the given function
@ -1786,8 +1777,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
// the constructor function we add a usage to. // the constructor function we add a usage to.
optional<ClangCursor> opt_found_type = FindType(ref->cursor); optional<ClangCursor> opt_found_type = FindType(ref->cursor);
if (opt_found_type) { if (opt_found_type) {
std::string ctor_type_usr = USR ctor_type_usr = opt_found_type->get_referenced().get_usr_hash();
opt_found_type->get_referenced().get_usr();
ClangCursor call_cursor = ref->cursor; ClangCursor call_cursor = ref->cursor;
// Build a type description from the parameters of the call, so we // Build a type description from the parameters of the call, so we
@ -1800,7 +1790,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
} }
// Try to find the constructor and add a reference. // Try to find the constructor and add a reference.
optional<std::string> ctor_usr = optional<USR> ctor_usr =
param->ctors.TryFindConstructorUsr(ctor_type_usr, call_type_desc); param->ctors.TryFindConstructorUsr(ctor_type_usr, call_type_desc);
if (ctor_usr) { if (ctor_usr) {
IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr)); IndexFunc* ctor = db->Resolve(db->ToFuncId(*ctor_usr));
@ -1823,7 +1813,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
case CXIdxEntity_CXXClass: { case CXIdxEntity_CXXClass: {
ClangCursor ref_cursor = ref->referencedEntity->cursor; ClangCursor ref_cursor = ref->referencedEntity->cursor;
ref_cursor = ref_cursor.template_specialization_to_template_definition(); ref_cursor = ref_cursor.template_specialization_to_template_definition();
IndexType* referenced = db->Resolve(db->ToTypeId(ref_cursor.get_usr())); IndexType* referenced = db->Resolve(db->ToTypeId(ref_cursor.get_usr_hash()));
// //
// The following will generate two TypeRefs to Foo, both located at the // The following will generate two TypeRefs to Foo, both located at the

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "clang_cursor.h"
#include "clang_index.h" #include "clang_index.h"
#include "clang_translation_unit.h" #include "clang_translation_unit.h"
#include "clang_utils.h" #include "clang_utils.h"
@ -259,7 +260,7 @@ struct IndexType {
using Def = using Def =
TypeDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>; TypeDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>;
std::string usr; USR usr;
IndexTypeId id; IndexTypeId id;
Def def; Def def;
@ -275,7 +276,7 @@ struct IndexType {
std::vector<Range> uses; std::vector<Range> uses;
IndexType() {} // For serialization. IndexType() {} // For serialization.
IndexType(IndexTypeId id, const std::string& usr); IndexType(IndexTypeId id, USR usr);
bool operator<(const IndexType& other) const { return id < other.id; } bool operator<(const IndexType& other) const { return id < other.id; }
}; };
@ -361,7 +362,7 @@ struct IndexFunc {
IndexFuncRef, IndexFuncRef,
Range>; Range>;
std::string usr; USR usr;
IndexFuncId id; IndexFuncId id;
Def def; Def def;
@ -391,7 +392,7 @@ struct IndexFunc {
std::vector<IndexFuncRef> callers; std::vector<IndexFuncRef> callers;
IndexFunc() {} // For serialization. IndexFunc() {} // For serialization.
IndexFunc(IndexFuncId id, const std::string& usr) : usr(usr), id(id) { IndexFunc(IndexFuncId id, USR usr) : usr(usr), id(id) {
// assert(usr.size() > 0); // assert(usr.size() > 0);
} }
@ -468,7 +469,7 @@ void Reflect(TVisitor& visitor,
struct IndexVar { struct IndexVar {
using Def = VarDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>; using Def = VarDefDefinitionData<IndexTypeId, IndexFuncId, IndexVarId, Range>;
std::string usr; USR usr;
IndexVarId id; IndexVarId id;
Def def; Def def;
@ -477,7 +478,7 @@ struct IndexVar {
std::vector<Range> uses; std::vector<Range> uses;
IndexVar() {} // For serialization. IndexVar() {} // For serialization.
IndexVar(IndexVarId id, const std::string& usr) : usr(usr), id(id) { IndexVar(IndexVarId id, USR usr) : usr(usr), id(id) {
// assert(usr.size() > 0); // assert(usr.size() > 0);
} }
@ -487,12 +488,12 @@ MAKE_HASHABLE(IndexVar, t.id);
struct IdCache { struct IdCache {
std::string primary_file; std::string primary_file;
std::unordered_map<std::string, IndexTypeId> usr_to_type_id; std::unordered_map<USR, IndexTypeId> usr_to_type_id;
std::unordered_map<std::string, IndexFuncId> usr_to_func_id; std::unordered_map<USR, IndexFuncId> usr_to_func_id;
std::unordered_map<std::string, IndexVarId> usr_to_var_id; std::unordered_map<USR, IndexVarId> usr_to_var_id;
std::unordered_map<IndexTypeId, std::string> type_id_to_usr; std::unordered_map<IndexTypeId, USR> type_id_to_usr;
std::unordered_map<IndexFuncId, std::string> func_id_to_usr; std::unordered_map<IndexFuncId, USR> func_id_to_usr;
std::unordered_map<IndexVarId, std::string> var_id_to_usr; std::unordered_map<IndexVarId, USR> var_id_to_usr;
IdCache(const std::string& primary_file); IdCache(const std::string& primary_file);
}; };
@ -544,9 +545,9 @@ struct IndexFile {
IndexFile(const std::string& path, const optional<std::string>& contents); IndexFile(const std::string& path, const optional<std::string>& contents);
IndexTypeId ToTypeId(const std::string& usr); IndexTypeId ToTypeId(USR usr);
IndexFuncId ToFuncId(const std::string& usr); IndexFuncId ToFuncId(USR usr);
IndexVarId ToVarId(const std::string& usr); IndexVarId ToVarId(USR usr);
IndexTypeId ToTypeId(const CXCursor& usr); IndexTypeId ToTypeId(const CXCursor& usr);
IndexFuncId ToFuncId(const CXCursor& usr); IndexFuncId ToFuncId(const CXCursor& usr);
IndexVarId ToVarId(const CXCursor& usr); IndexVarId ToVarId(const CXCursor& usr);

View File

@ -4,6 +4,7 @@
#include <loguru.hpp> #include <loguru.hpp>
// FIXME Interop with VSCode, change std::string usr to Usr (uint64_t)
namespace { namespace {
struct Ipc_CqueryCallTreeInitial struct Ipc_CqueryCallTreeInitial
: public IpcMessage<Ipc_CqueryCallTreeInitial> { : public IpcMessage<Ipc_CqueryCallTreeInitial> {
@ -62,7 +63,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildInitialCallTree(
Out_CqueryCallTree::CallEntry entry; Out_CqueryCallTree::CallEntry entry;
entry.name = root_func.def->short_name; entry.name = root_func.def->short_name;
entry.usr = root_func.usr; entry.usr = std::to_string(root_func.usr);
entry.location = *def_loc; entry.location = *def_loc;
entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, root_func); entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, root_func);
std::vector<Out_CqueryCallTree::CallEntry> result; std::vector<Out_CqueryCallTree::CallEntry> result;
@ -113,7 +114,7 @@ std::vector<Out_CqueryCallTree::CallEntry> BuildExpandCallTree(
Out_CqueryCallTree::CallEntry call_entry; Out_CqueryCallTree::CallEntry call_entry;
call_entry.name = call_func.def->short_name; call_entry.name = call_func.def->short_name;
call_entry.usr = call_func.usr; call_entry.usr = std::to_string(call_func.usr);
call_entry.location = *call_location; call_entry.location = *call_location;
call_entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, call_func); call_entry.hasCallers = HasCallersOnSelfOrBaseOrDerived(db, call_func);
call_entry.callType = call_type; call_entry.callType = call_type;
@ -188,7 +189,8 @@ struct CqueryCallTreeExpandHandler
Out_CqueryCallTree out; Out_CqueryCallTree out;
out.id = request->id; out.id = request->id;
auto func_id = db->usr_to_func.find(request->params.usr); // FIXME
auto func_id = db->usr_to_func.find(std::stoull(request->params.usr));
if (func_id != db->usr_to_func.end()) if (func_id != db->usr_to_func.end())
out.result = BuildExpandCallTree(db, working_files, func_id->second); out.result = BuildExpandCallTree(db, working_files, func_id->second);

View File

@ -104,7 +104,7 @@ optional<QueryFileId> GetImplementationFile(QueryDatabase* db,
LOG_S(INFO) << "!! Looking for impl file that starts with " << target_path; LOG_S(INFO) << "!! Looking for impl file that starts with " << target_path;
for (auto& entry : db->usr_to_file) { for (auto& entry : db->usr_to_file) {
Usr path = entry.first; const std::string& path = entry.first;
// Do not consider header files for implementation files. // Do not consider header files for implementation files.
// TODO: make file extensions configurable. // TODO: make file extensions configurable.

View File

@ -285,12 +285,13 @@ QueryFileId GetQueryFileIdFromPath(QueryDatabase* query_db,
return QueryFileId(it->second.id); return QueryFileId(it->second.id);
size_t idx = query_db->files.size(); size_t idx = query_db->files.size();
query_db->usr_to_file[LowerPathIfCaseInsensitive(path)] = QueryFileId(idx); query_db->usr_to_file[LowerPathIfCaseInsensitive(path)] =
QueryFileId(idx);
query_db->files.push_back(QueryFile(path)); query_db->files.push_back(QueryFile(path));
return QueryFileId(idx); return QueryFileId(idx);
} }
QueryTypeId GetQueryTypeIdFromUsr(QueryDatabase* query_db, const Usr& usr) { QueryTypeId GetQueryTypeIdFromUsr(QueryDatabase* query_db, USR usr) {
auto it = query_db->usr_to_type.find(usr); auto it = query_db->usr_to_type.find(usr);
if (it != query_db->usr_to_type.end()) if (it != query_db->usr_to_type.end())
return QueryTypeId(it->second.id); return QueryTypeId(it->second.id);
@ -301,7 +302,7 @@ QueryTypeId GetQueryTypeIdFromUsr(QueryDatabase* query_db, const Usr& usr) {
return QueryTypeId(idx); return QueryTypeId(idx);
} }
QueryFuncId GetQueryFuncIdFromUsr(QueryDatabase* query_db, const Usr& usr) { QueryFuncId GetQueryFuncIdFromUsr(QueryDatabase* query_db, USR usr) {
auto it = query_db->usr_to_func.find(usr); auto it = query_db->usr_to_func.find(usr);
if (it != query_db->usr_to_func.end()) if (it != query_db->usr_to_func.end())
return QueryFuncId(it->second.id); return QueryFuncId(it->second.id);
@ -713,8 +714,9 @@ void QueryDatabase::RemoveUsrs(SymbolKind usr_kind,
switch (usr_kind) { switch (usr_kind) {
case SymbolKind::File: { case SymbolKind::File: {
for (const Usr& usr : to_remove) // FIXME
files[usr_to_file[LowerPathIfCaseInsensitive(usr)].id].def = nullopt; //for (const Usr& usr : to_remove)
// files[usr_to_file[usr].id].def = nullopt;
break; break;
} }
case SymbolKind::Type: { case SymbolKind::Type: {
@ -896,30 +898,30 @@ TEST_SUITE("query") {
IndexFile previous("foo.cc", nullopt); IndexFile previous("foo.cc", nullopt);
IndexFile current("foo.cc", nullopt); IndexFile current("foo.cc", nullopt);
previous.Resolve(previous.ToTypeId("usr1"))->def.definition_spelling = previous.Resolve(previous.ToTypeId(HashUSR("usr1")))->def.definition_spelling =
Range(Position(1, 0)); Range(Position(1, 0));
previous.Resolve(previous.ToFuncId("usr2"))->def.definition_spelling = previous.Resolve(previous.ToFuncId(HashUSR("usr2")))->def.definition_spelling =
Range(Position(2, 0)); Range(Position(2, 0));
previous.Resolve(previous.ToVarId("usr3"))->def.definition_spelling = previous.Resolve(previous.ToVarId(HashUSR("usr3")))->def.definition_spelling =
Range(Position(3, 0)); Range(Position(3, 0));
IndexUpdate update = GetDelta(previous, current); IndexUpdate update = GetDelta(previous, current);
REQUIRE(update.types_removed == std::vector<Usr>{"usr1"}); REQUIRE(update.types_removed == std::vector<Usr>{HashUSR("usr1")});
REQUIRE(update.funcs_removed == std::vector<Usr>{"usr2"}); REQUIRE(update.funcs_removed == std::vector<Usr>{HashUSR("usr2")});
REQUIRE(update.vars_removed == std::vector<Usr>{"usr3"}); REQUIRE(update.vars_removed == std::vector<Usr>{HashUSR("usr3")});
} }
TEST_CASE("do not remove ref-only defs") { TEST_CASE("do not remove ref-only defs") {
IndexFile previous("foo.cc", nullopt); IndexFile previous("foo.cc", nullopt);
IndexFile current("foo.cc", nullopt); IndexFile current("foo.cc", nullopt);
previous.Resolve(previous.ToTypeId("usr1")) previous.Resolve(previous.ToTypeId(HashUSR("usr1")))
->uses.push_back(Range(Position(1, 0))); ->uses.push_back(Range(Position(1, 0)));
previous.Resolve(previous.ToFuncId("usr2")) previous.Resolve(previous.ToFuncId(HashUSR("usr2")))
->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), ->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)),
false /*is_implicit*/)); false /*is_implicit*/));
previous.Resolve(previous.ToVarId("usr3")) previous.Resolve(previous.ToVarId(HashUSR("usr3")))
->uses.push_back(Range(Position(3, 0))); ->uses.push_back(Range(Position(3, 0)));
IndexUpdate update = GetDelta(previous, current); IndexUpdate update = GetDelta(previous, current);
@ -933,8 +935,8 @@ TEST_SUITE("query") {
IndexFile previous("foo.cc", nullopt); IndexFile previous("foo.cc", nullopt);
IndexFile current("foo.cc", nullopt); IndexFile current("foo.cc", nullopt);
IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUSR("usr")));
IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); IndexFunc* cf = current.Resolve(current.ToFuncId(HashUSR("usr")));
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)),
false /*is_implicit*/)); false /*is_implicit*/));
@ -958,8 +960,8 @@ TEST_SUITE("query") {
IndexFile previous("foo.cc", nullopt); IndexFile previous("foo.cc", nullopt);
IndexFile current("foo.cc", nullopt); IndexFile current("foo.cc", nullopt);
IndexType* pt = previous.Resolve(previous.ToTypeId("usr")); IndexType* pt = previous.Resolve(previous.ToTypeId(HashUSR("usr")));
IndexType* ct = current.Resolve(current.ToTypeId("usr")); IndexType* ct = current.Resolve(current.ToTypeId(HashUSR("usr")));
pt->uses.push_back(Range(Position(1, 0))); pt->uses.push_back(Range(Position(1, 0)));
ct->uses.push_back(Range(Position(2, 0))); ct->uses.push_back(Range(Position(2, 0)));
@ -979,8 +981,8 @@ TEST_SUITE("query") {
IndexFile previous("foo.cc", nullopt); IndexFile previous("foo.cc", nullopt);
IndexFile current("foo.cc", nullopt); IndexFile current("foo.cc", nullopt);
IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); IndexFunc* pf = previous.Resolve(previous.ToFuncId(HashUSR("usr")));
IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); IndexFunc* cf = current.Resolve(current.ToFuncId(HashUSR("usr")));
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)),
false /*is_implicit*/)); false /*is_implicit*/));
pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)),

View File

@ -7,7 +7,7 @@
#include <functional> #include <functional>
using Usr = std::string; using Usr = USR;
struct QueryFile; struct QueryFile;
struct QueryType; struct QueryType;
@ -170,10 +170,10 @@ void Reflect(TVisitor& visitor, MergeableUpdate<TId, TValue>& value) {
template <typename T> template <typename T>
struct WithUsr { struct WithUsr {
Usr usr; USR usr;
T value; T value;
WithUsr(const Usr& usr, const T& value) : usr(usr), value(value) {} WithUsr(USR usr, const T& value) : usr(usr), value(value) {}
}; };
template <typename TVisitor, typename T> template <typename TVisitor, typename T>
void Reflect(TVisitor& visitor, WithUsr<T>& value) { void Reflect(TVisitor& visitor, WithUsr<T>& value) {
@ -225,7 +225,7 @@ struct QueryType {
using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>; using InstancesUpdate = MergeableUpdate<QueryTypeId, QueryVarId>;
using UsesUpdate = MergeableUpdate<QueryTypeId, QueryLocation>; using UsesUpdate = MergeableUpdate<QueryTypeId, QueryLocation>;
Usr usr; USR usr;
optional<Def> def; optional<Def> def;
std::vector<QueryTypeId> derived; std::vector<QueryTypeId> derived;
std::vector<QueryVarId> instances; std::vector<QueryVarId> instances;
@ -246,7 +246,7 @@ struct QueryFunc {
using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>; using DerivedUpdate = MergeableUpdate<QueryFuncId, QueryFuncId>;
using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>; using CallersUpdate = MergeableUpdate<QueryFuncId, QueryFuncRef>;
Usr usr; USR usr;
optional<Def> def; optional<Def> def;
std::vector<QueryLocation> declarations; std::vector<QueryLocation> declarations;
std::vector<QueryFuncId> derived; std::vector<QueryFuncId> derived;
@ -352,7 +352,7 @@ struct QueryDatabase {
// Lookup symbol based on a usr. // Lookup symbol based on a usr.
// NOTE: For usr_to_file make sure to call LowerPathIfCaseInsensitive on key. // NOTE: For usr_to_file make sure to call LowerPathIfCaseInsensitive on key.
// TODO: add type wrapper to enforce we call it // TODO: add type wrapper to enforce we call it
spp::sparse_hash_map<Usr, QueryFileId> usr_to_file; spp::sparse_hash_map<std::string, QueryFileId> usr_to_file;
spp::sparse_hash_map<Usr, QueryTypeId> usr_to_type; spp::sparse_hash_map<Usr, QueryTypeId> usr_to_type;
spp::sparse_hash_map<Usr, QueryFuncId> usr_to_func; spp::sparse_hash_map<Usr, QueryFuncId> usr_to_func;
spp::sparse_hash_map<Usr, QueryVarId> usr_to_var; spp::sparse_hash_map<Usr, QueryVarId> usr_to_var;

View File

@ -171,7 +171,8 @@ void Reflect(TVisitor& visitor, IndexVar& value) {
// IndexFile // IndexFile
bool ReflectMemberStart(Writer& visitor, IndexFile& value) { bool ReflectMemberStart(Writer& visitor, IndexFile& value) {
auto it = value.id_cache.usr_to_type_id.find(""); // FIXME
auto it = value.id_cache.usr_to_type_id.find(HashUSR(""));
if (it != value.id_cache.usr_to_type_id.end()) { if (it != value.id_cache.usr_to_type_id.end()) {
value.Resolve(it->second)->def.short_name = "<fundamental>"; value.Resolve(it->second)->def.short_name = "<fundamental>";
assert(value.Resolve(it->second)->uses.size() == 0); assert(value.Resolve(it->second)->uses.size() == 0);

165
third_party/siphash.c vendored Normal file
View File

@ -0,0 +1,165 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2016 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* default: SipHash-2-4 */
#define cROUNDS 2
#define dROUNDS 4
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U64TO8_LE(p, v) \
U32TO8_LE((p), (uint32_t)((v))); \
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define U8TO64_LE(p) \
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v0; \
v0 = ROTL(v0, 32); \
v2 += v3; \
v3 = ROTL(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 17); \
v1 ^= v2; \
v2 = ROTL(v2, 32); \
} while (0)
#ifdef DEBUG
#define TRACE \
do { \
printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \
(uint32_t)v0); \
printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \
(uint32_t)v1); \
printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \
(uint32_t)v2); \
printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \
(uint32_t)v3); \
} while (0)
#else
#define TRACE
#endif
int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
uint8_t *out, const size_t outlen) {
assert((outlen == 8) || (outlen == 16));
uint64_t v0 = 0x736f6d6570736575ULL;
uint64_t v1 = 0x646f72616e646f6dULL;
uint64_t v2 = 0x6c7967656e657261ULL;
uint64_t v3 = 0x7465646279746573ULL;
uint64_t k0 = U8TO64_LE(k);
uint64_t k1 = U8TO64_LE(k + 8);
uint64_t m;
int i;
const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
const int left = inlen & 7;
uint64_t b = ((uint64_t)inlen) << 56;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 16)
v1 ^= 0xee;
for (; in != end; in += 8) {
m = U8TO64_LE(in);
v3 ^= m;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= m;
}
switch (left) {
case 7:
b |= ((uint64_t)in[6]) << 48;
case 6:
b |= ((uint64_t)in[5]) << 40;
case 5:
b |= ((uint64_t)in[4]) << 32;
case 4:
b |= ((uint64_t)in[3]) << 24;
case 3:
b |= ((uint64_t)in[2]) << 16;
case 2:
b |= ((uint64_t)in[1]) << 8;
case 1:
b |= ((uint64_t)in[0]);
break;
case 0:
break;
}
v3 ^= b;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= b;
if (outlen == 16)
v2 ^= 0xee;
else
v2 ^= 0xff;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out, b);
if (outlen == 8)
return 0;
v1 ^= 0xdd;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out + 8, b);
return 0;
}

View File

@ -152,7 +152,8 @@ def configure(ctx):
if ctx.env.CXXFLAGS: if ctx.env.CXXFLAGS:
cxxflags = ctx.env.CXXFLAGS cxxflags = ctx.env.CXXFLAGS
else: else:
cxxflags = ['-g', '-Wall', '-Wno-sign-compare', '-Werror'] # FIXME Figure out how to treat siphash.c as C file so that we can remove -Wno-deprecated
cxxflags = ['-g', '-Wall', '-Wno-sign-compare', '-Wno-deprecated', '-Werror']
if all(not x.startswith('-std=') for x in ctx.env.CXXFLAGS): if all(not x.startswith('-std=') for x in ctx.env.CXXFLAGS):
cxxflags.append('-std=c++11') cxxflags.append('-std=c++11')
@ -358,10 +359,12 @@ def build(bld):
else: else:
rpath = bld.env['LIBPATH_clang'] rpath = bld.env['LIBPATH_clang']
bld.objects(name='siphash', source='third_party/siphash.c')
# https://waf.io/apidocs/tools/c_aliases.html#waflib.Tools.c_aliases.program # https://waf.io/apidocs/tools/c_aliases.html#waflib.Tools.c_aliases.program
bld.program( bld.program(
source=cc_files, source=cc_files,
use='clang', use=['clang', 'siphash'],
includes=[ includes=[
'src/', 'src/',
'third_party/', 'third_party/',