1//===- MultiArchStaticLibrary.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#include "JSONFormatImpl.h"
10
11#include "clang/ScalableStaticAnalysis/Core/EntityLinker/MultiArchStaticLibrary.h"
12#include "clang/ScalableStaticAnalysis/Core/EntityLinker/StaticLibrary.h"
13#include "llvm/TargetParser/Triple.h"
14
15namespace clang::ssaf {
16
17//----------------------------------------------------------------------------
18// MultiArchStaticLibrary
19//----------------------------------------------------------------------------
20
21llvm::Expected<MultiArchStaticLibrary>
22JSONFormat::readMultiArchStaticLibrary(llvm::StringRef Path) {
23 auto ExpectedJSON = readJSON(Path);
24 if (!ExpectedJSON) {
25 return ErrorBuilder::wrap(E: ExpectedJSON.takeError())
26 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "MultiArchStaticLibrary", ArgVals&: Path)
27 .build();
28 }
29
30 Object *RootObjectPtr = ExpectedJSON->getAsObject();
31 if (!RootObjectPtr) {
32 return ErrorBuilder::create(EC: std::errc::invalid_argument,
33 Fmt: ErrorMessages::FailedToReadObject,
34 ArgVals: "MultiArchStaticLibrary", ArgVals: "object")
35 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "MultiArchStaticLibrary", ArgVals&: Path)
36 .build();
37 }
38
39 if (auto Err = checkSummaryType(RootObject: *RootObjectPtr,
40 ExpectedType: JSONTypeValueMultiArchStaticLibrary)) {
41 return ErrorBuilder::wrap(E: std::move(Err))
42 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "MultiArchStaticLibrary", ArgVals&: Path)
43 .build();
44 }
45
46 auto ExpectedM = readMultiArchStaticLibraryFromObject(Root: *RootObjectPtr);
47 if (!ExpectedM) {
48 return ErrorBuilder::wrap(E: ExpectedM.takeError())
49 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "MultiArchStaticLibrary", ArgVals&: Path)
50 .build();
51 }
52
53 return std::move(*ExpectedM);
54}
55
56llvm::Expected<MultiArchStaticLibrary>
57JSONFormat::readMultiArchStaticLibraryFromObject(const Object &RootObject) {
58 const Object *NamespaceObject = RootObject.getObject(K: "namespace");
59 if (!NamespaceObject) {
60 return ErrorBuilder::create(EC: std::errc::invalid_argument,
61 Fmt: ErrorMessages::FailedToReadObjectAtField,
62 ArgVals: "BuildNamespace", ArgVals: "namespace", ArgVals: "object")
63 .build();
64 }
65
66 auto ExpectedNamespace = buildNamespaceFromJSON(BuildNamespaceObject: *NamespaceObject);
67 if (!ExpectedNamespace) {
68 return ErrorBuilder::wrap(E: ExpectedNamespace.takeError())
69 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "BuildNamespace", ArgVals: "namespace")
70 .build();
71 }
72
73 if (getKind(X&: *ExpectedNamespace) !=
74 BuildNamespaceKind::MultiArchStaticLibrary) {
75 return ErrorBuilder::create(
76 EC: std::errc::invalid_argument,
77 Fmt: ErrorMessages::MismatchedSummaryType,
78 ArgVals: buildNamespaceKindToJSON(
79 BNK: BuildNamespaceKind::MultiArchStaticLibrary),
80 ArgVals: "namespace.kind",
81 ArgVals: buildNamespaceKindToJSON(BNK: getKind(X&: *ExpectedNamespace)))
82 .build();
83 }
84
85 const Array *MembersArray = RootObject.getArray(K: "members");
86 if (!MembersArray) {
87 return ErrorBuilder::create(EC: std::errc::invalid_argument,
88 Fmt: ErrorMessages::FailedToReadObjectAtField,
89 ArgVals: "MultiArchStaticLibrary members", ArgVals: "members",
90 ArgVals: "array")
91 .build();
92 }
93
94 MultiArchStaticLibrary M(std::move(*ExpectedNamespace));
95 auto &Members = getMembers(X&: M);
96 const auto &ExpectedName = getName(X&: getNamespace(X&: M));
97
98 for (const auto &[Index, MemberValue] : llvm::enumerate(First: *MembersArray)) {
99 const Object *MemberObject = MemberValue.getAsObject();
100 if (!MemberObject) {
101 return ErrorBuilder::create(EC: std::errc::invalid_argument,
102 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
103 ArgVals: "MultiArchStaticLibrary member", ArgVals&: Index,
104 ArgVals: "object")
105 .build();
106 }
107
108 if (auto Err =
109 checkSummaryType(RootObject: *MemberObject, ExpectedType: JSONTypeValueStaticLibrary)) {
110 return ErrorBuilder::wrap(E: std::move(Err))
111 .context(Fmt: ErrorMessages::ReadingFromIndex,
112 ArgVals: "MultiArchStaticLibrary member", ArgVals&: Index)
113 .build();
114 }
115
116 auto ExpectedMember = readStaticLibraryFromObject(Root: *MemberObject);
117 if (!ExpectedMember) {
118 return ErrorBuilder::wrap(E: ExpectedMember.takeError())
119 .context(Fmt: ErrorMessages::ReadingFromIndex,
120 ArgVals: "MultiArchStaticLibrary member", ArgVals&: Index)
121 .build();
122 }
123
124 const auto &MemberName = getName(X&: getNamespace(X&: *ExpectedMember));
125 if (MemberName != ExpectedName) {
126 return ErrorBuilder::create(EC: std::errc::invalid_argument,
127 Fmt: ErrorMessages::MismatchedSummaryType,
128 ArgVals: ExpectedName, ArgVals: "namespace.name", ArgVals: MemberName)
129 .context(Fmt: ErrorMessages::ReadingFromIndex,
130 ArgVals: "MultiArchStaticLibrary member", ArgVals&: Index)
131 .build();
132 }
133
134 auto [It, Inserted] = Members.insert(
135 x: std::make_unique<StaticLibrary>(args: std::move(*ExpectedMember)));
136 if (!Inserted) {
137 auto MemberTriple = llvm::Triple::normalize(Str: getTargetTriple(X&: **It).str());
138 return ErrorBuilder::create(EC: std::errc::invalid_argument,
139 Fmt: ErrorMessages::FailedInsertionOnDuplication,
140 ArgVals: "MultiArchStaticLibrary member", ArgVals&: Index,
141 ArgVals&: MemberTriple)
142 .build();
143 }
144 }
145
146 return std::move(M);
147}
148
149llvm::Error
150JSONFormat::writeMultiArchStaticLibrary(const MultiArchStaticLibrary &M,
151 llvm::StringRef Path) {
152 Object RootObject;
153
154 RootObject[JSONTypeKey] = JSONTypeValueMultiArchStaticLibrary;
155
156 RootObject["namespace"] = buildNamespaceToJSON(BN: getNamespace(X: M));
157
158 Array MembersArray;
159 MembersArray.reserve(S: getMembers(X: M).size());
160 for (const auto &Member : getMembers(X: M)) {
161 MembersArray.push_back(E: staticLibraryToJSON(S: *Member));
162 }
163 RootObject["members"] = std::move(MembersArray);
164
165 if (auto Error = writeJSON(V: std::move(RootObject), Path)) {
166 return ErrorBuilder::wrap(E: std::move(Error))
167 .context(Fmt: ErrorMessages::WritingToFile, ArgVals: "MultiArchStaticLibrary", ArgVals&: Path)
168 .build();
169 }
170
171 return llvm::Error::success();
172}
173
174} // namespace clang::ssaf
175