blob: 410653c820d14101919d6b385ebbe96e8be1cce8 [file] [log] [blame]
Marcel Hlopko42abfc82021-08-09 07:03:17 +00001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#include "rs_bindings_from_cc/ir.h"
6
Devin Jeanpierref2ec8712021-10-13 20:47:16 +00007#include <optional>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +00008#include <ostream>
Marcel Hlopko42abfc82021-08-09 07:03:17 +00009#include <string>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000010#include <utility>
Devin Jeanpierref2ec8712021-10-13 20:47:16 +000011#include <variant>
Marcel Hlopko42abfc82021-08-09 07:03:17 +000012#include <vector>
13
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070014#include "absl/log/check.h"
Dmitri Gribenko785831e2023-07-14 06:47:36 -070015#include "absl/strings/str_cat.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070016#include "absl/strings/string_view.h"
Dmitri Gribenko785831e2023-07-14 06:47:36 -070017#include "common/string_type.h"
Marco Polettic61bcc42022-04-08 12:54:30 -070018#include "common/strong_int.h"
Googler1bff6372023-03-24 10:06:29 -070019#include "clang/AST/Type.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070020#include "llvm/Support/JSON.h"
Marcel Hlopko42abfc82021-08-09 07:03:17 +000021
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070022namespace crubit {
Marcel Hlopko42abfc82021-08-09 07:03:17 +000023
Googler7ce38c92021-12-02 07:50:52 +000024template <class T>
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000025llvm::json::Value toJSON(const T& t) {
26 return t.ToJson();
Googler7ce38c92021-12-02 07:50:52 +000027}
28
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000029template <typename TTag, typename TInt>
Marco Polettic61bcc42022-04-08 12:54:30 -070030llvm::json::Value toJSON(const crubit::StrongInt<TTag, TInt> strong_int) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000031 return llvm::json::Value(strong_int.value());
Marcel Hlopkof1123c82021-08-19 11:38:52 +000032}
33
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000034template <typename TTag>
Marco Polettic61bcc42022-04-08 12:54:30 -070035llvm::json::Value toJSON(const crubit::StringType<TTag> string_type) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000036 return llvm::json::Value(string_type.value());
Googler64e4edb2021-12-03 12:17:38 +000037}
38
Lukasz Anforowiczfea0db92022-05-17 17:28:04 -070039template <class T>
40llvm::json::Value toJSON(const absl::StatusOr<T>& t) {
41 if (t.ok()) {
42 return llvm::json::Object{{"Ok", *t}};
43 }
44 return llvm::json::Object{{"Err", std::string(t.status().message())}};
45}
46
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000047llvm::json::Value HeaderName::ToJson() const {
48 return llvm::json::Object{
49 {"name", name_},
50 };
Marcel Hlopko42abfc82021-08-09 07:03:17 +000051}
52
Marcel Hlopkoaf682a02022-04-08 07:27:14 -070053llvm::json::Value LifetimeName::ToJson() const {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000054 return llvm::json::Object{
55 {"name", name},
56 {"id", id},
57 };
58}
Devin Jeanpierre09c6f452021-09-29 07:34:24 +000059
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000060llvm::json::Value RsType::ToJson() const {
61 return llvm::json::Object{
Dmitri Gribenko57ddcf92022-07-20 10:24:33 -070062 {"name", decl_id.has_value() ? llvm::json::Value(nullptr)
63 : llvm::json::Value(name)},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000064 {"lifetime_args", lifetime_args},
65 {"type_args", type_args},
66 {"decl_id", decl_id},
67 };
68}
Devin Jeanpierre09c6f452021-09-29 07:34:24 +000069
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000070llvm::json::Value CcType::ToJson() const {
71 return llvm::json::Object{
Dmitri Gribenko57ddcf92022-07-20 10:24:33 -070072 {"name", decl_id.has_value() ? llvm::json::Value(nullptr)
73 : llvm::json::Value(name)},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000074 {"is_const", is_const},
75 {"type_args", type_args},
76 {"decl_id", decl_id},
77 };
Devin Jeanpierre09c6f452021-09-29 07:34:24 +000078}
79
Devin Jeanpierredeea7892022-03-29 02:13:31 -070080namespace {
81enum class ValueCategory { kLvalue, kRvalue };
82
Googler1bff6372023-03-24 10:06:29 -070083MappedType PointerOrReferenceTo(
84 MappedType pointee_type, absl::string_view cc_ptr_name,
85 ValueCategory value_category, std::optional<LifetimeId> lifetime,
86 std::optional<clang::RefQualifierKind> ref_qualifier_kind, bool nullable) {
Googler454f2652021-12-06 12:53:12 +000087 bool has_lifetime = lifetime.has_value();
Devin Jeanpierre70393902022-03-15 13:22:59 +000088 absl::string_view rs_name;
Devin Jeanpierredeea7892022-03-29 02:13:31 -070089 if (value_category == ValueCategory::kLvalue) {
90 if (has_lifetime) {
Googler1bff6372023-03-24 10:06:29 -070091 if (ref_qualifier_kind.has_value() &&
92 ref_qualifier_kind.value() == clang::RefQualifierKind::RQ_RValue) {
93 rs_name = pointee_type.cc_type.is_const ? internal::kRustRvalueRefConst
94 : internal::kRustRvalueRefMut;
95 } else {
96 rs_name = pointee_type.cc_type.is_const ? internal::kRustRefConst
97 : internal::kRustRefMut;
98 }
Devin Jeanpierredeea7892022-03-29 02:13:31 -070099 } else {
100 rs_name = pointee_type.cc_type.is_const ? internal::kRustPtrConst
101 : internal::kRustPtrMut;
102 }
Googler02da3fb2021-12-06 11:59:19 +0000103 } else {
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -0700104 CHECK(has_lifetime);
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700105 rs_name = pointee_type.cc_type.is_const ? internal::kRustRvalueRefConst
106 : internal::kRustRvalueRefMut;
Googler02da3fb2021-12-06 11:59:19 +0000107 }
108 auto pointer_type =
Devin Jeanpierre70393902022-03-15 13:22:59 +0000109 MappedType::Simple(std::string(rs_name), std::string(cc_ptr_name));
Googler454f2652021-12-06 12:53:12 +0000110 if (has_lifetime) {
Googler02da3fb2021-12-06 11:59:19 +0000111 pointer_type.rs_type.lifetime_args.push_back(*std::move(lifetime));
112 }
113 pointer_type.rs_type.type_args.push_back(std::move(pointee_type.rs_type));
Googler454f2652021-12-06 12:53:12 +0000114 if (has_lifetime && nullable) {
115 pointer_type.rs_type =
116 RsType{.name = "Option", .type_args = {pointer_type.rs_type}};
117 }
Googler02da3fb2021-12-06 11:59:19 +0000118 pointer_type.cc_type.type_args.push_back(std::move(pointee_type.cc_type));
119 return pointer_type;
120}
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700121} // namespace
Googler02da3fb2021-12-06 11:59:19 +0000122
Googler1bff6372023-03-24 10:06:29 -0700123MappedType MappedType::PointerTo(
124 MappedType pointee_type, std::optional<LifetimeId> lifetime,
125 std::optional<clang::RefQualifierKind> ref_qualifier_kind, bool nullable) {
Devin Jeanpierre70393902022-03-15 13:22:59 +0000126 return PointerOrReferenceTo(std::move(pointee_type), internal::kCcPtr,
Googler1bff6372023-03-24 10:06:29 -0700127 ValueCategory::kLvalue, lifetime,
128 ref_qualifier_kind, nullable);
Devin Jeanpierre70393902022-03-15 13:22:59 +0000129}
130
Googler02da3fb2021-12-06 11:59:19 +0000131MappedType MappedType::LValueReferenceTo(MappedType pointee_type,
132 std::optional<LifetimeId> lifetime) {
Devin Jeanpierre70393902022-03-15 13:22:59 +0000133 return PointerOrReferenceTo(std::move(pointee_type), internal::kCcLValueRef,
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700134 ValueCategory::kLvalue, lifetime,
Googler1bff6372023-03-24 10:06:29 -0700135 /*ref_qualifier_kind=*/std::nullopt,
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700136 /*nullable=*/false);
137}
138
139MappedType MappedType::RValueReferenceTo(MappedType pointee_type,
140 LifetimeId lifetime) {
141 return PointerOrReferenceTo(std::move(pointee_type), internal::kCcRValueRef,
142 ValueCategory::kRvalue, lifetime,
Googler1bff6372023-03-24 10:06:29 -0700143 /*ref_qualifier_kind=*/std::nullopt,
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700144 /*nullable=*/false);
Googler02da3fb2021-12-06 11:59:19 +0000145}
146
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000147MappedType MappedType::FuncPtr(absl::string_view cc_call_conv,
148 absl::string_view rs_abi,
149 std::optional<LifetimeId> lifetime,
150 MappedType return_type,
151 std::vector<MappedType> param_types) {
Lukasz Anforowicz92c81c32022-03-04 19:03:56 +0000152 MappedType result = FuncRef(cc_call_conv, rs_abi, lifetime,
153 std::move(return_type), std::move(param_types));
154
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -0700155 CHECK_EQ(result.cc_type.name, internal::kCcLValueRef);
Lukasz Anforowicz92c81c32022-03-04 19:03:56 +0000156 result.cc_type.name = std::string(internal::kCcPtr);
157
158 RsType rs_func_ptr_type = std::move(result.rs_type);
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -0700159 CHECK(rs_func_ptr_type.name.substr(0, internal::kRustFuncPtr.length()) ==
160 internal::kRustFuncPtr);
Lukasz Anforowicz92c81c32022-03-04 19:03:56 +0000161 result.rs_type =
162 RsType{.name = "Option", .type_args = {std::move(rs_func_ptr_type)}};
163
164 return result;
165}
166
167MappedType MappedType::FuncRef(absl::string_view cc_call_conv,
168 absl::string_view rs_abi,
169 std::optional<LifetimeId> lifetime,
170 MappedType return_type,
171 std::vector<MappedType> param_types) {
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000172 std::vector<MappedType> type_args = std::move(param_types);
173 type_args.push_back(std::move(return_type));
174
175 std::vector<CcType> cc_type_args;
176 std::vector<RsType> rs_type_args;
177 cc_type_args.reserve(type_args.size());
178 rs_type_args.reserve(type_args.size());
179 for (MappedType& type_arg : type_args) {
180 cc_type_args.push_back(std::move(type_arg.cc_type));
181 rs_type_args.push_back(std::move(type_arg.rs_type));
182 }
183
184 CcType cc_func_value_type = CcType{
185 .name = absl::StrCat(internal::kCcFuncValue, " ", cc_call_conv),
186 .type_args = std::move(cc_type_args),
187 };
Lukasz Anforowicz92c81c32022-03-04 19:03:56 +0000188 CcType cc_func_ref_type = CcType{.name = std::string(internal::kCcLValueRef),
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000189 .type_args = {cc_func_value_type}};
190
191 // Rust cannot express a function *value* type, only function pointer types.
192 RsType rs_func_ptr_type = RsType{
193 .name = absl::StrCat(internal::kRustFuncPtr, " ", rs_abi),
194 .type_args = std::move(rs_type_args),
195 };
196 if (lifetime.has_value())
197 rs_func_ptr_type.lifetime_args.push_back(*std::move(lifetime));
198
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000199 return MappedType{
Lukasz Anforowicz92c81c32022-03-04 19:03:56 +0000200 .rs_type = std::move(rs_func_ptr_type),
201 .cc_type = std::move(cc_func_ref_type),
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000202 };
203}
204
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000205llvm::json::Value MappedType::ToJson() const {
206 return llvm::json::Object{
207 {"rs_type", rs_type},
208 {"cc_type", cc_type},
209 };
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000210}
211
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000212llvm::json::Value Identifier::ToJson() const {
213 return llvm::json::Object{
214 {"identifier", identifier_},
215 };
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000216}
217
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000218llvm::json::Value IntegerConstant::ToJson() const {
219 return llvm::json::Object{
220 {"is_negative", is_negative_},
221 {"wrapped_value", wrapped_value_},
222 };
Teddy Katz76fa42b2022-02-23 01:22:56 +0000223}
224
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000225llvm::json::Value Operator::ToJson() const {
226 return llvm::json::Object{
227 {"name", name_},
228 };
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000229}
230
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000231static std::string SpecialNameToString(SpecialName special_name) {
232 switch (special_name) {
233 case SpecialName::kDestructor:
234 return "Destructor";
235 case SpecialName::kConstructor:
236 return "Constructor";
237 }
238}
239
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000240llvm::json::Value toJSON(const UnqualifiedIdentifier& unqualified_identifier) {
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000241 if (auto* id = std::get_if<Identifier>(&unqualified_identifier)) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000242 return llvm::json::Object{
243 {"Identifier", *id},
244 };
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000245 } else if (auto* op = std::get_if<Operator>(&unqualified_identifier)) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000246 return llvm::json::Object{
247 {"Operator", *op},
248 };
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000249 } else {
250 SpecialName special_name = std::get<SpecialName>(unqualified_identifier);
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000251 return llvm::json::Object{
252 {SpecialNameToString(special_name), nullptr},
253 };
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000254 }
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000255}
256
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000257llvm::json::Value FuncParam::ToJson() const {
258 return llvm::json::Object{
259 {"type", type},
260 {"identifier", identifier},
261 };
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000262}
263
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000264std::ostream& operator<<(std::ostream& o, const SpecialName& special_name) {
265 return o << SpecialNameToString(special_name);
266}
267
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000268llvm::json::Value MemberFuncMetadata::InstanceMethodMetadata::ToJson() const {
269 const char* reference_str = nullptr;
270 switch (reference) {
271 case MemberFuncMetadata::kLValue:
272 reference_str = "LValue";
273 break;
274 case MemberFuncMetadata::kRValue:
275 reference_str = "RValue";
276 break;
277 case MemberFuncMetadata::kUnqualified:
278 reference_str = "Unqualified";
279 break;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000280 }
281
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000282 return llvm::json::Object{
283 {"reference", reference_str},
284 {"is_const", is_const},
285 {"is_virtual", is_virtual},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000286 };
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000287}
288
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000289llvm::json::Value MemberFuncMetadata::ToJson() const {
290 return llvm::json::Object{
291 {"record_id", record_id},
292 {"instance_method_metadata", instance_method_metadata},
293 };
294}
Michael Forster7ef80732021-10-01 18:12:19 +0000295
Devin Jeanpierre93e800e2023-05-08 12:55:53 -0700296llvm::json::Value TypeMapOverride::ToJson() const {
297 llvm::json::Object override{
Devin Jeanpierreb7f8e282023-05-26 16:03:12 -0700298 {"rs_name", rs_name},
299 {"cc_name", cc_name},
Devin Jeanpierre93e800e2023-05-08 12:55:53 -0700300 {"owning_target", owning_target},
Devin Jeanpierrec850c772023-05-30 17:14:19 -0700301 {"is_same_abi", is_same_abi},
Devin Jeanpierre93e800e2023-05-08 12:55:53 -0700302 {"id", id},
303 };
Devin Jeanpierre1e2d3242023-05-15 12:21:59 -0700304 if (size_align.has_value()) {
305 override.insert({"size_align", size_align->ToJson()});
306 }
Devin Jeanpierre93e800e2023-05-08 12:55:53 -0700307
308 return llvm::json::Object{
309 {"TypeMapOverride", std::move(override)},
310 };
311}
312
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -0700313llvm::json::Value UseMod::ToJson() const {
314 llvm::json::Object use_mod{
315 {"path", path},
316 {"mod_name", mod_name},
317 {"id", id},
318 };
319
320 return llvm::json::Object{
321 {"UseMod", std::move(use_mod)},
322 };
323}
324
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000325llvm::json::Value Func::ToJson() const {
326 llvm::json::Object func{
327 {"name", name},
328 {"owning_target", owning_target},
329 {"doc_comment", doc_comment},
330 {"mangled_name", mangled_name},
331 {"return_type", return_type},
332 {"params", params},
333 {"lifetime_params", lifetime_params},
334 {"is_inline", is_inline},
335 {"member_func_metadata", member_func_metadata},
Lukasz Anforowicz0b6a6ac2022-03-22 22:32:23 +0000336 {"has_c_calling_convention", has_c_calling_convention},
Lukasz Anforowiczb1ff2e52022-05-16 10:54:23 -0700337 {"is_member_or_descendant_of_class_template",
338 is_member_or_descendant_of_class_template},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000339 {"source_loc", source_loc},
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000340 {"id", id},
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700341 {"enclosing_namespace_id", enclosing_namespace_id},
Michael VanBemmel7a4d4c02022-07-27 13:21:47 -0700342 {"adl_enclosing_record", adl_enclosing_record},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000343 };
344
345 return llvm::json::Object{
346 {"Func", std::move(func)},
347 };
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000348}
349
Googler2294c702021-09-17 07:32:07 +0000350static std::string AccessToString(AccessSpecifier access) {
351 switch (access) {
352 case kPublic:
353 return "Public";
354 case kProtected:
355 return "Protected";
356 case kPrivate:
357 return "Private";
358 }
359}
360
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000361std::ostream& operator<<(std::ostream& o, const AccessSpecifier& access) {
362 return o << AccessToString(access);
363}
364
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000365llvm::json::Value Field::ToJson() const {
366 return llvm::json::Object{
367 {"identifier", identifier},
368 {"doc_comment", doc_comment},
369 {"type", type},
370 {"access", AccessToString(access)},
371 {"offset", offset},
Lukasz Anforowicz5765bb82022-05-17 17:21:06 -0700372 {"size", size},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000373 {"is_no_unique_address", is_no_unique_address},
Michael Forster82c02d32022-05-20 21:47:33 -0700374 {"is_bitfield", is_bitfield},
Kinuko Yasuda6ff59f12022-08-11 08:41:45 -0700375 {"is_inheritable", is_inheritable},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000376 };
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000377}
378
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700379llvm::json::Value toJSON(const SpecialMemberFunc& f) {
380 switch (f) {
381 case SpecialMemberFunc::kTrivial:
Devin Jeanpierre07931272021-10-05 11:40:13 +0000382 return "Trivial";
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700383 case SpecialMemberFunc::kNontrivialMembers:
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000384 return "NontrivialMembers";
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700385 case SpecialMemberFunc::kNontrivialUserDefined:
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000386 return "NontrivialUserDefined";
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700387 case SpecialMemberFunc::kUnavailable:
388 return "Unavailable";
Devin Jeanpierre07931272021-10-05 11:40:13 +0000389 }
390}
391
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000392llvm::json::Value BaseClass::ToJson() const {
393 return llvm::json::Object{
394 {"base_record_id", base_record_id},
395 {"offset", offset},
396 };
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000397}
Googler098c4582022-01-10 12:29:34 +0000398
Lukasz Anforowiczd4742ff2022-07-11 17:05:02 -0700399static std::string RecordTypeToString(RecordType record_type) {
400 switch (record_type) {
401 case kStruct:
402 return "Struct";
403 case kUnion:
404 return "Union";
405 case kClass:
406 return "Class";
407 }
408}
409
410std::ostream& operator<<(std::ostream& o, const RecordType& record_type) {
411 return o << RecordTypeToString(record_type);
412}
413
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700414llvm::json::Value IncompleteRecord::ToJson() const {
415 llvm::json::Object record{
416 {"cc_name", cc_name},
Rosica Dejanovskae12d7172022-06-22 12:20:17 -0700417 {"rs_name", rs_name},
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700418 {"id", id},
419 {"owning_target", owning_target},
Lukasz Anforowicz8dd51792022-08-31 10:11:17 -0700420 {"record_type", RecordTypeToString(record_type)},
Lukasz Anforowicz49dbeea2022-09-16 07:31:49 -0700421 {"enclosing_namespace_id", enclosing_namespace_id},
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700422 };
423
424 return llvm::json::Object{
425 {"IncompleteRecord", std::move(record)},
426 };
427}
428
Devin Jeanpierre1e2d3242023-05-15 12:21:59 -0700429llvm::json::Value SizeAlign::ToJson() const {
430 return llvm::json::Object{
431 {"size", size},
432 {"alignment", alignment},
433 };
434}
435
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000436llvm::json::Value Record::ToJson() const {
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700437 std::vector<llvm::json::Value> json_item_ids;
438 json_item_ids.reserve(child_item_ids.size());
439 for (const auto& id : child_item_ids) {
440 json_item_ids.push_back(id.value());
441 }
442
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000443 llvm::json::Object record{
444 {"rs_name", rs_name},
445 {"cc_name", cc_name},
Lukasz Anforowicz3f133972022-09-01 09:01:02 -0700446 {"mangled_cc_name", mangled_cc_name},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000447 {"id", id},
448 {"owning_target", owning_target},
Devin Jeanpierre3f0d0682023-04-13 14:47:28 -0700449 {"defining_target", defining_target},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000450 {"doc_comment", doc_comment},
Googlerafd18fb2023-01-25 12:55:07 -0800451 {"source_loc", source_loc},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000452 {"unambiguous_public_bases", unambiguous_public_bases},
453 {"fields", fields},
454 {"lifetime_params", lifetime_params},
Devin Jeanpierre1e2d3242023-05-15 12:21:59 -0700455 {"size_align", size_align.ToJson()},
Devin Jeanpierre1221c2a2022-05-05 22:36:22 -0700456 {"is_derived_class", is_derived_class},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000457 {"override_alignment", override_alignment},
458 {"copy_constructor", copy_constructor},
459 {"move_constructor", move_constructor},
460 {"destructor", destructor},
461 {"is_trivial_abi", is_trivial_abi},
Teddy Katzd2cd1422022-04-04 09:41:33 -0700462 {"is_inheritable", is_inheritable},
Devin Jeanpierreccb67672022-08-17 10:05:47 -0700463 {"is_abstract", is_abstract},
Lukasz Anforowiczd4742ff2022-07-11 17:05:02 -0700464 {"record_type", RecordTypeToString(record_type)},
Devin Jeanpierrea2be2a22022-05-18 18:59:05 -0700465 {"is_aggregate", is_aggregate},
Kinuko Yasuda8dd84642022-08-17 09:19:47 -0700466 {"is_anon_record_with_typedef", is_anon_record_with_typedef},
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700467 {"child_item_ids", std::move(json_item_ids)},
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700468 {"enclosing_namespace_id", enclosing_namespace_id},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000469 };
470
471 return llvm::json::Object{
472 {"Record", std::move(record)},
473 };
Teddy Katz76fa42b2022-02-23 01:22:56 +0000474}
475
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000476llvm::json::Value Enumerator::ToJson() const {
477 return llvm::json::Object{
478 {"identifier", identifier},
479 {"value", value},
480 };
Teddy Katz76fa42b2022-02-23 01:22:56 +0000481}
482
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000483llvm::json::Value Enum::ToJson() const {
484 llvm::json::Object enum_ir{
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700485 {"identifier", identifier},
486 {"id", id},
487 {"owning_target", owning_target},
Googlerafd18fb2023-01-25 12:55:07 -0800488 {"source_loc", source_loc},
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700489 {"underlying_type", underlying_type},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000490 {"enumerators", enumerators},
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700491 {"enclosing_namespace_id", enclosing_namespace_id},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000492 };
Googler098c4582022-01-10 12:29:34 +0000493
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000494 return llvm::json::Object{
495 {"Enum", std::move(enum_ir)},
496 };
Googler098c4582022-01-10 12:29:34 +0000497}
498
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000499llvm::json::Value TypeAlias::ToJson() const {
500 llvm::json::Object type_alias{
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700501 {"identifier", identifier},
502 {"id", id},
503 {"owning_target", owning_target},
504 {"doc_comment", doc_comment},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000505 {"underlying_type", underlying_type},
Devin Jeanpierre5fecde52022-09-14 06:53:39 -0700506 {"source_loc", source_loc},
507 {"enclosing_record_id", enclosing_record_id},
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700508 {"enclosing_namespace_id", enclosing_namespace_id},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000509 };
510
511 return llvm::json::Object{
512 {"TypeAlias", std::move(type_alias)},
513 };
Michael Forster6a184ad2021-10-12 13:04:05 +0000514}
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000515
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000516llvm::json::Value UnsupportedItem::ToJson() const {
517 llvm::json::Object unsupported{
518 {"name", name},
519 {"message", message},
520 {"source_loc", source_loc},
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000521 {"id", id},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000522 };
Michael Forsterf1dce422021-10-13 09:50:16 +0000523
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000524 return llvm::json::Object{
525 {"UnsupportedItem", std::move(unsupported)},
526 };
Michael Forsterf1dce422021-10-13 09:50:16 +0000527}
528
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000529llvm::json::Value Comment::ToJson() const {
530 llvm::json::Object comment{
531 {"text", text},
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000532 {"id", id},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000533 };
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700534 comment["id"] = id.value();
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000535 return llvm::json::Object{
536 {"Comment", std::move(comment)},
537 };
538}
539
Rosica Dejanovskadd9a9032022-04-12 07:34:41 -0700540llvm::json::Value Namespace::ToJson() const {
541 std::vector<llvm::json::Value> json_item_ids;
542 json_item_ids.reserve(child_item_ids.size());
543 for (const auto& id : child_item_ids) {
544 json_item_ids.push_back(id.value());
545 }
546
547 llvm::json::Object ns{
548 {"name", name},
549 {"id", id},
Rosica Dejanovska6efd17f2022-05-11 08:09:57 -0700550 {"canonical_namespace_id", canonical_namespace_id},
Rosica Dejanovskadd9a9032022-04-12 07:34:41 -0700551 {"owning_target", owning_target},
552 {"child_item_ids", std::move(json_item_ids)},
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700553 {"enclosing_namespace_id", enclosing_namespace_id},
Devin Jeanpierrefe6aaea2022-09-09 12:33:50 -0700554 {"is_inline", is_inline},
Rosica Dejanovskadd9a9032022-04-12 07:34:41 -0700555 };
556
557 return llvm::json::Object{
558 {"Namespace", std::move(ns)},
559 };
560}
561
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000562llvm::json::Value IR::ToJson() const {
563 std::vector<llvm::json::Value> json_items;
Michael Forster7ef80732021-10-01 18:12:19 +0000564 json_items.reserve(items.size());
565 for (const auto& item : items) {
566 std::visit([&](auto&& item) { json_items.push_back(item.ToJson()); }, item);
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000567 }
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -0700568 CHECK_EQ(json_items.size(), items.size());
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000569
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700570 std::vector<llvm::json::Value> top_level_ids;
571 top_level_ids.reserve(top_level_item_ids.size());
572 for (const auto& id : top_level_item_ids) {
573 top_level_ids.push_back(id.value());
574 }
575
Devin Jeanpierre6ed0f602023-03-01 17:22:54 -0800576 llvm::json::Object features_json;
577 for (const auto& [target, features] : crubit_features) {
578 std::vector<llvm::json::Value> feature_array;
579 for (const std::string& feature : features) {
580 feature_array.push_back(feature);
581 }
582 features_json[target.value()] = std::move(feature_array);
583 }
584
Marcel Hlopkob4d5d8e2022-11-16 03:15:00 -0800585 llvm::json::Object result{
Lukasz Anforowicz121338a2022-11-01 14:28:32 -0700586 {"public_headers", public_headers},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000587 {"current_target", current_target},
588 {"items", std::move(json_items)},
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700589 {"top_level_item_ids", std::move(top_level_ids)},
Devin Jeanpierre6ed0f602023-03-01 17:22:54 -0800590 {"crubit_features", std::move(features_json)},
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000591 };
Devin Jeanpierre97047892023-01-11 01:54:53 -0800592 if (!crate_root_path.empty()) {
593 result["crate_root_path"] = crate_root_path;
Marcel Hlopkob4d5d8e2022-11-16 03:15:00 -0800594 }
595 return std::move(result);
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000596}
597
Devin Jeanpierre1bcd7262022-10-04 20:07:59 -0700598std::string ItemToString(const IR::Item& item) {
599 return std::visit(
600 [&](auto&& item) { return llvm::formatv("{0}", item.ToJson()); }, item);
601}
602
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -0700603} // namespace crubit