blob: 943e746e91a705d6638823ddde675d01b71087c0 [file] [log] [blame]
Marcel Hlopkobfd8d322021-08-02 12:28:52 +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// This file defines an intermediate representation (IR) used between Clang AST
6// and code generators that generate Rust bindings and C++ bindings
7// implementation.
8//
9// All types in this file own their data. This IR is expected to outlive the
10// Clang's AST context, therefore it cannot reference data owned by it.
11#ifndef CRUBIT_RS_BINDINGS_FROM_CC_IR_H_
12#define CRUBIT_RS_BINDINGS_FROM_CC_IR_H_
13
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000014#include <stdint.h>
15
Googler56183012021-12-01 11:07:05 +000016#include <iomanip>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000017#include <optional>
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000018#include <string>
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000019#include <utility>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000020#include <variant>
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000021#include <vector>
22
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000023#include "base/integral_types.h"
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000024#include "base/logging.h"
Marcel Hlopko80441c12021-11-12 10:43:18 +000025#include "rs_bindings_from_cc/bazel_types.h"
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000026#include "third_party/absl/strings/string_view.h"
Marcel Hlopko42abfc82021-08-09 07:03:17 +000027#include "third_party/json/src/json.hpp"
Marcel Hlopko9c150da2021-11-12 10:30:03 +000028#include "util/intops/strong_int.h"
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000029
30namespace rs_bindings_from_cc {
31
Devin Jeanpierre5c87a722021-09-16 10:35:58 +000032namespace internal {
33inline constexpr absl::string_view kRustPtrMut = "*mut";
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +000034inline constexpr absl::string_view kRustPtrConst = "*const";
Googler4e1bc132021-12-06 10:10:42 +000035inline constexpr absl::string_view kRustRefMut = "&mut";
36inline constexpr absl::string_view kRustRefConst = "&";
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +000037inline constexpr absl::string_view kCcPtr = "*";
Googler61dce3b2021-12-02 09:16:32 +000038inline constexpr absl::string_view kCcLValueRef = "&";
Googler56183012021-12-01 11:07:05 +000039inline constexpr int kJsonIndent = 2;
Devin Jeanpierre5c87a722021-09-16 10:35:58 +000040} // namespace internal
41
Marcel Hlopkof1123c82021-08-19 11:38:52 +000042// A name of a public header of the C++ library.
43class HeaderName {
44 public:
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000045 explicit HeaderName(std::string name) : name_(std::move(name)) {}
Marcel Hlopkof1123c82021-08-19 11:38:52 +000046
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000047 absl::string_view IncludePath() const { return name_; }
Marcel Hlopkof1123c82021-08-19 11:38:52 +000048
49 nlohmann::json ToJson() const;
50
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000051 template <typename H>
52 friend H AbslHashValue(H h, const HeaderName& header_name) {
53 return H::combine(std::move(h), header_name.name_);
54 }
55
Marcel Hlopkof1123c82021-08-19 11:38:52 +000056 private:
57 // Header pathname in the format suitable for a google3-relative quote
58 // include.
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000059 std::string name_;
Marcel Hlopkof1123c82021-08-19 11:38:52 +000060};
61
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000062inline bool operator==(const HeaderName& lhs, const HeaderName& rhs) {
63 return lhs.IncludePath() == rhs.IncludePath();
64}
65
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +000066inline std::ostream& operator<<(std::ostream& o, const HeaderName& h) {
Googler56183012021-12-01 11:07:05 +000067 return o << std::setw(internal::kJsonIndent) << h.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +000068}
69
Marcel Hlopko9c150da2021-11-12 10:30:03 +000070// An int uniquely representing a Decl. Since our IR goes through the JSON
71// serialization/deserialization at the moment, we need a way to restore graph
72// edges that don't follow the JSON tree structure (for example between types
73// and records). We use DeclIds for this.
74DEFINE_STRONG_INT_TYPE(DeclId, uintptr_t);
75
Googler64e4edb2021-12-03 12:17:38 +000076// A numerical ID that uniquely identifies a lifetime.
77DEFINE_STRONG_INT_TYPE(LifetimeId, int);
78
79// A lifetime.
80struct Lifetime {
81 nlohmann::json ToJson() const;
82
83 // Lifetime name. Unlike syn::Lifetime, this does not include the apostrophe.
84 //
85 // Note that this is not an identifier; the rules for what is a valid lifetime
86 // name are slightly different than for identifiers, so we simply use a
87 // std::string instead of an Identifier here.
88 std::string name;
89
90 LifetimeId id;
91};
92
93inline std::ostream& operator<<(std::ostream& o, const Lifetime& l) {
94 return o << std::setw(internal::kJsonIndent) << l.ToJson();
95}
96
Devin Jeanpierre09c6f452021-09-29 07:34:24 +000097// A C++ type involved in the bindings. It has the knowledge of how the type
98// is spelled in C++.
99struct CcType {
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000100 nlohmann::json ToJson() const;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000101 // The name of the type. For example, int or void.
102 std::string name;
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +0000103
Marcel Hlopko9c150da2021-11-12 10:30:03 +0000104 // Id of a decl that this type corresponds to. `nullopt` for primitive types.
105 std::optional<DeclId> decl_id = std::nullopt;
106
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +0000107 // The C++ const-qualification for the type.
108 //
Devin Jeanpierrec6c62eb2021-09-29 07:13:35 +0000109 // Note: there are two types for which cv-qualification does not do anything:
110 // references and functions. if `T` is either a function type like `void()`,
111 // or a reference type like `int&`, then `T`, `const T`, and `volatile T` are
112 // all the same type in C++.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000113 bool is_const = false;
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +0000114
Googlerff7fc232021-12-02 09:43:00 +0000115 // Type arguments for a generic type. Examples:
116 // int has no type arguments.
117 // int* has a single type argument, int.
118 // tuple<int, float> has two type arguments, int and float.
119 std::vector<CcType> type_args = {};
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000120};
121
122// A Rust type involved in the bindings. It has the knowledge of how the type
123// is spelled in Rust.
124struct RsType {
125 nlohmann::json ToJson() const;
126
127 // The name of the type. For example, i32 or ().
128 std::string name;
129
Marcel Hlopko9c150da2021-11-12 10:30:03 +0000130 // Id of a decl that this type corresponds to. `nullopt` for primitive types.
131 std::optional<DeclId> decl_id = std::nullopt;
132
Googler64e4edb2021-12-03 12:17:38 +0000133 // Lifetime arguments for a generic type. Examples:
134 // *mut i32 has no lifetime arguments
135 // &'a 32 has a single lifetime argument, 'a.
136 // SomeType<'a, 'b> has two lifetime arguments, 'a and 'b.
137 // Lifetimes are identified by their unique ID. The corresponding Lifetime
138 // will be found within the lifetime_params of a Func or Record that uses
139 // this type.
140 std::vector<LifetimeId> lifetime_args = {};
141
Googlerff7fc232021-12-02 09:43:00 +0000142 // Type arguments for a generic type. Examples:
143 // i32 has no type arguments.
144 // *mut i32 has a single type argument, i32.
145 // (i32, f32) has two type arguments, i32 and f32.
146 std::vector<RsType> type_args = {};
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000147};
148
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000149inline std::ostream& operator<<(std::ostream& o, const RsType& type) {
Googler56183012021-12-01 11:07:05 +0000150 return o << std::setw(internal::kJsonIndent) << type.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000151}
152
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000153// A type involved in the bindings. The rs_type and cc_type will be treated
154// as interchangeable during bindings, and so should share the same layout.
155//
156// For example: a C++ pointer may be a usize in Rust, rather than a pointer, but
157// should almost certainly not be a u8, because u8 and pointers are sized and
158// aligned differently.
159struct MappedType {
160 static MappedType Void() { return Simple("()", "void"); }
161
162 /// Returns the MappedType for a non-templated/generic, non-cv-qualified type.
163 /// For example, Void() is Simple("()", "void").
164 static MappedType Simple(std::string rs_name, std::string cc_name) {
165 return MappedType{RsType{rs_name}, CcType{cc_name}};
166 }
167
Marcel Hlopko9c150da2021-11-12 10:30:03 +0000168 static MappedType WithDeclIds(std::string rs_name, DeclId rs_decl_id,
169 std::string cc_name, DeclId cc_decl_id) {
170 return MappedType{RsType{std::move(rs_name), rs_decl_id},
171 CcType{std::move(cc_name), cc_decl_id}};
172 }
173
Googler4e1bc132021-12-06 10:10:42 +0000174 static MappedType PointerTo(MappedType pointee_type,
175 std::optional<LifetimeId> lifetime,
Googler02da3fb2021-12-06 11:59:19 +0000176 bool nullable = true);
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000177
Googler4e1bc132021-12-06 10:10:42 +0000178 static MappedType LValueReferenceTo(MappedType pointee_type,
Googler02da3fb2021-12-06 11:59:19 +0000179 std::optional<LifetimeId> lifetime);
Googler61dce3b2021-12-02 09:16:32 +0000180
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000181 bool IsVoid() const { return rs_type.name == "()"; }
182
183 nlohmann::json ToJson() const;
184
185 RsType rs_type;
186 CcType cc_type;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000187};
188
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000189inline std::ostream& operator<<(std::ostream& o, const MappedType& type) {
Googler56183012021-12-01 11:07:05 +0000190 return o << std::setw(internal::kJsonIndent) << type.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000191}
192
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000193// An identifier involved in bindings.
194//
195// Examples:
196// Identifier of C++'s `int32_t Add(int32_t a, int32_t b)` will be
197// `Identifier("add")`.
198//
199// Invariants:
200// `identifier` cannot be empty.
201class Identifier {
202 public:
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +0000203 explicit Identifier(std::string identifier)
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000204 : identifier_(std::move(identifier)) {
205 CHECK(!identifier_.empty()) << "Identifier name cannot be empty.";
206 }
207
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +0000208 absl::string_view Ident() const { return identifier_; }
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000209
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000210 nlohmann::json ToJson() const;
211
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000212 private:
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +0000213 std::string identifier_;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000214};
215
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000216inline std::ostream& operator<<(std::ostream& o, const Identifier& id) {
Googler56183012021-12-01 11:07:05 +0000217 return o << std::setw(internal::kJsonIndent) << id.Ident();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000218}
219
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000220// A function parameter.
221//
222// Examples:
223// FuncParam of a C++ function `void Foo(int32_t a);` will be
Devin Jeanpierre29a25f12021-09-15 11:54:32 +0000224// `FuncParam{.type=Type{"i32", "int32_t"}, .identifier=Identifier("foo"))`.
Devin Jeanpierre601f14f2021-09-15 11:53:18 +0000225struct FuncParam {
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000226 nlohmann::json ToJson() const;
227
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000228 MappedType type;
Devin Jeanpierre601f14f2021-09-15 11:53:18 +0000229 Identifier identifier;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000230};
231
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000232inline std::ostream& operator<<(std::ostream& o, const FuncParam& param) {
Googler56183012021-12-01 11:07:05 +0000233 return o << std::setw(internal::kJsonIndent) << param.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000234}
235
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000236enum SpecialName {
237 kDestructor,
238 kConstructor,
239};
240
241std::ostream& operator<<(std::ostream& o, const SpecialName& special_name);
242
243// A generalized notion of identifier, or an "Unqualified Identifier" in C++
244// jargon: https://en.cppreference.com/w/cpp/language/identifiers
245//
246// Note that constructors are given a separate variant, so that we can treat
247// them differently. After all, they are not invoked or defined like normal
248// functions.
249using UnqualifiedIdentifier = std::variant<Identifier, SpecialName>;
250
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000251struct MemberFuncMetadata {
252 enum ReferenceQualification : char {
253 kLValue, // void Foo() &;
254 kRValue, // void Foo() &&;
255 kUnqualified, // void Foo();
256 };
257
258 struct InstanceMethodMetadata {
259 ReferenceQualification reference = kUnqualified;
260 bool is_const = false;
261 bool is_virtual = false;
262 };
263
264 nlohmann::json ToJson() const;
265
266 // The type that this is a member function for.
Devin Jeanpierre7e9a1de2021-12-03 08:04:22 +0000267 DeclId record_id;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000268
269 // Qualifiers for the instance method.
270 //
271 // If null, this is a static method.
272 std::optional<InstanceMethodMetadata> instance_method_metadata;
273};
274
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000275// A function involved in the bindings.
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000276struct Func {
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000277 nlohmann::json ToJson() const;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000278
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000279 UnqualifiedIdentifier name;
Marcel Hlopko80441c12021-11-12 10:43:18 +0000280 Label owning_target;
Michael Forster409d9412021-10-07 08:35:29 +0000281 std::optional<std::string> doc_comment;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000282 std::string mangled_name;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000283 MappedType return_type;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000284 std::vector<FuncParam> params;
Googler64e4edb2021-12-03 12:17:38 +0000285 std::vector<Lifetime> lifetime_params;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000286 bool is_inline;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000287 // If null, this is not a member function.
288 std::optional<MemberFuncMetadata> member_func_metadata;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000289};
290
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000291inline std::ostream& operator<<(std::ostream& o, const Func& f) {
Googler56183012021-12-01 11:07:05 +0000292 return o << std::setw(internal::kJsonIndent) << f.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000293}
294
Googler2e85f342021-09-17 07:04:07 +0000295// Access specifier for a member or base class.
296enum AccessSpecifier {
297 kPublic,
298 kProtected,
299 kPrivate,
300};
301
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000302std::ostream& operator<<(std::ostream& o, const AccessSpecifier& access);
303
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000304// A field (non-static member variable) of a record.
Michael Forster6e95ad32021-09-15 21:01:21 +0000305struct Field {
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000306 nlohmann::json ToJson() const;
307
Michael Forster6e95ad32021-09-15 21:01:21 +0000308 Identifier identifier;
Michael Forstercc5941a2021-10-07 07:12:24 +0000309 std::optional<std::string> doc_comment;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000310 MappedType type;
Googler2e85f342021-09-17 07:04:07 +0000311 AccessSpecifier access;
Googler6986c072021-09-17 13:54:56 +0000312 // Field offset in bits.
313 uint64_t offset;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000314};
315
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000316inline std::ostream& operator<<(std::ostream& o, const Field& f) {
Googler56183012021-12-01 11:07:05 +0000317 return o << std::setw(internal::kJsonIndent) << f.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000318}
319
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000320// Information about special member functions.
321//
322// Nontrivial definitions are divided into two: there are nontrivial definitions
323// which are nontrivial only due to a member variable which defines the special
324// member function, and those which are nontrivial because the operation was
325// user defined for the object itself, or for any base class.
326//
Devin Jeanpierrecd0ba852021-10-21 12:55:47 +0000327// This allows us to sidestep calling C++ implementations of special member
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000328// functions in narrow cases: even for a nontrivial special member function, if
329// it is kNontrivialMembers, we can directly implement it in Rust in terms of
330// the member variables.
Devin Jeanpierre07931272021-10-05 11:40:13 +0000331struct SpecialMemberFunc {
332 enum class Definition : char {
333 kTrivial,
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000334 // Nontrivial, but only because of a member variable with a nontrivial
335 // special member function.
336 kNontrivialMembers,
337 // Nontrivial because of a user-defined special member function in this or a
338 // base class. (May *also* be nontrivial due to member variables.)
339 kNontrivialSelf,
Devin Jeanpierre07931272021-10-05 11:40:13 +0000340 kDeleted,
341 };
342
343 nlohmann::json ToJson() const;
344
345 Definition definition = Definition::kTrivial;
346 AccessSpecifier access = AccessSpecifier::kPublic;
347};
348
349std::ostream& operator<<(std::ostream& o,
350 const SpecialMemberFunc::Definition& definition);
351
352inline std::ostream& operator<<(std::ostream& o, const SpecialMemberFunc& f) {
Googler56183012021-12-01 11:07:05 +0000353 return o << std::setw(internal::kJsonIndent) << f.ToJson();
Devin Jeanpierre07931272021-10-05 11:40:13 +0000354}
355
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000356// A record (struct, class, union).
Googler949b7d92021-09-17 07:46:11 +0000357struct Record {
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000358 nlohmann::json ToJson() const;
359
Googler949b7d92021-09-17 07:46:11 +0000360 Identifier identifier;
Marcel Hlopko264b9ad2021-12-02 21:06:44 +0000361 DeclId id;
Marcel Hlopko80441c12021-11-12 10:43:18 +0000362 Label owning_target;
Michael Forster028800b2021-10-05 12:39:59 +0000363 std::optional<std::string> doc_comment;
Googler949b7d92021-09-17 07:46:11 +0000364 std::vector<Field> fields;
Googler64e4edb2021-12-03 12:17:38 +0000365 std::vector<Lifetime> lifetime_params;
Googler6986c072021-09-17 13:54:56 +0000366 // Size and alignment in bytes.
367 int64_t size;
368 int64_t alignment;
Devin Jeanpierreb2cd0212021-10-01 07:16:23 +0000369
Devin Jeanpierre07931272021-10-05 11:40:13 +0000370 // Special member functions.
371 SpecialMemberFunc copy_constructor = {};
372 SpecialMemberFunc move_constructor = {};
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000373 SpecialMemberFunc destructor = {};
Devin Jeanpierre07931272021-10-05 11:40:13 +0000374
Devin Jeanpierreb2cd0212021-10-01 07:16:23 +0000375 // Whether this type is passed by value as if it were a trivial type (the same
376 // as it would be if it were a struct in C).
377 //
378 // This can be either due to language rules (it *is* a trivial type), or due
379 // to the usage of a Clang attribute that forces trivial for calls:
380 //
381 // * https://eel.is/c++draft/class.temporary#3
382 // * https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
383 bool is_trivial_abi = false;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000384};
385
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000386inline std::ostream& operator<<(std::ostream& o, const Record& r) {
Googler56183012021-12-01 11:07:05 +0000387 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000388}
389
Michael Forster6a184ad2021-10-12 13:04:05 +0000390// Source code location
391struct SourceLoc {
392 nlohmann::json ToJson() const;
393
394 std::string filename;
395 uint64 line;
396 uint64 column;
397};
398
399inline std::ostream& operator<<(std::ostream& o, const SourceLoc& r) {
Googler56183012021-12-01 11:07:05 +0000400 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Michael Forster6a184ad2021-10-12 13:04:05 +0000401}
402
Michael Forster523dbd42021-10-12 11:05:44 +0000403// A placeholder for an item that we can't generate bindings for (yet)
404struct UnsupportedItem {
405 nlohmann::json ToJson() const;
406
407 // TODO(forster): We could show the original declaration in the generated
408 // message (potentially also for successfully imported items).
409
410 // Qualified name of the item for which we couldn't generate bindings
411 std::string name;
412
413 // Explanation of why we couldn't generate bindings
414 // TODO(forster): We should support multiple reasons per unsupported item.
415 std::string message;
Michael Forster6a184ad2021-10-12 13:04:05 +0000416 SourceLoc source_loc;
Michael Forster523dbd42021-10-12 11:05:44 +0000417};
418
419inline std::ostream& operator<<(std::ostream& o, const UnsupportedItem& r) {
Googler56183012021-12-01 11:07:05 +0000420 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Michael Forster523dbd42021-10-12 11:05:44 +0000421}
422
Michael Forsterf1dce422021-10-13 09:50:16 +0000423struct Comment {
424 nlohmann::json ToJson() const;
425
426 std::string text;
427};
428
429inline std::ostream& operator<<(std::ostream& o, const Comment& r) {
Googler56183012021-12-01 11:07:05 +0000430 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Michael Forsterf1dce422021-10-13 09:50:16 +0000431}
432
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000433// A complete intermediate representation of bindings for publicly accessible
434// declarations of a single C++ library.
Devin Jeanpierre0d5d0d42021-09-16 10:37:21 +0000435struct IR {
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000436 nlohmann::json ToJson() const;
437
Michael Forster523dbd42021-10-12 11:05:44 +0000438 template <typename T>
Googler1661eee2021-12-01 12:36:19 +0000439 std::vector<const T*> get_items_if() const {
440 std::vector<const T*> filtered_items;
441 for (const auto& item : items) {
Michael Forster523dbd42021-10-12 11:05:44 +0000442 if (auto* filtered_item = std::get_if<T>(&item)) {
443 filtered_items.push_back(filtered_item);
444 }
445 }
446 return filtered_items;
447 }
448
Marcel Hlopkof1123c82021-08-19 11:38:52 +0000449 // Collection of public headers that were used to construct the AST this `IR`
450 // is generated from.
Devin Jeanpierre0d5d0d42021-09-16 10:37:21 +0000451 std::vector<HeaderName> used_headers;
Marcel Hlopko80441c12021-11-12 10:43:18 +0000452 Label current_target;
Michael Forsterf1dce422021-10-13 09:50:16 +0000453 std::vector<std::variant<Func, Record, UnsupportedItem, Comment>> items;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000454};
455
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000456inline std::ostream& operator<<(std::ostream& o, const IR& ir) {
Googler56183012021-12-01 11:07:05 +0000457 return o << std::setw(internal::kJsonIndent) << ir.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000458}
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000459} // namespace rs_bindings_from_cc
460
461#endif // CRUBIT_RS_BINDINGS_FROM_CC_IR_H_