blob: eaaa08d17346057126f8424564247d5e1f557f7f [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,
David Tolnaya9449372021-03-26 16:40:53 -040018 pub unsafe_bitcopy_t: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070019 pub rust_error: bool,
20 pub manually_drop: bool,
21 pub maybe_uninit: bool,
22 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070023 pub ptr_len: bool,
David Tolnayfe77f332021-01-02 17:39:51 -080024 pub repr_fat: bool,
David Tolnaye5cd1482021-01-02 21:04:32 -080025 pub rust_str_new_unchecked: bool,
26 pub rust_str_repr: bool,
27 pub rust_slice_new: bool,
28 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080029 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080030 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080031 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080032 pub is_complete: bool,
33 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080034 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070035}
36
David Tolnay97c5b862020-11-01 14:59:01 -080037impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070038 pub fn new() -> Self {
39 Builtins::default()
40 }
41}
David Tolnay3374d8d2020-10-31 22:18:45 -070042
43pub(super) fn write(out: &mut OutFile) {
44 if out.builtin == Default::default() {
45 return;
46 }
47
48 let include = &mut out.include;
49 let builtin = &mut out.builtin;
50 let out = &mut builtin.content;
51
David Tolnaydcfa8e92020-11-02 09:50:06 -080052 if builtin.rust_string {
53 include.array = true;
54 include.cstdint = true;
55 include.string = true;
56 }
57
58 if builtin.rust_str {
David Tolnay851d2f72021-01-04 12:20:50 -080059 include.array = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080060 include.cstdint = true;
61 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080062 builtin.friend_impl = true;
63 }
64
David Tolnay725bf502020-12-27 02:47:40 -080065 if builtin.rust_vec {
66 include.algorithm = true;
67 include.array = true;
David Tolnayecb4dbf2021-01-14 11:22:34 -080068 include.cassert = true;
David Tolnay725bf502020-12-27 02:47:40 -080069 include.cstddef = true;
David Tolnay851d2f72021-01-04 12:20:50 -080070 include.cstdint = true;
David Tolnay725bf502020-12-27 02:47:40 -080071 include.initializer_list = true;
72 include.iterator = true;
73 include.new = true;
David Tolnay96e5d5e2021-03-28 03:16:11 -040074 include.stdexcept = true;
David Tolnay725bf502020-12-27 02:47:40 -080075 include.type_traits = true;
76 include.utility = true;
77 builtin.panic = true;
78 builtin.rust_slice = true;
David Tolnaya9449372021-03-26 16:40:53 -040079 builtin.unsafe_bitcopy_t = true;
David Tolnay725bf502020-12-27 02:47:40 -080080 }
81
David Tolnay22664ae2020-11-04 16:30:45 -080082 if builtin.rust_slice {
David Tolnay851d2f72021-01-04 12:20:50 -080083 include.array = true;
David Tolnayecb4dbf2021-01-14 11:22:34 -080084 include.cassert = true;
David Tolnay08679ae2020-12-12 22:10:01 -080085 include.cstddef = true;
David Tolnay851d2f72021-01-04 12:20:50 -080086 include.cstdint = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080087 include.iterator = true;
David Tolnay96e5d5e2021-03-28 03:16:11 -040088 include.stdexcept = true;
David Tolnay450d8cd2020-11-25 20:36:06 -080089 include.type_traits = true;
David Tolnay22664ae2020-11-04 16:30:45 -080090 builtin.friend_impl = true;
David Tolnay6f92baa2020-12-27 01:09:26 -080091 builtin.layout = true;
David Tolnay78dd5352020-12-26 23:44:20 -080092 builtin.panic = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080093 }
94
95 if builtin.rust_box {
96 include.new = true;
97 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080098 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080099 }
100
David Tolnaya5a13012020-11-10 15:03:09 -0800101 if builtin.rust_fn {
102 include.utility = true;
103 }
104
David Tolnaydcfa8e92020-11-02 09:50:06 -0800105 if builtin.rust_error {
106 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -0800107 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -0800108 }
109
110 if builtin.rust_isize {
111 include.basetsd = true;
David Tolnay74dd66f2020-12-12 22:03:47 -0800112 include.sys_types = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -0800113 }
114
David Tolnay174bd952020-11-02 09:23:12 -0800115 if builtin.relocatable {
116 include.type_traits = true;
117 }
118
David Tolnayee6ecfc2020-12-26 21:54:37 -0800119 if builtin.layout {
120 include.type_traits = true;
121 include.cstddef = true;
122 builtin.is_complete = true;
123 }
124
David Tolnay75068632020-12-26 22:15:17 -0800125 if builtin.is_complete {
126 include.cstddef = true;
127 include.type_traits = true;
128 }
129
David Tolnaya9449372021-03-26 16:40:53 -0400130 if builtin.unsafe_bitcopy {
131 builtin.unsafe_bitcopy_t = true;
132 }
133
David Tolnay0c033e32020-11-01 15:15:48 -0800134 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -0800135 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700136
David Tolnay5e14b102021-03-26 00:17:07 -0400137 let cxx_header = include.has_cxx_header();
David Tolnayccd269d2021-03-25 23:53:38 -0400138 if !cxx_header {
139 writeln!(out, "// #include \"rust/cxx.h\"");
David Tolnay3374d8d2020-10-31 22:18:45 -0700140
David Tolnayccd269d2021-03-25 23:53:38 -0400141 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
142
143 if builtin.rust_string {
144 out.next_section();
145 writeln!(out, "struct unsafe_bitcopy_t;");
146 }
147
148 if builtin.friend_impl {
149 out.begin_block(Block::AnonymousNamespace);
150 writeln!(out, "template <typename T>");
151 writeln!(out, "class impl;");
152 out.end_block(Block::AnonymousNamespace);
153 }
154
David Tolnay3374d8d2020-10-31 22:18:45 -0700155 out.next_section();
David Tolnayccd269d2021-03-25 23:53:38 -0400156 if builtin.rust_str && !builtin.rust_string {
157 writeln!(out, "class String;");
158 }
159 if builtin.layout && !builtin.opaque {
160 writeln!(out, "class Opaque;");
161 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700162
David Tolnayccd269d2021-03-25 23:53:38 -0400163 if builtin.rust_slice {
164 out.next_section();
165 writeln!(out, "template <typename T>");
166 writeln!(out, "::std::size_t size_of();");
167 writeln!(out, "template <typename T>");
168 writeln!(out, "::std::size_t align_of();");
169 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700170
David Tolnayccd269d2021-03-25 23:53:38 -0400171 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
172 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
173 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
174 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
David Tolnaya9449372021-03-26 16:40:53 -0400175 ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T");
David Tolnayccd269d2021-03-25 23:53:38 -0400176 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
177 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
178 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
179 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
180 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
181 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
182 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
183 ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
184 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay828e5132020-11-29 20:40:40 -0800185 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700186
David Tolnaye5cd1482021-01-02 21:04:32 -0800187 if builtin.rust_str_new_unchecked {
188 out.next_section();
189 writeln!(out, "class Str::uninit {{}};");
190 writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
191 }
192
193 if builtin.rust_slice_new {
194 out.next_section();
195 writeln!(out, "template <typename T>");
196 writeln!(out, "class Slice<T>::uninit {{}};");
197 writeln!(out, "template <typename T>");
198 writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
199 }
200
David Tolnay718ca0f2020-12-09 23:01:11 -0800201 out.begin_block(Block::Namespace("detail"));
202
203 if builtin.maybe_uninit {
204 include.cstddef = true;
205 include.new = true;
206 out.next_section();
207 writeln!(out, "template <typename T, typename = void *>");
208 writeln!(out, "struct operator_new {{");
209 writeln!(
210 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800211 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800212 );
213 writeln!(out, "}};");
214 out.next_section();
215 writeln!(out, "template <typename T>");
216 writeln!(
217 out,
218 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
219 );
220 writeln!(
221 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800222 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800223 );
224 writeln!(out, "}};");
225 }
226
227 out.end_block(Block::Namespace("detail"));
228
David Tolnay3374d8d2020-10-31 22:18:45 -0700229 if builtin.manually_drop {
230 out.next_section();
231 include.utility = true;
232 writeln!(out, "template <typename T>");
233 writeln!(out, "union ManuallyDrop {{");
234 writeln!(out, " T value;");
235 writeln!(
236 out,
237 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
238 );
239 writeln!(out, " ~ManuallyDrop() {{}}");
240 writeln!(out, "}};");
241 }
242
243 if builtin.maybe_uninit {
David Tolnay718ca0f2020-12-09 23:01:11 -0800244 include.cstddef = true;
David Tolnay3374d8d2020-10-31 22:18:45 -0700245 out.next_section();
246 writeln!(out, "template <typename T>");
247 writeln!(out, "union MaybeUninit {{");
248 writeln!(out, " T value;");
David Tolnay718ca0f2020-12-09 23:01:11 -0800249 writeln!(
250 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800251 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800252 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700253 writeln!(out, " MaybeUninit() {{}}");
254 writeln!(out, " ~MaybeUninit() {{}}");
255 writeln!(out, "}};");
256 }
257
David Tolnay0c033e32020-11-01 15:15:48 -0800258 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700259
David Tolnaye5cd1482021-01-02 21:04:32 -0800260 if builtin.repr_fat {
261 include.array = true;
262 include.cstdint = true;
263 out.next_section();
264 out.begin_block(Block::Namespace("repr"));
265 writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
266 out.end_block(Block::Namespace("repr"));
267 }
268
David Tolnay919085c2020-10-31 22:32:22 -0700269 if builtin.ptr_len {
David Tolnay12320e12020-12-09 23:09:36 -0800270 include.cstddef = true;
David Tolnaye5cd1482021-01-02 21:04:32 -0800271 out.next_section();
David Tolnay0c033e32020-11-01 15:15:48 -0800272 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700273 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800274 writeln!(out, " void *ptr;");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800275 writeln!(out, " ::std::size_t len;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700276 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800277 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700278 }
279
David Tolnaye5cd1482021-01-02 21:04:32 -0800280 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
281 out.next_section();
282 writeln!(out, "template <>");
283 writeln!(out, "class impl<Str> final {{");
284 writeln!(out, "public:");
285 if builtin.rust_str_new_unchecked {
286 writeln!(
287 out,
288 " static Str new_unchecked(repr::Fat repr) noexcept {{",
289 );
290 writeln!(out, " Str str = Str::uninit{{}};");
291 writeln!(out, " str.repr = repr;");
292 writeln!(out, " return str;");
293 writeln!(out, " }}");
294 }
295 if builtin.rust_str_repr {
296 writeln!(out, " static repr::Fat repr(Str str) noexcept {{");
297 writeln!(out, " return str.repr;");
298 writeln!(out, " }}");
299 }
David Tolnayfe77f332021-01-02 17:39:51 -0800300 writeln!(out, "}};");
David Tolnaye5cd1482021-01-02 21:04:32 -0800301 }
302
303 if builtin.rust_slice_new || builtin.rust_slice_repr {
304 out.next_section();
305 writeln!(out, "template <typename T>");
306 writeln!(out, "class impl<Slice<T>> final {{");
307 writeln!(out, "public:");
308 if builtin.rust_slice_new {
309 writeln!(out, " static Slice<T> slice(repr::Fat repr) noexcept {{");
310 writeln!(out, " Slice<T> slice = typename Slice<T>::uninit{{}};");
311 writeln!(out, " slice.repr = repr;");
312 writeln!(out, " return slice;");
313 writeln!(out, " }}");
314 }
315 if builtin.rust_slice_repr {
316 writeln!(out, " static repr::Fat repr(Slice<T> slice) noexcept {{");
317 writeln!(out, " return slice.repr;");
318 writeln!(out, " }}");
319 }
320 writeln!(out, "}};");
David Tolnayfe77f332021-01-02 17:39:51 -0800321 }
322
David Tolnay3374d8d2020-10-31 22:18:45 -0700323 if builtin.rust_error {
324 out.next_section();
325 writeln!(out, "template <>");
326 writeln!(out, "class impl<Error> final {{");
327 writeln!(out, "public:");
328 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
329 writeln!(out, " Error error;");
330 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
331 writeln!(out, " error.len = repr.len;");
332 writeln!(out, " return error;");
333 writeln!(out, " }}");
334 writeln!(out, "}};");
335 }
336
David Tolnay53462762020-11-25 07:08:10 -0800337 if builtin.deleter_if {
338 out.next_section();
339 writeln!(out, "template <bool> struct deleter_if {{");
340 writeln!(out, " template <typename T> void operator()(T *) {{}}");
341 writeln!(out, "}};");
342 out.next_section();
343 writeln!(out, "template <> struct deleter_if<true> {{");
344 writeln!(
345 out,
346 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
347 );
348 writeln!(out, "}};");
349 }
350
David Tolnay0c033e32020-11-01 15:15:48 -0800351 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800352 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700353
354 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800355 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700356 include.exception = true;
357 include.type_traits = true;
358 include.utility = true;
359 writeln!(out, "class missing {{}};");
360 writeln!(out, "missing trycatch(...);");
361 writeln!(out);
362 writeln!(out, "template <typename Try, typename Fail>");
363 writeln!(out, "static typename ::std::enable_if<");
364 writeln!(
365 out,
366 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
367 );
368 writeln!(out, " missing>::value>::type");
369 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
370 writeln!(out, " func();");
371 writeln!(out, "}} catch (const ::std::exception &e) {{");
372 writeln!(out, " fail(e.what());");
373 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800374 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700375 }
376
David Tolnay0c033e32020-11-01 15:15:48 -0800377 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800378
379 if builtin.exception {
David Tolnay12320e12020-12-09 23:09:36 -0800380 include.cstddef = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800381 out.begin_block(Block::ExternC);
382 writeln!(
383 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800384 "const char *cxxbridge1$exception(const char *, ::std::size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800385 );
386 out.end_block(Block::ExternC);
387 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700388}