Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-compile-type.h"
20 : : #include "rust-compile-expr.h"
21 : : #include "rust-constexpr.h"
22 : : #include "rust-gcc.h"
23 : :
24 : : #include "tree.h"
25 : :
26 : : namespace Rust {
27 : : namespace Compile {
28 : :
29 : : static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
30 : :
31 : 181395 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
32 : 181395 : : ctx (ctx), trait_object_mode (trait_object_mode),
33 : 181395 : translated (error_mark_node)
34 : 181395 : {}
35 : :
36 : : tree
37 : 181395 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
38 : : bool trait_object_mode)
39 : : {
40 : 181395 : TyTyResolveCompile compiler (ctx, trait_object_mode);
41 : 181395 : const TyTy::BaseType *destructured = ty->destructure ();
42 : 181395 : destructured->accept_vis (compiler);
43 : :
44 : 181395 : if (compiler.translated != error_mark_node
45 : 181395 : && TYPE_NAME (compiler.translated) != NULL)
46 : : {
47 : : // canonicalize the type
48 : 160074 : compiler.translated = ctx->insert_compiled_type (compiler.translated);
49 : : }
50 : :
51 : 181395 : return compiler.translated;
52 : : }
53 : :
54 : : // see: gcc/c/c-decl.cc:8230-8241
55 : : // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
56 : : tree
57 : 2128 : TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx)
58 : : {
59 : : // static tree enum_node = NULL_TREE;
60 : : // if (enum_node == NULL_TREE)
61 : : // {
62 : : // enum_node = make_node (ENUMERAL_TYPE);
63 : : // SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node));
64 : : // SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node));
65 : : // TYPE_USER_ALIGN (enum_node) = 0;
66 : : // TYPE_UNSIGNED (enum_node) = 1;
67 : : // TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node);
68 : : // TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node);
69 : : // TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node);
70 : :
71 : : // // tree identifier = ctx->get_backend ()->get_identifier_node
72 : : // // ("enumeral"); tree enum_decl
73 : : // // = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier,
74 : : // enum_node);
75 : : // // TYPE_NAME (enum_node) = enum_decl;
76 : : // }
77 : : // return enum_node;
78 : :
79 : 2128 : static tree enum_node = NULL_TREE;
80 : 2128 : if (enum_node == NULL_TREE)
81 : : {
82 : : // equivalent to isize
83 : 106 : enum_node = Backend::named_type (
84 : : "enumeral", Backend::integer_type (false, Backend::get_pointer_size ()),
85 : : BUILTINS_LOCATION);
86 : : }
87 : 2128 : return enum_node;
88 : : }
89 : :
90 : : tree
91 : 19460 : TyTyResolveCompile::get_unit_type (Context *ctx)
92 : : {
93 : 19460 : static tree unit_type;
94 : 19460 : if (unit_type == nullptr)
95 : : {
96 : 3313 : auto unit_type_node = Backend::struct_type ({});
97 : 3313 : unit_type = Backend::named_type ("()", unit_type_node, BUILTINS_LOCATION);
98 : : }
99 : 19460 : return unit_type;
100 : : }
101 : :
102 : : void
103 : 0 : TyTyResolveCompile::visit (const TyTy::ErrorType &)
104 : : {
105 : 0 : translated = error_mark_node;
106 : 0 : }
107 : :
108 : : void
109 : 16 : TyTyResolveCompile::visit (const TyTy::InferType &type)
110 : : {
111 : 16 : const TyTy::BaseType *orig = &type;
112 : 16 : TyTy::BaseType *lookup = nullptr;
113 : 16 : bool ok = ctx->get_tyctx ()->lookup_type (type.get_ref (), &lookup);
114 : 16 : if (!ok)
115 : : {
116 : 0 : translated = error_mark_node;
117 : 0 : return;
118 : : }
119 : :
120 : 16 : if (orig == lookup)
121 : : {
122 : 0 : translated = error_mark_node;
123 : 0 : return;
124 : : }
125 : :
126 : 16 : translated = TyTyResolveCompile::compile (ctx, lookup);
127 : : }
128 : :
129 : : void
130 : 0 : TyTyResolveCompile::visit (const TyTy::ParamType &)
131 : : {
132 : 0 : translated = error_mark_node;
133 : 0 : }
134 : :
135 : : void
136 : 0 : TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
137 : : {
138 : 0 : translated = error_mark_node;
139 : 0 : }
140 : :
141 : : void
142 : 0 : TyTyResolveCompile::visit (const TyTy::PlaceholderType &type)
143 : : {
144 : 0 : translated = error_mark_node;
145 : 0 : }
146 : :
147 : : void
148 : 181 : TyTyResolveCompile::visit (const TyTy::ClosureType &type)
149 : : {
150 : 181 : auto mappings = ctx->get_mappings ();
151 : :
152 : 181 : std::vector<Backend::typed_identifier> fields;
153 : :
154 : 181 : size_t i = 0;
155 : 216 : for (const auto &capture : type.get_captures ())
156 : : {
157 : : // lookup the HirId
158 : 35 : HirId ref = UNKNOWN_HIRID;
159 : 35 : bool ok = mappings->lookup_node_to_hir (capture, &ref);
160 : 35 : rust_assert (ok);
161 : :
162 : : // lookup the var decl type
163 : 35 : TyTy::BaseType *lookup = nullptr;
164 : 35 : bool found = ctx->get_tyctx ()->lookup_type (ref, &lookup);
165 : 35 : rust_assert (found);
166 : :
167 : : // FIXME get the var pattern name
168 : 35 : std::string mappings_name = "capture_" + std::to_string (i);
169 : :
170 : : // FIXME
171 : : // this should be based on the closure move-ability
172 : 35 : tree decl_type = TyTyResolveCompile::compile (ctx, lookup);
173 : 35 : tree capture_type = build_reference_type (decl_type);
174 : 35 : fields.push_back (Backend::typed_identifier (mappings_name, capture_type,
175 : 35 : type.get_ident ().locus));
176 : 35 : }
177 : :
178 : 181 : tree type_record = Backend::struct_type (fields);
179 : 181 : RS_CLOSURE_FLAG (type_record) = 1;
180 : :
181 : 181 : std::string named_struct_str
182 : 362 : = type.get_ident ().path.get () + "::{{closure}}";
183 : 181 : translated = Backend::named_type (named_struct_str, type_record,
184 : 181 : type.get_ident ().locus);
185 : 181 : }
186 : :
187 : : void
188 : 10547 : TyTyResolveCompile::visit (const TyTy::FnType &type)
189 : : {
190 : 10547 : Backend::typed_identifier receiver;
191 : 10547 : std::vector<Backend::typed_identifier> parameters;
192 : 10547 : std::vector<Backend::typed_identifier> results;
193 : :
194 : : // we can only return unit-type if its not the C ABI because it will expect
195 : : // void
196 : 10547 : auto hir_type = type.get_return_type ()->destructure ();
197 : 10547 : bool return_is_unit = hir_type->is_unit ();
198 : 10547 : bool is_c_abi = type.get_abi () == ABI::C;
199 : 10547 : bool should_be_void = is_c_abi && return_is_unit;
200 : 10547 : if (!should_be_void)
201 : : {
202 : 9821 : auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
203 : 9821 : location_t return_type_locus
204 : 9821 : = ctx->get_mappings ()->lookup_location (hir_type->get_ref ());
205 : 19642 : results.push_back (
206 : 19642 : Backend::typed_identifier ("_", ret, return_type_locus));
207 : : }
208 : :
209 : 18135 : for (auto ¶m_pair : type.get_params ())
210 : : {
211 : 7588 : auto param_tyty = param_pair.second;
212 : 7588 : auto compiled_param_type
213 : 7588 : = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
214 : :
215 : 7588 : auto compiled_param = Backend::typed_identifier (
216 : 7588 : param_pair.first->as_string (), compiled_param_type,
217 : 15176 : ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()));
218 : :
219 : 7588 : parameters.push_back (compiled_param);
220 : 7588 : }
221 : :
222 : 10547 : if (!type.is_variadic ())
223 : 9850 : translated = Backend::function_type (receiver, parameters, results, NULL,
224 : 9850 : type.get_ident ().locus);
225 : : else
226 : 697 : translated
227 : 697 : = Backend::function_type_variadic (receiver, parameters, results, NULL,
228 : 697 : type.get_ident ().locus);
229 : 10547 : }
230 : :
231 : : void
232 : 45 : TyTyResolveCompile::visit (const TyTy::FnPtr &type)
233 : : {
234 : 45 : tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
235 : :
236 : 45 : std::vector<tree> parameters;
237 : :
238 : 45 : auto ¶ms = type.get_params ();
239 : 84 : for (auto &p : params)
240 : : {
241 : 39 : tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
242 : 39 : parameters.push_back (pty);
243 : : }
244 : :
245 : 135 : translated = Backend::function_ptr_type (result_type, parameters,
246 : 45 : type.get_ident ().locus);
247 : 45 : }
248 : :
249 : : void
250 : 7503 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
251 : : {
252 : 7503 : tree type_record = error_mark_node;
253 : 7503 : if (!type.is_enum ())
254 : : {
255 : 6662 : rust_assert (type.number_of_variants () == 1);
256 : :
257 : 6662 : TyTy::VariantDef &variant = *type.get_variants ().at (0);
258 : 6662 : std::vector<Backend::typed_identifier> fields;
259 : 20090 : for (size_t i = 0; i < variant.num_fields (); i++)
260 : : {
261 : 13428 : const TyTy::StructFieldType *field = variant.get_field_at_index (i);
262 : 13428 : tree compiled_field_ty
263 : 13428 : = TyTyResolveCompile::compile (ctx, field->get_field_type ());
264 : :
265 : 13428 : Backend::typed_identifier f (field->get_name (), compiled_field_ty,
266 : 13428 : ctx->get_mappings ()->lookup_location (
267 : 26856 : type.get_ty_ref ()));
268 : 13428 : fields.push_back (std::move (f));
269 : 13428 : }
270 : :
271 : 6662 : type_record = type.is_union () ? Backend::union_type (fields)
272 : 6509 : : Backend::struct_type (fields);
273 : 6662 : }
274 : : else
275 : : {
276 : : // see:
277 : : // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
278 : : //
279 : : // enums are actually a big union so for example the rust enum:
280 : : //
281 : : // enum AnEnum {
282 : : // A,
283 : : // B,
284 : : // C (char),
285 : : // D { x: i64, y: i64 },
286 : : // }
287 : : //
288 : : // we actually turn this into
289 : : //
290 : : // union {
291 : : // struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
292 : : // struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
293 : : // struct C { int RUST$ENUM$DISR; char __0; };
294 : : // struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
295 : : // }
296 : : //
297 : : // Ada, qual_union_types might still work for this but I am not 100% sure.
298 : : // I ran into some issues lets reuse our normal union and ask Ada people
299 : : // about it.
300 : :
301 : 841 : std::vector<tree> variant_records;
302 : 2969 : for (auto &variant : type.get_variants ())
303 : : {
304 : 2128 : std::vector<Backend::typed_identifier> fields;
305 : :
306 : : // add in the qualifier field for the variant
307 : 2128 : tree enumeral_type
308 : 2128 : = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
309 : 2128 : Backend::typed_identifier f (RUST_ENUM_DISR_FIELD_NAME, enumeral_type,
310 : 2128 : ctx->get_mappings ()->lookup_location (
311 : 2128 : variant->get_id ()));
312 : 2128 : fields.push_back (std::move (f));
313 : :
314 : : // compile the rest of the fields
315 : 3453 : for (size_t i = 0; i < variant->num_fields (); i++)
316 : : {
317 : 1325 : const TyTy::StructFieldType *field
318 : 1325 : = variant->get_field_at_index (i);
319 : 1325 : tree compiled_field_ty
320 : 1325 : = TyTyResolveCompile::compile (ctx, field->get_field_type ());
321 : :
322 : 1325 : std::string field_name = field->get_name ();
323 : 1325 : if (variant->get_variant_type ()
324 : : == TyTy::VariantDef::VariantType::TUPLE)
325 : 821 : field_name = "__" + field->get_name ();
326 : :
327 : 1325 : Backend::typed_identifier f (
328 : : field_name, compiled_field_ty,
329 : 1325 : ctx->get_mappings ()->lookup_location (type.get_ty_ref ()));
330 : 1325 : fields.push_back (std::move (f));
331 : 1325 : }
332 : :
333 : 2128 : tree variant_record = Backend::struct_type (fields);
334 : 2128 : tree named_variant_record
335 : 2128 : = Backend::named_type (variant->get_ident ().path.get (),
336 : 4256 : variant_record, variant->get_ident ().locus);
337 : :
338 : : // set the qualifier to be a builtin
339 : 2128 : DECL_ARTIFICIAL (TYPE_FIELDS (variant_record)) = 1;
340 : :
341 : : // add them to the list
342 : 2128 : variant_records.push_back (named_variant_record);
343 : 2128 : }
344 : :
345 : : // now we need to make the actual union, but first we need to make
346 : : // named_type TYPE_DECL's out of the variants
347 : :
348 : 841 : size_t i = 0;
349 : 841 : std::vector<Backend::typed_identifier> enum_fields;
350 : 2969 : for (auto &variant_record : variant_records)
351 : : {
352 : 2128 : TyTy::VariantDef *variant = type.get_variants ().at (i++);
353 : 2128 : std::string implicit_variant_name = variant->get_identifier ();
354 : :
355 : 2128 : Backend::typed_identifier f (implicit_variant_name, variant_record,
356 : 2128 : ctx->get_mappings ()->lookup_location (
357 : 2128 : type.get_ty_ref ()));
358 : 2128 : enum_fields.push_back (std::move (f));
359 : 2128 : }
360 : :
361 : : // finally make the union or the enum
362 : 841 : type_record = Backend::union_type (enum_fields);
363 : 841 : }
364 : :
365 : : // Handle repr options
366 : : // TODO: "packed" should only narrow type alignment and "align" should only
367 : : // widen it. Do we need to check and enforce this here, or is it taken care of
368 : : // later on in the gcc middle-end?
369 : 7503 : TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
370 : 7503 : if (repr.pack)
371 : : {
372 : 8 : TYPE_PACKED (type_record) = 1;
373 : 8 : if (repr.pack > 1)
374 : : {
375 : 4 : SET_TYPE_ALIGN (type_record, repr.pack * 8);
376 : 4 : TYPE_USER_ALIGN (type_record) = 1;
377 : : }
378 : : }
379 : 7495 : else if (repr.align)
380 : : {
381 : 8 : SET_TYPE_ALIGN (type_record, repr.align * 8);
382 : 8 : TYPE_USER_ALIGN (type_record) = 1;
383 : : }
384 : :
385 : 7503 : std::string named_struct_str
386 : 7503 : = type.get_ident ().path.get () + type.subst_as_string ();
387 : 7503 : translated = Backend::named_type (named_struct_str, type_record,
388 : 7503 : type.get_ident ().locus);
389 : 7503 : }
390 : :
391 : : void
392 : 12478 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
393 : : {
394 : 12478 : if (type.num_fields () == 0)
395 : : {
396 : 11222 : translated = get_unit_type (ctx);
397 : 11222 : return;
398 : : }
399 : :
400 : : // create implicit struct
401 : 1256 : std::vector<Backend::typed_identifier> fields;
402 : 3921 : for (size_t i = 0; i < type.num_fields (); i++)
403 : : {
404 : 2665 : TyTy::BaseType *field = type.get_field (i);
405 : 2665 : tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
406 : :
407 : : // rustc uses the convention __N, where N is an integer, to
408 : : // name the fields of a tuple. We follow this as well,
409 : : // because this is used by GDB. One further reason to prefer
410 : : // this, rather than simply emitting the integer, is that this
411 : : // approach makes it simpler to use a C-only debugger, or
412 : : // GDB's C mode, when debugging Rust.
413 : 5330 : Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty,
414 : 2665 : ctx->get_mappings ()->lookup_location (
415 : 5330 : type.get_ty_ref ()));
416 : 2665 : fields.push_back (std::move (f));
417 : 2665 : }
418 : :
419 : 1256 : tree struct_type_record = Backend::struct_type (fields);
420 : 1256 : translated = Backend::named_type (type.as_string (), struct_type_record,
421 : 1256 : type.get_ident ().locus);
422 : 1256 : }
423 : :
424 : : void
425 : 2337 : TyTyResolveCompile::visit (const TyTy::ArrayType &type)
426 : : {
427 : 2337 : tree element_type
428 : 2337 : = TyTyResolveCompile::compile (ctx, type.get_element_type ());
429 : :
430 : 2337 : ctx->push_const_context ();
431 : 2337 : tree capacity_expr = CompileExpr::Compile (&type.get_capacity_expr (), ctx);
432 : 2337 : ctx->pop_const_context ();
433 : :
434 : 2337 : tree folded_capacity_expr = fold_expr (capacity_expr);
435 : :
436 : 2337 : translated = Backend::array_type (element_type, folded_capacity_expr);
437 : 2337 : }
438 : :
439 : : void
440 : 73 : TyTyResolveCompile::visit (const TyTy::SliceType &type)
441 : : {
442 : 73 : tree type_record = create_slice_type_record (type);
443 : :
444 : 73 : std::string named_struct_str
445 : 146 : = std::string ("[") + type.get_element_type ()->get_name () + "]";
446 : 73 : translated = Backend::named_type (named_struct_str, type_record,
447 : 73 : type.get_ident ().locus);
448 : 73 : }
449 : :
450 : : void
451 : 6160 : TyTyResolveCompile::visit (const TyTy::BoolType &)
452 : : {
453 : 6160 : translated
454 : 6160 : = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
455 : 6160 : }
456 : :
457 : : void
458 : 48687 : TyTyResolveCompile::visit (const TyTy::IntType &type)
459 : : {
460 : 48687 : switch (type.get_int_kind ())
461 : : {
462 : 6954 : case TyTy::IntType::I8:
463 : 6954 : translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
464 : : BUILTINS_LOCATION);
465 : 6954 : return;
466 : :
467 : 3811 : case TyTy::IntType::I16:
468 : 3811 : translated
469 : 3811 : = Backend::named_type ("i16", Backend::integer_type (false, 16),
470 : : BUILTINS_LOCATION);
471 : 3811 : return;
472 : :
473 : 30115 : case TyTy::IntType::I32:
474 : 30115 : translated
475 : 30115 : = Backend::named_type ("i32", Backend::integer_type (false, 32),
476 : : BUILTINS_LOCATION);
477 : 30115 : return;
478 : :
479 : 3927 : case TyTy::IntType::I64:
480 : 3927 : translated
481 : 3927 : = Backend::named_type ("i64", Backend::integer_type (false, 64),
482 : : BUILTINS_LOCATION);
483 : 3927 : return;
484 : :
485 : 3880 : case TyTy::IntType::I128:
486 : 3880 : translated
487 : 3880 : = Backend::named_type ("i128", Backend::integer_type (false, 128),
488 : : BUILTINS_LOCATION);
489 : 3880 : return;
490 : : }
491 : : }
492 : :
493 : : void
494 : 29963 : TyTyResolveCompile::visit (const TyTy::UintType &type)
495 : : {
496 : 29963 : switch (type.get_uint_kind ())
497 : : {
498 : 8114 : case TyTy::UintType::U8:
499 : 8114 : translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
500 : : BUILTINS_LOCATION);
501 : 8114 : return;
502 : :
503 : 5202 : case TyTy::UintType::U16:
504 : 5202 : translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
505 : : BUILTINS_LOCATION);
506 : 5202 : return;
507 : :
508 : 7349 : case TyTy::UintType::U32:
509 : 7349 : translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
510 : : BUILTINS_LOCATION);
511 : 7349 : return;
512 : :
513 : 5810 : case TyTy::UintType::U64:
514 : 5810 : translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
515 : : BUILTINS_LOCATION);
516 : 5810 : return;
517 : :
518 : 3488 : case TyTy::UintType::U128:
519 : 3488 : translated
520 : 3488 : = Backend::named_type ("u128", Backend::integer_type (true, 128),
521 : : BUILTINS_LOCATION);
522 : 3488 : return;
523 : : }
524 : : }
525 : :
526 : : void
527 : 11418 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
528 : : {
529 : 11418 : switch (type.get_float_kind ())
530 : : {
531 : 5549 : case TyTy::FloatType::F32:
532 : 5549 : translated = Backend::named_type ("f32", Backend::float_type (32),
533 : : BUILTINS_LOCATION);
534 : 5549 : return;
535 : :
536 : 5869 : case TyTy::FloatType::F64:
537 : 5869 : translated = Backend::named_type ("f64", Backend::float_type (64),
538 : : BUILTINS_LOCATION);
539 : 5869 : return;
540 : : }
541 : : }
542 : :
543 : : void
544 : 21863 : TyTyResolveCompile::visit (const TyTy::USizeType &)
545 : : {
546 : 21863 : translated
547 : 21863 : = Backend::named_type ("usize",
548 : : Backend::integer_type (true,
549 : : Backend::get_pointer_size ()),
550 : : BUILTINS_LOCATION);
551 : 21863 : }
552 : :
553 : : void
554 : 5059 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
555 : : {
556 : 5059 : translated
557 : 5059 : = Backend::named_type ("isize",
558 : : Backend::integer_type (false,
559 : : Backend::get_pointer_size ()),
560 : : BUILTINS_LOCATION);
561 : 5059 : }
562 : :
563 : : void
564 : 4101 : TyTyResolveCompile::visit (const TyTy::CharType &)
565 : : {
566 : 4101 : translated
567 : 4101 : = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
568 : 4101 : }
569 : :
570 : : void
571 : 6950 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
572 : : {
573 : 6950 : const TyTy::SliceType *slice = nullptr;
574 : 6950 : const TyTy::StrType *str = nullptr;
575 : 6950 : const TyTy::DynamicObjectType *dyn = nullptr;
576 : 6950 : if (type.is_dyn_slice_type (&slice))
577 : : {
578 : 463 : tree type_record = create_slice_type_record (*slice);
579 : 463 : std::string dyn_slice_type_str
580 : 1389 : = std::string (type.is_mutable () ? "&mut " : "&") + "["
581 : 1389 : + slice->get_element_type ()->get_name () + "]";
582 : :
583 : 463 : translated = Backend::named_type (dyn_slice_type_str, type_record,
584 : : slice->get_locus ());
585 : :
586 : 463 : return;
587 : 463 : }
588 : 6487 : else if (type.is_dyn_str_type (&str))
589 : : {
590 : 2526 : tree type_record = create_str_type_record (*str);
591 : 2526 : std::string dyn_str_type_str
592 : 7578 : = std::string (type.is_mutable () ? "&mut " : "&") + "str";
593 : :
594 : 2526 : translated = Backend::named_type (dyn_str_type_str, type_record,
595 : : str->get_locus ());
596 : :
597 : 2526 : return;
598 : 2526 : }
599 : 3961 : else if (type.is_dyn_obj_type (&dyn))
600 : : {
601 : 342 : tree type_record = create_dyn_obj_record (*dyn);
602 : 342 : std::string dyn_str_type_str
603 : 684 : = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
604 : :
605 : 342 : translated = Backend::named_type (dyn_str_type_str, type_record,
606 : : dyn->get_locus ());
607 : :
608 : 342 : return;
609 : 342 : }
610 : :
611 : 3619 : tree base_compiled_type
612 : 3619 : = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
613 : 3619 : if (type.is_mutable ())
614 : : {
615 : 325 : translated = Backend::reference_type (base_compiled_type);
616 : : }
617 : : else
618 : : {
619 : 3294 : auto base = Backend::immutable_type (base_compiled_type);
620 : 3294 : translated = Backend::reference_type (base);
621 : : }
622 : : }
623 : :
624 : : void
625 : 7275 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
626 : : {
627 : 7275 : const TyTy::SliceType *slice = nullptr;
628 : 7275 : const TyTy::StrType *str = nullptr;
629 : 7275 : const TyTy::DynamicObjectType *dyn = nullptr;
630 : 7275 : if (type.is_dyn_slice_type (&slice))
631 : : {
632 : 505 : tree type_record = create_slice_type_record (*slice);
633 : 505 : std::string dyn_slice_type_str
634 : 1466 : = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
635 : 1515 : + slice->get_element_type ()->get_name () + "]";
636 : :
637 : 505 : translated = Backend::named_type (dyn_slice_type_str, type_record,
638 : : slice->get_locus ());
639 : :
640 : 505 : return;
641 : 505 : }
642 : 6770 : else if (type.is_dyn_str_type (&str))
643 : : {
644 : 1997 : tree type_record = create_str_type_record (*str);
645 : 1997 : std::string dyn_str_type_str
646 : 5991 : = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
647 : :
648 : 1997 : translated = Backend::named_type (dyn_str_type_str, type_record,
649 : : str->get_locus ());
650 : :
651 : 1997 : return;
652 : 1997 : }
653 : 4773 : else if (type.is_dyn_obj_type (&dyn))
654 : : {
655 : 0 : tree type_record = create_dyn_obj_record (*dyn);
656 : 0 : std::string dyn_str_type_str
657 : 0 : = std::string (type.is_mutable () ? "*mut " : "*const ")
658 : 0 : + dyn->get_name ();
659 : :
660 : 0 : translated = Backend::named_type (dyn_str_type_str, type_record,
661 : : dyn->get_locus ());
662 : :
663 : 0 : return;
664 : 0 : }
665 : :
666 : 4773 : tree base_compiled_type
667 : 4773 : = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
668 : 4773 : if (type.is_mutable ())
669 : : {
670 : 722 : translated = Backend::pointer_type (base_compiled_type);
671 : : }
672 : : else
673 : : {
674 : 4051 : auto base = Backend::immutable_type (base_compiled_type);
675 : 4051 : translated = Backend::pointer_type (base);
676 : : }
677 : : }
678 : :
679 : : void
680 : 3313 : TyTyResolveCompile::visit (const TyTy::StrType &type)
681 : : {
682 : 3313 : tree raw_str = create_str_type_record (type);
683 : 3313 : translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
684 : 3313 : }
685 : :
686 : : void
687 : 3426 : TyTyResolveCompile::visit (const TyTy::NeverType &)
688 : : {
689 : 3426 : translated = get_unit_type (ctx);
690 : 3426 : }
691 : :
692 : : void
693 : 0 : TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
694 : : {
695 : 0 : if (trait_object_mode)
696 : : {
697 : 0 : translated = Backend::integer_type (true, Backend::get_pointer_size ());
698 : 0 : return;
699 : : }
700 : :
701 : 0 : tree type_record = create_dyn_obj_record (type);
702 : 0 : translated = Backend::named_type (type.get_name (), type_record,
703 : 0 : type.get_ident ().locus);
704 : : }
705 : :
706 : : tree
707 : 342 : TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
708 : : {
709 : : // create implicit struct
710 : 342 : auto items = type.get_object_items ();
711 : 342 : std::vector<Backend::typed_identifier> fields;
712 : :
713 : 342 : tree uint = Backend::integer_type (true, Backend::get_pointer_size ());
714 : 342 : tree uintptr_ty = build_pointer_type (uint);
715 : :
716 : 342 : Backend::typed_identifier f ("pointer", uintptr_ty,
717 : 342 : ctx->get_mappings ()->lookup_location (
718 : 342 : type.get_ty_ref ()));
719 : 342 : fields.push_back (std::move (f));
720 : :
721 : 342 : tree vtable_size = build_int_cst (size_type_node, items.size ());
722 : 342 : tree vtable_type = Backend::array_type (uintptr_ty, vtable_size);
723 : 342 : Backend::typed_identifier vtf ("vtable", vtable_type,
724 : 342 : ctx->get_mappings ()->lookup_location (
725 : 342 : type.get_ty_ref ()));
726 : 342 : fields.push_back (std::move (vtf));
727 : :
728 : 342 : tree record = Backend::struct_type (fields);
729 : 342 : RS_DST_FLAG (record) = 1;
730 : 342 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
731 : :
732 : 342 : return record;
733 : 342 : }
734 : :
735 : : tree
736 : 1041 : TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
737 : : {
738 : : // lookup usize
739 : 1041 : TyTy::BaseType *usize = nullptr;
740 : 1041 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
741 : 1041 : rust_assert (ok);
742 : :
743 : 1041 : tree element_type
744 : 1041 : = TyTyResolveCompile::compile (ctx, type.get_element_type ());
745 : 1041 : tree data_field_ty = build_pointer_type (element_type);
746 : 1041 : Backend::typed_identifier data_field ("data", data_field_ty,
747 : 1041 : type.get_locus ());
748 : :
749 : 1041 : tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
750 : 1041 : Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
751 : :
752 : 3123 : tree record = Backend::struct_type ({data_field, len_field});
753 : 1041 : RS_DST_FLAG (record) = 1;
754 : 1041 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
755 : :
756 : 1041 : return record;
757 : 1041 : }
758 : :
759 : : tree
760 : 7836 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
761 : : {
762 : : // lookup usize
763 : 7836 : TyTy::BaseType *usize = nullptr;
764 : 7836 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
765 : 7836 : rust_assert (ok);
766 : :
767 : 7836 : tree char_ptr = build_pointer_type (char_type_node);
768 : 7836 : tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
769 : :
770 : 7836 : tree element_type = const_char_type;
771 : 7836 : tree data_field_ty = build_pointer_type (element_type);
772 : 7836 : Backend::typed_identifier data_field ("data", data_field_ty,
773 : 7836 : type.get_locus ());
774 : :
775 : 7836 : tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
776 : 7836 : Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
777 : :
778 : 23508 : tree record = Backend::struct_type ({data_field, len_field});
779 : 7836 : RS_DST_FLAG (record) = 1;
780 : 7836 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
781 : :
782 : 7836 : return record;
783 : 7836 : }
784 : :
785 : : } // namespace Compile
786 : : } // namespace Rust
|