TextStub.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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. // clang-format on
  132. using namespace llvm;
  133. using namespace llvm::yaml;
  134. using namespace llvm::MachO;
  135. namespace {
  136. struct ExportSection {
  137. std::vector<Architecture> Architectures;
  138. std::vector<FlowStringRef> AllowableClients;
  139. std::vector<FlowStringRef> ReexportedLibraries;
  140. std::vector<FlowStringRef> Symbols;
  141. std::vector<FlowStringRef> Classes;
  142. std::vector<FlowStringRef> ClassEHs;
  143. std::vector<FlowStringRef> IVars;
  144. std::vector<FlowStringRef> WeakDefSymbols;
  145. std::vector<FlowStringRef> TLVSymbols;
  146. };
  147. struct UndefinedSection {
  148. std::vector<Architecture> Architectures;
  149. std::vector<FlowStringRef> Symbols;
  150. std::vector<FlowStringRef> Classes;
  151. std::vector<FlowStringRef> ClassEHs;
  152. std::vector<FlowStringRef> IVars;
  153. std::vector<FlowStringRef> WeakRefSymbols;
  154. };
  155. // clang-format off
  156. enum TBDFlags : unsigned {
  157. None = 0U,
  158. FlatNamespace = 1U << 0,
  159. NotApplicationExtensionSafe = 1U << 1,
  160. InstallAPI = 1U << 2,
  161. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
  162. };
  163. // clang-format on
  164. } // end anonymous namespace.
  165. LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
  166. LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
  167. LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
  168. namespace llvm {
  169. namespace yaml {
  170. template <> struct MappingTraits<ExportSection> {
  171. static void mapping(IO &IO, ExportSection &Section) {
  172. const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  173. assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
  174. "File type is not set in YAML context");
  175. IO.mapRequired("archs", Section.Architectures);
  176. if (Ctx->FileKind == FileType::TBD_V1)
  177. IO.mapOptional("allowed-clients", Section.AllowableClients);
  178. else
  179. IO.mapOptional("allowable-clients", Section.AllowableClients);
  180. IO.mapOptional("re-exports", Section.ReexportedLibraries);
  181. IO.mapOptional("symbols", Section.Symbols);
  182. IO.mapOptional("objc-classes", Section.Classes);
  183. if (Ctx->FileKind == FileType::TBD_V3)
  184. IO.mapOptional("objc-eh-types", Section.ClassEHs);
  185. IO.mapOptional("objc-ivars", Section.IVars);
  186. IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
  187. IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
  188. }
  189. };
  190. template <> struct MappingTraits<UndefinedSection> {
  191. static void mapping(IO &IO, UndefinedSection &Section) {
  192. const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  193. assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
  194. "File type is not set in YAML context");
  195. IO.mapRequired("archs", Section.Architectures);
  196. IO.mapOptional("symbols", Section.Symbols);
  197. IO.mapOptional("objc-classes", Section.Classes);
  198. if (Ctx->FileKind == FileType::TBD_V3)
  199. IO.mapOptional("objc-eh-types", Section.ClassEHs);
  200. IO.mapOptional("objc-ivars", Section.IVars);
  201. IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
  202. }
  203. };
  204. template <> struct ScalarBitSetTraits<TBDFlags> {
  205. static void bitset(IO &IO, TBDFlags &Flags) {
  206. IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
  207. IO.bitSetCase(Flags, "not_app_extension_safe",
  208. TBDFlags::NotApplicationExtensionSafe);
  209. IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
  210. }
  211. };
  212. template <> struct MappingTraits<const InterfaceFile *> {
  213. struct NormalizedTBD {
  214. explicit NormalizedTBD(IO &IO) {}
  215. NormalizedTBD(IO &IO, const InterfaceFile *&File) {
  216. Architectures = File->getArchitectures();
  217. UUIDs = File->uuids();
  218. Platforms = File->getPlatforms();
  219. InstallName = File->getInstallName();
  220. CurrentVersion = PackedVersion(File->getCurrentVersion());
  221. CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
  222. SwiftABIVersion = File->getSwiftABIVersion();
  223. ObjCConstraint = File->getObjCConstraint();
  224. Flags = TBDFlags::None;
  225. if (!File->isApplicationExtensionSafe())
  226. Flags |= TBDFlags::NotApplicationExtensionSafe;
  227. if (!File->isTwoLevelNamespace())
  228. Flags |= TBDFlags::FlatNamespace;
  229. if (File->isInstallAPI())
  230. Flags |= TBDFlags::InstallAPI;
  231. for (const auto &Iter : File->umbrellas()) {
  232. ParentUmbrella = Iter.second;
  233. break;
  234. }
  235. std::set<ArchitectureSet> ArchSet;
  236. for (const auto &Library : File->allowableClients())
  237. ArchSet.insert(Library.getArchitectures());
  238. for (const auto &Library : File->reexportedLibraries())
  239. ArchSet.insert(Library.getArchitectures());
  240. std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
  241. for (const auto *Symbol : File->exports()) {
  242. auto Architectures = Symbol->getArchitectures();
  243. SymbolToArchSet[Symbol] = Architectures;
  244. ArchSet.insert(Architectures);
  245. }
  246. for (auto Architectures : ArchSet) {
  247. ExportSection Section;
  248. Section.Architectures = Architectures;
  249. for (const auto &Library : File->allowableClients())
  250. if (Library.getArchitectures() == Architectures)
  251. Section.AllowableClients.emplace_back(Library.getInstallName());
  252. for (const auto &Library : File->reexportedLibraries())
  253. if (Library.getArchitectures() == Architectures)
  254. Section.ReexportedLibraries.emplace_back(Library.getInstallName());
  255. for (const auto &SymArch : SymbolToArchSet) {
  256. if (SymArch.second != Architectures)
  257. continue;
  258. const auto *Symbol = SymArch.first;
  259. switch (Symbol->getKind()) {
  260. case SymbolKind::GlobalSymbol:
  261. if (Symbol->isWeakDefined())
  262. Section.WeakDefSymbols.emplace_back(Symbol->getName());
  263. else if (Symbol->isThreadLocalValue())
  264. Section.TLVSymbols.emplace_back(Symbol->getName());
  265. else
  266. Section.Symbols.emplace_back(Symbol->getName());
  267. break;
  268. case SymbolKind::ObjectiveCClass:
  269. if (File->getFileType() != FileType::TBD_V3)
  270. Section.Classes.emplace_back(
  271. copyString("_" + Symbol->getName().str()));
  272. else
  273. Section.Classes.emplace_back(Symbol->getName());
  274. break;
  275. case SymbolKind::ObjectiveCClassEHType:
  276. if (File->getFileType() != FileType::TBD_V3)
  277. Section.Symbols.emplace_back(
  278. copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
  279. else
  280. Section.ClassEHs.emplace_back(Symbol->getName());
  281. break;
  282. case SymbolKind::ObjectiveCInstanceVariable:
  283. if (File->getFileType() != FileType::TBD_V3)
  284. Section.IVars.emplace_back(
  285. copyString("_" + Symbol->getName().str()));
  286. else
  287. Section.IVars.emplace_back(Symbol->getName());
  288. break;
  289. }
  290. }
  291. llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
  292. llvm::sort(Section.Classes.begin(), Section.Classes.end());
  293. llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
  294. llvm::sort(Section.IVars.begin(), Section.IVars.end());
  295. llvm::sort(Section.WeakDefSymbols.begin(),
  296. Section.WeakDefSymbols.end());
  297. llvm::sort(Section.TLVSymbols.begin(), Section.TLVSymbols.end());
  298. Exports.emplace_back(std::move(Section));
  299. }
  300. ArchSet.clear();
  301. SymbolToArchSet.clear();
  302. for (const auto *Symbol : File->undefineds()) {
  303. auto Architectures = Symbol->getArchitectures();
  304. SymbolToArchSet[Symbol] = Architectures;
  305. ArchSet.insert(Architectures);
  306. }
  307. for (auto Architectures : ArchSet) {
  308. UndefinedSection Section;
  309. Section.Architectures = Architectures;
  310. for (const auto &SymArch : SymbolToArchSet) {
  311. if (SymArch.second != Architectures)
  312. continue;
  313. const auto *Symbol = SymArch.first;
  314. switch (Symbol->getKind()) {
  315. case SymbolKind::GlobalSymbol:
  316. if (Symbol->isWeakReferenced())
  317. Section.WeakRefSymbols.emplace_back(Symbol->getName());
  318. else
  319. Section.Symbols.emplace_back(Symbol->getName());
  320. break;
  321. case SymbolKind::ObjectiveCClass:
  322. if (File->getFileType() != FileType::TBD_V3)
  323. Section.Classes.emplace_back(
  324. copyString("_" + Symbol->getName().str()));
  325. else
  326. Section.Classes.emplace_back(Symbol->getName());
  327. break;
  328. case SymbolKind::ObjectiveCClassEHType:
  329. if (File->getFileType() != FileType::TBD_V3)
  330. Section.Symbols.emplace_back(
  331. copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
  332. else
  333. Section.ClassEHs.emplace_back(Symbol->getName());
  334. break;
  335. case SymbolKind::ObjectiveCInstanceVariable:
  336. if (File->getFileType() != FileType::TBD_V3)
  337. Section.IVars.emplace_back(
  338. copyString("_" + Symbol->getName().str()));
  339. else
  340. Section.IVars.emplace_back(Symbol->getName());
  341. break;
  342. }
  343. }
  344. llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
  345. llvm::sort(Section.Classes.begin(), Section.Classes.end());
  346. llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
  347. llvm::sort(Section.IVars.begin(), Section.IVars.end());
  348. llvm::sort(Section.WeakRefSymbols.begin(),
  349. Section.WeakRefSymbols.end());
  350. Undefineds.emplace_back(std::move(Section));
  351. }
  352. }
  353. // TBD v1 - TBD v3 files only support one platform and several
  354. // architectures. It is possible to have more than one platform for TBD v3
  355. // files, but the architectures don't apply to all
  356. // platforms, specifically to filter out the i386 slice from
  357. // platform macCatalyst.
  358. TargetList synthesizeTargets(ArchitectureSet Architectures,
  359. const PlatformSet &Platforms) {
  360. TargetList Targets;
  361. for (auto Platform : Platforms) {
  362. Platform = mapToPlatformKind(Platform, Architectures.hasX86());
  363. for (const auto &&Architecture : Architectures) {
  364. if ((Architecture == AK_i386) &&
  365. (Platform == PlatformKind::macCatalyst))
  366. continue;
  367. Targets.emplace_back(Architecture, Platform);
  368. }
  369. }
  370. return Targets;
  371. }
  372. const InterfaceFile *denormalize(IO &IO) {
  373. auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  374. assert(Ctx);
  375. auto *File = new InterfaceFile;
  376. File->setPath(Ctx->Path);
  377. File->setFileType(Ctx->FileKind);
  378. File->addTargets(synthesizeTargets(Architectures, Platforms));
  379. for (auto &ID : UUIDs)
  380. File->addUUID(ID.first, ID.second);
  381. File->setInstallName(InstallName);
  382. File->setCurrentVersion(CurrentVersion);
  383. File->setCompatibilityVersion(CompatibilityVersion);
  384. File->setSwiftABIVersion(SwiftABIVersion);
  385. File->setObjCConstraint(ObjCConstraint);
  386. for (const auto &Target : File->targets())
  387. File->addParentUmbrella(Target, ParentUmbrella);
  388. if (Ctx->FileKind == FileType::TBD_V1) {
  389. File->setTwoLevelNamespace();
  390. File->setApplicationExtensionSafe();
  391. } else {
  392. File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
  393. File->setApplicationExtensionSafe(
  394. !(Flags & TBDFlags::NotApplicationExtensionSafe));
  395. File->setInstallAPI(Flags & TBDFlags::InstallAPI);
  396. }
  397. for (const auto &Section : Exports) {
  398. const auto Targets =
  399. synthesizeTargets(Section.Architectures, Platforms);
  400. for (const auto &Lib : Section.AllowableClients)
  401. for (const auto &Target : Targets)
  402. File->addAllowableClient(Lib, Target);
  403. for (const auto &Lib : Section.ReexportedLibraries)
  404. for (const auto &Target : Targets)
  405. File->addReexportedLibrary(Lib, Target);
  406. for (const auto &Symbol : Section.Symbols) {
  407. if (Ctx->FileKind != FileType::TBD_V3 &&
  408. Symbol.value.startswith("_OBJC_EHTYPE_$_"))
  409. File->addSymbol(SymbolKind::ObjectiveCClassEHType,
  410. Symbol.value.drop_front(15), Targets);
  411. else
  412. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
  413. }
  414. for (auto &Symbol : Section.Classes) {
  415. auto Name = Symbol.value;
  416. if (Ctx->FileKind != FileType::TBD_V3)
  417. Name = Name.drop_front();
  418. File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
  419. }
  420. for (auto &Symbol : Section.ClassEHs)
  421. File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
  422. for (auto &Symbol : Section.IVars) {
  423. auto Name = Symbol.value;
  424. if (Ctx->FileKind != FileType::TBD_V3)
  425. Name = Name.drop_front();
  426. File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
  427. Targets);
  428. }
  429. for (auto &Symbol : Section.WeakDefSymbols)
  430. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  431. SymbolFlags::WeakDefined);
  432. for (auto &Symbol : Section.TLVSymbols)
  433. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  434. SymbolFlags::ThreadLocalValue);
  435. }
  436. for (const auto &Section : Undefineds) {
  437. const auto Targets =
  438. synthesizeTargets(Section.Architectures, Platforms);
  439. for (auto &Symbol : Section.Symbols) {
  440. if (Ctx->FileKind != FileType::TBD_V3 &&
  441. Symbol.value.startswith("_OBJC_EHTYPE_$_"))
  442. File->addSymbol(SymbolKind::ObjectiveCClassEHType,
  443. Symbol.value.drop_front(15), Targets,
  444. SymbolFlags::Undefined);
  445. else
  446. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  447. SymbolFlags::Undefined);
  448. }
  449. for (auto &Symbol : Section.Classes) {
  450. auto Name = Symbol.value;
  451. if (Ctx->FileKind != FileType::TBD_V3)
  452. Name = Name.drop_front();
  453. File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
  454. SymbolFlags::Undefined);
  455. }
  456. for (auto &Symbol : Section.ClassEHs)
  457. File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
  458. SymbolFlags::Undefined);
  459. for (auto &Symbol : Section.IVars) {
  460. auto Name = Symbol.value;
  461. if (Ctx->FileKind != FileType::TBD_V3)
  462. Name = Name.drop_front();
  463. File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
  464. SymbolFlags::Undefined);
  465. }
  466. for (auto &Symbol : Section.WeakRefSymbols)
  467. File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
  468. SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
  469. }
  470. return File;
  471. }
  472. llvm::BumpPtrAllocator Allocator;
  473. StringRef copyString(StringRef String) {
  474. if (String.empty())
  475. return {};
  476. void *Ptr = Allocator.Allocate(String.size(), 1);
  477. memcpy(Ptr, String.data(), String.size());
  478. return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
  479. }
  480. std::vector<Architecture> Architectures;
  481. std::vector<UUID> UUIDs;
  482. PlatformSet Platforms;
  483. StringRef InstallName;
  484. PackedVersion CurrentVersion;
  485. PackedVersion CompatibilityVersion;
  486. SwiftVersion SwiftABIVersion{0};
  487. ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
  488. TBDFlags Flags{TBDFlags::None};
  489. StringRef ParentUmbrella;
  490. std::vector<ExportSection> Exports;
  491. std::vector<UndefinedSection> Undefineds;
  492. };
  493. static void mapping(IO &IO, const InterfaceFile *&File) {
  494. auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
  495. assert((!Ctx || !IO.outputting() ||
  496. (Ctx && Ctx->FileKind != FileType::Invalid)) &&
  497. "File type is not set in YAML context");
  498. MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
  499. // prope file type when reading.
  500. if (!IO.outputting()) {
  501. if (IO.mapTag("!tapi-tbd-v3", false))
  502. Ctx->FileKind = FileType::TBD_V3;
  503. else if (IO.mapTag("!tapi-tbd-v2", false))
  504. Ctx->FileKind = FileType::TBD_V2;
  505. else if (IO.mapTag("!tapi-tbd-v1", false) ||
  506. IO.mapTag("tag:yaml.org,2002:map", false))
  507. Ctx->FileKind = FileType::TBD_V1;
  508. else {
  509. IO.setError("unsupported file type");
  510. return;
  511. }
  512. }
  513. // Set file type when writing.
  514. if (IO.outputting()) {
  515. switch (Ctx->FileKind) {
  516. default:
  517. llvm_unreachable("unexpected file type");
  518. case FileType::TBD_V1:
  519. // Don't write the tag into the .tbd file for TBD v1.
  520. break;
  521. case FileType::TBD_V2:
  522. IO.mapTag("!tapi-tbd-v2", true);
  523. break;
  524. case FileType::TBD_V3:
  525. IO.mapTag("!tapi-tbd-v3", true);
  526. break;
  527. }
  528. }
  529. IO.mapRequired("archs", Keys->Architectures);
  530. if (Ctx->FileKind != FileType::TBD_V1)
  531. IO.mapOptional("uuids", Keys->UUIDs);
  532. IO.mapRequired("platform", Keys->Platforms);
  533. if (Ctx->FileKind != FileType::TBD_V1)
  534. IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
  535. IO.mapRequired("install-name", Keys->InstallName);
  536. IO.mapOptional("current-version", Keys->CurrentVersion,
  537. PackedVersion(1, 0, 0));
  538. IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
  539. PackedVersion(1, 0, 0));
  540. if (Ctx->FileKind != FileType::TBD_V3)
  541. IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
  542. else
  543. IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
  544. SwiftVersion(0));
  545. IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
  546. (Ctx->FileKind == FileType::TBD_V1)
  547. ? ObjCConstraintType::None
  548. : ObjCConstraintType::Retain_Release);
  549. if (Ctx->FileKind != FileType::TBD_V1)
  550. IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
  551. IO.mapOptional("exports", Keys->Exports);
  552. if (Ctx->FileKind != FileType::TBD_V1)
  553. IO.mapOptional("undefineds", Keys->Undefineds);
  554. }
  555. };
  556. template <>
  557. struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
  558. static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
  559. return Seq.size();
  560. }
  561. static const InterfaceFile *&
  562. element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
  563. if (Index >= Seq.size())
  564. Seq.resize(Index + 1);
  565. return Seq[Index];
  566. }
  567. };
  568. } // end namespace yaml.
  569. namespace MachO {
  570. static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
  571. auto *File = static_cast<TextAPIContext *>(Context);
  572. SmallString<1024> Message;
  573. raw_svector_ostream S(Message);
  574. SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
  575. Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
  576. Diag.getMessage(), Diag.getLineContents(),
  577. Diag.getRanges(), Diag.getFixIts());
  578. NewDiag.print(nullptr, S);
  579. File->ErrorMessage = ("malformed file\n" + Message).str();
  580. }
  581. Expected<std::unique_ptr<InterfaceFile>>
  582. TextAPIReader::get(MemoryBufferRef InputBuffer) {
  583. TextAPIContext Ctx;
  584. Ctx.Path = InputBuffer.getBufferIdentifier();
  585. yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
  586. // Fill vector with interface file objects created by parsing the YAML file.
  587. std::vector<const InterfaceFile *> Files;
  588. YAMLIn >> Files;
  589. // YAMLIn dynamically allocates for Interface file and in case of error,
  590. // memory leak will occur unless wrapped around unique_ptr
  591. auto File = std::unique_ptr<InterfaceFile>(
  592. const_cast<InterfaceFile *>(Files.front()));
  593. if (YAMLIn.error())
  594. return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
  595. return std::move(File);
  596. }
  597. Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
  598. TextAPIContext Ctx;
  599. Ctx.Path = File.getPath();
  600. Ctx.FileKind = File.getFileType();
  601. llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
  602. std::vector<const InterfaceFile *> Files;
  603. Files.emplace_back(&File);
  604. // Stream out yaml.
  605. YAMLOut << Files;
  606. return Error::success();
  607. }
  608. } // end namespace MachO.
  609. } // end namespace llvm.