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