Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 1 | // 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 Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 14 | #include <stdint.h> |
| 15 | |
| 16 | #include <optional> |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 17 | #include <string> |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 18 | #include <utility> |
Marcel Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 19 | #include <variant> |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 20 | #include <vector> |
| 21 | |
Marcel Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 22 | #include "base/integral_types.h" |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 23 | #include "base/logging.h" |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 24 | #include "third_party/absl/strings/string_view.h" |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 25 | #include "third_party/json/src/json.hpp" |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 26 | #include "util/intops/strong_int.h" |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 27 | |
| 28 | namespace rs_bindings_from_cc { |
| 29 | |
Devin Jeanpierre | 5c87a72 | 2021-09-16 10:35:58 +0000 | [diff] [blame] | 30 | namespace internal { |
| 31 | inline constexpr absl::string_view kRustPtrMut = "*mut"; |
Devin Jeanpierre | 184f9ac | 2021-09-17 13:47:03 +0000 | [diff] [blame] | 32 | inline constexpr absl::string_view kRustPtrConst = "*const"; |
| 33 | inline constexpr absl::string_view kCcPtr = "*"; |
Devin Jeanpierre | 5c87a72 | 2021-09-16 10:35:58 +0000 | [diff] [blame] | 34 | } // namespace internal |
| 35 | |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 36 | // A name of a public header of the C++ library. |
| 37 | class HeaderName { |
| 38 | public: |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 39 | explicit HeaderName(std::string name) : name_(std::move(name)) {} |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 40 | |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 41 | absl::string_view IncludePath() const { return name_; } |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 42 | |
| 43 | nlohmann::json ToJson() const; |
| 44 | |
Marcel Hlopko | 7aa38a7 | 2021-11-11 07:39:51 +0000 | [diff] [blame] | 45 | template <typename H> |
| 46 | friend H AbslHashValue(H h, const HeaderName& header_name) { |
| 47 | return H::combine(std::move(h), header_name.name_); |
| 48 | } |
| 49 | |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 50 | private: |
| 51 | // Header pathname in the format suitable for a google3-relative quote |
| 52 | // include. |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 53 | std::string name_; |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 54 | }; |
| 55 | |
Marcel Hlopko | 7aa38a7 | 2021-11-11 07:39:51 +0000 | [diff] [blame] | 56 | inline bool operator==(const HeaderName& lhs, const HeaderName& rhs) { |
| 57 | return lhs.IncludePath() == rhs.IncludePath(); |
| 58 | } |
| 59 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 60 | inline std::ostream& operator<<(std::ostream& o, const HeaderName& h) { |
| 61 | return o << h.ToJson(); |
| 62 | } |
| 63 | |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 64 | // An int uniquely representing a Decl. Since our IR goes through the JSON |
| 65 | // serialization/deserialization at the moment, we need a way to restore graph |
| 66 | // edges that don't follow the JSON tree structure (for example between types |
| 67 | // and records). We use DeclIds for this. |
| 68 | DEFINE_STRONG_INT_TYPE(DeclId, uintptr_t); |
| 69 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 70 | // A C++ type involved in the bindings. It has the knowledge of how the type |
| 71 | // is spelled in C++. |
| 72 | struct CcType { |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 73 | nlohmann::json ToJson() const; |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 74 | // The name of the type. For example, int or void. |
| 75 | std::string name; |
Devin Jeanpierre | 184f9ac | 2021-09-17 13:47:03 +0000 | [diff] [blame] | 76 | |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 77 | // Id of a decl that this type corresponds to. `nullopt` for primitive types. |
| 78 | std::optional<DeclId> decl_id = std::nullopt; |
| 79 | |
Devin Jeanpierre | 184f9ac | 2021-09-17 13:47:03 +0000 | [diff] [blame] | 80 | // The C++ const-qualification for the type. |
| 81 | // |
Devin Jeanpierre | c6c62eb | 2021-09-29 07:13:35 +0000 | [diff] [blame] | 82 | // Note: there are two types for which cv-qualification does not do anything: |
| 83 | // references and functions. if `T` is either a function type like `void()`, |
| 84 | // or a reference type like `int&`, then `T`, `const T`, and `volatile T` are |
| 85 | // all the same type in C++. |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 86 | bool is_const = false; |
Devin Jeanpierre | 184f9ac | 2021-09-17 13:47:03 +0000 | [diff] [blame] | 87 | |
Devin Jeanpierre | 5c87a72 | 2021-09-16 10:35:58 +0000 | [diff] [blame] | 88 | // Type parameters for a generic type. Examples: |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 89 | // int has no type parameters. |
Devin Jeanpierre | 5c87a72 | 2021-09-16 10:35:58 +0000 | [diff] [blame] | 90 | // int* has a single type parameter, int. |
| 91 | // tuple<int, float> has two type parameters, int and float. |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 92 | std::vector<CcType> type_params = {}; |
| 93 | }; |
| 94 | |
| 95 | // A Rust type involved in the bindings. It has the knowledge of how the type |
| 96 | // is spelled in Rust. |
| 97 | struct RsType { |
| 98 | nlohmann::json ToJson() const; |
| 99 | |
| 100 | // The name of the type. For example, i32 or (). |
| 101 | std::string name; |
| 102 | |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 103 | // Id of a decl that this type corresponds to. `nullopt` for primitive types. |
| 104 | std::optional<DeclId> decl_id = std::nullopt; |
| 105 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 106 | // Type parameters for a generic type. Examples: |
| 107 | // i32 has no type parameters. |
| 108 | // *mut i32 has a single type parameter, i32. |
| 109 | // (i32, f32) has two type parameters, i32 and f32. |
| 110 | std::vector<RsType> type_params = {}; |
| 111 | }; |
| 112 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 113 | inline std::ostream& operator<<(std::ostream& o, const RsType& type) { |
| 114 | return o << type.ToJson(); |
| 115 | } |
| 116 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 117 | // A type involved in the bindings. The rs_type and cc_type will be treated |
| 118 | // as interchangeable during bindings, and so should share the same layout. |
| 119 | // |
| 120 | // For example: a C++ pointer may be a usize in Rust, rather than a pointer, but |
| 121 | // should almost certainly not be a u8, because u8 and pointers are sized and |
| 122 | // aligned differently. |
| 123 | struct MappedType { |
| 124 | static MappedType Void() { return Simple("()", "void"); } |
| 125 | |
| 126 | /// Returns the MappedType for a non-templated/generic, non-cv-qualified type. |
| 127 | /// For example, Void() is Simple("()", "void"). |
| 128 | static MappedType Simple(std::string rs_name, std::string cc_name) { |
| 129 | return MappedType{RsType{rs_name}, CcType{cc_name}}; |
| 130 | } |
| 131 | |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 132 | static MappedType WithDeclIds(std::string rs_name, DeclId rs_decl_id, |
| 133 | std::string cc_name, DeclId cc_decl_id) { |
| 134 | return MappedType{RsType{std::move(rs_name), rs_decl_id}, |
| 135 | CcType{std::move(cc_name), cc_decl_id}}; |
| 136 | } |
| 137 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 138 | static MappedType PointerTo(MappedType pointee_type) { |
| 139 | absl::string_view rs_name = pointee_type.cc_type.is_const |
| 140 | ? internal::kRustPtrConst |
| 141 | : internal::kRustPtrMut; |
| 142 | auto pointer_type = |
| 143 | Simple(std::string(rs_name), std::string(internal::kCcPtr)); |
| 144 | pointer_type.rs_type.type_params.push_back(std::move(pointee_type.rs_type)); |
| 145 | pointer_type.cc_type.type_params.push_back(std::move(pointee_type.cc_type)); |
| 146 | return pointer_type; |
| 147 | } |
| 148 | |
| 149 | bool IsVoid() const { return rs_type.name == "()"; } |
| 150 | |
| 151 | nlohmann::json ToJson() const; |
| 152 | |
| 153 | RsType rs_type; |
| 154 | CcType cc_type; |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 155 | }; |
| 156 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 157 | inline std::ostream& operator<<(std::ostream& o, const MappedType& type) { |
| 158 | return o << type.ToJson(); |
| 159 | } |
| 160 | |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 161 | // An identifier involved in bindings. |
| 162 | // |
| 163 | // Examples: |
| 164 | // Identifier of C++'s `int32_t Add(int32_t a, int32_t b)` will be |
| 165 | // `Identifier("add")`. |
| 166 | // |
| 167 | // Invariants: |
| 168 | // `identifier` cannot be empty. |
| 169 | class Identifier { |
| 170 | public: |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 171 | explicit Identifier(std::string identifier) |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 172 | : identifier_(std::move(identifier)) { |
| 173 | CHECK(!identifier_.empty()) << "Identifier name cannot be empty."; |
| 174 | } |
| 175 | |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 176 | absl::string_view Ident() const { return identifier_; } |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 177 | |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 178 | nlohmann::json ToJson() const; |
| 179 | |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 180 | private: |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 181 | std::string identifier_; |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 182 | }; |
| 183 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 184 | inline std::ostream& operator<<(std::ostream& o, const Identifier& id) { |
| 185 | return o << id.Ident(); |
| 186 | } |
| 187 | |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 188 | // A function parameter. |
| 189 | // |
| 190 | // Examples: |
| 191 | // FuncParam of a C++ function `void Foo(int32_t a);` will be |
Devin Jeanpierre | 29a25f1 | 2021-09-15 11:54:32 +0000 | [diff] [blame] | 192 | // `FuncParam{.type=Type{"i32", "int32_t"}, .identifier=Identifier("foo"))`. |
Devin Jeanpierre | 601f14f | 2021-09-15 11:53:18 +0000 | [diff] [blame] | 193 | struct FuncParam { |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 194 | nlohmann::json ToJson() const; |
| 195 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 196 | MappedType type; |
Devin Jeanpierre | 601f14f | 2021-09-15 11:53:18 +0000 | [diff] [blame] | 197 | Identifier identifier; |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 198 | }; |
| 199 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 200 | inline std::ostream& operator<<(std::ostream& o, const FuncParam& param) { |
| 201 | return o << param.ToJson(); |
| 202 | } |
| 203 | |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 204 | enum SpecialName { |
| 205 | kDestructor, |
| 206 | kConstructor, |
| 207 | }; |
| 208 | |
| 209 | std::ostream& operator<<(std::ostream& o, const SpecialName& special_name); |
| 210 | |
| 211 | // A generalized notion of identifier, or an "Unqualified Identifier" in C++ |
| 212 | // jargon: https://en.cppreference.com/w/cpp/language/identifiers |
| 213 | // |
| 214 | // Note that constructors are given a separate variant, so that we can treat |
| 215 | // them differently. After all, they are not invoked or defined like normal |
| 216 | // functions. |
| 217 | using UnqualifiedIdentifier = std::variant<Identifier, SpecialName>; |
| 218 | |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 219 | struct MemberFuncMetadata { |
| 220 | enum ReferenceQualification : char { |
| 221 | kLValue, // void Foo() &; |
| 222 | kRValue, // void Foo() &&; |
| 223 | kUnqualified, // void Foo(); |
| 224 | }; |
| 225 | |
| 226 | struct InstanceMethodMetadata { |
| 227 | ReferenceQualification reference = kUnqualified; |
| 228 | bool is_const = false; |
| 229 | bool is_virtual = false; |
| 230 | }; |
| 231 | |
| 232 | nlohmann::json ToJson() const; |
| 233 | |
| 234 | // The type that this is a member function for. |
| 235 | Identifier for_type; |
| 236 | |
| 237 | // Qualifiers for the instance method. |
| 238 | // |
| 239 | // If null, this is a static method. |
| 240 | std::optional<InstanceMethodMetadata> instance_method_metadata; |
| 241 | }; |
| 242 | |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 243 | // A function involved in the bindings. |
Devin Jeanpierre | 4d33b59 | 2021-09-15 11:53:32 +0000 | [diff] [blame] | 244 | struct Func { |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 245 | nlohmann::json ToJson() const; |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 246 | |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 247 | UnqualifiedIdentifier name; |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 248 | DeclId decl_id; |
Michael Forster | 409d941 | 2021-10-07 08:35:29 +0000 | [diff] [blame] | 249 | std::optional<std::string> doc_comment; |
Devin Jeanpierre | 4d33b59 | 2021-09-15 11:53:32 +0000 | [diff] [blame] | 250 | std::string mangled_name; |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 251 | MappedType return_type; |
Devin Jeanpierre | 4d33b59 | 2021-09-15 11:53:32 +0000 | [diff] [blame] | 252 | std::vector<FuncParam> params; |
| 253 | bool is_inline; |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 254 | // If null, this is not a member function. |
| 255 | std::optional<MemberFuncMetadata> member_func_metadata; |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 256 | }; |
| 257 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 258 | inline std::ostream& operator<<(std::ostream& o, const Func& f) { |
| 259 | return o << f.ToJson(); |
| 260 | } |
| 261 | |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 262 | // Access specifier for a member or base class. |
| 263 | enum AccessSpecifier { |
| 264 | kPublic, |
| 265 | kProtected, |
| 266 | kPrivate, |
| 267 | }; |
| 268 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 269 | std::ostream& operator<<(std::ostream& o, const AccessSpecifier& access); |
| 270 | |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 271 | // A field (non-static member variable) of a record. |
Michael Forster | 6e95ad3 | 2021-09-15 21:01:21 +0000 | [diff] [blame] | 272 | struct Field { |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 273 | nlohmann::json ToJson() const; |
| 274 | |
Michael Forster | 6e95ad3 | 2021-09-15 21:01:21 +0000 | [diff] [blame] | 275 | Identifier identifier; |
Michael Forster | cc5941a | 2021-10-07 07:12:24 +0000 | [diff] [blame] | 276 | std::optional<std::string> doc_comment; |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 277 | MappedType type; |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 278 | AccessSpecifier access; |
Googler | 6986c07 | 2021-09-17 13:54:56 +0000 | [diff] [blame] | 279 | // Field offset in bits. |
| 280 | uint64_t offset; |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 281 | }; |
| 282 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 283 | inline std::ostream& operator<<(std::ostream& o, const Field& f) { |
| 284 | return o << f.ToJson(); |
| 285 | } |
| 286 | |
Devin Jeanpierre | be2f33b | 2021-10-21 12:54:19 +0000 | [diff] [blame] | 287 | // Information about special member functions. |
| 288 | // |
| 289 | // Nontrivial definitions are divided into two: there are nontrivial definitions |
| 290 | // which are nontrivial only due to a member variable which defines the special |
| 291 | // member function, and those which are nontrivial because the operation was |
| 292 | // user defined for the object itself, or for any base class. |
| 293 | // |
Devin Jeanpierre | cd0ba85 | 2021-10-21 12:55:47 +0000 | [diff] [blame] | 294 | // This allows us to sidestep calling C++ implementations of special member |
Devin Jeanpierre | be2f33b | 2021-10-21 12:54:19 +0000 | [diff] [blame] | 295 | // functions in narrow cases: even for a nontrivial special member function, if |
| 296 | // it is kNontrivialMembers, we can directly implement it in Rust in terms of |
| 297 | // the member variables. |
Devin Jeanpierre | 0793127 | 2021-10-05 11:40:13 +0000 | [diff] [blame] | 298 | struct SpecialMemberFunc { |
| 299 | enum class Definition : char { |
| 300 | kTrivial, |
Devin Jeanpierre | be2f33b | 2021-10-21 12:54:19 +0000 | [diff] [blame] | 301 | // Nontrivial, but only because of a member variable with a nontrivial |
| 302 | // special member function. |
| 303 | kNontrivialMembers, |
| 304 | // Nontrivial because of a user-defined special member function in this or a |
| 305 | // base class. (May *also* be nontrivial due to member variables.) |
| 306 | kNontrivialSelf, |
Devin Jeanpierre | 0793127 | 2021-10-05 11:40:13 +0000 | [diff] [blame] | 307 | kDeleted, |
| 308 | }; |
| 309 | |
| 310 | nlohmann::json ToJson() const; |
| 311 | |
| 312 | Definition definition = Definition::kTrivial; |
| 313 | AccessSpecifier access = AccessSpecifier::kPublic; |
| 314 | }; |
| 315 | |
| 316 | std::ostream& operator<<(std::ostream& o, |
| 317 | const SpecialMemberFunc::Definition& definition); |
| 318 | |
| 319 | inline std::ostream& operator<<(std::ostream& o, const SpecialMemberFunc& f) { |
| 320 | return o << f.ToJson(); |
| 321 | } |
| 322 | |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 323 | // A record (struct, class, union). |
Googler | 949b7d9 | 2021-09-17 07:46:11 +0000 | [diff] [blame] | 324 | struct Record { |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 325 | nlohmann::json ToJson() const; |
| 326 | |
Googler | 949b7d9 | 2021-09-17 07:46:11 +0000 | [diff] [blame] | 327 | Identifier identifier; |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame^] | 328 | DeclId decl_id; |
Michael Forster | 028800b | 2021-10-05 12:39:59 +0000 | [diff] [blame] | 329 | std::optional<std::string> doc_comment; |
Googler | 949b7d9 | 2021-09-17 07:46:11 +0000 | [diff] [blame] | 330 | std::vector<Field> fields; |
Googler | 6986c07 | 2021-09-17 13:54:56 +0000 | [diff] [blame] | 331 | // Size and alignment in bytes. |
| 332 | int64_t size; |
| 333 | int64_t alignment; |
Devin Jeanpierre | b2cd021 | 2021-10-01 07:16:23 +0000 | [diff] [blame] | 334 | |
Devin Jeanpierre | 0793127 | 2021-10-05 11:40:13 +0000 | [diff] [blame] | 335 | // Special member functions. |
| 336 | SpecialMemberFunc copy_constructor = {}; |
| 337 | SpecialMemberFunc move_constructor = {}; |
Devin Jeanpierre | e78b2fb | 2021-10-05 11:40:33 +0000 | [diff] [blame] | 338 | SpecialMemberFunc destructor = {}; |
Devin Jeanpierre | 0793127 | 2021-10-05 11:40:13 +0000 | [diff] [blame] | 339 | |
Devin Jeanpierre | b2cd021 | 2021-10-01 07:16:23 +0000 | [diff] [blame] | 340 | // Whether this type is passed by value as if it were a trivial type (the same |
| 341 | // as it would be if it were a struct in C). |
| 342 | // |
| 343 | // This can be either due to language rules (it *is* a trivial type), or due |
| 344 | // to the usage of a Clang attribute that forces trivial for calls: |
| 345 | // |
| 346 | // * https://eel.is/c++draft/class.temporary#3 |
| 347 | // * https://clang.llvm.org/docs/AttributeReference.html#trivial-abi |
| 348 | bool is_trivial_abi = false; |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 349 | }; |
| 350 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 351 | inline std::ostream& operator<<(std::ostream& o, const Record& r) { |
| 352 | return o << r.ToJson(); |
| 353 | } |
| 354 | |
Michael Forster | 6a184ad | 2021-10-12 13:04:05 +0000 | [diff] [blame] | 355 | // Source code location |
| 356 | struct SourceLoc { |
| 357 | nlohmann::json ToJson() const; |
| 358 | |
| 359 | std::string filename; |
| 360 | uint64 line; |
| 361 | uint64 column; |
| 362 | }; |
| 363 | |
| 364 | inline std::ostream& operator<<(std::ostream& o, const SourceLoc& r) { |
| 365 | return o << r.ToJson(); |
| 366 | } |
| 367 | |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 368 | // A placeholder for an item that we can't generate bindings for (yet) |
| 369 | struct UnsupportedItem { |
| 370 | nlohmann::json ToJson() const; |
| 371 | |
| 372 | // TODO(forster): We could show the original declaration in the generated |
| 373 | // message (potentially also for successfully imported items). |
| 374 | |
| 375 | // Qualified name of the item for which we couldn't generate bindings |
| 376 | std::string name; |
| 377 | |
| 378 | // Explanation of why we couldn't generate bindings |
| 379 | // TODO(forster): We should support multiple reasons per unsupported item. |
| 380 | std::string message; |
Michael Forster | 6a184ad | 2021-10-12 13:04:05 +0000 | [diff] [blame] | 381 | SourceLoc source_loc; |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 382 | }; |
| 383 | |
| 384 | inline std::ostream& operator<<(std::ostream& o, const UnsupportedItem& r) { |
| 385 | return o << r.ToJson(); |
| 386 | } |
| 387 | |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 388 | struct Comment { |
| 389 | nlohmann::json ToJson() const; |
| 390 | |
| 391 | std::string text; |
| 392 | }; |
| 393 | |
| 394 | inline std::ostream& operator<<(std::ostream& o, const Comment& r) { |
| 395 | return o << r.ToJson(); |
| 396 | } |
| 397 | |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 398 | // A complete intermediate representation of bindings for publicly accessible |
| 399 | // declarations of a single C++ library. |
Devin Jeanpierre | 0d5d0d4 | 2021-09-16 10:37:21 +0000 | [diff] [blame] | 400 | struct IR { |
Marcel Hlopko | 42abfc8 | 2021-08-09 07:03:17 +0000 | [diff] [blame] | 401 | nlohmann::json ToJson() const; |
| 402 | |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 403 | template <typename T> |
| 404 | std::vector<T*> get_items_if() { |
| 405 | std::vector<T*> filtered_items; |
| 406 | for (auto& item : items) { |
| 407 | if (auto* filtered_item = std::get_if<T>(&item)) { |
| 408 | filtered_items.push_back(filtered_item); |
| 409 | } |
| 410 | } |
| 411 | return filtered_items; |
| 412 | } |
| 413 | |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 414 | // Collection of public headers that were used to construct the AST this `IR` |
| 415 | // is generated from. |
Devin Jeanpierre | 0d5d0d4 | 2021-09-16 10:37:21 +0000 | [diff] [blame] | 416 | std::vector<HeaderName> used_headers; |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 417 | std::vector<std::variant<Func, Record, UnsupportedItem, Comment>> items; |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 418 | }; |
| 419 | |
Devin Jeanpierre | 2d5718a | 2021-10-05 11:39:34 +0000 | [diff] [blame] | 420 | inline std::ostream& operator<<(std::ostream& o, const IR& ir) { |
| 421 | return o << ir.ToJson(); |
| 422 | } |
Marcel Hlopko | bfd8d32 | 2021-08-02 12:28:52 +0000 | [diff] [blame] | 423 | } // namespace rs_bindings_from_cc |
| 424 | |
| 425 | #endif // CRUBIT_RS_BINDINGS_FROM_CC_IR_H_ |