Skip to content

[Index] Convert to hashing to HashBuilder with BLAKE3 #77116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 54 additions & 28 deletions lib/Index/IndexRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
#include "clang/Index/IndexingAction.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/Support/BLAKE3.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/HashBuilder.h"
#include "llvm/Support/Path.h"

using namespace swift;
Expand All @@ -50,29 +52,48 @@ using clang::index::SymbolRoleSet;
//===----------------------------------------------------------------------===//

namespace {

using HashBuilderTy =
llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>;

class SymbolTracker {
public:
struct SymbolRelation {
size_t symbolIndex;
SymbolRoleSet roles;

llvm::hash_code hash() const { return llvm::hash_combine(symbolIndex, roles); }
SymbolRelation(size_t symbolIndex, SymbolRoleSet roles)
: symbolIndex(symbolIndex), roles(roles) {}

void hash(HashBuilderTy &HashBuilder) {
HashBuilder.add(symbolIndex);
HashBuilder.add(roles);
}
};

struct SymbolOccurrence {
size_t symbolIndex;
SymbolRoleSet roles;
unsigned line;
unsigned column;
SmallVector<SymbolRelation, 3> related;

llvm::hash_code hash() const {
auto hash = llvm::hash_combine(symbolIndex, roles, line, column);
SymbolOccurrence(size_t symbolIndex, SymbolRoleSet roles, unsigned line,
unsigned column, SmallVector<SymbolRelation, 3> related)
: symbolIndex(symbolIndex), roles(roles), line(line), column(column),
related(std::move(related)) {}

void hash(HashBuilderTy &HashBuilder) {
HashBuilder.add(symbolIndex);
HashBuilder.add(roles);
HashBuilder.add(line);
HashBuilder.add(column);
for (auto &relation : related) {
hash = llvm::hash_combine(hash, relation.hash());
relation.hash(HashBuilder);
}
return hash;
}
};

struct Symbol {
StringRef name;
StringRef USR;
Expand All @@ -81,12 +102,19 @@ class SymbolTracker {
SymbolInfo symInfo;
unsigned isTestCandidate : 1;

llvm::hash_code hash() const {
return llvm::hash_combine(
name, USR, group,
static_cast<unsigned>(symInfo.Kind),
static_cast<unsigned>(symInfo.SubKind),
symInfo.Properties, isTestCandidate);
Symbol(StringRef name, StringRef usr, StringRef group, SymbolInfo symInfo,
bool isTestCandidate)
: name(name), USR(usr), group(group), symInfo(std::move(symInfo)),
isTestCandidate(isTestCandidate) {}

void hash(HashBuilderTy &HashBuilder) {
HashBuilder.add(name);
HashBuilder.add(USR);
HashBuilder.add(group);
HashBuilder.add(symInfo.Kind);
HashBuilder.add(symInfo.SubKind);
HashBuilder.add(symInfo.Properties);
HashBuilder.add(isTestCandidate);
}
};

Expand Down Expand Up @@ -114,13 +142,9 @@ class SymbolTracker {
auto pair = USRToSymbol.insert(std::make_pair(indexSym.USR.data(),
symbols.size()));
if (pair.second) {
Symbol symbol{indexSym.name,
indexSym.USR,
indexSym.group,
indexSym.symInfo,
0};
recordHash = llvm::hash_combine(recordHash, symbol.hash());
symbols.push_back(std::move(symbol));
symbols.emplace_back(indexSym.name, indexSym.USR, indexSym.group,
indexSym.symInfo, 0);
symbols.back().hash(HashBuilder);
}

return pair.first->second;
Expand All @@ -131,26 +155,28 @@ class SymbolTracker {

SmallVector<SymbolRelation, 3> relations;
for(IndexRelation indexRel: indexOccur.Relations) {
relations.push_back({addSymbol(indexRel), indexRel.roles});
relations.emplace_back(addSymbol(indexRel), indexRel.roles);
}

occurrences.push_back({/*symbolIndex=*/addSymbol(indexOccur),
indexOccur.roles,
indexOccur.line,
indexOccur.column,
std::move(relations)});

recordHash = llvm::hash_combine(recordHash, occurrences.back().hash());
occurrences.emplace_back(addSymbol(indexOccur), indexOccur.roles,
indexOccur.line, indexOccur.column,
std::move(relations));
occurrences.back().hash(HashBuilder);
}

llvm::hash_code hashRecord() const { return recordHash; }
uint64_t hashRecord() {
std::array<uint8_t, 8> recordHashArr = HashBuilder.final();
uint64_t recordHash = 0;
std::memcpy(&recordHash, recordHashArr.data(), recordHashArr.size());
return recordHash;
}

private:
llvm::DenseMap<const char *, size_t> USRToSymbol;
std::vector<Symbol> symbols;
std::vector<SymbolOccurrence> occurrences;
bool sorted = false;
llvm::hash_code recordHash = 0;
HashBuilderTy HashBuilder;
};

class IndexRecordingConsumer : public IndexDataConsumer {
Expand Down
2 changes: 1 addition & 1 deletion test/Index/Store/cross-import-overlay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ from__ABAdditionsCAdditions()
//
// RUN: %FileCheck %s --input-file %t/units --check-prefix=MAIN
// MAIN: module-name: cross_import_overlay
// MAIN: out-file: {{.*}}/file1.o
// MAIN: out-file: {{.*}}{{/|\\}}file1.o
// MAIN-NEXT: target: {{.*}}
// MAIN-NEXT: is-debug: 1
// MAIN-NEXT: DEPEND START
Expand Down
57 changes: 34 additions & 23 deletions test/Index/Store/unit-multiple-sourcefiles-remapped.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,50 @@

// RUN: %empty-directory(%t)
// RUN: touch %t/s1.swift %t/s2.swift
// RUN: %target-swift-frontend -index-store-path %t/idx -file-prefix-map %t=REMAPPED_OUT_DIR -primary-file %t/s1.swift %t/s2.swift -o %t/s1.o -c -module-name main -emit-module -emit-module-path %t/s1.swiftmodule
// RUN: %target-swift-frontend -index-store-path %t/idx -file-prefix-map %t=REMAPPED_OUT_DIR %t/s1.swift -primary-file %t/s2.swift -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/s2.swiftmodule
// RUN: %target-swift-frontend -index-store-path %t/idx -file-prefix-map %t=REMAPPED_OUT_DIR %t/s1.swiftmodule %t/s2.swiftmodule -emit-module -o %t/main.swiftmodule -module-name main
// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s

// RUN: echo "-----separate-----" > %t/units.out
// RUN: %target-swift-frontend -index-store-path %t/idx1 -file-prefix-map %t=REMAPPED_OUT_DIR -primary-file %t/s1.swift %t/s2.swift -o %t/s1.o -c -module-name main -emit-module -emit-module-path %t/s1.swiftmodule
// RUN: %target-swift-frontend -index-store-path %t/idx1 -file-prefix-map %t=REMAPPED_OUT_DIR %t/s1.swift -primary-file %t/s2.swift -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/s2.swiftmodule
// RUN: %target-swift-frontend -index-store-path %t/idx1 -file-prefix-map %t=REMAPPED_OUT_DIR %t/s1.swiftmodule %t/s2.swiftmodule -emit-module -o %t/main.swiftmodule -module-name main
// RUN: c-index-test core -print-unit %t/idx1 >> %t/units.out

//===--- Building source files together (e.g. WMO)

// RUN: %empty-directory(%t)
// RUN: touch %t/s1.swift %t/s2.swift
// RUN: %target-swift-frontend -index-store-path %t/idx -file-prefix-map %t=REMAPPED_OUT_DIR %t/s1.swift %t/s2.swift -o %t/s1.o -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/main.swiftmodule
// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
// RUN: echo "-----together-----" >> %t/units.out
// RUN: %target-swift-frontend -index-store-path %t/idx2 -file-prefix-map %t=REMAPPED_OUT_DIR %t/s1.swift %t/s2.swift -o %t/s1.o -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/main.swiftmodule
// RUN: c-index-test core -print-unit %t/idx2 >> %t/units.out

//===--- Building separately but with relative paths for the source file inputs

// RUN: %empty-directory(%t)
// RUN: cd %t
// RUN: touch %t/s1.swift %t/s2.swift
// RUN: %target-swift-frontend -index-store-path idx -file-prefix-map %t=REMAPPED_OUT_DIR -primary-file s1.swift s2.swift -o s1.o -c -module-name main -emit-module -emit-module-path s1.swiftmodule
// RUN: %target-swift-frontend -index-store-path idx -file-prefix-map %t=REMAPPED_OUT_DIR s1.swift -primary-file s2.swift -o s2.o -c -module-name main -emit-module -emit-module-path s2.swiftmodule
// RUN: %target-swift-frontend -index-store-path idx -file-prefix-map %t=REMAPPED_OUT_DIR s1.swiftmodule s2.swiftmodule -emit-module -o main.swiftmodule -module-name main
// RUN: c-index-test core -print-unit idx | %FileCheck %s
// CHECK-NOT: main.swiftmodule-{{[A-Z0-9]*}}
// RUN: echo "-----together-relative-----" >> %t/units.out
// RUN: %target-swift-frontend -index-store-path idx3 -file-prefix-map %t=REMAPPED_OUT_DIR -primary-file s1.swift s2.swift -o s1.o -c -module-name main -emit-module -emit-module-path s1.swiftmodule
// RUN: %target-swift-frontend -index-store-path idx3 -file-prefix-map %t=REMAPPED_OUT_DIR s1.swift -primary-file s2.swift -o s2.o -c -module-name main -emit-module -emit-module-path s2.swiftmodule
// RUN: %target-swift-frontend -index-store-path idx3 -file-prefix-map %t=REMAPPED_OUT_DIR s1.swiftmodule s2.swiftmodule -emit-module -o main.swiftmodule -module-name main
// RUN: c-index-test core -print-unit idx3 >> %t/units.out

// RUN: %FileCheck %s --dump-input-filter all < %t/units.out

// CHECK: s1.o-{{2LQAU7D8TZHZ8|2RHC8ZJFDYDW4}}
// CHECK: -----separate-----
// CHECK: s1.o-[[S1_HASH:.*$]]
// CHECK: --------
// CHECK: out-file: REMAPPED_OUT_DIR{{/|\\}}s1.o
// CHECK: DEPEND START
// CHECK: Unit | system | {{.*}}Swift.swiftmodule
// CHECK: DEPEND END
// CHECK: s2.o-[[S2_HASH:.*$]]
// CHECK: --------
// CHECK: out-file: REMAPPED_OUT_DIR{{/|\\}}s2.o

// CHECK: s2.o-{{2OIL2LG8UULK6|15MCL6ZLKZKNL}}
// CHECK: -----together-----
// CHECK: s1.o-[[S1_HASH]]
// CHECK: --------
// CHECK: out-file: REMAPPED_OUT_DIR{{/|\\}}s1.o
// CHECK: s2.o-[[S2_HASH]]
// CHECK: --------
// CHECK: out-file: REMAPPED_OUT_DIR{{/|\\}}s2.o

// CHECK: -----together-relative-----
// CHECK: s1.o-[[S1_HASH]]
// CHECK: --------
// CHECK: out-file: REMAPPED_OUT_DIR{{/|\\}}s1.o
// CHECK: s2.o-[[S2_HASH]]
// CHECK: --------
// CHECK: out-file: REMAPPED_OUT_DIR{{/|\\}}s2.o
// CHECK: DEPEND START
// CHECK: Unit | system | {{.*}}Swift.swiftmodule
// CHECK: DEPEND END
25 changes: 15 additions & 10 deletions test/Index/Store/unit-one-sourcefile-remapped.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
// RUN: rm -rf %t
// RUN: %empty-directory(%t)
// RUN: mkdir -p %t/BuildRoot && cd %t/BuildRoot

// Check paths are mapped
// RUN: %target-swift-frontend -index-store-path %t/idx -file-prefix-map %S=REMAPPED_SRC_ROOT -file-prefix-map %t=REMAPPED_OUT_DIR %s -o %t/file1.o -typecheck
// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s --dump-input-filter all
// RUN: c-index-test core -print-unit %t/idx > %t/units.out

// Check round-trip remapping to make sure they're converted back to the local paths
// RUN: c-index-test core -print-unit %t/idx -index-store-prefix-map REMAPPED_SRC_ROOT=%S -index-store-prefix-map REMAPPED_OUT_DIR=%t >> %t/units.out

// RUN: %FileCheck %s --dump-input-filter all < %t/units.out

// CHECK: file1.o-1AYKXZF3HH50A
// CHECK: file1.o-[[UNIT_HASH:.*$]]
// CHECK: --------
// CHECK: main-path: REMAPPED_SRC_ROOT{{/|\\}}unit-one-sourcefile-remapped.swift
// CHECK: work-dir: REMAPPED_OUT_DIR{{/|\\}}BuildRoot
Expand All @@ -12,11 +19,9 @@
// CHECK: Unit | system | Swift | {{BUILD_DIR|.*lib\\swift\\windows}}{{.*}}Swift.swiftmodule
// CHECK: DEPEND END

// CHECK: file1.o-[[UNIT_HASH]]
// CHECK: --------
// CHECK: main-path: SOURCE_DIR{{/|\\}}test{{/|\\}}Index{{/|\\}}Store{{/|\\}}unit-one-sourcefile-remapped.swift
// CHECK-NOT: work-dir: REMAPPED_OUT_DIR

// Check round-trip remapping to make sure they're converted back to the local paths.
// RUN: c-index-test core -print-unit %t/idx -index-store-prefix-map REMAPPED_SRC_ROOT=%S -index-store-prefix-map REMAPPED_OUT_DIR=%t | %FileCheck %s -check-prefix=ROUNDTRIP --dump-input-filter all

// ROUNDTRIP: file1.o-1AYKXZF3HH50A
// ROUNDTRIP: --------
// ROUNDTRIP: main-path: SOURCE_DIR{{/|\\}}test{{/|\\}}Index{{/|\\}}Store{{/|\\}}unit-one-sourcefile-remapped.swift
// ROUNDTRIP-NOT: work-dir: REMAPPED_OUT_DIR
// CHECK-NOT: file1.o-[[UNIT_HASH]]
4 changes: 2 additions & 2 deletions test/Index/Store/unit-pcm-dependency-remapped.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func test() {
// FILE1: Record | user | {{.*}}ClangModuleB.h | ClangModuleB.h-
// FILE1: DEPEND END

// FILE1: s1.o-{{2LQAU7D8TZHZ8|2RHC8ZJFDYDW4}}
// FILE1: s1.o-
// FILE1: --------
// FILE1: has-main: 1
// FILE1-ABSOLUTE: main-path: REMAPPED_SRC_DIR{{.*}}unit-pcm-dependency-remapped.swift
Expand All @@ -81,7 +81,7 @@ func test() {

// FILE2-NOT: main.swiftmodule-

// FILE2: s2.o-{{2OIL2LG8UULK6|15MCL6ZLKZKNL}}
// FILE2: s2.o-
// FILE2: --------
// FILE2: has-main: 1
// FILE2: main-path: REMAPPED_OUT_DIR{{.*}}s2.swift
Expand Down
2 changes: 1 addition & 1 deletion test/Index/Store/unit-swiftmodule-dependency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func test() {
// CHECK: [[MODB:SwiftModuleB.swiftmodule-[A-Z0-9]*]]
// CHECK: --------
// CHECK: has-main: 1
// CHECK: out-file: {{.*}}/SwiftModuleB.swiftmodule
// CHECK: out-file: {{.*}}{{/|\\}}SwiftModuleB.swiftmodule
// CHECK: DEPEND START
// CHECK: Unit | system | Swift | {{.*}}{{/|\\}}Swift.swiftmodule
// CHECK: Unit | user | SwiftModuleA | {{.*}}{{/|\\}}SwiftModuleA.swiftmodule
Expand Down