Skip to content

Commit 4e4e4a1

Browse files
authored
[TextAPI] Track RPaths in the order its provided via command line. (#131665)
RPaths are basically search paths for how to load dependent libraries. The order they appear is the order the linker will search, we should preserve that order in tbd files. * Additionally add this level of detection to llvm-readtapi. resolves: rdar://145603347
1 parent fa12285 commit 4e4e4a1

File tree

4 files changed

+74
-15
lines changed

4 files changed

+74
-15
lines changed

llvm/lib/TextAPI/InterfaceFile.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ void InterfaceFile::addRPath(StringRef RPath, const Target &InputTarget) {
5959
return;
6060
using RPathEntryT = const std::pair<Target, std::string>;
6161
RPathEntryT Entry(InputTarget, RPath);
62-
auto Iter =
63-
lower_bound(RPaths, Entry,
64-
[](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });
6562

66-
if ((Iter != RPaths.end()) && (*Iter == Entry))
63+
if (is_contained(RPaths, Entry))
6764
return;
6865

69-
RPaths.emplace(Iter, Entry);
66+
RPaths.emplace_back(Entry);
7067
}
7168

7269
void InterfaceFile::addTarget(const Target &Target) {

llvm/lib/TextAPI/TextStubV5.cpp

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,33 @@ using AttrToTargets = std::map<std::string, TargetList>;
8383
using TargetsToSymbols =
8484
SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;
8585

86+
/// Wrapper over a vector for handling textstub attributes, mapped to target
87+
/// triples, that require insertion order to be intact in the resulting \c
88+
/// InterfaceFile.
89+
class InOrderAttrToTargets {
90+
using EntryT = std::pair<std::string, TargetList>;
91+
92+
public:
93+
void insert(EntryT &&Entry) {
94+
auto &Element = get(Entry.first);
95+
Element.second = Entry.second;
96+
}
97+
98+
const EntryT *begin() { return Container.begin(); }
99+
const EntryT *end() { return Container.end(); }
100+
101+
private:
102+
EntryT &get(std::string &Key) {
103+
auto *It = find_if(Container,
104+
[&Key](EntryT &Input) { return Input.first == Key; });
105+
if (It != Container.end())
106+
return *It;
107+
Container.push_back(EntryT(Key, {}));
108+
return Container.back();
109+
}
110+
llvm::SmallVector<EntryT> Container;
111+
};
112+
86113
enum TBDKey : size_t {
87114
TBDVersion = 0U,
88115
MainLibrary,
@@ -437,14 +464,14 @@ Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key,
437464
return std::move(Result);
438465
}
439466

440-
Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
441-
TBDKey SubKey,
442-
const TargetList &Targets) {
467+
template <typename ReturnT = AttrToTargets>
468+
Expected<ReturnT> getLibSection(const Object *File, TBDKey Key, TBDKey SubKey,
469+
const TargetList &Targets) {
443470
auto *Section = File->getArray(Keys[Key]);
444471
if (!Section)
445-
return AttrToTargets();
472+
return ReturnT();
446473

447-
AttrToTargets Result;
474+
ReturnT Result;
448475
TargetList MappedTargets;
449476
for (auto Val : *Section) {
450477
auto *Obj = Val.getAsObject();
@@ -460,7 +487,7 @@ Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
460487
}
461488
auto Err =
462489
collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
463-
Result[Key.str()] = MappedTargets;
490+
Result.insert({Key.str(), MappedTargets});
464491
});
465492
if (Err)
466493
return std::move(Err);
@@ -629,10 +656,11 @@ Expected<IFPtr> parseToInterfaceFile(const Object *File) {
629656
return RLOrErr.takeError();
630657
AttrToTargets ReexportLibs = std::move(*RLOrErr);
631658

632-
auto RPathsOrErr = getLibSection(File, TBDKey::RPath, TBDKey::Paths, Targets);
659+
auto RPathsOrErr = getLibSection<InOrderAttrToTargets>(
660+
File, TBDKey::RPath, TBDKey::Paths, Targets);
633661
if (!RPathsOrErr)
634662
return RPathsOrErr.takeError();
635-
AttrToTargets RPaths = std::move(*RPathsOrErr);
663+
InOrderAttrToTargets RPaths = std::move(*RPathsOrErr);
636664

637665
auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports, Targets);
638666
if (!ExportsOrErr)
@@ -802,6 +830,8 @@ Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) {
802830
return Container;
803831
}
804832

