Skip to content

Commit 01c47c2

Browse files
committed
rustc: Tweak the isExported callback for ThinLTO
Previously we were too eagerly exporting almost all symbols used in ThinLTO which can cause a whole host of problems downstream! This commit instead fixes this error by aligning more closely with `lib/LTO/LTO.cpp` in LLVM's codebase which is to only change the linkage of summaries which are computed as dead. Closes #46374
1 parent 4fa202d commit 01c47c2

File tree

1 file changed

+23
-87
lines changed

1 file changed

+23
-87
lines changed

src/rustllvm/PassWrapper.cpp

+23-87
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <stdio.h>
1212

1313
#include <vector>
14+
#include <set>
1415

1516
#include "rustllvm.h"
1617

@@ -885,86 +886,6 @@ getFirstDefinitionForLinker(const GlobalValueSummaryList &GVSummaryList) {
885886
return FirstDefForLinker->get();
886887
}
887888

888-
// This is a helper function we added that isn't present in LLVM's source.
889-
//
890-
// The way LTO works in Rust is that we typically have a number of symbols that
891-
// we know ahead of time need to be preserved. We want to ensure that ThinLTO
892-
// doesn't accidentally internalize any of these and otherwise is always
893-
// ready to keep them linking correctly.
894-
//
895-
// This function will recursively walk the `GUID` provided and all of its
896-
// references, as specified in the `Index`. In other words, we're taking a
897-
// `GUID` as input, adding it to `Preserved`, and then taking all `GUID`
898-
// items that the input references and recursing.
899-
static void
900-
addPreservedGUID(const ModuleSummaryIndex &Index,
901-
DenseSet<GlobalValue::GUID> &Preserved,
902-
GlobalValue::GUID GUID) {
903-
if (Preserved.count(GUID))
904-
return;
905-
Preserved.insert(GUID);
906-
907-
#if LLVM_VERSION_GE(5, 0)
908-
auto Info = Index.getValueInfo(GUID);
909-
if (!Info) {
910-
return;
911-
}
912-
for (auto &Summary : Info.getSummaryList()) {
913-
for (auto &Ref : Summary->refs()) {
914-
addPreservedGUID(Index, Preserved, Ref.getGUID());
915-
}
916-
917-
GlobalValueSummary *GVSummary = Summary.get();
918-
if (isa<FunctionSummary>(GVSummary)) {
919-
auto *FS = cast<FunctionSummary>(GVSummary);
920-
for (auto &Call: FS->calls()) {
921-
addPreservedGUID(Index, Preserved, Call.first.getGUID());
922-
}
923-
for (auto &GUID: FS->type_tests()) {
924-
addPreservedGUID(Index, Preserved, GUID);
925-
}
926-
}
927-
if (isa<AliasSummary>(GVSummary)) {
928-
auto *AS = cast<AliasSummary>(GVSummary);
929-
auto GUID = AS->getAliasee().getOriginalName();
930-
addPreservedGUID(Index, Preserved, GUID);
931-
}
932-
}
933-
#else
934-
auto SummaryList = Index.findGlobalValueSummaryList(GUID);
935-
if (SummaryList == Index.end())
936-
return;
937-
for (auto &Summary : SummaryList->second) {
938-
for (auto &Ref : Summary->refs()) {
939-
if (Ref.isGUID()) {
940-
addPreservedGUID(Index, Preserved, Ref.getGUID());
941-
} else {
942-
auto Value = Ref.getValue();
943-
addPreservedGUID(Index, Preserved, Value->getGUID());
944-
}
945-
}
946-
947-
if (auto *FS = dyn_cast<FunctionSummary>(Summary.get())) {
948-
for (auto &Call: FS->calls()) {
949-
if (Call.first.isGUID()) {
950-
addPreservedGUID(Index, Preserved, Call.first.getGUID());
951-
} else {
952-
auto Value = Call.first.getValue();
953-
addPreservedGUID(Index, Preserved, Value->getGUID());
954-
}
955-
}
956-
for (auto &GUID: FS->type_tests()) {
957-
addPreservedGUID(Index, Preserved, GUID);
958-
}
959-
}
960-
if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
961-
auto GUID = AS->getAliasee().getOriginalName();
962-
addPreservedGUID(Index, Preserved, GUID);
963-
}
964-
}
965-
#endif
966-
}
967-
968889
// The main entry point for creating the global ThinLTO analysis. The structure
969890
// here is basically the same as before threads are spawned in the `run`
970891
// function of `lib/LTO/ThinLTOCodeGenerator.cpp`.
@@ -1004,12 +925,10 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1004925
Ret->Index.collectDefinedGVSummariesPerModule(Ret->ModuleToDefinedGVSummaries);
1005926

1006927
// Convert the preserved symbols set from string to GUID, this is then needed
1007-
// for internalization. We use `addPreservedGUID` to include any transitively
1008-
// used symbol as well.
928+
// for internalization.
1009929
for (int i = 0; i < num_symbols; i++) {
1010-
addPreservedGUID(Ret->Index,
1011-
Ret->GUIDPreservedSymbols,
1012-
GlobalValue::getGUID(preserved_symbols[i]));
930+
auto GUID = GlobalValue::getGUID(preserved_symbols[i]);
931+
Ret->GUIDPreservedSymbols.insert(GUID);
1013932
}
1014933

1015934
// Collect the import/export lists for all modules from the call-graph in the
@@ -1038,7 +957,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1038957
// Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
1039958
// impacts the caching.
1040959
//
1041-
// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
960+
// This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp` with some of this
961+
// being lifted from `lib/LTO/LTO.cpp` as well
1042962
StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
1043963
DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
1044964
for (auto &I : Ret->Index) {
@@ -1062,11 +982,27 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
1062982
ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
1063983
};
1064984
thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);
985+
986+
// Here we calculate an `ExportedGUIDs` set for use in the `isExported`
987+
// callback below. This callback below will dictate the linkage for all
988+
// summaries in the index, and we basically just only want to ensure that dead
989+
// symbols are internalized. Otherwise everything that's already external
990+
// linkage will stay as external, and internal will stay as internal.
991+
std::set<GlobalValue::GUID> ExportedGUIDs;
992+
for (auto &List : Ret->Index) {
993+
for (auto &GVS: List.second) {
994+
if (!GlobalValue::isExternalLinkage(GVS->linkage()))
995+
continue;
996+
auto GUID = GVS->getOriginalName();
997+
if (!DeadSymbols.count(GUID))
998+
ExportedGUIDs.insert(GUID);
999+
}
1000+
}
10651001
auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
10661002
const auto &ExportList = Ret->ExportLists.find(ModuleIdentifier);
10671003
return (ExportList != Ret->ExportLists.end() &&
10681004
ExportList->second.count(GUID)) ||
1069-
Ret->GUIDPreservedSymbols.count(GUID);
1005+
ExportedGUIDs.count(GUID);
10701006
};
10711007
thinLTOInternalizeAndPromoteInIndex(Ret->Index, isExported);
10721008

0 commit comments

Comments
 (0)