123std::array<StringRef, 64>
Keys = {
135 "compatibility_versions",
143 "reexported_libraries",
147 "reexported_symbols",
162 return {
"invalid ",
Keys[Key],
" section"};
166 return {
"missing ",
Keys[Key],
" information"};
182template <
typename JsonT,
typename StubT = JsonT>
185 std::function<std::optional<JsonT>(
const Object *,
StringRef)> GetValue,
186 std::function<std::optional<StubT>(JsonT)> Validate =
nullptr) {
187 std::optional<JsonT> Val = GetValue(Obj,
Keys[Key]);
191 if (Validate ==
nullptr)
192 return static_cast<StubT
>(*Val);
194 std::optional<StubT> Result = Validate(*Val);
195 if (!Result.has_value())
197 return Result.value();
200template <
typename JsonT,
typename StubT = JsonT>
203 std::function<std::optional<JsonT>(
const Object *,
StringRef)> GetValue,
204 StubT DefaultValue, std::function<std::optional<StubT>(JsonT)> Validate) {
205 std::optional<JsonT> Val = GetValue(Obj,
Keys[Key]);
209 std::optional<StubT> Result;
210 Result = Validate(*Val);
211 if (!Result.has_value())
213 return Result.value();
218 bool IsRequired =
false) {
226 for (
const Value &Val : *Values) {
227 auto ValStr = Val.getAsString();
228 if (!ValStr.has_value())
230 Append(ValStr.value());
239 auto VersionOrErr = getRequiredValue<int64_t, FileType>(
241 [](int64_t Val) -> std::optional<FileType> {
242 unsigned Result = Val;
245 return FileType::TBD_V5;
249 return VersionOrErr.takeError();
250 return *VersionOrErr;
254 const auto *
Targets = Section->getArray(
Keys[TBDKey::Targets]);
260 auto TargetStr = JSONTarget.getAsString();
261 if (!TargetStr.has_value())
268 return std::move(IFTargets);
278 const auto *Obj = JSONTarget.getAsObject();
285 auto VersionStr = getRequiredValue<StringRef>(TBDKey::Deployment, Obj,
290 if (Version.tryParse(*VersionStr))
295 TargetOrErr->MinDeployment = Version;
301 return std::move(IFTargets);
307 TBDKey::Globals, Segment, [&Result, &SectionFlag](
StringRef Name) {
309 Result.back().second.emplace_back(
Sym);
315 TBDKey::ObjCClass, Segment, [&Result, &SectionFlag](
StringRef Name) {
317 Result.back().second.emplace_back(
Sym);
325 Name.str(), SectionFlag};
326 Result.back().second.emplace_back(
Sym);
332 TBDKey::ObjCIvar, Segment, [&Result, &SectionFlag](
StringRef Name) {
335 Result.back().second.emplace_back(
Sym);
342 (((SectionFlag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
343 ? SymbolFlags::WeakReferenced
344 : SymbolFlags::WeakDefined);
348 Result.back().second.emplace_back(
Sym);
354 TBDKey::ThreadLocal, Segment, [&Result, SectionFlag](
StringRef Name) {
356 SymbolFlags::ThreadLocalValue | SectionFlag};
357 Result.back().second.emplace_back(
Sym);
366 const Array *Section = File->getArray(
Keys[TBDKey::InstallName]);
370 assert(!Section->empty() &&
"unexpected missing install name");
372 const auto *Obj = Section->front().getAsObject();
382 const Array *Section = File->getArray(
Keys[Key]);
388 case TBDKey::Reexports:
389 SectionFlag = SymbolFlags::Rexported;
391 case TBDKey::Undefineds:
392 SectionFlag = SymbolFlags::Undefined;
395 SectionFlag = SymbolFlags::None;
401 for (
auto Val : *Section) {
402 auto *Obj = Val.getAsObject();
411 MappedTargets = *TargetsOrErr;
414 std::make_pair(std::move(MappedTargets), std::vector<JSONSymbol>()));
419 if (!DataSection && !TextSection)
424 SectionFlag | SymbolFlags::Data);
426 return std::move(Err);
430 SectionFlag | SymbolFlags::Text);
432 return std::move(Err);
436 return std::move(Result);
442 auto *Section = File->getArray(
Keys[Key]);
448 for (
auto Val : *Section) {
449 auto *Obj = Val.getAsObject();
458 MappedTargets = *TargetsOrErr;
462 Result[Key.str()] = MappedTargets;
465 return std::move(Err);
468 return std::move(Result);
473 const auto *
Umbrella = File->getArray(
Keys[TBDKey::ParentUmbrella]);
480 auto *Obj = Val.getAsObject();
482 return make_error<JSONStubError>(
491 MappedTargets = *TargetsOrErr;
497 return UmbrellaOrErr.takeError();
498 Result[UmbrellaOrErr->str()] =
Targets;
500 return std::move(Result);
504 const Array *Versions = File->getArray(
Keys[TBDKey::SwiftABI]);
508 for (
const auto &Val : *Versions) {
509 const auto *Obj = Val.getAsObject();
514 return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj,
522 const Array *Versions = File->getArray(
Keys[Key]);
526 for (
const auto &Val : *Versions) {
527 const auto *Obj = Val.getAsObject();
531 auto ValidatePV = [](
StringRef Version) -> std::optional<PackedVersion> {
539 return getRequiredValue<StringRef, PackedVersion>(
549 const Array *Section = File->getArray(
Keys[TBDKey::Flags]);
553 for (
auto &Val : *Section) {
555 const auto *Obj = Val.getAsObject();
563 .
Case(
"flat_namespace", TBDFlags::FlatNamespace)
564 .
Case(
"not_app_extension_safe",
565 TBDFlags::NotApplicationExtensionSafe)
571 return std::move(FlagsOrErr);
579using IFPtr = std::unique_ptr<InterfaceFile>;
583 return TargetsOrErr.takeError();
588 return NameOrErr.takeError();
592 if (!CurrVersionOrErr)
593 return CurrVersionOrErr.takeError();
596 auto CompVersionOrErr =
getPackedVersion(File, TBDKey::CompatibilityVersion);
597 if (!CompVersionOrErr)
598 return CompVersionOrErr.takeError();
603 return SwiftABIOrErr.takeError();
608 return FlagsOrErr.takeError();
613 return UmbrellasOrErr.takeError();
619 return ClientsOrErr.takeError();
625 return RLOrErr.takeError();
630 return RPathsOrErr.takeError();
635 return ExportsOrErr.takeError();
640 return ReexportsOrErr.takeError();
644 if (!UndefinedsOrErr)
645 return UndefinedsOrErr.takeError();
649 F->setInstallName(
Name);
650 F->setCurrentVersion(CurrVersion);
651 F->setCompatibilityVersion(CompVersion);
653 F->setTwoLevelNamespace(!(
Flags & TBDFlags::FlatNamespace));
654 F->setApplicationExtensionSafe(
655 !(
Flags & TBDFlags::NotApplicationExtensionSafe));
671 for (
auto &
Sym : Symbols)
674 for (
auto &
Sym : Symbols)
677 for (
auto &
Sym : Symbols)
684 std::vector<IFPtr> IFs;
685 const Array *Files = File->getArray(
Keys[TBDKey::Documents]);
687 return std::move(IFs);
689 for (
auto Lib : *Files) {
692 return IFOrErr.takeError();
693 auto IF = std::move(*IFOrErr);
694 IFs.emplace_back(std::move(IF));
696 return std::move(IFs);
703 auto ValOrErr =
parse(JSON);
705 return ValOrErr.takeError();
707 auto *Root = ValOrErr->getAsObject();
710 return VersionOrErr.takeError();
716 return IFOrErr.takeError();
717 (*IFOrErr)->setFileType(
Version);
718 std::unique_ptr<InterfaceFile> IF(std::move(*IFOrErr));
722 return IFsOrErr.takeError();
723 for (
auto &File : *IFsOrErr) {
725 IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File)));
727 return std::move(IF);
732template <
typename ContainerT = Array>
733bool insertNonEmptyValues(
Object &Obj,
TBDKey Key, ContainerT &&Contents) {
734 if (Contents.empty())
736 Obj[
Keys[Key]] = std::move(Contents);
747template <
typename AggregateT>
748std::vector<std::string> serializeTargets(
const AggregateT
Targets,
750 std::vector<std::string> TargetsStr;
755 TargetsStr.emplace_back(getFormattedStr(
Target));
762 for (
const auto Targ : ActiveTargets) {
771template <
typename ValueT,
typename EntryT = ValueT>
782using TargetsToValuesMap =
783 std::map<std::vector<std::string>, std::vector<std::string>>;
785template <
typename AggregateT = TargetsToValuesMap>
786Array serializeAttrToTargets(AggregateT &Entries,
TBDKey Key) {
788 for (
const auto &[
Targets, Values] : Entries) {
797template <
typename ValueT = std::string,
798 typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
799Array serializeField(
TBDKey Key,
const AggregateT &Values,
800 const TargetList &ActiveTargets,
bool IsArray =
true) {
801 std::map<ValueT, std::set<MachO::Target>> Entries;
802 for (
const auto &[
Target, Val] : Values)
803 Entries[Val].insert(
Target);
806 std::map<std::vector<std::string>, std::string> FinalEntries;
807 for (
const auto &[Val,
Targets] : Entries)
808 FinalEntries[serializeTargets(
Targets, ActiveTargets)] = Val;
809 return serializeAttrToTargets(FinalEntries, Key);
812 TargetsToValuesMap FinalEntries;
813 for (
const auto &[Val,
Targets] : Entries)
814 FinalEntries[serializeTargets(
Targets, ActiveTargets)].emplace_back(Val);
815 return serializeAttrToTargets(FinalEntries, Key);
818Array serializeField(
TBDKey Key,
const std::vector<InterfaceFileRef> &Values,
820 TargetsToValuesMap FinalEntries;
821 for (
const auto &
Ref : Values) {
823 FinalEntries[serializeTargets(
Targets, ActiveTargets)].emplace_back(
824 Ref.getInstallName());
826 return serializeAttrToTargets(FinalEntries, Key);
831 std::vector<StringRef> Weaks;
832 std::vector<StringRef>
Globals;
833 std::vector<StringRef> TLV;
834 std::vector<StringRef> ObjCClasses;
835 std::vector<StringRef> IVars;
836 std::vector<StringRef> EHTypes;
839 return Weaks.empty() &&
Globals.empty() && TLV.empty() &&
840 ObjCClasses.empty() && IVars.empty() && EHTypes.empty();
849 auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment,
852 case SymbolKind::ObjectiveCClass:
855 case SymbolKind::ObjectiveCClassEHType:
856 Assignment.EHTypes.emplace_back(
Sym->
getName());
858 case SymbolKind::ObjectiveCInstanceVariable:
859 Assignment.IVars.emplace_back(
Sym->
getName());
861 case SymbolKind::GlobalSymbol: {
863 Assignment.Weaks.emplace_back(
Sym->
getName());
867 Assignment.Globals.emplace_back(
Sym->
getName());
873 std::map<std::vector<std::string>, SymbolFields> Entries;
874 for (
const auto *
Sym : Symbols) {
877 auto JSONTargets = serializeTargets(
Targets, ActiveTargets);
879 AssignForSymbolType(Entries[std::move(JSONTargets)].
Data,
Sym);
881 AssignForSymbolType(Entries[std::move(JSONTargets)].
Text,
Sym);
886 auto InsertSymbolsToJSON = [](
Object &SymSection,
TBDKey SegmentKey,
887 SymbolFields::SymbolTypes &SymField) {
888 if (SymField.empty())
891 insertNonEmptyValues(Segment,
TBDKey::Globals, std::move(SymField.Globals));
893 insertNonEmptyValues(Segment,
TBDKey::Weak, std::move(SymField.Weaks));
895 std::move(SymField.ObjCClasses));
897 std::move(SymField.EHTypes));
899 insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment));
903 for (
auto &[
Targets, Fields] : Entries) {
906 InsertSymbolsToJSON(AllSyms,
TBDKey::Data, Fields.Data);
907 InsertSymbolsToJSON(AllSyms,
TBDKey::Text, Fields.Text);
911 return SymbolSection;
917 if (!
File->isTwoLevelNamespace())
918 Flags.emplace_back(
"flat_namespace");
919 if (!
File->isApplicationExtensionSafe())
920 Flags.emplace_back(
"not_app_extension_safe");
930 serializeTargetInfo(ActiveTargets)))
941 Array CurrentV = serializeScalar<PackedVersion, std::string>(
945 Array CompatV = serializeScalar<PackedVersion, std::string>(
955 insertNonEmptyValues(Library,
TBDKey::RPath, std::move(RPaths));
958 ActiveTargets,
false);
976 if (!
File->isTwoLevelNamespace()) {
981 return std::move(Library);
985 assert(
File->getFileType() == FileType::TBD_V5 &&
986 "unexpected json file format version");
989 auto MainLibOrErr = serializeIF(File);
994 for (
const auto &Doc :
File->documents()) {
995 auto LibOrErr = serializeIF(Doc.get());
998 Documents.emplace_back(std::move(*LibOrErr));
1003 return std::move(Root);
1011 auto TextFile = getJSON(&File);
1013 return TextFile.takeError();
This file supports working with JSON data.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static llvm::SmallString< 128 > getSerializeErrorMsg(TBDKey Key)
Error collectFromArray(TBDKey Key, const Object *Obj, std::function< void(StringRef)> Append, bool IsRequired=false)
std::map< std::string, TargetList > AttrToTargets
static llvm::SmallString< 128 > getParseErrorMsg(TBDKey Key)
std::array< StringRef, 64 > Keys
SmallVector< std::pair< TargetList, std::vector< JSONSymbol > > > TargetsToSymbols
Expected< StubT > getRequiredValue(TBDKey Key, const Object *Obj, std::function< std::optional< JsonT >(const Object *, StringRef)> GetValue, std::function< std::optional< StubT >(JsonT)> Validate=nullptr)
std::error_code convertToErrorCode() const override
Convert this error to a std::error_code.
void log(llvm::raw_ostream &OS) const override
Print an error message to an output stream.
JSONStubError(Twine ErrMsg)
Base class for user error types.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Defines the interface file.
std::pair< bool, bool > parse64(StringRef Str)
bool isWeakDefined() const
const_target_range targets() const
bool isThreadLocalValue() const
SymbolKind getKind() const
StringRef getName() const
bool isWeakReferenced() const
static llvm::Expected< Target > create(StringRef Target)
VersionTuple MinDeployment
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
Represents a version number in the form major[.minor[.subminor[.build]]].
std::string getAsString() const
Retrieve a string representation of the version number.
A range adaptor for a pair of iterators.
An Array is a JSON array, which contains heterogeneous JSON values.
void emplace_back(Args &&...A)
An Object is a JSON object, which maps strings to heterogenous JSON values.
const json::Object * getObject(StringRef K) const
std::optional< llvm::StringRef > getString(StringRef K) const
std::optional< int64_t > getInteger(StringRef K) const
const json::Array * getArray(StringRef K) const
A "cursor" marking a position within a Value.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Expected< TargetsToSymbols > getSymbolSection(const Object *File, TBDKey Key, TargetList &Targets)
std::unique_ptr< InterfaceFile > IFPtr
Expected< TargetList > getTargetsSection(const Object *Section)
Expected< IFPtr > parseToInterfaceFile(const Object *File)
Expected< TBDFlags > getFlags(const Object *File)
Expected< std::vector< IFPtr > > getInlinedLibs(const Object *File)
Expected< FileType > getVersion(const Object *File)
Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result, SymbolFlags SectionFlag)
Expected< uint8_t > getSwiftVersion(const Object *File)
Expected< TargetList > getTargets(const Object *Section)
Expected< AttrToTargets > getUmbrellaSection(const Object *File, const TargetList &Targets)
Expected< AttrToTargets > getLibSection(const Object *File, TBDKey Key, TBDKey SubKey, const TargetList &Targets)
Expected< PackedVersion > getPackedVersion(const Object *File, TBDKey Key)
Expected< StringRef > getNameSection(const Object *File)
std::string getTargetTripleName(const Target &Targ)
FileType
Defines the file type this file represents.
StringRef getArchitectureName(Architecture Arch)
Convert an architecture slice to a string.
std::string getOSAndEnvironmentName(PlatformType Platform, std::string Version="")
Error serializeInterfaceFileToJSON(raw_ostream &OS, const InterfaceFile &File, bool Compact)
Expected< std::unique_ptr< InterfaceFile > > getInterfaceFileFromJSON(StringRef JSON)
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
@ Ref
The access may reference the value stored in memory.
void consumeError(Error Err)
Consume a Error without doing anything.