Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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-constexpr.h"
21 : : #include "rust-compile-base.h"
22 : :
23 : : #include "tree.h"
24 : : #include "fold-const.h"
25 : : #include "stor-layout.h"
26 : :
27 : : namespace Rust {
28 : : namespace Compile {
29 : :
30 : : static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
31 : :
32 : 377769 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
33 : 377769 : : ctx (ctx), trait_object_mode (trait_object_mode),
34 : 377769 : translated (error_mark_node)
35 : 377769 : {}
36 : :
37 : : tree
38 : 377769 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
39 : : bool trait_object_mode)
40 : : {
41 : 377769 : TyTyResolveCompile compiler (ctx, trait_object_mode);
42 : 377769 : const TyTy::BaseType *destructured = ty->destructure ();
43 : 377769 : destructured->accept_vis (compiler);
44 : :
45 : 377769 : if (compiler.translated != error_mark_node
46 : 377769 : && TYPE_NAME (compiler.translated) != NULL)
47 : : {
48 : : // canonicalize the type
49 : 338286 : compiler.translated = ctx->insert_compiled_type (compiler.translated);
50 : : }
51 : :
52 : 377769 : return compiler.translated;
53 : : }
54 : :
55 : : // see: gcc/c/c-decl.cc:8230-8241
56 : : // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
57 : : tree
58 : 6351 : TyTyResolveCompile::get_implicit_enumeral_node_type (TyTy::BaseType *repr)
59 : : {
60 : : // static tree enum_node = NULL_TREE;
61 : : // if (enum_node == NULL_TREE)
62 : : // {
63 : : // enum_node = make_node (ENUMERAL_TYPE);
64 : : // SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node));
65 : : // SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node));
66 : : // TYPE_USER_ALIGN (enum_node) = 0;
67 : : // TYPE_UNSIGNED (enum_node) = 1;
68 : : // TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node);
69 : : // TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node);
70 : : // TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node);
71 : :
72 : : // // tree identifier = ctx->get_backend ()->get_identifier_node
73 : : // // ("enumeral"); tree enum_decl
74 : : // // = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier,
75 : : // enum_node);
76 : : // // TYPE_NAME (enum_node) = enum_decl;
77 : : // }
78 : : // return enum_node;
79 : :
80 : 6351 : return compile (ctx, repr);
81 : : }
82 : :
83 : : tree
84 : 33665 : TyTyResolveCompile::get_unit_type (Context *ctx)
85 : : {
86 : 33665 : static tree unit_type;
87 : 33665 : if (unit_type == nullptr)
88 : : {
89 : 4118 : auto cn = ctx->get_mappings ().get_current_crate ();
90 : 4118 : auto &c = ctx->get_mappings ().get_ast_crate (cn);
91 : 4118 : location_t locus = BUILTINS_LOCATION;
92 : 4118 : if (c.items.size () > 0)
93 : : {
94 : 4117 : auto &item = c.items[0];
95 : 4117 : locus = item->get_locus ();
96 : : }
97 : :
98 : 4118 : auto unit_type_node = Backend::struct_type ({});
99 : 4118 : unit_type = Backend::named_type ("()", unit_type_node, locus);
100 : : }
101 : 33665 : return unit_type;
102 : : }
103 : :
104 : : void
105 : 0 : TyTyResolveCompile::visit (const TyTy::ErrorType &)
106 : : {
107 : 0 : translated = error_mark_node;
108 : 0 : }
109 : :
110 : : void
111 : 477 : TyTyResolveCompile::visit (const TyTy::InferType &type)
112 : : {
113 : 477 : const TyTy::BaseType *orig = &type;
114 : 477 : TyTy::BaseType *lookup = nullptr;
115 : 477 : bool ok = ctx->get_tyctx ()->lookup_type (type.get_ref (), &lookup);
116 : 477 : if (!ok)
117 : : {
118 : 0 : translated = error_mark_node;
119 : 4 : return;
120 : : }
121 : :
122 : 477 : if (orig == lookup)
123 : : {
124 : 4 : TyTy::BaseType *def = nullptr;
125 : 4 : if (type.default_type (&def))
126 : : {
127 : 4 : translated = TyTyResolveCompile::compile (ctx, def);
128 : 4 : return;
129 : : }
130 : :
131 : 0 : translated = error_mark_node;
132 : 0 : return;
133 : : }
134 : :
135 : 473 : translated = TyTyResolveCompile::compile (ctx, lookup);
136 : : }
137 : :
138 : : void
139 : 0 : TyTyResolveCompile::visit (const TyTy::ParamType &)
140 : : {
141 : 0 : translated = error_mark_node;
142 : 0 : }
143 : :
144 : : void
145 : 0 : TyTyResolveCompile::visit (const TyTy::ConstType &)
146 : : {
147 : 0 : translated = error_mark_node;
148 : 0 : }
149 : :
150 : : void
151 : 0 : TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
152 : : {
153 : 0 : translated = error_mark_node;
154 : 0 : }
155 : :
156 : : void
157 : 0 : TyTyResolveCompile::visit (const TyTy::PlaceholderType &type)
158 : : {
159 : 0 : translated = error_mark_node;
160 : 0 : }
161 : :
162 : : void
163 : 239 : TyTyResolveCompile::visit (const TyTy::ClosureType &type)
164 : : {
165 : 239 : auto &mappings = ctx->get_mappings ();
166 : :
167 : 239 : std::vector<Backend::typed_identifier> fields;
168 : :
169 : 239 : size_t i = 0;
170 : 330 : for (const auto &capture : type.get_captures ())
171 : : {
172 : : // lookup the HirId
173 : 91 : tl::optional<HirId> hid = mappings.lookup_node_to_hir (capture);
174 : 91 : rust_assert (hid.has_value ());
175 : 91 : auto ref = hid.value ();
176 : :
177 : : // lookup the var decl type
178 : 91 : TyTy::BaseType *lookup = nullptr;
179 : 91 : bool found = ctx->get_tyctx ()->lookup_type (ref, &lookup);
180 : 91 : rust_assert (found);
181 : :
182 : : // FIXME get the var pattern name
183 : 91 : std::string mappings_name = "capture_" + std::to_string (i);
184 : :
185 : : // FIXME
186 : : // this should be based on the closure move-ability
187 : 91 : tree decl_type = TyTyResolveCompile::compile (ctx, lookup);
188 : 91 : tree capture_type = build_reference_type (decl_type);
189 : 91 : fields.push_back (Backend::typed_identifier (mappings_name, capture_type,
190 : 91 : type.get_ident ().locus));
191 : 91 : }
192 : :
193 : 239 : tree type_record = Backend::struct_type (fields);
194 : 239 : RS_CLOSURE_FLAG (type_record) = 1;
195 : :
196 : 239 : std::string named_struct_str
197 : 478 : = type.get_ident ().path.get () + "::{{closure}}";
198 : 239 : translated = Backend::named_type (named_struct_str, type_record,
199 : 239 : type.get_ident ().locus);
200 : 239 : }
201 : :
202 : : void
203 : 15987 : TyTyResolveCompile::visit (const TyTy::FnType &type)
204 : : {
205 : 15987 : Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
206 : 15987 : std::vector<Backend::typed_identifier> parameters;
207 : 15987 : std::vector<Backend::typed_identifier> results;
208 : :
209 : : // we can only return unit-type if its not the C ABI because it will expect
210 : : // void
211 : 15987 : auto hir_type = type.get_return_type ()->destructure ();
212 : 15987 : bool return_is_unit = hir_type->is_unit ();
213 : 15987 : bool is_c_abi = type.get_abi () == ABI::C;
214 : 15987 : bool should_be_void = is_c_abi && return_is_unit;
215 : 15987 : if (!should_be_void)
216 : : {
217 : 14992 : auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
218 : 14992 : location_t return_type_locus
219 : 14992 : = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
220 : 29984 : results.push_back (
221 : 14992 : Backend::typed_identifier ("_", ret, return_type_locus));
222 : : }
223 : :
224 : 32081 : for (auto ¶m_pair : type.get_params ())
225 : : {
226 : 16094 : auto param_tyty = param_pair.get_type ();
227 : 16094 : auto compiled_param_type
228 : 16094 : = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
229 : :
230 : 16094 : auto compiled_param = Backend::typed_identifier (
231 : 16094 : param_pair.get_pattern ().as_string (), compiled_param_type,
232 : 32188 : ctx->get_mappings ().lookup_location (param_tyty->get_ref ()));
233 : :
234 : 16094 : parameters.push_back (compiled_param);
235 : : }
236 : :
237 : 15987 : if (!type.is_variadic ())
238 : 15171 : translated = Backend::function_type (receiver, parameters, results, NULL,
239 : 15171 : type.get_ident ().locus);
240 : : else
241 : 816 : translated
242 : 816 : = Backend::function_type_variadic (receiver, parameters, results, NULL,
243 : 816 : type.get_ident ().locus);
244 : 15987 : }
245 : :
246 : : void
247 : 66 : TyTyResolveCompile::visit (const TyTy::FnPtr &type)
248 : : {
249 : 66 : tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
250 : :
251 : 66 : std::vector<tree> parameters;
252 : :
253 : 66 : auto ¶ms = type.get_params ();
254 : 136 : for (auto &p : params)
255 : : {
256 : 70 : tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
257 : 70 : parameters.push_back (pty);
258 : : }
259 : :
260 : 66 : translated = Backend::function_ptr_type (result_type, parameters,
261 : 66 : type.get_ident ().locus);
262 : 66 : }
263 : :
264 : : void
265 : 20464 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
266 : : {
267 : 20464 : tree type_record = error_mark_node;
268 : 20464 : if (!type.is_enum ())
269 : : {
270 : 14113 : rust_assert (type.number_of_variants () == 1);
271 : :
272 : 14113 : TyTy::VariantDef &variant = *type.get_variants ().at (0);
273 : 14113 : std::vector<Backend::typed_identifier> fields;
274 : 39888 : for (size_t i = 0; i < variant.num_fields (); i++)
275 : : {
276 : 25775 : const TyTy::StructFieldType *field = variant.get_field_at_index (i);
277 : 25775 : tree compiled_field_ty
278 : 25775 : = TyTyResolveCompile::compile (ctx, field->get_field_type ());
279 : :
280 : 25775 : Backend::typed_identifier f (field->get_name (), compiled_field_ty,
281 : 25775 : ctx->get_mappings ().lookup_location (
282 : 51550 : type.get_ty_ref ()));
283 : 25775 : fields.push_back (std::move (f));
284 : : }
285 : :
286 : 14113 : type_record = type.is_union () ? Backend::union_type (fields, false)
287 : 13913 : : Backend::struct_type (fields, false);
288 : 14113 : }
289 : : else
290 : : {
291 : : // see:
292 : : // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
293 : : //
294 : : // enums are actually a big union so for example the rust enum:
295 : : //
296 : : // enum AnEnum {
297 : : // A,
298 : : // B,
299 : : // C (char),
300 : : // D { x: i64, y: i64 },
301 : : // }
302 : : //
303 : : // we actually turn this into
304 : : //
305 : : // union {
306 : : // struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
307 : : // struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
308 : : // struct C { int RUST$ENUM$DISR; char __0; };
309 : : // struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
310 : : // }
311 : : //
312 : : // Ada, qual_union_types might still work for this but I am not 100% sure.
313 : : // I ran into some issues lets reuse our normal union and ask Ada people
314 : : // about it.
315 : : //
316 : : // I think the above is actually wrong and it should actually be this
317 : : //
318 : : // struct {
319 : : // int RUST$ENUM$DISR; // take into account the repr for this TODO
320 : : // union {
321 : : // // Variant A
322 : : // struct {
323 : : // // No additional fields
324 : : // } A;
325 : :
326 : : // // Variant B
327 : : // struct {
328 : : // // No additional fields
329 : : // } B;
330 : :
331 : : // // Variant C
332 : : // struct {
333 : : // char c;
334 : : // } C;
335 : :
336 : : // // Variant D
337 : : // struct {
338 : : // int64_t x;
339 : : // int64_t y;
340 : : // } D;
341 : : // } payload; // The union of all variant data
342 : : // };
343 : :
344 : 6351 : std::vector<tree> variant_records;
345 : 22396 : for (auto &variant : type.get_variants ())
346 : : {
347 : 16045 : std::vector<Backend::typed_identifier> fields;
348 : 22057 : for (size_t i = 0; i < variant->num_fields (); i++)
349 : : {
350 : 6012 : const TyTy::StructFieldType *field
351 : 6012 : = variant->get_field_at_index (i);
352 : 6012 : tree compiled_field_ty
353 : 6012 : = TyTyResolveCompile::compile (ctx, field->get_field_type ());
354 : :
355 : 6012 : std::string field_name = field->get_name ();
356 : 6012 : if (variant->get_variant_type ()
357 : : == TyTy::VariantDef::VariantType::TUPLE)
358 : 4509 : field_name = "__" + field->get_name ();
359 : :
360 : 6012 : Backend::typed_identifier f (
361 : 6012 : field_name, compiled_field_ty,
362 : 6012 : ctx->get_mappings ().lookup_location (type.get_ty_ref ()));
363 : 6012 : fields.push_back (std::move (f));
364 : 6012 : }
365 : :
366 : 16045 : tree variant_record = Backend::struct_type (fields);
367 : 16045 : tree named_variant_record
368 : 16045 : = Backend::named_type (variant->get_ident ().path.get (),
369 : 32090 : variant_record, variant->get_ident ().locus);
370 : :
371 : : // add them to the list
372 : 16045 : variant_records.push_back (named_variant_record);
373 : 16045 : }
374 : :
375 : : // now we need to make the actual union, but first we need to make
376 : : // named_type TYPE_DECL's out of the variants
377 : :
378 : 6351 : size_t i = 0;
379 : 6351 : std::vector<Backend::typed_identifier> enum_fields;
380 : 22396 : for (auto &variant_record : variant_records)
381 : : {
382 : 16045 : TyTy::VariantDef *variant = type.get_variants ().at (i++);
383 : 16045 : std::string implicit_variant_name = variant->get_identifier ();
384 : :
385 : 16045 : Backend::typed_identifier f (implicit_variant_name, variant_record,
386 : 16045 : ctx->get_mappings ().lookup_location (
387 : 16045 : type.get_ty_ref ()));
388 : 16045 : enum_fields.push_back (std::move (f));
389 : 16045 : }
390 : :
391 : : //
392 : 6351 : location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
393 : :
394 : : // finally make the union or the enum
395 : 6351 : tree variants_union = Backend::union_type (enum_fields, false);
396 : 6351 : layout_type (variants_union);
397 : 6351 : tree named_union_record
398 : 6351 : = Backend::named_type ("payload", variants_union, locus);
399 : :
400 : : // create the overall struct
401 : 6351 : tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
402 : 6351 : type.get_repr_options ().repr);
403 : 6351 : Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
404 : 6351 : enumeral_type, locus);
405 : 6351 : Backend::typed_identifier variants_union_field ("payload",
406 : : named_union_record,
407 : 6351 : locus);
408 : :
409 : 6351 : std::vector<Backend::typed_identifier> fields
410 : 6351 : = {discrim, variants_union_field};
411 : 6351 : type_record = Backend::struct_type (fields, false);
412 : 6351 : }
413 : :
414 : : // Handle repr options
415 : : // TODO: "packed" should only narrow type alignment and "align" should only
416 : : // widen it. Do we need to check and enforce this here, or is it taken care of
417 : : // later on in the gcc middle-end?
418 : 20464 : TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
419 : 20464 : if (repr.pack)
420 : : {
421 : 10 : TYPE_PACKED (type_record) = 1;
422 : 10 : if (repr.pack > 1)
423 : : {
424 : 5 : SET_TYPE_ALIGN (type_record, repr.pack * 8);
425 : 5 : TYPE_USER_ALIGN (type_record) = 1;
426 : : }
427 : : }
428 : 20454 : else if (repr.align)
429 : : {
430 : 10 : SET_TYPE_ALIGN (type_record, repr.align * 8);
431 : 10 : TYPE_USER_ALIGN (type_record) = 1;
432 : : }
433 : 20464 : layout_type (type_record);
434 : :
435 : 20464 : std::string named_struct_str
436 : 20464 : = type.get_ident ().path.get () + type.subst_as_string ();
437 : 20464 : translated = Backend::named_type (named_struct_str, type_record,
438 : 20464 : type.get_ident ().locus);
439 : 20464 : }
440 : :
441 : : void
442 : 20786 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
443 : : {
444 : 20786 : if (type.num_fields () == 0)
445 : : {
446 : 18710 : translated = get_unit_type (ctx);
447 : 18710 : return;
448 : : }
449 : :
450 : : // create implicit struct
451 : 2076 : std::vector<Backend::typed_identifier> fields;
452 : 6399 : for (size_t i = 0; i < type.num_fields (); i++)
453 : : {
454 : 4323 : TyTy::BaseType *field = type.get_field (i);
455 : 4323 : tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
456 : :
457 : : // rustc uses the convention __N, where N is an integer, to
458 : : // name the fields of a tuple. We follow this as well,
459 : : // because this is used by GDB. One further reason to prefer
460 : : // this, rather than simply emitting the integer, is that this
461 : : // approach makes it simpler to use a C-only debugger, or
462 : : // GDB's C mode, when debugging Rust.
463 : 4323 : Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty,
464 : 4323 : ctx->get_mappings ().lookup_location (
465 : 8646 : type.get_ty_ref ()));
466 : 4323 : fields.push_back (std::move (f));
467 : : }
468 : :
469 : 2076 : tree struct_type_record = Backend::struct_type (fields);
470 : 2076 : translated = Backend::named_type (type.get_name (), struct_type_record,
471 : 2076 : type.get_ident ().locus);
472 : 2076 : }
473 : :
474 : : void
475 : 3640 : TyTyResolveCompile::visit (const TyTy::ArrayType &type)
476 : : {
477 : 3640 : tree element_type
478 : 3640 : = TyTyResolveCompile::compile (ctx, type.get_element_type ());
479 : 3640 : TyTy::ConstType *const_capacity = type.get_capacity ();
480 : 3640 : tree folded_capacity_expr = const_capacity->get_value ();
481 : :
482 : : // build_index_type takes the maximum index, which is one less than
483 : : // the length.
484 : 3640 : tree index_type_tree = build_index_type (
485 : : fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
486 : :
487 : 3640 : translated = build_array_type (element_type, index_type_tree, false);
488 : 3640 : }
489 : :
490 : : void
491 : 93 : TyTyResolveCompile::visit (const TyTy::SliceType &type)
492 : : {
493 : 93 : tree type_record = create_slice_type_record (type);
494 : :
495 : 93 : std::string named_struct_str
496 : 186 : = std::string ("[") + type.get_element_type ()->get_name () + "]";
497 : 93 : translated = Backend::named_type (named_struct_str, type_record,
498 : 93 : type.get_ident ().locus);
499 : 93 : }
500 : :
501 : : void
502 : 14243 : TyTyResolveCompile::visit (const TyTy::BoolType &)
503 : : {
504 : 14243 : translated
505 : 14243 : = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
506 : 14243 : }
507 : :
508 : : void
509 : 90761 : TyTyResolveCompile::visit (const TyTy::IntType &type)
510 : : {
511 : 90761 : switch (type.get_int_kind ())
512 : : {
513 : 12717 : case TyTy::IntType::I8:
514 : 12717 : translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
515 : : BUILTINS_LOCATION);
516 : 12717 : return;
517 : :
518 : 8898 : case TyTy::IntType::I16:
519 : 8898 : translated
520 : 8898 : = Backend::named_type ("i16", Backend::integer_type (false, 16),
521 : : BUILTINS_LOCATION);
522 : 8898 : return;
523 : :
524 : 51149 : case TyTy::IntType::I32:
525 : 51149 : translated
526 : 51149 : = Backend::named_type ("i32", Backend::integer_type (false, 32),
527 : : BUILTINS_LOCATION);
528 : 51149 : return;
529 : :
530 : 9065 : case TyTy::IntType::I64:
531 : 9065 : translated
532 : 9065 : = Backend::named_type ("i64", Backend::integer_type (false, 64),
533 : : BUILTINS_LOCATION);
534 : 9065 : return;
535 : :
536 : 8932 : case TyTy::IntType::I128:
537 : 8932 : translated
538 : 8932 : = Backend::named_type ("i128", Backend::integer_type (false, 128),
539 : : BUILTINS_LOCATION);
540 : 8932 : return;
541 : : }
542 : : }
543 : :
544 : : void
545 : 71599 : TyTyResolveCompile::visit (const TyTy::UintType &type)
546 : : {
547 : 71599 : switch (type.get_uint_kind ())
548 : : {
549 : 17686 : case TyTy::UintType::U8:
550 : 17686 : translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
551 : : BUILTINS_LOCATION);
552 : 17686 : return;
553 : :
554 : 12098 : case TyTy::UintType::U16:
555 : 12098 : translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
556 : : BUILTINS_LOCATION);
557 : 12098 : return;
558 : :
559 : 16254 : case TyTy::UintType::U32:
560 : 16254 : translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
561 : : BUILTINS_LOCATION);
562 : 16254 : return;
563 : :
564 : 16893 : case TyTy::UintType::U64:
565 : 16893 : translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
566 : : BUILTINS_LOCATION);
567 : 16893 : return;
568 : :
569 : 8668 : case TyTy::UintType::U128:
570 : 8668 : translated
571 : 8668 : = Backend::named_type ("u128", Backend::integer_type (true, 128),
572 : : BUILTINS_LOCATION);
573 : 8668 : return;
574 : : }
575 : : }
576 : :
577 : : void
578 : 22293 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
579 : : {
580 : 22293 : switch (type.get_float_kind ())
581 : : {
582 : 10935 : case TyTy::FloatType::F32:
583 : 10935 : translated = Backend::named_type ("f32", Backend::float_type (32),
584 : : BUILTINS_LOCATION);
585 : 10935 : return;
586 : :
587 : 11358 : case TyTy::FloatType::F64:
588 : 11358 : translated = Backend::named_type ("f64", Backend::float_type (64),
589 : : BUILTINS_LOCATION);
590 : 11358 : return;
591 : : }
592 : : }
593 : :
594 : : void
595 : 41157 : TyTyResolveCompile::visit (const TyTy::USizeType &)
596 : : {
597 : 41157 : translated
598 : 41157 : = Backend::named_type ("usize",
599 : : Backend::integer_type (true,
600 : : Backend::get_pointer_size ()),
601 : : BUILTINS_LOCATION);
602 : 41157 : }
603 : :
604 : : void
605 : 22178 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
606 : : {
607 : 22178 : translated
608 : 22178 : = Backend::named_type ("isize",
609 : : Backend::integer_type (false,
610 : : Backend::get_pointer_size ()),
611 : : BUILTINS_LOCATION);
612 : 22178 : }
613 : :
614 : : void
615 : 9163 : TyTyResolveCompile::visit (const TyTy::CharType &)
616 : : {
617 : 9163 : translated
618 : 9163 : = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
619 : 9163 : }
620 : :
621 : : void
622 : 17943 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
623 : : {
624 : 17943 : const TyTy::SliceType *slice = nullptr;
625 : 17943 : const TyTy::StrType *str = nullptr;
626 : 17943 : const TyTy::DynamicObjectType *dyn = nullptr;
627 : 17943 : if (type.is_dyn_slice_type (&slice))
628 : : {
629 : 596 : tree type_record = create_slice_type_record (*slice);
630 : 596 : std::string dyn_slice_type_str
631 : 1788 : = std::string (type.is_mutable () ? "&mut " : "&") + "["
632 : 1788 : + slice->get_element_type ()->get_name () + "]";
633 : :
634 : 596 : translated = Backend::named_type (dyn_slice_type_str, type_record,
635 : : slice->get_locus ());
636 : :
637 : 596 : return;
638 : 596 : }
639 : 17347 : else if (type.is_dyn_str_type (&str))
640 : : {
641 : 3941 : tree type_record = create_str_type_record (*str);
642 : 3941 : std::string dyn_str_type_str
643 : 11823 : = std::string (type.is_mutable () ? "&mut " : "&") + "str";
644 : :
645 : 3941 : translated = Backend::named_type (dyn_str_type_str, type_record,
646 : : str->get_locus ());
647 : :
648 : 3941 : return;
649 : 3941 : }
650 : 13406 : else if (type.is_dyn_obj_type (&dyn))
651 : : {
652 : 549 : tree type_record = create_dyn_obj_record (*dyn);
653 : 549 : std::string dyn_str_type_str
654 : 1098 : = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name ();
655 : :
656 : 549 : translated = Backend::named_type (dyn_str_type_str, type_record,
657 : : dyn->get_locus ());
658 : :
659 : 549 : return;
660 : 549 : }
661 : :
662 : 12857 : tree base_compiled_type
663 : 12857 : = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
664 : 12857 : if (type.is_mutable ())
665 : : {
666 : 1104 : translated = Backend::reference_type (base_compiled_type);
667 : : }
668 : : else
669 : : {
670 : 11753 : auto base = Backend::immutable_type (base_compiled_type);
671 : 11753 : translated = Backend::reference_type (base);
672 : : }
673 : : }
674 : :
675 : : void
676 : 9953 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
677 : : {
678 : 9953 : const TyTy::SliceType *slice = nullptr;
679 : 9953 : const TyTy::StrType *str = nullptr;
680 : 9953 : const TyTy::DynamicObjectType *dyn = nullptr;
681 : 9953 : if (type.is_dyn_slice_type (&slice))
682 : : {
683 : 533 : tree type_record = create_slice_type_record (*slice);
684 : 533 : std::string dyn_slice_type_str
685 : 1543 : = std::string (type.is_mutable () ? "*mut " : "*const ") + "["
686 : 1599 : + slice->get_element_type ()->get_name () + "]";
687 : :
688 : 533 : translated = Backend::named_type (dyn_slice_type_str, type_record,
689 : : slice->get_locus ());
690 : :
691 : 533 : return;
692 : 533 : }
693 : 9420 : else if (type.is_dyn_str_type (&str))
694 : : {
695 : 2487 : tree type_record = create_str_type_record (*str);
696 : 2487 : std::string dyn_str_type_str
697 : 7461 : = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
698 : :
699 : 2487 : translated = Backend::named_type (dyn_str_type_str, type_record,
700 : : str->get_locus ());
701 : :
702 : 2487 : return;
703 : 2487 : }
704 : 6933 : else if (type.is_dyn_obj_type (&dyn))
705 : : {
706 : 0 : tree type_record = create_dyn_obj_record (*dyn);
707 : 0 : std::string dyn_str_type_str
708 : 0 : = std::string (type.is_mutable () ? "*mut " : "*const ")
709 : 0 : + dyn->get_name ();
710 : :
711 : 0 : translated = Backend::named_type (dyn_str_type_str, type_record,
712 : : dyn->get_locus ());
713 : :
714 : 0 : return;
715 : 0 : }
716 : :
717 : 6933 : tree base_compiled_type
718 : 6933 : = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
719 : 6933 : if (type.is_mutable ())
720 : : {
721 : 1681 : translated = Backend::pointer_type (base_compiled_type);
722 : : }
723 : : else
724 : : {
725 : 5252 : auto base = Backend::immutable_type (base_compiled_type);
726 : 5252 : translated = Backend::pointer_type (base);
727 : : }
728 : : }
729 : :
730 : : void
731 : 8236 : TyTyResolveCompile::visit (const TyTy::StrType &type)
732 : : {
733 : 8236 : tree raw_str = create_str_type_record (type);
734 : 8236 : translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
735 : 8236 : }
736 : :
737 : : void
738 : 8491 : TyTyResolveCompile::visit (const TyTy::NeverType &)
739 : : {
740 : 8491 : translated = get_unit_type (ctx);
741 : 8491 : }
742 : :
743 : : void
744 : 0 : TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
745 : : {
746 : 0 : if (trait_object_mode)
747 : : {
748 : 0 : translated = Backend::integer_type (true, Backend::get_pointer_size ());
749 : 0 : return;
750 : : }
751 : :
752 : 0 : tree type_record = create_dyn_obj_record (type);
753 : 0 : translated = Backend::named_type (type.get_name (), type_record,
754 : 0 : type.get_ident ().locus);
755 : : }
756 : :
757 : : void
758 : 0 : TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
759 : : {
760 : 0 : rust_assert (type.can_resolve ());
761 : 0 : auto underlying = type.resolve ();
762 : 0 : translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
763 : 0 : }
764 : :
765 : : tree
766 : 549 : TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type)
767 : : {
768 : : // create implicit struct
769 : 549 : auto items = type.get_object_items ();
770 : 549 : std::vector<Backend::typed_identifier> fields;
771 : :
772 : 549 : tree uint = Backend::integer_type (true, Backend::get_pointer_size ());
773 : 549 : tree uintptr_ty = build_pointer_type (uint);
774 : :
775 : 549 : Backend::typed_identifier f ("pointer", uintptr_ty,
776 : 549 : ctx->get_mappings ().lookup_location (
777 : 549 : type.get_ty_ref ()));
778 : 549 : fields.push_back (std::move (f));
779 : :
780 : 549 : tree vtable_size = build_int_cst (size_type_node, items.size ());
781 : 549 : tree vtable_type = Backend::array_type (uintptr_ty, vtable_size);
782 : 549 : Backend::typed_identifier vtf ("vtable", vtable_type,
783 : 549 : ctx->get_mappings ().lookup_location (
784 : 549 : type.get_ty_ref ()));
785 : 549 : fields.push_back (std::move (vtf));
786 : :
787 : 549 : tree record = Backend::struct_type (fields);
788 : 549 : RS_DST_FLAG (record) = 1;
789 : 549 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
790 : :
791 : 549 : return record;
792 : 549 : }
793 : :
794 : : tree
795 : 1222 : TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
796 : : {
797 : : // lookup usize
798 : 1222 : TyTy::BaseType *usize = nullptr;
799 : 1222 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
800 : 1222 : rust_assert (ok);
801 : :
802 : 1222 : tree element_type
803 : 1222 : = TyTyResolveCompile::compile (ctx, type.get_element_type ());
804 : 1222 : tree data_field_ty = build_pointer_type (element_type);
805 : 1222 : Backend::typed_identifier data_field ("data", data_field_ty,
806 : 1222 : type.get_locus ());
807 : :
808 : 1222 : tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
809 : 1222 : Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
810 : :
811 : 1222 : tree record = Backend::struct_type ({data_field, len_field});
812 : 1222 : RS_DST_FLAG (record) = 1;
813 : 1222 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
814 : :
815 : 1222 : return record;
816 : : }
817 : :
818 : : tree
819 : 14664 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
820 : : {
821 : : // lookup usize
822 : 14664 : TyTy::BaseType *usize = nullptr;
823 : 14664 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
824 : 14664 : rust_assert (ok);
825 : :
826 : 14664 : tree char_ptr = build_pointer_type (char_type_node);
827 : 14664 : tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
828 : :
829 : 14664 : tree element_type = const_char_type;
830 : 14664 : tree data_field_ty = build_pointer_type (element_type);
831 : 14664 : Backend::typed_identifier data_field ("data", data_field_ty,
832 : 14664 : type.get_locus ());
833 : :
834 : 14664 : tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
835 : 14664 : Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
836 : :
837 : 14664 : tree record = Backend::struct_type ({data_field, len_field});
838 : 14664 : RS_DST_FLAG (record) = 1;
839 : 14664 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
840 : :
841 : 14664 : return record;
842 : : }
843 : :
844 : : } // namespace Compile
845 : : } // namespace Rust
|