@@ -83,6 +83,33 @@ using AttrToTargets = std::map<std::string, TargetList>;
8383using 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+
86113enum 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.
805835template <typename ValueT = std::string,
806836 typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
807837Array 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+
837882struct 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 (),
0 commit comments