blob: 9b8d45eedd385a96695872be158380eccbc57e94 [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 Tolnay3be0e1f2020-10-31 20:53:00 -070023 pub rust_str_new_unchecked: bool,
24 pub rust_str_repr: bool,
David Tolnay36aa9e02020-10-31 23:08:21 -070025 pub rust_slice_new: bool,
26 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080027 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080028 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080029 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080030 pub is_complete: bool,
31 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080032 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070033}
34
David Tolnay97c5b862020-11-01 14:59:01 -080035impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070036 pub fn new() -> Self {
37 Builtins::default()
38 }
39}
David Tolnay3374d8d2020-10-31 22:18:45 -070040
41pub(super) fn write(out: &mut OutFile) {
42 if out.builtin == Default::default() {
43 return;
44 }
45
46 let include = &mut out.include;
47 let builtin = &mut out.builtin;
48 let out = &mut builtin.content;
49
David Tolnaydcfa8e92020-11-02 09:50:06 -080050 if builtin.rust_string {
51 include.array = true;
52 include.cstdint = true;
53 include.string = true;
54 }
55
56 if builtin.rust_str {
57 include.cstdint = true;
58 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080059 builtin.friend_impl = true;
60 }
61
62 if builtin.rust_slice {
David Tolnay08679ae2020-12-12 22:10:01 -080063 include.cstddef = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080064 include.iterator = true;
David Tolnay450d8cd2020-11-25 20:36:06 -080065 include.type_traits = true;
David Tolnay22664ae2020-11-04 16:30:45 -080066 builtin.friend_impl = true;
David Tolnay6f92baa2020-12-27 01:09:26 -080067 builtin.layout = true;
David Tolnay78dd5352020-12-26 23:44:20 -080068 builtin.panic = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080069 }
70
71 if builtin.rust_box {
72 include.new = true;
73 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080074 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080075 }
76
77 if builtin.rust_vec {
David Tolnayf799b372020-11-29 23:57:42 -080078 include.algorithm = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080079 include.array = true;
David Tolnay08679ae2020-12-12 22:10:01 -080080 include.cstddef = true;
David Tolnayf799b372020-11-29 23:57:42 -080081 include.initializer_list = true;
David Tolnayd1df4c72020-11-25 20:38:05 -080082 include.iterator = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080083 include.new = true;
84 include.type_traits = true;
David Tolnayfb6b73c2020-11-10 14:32:16 -080085 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080086 builtin.panic = true;
87 builtin.unsafe_bitcopy = true;
88 }
89
David Tolnaya5a13012020-11-10 15:03:09 -080090 if builtin.rust_fn {
91 include.utility = true;
92 }
93
David Tolnaydcfa8e92020-11-02 09:50:06 -080094 if builtin.rust_error {
95 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -080096 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080097 }
98
99 if builtin.rust_isize {
100 include.basetsd = true;
David Tolnay74dd66f2020-12-12 22:03:47 -0800101 include.sys_types = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -0800102 }
103
David Tolnay174bd952020-11-02 09:23:12 -0800104 if builtin.relocatable {
105 include.type_traits = true;
106 }
107
David Tolnayee6ecfc2020-12-26 21:54:37 -0800108 if builtin.layout {
109 include.type_traits = true;
110 include.cstddef = true;
111 builtin.is_complete = true;
112 }
113
David Tolnay75068632020-12-26 22:15:17 -0800114 if builtin.is_complete {
115 include.cstddef = true;
116 include.type_traits = true;
117 }
118
David Tolnay0c033e32020-11-01 15:15:48 -0800119 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -0800120 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700121 writeln!(out, "// #include \"rust/cxx.h\"");
122
David Tolnay0f0162f2020-11-16 23:43:37 -0800123 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -0700124
125 if builtin.rust_string {
126 out.next_section();
127 writeln!(out, "struct unsafe_bitcopy_t;");
128 }
129
David Tolnay22664ae2020-11-04 16:30:45 -0800130 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800131 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700132 writeln!(out, "template <typename T>");
133 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800134 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700135 }
136
David Tolnayee6ecfc2020-12-26 21:54:37 -0800137 out.next_section();
David Tolnay828e5132020-11-29 20:40:40 -0800138 if builtin.rust_str && !builtin.rust_string {
David Tolnay828e5132020-11-29 20:40:40 -0800139 writeln!(out, "class String;");
140 }
David Tolnayee6ecfc2020-12-26 21:54:37 -0800141 if builtin.layout && !builtin.opaque {
142 writeln!(out, "class Opaque;");
143 }
David Tolnay828e5132020-11-29 20:40:40 -0800144
David Tolnay6f92baa2020-12-27 01:09:26 -0800145 if builtin.rust_slice {
146 out.next_section();
147 writeln!(out, "template <typename T>");
148 writeln!(out, "::std::size_t size_of();");
David Tolnayeee622c2020-12-27 01:26:17 -0800149 writeln!(out, "template <typename T>");
150 writeln!(out, "::std::size_t align_of();");
David Tolnay6f92baa2020-12-27 01:09:26 -0800151 }
152
David Tolnay0f0162f2020-11-16 23:43:37 -0800153 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
154 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
155 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
156 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
157 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
158 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
159 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
160 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
161 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
David Tolnay365fc7c2020-11-25 16:08:13 -0800162 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
David Tolnay75068632020-12-26 22:15:17 -0800163 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
David Tolnayee6ecfc2020-12-26 21:54:37 -0800164 ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
165 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700166
David Tolnay718ca0f2020-12-09 23:01:11 -0800167 out.begin_block(Block::Namespace("detail"));
168
169 if builtin.maybe_uninit {
170 include.cstddef = true;
171 include.new = true;
172 out.next_section();
173 writeln!(out, "template <typename T, typename = void *>");
174 writeln!(out, "struct operator_new {{");
175 writeln!(
176 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800177 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800178 );
179 writeln!(out, "}};");
180 out.next_section();
181 writeln!(out, "template <typename T>");
182 writeln!(
183 out,
184 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
185 );
186 writeln!(
187 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800188 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800189 );
190 writeln!(out, "}};");
191 }
192
193 out.end_block(Block::Namespace("detail"));
194
David Tolnay3374d8d2020-10-31 22:18:45 -0700195 if builtin.manually_drop {
196 out.next_section();
197 include.utility = true;
198 writeln!(out, "template <typename T>");
199 writeln!(out, "union ManuallyDrop {{");
200 writeln!(out, " T value;");
201 writeln!(
202 out,
203 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
204 );
205 writeln!(out, " ~ManuallyDrop() {{}}");
206 writeln!(out, "}};");
207 }
208
209 if builtin.maybe_uninit {
David Tolnay718ca0f2020-12-09 23:01:11 -0800210 include.cstddef = true;
David Tolnay3374d8d2020-10-31 22:18:45 -0700211 out.next_section();
212 writeln!(out, "template <typename T>");
213 writeln!(out, "union MaybeUninit {{");
214 writeln!(out, " T value;");
David Tolnay718ca0f2020-12-09 23:01:11 -0800215 writeln!(
216 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800217 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
David Tolnay718ca0f2020-12-09 23:01:11 -0800218 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700219 writeln!(out, " MaybeUninit() {{}}");
220 writeln!(out, " ~MaybeUninit() {{}}");
221 writeln!(out, "}};");
222 }
223
David Tolnay0c033e32020-11-01 15:15:48 -0800224 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700225
David Tolnay919085c2020-10-31 22:32:22 -0700226 if builtin.ptr_len {
David Tolnay12320e12020-12-09 23:09:36 -0800227 include.cstddef = true;
David Tolnay0c033e32020-11-01 15:15:48 -0800228 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700229 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800230 writeln!(out, " void *ptr;");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800231 writeln!(out, " ::std::size_t len;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700232 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800233 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700234 }
235
236 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
237 out.next_section();
238 writeln!(out, "template <>");
239 writeln!(out, "class impl<Str> final {{");
240 writeln!(out, "public:");
241 if builtin.rust_str_new_unchecked {
242 writeln!(
243 out,
244 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
245 );
246 writeln!(out, " Str str;");
247 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
248 writeln!(out, " str.len = repr.len;");
249 writeln!(out, " return str;");
250 writeln!(out, " }}");
251 }
252 if builtin.rust_str_repr {
253 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800254 writeln!(
255 out,
256 " return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
257 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700258 writeln!(out, " }}");
259 }
260 writeln!(out, "}};");
261 }
262
David Tolnay36aa9e02020-10-31 23:08:21 -0700263 if builtin.rust_slice_new || builtin.rust_slice_repr {
264 out.next_section();
265 writeln!(out, "template <typename T>");
266 writeln!(out, "class impl<Slice<T>> final {{");
267 writeln!(out, "public:");
268 if builtin.rust_slice_new {
269 writeln!(
270 out,
271 " static Slice<T> slice(repr::PtrLen repr) noexcept {{",
272 );
David Tolnayc5629f02020-11-23 18:32:46 -0800273 writeln!(out, " return {{static_cast<T *>(repr.ptr), repr.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700274 writeln!(out, " }}");
275 }
276 if builtin.rust_slice_repr {
David Tolnayc5629f02020-11-23 18:32:46 -0800277 include.type_traits = true;
David Tolnay36aa9e02020-10-31 23:08:21 -0700278 writeln!(
279 out,
280 " static repr::PtrLen repr(Slice<T> slice) noexcept {{",
281 );
David Tolnay5ce110e2020-12-27 02:45:53 -0800282 writeln!(out, " return repr::PtrLen{{slice.ptr, slice.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700283 writeln!(out, " }}");
284 }
285 writeln!(out, "}};");
286 }
287
David Tolnay3374d8d2020-10-31 22:18:45 -0700288 if builtin.rust_error {
289 out.next_section();
290 writeln!(out, "template <>");
291 writeln!(out, "class impl<Error> final {{");
292 writeln!(out, "public:");
293 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
294 writeln!(out, " Error error;");
295 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
296 writeln!(out, " error.len = repr.len;");
297 writeln!(out, " return error;");
298 writeln!(out, " }}");
299 writeln!(out, "}};");
300 }
301
David Tolnay53462762020-11-25 07:08:10 -0800302 if builtin.deleter_if {
303 out.next_section();
304 writeln!(out, "template <bool> struct deleter_if {{");
305 writeln!(out, " template <typename T> void operator()(T *) {{}}");
306 writeln!(out, "}};");
307 out.next_section();
308 writeln!(out, "template <> struct deleter_if<true> {{");
309 writeln!(
310 out,
311 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
312 );
313 writeln!(out, "}};");
314 }
315
David Tolnay0c033e32020-11-01 15:15:48 -0800316 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800317 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700318
319 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800320 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700321 include.exception = true;
322 include.type_traits = true;
323 include.utility = true;
324 writeln!(out, "class missing {{}};");
325 writeln!(out, "missing trycatch(...);");
326 writeln!(out);
327 writeln!(out, "template <typename Try, typename Fail>");
328 writeln!(out, "static typename ::std::enable_if<");
329 writeln!(
330 out,
331 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
332 );
333 writeln!(out, " missing>::value>::type");
334 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
335 writeln!(out, " func();");
336 writeln!(out, "}} catch (const ::std::exception &e) {{");
337 writeln!(out, " fail(e.what());");
338 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800339 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700340 }
341
David Tolnay0c033e32020-11-01 15:15:48 -0800342 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800343
344 if builtin.exception {
David Tolnay12320e12020-12-09 23:09:36 -0800345 include.cstddef = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800346 out.begin_block(Block::ExternC);
347 writeln!(
348 out,
David Tolnaybe3cbf72020-12-12 22:12:07 -0800349 "const char *cxxbridge1$exception(const char *, ::std::size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800350 );
351 out.end_block(Block::ExternC);
352 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700353}