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