blob: dbd019b26d26798200d7cbef1c6ddb2d321345ac [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 Tolnay3be0e1f2020-10-31 20:53:00 -070016 pub unsafe_bitcopy: bool,
17 pub rust_error: bool,
18 pub manually_drop: bool,
19 pub maybe_uninit: bool,
20 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070021 pub ptr_len: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070022 pub rust_str_new_unchecked: bool,
23 pub rust_str_repr: bool,
David Tolnay36aa9e02020-10-31 23:08:21 -070024 pub rust_slice_new: bool,
25 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080026 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080027 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080028 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080029 pub is_complete: bool,
30 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080031 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070032}
33
David Tolnay97c5b862020-11-01 14:59:01 -080034impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070035 pub fn new() -> Self {
36 Builtins::default()
37 }
38}
David Tolnay3374d8d2020-10-31 22:18:45 -070039
40pub(super) fn write(out: &mut OutFile) {
41 if out.builtin == Default::default() {
42 return;
43 }
44
45 let include = &mut out.include;
46 let builtin = &mut out.builtin;
47 let out = &mut builtin.content;
48
David Tolnaydcfa8e92020-11-02 09:50:06 -080049 if builtin.rust_string {
50 include.array = true;
51 include.cstdint = true;
52 include.string = true;
53 }
54
55 if builtin.rust_str {
56 include.cstdint = true;
57 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080058 builtin.friend_impl = true;
59 }
60
61 if builtin.rust_slice {
David Tolnay08679ae2020-12-12 22:10:01 -080062 include.cstddef = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080063 include.iterator = true;
David Tolnay450d8cd2020-11-25 20:36:06 -080064 include.type_traits = true;
David Tolnay22664ae2020-11-04 16:30:45 -080065 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080066 }
67
68 if builtin.rust_box {
69 include.new = true;
70 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080071 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080072 }
73
74 if builtin.rust_vec {
David Tolnayf799b372020-11-29 23:57:42 -080075 include.algorithm = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080076 include.array = true;
David Tolnay08679ae2020-12-12 22:10:01 -080077 include.cstddef = true;
David Tolnayf799b372020-11-29 23:57:42 -080078 include.initializer_list = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080079 include.iterator = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080080 include.new = true;
81 include.type_traits = true;
David Tolnayfb6b73c2020-11-10 14:32:16 -080082 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080083 builtin.panic = true;
84 builtin.unsafe_bitcopy = true;
85 }
86
David Tolnaya5a13012020-11-10 15:03:09 -080087 if builtin.rust_fn {
88 include.utility = true;
89 }
90
David Tolnaydcfa8e92020-11-02 09:50:06 -080091 if builtin.rust_error {
92 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -080093 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080094 }
95
96 if builtin.rust_isize {
97 include.basetsd = true;
David Tolnay74dd66f2020-12-12 22:03:47 -080098 include.sys_types = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080099 }
100
David Tolnay174bd952020-11-02 09:23:12 -0800101 if builtin.relocatable {
102 include.type_traits = true;
103 }
104
David Tolnay75068632020-12-26 22:15:17 -0800105 if builtin.is_complete {
106 include.cstddef = true;
107 include.type_traits = true;
108 }
109
David Tolnay0c033e32020-11-01 15:15:48 -0800110 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -0800111 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700112 writeln!(out, "// #include \"rust/cxx.h\"");
113
David Tolnay0f0162f2020-11-16 23:43:37 -0800114 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -0700115
116 if builtin.rust_string {
117 out.next_section();
118 writeln!(out, "struct unsafe_bitcopy_t;");
119 }
120
David Tolnay22664ae2020-11-04 16:30:45 -0800121 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800122 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700123 writeln!(out, "template <typename T>");
124 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800125 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700126 }
127
David Tolnay828e5132020-11-29 20:40:40 -0800128 if builtin.rust_str && !builtin.rust_string {
129 out.next_section();
130 writeln!(out, "class String;");
131 }
132
David Tolnay0f0162f2020-11-16 23:43:37 -0800133 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
134 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
135 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
136 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
137 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
138 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
139 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
140 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
141 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
David Tolnay365fc7c2020-11-25 16:08:13 -0800142 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
David Tolnay0f0162f2020-11-16 23:43:37 -0800143 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay75068632020-12-26 22:15:17 -0800144 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700145
David Tolnay718ca0f2020-12-09 23:01:11 -0800146 out.begin_block(Block::Namespace("detail"));
147
148 if builtin.maybe_uninit {
149 include.cstddef = true;
150 include.new = true;
151 out.next_section();
152 writeln!(out, "template <typename T, typename = void *>");
153 writeln!(out, "struct operator_new {{");
154 writeln!(
155 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800156 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800157 );
158 writeln!(out, "}};");
159 out.next_section();
160 writeln!(out, "template <typename T>");
161 writeln!(
162 out,
163 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
164 );
165 writeln!(
166 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800167 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800168 );
169 writeln!(out, "}};");
170 }
171
172 out.end_block(Block::Namespace("detail"));
173
David Tolnay3374d8d2020-10-31 22:18:45 -0700174 if builtin.manually_drop {
175 out.next_section();
176 include.utility = true;
177 writeln!(out, "template <typename T>");
178 writeln!(out, "union ManuallyDrop {{");
179 writeln!(out, " T value;");
180 writeln!(
181 out,
182 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
183 );
184 writeln!(out, " ~ManuallyDrop() {{}}");
185 writeln!(out, "}};");
186 }
187
188 if builtin.maybe_uninit {
David Tolnay718ca0f2020-12-09 23:01:11 -0800189 include.cstddef = true;
David Tolnay3374d8d2020-10-31 22:18:45 -0700190 out.next_section();
191 writeln!(out, "template <typename T>");
192 writeln!(out, "union MaybeUninit {{");
193 writeln!(out, " T value;");
David Tolnay718ca0f2020-12-09 23:01:11 -0800194 writeln!(
195 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800196 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800197 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700198 writeln!(out, " MaybeUninit() {{}}");
199 writeln!(out, " ~MaybeUninit() {{}}");
200 writeln!(out, "}};");
201 }
202
David Tolnay0c033e32020-11-01 15:15:48 -0800203 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700204
David Tolnay919085c2020-10-31 22:32:22 -0700205 if builtin.ptr_len {
David Tolnay12320e12020-12-09 23:09:36 -0800206 include.cstddef = true;
David Tolnay0c033e32020-11-01 15:15:48 -0800207 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700208 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800209 writeln!(out, " void *ptr;");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800210 writeln!(out, " ::std::size_t len;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700211 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800212 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700213 }
214
215 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
216 out.next_section();
217 writeln!(out, "template <>");
218 writeln!(out, "class impl<Str> final {{");
219 writeln!(out, "public:");
220 if builtin.rust_str_new_unchecked {
221 writeln!(
222 out,
223 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
224 );
225 writeln!(out, " Str str;");
226 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
227 writeln!(out, " str.len = repr.len;");
228 writeln!(out, " return str;");
229 writeln!(out, " }}");
230 }
231 if builtin.rust_str_repr {
232 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800233 writeln!(
234 out,
235 " return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
236 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700237 writeln!(out, " }}");
238 }
239 writeln!(out, "}};");
240 }
241
David Tolnay36aa9e02020-10-31 23:08:21 -0700242 if builtin.rust_slice_new || builtin.rust_slice_repr {
243 out.next_section();
244 writeln!(out, "template <typename T>");
245 writeln!(out, "class impl<Slice<T>> final {{");
246 writeln!(out, "public:");
247 if builtin.rust_slice_new {
248 writeln!(
249 out,
250 " static Slice<T> slice(repr::PtrLen repr) noexcept {{",
251 );
David Tolnayc5629f02020-11-23 18:32:46 -0800252 writeln!(out, " return {{static_cast<T *>(repr.ptr), repr.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700253 writeln!(out, " }}");
254 }
255 if builtin.rust_slice_repr {
David Tolnayc5629f02020-11-23 18:32:46 -0800256 include.type_traits = true;
David Tolnay36aa9e02020-10-31 23:08:21 -0700257 writeln!(
258 out,
259 " static repr::PtrLen repr(Slice<T> slice) noexcept {{",
260 );
David Tolnayc5629f02020-11-23 18:32:46 -0800261 writeln!(out, " return repr::PtrLen{{");
262 writeln!(
263 out,
264 " const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
265 );
266 writeln!(out, " slice.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700267 writeln!(out, " }}");
268 }
269 writeln!(out, "}};");
270 }
271
David Tolnay3374d8d2020-10-31 22:18:45 -0700272 if builtin.rust_error {
273 out.next_section();
274 writeln!(out, "template <>");
275 writeln!(out, "class impl<Error> final {{");
276 writeln!(out, "public:");
277 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
278 writeln!(out, " Error error;");
279 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
280 writeln!(out, " error.len = repr.len;");
281 writeln!(out, " return error;");
282 writeln!(out, " }}");
283 writeln!(out, "}};");
284 }
285
David Tolnay53462762020-11-25 07:08:10 -0800286 if builtin.deleter_if {
287 out.next_section();
288 writeln!(out, "template <bool> struct deleter_if {{");
289 writeln!(out, " template <typename T> void operator()(T *) {{}}");
290 writeln!(out, "}};");
291 out.next_section();
292 writeln!(out, "template <> struct deleter_if<true> {{");
293 writeln!(
294 out,
295 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
296 );
297 writeln!(out, "}};");
298 }
299
David Tolnay0c033e32020-11-01 15:15:48 -0800300 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800301 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700302
303 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800304 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700305 include.exception = true;
306 include.type_traits = true;
307 include.utility = true;
308 writeln!(out, "class missing {{}};");
309 writeln!(out, "missing trycatch(...);");
310 writeln!(out);
311 writeln!(out, "template <typename Try, typename Fail>");
312 writeln!(out, "static typename ::std::enable_if<");
313 writeln!(
314 out,
315 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
316 );
317 writeln!(out, " missing>::value>::type");
318 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
319 writeln!(out, " func();");
320 writeln!(out, "}} catch (const ::std::exception &e) {{");
321 writeln!(out, " fail(e.what());");
322 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800323 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700324 }
325
David Tolnay0c033e32020-11-01 15:15:48 -0800326 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800327
328 if builtin.exception {
David Tolnay12320e12020-12-09 23:09:36 -0800329 include.cstddef = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800330 out.begin_block(Block::ExternC);
331 writeln!(
332 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800333 "const char *cxxbridge1$exception(const char *, ::std::size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800334 );
335 out.end_block(Block::ExternC);
336 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700337}