blob: 378467b6603d228047dc15e767a3d0bd5b87d68b [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 Tolnaye5cd1482021-01-02 21:04:32 -080024 pub rust_str_new_unchecked: bool,
25 pub rust_str_repr: bool,
26 pub rust_slice_new: bool,
27 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080028 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080029 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080030 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080031 pub is_complete: bool,
32 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080033 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070034}
35
David Tolnay97c5b862020-11-01 14:59:01 -080036impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070037 pub fn new() -> Self {
38 Builtins::default()
39 }
40}
David Tolnay3374d8d2020-10-31 22:18:45 -070041
42pub(super) fn write(out: &mut OutFile) {
43 if out.builtin == Default::default() {
44 return;
45 }
46
47 let include = &mut out.include;
48 let builtin = &mut out.builtin;
49 let out = &mut builtin.content;
50
David Tolnaydcfa8e92020-11-02 09:50:06 -080051 if builtin.rust_string {
52 include.array = true;
53 include.cstdint = true;
54 include.string = true;
55 }
56
57 if builtin.rust_str {
David Tolnay851d2f72021-01-04 12:20:50 -080058 include.array = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080059 include.cstdint = true;
60 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080061 builtin.friend_impl = true;
62 }
63
David Tolnay725bf502020-12-27 02:47:40 -080064 if builtin.rust_vec {
65 include.algorithm = true;
66 include.array = true;
David Tolnayecb4dbf2021-01-14 11:22:34 -080067 include.cassert = true;
David Tolnay725bf502020-12-27 02:47:40 -080068 include.cstddef = true;
David Tolnay851d2f72021-01-04 12:20:50 -080069 include.cstdint = true;
David Tolnay725bf502020-12-27 02:47:40 -080070 include.initializer_list = true;
71 include.iterator = true;
72 include.new = true;
73 include.type_traits = true;
74 include.utility = true;
75 builtin.panic = true;
76 builtin.rust_slice = true;
77 builtin.unsafe_bitcopy = true;
78 }
79
David Tolnay22664ae2020-11-04 16:30:45 -080080 if builtin.rust_slice {
David Tolnay851d2f72021-01-04 12:20:50 -080081 include.array = true;
David Tolnayecb4dbf2021-01-14 11:22:34 -080082 include.cassert = true;
David Tolnay08679ae2020-12-12 22:10:01 -080083 include.cstddef = true;
David Tolnay851d2f72021-01-04 12:20:50 -080084 include.cstdint = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080085 include.iterator = true;
David Tolnay450d8cd2020-11-25 20:36:06 -080086 include.type_traits = true;
David Tolnay22664ae2020-11-04 16:30:45 -080087 builtin.friend_impl = true;
David Tolnay6f92baa2020-12-27 01:09:26 -080088 builtin.layout = true;
David Tolnay78dd5352020-12-26 23:44:20 -080089 builtin.panic = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080090 }
91
92 if builtin.rust_box {
93 include.new = true;
94 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080095 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080096 }
97
David Tolnaya5a13012020-11-10 15:03:09 -080098 if builtin.rust_fn {
99 include.utility = true;
100 }
101
David Tolnaydcfa8e92020-11-02 09:50:06 -0800102 if builtin.rust_error {
103 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -0800104 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -0800105 }
106
107 if builtin.rust_isize {
108 include.basetsd = true;
David Tolnay74dd66f2020-12-12 22:03:47 -0800109 include.sys_types = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -0800110 }
111
David Tolnay174bd952020-11-02 09:23:12 -0800112 if builtin.relocatable {
113 include.type_traits = true;
114 }
115
David Tolnayee6ecfc2020-12-26 21:54:37 -0800116 if builtin.layout {
117 include.type_traits = true;
118 include.cstddef = true;
119 builtin.is_complete = true;
120 }
121
David Tolnay75068632020-12-26 22:15:17 -0800122 if builtin.is_complete {
123 include.cstddef = true;
124 include.type_traits = true;
125 }
126
David Tolnay0c033e32020-11-01 15:15:48 -0800127 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -0800128 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700129 writeln!(out, "// #include \"rust/cxx.h\"");
130
David Tolnay0f0162f2020-11-16 23:43:37 -0800131 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -0700132
133 if builtin.rust_string {
134 out.next_section();
135 writeln!(out, "struct unsafe_bitcopy_t;");
136 }
137
David Tolnay22664ae2020-11-04 16:30:45 -0800138 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800139 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700140 writeln!(out, "template <typename T>");
141 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800142 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700143 }
144
David Tolnayee6ecfc2020-12-26 21:54:37 -0800145 out.next_section();
David Tolnay828e5132020-11-29 20:40:40 -0800146 if builtin.rust_str && !builtin.rust_string {
David Tolnay828e5132020-11-29 20:40:40 -0800147 writeln!(out, "class String;");
148 }
David Tolnayee6ecfc2020-12-26 21:54:37 -0800149 if builtin.layout && !builtin.opaque {
150 writeln!(out, "class Opaque;");
151 }
David Tolnay828e5132020-11-29 20:40:40 -0800152
David Tolnay6f92baa2020-12-27 01:09:26 -0800153 if builtin.rust_slice {
154 out.next_section();
155 writeln!(out, "template <typename T>");
156 writeln!(out, "::std::size_t size_of();");
David Tolnayeee622c2020-12-27 01:26:17 -0800157 writeln!(out, "template <typename T>");
158 writeln!(out, "::std::size_t align_of();");
David Tolnay6f92baa2020-12-27 01:09:26 -0800159 }
160
David Tolnay0f0162f2020-11-16 23:43:37 -0800161 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
162 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
163 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
164 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
165 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
166 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
167 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
168 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
169 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
David Tolnay365fc7c2020-11-25 16:08:13 -0800170 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
David Tolnay75068632020-12-26 22:15:17 -0800171 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
David Tolnayee6ecfc2020-12-26 21:54:37 -0800172 ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
173 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700174
David Tolnaye5cd1482021-01-02 21:04:32 -0800175 if builtin.rust_str_new_unchecked {
176 out.next_section();
177 writeln!(out, "class Str::uninit {{}};");
178 writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
179 }
180
181 if builtin.rust_slice_new {
182 out.next_section();
183 writeln!(out, "template <typename T>");
184 writeln!(out, "class Slice<T>::uninit {{}};");
185 writeln!(out, "template <typename T>");
186 writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
187 }
188
David Tolnay718ca0f2020-12-09 23:01:11 -0800189 out.begin_block(Block::Namespace("detail"));
190
191 if builtin.maybe_uninit {
192 include.cstddef = true;
193 include.new = true;
194 out.next_section();
195 writeln!(out, "template <typename T, typename = void *>");
196 writeln!(out, "struct operator_new {{");
197 writeln!(
198 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800199 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800200 );
201 writeln!(out, "}};");
202 out.next_section();
203 writeln!(out, "template <typename T>");
204 writeln!(
205 out,
206 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
207 );
208 writeln!(
209 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800210 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800211 );
212 writeln!(out, "}};");
213 }
214
215 out.end_block(Block::Namespace("detail"));
216
David Tolnay3374d8d2020-10-31 22:18:45 -0700217 if builtin.manually_drop {
218 out.next_section();
219 include.utility = true;
220 writeln!(out, "template <typename T>");
221 writeln!(out, "union ManuallyDrop {{");
222 writeln!(out, " T value;");
223 writeln!(
224 out,
225 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
226 );
227 writeln!(out, " ~ManuallyDrop() {{}}");
228 writeln!(out, "}};");
229 }
230
231 if builtin.maybe_uninit {
David Tolnay718ca0f2020-12-09 23:01:11 -0800232 include.cstddef = true;
David Tolnay3374d8d2020-10-31 22:18:45 -0700233 out.next_section();
234 writeln!(out, "template <typename T>");
235 writeln!(out, "union MaybeUninit {{");
236 writeln!(out, " T value;");
David Tolnay718ca0f2020-12-09 23:01:11 -0800237 writeln!(
238 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800239 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800240 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700241 writeln!(out, " MaybeUninit() {{}}");
242 writeln!(out, " ~MaybeUninit() {{}}");
243 writeln!(out, "}};");
244 }
245
David Tolnay0c033e32020-11-01 15:15:48 -0800246 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700247
David Tolnaye5cd1482021-01-02 21:04:32 -0800248 if builtin.repr_fat {
249 include.array = true;
250 include.cstdint = true;
251 out.next_section();
252 out.begin_block(Block::Namespace("repr"));
253 writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
254 out.end_block(Block::Namespace("repr"));
255 }
256
David Tolnay919085c2020-10-31 22:32:22 -0700257 if builtin.ptr_len {
David Tolnay12320e12020-12-09 23:09:36 -0800258 include.cstddef = true;
David Tolnaye5cd1482021-01-02 21:04:32 -0800259 out.next_section();
David Tolnay0c033e32020-11-01 15:15:48 -0800260 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700261 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800262 writeln!(out, " void *ptr;");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800263 writeln!(out, " ::std::size_t len;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700264 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800265 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700266 }
267
David Tolnaye5cd1482021-01-02 21:04:32 -0800268 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
269 out.next_section();
270 writeln!(out, "template <>");
271 writeln!(out, "class impl<Str> final {{");
272 writeln!(out, "public:");
273 if builtin.rust_str_new_unchecked {
274 writeln!(
275 out,
276 " static Str new_unchecked(repr::Fat repr) noexcept {{",
277 );
278 writeln!(out, " Str str = Str::uninit{{}};");
279 writeln!(out, " str.repr = repr;");
280 writeln!(out, " return str;");
281 writeln!(out, " }}");
282 }
283 if builtin.rust_str_repr {
284 writeln!(out, " static repr::Fat repr(Str str) noexcept {{");
285 writeln!(out, " return str.repr;");
286 writeln!(out, " }}");
287 }
David Tolnayfe77f332021-01-02 17:39:51 -0800288 writeln!(out, "}};");
David Tolnaye5cd1482021-01-02 21:04:32 -0800289 }
290
291 if builtin.rust_slice_new || builtin.rust_slice_repr {
292 out.next_section();
293 writeln!(out, "template <typename T>");
294 writeln!(out, "class impl<Slice<T>> final {{");
295 writeln!(out, "public:");
296 if builtin.rust_slice_new {
297 writeln!(out, " static Slice<T> slice(repr::Fat repr) noexcept {{");
298 writeln!(out, " Slice<T> slice = typename Slice<T>::uninit{{}};");
299 writeln!(out, " slice.repr = repr;");
300 writeln!(out, " return slice;");
301 writeln!(out, " }}");
302 }
303 if builtin.rust_slice_repr {
304 writeln!(out, " static repr::Fat repr(Slice<T> slice) noexcept {{");
305 writeln!(out, " return slice.repr;");
306 writeln!(out, " }}");
307 }
308 writeln!(out, "}};");
David Tolnayfe77f332021-01-02 17:39:51 -0800309 }
310
David Tolnay3374d8d2020-10-31 22:18:45 -0700311 if builtin.rust_error {
312 out.next_section();
313 writeln!(out, "template <>");
314 writeln!(out, "class impl<Error> final {{");
315 writeln!(out, "public:");
316 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
317 writeln!(out, " Error error;");
318 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
319 writeln!(out, " error.len = repr.len;");
320 writeln!(out, " return error;");
321 writeln!(out, " }}");
322 writeln!(out, "}};");
323 }
324
David Tolnay53462762020-11-25 07:08:10 -0800325 if builtin.deleter_if {
326 out.next_section();
327 writeln!(out, "template <bool> struct deleter_if {{");
328 writeln!(out, " template <typename T> void operator()(T *) {{}}");
329 writeln!(out, "}};");
330 out.next_section();
331 writeln!(out, "template <> struct deleter_if<true> {{");
332 writeln!(
333 out,
334 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
335 );
336 writeln!(out, "}};");
337 }
338
David Tolnay0c033e32020-11-01 15:15:48 -0800339 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800340 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700341
342 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800343 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700344 include.exception = true;
345 include.type_traits = true;
346 include.utility = true;
347 writeln!(out, "class missing {{}};");
348 writeln!(out, "missing trycatch(...);");
349 writeln!(out);
350 writeln!(out, "template <typename Try, typename Fail>");
351 writeln!(out, "static typename ::std::enable_if<");
352 writeln!(
353 out,
354 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
355 );
356 writeln!(out, " missing>::value>::type");
357 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
358 writeln!(out, " func();");
359 writeln!(out, "}} catch (const ::std::exception &e) {{");
360 writeln!(out, " fail(e.what());");
361 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800362 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700363 }
364
David Tolnay0c033e32020-11-01 15:15:48 -0800365 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800366
367 if builtin.exception {
David Tolnay12320e12020-12-09 23:09:36 -0800368 include.cstddef = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800369 out.begin_block(Block::ExternC);
370 writeln!(
371 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800372 "const char *cxxbridge1$exception(const char *, ::std::size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800373 );
374 out.end_block(Block::ExternC);
375 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700376}