blob: 65cd703ee52091ab44a21f018bb39cfe8325d073 [file] [log] [blame]
David Tolnay0c033e32020-11-01 15:15:48 -08001use crate::gen::block::Block;
David Tolnay3374d8d2020-10-31 22:18:45 -07002use crate::gen::ifndef;
3use crate::gen::out::{Content, OutFile};
David Tolnay8c14d9a2020-10-31 21:52:38 -07004
David Tolnay3be0e1f2020-10-31 20:53:00 -07005#[derive(Default, PartialEq)]
David Tolnay97c5b862020-11-01 14:59:01 -08006pub struct Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -07007 pub panic: bool,
8 pub rust_string: bool,
9 pub rust_str: bool,
10 pub rust_slice: bool,
11 pub rust_box: bool,
12 pub rust_vec: bool,
13 pub rust_fn: bool,
14 pub rust_isize: bool,
David Tolnay365fc7c2020-11-25 16:08:13 -080015 pub opaque: bool,
David Tolnayee6ecfc2020-12-26 21:54:37 -080016 pub layout: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070017 pub unsafe_bitcopy: bool,
18 pub rust_error: bool,
19 pub manually_drop: bool,
20 pub maybe_uninit: bool,
21 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070022 pub ptr_len: bool,
David Tolnayfe77f332021-01-02 17:39:51 -080023 pub repr_fat: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080024 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080025 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080026 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080027 pub is_complete: bool,
28 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080029 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070030}
31
David Tolnay97c5b862020-11-01 14:59:01 -080032impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070033 pub fn new() -> Self {
34 Builtins::default()
35 }
36}
David Tolnay3374d8d2020-10-31 22:18:45 -070037
38pub(super) fn write(out: &mut OutFile) {
39 if out.builtin == Default::default() {
40 return;
41 }
42
43 let include = &mut out.include;
44 let builtin = &mut out.builtin;
45 let out = &mut builtin.content;
46
David Tolnaydcfa8e92020-11-02 09:50:06 -080047 if builtin.rust_string {
48 include.array = true;
49 include.cstdint = true;
50 include.string = true;
51 }
52
53 if builtin.rust_str {
54 include.cstdint = true;
55 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080056 builtin.friend_impl = true;
57 }
58
David Tolnay725bf502020-12-27 02:47:40 -080059 if builtin.rust_vec {
60 include.algorithm = true;
61 include.array = true;
62 include.cstddef = true;
63 include.initializer_list = true;
64 include.iterator = true;
65 include.new = true;
66 include.type_traits = true;
67 include.utility = true;
68 builtin.panic = true;
69 builtin.rust_slice = true;
70 builtin.unsafe_bitcopy = true;
71 }
72
David Tolnay22664ae2020-11-04 16:30:45 -080073 if builtin.rust_slice {
David Tolnay08679ae2020-12-12 22:10:01 -080074 include.cstddef = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080075 include.iterator = true;
David Tolnay450d8cd2020-11-25 20:36:06 -080076 include.type_traits = true;
David Tolnay22664ae2020-11-04 16:30:45 -080077 builtin.friend_impl = true;
David Tolnay6f92baa2020-12-27 01:09:26 -080078 builtin.layout = true;
David Tolnay78dd5352020-12-26 23:44:20 -080079 builtin.panic = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080080 }
81
82 if builtin.rust_box {
83 include.new = true;
84 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080085 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080086 }
87
David Tolnaya5a13012020-11-10 15:03:09 -080088 if builtin.rust_fn {
89 include.utility = true;
90 }
91
David Tolnaydcfa8e92020-11-02 09:50:06 -080092 if builtin.rust_error {
93 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -080094 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080095 }
96
97 if builtin.rust_isize {
98 include.basetsd = true;
David Tolnay74dd66f2020-12-12 22:03:47 -080099 include.sys_types = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -0800100 }
101
David Tolnay174bd952020-11-02 09:23:12 -0800102 if builtin.relocatable {
103 include.type_traits = true;
104 }
105
David Tolnayee6ecfc2020-12-26 21:54:37 -0800106 if builtin.layout {
107 include.type_traits = true;
108 include.cstddef = true;
109 builtin.is_complete = true;
110 }
111
David Tolnay75068632020-12-26 22:15:17 -0800112 if builtin.is_complete {
113 include.cstddef = true;
114 include.type_traits = true;
115 }
116
David Tolnay0c033e32020-11-01 15:15:48 -0800117 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -0800118 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700119 writeln!(out, "// #include \"rust/cxx.h\"");
120
David Tolnay0f0162f2020-11-16 23:43:37 -0800121 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -0700122
123 if builtin.rust_string {
124 out.next_section();
125 writeln!(out, "struct unsafe_bitcopy_t;");
126 }
127
David Tolnay22664ae2020-11-04 16:30:45 -0800128 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800129 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700130 writeln!(out, "template <typename T>");
131 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800132 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700133 }
134
David Tolnayee6ecfc2020-12-26 21:54:37 -0800135 out.next_section();
David Tolnay828e5132020-11-29 20:40:40 -0800136 if builtin.rust_str && !builtin.rust_string {
David Tolnay828e5132020-11-29 20:40:40 -0800137 writeln!(out, "class String;");
138 }
David Tolnayee6ecfc2020-12-26 21:54:37 -0800139 if builtin.layout && !builtin.opaque {
140 writeln!(out, "class Opaque;");
141 }
David Tolnay828e5132020-11-29 20:40:40 -0800142
David Tolnay6f92baa2020-12-27 01:09:26 -0800143 if builtin.rust_slice {
144 out.next_section();
145 writeln!(out, "template <typename T>");
146 writeln!(out, "::std::size_t size_of();");
David Tolnayeee622c2020-12-27 01:26:17 -0800147 writeln!(out, "template <typename T>");
148 writeln!(out, "::std::size_t align_of();");
David Tolnay6f92baa2020-12-27 01:09:26 -0800149 }
150
David Tolnay0f0162f2020-11-16 23:43:37 -0800151 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
152 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
153 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
154 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
155 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
156 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
157 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
158 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
159 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
David Tolnay365fc7c2020-11-25 16:08:13 -0800160 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
David Tolnay75068632020-12-26 22:15:17 -0800161 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
David Tolnayee6ecfc2020-12-26 21:54:37 -0800162 ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
163 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700164
David Tolnay718ca0f2020-12-09 23:01:11 -0800165 out.begin_block(Block::Namespace("detail"));
166
167 if builtin.maybe_uninit {
168 include.cstddef = true;
169 include.new = true;
170 out.next_section();
171 writeln!(out, "template <typename T, typename = void *>");
172 writeln!(out, "struct operator_new {{");
173 writeln!(
174 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800175 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800176 );
177 writeln!(out, "}};");
178 out.next_section();
179 writeln!(out, "template <typename T>");
180 writeln!(
181 out,
182 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
183 );
184 writeln!(
185 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800186 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800187 );
188 writeln!(out, "}};");
189 }
190
191 out.end_block(Block::Namespace("detail"));
192
David Tolnay3374d8d2020-10-31 22:18:45 -0700193 if builtin.manually_drop {
194 out.next_section();
195 include.utility = true;
196 writeln!(out, "template <typename T>");
197 writeln!(out, "union ManuallyDrop {{");
198 writeln!(out, " T value;");
199 writeln!(
200 out,
201 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
202 );
203 writeln!(out, " ~ManuallyDrop() {{}}");
204 writeln!(out, "}};");
205 }
206
207 if builtin.maybe_uninit {
David Tolnay718ca0f2020-12-09 23:01:11 -0800208 include.cstddef = true;
David Tolnay3374d8d2020-10-31 22:18:45 -0700209 out.next_section();
210 writeln!(out, "template <typename T>");
211 writeln!(out, "union MaybeUninit {{");
212 writeln!(out, " T value;");
David Tolnay718ca0f2020-12-09 23:01:11 -0800213 writeln!(
214 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800215 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800216 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700217 writeln!(out, " MaybeUninit() {{}}");
218 writeln!(out, " ~MaybeUninit() {{}}");
219 writeln!(out, "}};");
220 }
221
David Tolnay0c033e32020-11-01 15:15:48 -0800222 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700223
David Tolnay919085c2020-10-31 22:32:22 -0700224 if builtin.ptr_len {
David Tolnay12320e12020-12-09 23:09:36 -0800225 include.cstddef = true;
David Tolnay0c033e32020-11-01 15:15:48 -0800226 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700227 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800228 writeln!(out, " void *ptr;");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800229 writeln!(out, " ::std::size_t len;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700230 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800231 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700232 }
233
David Tolnayfe77f332021-01-02 17:39:51 -0800234 if builtin.repr_fat {
235 include.array = true;
236 include.cstdint = true;
237 out.begin_block(Block::Namespace("repr"));
238 writeln!(out, "template <typename T>");
239 writeln!(out, "struct Fat final {{");
240 writeln!(out, " T repr;");
241 writeln!(out, "}};");
242 out.end_block(Block::Namespace("repr"));
243 }
244
David Tolnay3374d8d2020-10-31 22:18:45 -0700245 if builtin.rust_error {
246 out.next_section();
247 writeln!(out, "template <>");
248 writeln!(out, "class impl<Error> final {{");
249 writeln!(out, "public:");
250 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
251 writeln!(out, " Error error;");
252 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
253 writeln!(out, " error.len = repr.len;");
254 writeln!(out, " return error;");
255 writeln!(out, " }}");
256 writeln!(out, "}};");
257 }
258
David Tolnay53462762020-11-25 07:08:10 -0800259 if builtin.deleter_if {
260 out.next_section();
261 writeln!(out, "template <bool> struct deleter_if {{");
262 writeln!(out, " template <typename T> void operator()(T *) {{}}");
263 writeln!(out, "}};");
264 out.next_section();
265 writeln!(out, "template <> struct deleter_if<true> {{");
266 writeln!(
267 out,
268 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
269 );
270 writeln!(out, "}};");
271 }
272
David Tolnay0c033e32020-11-01 15:15:48 -0800273 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800274 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700275
276 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800277 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700278 include.exception = true;
279 include.type_traits = true;
280 include.utility = true;
281 writeln!(out, "class missing {{}};");
282 writeln!(out, "missing trycatch(...);");
283 writeln!(out);
284 writeln!(out, "template <typename Try, typename Fail>");
285 writeln!(out, "static typename ::std::enable_if<");
286 writeln!(
287 out,
288 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
289 );
290 writeln!(out, " missing>::value>::type");
291 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
292 writeln!(out, " func();");
293 writeln!(out, "}} catch (const ::std::exception &e) {{");
294 writeln!(out, " fail(e.what());");
295 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800296 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700297 }
298
David Tolnay0c033e32020-11-01 15:15:48 -0800299 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800300
301 if builtin.exception {
David Tolnay12320e12020-12-09 23:09:36 -0800302 include.cstddef = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800303 out.begin_block(Block::ExternC);
304 writeln!(
305 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800306 "const char *cxxbridge1$exception(const char *, ::std::size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800307 );
308 out.end_block(Block::ExternC);
309 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700310}