@@ -83,6 +83,33 @@ using AttrToTargets = std::map<std::string, TargetList>;
83
83
using TargetsToSymbols =
84
84
SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;
85
85
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
+
86
113
enum TBDKey : size_t {
87
114
TBDVersion = 0U ,
88
115
MainLibrary,
@@ -437,14 +464,14 @@ Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key,
437
464
return std::move (Result);
438
465
}
439
466
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) {
443
470
auto *Section = File->getArray (Keys[Key]);
444
471
if (!Section)
445
- return AttrToTargets ();
472
+ return ReturnT ();
446
473
447
- AttrToTargets Result;
474
+ ReturnT Result;
448
475
TargetList MappedTargets;
449
476
for (auto Val : *Section) {
450
477
auto *Obj = Val.getAsObject ();
@@ -460,7 +487,7 @@ Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
460
487
}
461
488
auto Err =
462
489
collectFromArray (SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
463
- Result[ Key.str ()] = MappedTargets;
490
+ Result. insert ({ Key.str (), MappedTargets}) ;
464
491
});
465
492
if (Err)
466
493
return std::move (Err);
@@ -629,10 +656,11 @@ Expected<IFPtr> parseToInterfaceFile(const Object *File) {
629
656
return RLOrErr.takeError ();
630
657
AttrToTargets ReexportLibs = std::move (*RLOrErr);
631
658
632
- auto RPathsOrErr = getLibSection (File, TBDKey::RPath, TBDKey::Paths, Targets);
659
+ auto RPathsOrErr = getLibSection<InOrderAttrToTargets>(
660
+ File, TBDKey::RPath, TBDKey::Paths, Targets);
633
661
if (!RPathsOrErr)
634
662
return RPathsOrErr.takeError ();
635
- AttrToTargets RPaths = std::move (*RPathsOrErr);
663
+ InOrderAttrToTargets RPaths = std::move (*RPathsOrErr);
636
664
637
665
auto ExportsOrErr = getSymbolSection (File, TBDKey::Exports, Targets);
638
666
if (!ExportsOrErr)
@@ -802,6 +830,8 @@ Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) {
802
830
return Container;
803
831
}
804
832
833
+ // / When there is no significance in order, the common case, serialize all
834
+ // / attributes in a stable order.
805
835
template <typename ValueT = std::string,
806
836
typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
807
837
Array serializeField (TBDKey Key, const AggregateT &Values,
@@ -834,6 +864,21 @@ Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values,
834
864
return serializeAttrToTargets (FinalEntries, Key);
835
865
}
836
866
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
+
837
882
struct SymbolFields {
838
883
struct SymbolTypes {
839
884
std::vector<StringRef> Weaks;
@@ -963,7 +1008,8 @@ Expected<Object> serializeIF(const InterfaceFile *File) {
963
1008
TBDKey::ABI, File->getSwiftABIVersion (), 0u );
964
1009
insertNonEmptyValues (Library, TBDKey::SwiftABI, std::move (SwiftABI));
965
1010
966
- Array RPaths = serializeField (TBDKey::Paths, File->rpaths (), ActiveTargets);
1011
+ Array RPaths = serializeFieldInInsertionOrder (TBDKey::Paths, File->rpaths (),
1012
+ ActiveTargets);
967
1013
insertNonEmptyValues (Library, TBDKey::RPath, std::move (RPaths));
968
1014
969
1015
Array Umbrellas = serializeField (TBDKey::Umbrella, File->umbrellas (),
0 commit comments