-
Notifications
You must be signed in to change notification settings - Fork 18k
[CFI][ThinLTO] Remove the need for CFI calculating ThinLTO GUIDs #201370
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
Changes from 2 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
6f7db23
decouple cfi from thinlto
mtrofin ba2413e
Merge branch 'main' into cfi2
mtrofin 1ccc32b
feedback
mtrofin ba84783
comment nit
mtrofin ff623a4
Prior to this patch, LowerTypeTests and the ModuleSummaryIndex mapped…
mtrofin 2aa3087
rebase (merge, actually)
mtrofin f616520
Merge branch 'main' into cfi2
mtrofin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,11 +18,13 @@ | |
| #include "llvm/ADT/ArrayRef.h" | ||
| #include "llvm/ADT/DenseMap.h" | ||
| #include "llvm/ADT/STLExtras.h" | ||
| #include "llvm/ADT/SetVector.h" | ||
| #include "llvm/ADT/SmallString.h" | ||
| #include "llvm/ADT/SmallVector.h" | ||
| #include "llvm/ADT/StringExtras.h" | ||
| #include "llvm/ADT/StringMap.h" | ||
| #include "llvm/ADT/StringRef.h" | ||
| #include "llvm/ADT/StringSet.h" | ||
| #include "llvm/ADT/iterator_range.h" | ||
| #include "llvm/IR/ConstantRange.h" | ||
| #include "llvm/IR/GlobalValue.h" | ||
|
|
@@ -1317,72 +1319,75 @@ struct TypeIdSummary { | |
| std::map<uint64_t, WholeProgramDevirtResolution> WPDRes; | ||
| }; | ||
|
|
||
| /// Encapsulate the names of CFI target functions. It interfaces with ThinLTO to | ||
| /// determine efficiently which of the names need to be exported for a | ||
| /// particular module. | ||
| class CfiFunctionIndex { | ||
| DenseMap<GlobalValue::GUID, std::set<std::string, std::less<>>> Index; | ||
| using IndexIterator = | ||
| DenseMap<GlobalValue::GUID, | ||
| std::set<std::string, std::less<>>>::const_iterator; | ||
| using NestedIterator = std::set<std::string, std::less<>>::const_iterator; | ||
| // `Names` is the authoritative source of data. `ThinLTOToNamesIndex` is there | ||
| // just to efficiently retrieve which names in this index need exporting for | ||
| // a particular module index. We cannot guarantee the ThinLTO GUIDs are | ||
| // collision - free, so we associate a collection to a guid. Functions with | ||
| // the same name may have different GUIDs, too. So we index a list of names | ||
| // with the same GUID under that GUID key. We don't need the reverse because | ||
| // the queries from ThinLTO use GUIDs as key. | ||
| // Note that StringSet rehashing doesn't move keys, so we can safely store the | ||
| // StringRef value inserted in `Names` in ThinLTOToNamesIndex, and avoid | ||
| // copies. | ||
| // Design note: we could do away with Names and use ThinLTOToNamesIndex as | ||
| // index and data source, but opted against, for a small heap penalty, to | ||
| // avoid confusion wrt the role GUIDs play in this case: they are an artifact | ||
| // of the need to interface with ThinLTO, not otherwise necessary to CFI. | ||
| StringSet<> Names; | ||
|
mtrofin marked this conversation as resolved.
|
||
|
|
||
| using InternalIndexGroup = SetVector<StringRef>; | ||
| DenseMap<GlobalValue::GUID, InternalIndexGroup> ThinLTOToNamesIndex; | ||
|
|
||
| using NestedIterator = InternalIndexGroup::const_iterator; | ||
|
|
||
| public: | ||
| // Iterates keys of the DenseMap. | ||
| class GUIDIterator : public iterator_adaptor_base<GUIDIterator, IndexIterator, | ||
| std::forward_iterator_tag, | ||
| GlobalValue::GUID> { | ||
| using base = GUIDIterator::iterator_adaptor_base; | ||
|
|
||
| public: | ||
| GUIDIterator() = default; | ||
| explicit GUIDIterator(IndexIterator I) : base(I) {} | ||
|
|
||
| GlobalValue::GUID operator*() const { return this->wrapped()->first; } | ||
| }; | ||
|
|
||
| CfiFunctionIndex() = default; | ||
| template <typename It> CfiFunctionIndex(It B, It E) { | ||
| for (; B != E; ++B) | ||
| emplace(*B); | ||
| } | ||
|
|
||
| std::vector<StringRef> symbols() const { | ||
| std::vector<StringRef> Symbols; | ||
| for (auto &[GUID, Syms] : Index) { | ||
| (void)GUID; | ||
| llvm::append_range(Symbols, Syms); | ||
| } | ||
| /// API used for serialization, e.g. YAML. | ||
| std::vector<std::pair<StringRef, GlobalValue::GUID>> | ||
| getSortedSymbols() const { | ||
| std::vector<std::pair<StringRef, GlobalValue::GUID>> Symbols; | ||
| for (auto &[GUID, Names] : ThinLTOToNamesIndex) | ||
| for (auto Name : Names) | ||
| Symbols.emplace_back(Name, GUID); | ||
| llvm::sort(Symbols, std::less<>()); | ||
|
mtrofin marked this conversation as resolved.
Outdated
|
||
| return Symbols; | ||
| } | ||
|
|
||
| GUIDIterator guid_begin() const { return GUIDIterator(Index.begin()); } | ||
| GUIDIterator guid_end() const { return GUIDIterator(Index.end()); } | ||
| iterator_range<GUIDIterator> guids() const { | ||
| return make_range(guid_begin(), guid_end()); | ||
| /// get the set of GUIDs that should also be exported because they are the | ||
| /// GUIDs of the cfi functions encapsulated here. | ||
| auto getExportedThinLTOGUIDs() const { | ||
| return map_range(ThinLTOToNamesIndex, [](auto I) { return I.first; }); | ||
| } | ||
|
|
||
| iterator_range<NestedIterator> forGuid(GlobalValue::GUID GUID) const { | ||
| auto I = Index.find(GUID); | ||
| if (I == Index.end()) | ||
| /// get the name(s) associated with a given ThinLTO GUID. This enables | ||
| /// efficient identification of the subset of names that should be included in | ||
| /// a module summary. | ||
| auto getMatchingNamesForThinLTOGUID(GlobalValue::GUID GUID) const { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: prefer shorter name
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| auto I = ThinLTOToNamesIndex.find(GUID); | ||
| if (I == ThinLTOToNamesIndex.end()) | ||
| return make_range(NestedIterator{}, NestedIterator{}); | ||
| return make_range(I->second.begin(), I->second.end()); | ||
| } | ||
|
|
||
| template <typename... Args> void emplace(Args &&...A) { | ||
| StringRef S(std::forward<Args>(A)...); | ||
| GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( | ||
| GlobalValue::dropLLVMManglingEscape(S)); | ||
| Index[GUID].emplace(S); | ||
| /// Add the function name and the GUID that ThinLTO uses for it. | ||
| void addSymbolWithThinLTOGUID(StringRef Name, GlobalValue::GUID GUID) { | ||
| auto [Iter, _] = Names.insert(Name); | ||
| ThinLTOToNamesIndex[GUID].insert(Iter->first()); | ||
| } | ||
|
|
||
| size_t count(StringRef S) const { | ||
| GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage( | ||
| GlobalValue::dropLLVMManglingEscape(S)); | ||
| auto I = Index.find(GUID); | ||
| if (I == Index.end()) | ||
| return 0; | ||
| return I->second.count(S); | ||
| bool contains(StringRef Name) const { | ||
| return Names.find(Name) != Names.end(); | ||
| } | ||
|
|
||
| bool empty() const { return Index.empty(); } | ||
| bool empty() const { | ||
| assert(Names.empty() == ThinLTOToNamesIndex.empty()); | ||
| return Names.empty(); | ||
| } | ||
| }; | ||
|
|
||
| /// 160 bits SHA1 | ||
|
|
@@ -1566,7 +1571,7 @@ class ModuleSummaryIndex { | |
| // in the way some record are interpreted, like flags for instance. | ||
| // Note that incrementing this may require changes in both BitcodeReader.cpp | ||
| // and BitcodeWriter.cpp. | ||
| static constexpr uint64_t BitcodeSummaryVersion = 13; | ||
| static constexpr uint64_t BitcodeSummaryVersion = 14; | ||
|
|
||
| // Regular LTO module name for ASM writer | ||
| static constexpr const char *getRegularLTOModuleName() { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.