blob: 49b9db9512092d84049eb5825358edabfe0b73f3 [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
Lukasz Anforowicz71716b72022-01-26 17:05:05 +0000258 // TODO(lukasza): Consider extracting a separate ConstructorMetadata struct to
259 // account for the fact that 1) `is_explicit_ctor` applies only to
260 // constructors and 2) `is_const` and `is_virtual` never applies to
261 // constructors.
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000262 struct InstanceMethodMetadata {
263 ReferenceQualification reference = kUnqualified;
264 bool is_const = false;
265 bool is_virtual = false;
Lukasz Anforowicz71716b72022-01-26 17:05:05 +0000266
267 // If the member function was a constructor with an `explicit` specifier.
268 bool is_explicit_ctor = false;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000269 };
270
271 nlohmann::json ToJson() const;
272
273 // The type that this is a member function for.
Devin Jeanpierre7e9a1de2021-12-03 08:04:22 +0000274 DeclId record_id;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000275
276 // Qualifiers for the instance method.
277 //
278 // If null, this is a static method.
279 std::optional<InstanceMethodMetadata> instance_method_metadata;
280};
281
Googler95f29a12022-01-07 07:47:26 +0000282// Source code location
283struct SourceLoc {
284 nlohmann::json ToJson() const;
285
286 std::string filename;
287 uint64 line;
288 uint64 column;
289};
290
291inline std::ostream& operator<<(std::ostream& o, const SourceLoc& r) {
292 return o << std::setw(internal::kJsonIndent) << r.ToJson();
293}
294
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000295// A function involved in the bindings.
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000296struct Func {
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000297 nlohmann::json ToJson() const;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000298
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000299 UnqualifiedIdentifier name;
Googlere05154d2022-01-10 08:39:03 +0000300 BlazeLabel owning_target;
Michael Forster409d9412021-10-07 08:35:29 +0000301 std::optional<std::string> doc_comment;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000302 std::string mangled_name;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000303 MappedType return_type;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000304 std::vector<FuncParam> params;
Googler64e4edb2021-12-03 12:17:38 +0000305 std::vector<Lifetime> lifetime_params;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000306 bool is_inline;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000307 // If null, this is not a member function.
308 std::optional<MemberFuncMetadata> member_func_metadata;
Googler95f29a12022-01-07 07:47:26 +0000309 SourceLoc source_loc;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000310};
311
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000312inline std::ostream& operator<<(std::ostream& o, const Func& f) {
Googler56183012021-12-01 11:07:05 +0000313 return o << std::setw(internal::kJsonIndent) << f.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000314}
315
Googler2e85f342021-09-17 07:04:07 +0000316// Access specifier for a member or base class.
317enum AccessSpecifier {
318 kPublic,
319 kProtected,
320 kPrivate,
321};
322
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000323std::ostream& operator<<(std::ostream& o, const AccessSpecifier& access);
324
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000325// A field (non-static member variable) of a record.
Michael Forster6e95ad32021-09-15 21:01:21 +0000326struct Field {
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000327 nlohmann::json ToJson() const;
328
Michael Forster6e95ad32021-09-15 21:01:21 +0000329 Identifier identifier;
Michael Forstercc5941a2021-10-07 07:12:24 +0000330 std::optional<std::string> doc_comment;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000331 MappedType type;
Googler2e85f342021-09-17 07:04:07 +0000332 AccessSpecifier access;
Googler6986c072021-09-17 13:54:56 +0000333 // Field offset in bits.
334 uint64_t offset;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000335};
336
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000337inline std::ostream& operator<<(std::ostream& o, const Field& f) {
Googler56183012021-12-01 11:07:05 +0000338 return o << std::setw(internal::kJsonIndent) << f.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000339}
340
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000341// Information about special member functions.
342//
343// Nontrivial definitions are divided into two: there are nontrivial definitions
344// which are nontrivial only due to a member variable which defines the special
345// member function, and those which are nontrivial because the operation was
346// user defined for the object itself, or for any base class.
347//
Devin Jeanpierrecd0ba852021-10-21 12:55:47 +0000348// This allows us to sidestep calling C++ implementations of special member
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000349// functions in narrow cases: even for a nontrivial special member function, if
350// it is kNontrivialMembers, we can directly implement it in Rust in terms of
351// the member variables.
Devin Jeanpierre07931272021-10-05 11:40:13 +0000352struct SpecialMemberFunc {
353 enum class Definition : char {
354 kTrivial,
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000355 // Nontrivial, but only because of a member variable with a nontrivial
356 // special member function.
357 kNontrivialMembers,
358 // Nontrivial because of a user-defined special member function in this or a
359 // base class. (May *also* be nontrivial due to member variables.)
Devin Jeanpierre7b62e952021-12-08 21:43:30 +0000360 kNontrivialUserDefined,
Devin Jeanpierre07931272021-10-05 11:40:13 +0000361 kDeleted,
362 };
363
364 nlohmann::json ToJson() const;
365
366 Definition definition = Definition::kTrivial;
367 AccessSpecifier access = AccessSpecifier::kPublic;
368};
369
370std::ostream& operator<<(std::ostream& o,
371 const SpecialMemberFunc::Definition& definition);
372
373inline std::ostream& operator<<(std::ostream& o, const SpecialMemberFunc& f) {
Googler56183012021-12-01 11:07:05 +0000374 return o << std::setw(internal::kJsonIndent) << f.ToJson();
Devin Jeanpierre07931272021-10-05 11:40:13 +0000375}
376
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000377// A record (struct, class, union).
Googler949b7d92021-09-17 07:46:11 +0000378struct Record {
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000379 nlohmann::json ToJson() const;
380
Googler949b7d92021-09-17 07:46:11 +0000381 Identifier identifier;
Marcel Hlopko264b9ad2021-12-02 21:06:44 +0000382 DeclId id;
Googlere05154d2022-01-10 08:39:03 +0000383 BlazeLabel owning_target;
Michael Forster028800b2021-10-05 12:39:59 +0000384 std::optional<std::string> doc_comment;
Googler949b7d92021-09-17 07:46:11 +0000385 std::vector<Field> fields;
Googler64e4edb2021-12-03 12:17:38 +0000386 std::vector<Lifetime> lifetime_params;
Googler6986c072021-09-17 13:54:56 +0000387 // Size and alignment in bytes.
388 int64_t size;
389 int64_t alignment;
Devin Jeanpierreb2cd0212021-10-01 07:16:23 +0000390
Devin Jeanpierrec80e6242022-02-03 01:56:40 +0000391 // The size of the base class subobjects, or null if there are none.
392 //
393 // More information: docs/struct_layout
394 std::optional<size_t> base_size = std::nullopt;
395
396 // True if the alignment may differ from what the fields would imply.
397 //
398 // For example, a base class or [[no_unique_address]] of alignment 8 should
399 // cause the record to have alignment at least 8. Since the field cannot be
400 // aligned due to layout issues, the parent struct must instead receive an
401 // alignment adjustment as necessary, via .override_alignment=true.
402 //
403 // TODO(b/216726709): use this for [[no_unique_address]].
404 //
405 // More information: docs/struct_layout
406 bool override_alignment = false;
407
Devin Jeanpierre07931272021-10-05 11:40:13 +0000408 // Special member functions.
409 SpecialMemberFunc copy_constructor = {};
410 SpecialMemberFunc move_constructor = {};
Devin Jeanpierree78b2fb2021-10-05 11:40:33 +0000411 SpecialMemberFunc destructor = {};
Devin Jeanpierre07931272021-10-05 11:40:13 +0000412
Devin Jeanpierreb2cd0212021-10-01 07:16:23 +0000413 // Whether this type is passed by value as if it were a trivial type (the same
414 // as it would be if it were a struct in C).
415 //
416 // This can be either due to language rules (it *is* a trivial type), or due
417 // to the usage of a Clang attribute that forces trivial for calls:
418 //
419 // * https://eel.is/c++draft/class.temporary#3
420 // * https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
421 bool is_trivial_abi = false;
Devin Jeanpierree6e16652021-12-22 15:54:46 +0000422
423 // Whether this type is effectively `final`, and cannot be inherited from.
424 //
425 // This can happen because it was explicitly marked final, or because a core
426 // function like the destructor was marked final.
427 bool is_final = false;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000428};
429
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000430inline std::ostream& operator<<(std::ostream& o, const Record& r) {
Googler56183012021-12-01 11:07:05 +0000431 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000432}
433
Googler098c4582022-01-10 12:29:34 +0000434// A type alias (defined either using `typedef` or `using`).
435struct TypeAlias {
436 nlohmann::json ToJson() const;
437
438 Identifier identifier;
439 DeclId id;
440 BlazeLabel owning_target;
441 MappedType underlying_type;
442};
443
444inline std::ostream& operator<<(std::ostream& o, const TypeAlias& t) {
445 return o << std::setw(internal::kJsonIndent) << t.ToJson();
446}
447
Michael Forster523dbd42021-10-12 11:05:44 +0000448// A placeholder for an item that we can't generate bindings for (yet)
449struct UnsupportedItem {
450 nlohmann::json ToJson() const;
451
452 // TODO(forster): We could show the original declaration in the generated
453 // message (potentially also for successfully imported items).
454
455 // Qualified name of the item for which we couldn't generate bindings
456 std::string name;
457
458 // Explanation of why we couldn't generate bindings
459 // TODO(forster): We should support multiple reasons per unsupported item.
460 std::string message;
Michael Forster6a184ad2021-10-12 13:04:05 +0000461 SourceLoc source_loc;
Michael Forster523dbd42021-10-12 11:05:44 +0000462};
463
464inline std::ostream& operator<<(std::ostream& o, const UnsupportedItem& r) {
Googler56183012021-12-01 11:07:05 +0000465 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Michael Forster523dbd42021-10-12 11:05:44 +0000466}
467
Michael Forsterf1dce422021-10-13 09:50:16 +0000468struct Comment {
469 nlohmann::json ToJson() const;
470
471 std::string text;
472};
473
474inline std::ostream& operator<<(std::ostream& o, const Comment& r) {
Googler56183012021-12-01 11:07:05 +0000475 return o << std::setw(internal::kJsonIndent) << r.ToJson();
Michael Forsterf1dce422021-10-13 09:50:16 +0000476}
477
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000478// A complete intermediate representation of bindings for publicly accessible
479// declarations of a single C++ library.
Devin Jeanpierre0d5d0d42021-09-16 10:37:21 +0000480struct IR {
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000481 nlohmann::json ToJson() const;
482
Michael Forster523dbd42021-10-12 11:05:44 +0000483 template <typename T>
Googler1661eee2021-12-01 12:36:19 +0000484 std::vector<const T*> get_items_if() const {
485 std::vector<const T*> filtered_items;
486 for (const auto& item : items) {
Michael Forster523dbd42021-10-12 11:05:44 +0000487 if (auto* filtered_item = std::get_if<T>(&item)) {
488 filtered_items.push_back(filtered_item);
489 }
490 }
491 return filtered_items;
492 }
493
Marcel Hlopkof1123c82021-08-19 11:38:52 +0000494 // Collection of public headers that were used to construct the AST this `IR`
495 // is generated from.
Devin Jeanpierre0d5d0d42021-09-16 10:37:21 +0000496 std::vector<HeaderName> used_headers;
Googlere05154d2022-01-10 08:39:03 +0000497 BlazeLabel current_target;
Michael Forster365bba12022-01-24 16:56:06 +0000498
499 using Item = std::variant<Func, Record, TypeAlias, UnsupportedItem, Comment>;
500 std::vector<Item> items;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000501};
502
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000503inline std::ostream& operator<<(std::ostream& o, const IR& ir) {
Googler56183012021-12-01 11:07:05 +0000504 return o << std::setw(internal::kJsonIndent) << ir.ToJson();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000505}
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000506} // namespace rs_bindings_from_cc
507
508#endif // CRUBIT_RS_BINDINGS_FROM_CC_IR_H_