833+
/// When there is no significance in order, the common case, serialize all
834+
/// attributes in a stable order.
805835
template <typename ValueT = std::string,
806836
typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
807837
Array serializeField(TBDKey Key, const AggregateT &Values,
@@ -834,6 +864,21 @@ Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values,
834864
return serializeAttrToTargets(FinalEntries, Key);
835865
}
836866

867+
template <
868+
typename AggregateT = std::vector<std::pair<MachO::Target, std::string>>>
869+
Array serializeFieldInInsertionOrder(TBDKey Key, const AggregateT &Values,
870+
const TargetList &ActiveTargets) {
871+
MapVector<StringRef, std::set<MachO::Target>> Entries;
872+
for (const auto &[Target, Val] : Values)
873+
Entries[Val].insert(Target);
874+
875+
TargetsToValuesMap FinalEntries;
876+
for (const auto &[Val, Targets] : Entries)
877+
FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(
878+
Val.str());
879+
return serializeAttrToTargets(FinalEntries, Key);
880+
}
881+
837882
struct SymbolFields {
838883
struct SymbolTypes {
839884
std::vector<StringRef> Weaks;
@@ -963,7 +1008,8 @@ Expected<Object> serializeIF(const InterfaceFile *File) {
9631008
TBDKey::ABI, File->getSwiftABIVersion(), 0u);
9641009
insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI));
9651010

966-
Array RPaths = serializeField(TBDKey::Paths, File->rpaths(), ActiveTargets);
1011+
Array RPaths = serializeFieldInInsertionOrder(TBDKey::Paths, File->rpaths(),
1012+
ActiveTargets);
9671013
insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths));
9681014

9691015
Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(),
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; RUN: rm -rf %t
2+
; RUN: split-file %s %t
3+
; RUN: not llvm-readtapi --compare %t/rpaths_diff_order.tbd %t/rpaths.tbd 2>&1 | FileCheck %s
4+
5+
; CHECK: < {{.*}}rpaths_diff_order.tbd
6+
; CHECK: > {{.*}}rpaths.tbd
7+
8+
; CHECK: 'Run Path Search Paths' differ by order
9+
10+
//--- rpaths_diff_order.tbd
11+
{"main_library":{"exported_symbols":[{"text":{"global":["_foo"]}}],"rpaths": [{"paths": ["/usr/lib/swift", "@loader_path/../../../"]}], "flags":[{"attributes":["not_app_extension_safe"]}],"install_names":[{"name":"@rpath/libFake.dylib"}],"target_info":[{"min_deployment":"13","target":"x86_64-macos"},{"min_deployment":"13","target":"arm64-macos"}]},"tapi_tbd_version":5}
12+
13+
//--- rpaths.tbd
14+
{"main_library":{"exported_symbols":[{"text":{"global":["_foo"]}}],"rpaths": [{"paths": [ "@loader_path/../../../", "/usr/lib/swift"]}], "flags":[{"attributes":["not_app_extension_safe"]}],"install_names":[{"name":"@rpath/libFake.dylib"}],"target_info":[{"min_deployment":"13","target":"x86_64-macos"},{"min_deployment":"13","target":"arm64-macos"}]},"tapi_tbd_version":5}

llvm/tools/llvm-readtapi/DiffEngine.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,10 @@ template <typename T> void sortTargetValues(std::vector<T> &TargValues) {
449449

450450
template <typename T>
451451
void printVecVal(std::string Indent, const DiffOutput &Attr, raw_ostream &OS) {
452-
if (Attr.Values.empty())
452+
if (Attr.Values.empty()) {
453+
OS << Indent << "'" << Attr.Name << "' differ by order\n";
453454
return;
455+
}
454456

455457
OS << Indent << Attr.Name << "\n";
456458

0 commit comments

Comments
 (0)