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