clang 23.0.0git
Artifact.cpp
Go to the documentation of this file.
1//===- Artifact.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// Generic artifact read/write entry points that dispatch on the
10// self-describing "type" field of the JSON document.
11//
12//===----------------------------------------------------------------------===//
13
14#include "JSONFormatImpl.h"
15
16namespace clang::ssaf {
17
19 auto ExpectedJSON = readJSON(Path);
20 if (!ExpectedJSON) {
21 return ErrorBuilder::wrap(ExpectedJSON.takeError())
22 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
23 .build();
24 }
25
26 Object *RootObjectPtr = ExpectedJSON->getAsObject();
27 if (!RootObjectPtr) {
28 return ErrorBuilder::create(std::errc::invalid_argument,
30 "object")
31 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
32 .build();
33 }
34
35 auto ExpectedType = readSummaryType(*RootObjectPtr);
36 if (!ExpectedType) {
37 return ErrorBuilder::wrap(ExpectedType.takeError())
38 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
39 .build();
40 }
41
42 // Dispatch by the self-describing type field. The helpers operate on
43 // the already-parsed root object so the file is read and parsed only
44 // once per readArtifact call.
46 auto ExpectedTU = readTUSummaryFromObject(*RootObjectPtr);
47 if (!ExpectedTU) {
48 return ErrorBuilder::wrap(ExpectedTU.takeError())
49 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
50 .build();
51 }
52 return Artifact{std::move(*ExpectedTU)};
53 }
54
56 auto ExpectedLU = readLUSummaryFromObject(*RootObjectPtr);
57 if (!ExpectedLU) {
58 return ErrorBuilder::wrap(ExpectedLU.takeError())
59 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
60 .build();
61 }
62 return Artifact{std::move(*ExpectedLU)};
63 }
64
66 auto ExpectedWPA = readWPASuiteFromObject(*RootObjectPtr);
67 if (!ExpectedWPA) {
68 return ErrorBuilder::wrap(ExpectedWPA.takeError())
69 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
70 .build();
71 }
72 return Artifact{std::move(*ExpectedWPA)};
73 }
74
75 return ErrorBuilder::create(std::errc::invalid_argument,
79 .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
80 .build();
81}
82
83llvm::Error JSONFormat::writeArtifact(const Artifact &A, llvm::StringRef Path) {
84 return std::visit(
85 [&](const auto &S) -> llvm::Error {
86 using T = std::decay_t<decltype(S)>;
87 if constexpr (std::is_same_v<T, TUSummary>) {
88 return writeTUSummary(S, Path);
89 } else if constexpr (std::is_same_v<T, LUSummary>) {
90 return writeLUSummary(S, Path);
91 } else {
92 static_assert(std::is_same_v<T, WPASuite>,
93 "Artifact visitor must cover all variant alternatives");
94 return writeWPASuite(S, Path);
95 }
96 },
97 A);
98}
99
101JSONFormat::readArtifactEncoding(llvm::StringRef Path) {
102 auto ExpectedJSON = readJSON(Path);
103 if (!ExpectedJSON) {
104 return ErrorBuilder::wrap(ExpectedJSON.takeError())
105 .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
106 .build();
107 }
108
109 Object *RootObjectPtr = ExpectedJSON->getAsObject();
110 if (!RootObjectPtr) {
111 return ErrorBuilder::create(std::errc::invalid_argument,
113 "ArtifactEncoding", "object")
114 .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
115 .build();
116 }
117
118 auto ExpectedType = readSummaryType(*RootObjectPtr);
119 if (!ExpectedType) {
120 return ErrorBuilder::wrap(ExpectedType.takeError())
121 .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
122 .build();
123 }
124
125 // Dispatch by the self-describing type field. The helpers operate on
126 // the already-parsed root object so the file is read and parsed only
127 // once per readArtifactEncoding call.
129 auto ExpectedTU = readTUSummaryEncodingFromObject(*RootObjectPtr);
130 if (!ExpectedTU) {
131 return ErrorBuilder::wrap(ExpectedTU.takeError())
132 .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
133 .build();
134 }
135 return ArtifactEncoding{std::move(*ExpectedTU)};
136 }
137
139 auto ExpectedLU = readLUSummaryEncodingFromObject(*RootObjectPtr);
140 if (!ExpectedLU) {
141 return ErrorBuilder::wrap(ExpectedLU.takeError())
142 .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
143 .build();
144 }
145 return ArtifactEncoding{std::move(*ExpectedLU)};
146 }
147
148 return ErrorBuilder::create(std::errc::invalid_argument,
152 .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
153 .build();
154}
155
157 llvm::StringRef Path) {
158 return std::visit(
159 [&](const auto &Enc) -> llvm::Error {
160 using T = std::decay_t<decltype(Enc)>;
161 if constexpr (std::is_same_v<T, TUSummaryEncoding>) {
162 return writeTUSummaryEncoding(Enc, Path);
163 } else {
164 static_assert(
165 std::is_same_v<T, LUSummaryEncoding>,
166 "ArtifactEncoding visitor must cover all variant alternatives");
167 return writeLUSummaryEncoding(Enc, Path);
168 }
169 },
170 E);
171}
172
173} // namespace clang::ssaf
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 writeArtifact(const Artifact &A, llvm::StringRef Path) override
Generic write entry point.
Definition Artifact.cpp:83
llvm::Expected< ArtifactEncoding > readArtifactEncoding(llvm::StringRef Path) override
Encoding-flavored counterpart of readArtifact.
Definition Artifact.cpp:101
llvm::Error writeArtifactEncoding(const ArtifactEncoding &E, llvm::StringRef Path) override
Encoding-flavored counterpart of writeArtifact.
Definition Artifact.cpp:156
llvm::Error writeLUSummary(const LUSummary &Summary, llvm::StringRef Path) override
llvm::Error writeWPASuite(const WPASuite &Suite, llvm::StringRef Path) override
Definition WPASuite.cpp:200
llvm::Error writeTUSummary(const TUSummary &Summary, llvm::StringRef Path) override
llvm::Error writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) override
llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) override
llvm::Expected< Artifact > readArtifact(llvm::StringRef Path) override
Generic read entry point.
Definition Artifact.cpp:18
constexpr const char * ReadingFromFile
constexpr const char * UnknownArtifactEncodingType
constexpr const char * FailedToReadObject
constexpr const char * UnknownArtifactType
constexpr const char * JSONTypeKey
Root-object key naming the summary kind so files are self-describing.
llvm::Expected< llvm::StringRef > readSummaryType(const Object &RootObject)
Reads the JSONTypeKey field from the root object as a string.
constexpr const char * JSONTypeValueWPASuite
Value written to JSONTypeKey for serialized WPASuite files.
constexpr const char * JSONTypeValueTUSummary
Value written to JSONTypeKey for serialized TUSummary files.
constexpr const char * JSONTypeValueLUSummary
Value written to JSONTypeKey for serialized LUSummary files.
std::variant< TUSummaryEncoding, LUSummaryEncoding > ArtifactEncoding
Lazily-deserialized counterpart of Artifact: the same on-disk artifacts but with their per-entity sum...
llvm::Expected< Value > readJSON(llvm::StringRef Path)
std::variant< TUSummary, LUSummary, WPASuite > Artifact
Sum type returned by SerializationFormat::readArtifact, used when the caller does not know up-front w...
llvm::Expected< QualType > ExpectedType