1//===- TUSummaryEncoding.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/TUSummaryEncoding.h"
12#include "llvm/TargetParser/Triple.h"
13
14#include <set>
15
16namespace clang::ssaf {
17
18//----------------------------------------------------------------------------
19// TUSummaryEncoding
20//----------------------------------------------------------------------------
21
22llvm::Expected<TUSummaryEncoding>
23JSONFormat::readTUSummaryEncoding(llvm::StringRef Path) {
24 auto ExpectedJSON = readJSON(Path);
25 if (!ExpectedJSON) {
26 return ErrorBuilder::wrap(E: ExpectedJSON.takeError())
27 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
28 .build();
29 }
30
31 Object *RootObjectPtr = ExpectedJSON->getAsObject();
32 if (!RootObjectPtr) {
33 return ErrorBuilder::create(EC: std::errc::invalid_argument,
34 Fmt: ErrorMessages::FailedToReadObject, ArgVals: "TUSummary",
35 ArgVals: "object")
36 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
37 .build();
38 }
39
40 if (auto Err = checkSummaryType(RootObject: *RootObjectPtr, ExpectedType: JSONTypeValueTUSummary)) {
41 return ErrorBuilder::wrap(E: std::move(Err))
42 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
43 .build();
44 }
45
46 auto ExpectedEncoding = readTUSummaryEncodingFromObject(Root: *RootObjectPtr);
47 if (!ExpectedEncoding) {
48 return ErrorBuilder::wrap(E: ExpectedEncoding.takeError())
49 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
50 .build();
51 }
52
53 return std::move(*ExpectedEncoding);
54}
55
56llvm::Expected<TUSummaryEncoding>
57JSONFormat::readTUSummaryEncodingFromObject(const Object &RootObject) {
58 auto OptTargetTriple = RootObject.getString(K: "target_triple");
59 if (!OptTargetTriple) {
60 return ErrorBuilder::create(EC: std::errc::invalid_argument,
61 Fmt: ErrorMessages::FailedToReadObjectAtField,
62 ArgVals: "TargetTriple", ArgVals: "target_triple", ArgVals: "string")
63 .build();
64 }
65
66 if (auto Err = validateNormalizedTargetTriple(Triple: *OptTargetTriple)) {
67 return ErrorBuilder::wrap(E: std::move(Err))
68 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "TargetTriple",
69 ArgVals: "target_triple")
70 .build();
71 }
72
73 llvm::Triple T(*OptTargetTriple);
74
75 const Object *TUNamespaceObject = RootObject.getObject(K: "tu_namespace");
76 if (!TUNamespaceObject) {
77 return ErrorBuilder::create(EC: std::errc::invalid_argument,
78 Fmt: ErrorMessages::FailedToReadObjectAtField,
79 ArgVals: "BuildNamespace", ArgVals: "tu_namespace", ArgVals: "object")
80 .build();
81 }
82
83 auto ExpectedTUNamespace = buildNamespaceFromJSON(BuildNamespaceObject: *TUNamespaceObject);
84 if (!ExpectedTUNamespace) {
85 return ErrorBuilder::wrap(E: ExpectedTUNamespace.takeError())
86 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "BuildNamespace",
87 ArgVals: "tu_namespace")
88 .build();
89 }
90
91 TUSummaryEncoding Encoding(std::move(T), std::move(*ExpectedTUNamespace));
92
93 {
94 const Array *IdTableArray = RootObject.getArray(K: "id_table");
95 if (!IdTableArray) {
96 return ErrorBuilder::create(EC: std::errc::invalid_argument,
97 Fmt: ErrorMessages::FailedToReadObjectAtField,
98 ArgVals: "IdTable", ArgVals: "id_table", ArgVals: "array")
99 .build();
100 }
101
102 auto ExpectedIdTable = tuEntityIdTableFromJSON(EntityIdTableArray: *IdTableArray);
103 if (!ExpectedIdTable) {
104 return ErrorBuilder::wrap(E: ExpectedIdTable.takeError())
105 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "IdTable", ArgVals: "id_table")
106 .build();
107 }
108
109 getIdTable(X&: Encoding) = std::move(*ExpectedIdTable);
110 }
111
112 {
113 const Array *LinkageTableArray = RootObject.getArray(K: "linkage_table");
114 if (!LinkageTableArray) {
115 return ErrorBuilder::create(EC: std::errc::invalid_argument,
116 Fmt: ErrorMessages::FailedToReadObjectAtField,
117 ArgVals: "LinkageTable", ArgVals: "linkage_table", ArgVals: "array")
118 .build();
119 }
120
121 auto ExpectedIdRange =
122 llvm::make_second_range(c&: getEntities(X&: getIdTable(X&: Encoding)));
123 std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
124 ExpectedIdRange.end());
125
126 // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
127 // that the linkage table contains exactly the ids present in the IdTable.
128 auto ExpectedLinkageTable =
129 linkageTableFromJSON(LinkageTableArray: *LinkageTableArray, ExpectedIds: std::move(ExpectedIds));
130 if (!ExpectedLinkageTable) {
131 return ErrorBuilder::wrap(E: ExpectedLinkageTable.takeError())
132 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "LinkageTable",
133 ArgVals: "linkage_table")
134 .build();
135 }
136
137 getLinkageTable(X&: Encoding) = std::move(*ExpectedLinkageTable);
138 }
139
140 {
141 const Array *SummaryDataArray = RootObject.getArray(K: "data");
142 if (!SummaryDataArray) {
143 return ErrorBuilder::create(EC: std::errc::invalid_argument,
144 Fmt: ErrorMessages::FailedToReadObjectAtField,
145 ArgVals: "SummaryData entries", ArgVals: "data", ArgVals: "array")
146 .build();
147 }
148
149 auto ExpectedEncodingSummaryDataMap =
150 encodingSummaryDataMapFromJSON(SummaryDataArray: *SummaryDataArray);
151 if (!ExpectedEncodingSummaryDataMap) {
152 return ErrorBuilder::wrap(E: ExpectedEncodingSummaryDataMap.takeError())
153 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "SummaryData entries",
154 ArgVals: "data")
155 .build();
156 }
157
158 getData(X&: Encoding) = std::move(*ExpectedEncodingSummaryDataMap);
159 }
160
161 return std::move(Encoding);
162}
163
164llvm::Error
165JSONFormat::writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
166 llvm::StringRef Path) {
167 Object RootObject;
168
169 RootObject[JSONTypeKey] = JSONTypeValueTUSummary;
170
171 RootObject["target_triple"] =
172 llvm::Triple::normalize(Str: getTargetTriple(X: SummaryEncoding).str());
173
174 RootObject["tu_namespace"] =
175 buildNamespaceToJSON(BN: getTUNamespace(X: SummaryEncoding));
176
177 RootObject["id_table"] = tuEntityIdTableToJSON(IdTable: getIdTable(X: SummaryEncoding));
178
179 RootObject["linkage_table"] =
180 linkageTableToJSON(LinkageTable: getLinkageTable(X: SummaryEncoding));
181
182 RootObject["data"] = encodingSummaryDataMapToJSON(EncodingSummaryDataMap: getData(X: SummaryEncoding));
183
184 if (auto Error = writeJSON(V: std::move(RootObject), Path)) {
185 return ErrorBuilder::wrap(E: std::move(Error))
186 .context(Fmt: ErrorMessages::WritingToFile, ArgVals: "TUSummary", ArgVals&: Path)
187 .build();
188 }
189
190 return llvm::Error::success();
191}
192
193} // namespace clang::ssaf
194