clang 23.0.0git
CallGraphJSONFormat.cpp
Go to the documentation of this file.
1//===- CallGraphJSONFormat.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
13#include "llvm/ADT/STLExtras.h"
14#include "llvm/Support/JSON.h"
15#include <memory>
16
17using namespace llvm;
18using namespace clang;
19using namespace ssaf;
20
21static const char *FailedToReadObjectAtField =
22 "failed to read {0} from field '{1}': expected JSON {2}";
23static const char *FailedToReadObjectAtIndex =
24 "failed to read {0} from index '{1}': expected JSON {2}";
25static const char *ReadingFromField = "reading {0} from field '{1}'";
26static const char *ReadingFromIndex = "reading {0} from index '{1}'";
27
28static json::Object serialize(const EntitySummary &Summary,
30 const auto &S = static_cast<const CallGraphSummary &>(Summary);
31
32 json::Array DirectCalleesArray;
33 DirectCalleesArray.reserve(S.DirectCallees.size());
34 append_range(DirectCalleesArray, map_range(S.DirectCallees, ToJSON));
35
36 json::Array VirtualCalleesArray;
37 VirtualCalleesArray.reserve(S.VirtualCallees.size());
38 append_range(VirtualCalleesArray, map_range(S.VirtualCallees, ToJSON));
39
40 return json::Object{
41 {"pretty_name", json::Value(S.PrettyName)},
42 {"direct_callees", std::move(DirectCalleesArray)},
43 {"virtual_callees", std::move(VirtualCalleesArray)},
44 {"def",
45 json::Object{
46 {"file", json::Value(S.Definition.File)},
47 {"line", json::Value(S.Definition.Line)},
48 {"col", json::Value(S.Definition.Column)},
49 }},
50 };
51}
52
54deserialize(const json::Object &Obj, EntityIdTable &IdTable,
56 auto Result = std::make_unique<CallGraphSummary>();
57
58 auto PrettyName = Obj.getString("pretty_name");
59 if (!PrettyName) {
60 return ErrorBuilder::create(std::errc::invalid_argument,
61 FailedToReadObjectAtField, "PrettyName",
62 "pretty_name", "string")
63 .build();
64 }
65 Result->PrettyName = PrettyName->str();
66
67 const json::Array *CalleesArray = Obj.getArray("direct_callees");
68 if (!CalleesArray) {
69 return ErrorBuilder::create(std::errc::invalid_argument,
70 FailedToReadObjectAtField, "DirectCallees",
71 "direct_callees", "array")
72 .build();
73 }
74 for (const auto &[Index, Value] : llvm::enumerate(*CalleesArray)) {
75 const json::Object *CalleeObj = Value.getAsObject();
76 if (!CalleeObj) {
77 return ErrorBuilder::create(std::errc::invalid_argument,
78 FailedToReadObjectAtIndex, "EntityId", Index,
79 "object")
80 .context(ReadingFromField, "DirectCallees", "direct_callees")
81 .build();
82 }
83 auto ExpectedId = FromJSON(*CalleeObj);
84 if (!ExpectedId) {
85 return ErrorBuilder::wrap(ExpectedId.takeError())
86 .context(ReadingFromIndex, "EntityId", Index)
87 .context(ReadingFromField, "DirectCallees", "direct_callees")
88 .build();
89 }
90 Result->DirectCallees.insert(*ExpectedId);
91 }
92
93 const json::Array *VirtualCalleesArray = Obj.getArray("virtual_callees");
94 if (!VirtualCalleesArray) {
95 return ErrorBuilder::create(std::errc::invalid_argument,
96 FailedToReadObjectAtField, "VirtualCallees",
97 "virtual_callees", "array")
98 .build();
99 }
100 for (const auto &[Index, Value] : llvm::enumerate(*VirtualCalleesArray)) {
101 const json::Object *CalleeObj = Value.getAsObject();
102 if (!CalleeObj) {
103 return ErrorBuilder::create(std::errc::invalid_argument,
104 FailedToReadObjectAtIndex, "EntityId", Index,
105 "object")
106 .context(ReadingFromField, "VirtualCallees", "virtual_callees")
107 .build();
108 }
109 auto ExpectedId = FromJSON(*CalleeObj);
110 if (!ExpectedId) {
111 return ErrorBuilder::wrap(ExpectedId.takeError())
112 .context(ReadingFromIndex, "EntityId", Index)
113 .context(ReadingFromField, "VirtualCallees", "virtual_callees")
114 .build();
115 }
116 Result->VirtualCallees.insert(*ExpectedId);
117 }
118
119 const json::Object *DefObj = Obj.getObject("def");
120 if (!DefObj) {
121 return ErrorBuilder::create(std::errc::invalid_argument,
122 FailedToReadObjectAtField, "SourceLocation",
123 "def", "object")
124 .build();
125 }
126 auto File = DefObj->getString("file");
127 if (!File) {
128 return ErrorBuilder::create(std::errc::invalid_argument,
129 FailedToReadObjectAtField, "File", "file",
130 "string")
131 .context(ReadingFromField, "SourceLocation", "def")
132 .build();
133 }
134 auto Line = DefObj->getInteger("line");
135 if (!Line) {
136 return ErrorBuilder::create(std::errc::invalid_argument,
137 FailedToReadObjectAtField, "Line", "line",
138 "number")
139 .context(ReadingFromField, "SourceLocation", "def")
140 .build();
141 }
142 auto Col = DefObj->getInteger("col");
143 if (!Col) {
144 return ErrorBuilder::create(std::errc::invalid_argument,
145 FailedToReadObjectAtField, "Column", "col",
146 "number")
147 .context(ReadingFromField, "SourceLocation", "def")
148 .build();
149 }
150 Result->Definition = {
151 File->str(),
152 static_cast<unsigned>(*Line),
153 static_cast<unsigned>(*Col),
154 };
155
156 return std::move(Result);
157}
158
159namespace {
160struct CallGraphJSONFormatInfo final : JSONFormat::FormatInfo {
161 CallGraphJSONFormatInfo()
162 : JSONFormat::FormatInfo(SummaryName(CallGraphSummary::Name.str()),
164};
165} // namespace
166
167static llvm::Registry<JSONFormat::FormatInfo>::Add<CallGraphJSONFormatInfo>
169 "JSON Format info for CallGraph summary");
170
171// This anchor is used to force the linker to link in the generated object file
172// and thus register the JSON format for CallGraphSummary.
173// NOLINTNEXTLINE(misc-use-internal-linkage)
static const char * FailedToReadObjectAtIndex
static const char * ReadingFromIndex
static const char * ReadingFromField
static json::Object serialize(const EntitySummary &Summary, JSONFormat::EntityIdToJSONFn ToJSON)
static const char * FailedToReadObjectAtField
static llvm::Registry< JSONFormat::FormatInfo >::Add< CallGraphJSONFormatInfo > RegisterFormatInfo(CallGraphSummary::Name, "JSON Format info for CallGraph summary")
static Expected< std::unique_ptr< EntitySummary > > deserialize(const json::Object &Obj, EntityIdTable &IdTable, JSONFormat::EntityIdFromJSONFn FromJSON)
volatile int CallGraphJSONFormatAnchorSource
Manages entity name interning and provides efficient EntityId handles.
Base class for analysis-specific summary data.
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::function_ref< llvm::Expected< EntityId >(const Object &)> EntityIdFromJSONFn
Definition JSONFormat.h:66
FormatInfoEntry< SerializerFn, DeserializerFn > FormatInfo
Definition JSONFormat.h:75
llvm::function_ref< Object(EntityId)> EntityIdToJSONFn
Definition JSONFormat.h:65
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
Summary of direct call-graph edges for a single function entity.
static constexpr llvm::StringLiteral Name