clang 23.0.0git
LUSummary.cpp
Go to the documentation of this file.
1//===- LUSummary.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
12#include "llvm/TargetParser/Triple.h"
13
14#include <set>
15
16namespace clang::ssaf {
17
18//----------------------------------------------------------------------------
19// LUSummary
20//----------------------------------------------------------------------------
21
23 auto ExpectedJSON = readJSON(Path);
24 if (!ExpectedJSON) {
25 return ErrorBuilder::wrap(ExpectedJSON.takeError())
26 .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
27 .build();
28 }
29
30 Object *RootObjectPtr = ExpectedJSON->getAsObject();
31 if (!RootObjectPtr) {
32 return ErrorBuilder::create(std::errc::invalid_argument,
34 "object")
35 .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
36 .build();
37 }
38
39 if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueLUSummary)) {
40 return ErrorBuilder::wrap(std::move(Err))
41 .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
42 .build();
43 }
44
45 auto ExpectedSummary = readLUSummaryFromObject(*RootObjectPtr);
46 if (!ExpectedSummary) {
47 return ErrorBuilder::wrap(ExpectedSummary.takeError())
48 .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
49 .build();
50 }
51
52 return std::move(*ExpectedSummary);
53}
54
56JSONFormat::readLUSummaryFromObject(const Object &RootObject) {
57 auto OptTargetTriple = RootObject.getString("target_triple");
58 if (!OptTargetTriple) {
59 return ErrorBuilder::create(std::errc::invalid_argument,
61 "TargetTriple", "target_triple", "string")
62 .build();
63 }
64
65 if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
66 return ErrorBuilder::wrap(std::move(Err))
68 "target_triple")
69 .build();
70 }
71
72 llvm::Triple T(*OptTargetTriple);
73
74 const Array *LUNamespaceArray = RootObject.getArray("lu_namespace");
75 if (!LUNamespaceArray) {
76 return ErrorBuilder::create(std::errc::invalid_argument,
78 "NestedBuildNamespace", "lu_namespace", "array")
79 .build();
80 }
81
82 auto ExpectedLUNamespace = nestedBuildNamespaceFromJSON(*LUNamespaceArray);
83 if (!ExpectedLUNamespace) {
84 return ErrorBuilder::wrap(ExpectedLUNamespace.takeError())
85 .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
86 "lu_namespace")
87 .build();
88 }
89
90 LUSummary Summary(std::move(T), std::move(*ExpectedLUNamespace));
91
92 {
93 const Array *IdTableArray = RootObject.getArray("id_table");
94 if (!IdTableArray) {
95 return ErrorBuilder::create(std::errc::invalid_argument,
97 "IdTable", "id_table", "array")
98 .build();
99 }
100
101 auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
102 if (!ExpectedIdTable) {
103 return ErrorBuilder::wrap(ExpectedIdTable.takeError())
104 .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
105 .build();
106 }
107
108 getIdTable(Summary) = std::move(*ExpectedIdTable);
109 }
110
111 {
112 const Array *LinkageTableArray = RootObject.getArray("linkage_table");
113 if (!LinkageTableArray) {
114 return ErrorBuilder::create(std::errc::invalid_argument,
116 "LinkageTable", "linkage_table", "array")
117 .build();
118 }
119
120 auto ExpectedIdRange =
121 llvm::make_second_range(getEntities(getIdTable(Summary)));
122 std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
123 ExpectedIdRange.end());
124
125 // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
126 // that the linkage table contains exactly the ids present in the IdTable.
127 auto ExpectedLinkageTable =
128 linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
129 if (!ExpectedLinkageTable) {
130 return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
132 "linkage_table")
133 .build();
134 }
135
136 getLinkageTable(Summary) = std::move(*ExpectedLinkageTable);
137 }
138
139 {
140 const Array *SummaryDataArray = RootObject.getArray("data");
141 if (!SummaryDataArray) {
142 return ErrorBuilder::create(std::errc::invalid_argument,
144 "SummaryData entries", "data", "array")
145 .build();
146 }
147
148 auto ExpectedSummaryDataMap =
149 summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary));
150 if (!ExpectedSummaryDataMap) {
151 return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError())
152 .context(ErrorMessages::ReadingFromField, "SummaryData entries",
153 "data")
154 .build();
155 }
156
157 getData(Summary) = std::move(*ExpectedSummaryDataMap);
158 }
159
160 return std::move(Summary);
161}
162
164 llvm::StringRef Path) {
165 Object RootObject;
166
168
169 RootObject["target_triple"] =
170 llvm::Triple::normalize(getTargetTriple(S).str());
171
172 RootObject["lu_namespace"] = nestedBuildNamespaceToJSON(getLUNamespace(S));
173
174 RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(S));
175
176 RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S));
177
178 auto ExpectedDataObject = summaryDataMapToJSON(getData(S));
179 if (!ExpectedDataObject) {
180 return ErrorBuilder::wrap(ExpectedDataObject.takeError())
181 .context(ErrorMessages::WritingToFile, "LUSummary", Path)
182 .build();
183 }
184
185 RootObject["data"] = std::move(*ExpectedDataObject);
186
187 if (auto Error = writeJSON(std::move(RootObject), Path)) {
188 return ErrorBuilder::wrap(std::move(Error))
189 .context(ErrorMessages::WritingToFile, "LUSummary", Path)
190 .build();
191 }
192
193 return llvm::Error::success();
194}
195
196} // namespace clang::ssaf
llvm::json::Array Array
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
ErrorBuilder & context(const char *Msg)
Add context information as a plain string.
llvm::Error build() const
Build and return the final error.
static ErrorBuilder wrap(llvm::Error E)
Wrap an existing error and optionally add context.
llvm::Error writeLUSummary(const LUSummary &Summary, llvm::StringRef Path) override
llvm::Expected< LUSummary > readLUSummary(llvm::StringRef Path) override
Definition LUSummary.cpp:22
Represents a link unit (LU) summary containing merged entity summaries.
Definition LUSummary.h:34
constexpr const char * ReadingFromFile
constexpr const char * ReadingFromField
constexpr const char * FailedToReadObjectAtField
constexpr const char * WritingToFile
constexpr const char * FailedToReadObject
constexpr const char * JSONTypeKey
Root-object key naming the summary kind so files are self-describing.
constexpr const char * JSONTypeValueLUSummary
Value written to JSONTypeKey for serialized LUSummary files.
llvm::Error validateNormalizedTargetTriple(llvm::StringRef Triple)
Validates that Triple is a target triple string in normalized form.
llvm::json::Object Object
llvm::Expected< Value > readJSON(llvm::StringRef Path)
llvm::Error checkSummaryType(const Object &RootObject, llvm::StringRef ExpectedType)
Reads the JSONTypeKey field from the root object and verifies it equals ExpectedType.
llvm::Error writeJSON(Value &&V, llvm::StringRef Path)