TextStub.cpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  1. //===- TextStub.cpp -------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Implements the text stub file reader/writer.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "TextAPIContext.h"
  13. #include "TextStubCommon.h"
  14. #include "llvm/ADT/BitmaskEnum.h"
  15. #include "llvm/ADT/SmallString.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/Support/Allocator.h"
  18. #include "llvm/Support/SourceMgr.h"
  19. #include "llvm/Support/YAMLTraits.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #include "llvm/TextAPI/MachO/Architecture.h"
  22. #include "llvm/TextAPI/MachO/ArchitectureSet.h"
  23. #include "llvm/TextAPI/MachO/InterfaceFile.h"
  24. #include "llvm/TextAPI/MachO/PackedVersion.h"
  25. #include "llvm/TextAPI/MachO/TextAPIReader.h"
  26. #include "llvm/TextAPI/MachO/TextAPIWriter.h"
  27. #include <algorithm>
  28. #include <set>
  29. // clang-format off
  30. /*
  31. YAML Format specification.
  32. The TBD v1 format only support two level address libraries and is per
  33. definition application extension safe.
  34. --- # the tag !tapi-tbd-v1 is optional and
  35. # shouldn't be emitted to support older linker.
  36. archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
  37. # supported by this file.
  38. platform: ios # Specifies the platform (macosx, ios, etc)
  39. install-name: /u/l/libfoo.dylib #
  40. current-version: 1.2.3 # Optional: defaults to 1.0
  41. compatibility-version: 1.0 # Optional: defaults to 1.0
  42. swift-version: 0 # Optional: defaults to 0
  43. objc-constraint: none # Optional: defaults to none
  44. exports: # List of export sections
  45. ...
  46. Each export section is defined as following:
  47. - archs: [ arm64 ] # the list of architecture slices
  48. allowed-clients: [ client ] # Optional: List of clients
  49. re-exports: [ ] # Optional: List of re-exports
  50. symbols: [ _sym ] # Optional: List of symbols
  51. objc-classes: [] # Optional: List of Objective-C classes
  52. objc-ivars: [] # Optional: List of Objective C Instance
  53. # Variables
  54. weak-def-symbols: [] # Optional: List of weak defined symbols
  55. thread-local-symbols: [] # Optional: List of thread local symbols
  56. */
  57. /*
  58. YAML Format specification.
  59. --- !tapi-tbd-v2
  60. archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
  61. # supported by this file.
  62. uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs.
  63. platform: ios # Specifies the platform (macosx, ios, etc)
  64. flags: [] # Optional:
  65. install-name: /u/l/libfoo.dylib #
  66. current-version: 1.2.3 # Optional: defaults to 1.0
  67. compatibility-version: 1.0 # Optional: defaults to 1.0
  68. swift-version: 0 # Optional: defaults to 0
  69. objc-constraint: retain_release # Optional: defaults to retain_release
  70. parent-umbrella: # Optional:
  71. exports: # List of export sections
  72. ...
  73. undefineds: # List of undefineds sections
  74. ...
  75. Each export section is defined as following:
  76. - archs: [ arm64 ] # the list of architecture slices
  77. allowed-clients: [ client ] # Optional: List of clients
  78. re-exports: [ ] # Optional: List of re-exports
  79. symbols: [ _sym ] # Optional: List of symbols
  80. objc-classes: [] # Optional: List of Objective-C classes
  81. objc-ivars: [] # Optional: List of Objective C Instance
  82. # Variables
  83. weak-def-symbols: [] # Optional: List of weak defined symbols
  84. thread-local-symbols: [] # Optional: List of thread local symbols
  85. Each undefineds section is defined as following:
  86. - archs: [ arm64 ] # the list of architecture slices
  87. symbols: [ _sym ] # Optional: List of symbols
  88. objc-classes: [] # Optional: List of Objective-C classes
  89. objc-ivars: [] # Optional: List of Objective C Instance Variables
  90. weak-ref-symbols: [] # Optional: List of weak defined symbols
  91. */
  92. /*
  93. YAML Format specification.
  94. --- !tapi-tbd-v3
  95. archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
  96. # supported by this file.
  97. uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs.
  98. platform: ios # Specifies the platform (macosx, ios, etc)
  99. flags: [] # Optional:
  100. install-name: /u/l/libfoo.dylib #
  101. current-version: 1.2.3 # Optional: defaults to 1.0
  102. compatibility-version: 1.0 # Optional: defaults to 1.0
  103. swift-abi-version: 0 # Optional: defaults to 0
  104. objc-constraint: retain_release # Optional: defaults to retain_release
  105. parent-umbrella: # Optional:
  106. exports: # List of export sections
  107. ...
  108. undefineds: # List of undefineds sections
  109. ...
  110. Each export section is defined as following:
  111. - archs: [ arm64 ] # the list of architecture slices
  112. allowed-clients: [ client ] # Optional: List of clients
  113. re-exports: [ ] # Optional: List of re-exports
  114. symbols: [ _sym ] # Optional: List of symbols
  115. objc-classes: [] # Optional: List of Objective-C classes
  116. objc-eh-types: [] # Optional: List of Objective-C classes
  117. # with EH
  118. objc-ivars: [] # Optional: List of Objective C Instance
  119. # Variables
  120. weak-def-symbols: [] # Optional: List of weak defined symbols
  121. thread-local-symbols: [] # Optional: List of thread local symbols
  122. Each undefineds section is defined as following:
  123. - archs: [ arm64 ] # the list of architecture slices
  124. symbols: [ _sym ] # Optional: List of symbols
  125. objc-classes: [] # Optional: List of Objective-C classes
  126. objc-eh-types: [] # Optional: List of Objective-C classes
  127. # with EH
  128. objc-ivars: [] # Optional: List of Objective C Instance Variables
  129. weak-ref-symbols: [] # Optional: List of weak defined symbols
  130. */
  131. /*
  132. YAML Format specification.
  133. --- !tapi-tbd
  134. tbd-version: 4 # The tbd version for format
  135. targets: [ armv7-ios, x86_64-maccatalyst ] # The list of applicable tapi supported target triples
  136. uuids: # Optional: List of target and UUID pairs.
  137. - target: armv7-ios
  138. value: ...
  139. - target: x86_64-maccatalyst
  140. value: ...
  141. flags: [] # Optional:
  142. install-name: /u/l/libfoo.dylib #
  143. current-version: 1.2.3 # Optional: defaults to 1.0
  144. compatibility-version: 1.0 # Optional: defaults to 1.0
  145. swift-abi-version: 0 # Optional: defaults to 0
  146. parent-umbrella: # Optional:
  147. allowable-clients:
  148. - targets: [ armv7-ios ] # Optional:
  149. clients: [ clientA ]
  150. exports: # List of export sections
  151. ...
  152. re-exports: # List of reexport sections
  153. ...
  154. undefineds: # List of undefineds sections
  155. ...
  156. Each export and reexport section is defined as following:
  157. - targets: [ arm64-macos ] # The list of target triples associated with symbols
  158. symbols: [ _symA ] # Optional: List of symbols
  159. objc-classes: [] # Optional: List of Objective-C classes
  160. objc-eh-types: [] # Optional: List of Objective-C classes
  161. # with EH
  162. objc-ivars: [] # Optional: List of Objective C Instance
  163. # Variables
  164. weak-symbols: [] # Optional: List of weak defined symbols
  165. thread-local-symbols: [] # Optional: List of thread local symbols
  166. - targets: [ arm64-macos, x86_64-maccatalyst ] # Optional: Targets for applicable additional symbols
  167. symbols: [ _symB ] # Optional: List of symbols
  168. Each undefineds section is defined as following:
  169. - targets: [ arm64-macos ] # The list of target triples associated with symbols
  170. symbols: [ _symC ] # Optional: List of symbols
  171. objc-classes: [] # Optional: List of Objective-C classes
  172. objc-eh-types: [] # Optional: List of Objective-C classes
  173. # with EH
  174. objc-ivars: [] # Optional: List of Objective C Instance Variables
  175. weak-symbols: [] # Optional: List of weak defined symbols
  176. */
  177. // clang-format on
  178. using namespace llvm;
  179. using namespace llvm::yaml;
  180. using namespace llvm::MachO;
  181. namespace {
  182. struct ExportSection {
  183. std::vector<Architecture> Architectures;
  184. std::vector<FlowStringRef> AllowableClients;
  185. std::vector<FlowStringRef> ReexportedLibraries;
  186. std::vector<FlowStringRef> Symbols;
  187. std::vector<FlowStringRef> Classes;
  188. std::vector<FlowStringRef> ClassEHs;
  189. std::vector<FlowStringRef> IVars;
  190. std::vector<FlowStringRef> WeakDefSymbols;
  191. std::vector<FlowStringRef> TLVSymbols;
  192. };
  193. struct UndefinedSection {
  194. std::vector<Architecture> Architectures;
  195. std::vector<FlowStringRef> Symbols;
  196. std::vector<FlowStringRef> Classes;
  197. std::vector<FlowStringRef> ClassEHs;
  198. std::vector<FlowStringRef> IVars;
  199. std::vector<FlowStringRef> WeakRefSymbols;
  200. };
  201. // Sections for direct target mapping in TBDv4
  202. struct SymbolSection {
  203. TargetList Targets;
  204. std::vector<FlowStringRef> Symbols;
  205. std::vector<FlowStringRef> Classes;
  206. std::vector<FlowStringRef> ClassEHs;
  207. std::vector<FlowStringRef> Ivars;
  208. std::vector<FlowStringRef> WeakSymbols;
  209. std::vector<FlowStringRef> TlvSymbols;
  210. };
  211. struct MetadataSection {
  212. enum Option { Clients, Libraries };
  213. std::vector<Target> Targets;
  214. std::vector<FlowStringRef> Values;
  215. };
  216. struct UmbrellaSection {
  217. std::vector<Target> Targets;
  218. std::string Umbrella;
  219. };
  220. // UUID's for TBDv4 are mapped to target not arch
  221. struct UUIDv4 {
  222. Target TargetID;
  223. std::string Value;
  224. UUIDv4() = default;
  225. UUIDv4(const Target &TargetID, const std::string &Value)
  226. : TargetID(TargetID), Value(Value) {}
  227. };
  228. // clang-format off
  229. enum TBDFlags : unsigned {
  230. None = 0U,
  231. FlatNamespace = 1U << 0,
  232. NotApplicationExtensionSafe = 1U << 1,
  233. InstallAPI = 1U << 2,
  234. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
  235. };
  236. // clang-format on
  237. } // end anonymous namespace.
  238. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
  239. LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
  240. LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
  241. // Specific to TBDv4
  242. LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
  243. LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
  244. LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
  245. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
  246. LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
  247. namespace llvm {
  248. namespace yaml {
  249. template <> struct MappingTraits<ExportSection> {
  250. static void mapping(IO &IO, ExportSection &Section) {
  251. const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  252. assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
  253. "File type is not set in YAML context");
  254. IO.mapRequired("archs", Section.Architectures);
  255. if (Ctx->FileKind == FileType::TBD_V1)
  256. IO.mapOptional("allowed-clients", Section.AllowableClients);
  257. else
  258. IO.mapOptional("allowable-clients", Section.AllowableClients);
  259. IO.mapOptional("re-exports", Section.ReexportedLibraries);
  260. IO.mapOptional("symbols", Section.Symbols);
  261. IO.mapOptional("objc-classes", Section.Classes);
  262. if (Ctx->FileKind == FileType::TBD_V3)
  263. IO.mapOptional("objc-eh-types", Section.ClassEHs);
  264. IO.mapOptional("objc-ivars", Section.IVars);
  265. IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
  266. IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
  267. }
  268. };
  269. template <> struct MappingTraits<UndefinedSection> {
  270. static void mapping(IO &IO, UndefinedSection &Section) {
  271. const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  272. assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
  273. "File type is not set in YAML context");
  274. IO.mapRequired("archs", Section.Architectures);
  275. IO.mapOptional("symbols", Section.Symbols);
  276. IO.mapOptional("objc-classes", Section.Classes);
  277. if (Ctx->FileKind == FileType::TBD_V3)
  278. IO.mapOptional("objc-eh-types", Section.ClassEHs);
  279. IO.mapOptional("objc-ivars", Section.IVars);
  280. IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
  281. }
  282. };
  283. template <> struct MappingTraits<SymbolSection> {
  284. static void mapping(IO &IO, SymbolSection &Section) {
  285. IO.mapRequired("targets", Section.Targets);
  286. IO.mapOptional("symbols", Section.Symbols);
  287. IO.mapOptional("objc-classes", Section.Classes);
  288. IO.mapOptional("objc-eh-types", Section.ClassEHs);
  289. IO.mapOptional("objc-ivars", Section.Ivars);
  290. IO.mapOptional("weak-symbols", Section.WeakSymbols);
  291. IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
  292. }
  293. };
  294. template <> struct MappingTraits<UmbrellaSection> {
  295. static void mapping(IO &IO, UmbrellaSection &Section) {
  296. IO.mapRequired("targets", Section.Targets);
  297. IO.mapRequired("umbrella", Section.Umbrella);
  298. }
  299. };
  300. template <> struct MappingTraits<UUIDv4> {
  301. static void mapping(IO &IO, UUIDv4 &UUID) {
  302. IO.mapRequired("target", UUID.TargetID);
  303. IO.mapRequired("value", UUID.Value);
  304. }
  305. };
  306. template <>
  307. struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
  308. static void mapping(IO &IO, MetadataSection &Section,
  309. MetadataSection::Option &OptionKind) {
  310. IO.mapRequired("targets", Section.Targets);
  311. switch (OptionKind) {
  312. case MetadataSection::Option::Clients:
  313. IO.mapRequired("clients", Section.Values);
  314. return;
  315. case MetadataSection::Option::Libraries:
  316. IO.mapRequired("libraries", Section.Values);
  317. return;
  318. }
  319. llvm_unreachable("unexpected option for metadata");
  320. }
  321. };
  322. template <> struct ScalarBitSetTraits<TBDFlags> {
  323. static void bitset(IO &IO, TBDFlags &Flags) {
  324. IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
  325. IO.bitSetCase(Flags, "not_app_extension_safe",
  326. TBDFlags::NotApplicationExtensionSafe);
  327. IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
  328. }
  329. };
  330. template <> struct ScalarTraits<Target> {
  331. static void output(const Target &Value, void *, raw_ostream &OS) {
  332. OS << Value.Arch << "-";
  333. switch (Value.Platform) {
  334. default:
  335. OS << "unknown";
  336. break;
  337. case PlatformKind::macOS:
  338. OS << "macos";
  339. break;
  340. case PlatformKind::iOS:
  341. OS << "ios";
  342. break;
  343. case PlatformKind::tvOS:
  344. OS << "tvos";
  345. break;
  346. case PlatformKind::watchOS:
  347. OS << "watchos";
  348. break;
  349. case PlatformKind::bridgeOS:
  350. OS << "bridgeos";
  351. break;
  352. case PlatformKind::macCatalyst:
  353. OS << "maccatalyst";
  354. break;
  355. case PlatformKind::iOSSimulator:
  356. OS << "ios-simulator";
  357. break;
  358. case PlatformKind::tvOSSimulator:
  359. OS << "tvos-simulator";
  360. break;
  361. case PlatformKind::watchOSSimulator:
  362. OS << "watchos-simulator";
  363. break;
  364. case PlatformKind::driverKit:
  365. OS << "driverkit";
  366. break;
  367. }
  368. }
  369. static StringRef input(StringRef Scalar, void *, Target &Value) {
  370. auto Result = Target::create(Scalar);
  371. if (!Result) {
  372. consumeError(Result.takeError());
  373. return "unparsable target";
  374. }
  375. Value = *Result;
  376. if (Value.Arch == AK_unknown)
  377. return "unknown architecture";
  378. if (Value.Platform == PlatformKind::unknown)
  379. return "unknown platform";
  380. return {};
  381. }
  382. static QuotingType mustQuote(StringRef) { return QuotingType::None; }
  383. };
  384. template <> struct MappingTraits<const InterfaceFile *> {
  385. struct NormalizedTBD {
  386. explicit NormalizedTBD(IO &IO) {}
  387. NormalizedTBD(IO &IO, const InterfaceFile *&File) {
  388. Architectures = File->getArchitectures();
  389. UUIDs = File->uuids();
  390. Platforms = File->getPlatforms();
  391. InstallName = File->getInstallName();
  392. CurrentVersion = PackedVersion(File->getCurrentVersion());
  393. CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
  394. SwiftABIVersion = File->getSwiftABIVersion();
  395. ObjCConstraint = File->getObjCConstraint();
  396. Flags = TBDFlags::None;
  397. if (!File->isApplicationExtensionSafe())
  398. Flags |= TBDFlags::NotApplicationExtensionSafe;
  399. if (!File->isTwoLevelNamespace())
  400. Flags |= TBDFlags::FlatNamespace;
  401. if (File->isInstallAPI())
  402. Flags |= TBDFlags::InstallAPI;
  403. if (!File->umbrellas().empty())
  404. ParentUmbrella = File->umbrellas().begin()->second;
  405. std::set<ArchitectureSet> ArchSet;
  406. for (const auto &Library : File->allowableClients())
  407. ArchSet.insert(Library.getArchitectures());
  408. for (const auto &Library : File->reexportedLibraries())
  409. ArchSet.insert(Library.getArchitectures());
  410. std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
  411. for (const auto *Symbol : File->exports()) {
  412. auto Architectures = Symbol->getArchitectures();
  413. SymbolToArchSet[Symbol] = Architectures;
  414. ArchSet.insert(Architectures);
  415. }
  416. for (auto Architectures : ArchSet) {
  417. ExportSection Section;
  418. Section.Architectures = Architectures;
  419. for (const auto &Library : File->allowableClients())
  420. if (Library.getArchitectures() == Architectures)
  421. Section.AllowableClients.emplace_back(Library.getInstallName());
  422. for (const auto &Library : File->reexportedLibraries())
  423. if (Library.getArchitectures() == Architectures)
  424. Section.ReexportedLibraries.emplace_back(Library.getInstallName());
  425. for (const auto &SymArch : SymbolToArchSet) {
  426. if (SymArch.second != Architectures)
  427. continue;
  428. const auto *Symbol = SymArch.first;
  429. switch (Symbol->getKind()) {
  430. case SymbolKind::GlobalSymbol:
  431. if (Symbol->isWeakDefined())
  432. Section.WeakDefSymbols.emplace_back(Symbol->getName());
  433. else if (Symbol->isThreadLocalValue())
  434. Section.TLVSymbols.emplace_back(Symbol->getName());
  435. else
  436. Section.Symbols.emplace_back(Symbol->getName());
  437. break;
  438. case SymbolKind::ObjectiveCClass:
  439. if (File->getFileType() != FileType::TBD_V3)
  440. Section.Classes.emplace_back(
  441. copyString("_" + Symbol->getName().str()));
  442. else
  443. Section.Classes.emplace_back(Symbol->getName());
  444. break;
  445. case SymbolKind::ObjectiveCClassEHType:
  446. if (File->getFileType() != FileType::TBD_V3)
  447. Section.Symbols.emplace_back(
  448. copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
  449. else
  450. Section.ClassEHs.emplace_back(Symbol->getName());
  451. break;
  452. case SymbolKind::ObjectiveCInstanceVariable:
  453. if (File->getFileType() != FileType::TBD_V3)
  454. Section.IVars.emplace_back(
  455. copyString("_" + Symbol->getName().str()));
  456. else
  457. Section.IVars.emplace_back(Symbol->getName());
  458. break;
  459. }
  460. }
  461. llvm::sort(Section.Symbols);
  462. llvm::sort(Section.Classes);
  463. llvm::sort(Section.ClassEHs);
  464. llvm::sort(Section.IVars);
  465. llvm::sort(Section.WeakDefSymbols);
  466. llvm::sort(Section.TLVSymbols);
  467. Exports.emplace_back(std::move(Section));
  468. }
  469. ArchSet.clear();
  470. SymbolToArchSet.clear();
  471. for (const auto *Symbol : File->undefineds()) {
  472. auto Architectures = Symbol->getArchitectures();
  473. SymbolToArchSet[Symbol] = Architectures;
  474. ArchSet.insert(Architectures);
  475. }
  476. for (auto Architectures : ArchSet) {
  477. UndefinedSection Section;
  478. Section.Architectures = Architectures;
  479. for (const auto &SymArch : SymbolToArchSet) {
  480. if (SymArch.second != Architectures)
  481. continue;
  482. const auto *Symbol = SymArch.first;
  483. switch (Symbol->getKind()) {
  484. case SymbolKind::GlobalSymbol:
  485. if (Symbol->isWeakReferenced())
  486. Section.WeakRefSymbols.emplace_back(Symbol->getName());
  487. else
  488. Section.Symbols.emplace_back(Symbol->getName());
  489. break;
  490. case SymbolKind::ObjectiveCClass:
  491. if (File->getFileType() != FileType::TBD_V3)
  492. Section.Classes.emplace_back(
  493. copyString("_" + Symbol->getName().str()));
  494. else
  495. Section.Classes.emplace_back(Symbol->getName());
  496. break;
  497. case SymbolKind::ObjectiveCClassEHType:
  498. if (File->getFileType() != FileType::TBD_V3)
  499. Section.Symbols.emplace_back(
  500. copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
  501. else
  502. Section.ClassEHs.emplace_back(Symbol->getName());
  503. break;
  504. case SymbolKind::ObjectiveCInstanceVariable:
  505. if (File->getFileType() != FileType::TBD_V3)
  506. Section.IVars.emplace_back(
  507. copyString("_" + Symbol->getName().str()));
  508. else
  509. Section.IVars.emplace_back(Symbol->getName());
  510. break;
  511. }
  512. }
  513. llvm::sort(Section.Symbols);
  514. llvm::sort(Section.Classes);
  515. llvm::sort(Section.ClassEHs);
  516. llvm::sort(Section.IVars);
  517. llvm::sort(Section.WeakRefSymbols);
  518. Undefineds.emplace_back(std::move(Section));
  519. }
  520. }
  521. // TBD v1 - TBD v3 files only support one platform and several
  522. // architectures. It is possible to have more than one platform for TBD v3
  523. // files, but the architectures don't apply to all
  524. // platforms, specifically to filter out the i386 slice from
  525. // platform macCatalyst.
  526. TargetList synthesizeTargets(ArchitectureSet Architectures,
  527. const PlatformSet &Platforms) {
  528. TargetList Targets;
  529. for (auto Platform : Platforms) {
  530. Platform = mapToPlatformKind(Platform, Architectures.hasX86());
  531. for (const auto &&Architecture : Architectures) {
  532. if ((Architecture == AK_i386) &&
  533. (Platform == PlatformKind::macCatalyst))
  534. continue;
  535. Targets.emplace_back(Architecture, Platform);
  536. }
  537. }
  538. return Targets;
  539. }
  540. const InterfaceFile *denormalize(IO &IO) {
  541. auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  542. assert(Ctx);
  543. auto *File = new InterfaceFile;
  544. File->setPath(Ctx->Path);
  545. File->setFileType(Ctx->FileKind);
  546. File->addTargets(synthesizeTargets(Architectures, Platforms));
  547. for (auto &ID : UUIDs)
  548. File->addUUID(ID.first, ID.second);
  549. File->setInstallName(InstallName);
  550. File->setCurrentVersion(CurrentVersion);
  551. File->setCompatibilityVersion(CompatibilityVersion);
  552. File->setSwiftABIVersion(SwiftABIVersion);
  553. File->setObjCConstraint(ObjCConstraint);
  554. for (const auto &Target : File->targets())
  555. File->addParentUmbrella(Target, ParentUmbrella);
  556. if (Ctx->FileKind == FileType::TBD_V1) {
  557. File->setTwoLevelNamespace();
  558. File->setApplicationExtensionSafe();
  559. } else {
  560. File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
  561. File->setApplicationExtensionSafe(
  562. !(Flags & TBDFlags::NotApplicationExtensionSafe));
  563. File->setInstallAPI(Flags & TBDFlags::InstallAPI);
  564. }
  565. for (const auto &Section : Exports) {
  566. const auto Targets =
  567. synthesizeTargets(Section.Architectures, Platforms);
  568. for (const auto &Lib : Section.AllowableClients)
  569. for (const auto &Target : Targets)
  570. File->addAllowableClient(Lib, Target);
  571. for (const auto &Lib : Section.ReexportedLibraries)
  572. for (const auto &Target : Targets)
  573. File->addReexportedLibrary(Lib, Target);
  574. for (const auto &Symbol : Section.Symbols) {
  575. if (Ctx->FileKind != FileType::TBD_V3 &&
  576. Symbol.value.startswith("_OBJC_EHTYPE_$_"))
  577. File->addSymbol(SymbolKind::ObjectiveCClassEHType,
  578. Symbol.value.drop_front(15), Targets);
  579. else
  580. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
  581. }
  582. for (auto &Symbol : Section.Classes) {
  583. auto Name = Symbol.value;
  584. if (Ctx->FileKind != FileType::TBD_V3)
  585. Name = Name.drop_front();
  586. File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
  587. }
  588. for (auto &Symbol : Section.ClassEHs)
  589. File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
  590. for (auto &Symbol : Section.IVars) {
  591. auto Name = Symbol.value;
  592. if (Ctx->FileKind != FileType::TBD_V3)
  593. Name = Name.drop_front();
  594. File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
  595. Targets);
  596. }
  597. for (auto &Symbol : Section.WeakDefSymbols)
  598. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  599. SymbolFlags::WeakDefined);
  600. for (auto &Symbol : Section.TLVSymbols)
  601. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  602. SymbolFlags::ThreadLocalValue);
  603. }
  604. for (const auto &Section : Undefineds) {
  605. const auto Targets =
  606. synthesizeTargets(Section.Architectures, Platforms);
  607. for (auto &Symbol : Section.Symbols) {
  608. if (Ctx->FileKind != FileType::TBD_V3 &&
  609. Symbol.value.startswith("_OBJC_EHTYPE_$_"))
  610. File->addSymbol(SymbolKind::ObjectiveCClassEHType,
  611. Symbol.value.drop_front(15), Targets,
  612. SymbolFlags::Undefined);
  613. else
  614. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  615. SymbolFlags::Undefined);
  616. }
  617. for (auto &Symbol : Section.Classes) {
  618. auto Name = Symbol.value;
  619. if (Ctx->FileKind != FileType::TBD_V3)
  620. Name = Name.drop_front();
  621. File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
  622. SymbolFlags::Undefined);
  623. }
  624. for (auto &Symbol : Section.ClassEHs)
  625. File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
  626. SymbolFlags::Undefined);
  627. for (auto &Symbol : Section.IVars) {
  628. auto Name = Symbol.value;
  629. if (Ctx->FileKind != FileType::TBD_V3)
  630. Name = Name.drop_front();
  631. File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
  632. SymbolFlags::Undefined);
  633. }
  634. for (auto &Symbol : Section.WeakRefSymbols)
  635. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  636. SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
  637. }
  638. return File;
  639. }
  640. llvm::BumpPtrAllocator Allocator;
  641. StringRef copyString(StringRef String) {
  642. if (String.empty())
  643. return {};
  644. void *Ptr = Allocator.Allocate(String.size(), 1);
  645. memcpy(Ptr, String.data(), String.size());
  646. return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
  647. }
  648. std::vector<Architecture> Architectures;
  649. std::vector<UUID> UUIDs;
  650. PlatformSet Platforms;
  651. StringRef InstallName;
  652. PackedVersion CurrentVersion;
  653. PackedVersion CompatibilityVersion;
  654. SwiftVersion SwiftABIVersion{0};
  655. ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
  656. TBDFlags Flags{TBDFlags::None};
  657. StringRef ParentUmbrella;
  658. std::vector<ExportSection> Exports;
  659. std::vector<UndefinedSection> Undefineds;
  660. };
  661. static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
  662. if (IO.mapTag("!tapi-tbd", false))
  663. Ctx->FileKind = FileType::TBD_V4;
  664. else if (IO.mapTag("!tapi-tbd-v3", false))
  665. Ctx->FileKind = FileType::TBD_V3;
  666. else if (IO.mapTag("!tapi-tbd-v2", false))
  667. Ctx->FileKind = FileType::TBD_V2;
  668. else if (IO.mapTag("!tapi-tbd-v1", false) ||
  669. IO.mapTag("tag:yaml.org,2002:map", false))
  670. Ctx->FileKind = FileType::TBD_V1;
  671. else {
  672. Ctx->FileKind = FileType::Invalid;
  673. return;
  674. }
  675. }
  676. static void mapping(IO &IO, const InterfaceFile *&File) {
  677. auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  678. assert((!Ctx || !IO.outputting() ||
  679. (Ctx && Ctx->FileKind != FileType::Invalid)) &&
  680. "File type is not set in YAML context");
  681. if (!IO.outputting()) {
  682. setFileTypeForInput(Ctx, IO);
  683. switch (Ctx->FileKind) {
  684. default:
  685. break;
  686. case FileType::TBD_V4:
  687. mapKeysToValuesV4(IO, File);
  688. return;
  689. case FileType::Invalid:
  690. IO.setError("unsupported file type");
  691. return;
  692. }
  693. } else {
  694. // Set file type when writing.
  695. switch (Ctx->FileKind) {
  696. default:
  697. llvm_unreachable("unexpected file type");
  698. case FileType::TBD_V4:
  699. mapKeysToValuesV4(IO, File);
  700. return;
  701. case FileType::TBD_V3:
  702. IO.mapTag("!tapi-tbd-v3", true);
  703. break;
  704. case FileType::TBD_V2:
  705. IO.mapTag("!tapi-tbd-v2", true);
  706. break;
  707. case FileType::TBD_V1:
  708. // Don't write the tag into the .tbd file for TBD v1
  709. break;
  710. }
  711. }
  712. mapKeysToValues(Ctx->FileKind, IO, File);
  713. }
  714. using SectionList = std::vector<SymbolSection>;
  715. struct NormalizedTBD_V4 {
  716. explicit NormalizedTBD_V4(IO &IO) {}
  717. NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
  718. auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  719. assert(Ctx);
  720. TBDVersion = Ctx->FileKind >> 1;
  721. Targets.insert(Targets.begin(), File->targets().begin(),
  722. File->targets().end());
  723. for (const auto &IT : File->uuids())
  724. UUIDs.emplace_back(IT.first, IT.second);
  725. InstallName = File->getInstallName();
  726. CurrentVersion = File->getCurrentVersion();
  727. CompatibilityVersion = File->getCompatibilityVersion();
  728. SwiftABIVersion = File->getSwiftABIVersion();
  729. Flags = TBDFlags::None;
  730. if (!File->isApplicationExtensionSafe())
  731. Flags |= TBDFlags::NotApplicationExtensionSafe;
  732. if (!File->isTwoLevelNamespace())
  733. Flags |= TBDFlags::FlatNamespace;
  734. if (File->isInstallAPI())
  735. Flags |= TBDFlags::InstallAPI;
  736. {
  737. std::map<std::string, TargetList> valueToTargetList;
  738. for (const auto &it : File->umbrellas())
  739. valueToTargetList[it.second].emplace_back(it.first);
  740. for (const auto &it : valueToTargetList) {
  741. UmbrellaSection CurrentSection;
  742. CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
  743. it.second.begin(), it.second.end());
  744. CurrentSection.Umbrella = it.first;
  745. ParentUmbrellas.emplace_back(std::move(CurrentSection));
  746. }
  747. }
  748. assignTargetsToLibrary(File->allowableClients(), AllowableClients);
  749. assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
  750. auto handleSymbols =
  751. [](SectionList &CurrentSections,
  752. InterfaceFile::const_filtered_symbol_range Symbols,
  753. std::function<bool(const Symbol *)> Pred) {
  754. std::set<TargetList> TargetSet;
  755. std::map<const Symbol *, TargetList> SymbolToTargetList;
  756. for (const auto *Symbol : Symbols) {
  757. if (!Pred(Symbol))
  758. continue;
  759. TargetList Targets(Symbol->targets());
  760. SymbolToTargetList[Symbol] = Targets;
  761. TargetSet.emplace(std::move(Targets));
  762. }
  763. for (const auto &TargetIDs : TargetSet) {
  764. SymbolSection CurrentSection;
  765. CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
  766. TargetIDs.begin(), TargetIDs.end());
  767. for (const auto &IT : SymbolToTargetList) {
  768. if (IT.second != TargetIDs)
  769. continue;
  770. const auto *Symbol = IT.first;
  771. switch (Symbol->getKind()) {
  772. case SymbolKind::GlobalSymbol:
  773. if (Symbol->isWeakDefined())
  774. CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
  775. else if (Symbol->isThreadLocalValue())
  776. CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
  777. else
  778. CurrentSection.Symbols.emplace_back(Symbol->getName());
  779. break;
  780. case SymbolKind::ObjectiveCClass:
  781. CurrentSection.Classes.emplace_back(Symbol->getName());
  782. break;
  783. case SymbolKind::ObjectiveCClassEHType:
  784. CurrentSection.ClassEHs.emplace_back(Symbol->getName());
  785. break;
  786. case SymbolKind::ObjectiveCInstanceVariable:
  787. CurrentSection.Ivars.emplace_back(Symbol->getName());
  788. break;
  789. }
  790. }
  791. sort(CurrentSection.Symbols);
  792. sort(CurrentSection.Classes);
  793. sort(CurrentSection.ClassEHs);
  794. sort(CurrentSection.Ivars);
  795. sort(CurrentSection.WeakSymbols);
  796. sort(CurrentSection.TlvSymbols);
  797. CurrentSections.emplace_back(std::move(CurrentSection));
  798. }
  799. };
  800. handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) {
  801. return !Symbol->isReexported();
  802. });
  803. handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) {
  804. return Symbol->isReexported();
  805. });
  806. handleSymbols(Undefineds, File->undefineds(),
  807. [](const Symbol *Symbol) { return true; });
  808. }
  809. const InterfaceFile *denormalize(IO &IO) {
  810. auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  811. assert(Ctx);
  812. auto *File = new InterfaceFile;
  813. File->setPath(Ctx->Path);
  814. File->setFileType(Ctx->FileKind);
  815. for (auto &id : UUIDs)
  816. File->addUUID(id.TargetID, id.Value);
  817. File->addTargets(Targets);
  818. File->setInstallName(InstallName);
  819. File->setCurrentVersion(CurrentVersion);
  820. File->setCompatibilityVersion(CompatibilityVersion);
  821. File->setSwiftABIVersion(SwiftABIVersion);
  822. for (const auto &CurrentSection : ParentUmbrellas)
  823. for (const auto &target : CurrentSection.Targets)
  824. File->addParentUmbrella(target, CurrentSection.Umbrella);
  825. File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
  826. File->setApplicationExtensionSafe(
  827. !(Flags & TBDFlags::NotApplicationExtensionSafe));
  828. File->setInstallAPI(Flags & TBDFlags::InstallAPI);
  829. for (const auto &CurrentSection : AllowableClients) {
  830. for (const auto &lib : CurrentSection.Values)
  831. for (const auto &Target : CurrentSection.Targets)
  832. File->addAllowableClient(lib, Target);
  833. }
  834. for (const auto &CurrentSection : ReexportedLibraries) {
  835. for (const auto &Lib : CurrentSection.Values)
  836. for (const auto &Target : CurrentSection.Targets)
  837. File->addReexportedLibrary(Lib, Target);
  838. }
  839. auto handleSymbols = [File](const SectionList &CurrentSections,
  840. SymbolFlags Flag = SymbolFlags::None) {
  841. for (const auto &CurrentSection : CurrentSections) {
  842. for (auto &sym : CurrentSection.Symbols)
  843. File->addSymbol(SymbolKind::GlobalSymbol, sym,
  844. CurrentSection.Targets, Flag);
  845. for (auto &sym : CurrentSection.Classes)
  846. File->addSymbol(SymbolKind::ObjectiveCClass, sym,
  847. CurrentSection.Targets);
  848. for (auto &sym : CurrentSection.ClassEHs)
  849. File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym,
  850. CurrentSection.Targets);
  851. for (auto &sym : CurrentSection.Ivars)
  852. File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
  853. CurrentSection.Targets);
  854. for (auto &sym : CurrentSection.WeakSymbols)
  855. File->addSymbol(SymbolKind::GlobalSymbol, sym,
  856. CurrentSection.Targets, SymbolFlags::WeakDefined);
  857. for (auto &sym : CurrentSection.TlvSymbols)
  858. File->addSymbol(SymbolKind::GlobalSymbol, sym,
  859. CurrentSection.Targets,
  860. SymbolFlags::ThreadLocalValue);
  861. }
  862. };
  863. handleSymbols(Exports);
  864. handleSymbols(Reexports, SymbolFlags::Rexported);
  865. handleSymbols(Undefineds, SymbolFlags::Undefined);
  866. return File;
  867. }
  868. unsigned TBDVersion;
  869. std::vector<UUIDv4> UUIDs;
  870. TargetList Targets;
  871. StringRef InstallName;
  872. PackedVersion CurrentVersion;
  873. PackedVersion CompatibilityVersion;
  874. SwiftVersion SwiftABIVersion{0};
  875. std::vector<MetadataSection> AllowableClients;
  876. std::vector<MetadataSection> ReexportedLibraries;
  877. TBDFlags Flags{TBDFlags::None};
  878. std::vector<UmbrellaSection> ParentUmbrellas;
  879. SectionList Exports;
  880. SectionList Reexports;
  881. SectionList Undefineds;
  882. private:
  883. void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
  884. std::vector<MetadataSection> &Section) {
  885. std::set<TargetList> targetSet;
  886. std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
  887. for (const auto &library : Libraries) {
  888. TargetList targets(library.targets());
  889. valueToTargetList[&library] = targets;
  890. targetSet.emplace(std::move(targets));
  891. }
  892. for (const auto &targets : targetSet) {
  893. MetadataSection CurrentSection;
  894. CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
  895. targets.begin(), targets.end());
  896. for (const auto &it : valueToTargetList) {
  897. if (it.second != targets)
  898. continue;
  899. CurrentSection.Values.emplace_back(it.first->getInstallName());
  900. }
  901. llvm::sort(CurrentSection.Values);
  902. Section.emplace_back(std::move(CurrentSection));
  903. }
  904. }
  905. };
  906. static void mapKeysToValues(FileType FileKind, IO &IO,
  907. const InterfaceFile *&File) {
  908. MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
  909. IO.mapRequired("archs", Keys->Architectures);
  910. if (FileKind != FileType::TBD_V1)
  911. IO.mapOptional("uuids", Keys->UUIDs);
  912. IO.mapRequired("platform", Keys->Platforms);
  913. if (FileKind != FileType::TBD_V1)
  914. IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
  915. IO.mapRequired("install-name", Keys->InstallName);
  916. IO.mapOptional("current-version", Keys->CurrentVersion,
  917. PackedVersion(1, 0, 0));
  918. IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
  919. PackedVersion(1, 0, 0));
  920. if (FileKind != FileType::TBD_V3)
  921. IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
  922. else
  923. IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
  924. SwiftVersion(0));
  925. IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
  926. (FileKind == FileType::TBD_V1)
  927. ? ObjCConstraintType::None
  928. : ObjCConstraintType::Retain_Release);
  929. if (FileKind != FileType::TBD_V1)
  930. IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
  931. IO.mapOptional("exports", Keys->Exports);
  932. if (FileKind != FileType::TBD_V1)
  933. IO.mapOptional("undefineds", Keys->Undefineds);
  934. }
  935. static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
  936. MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
  937. File);
  938. IO.mapTag("!tapi-tbd", true);
  939. IO.mapRequired("tbd-version", Keys->TBDVersion);
  940. IO.mapRequired("targets", Keys->Targets);
  941. IO.mapOptional("uuids", Keys->UUIDs);
  942. IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
  943. IO.mapRequired("install-name", Keys->InstallName);
  944. IO.mapOptional("current-version", Keys->CurrentVersion,
  945. PackedVersion(1, 0, 0));
  946. IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
  947. PackedVersion(1, 0, 0));
  948. IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
  949. IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
  950. auto OptionKind = MetadataSection::Option::Clients;
  951. IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
  952. OptionKind);
  953. OptionKind = MetadataSection::Option::Libraries;
  954. IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
  955. OptionKind);
  956. IO.mapOptional("exports", Keys->Exports);
  957. IO.mapOptional("reexports", Keys->Reexports);
  958. IO.mapOptional("undefineds", Keys->Undefineds);
  959. }
  960. };
  961. template <>
  962. struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
  963. static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
  964. return Seq.size();
  965. }
  966. static const InterfaceFile *&
  967. element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
  968. if (Index >= Seq.size())
  969. Seq.resize(Index + 1);
  970. return Seq[Index];
  971. }
  972. };
  973. } // end namespace yaml.
  974. } // namespace llvm
  975. static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
  976. auto *File = static_cast<TextAPIContext *>(Context);
  977. SmallString<1024> Message;
  978. raw_svector_ostream S(Message);
  979. SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
  980. Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
  981. Diag.getMessage(), Diag.getLineContents(),
  982. Diag.getRanges(), Diag.getFixIts());
  983. NewDiag.print(nullptr, S);
  984. File->ErrorMessage = ("malformed file\n" + Message).str();
  985. }
  986. Expected<std::unique_ptr<InterfaceFile>>
  987. TextAPIReader::get(MemoryBufferRef InputBuffer) {
  988. TextAPIContext Ctx;
  989. Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
  990. yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
  991. // Fill vector with interface file objects created by parsing the YAML file.
  992. std::vector<const InterfaceFile *> Files;
  993. YAMLIn >> Files;
  994. // YAMLIn dynamically allocates for Interface file and in case of error,
  995. // memory leak will occur unless wrapped around unique_ptr
  996. auto File = std::unique_ptr<InterfaceFile>(
  997. const_cast<InterfaceFile *>(Files.front()));
  998. for (auto Iter = std::next(Files.begin()); Iter != Files.end(); ++Iter)
  999. File->addDocument(
  1000. std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(*Iter)));
  1001. if (YAMLIn.error())
  1002. return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
  1003. return std::move(File);
  1004. }
  1005. Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
  1006. TextAPIContext Ctx;
  1007. Ctx.Path = std::string(File.getPath());
  1008. Ctx.FileKind = File.getFileType();
  1009. llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
  1010. std::vector<const InterfaceFile *> Files;
  1011. Files.emplace_back(&File);
  1012. for (auto Document : File.documents())
  1013. Files.emplace_back(Document.get());
  1014. // Stream out yaml.
  1015. YAMLOut << Files;
  1016. return Error::success();
  1017. }