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 :
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 302799 : TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
33 302799 : : ctx (ctx), trait_object_mode (trait_object_mode),
34 302799 : translated (error_mark_node)
35 302799 : {}
36 :
37 : tree
38 302799 : TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
39 : bool trait_object_mode)
40 : {
41 302799 : TyTyResolveCompile compiler (ctx, trait_object_mode);
42 302799 : const TyTy::BaseType *destructured = ty->destructure ();
43 302799 : destructured->accept_vis (compiler);
44 :
45 302799 : if (compiler.translated != error_mark_node
46 302799 : && TYPE_NAME (compiler.translated) != NULL)
47 : {
48 : // canonicalize the type
49 262389 : compiler.translated = ctx->insert_compiled_type (compiler.translated);
50 : }
51 :
52 302799 : 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 6368 : 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 6368 : return compile (ctx, repr);
81 : }
82 :
83 : tree
84 26378 : TyTyResolveCompile::get_unit_type (Context *ctx)
85 : {
86 26378 : static tree unit_type;
87 26378 : if (unit_type == nullptr)
88 : {
89 4301 : auto cn = ctx->get_mappings ().get_current_crate ();
90 4301 : auto &c = ctx->get_mappings ().get_ast_crate (cn);
91 4301 : location_t locus = BUILTINS_LOCATION;
92 4301 : if (c.items.size () > 0)
93 : {
94 4299 : auto &item = c.items[0];
95 4299 : locus = item->get_locus ();
96 : }
97 :
98 4301 : auto unit_type_node = Backend::struct_type ({});
99 4301 : unit_type = Backend::named_type ("()", unit_type_node, locus);
100 : }
101 26378 : 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 16241 : TyTyResolveCompile::visit (const TyTy::FnType &type)
222 : {
223 16241 : Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
224 16241 : std::vector<Backend::typed_identifier> parameters;
225 16241 : 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 16241 : auto hir_type = type.get_return_type ()->destructure ();
230 16241 : bool return_is_unit = hir_type->is_unit ();
231 16241 : bool is_c_abi = type.get_abi () == ABI::C;
232 16241 : bool should_be_void = is_c_abi && return_is_unit;
233 16241 : if (!should_be_void)
234 : {
235 15210 : auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
236 15210 : location_t return_type_locus
237 15210 : = ctx->get_mappings ().lookup_location (hir_type->get_ref ());
238 15210 : results.emplace_back ("_", ret, return_type_locus);
239 : }
240 :
241 32434 : for (auto ¶m_pair : type.get_params ())
242 : {
243 16193 : auto param_tyty = param_pair.get_type ();
244 16193 : auto compiled_param_type
245 16193 : = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
246 :
247 16193 : parameters.emplace_back (param_pair.get_pattern ().to_string (),
248 : compiled_param_type,
249 32386 : ctx->get_mappings ().lookup_location (
250 : param_tyty->get_ref ()));
251 : }
252 :
253 16241 : if (!type.is_variadic ())
254 15417 : translated = Backend::function_type (receiver, parameters, results, NULL,
255 15417 : type.get_ident ().locus);
256 : else
257 824 : translated
258 824 : = Backend::function_type_variadic (receiver, parameters, results, NULL,
259 824 : type.get_ident ().locus);
260 16241 : }
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 20623 : TyTyResolveCompile::visit (const TyTy::ADTType &type)
282 : {
283 20623 : tree type_record = error_mark_node;
284 20623 : if (!type.is_enum ())
285 : {
286 14255 : rust_assert (type.number_of_variants () == 1);
287 :
288 14255 : TyTy::VariantDef &variant = *type.get_variants ().at (0);
289 14255 : std::vector<Backend::typed_identifier> fields;
290 40200 : for (size_t i = 0; i < variant.num_fields (); i++)
291 : {
292 25945 : const TyTy::StructFieldType *field = variant.get_field_at_index (i);
293 25945 : tree compiled_field_ty
294 25945 : = TyTyResolveCompile::compile (ctx, field->get_field_type ());
295 :
296 25945 : fields.emplace_back (field->get_name (), compiled_field_ty,
297 51890 : ctx->get_mappings ().lookup_location (
298 : type.get_ty_ref ()));
299 : }
300 :
301 14255 : type_record = type.is_union () ? Backend::union_type (fields, false)
302 14055 : : Backend::struct_type (fields, false);
303 14255 : }
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 6368 : std::vector<tree> variant_records;
360 22442 : for (auto &variant : type.get_variants ())
361 : {
362 16074 : std::vector<Backend::typed_identifier> fields;
363 22092 : for (size_t i = 0; i < variant->num_fields (); i++)
364 : {
365 6018 : const TyTy::StructFieldType *field
366 6018 : = variant->get_field_at_index (i);
367 6018 : tree compiled_field_ty
368 6018 : = TyTyResolveCompile::compile (ctx, field->get_field_type ());
369 :
370 6018 : std::string field_name = field->get_name ();
371 6018 : if (variant->get_variant_type ()
372 : == TyTy::VariantDef::VariantType::TUPLE)
373 4513 : field_name = "__" + field->get_name ();
374 :
375 12036 : fields.emplace_back (field_name, compiled_field_ty,
376 6018 : ctx->get_mappings ().lookup_location (
377 : type.get_ty_ref ()));
378 6018 : }
379 :
380 16074 : tree variant_record = Backend::struct_type (fields);
381 16074 : tree named_variant_record
382 16074 : = Backend::named_type (variant->get_ident ().path.get (),
383 32148 : variant_record, variant->get_ident ().locus);
384 :
385 : // add them to the list
386 16074 : variant_records.push_back (named_variant_record);
387 16074 : }
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 6368 : size_t i = 0;
393 6368 : std::vector<Backend::typed_identifier> enum_fields;
394 22442 : for (auto &variant_record : variant_records)
395 : {
396 16074 : TyTy::VariantDef *variant = type.get_variants ().at (i++);
397 16074 : std::string implicit_variant_name = variant->get_identifier ();
398 :
399 32148 : enum_fields.emplace_back (implicit_variant_name, variant_record,
400 16074 : ctx->get_mappings ().lookup_location (
401 : type.get_ty_ref ()));
402 16074 : }
403 :
404 : //
405 6368 : location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ());
406 :
407 : // finally make the union or the enum
408 6368 : tree variants_union = Backend::union_type (enum_fields, false);
409 6368 : layout_type (variants_union);
410 6368 : tree named_union_record
411 6368 : = Backend::named_type ("payload", variants_union, locus);
412 :
413 : // create the overall struct
414 6368 : tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type (
415 6368 : type.get_repr_options ().repr);
416 6368 : Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME,
417 6368 : enumeral_type, locus);
418 6368 : Backend::typed_identifier variants_union_field ("payload",
419 : named_union_record,
420 6368 : locus);
421 :
422 6368 : std::vector<Backend::typed_identifier> fields
423 6368 : = {discrim, variants_union_field};
424 6368 : type_record = Backend::struct_type (fields, false);
425 6368 : }
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 20623 : TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
432 20623 : 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 20613 : 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 20623 : layout_type (type_record);
447 :
448 20623 : std::string named_struct_str
449 20623 : = type.get_ident ().path.get () + type.subst_as_string ();
450 20623 : translated = Backend::named_type (named_struct_str, type_record,
451 20623 : type.get_ident ().locus);
452 20623 : }
453 :
454 : void
455 17030 : TyTyResolveCompile::visit (const TyTy::TupleType &type)
456 : {
457 17030 : if (type.num_fields () == 0)
458 : {
459 15203 : translated = get_unit_type (ctx);
460 15203 : return;
461 : }
462 :
463 : // create implicit struct
464 1827 : std::vector<Backend::typed_identifier> fields;
465 5659 : for (size_t i = 0; i < type.num_fields (); i++)
466 : {
467 3832 : TyTy::BaseType *field = type.get_field (i);
468 3832 : 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 3832 : fields.emplace_back ("__" + std::to_string (i), compiled_field_ty,
477 7664 : ctx->get_mappings ().lookup_location (
478 : type.get_ty_ref ()));
479 : }
480 :
481 1827 : tree struct_type_record = Backend::struct_type (fields);
482 1827 : translated = Backend::named_type (type.get_name (), struct_type_record,
483 1827 : type.get_ident ().locus);
484 1827 : }
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 10048 : TyTyResolveCompile::visit (const TyTy::BoolType &)
529 : {
530 10048 : translated
531 10048 : = Backend::named_type ("bool", boolean_type_node, BUILTINS_LOCATION);
532 10048 : }
533 :
534 : void
535 72436 : TyTyResolveCompile::visit (const TyTy::IntType &type)
536 : {
537 72436 : switch (type.get_int_kind ())
538 : {
539 8913 : case TyTy::IntType::I8:
540 8913 : translated = Backend::named_type ("i8", Backend::integer_type (false, 8),
541 : BUILTINS_LOCATION);
542 8913 : return;
543 :
544 4963 : case TyTy::IntType::I16:
545 4963 : translated
546 4963 : = Backend::named_type ("i16", Backend::integer_type (false, 16),
547 : BUILTINS_LOCATION);
548 4963 : return;
549 :
550 48433 : case TyTy::IntType::I32:
551 48433 : translated
552 48433 : = Backend::named_type ("i32", Backend::integer_type (false, 32),
553 : BUILTINS_LOCATION);
554 48433 : return;
555 :
556 5130 : case TyTy::IntType::I64:
557 5130 : translated
558 5130 : = Backend::named_type ("i64", Backend::integer_type (false, 64),
559 : BUILTINS_LOCATION);
560 5130 : return;
561 :
562 4997 : case TyTy::IntType::I128:
563 4997 : translated
564 4997 : = Backend::named_type ("i128", Backend::integer_type (false, 128),
565 : BUILTINS_LOCATION);
566 4997 : return;
567 : }
568 : }
569 :
570 : void
571 52282 : TyTyResolveCompile::visit (const TyTy::UintType &type)
572 : {
573 52282 : switch (type.get_uint_kind ())
574 : {
575 13708 : case TyTy::UintType::U8:
576 13708 : translated = Backend::named_type ("u8", Backend::integer_type (true, 8),
577 : BUILTINS_LOCATION);
578 13708 : return;
579 :
580 8122 : case TyTy::UintType::U16:
581 8122 : translated = Backend::named_type ("u16", Backend::integer_type (true, 16),
582 : BUILTINS_LOCATION);
583 8122 : return;
584 :
585 12809 : case TyTy::UintType::U32:
586 12809 : translated = Backend::named_type ("u32", Backend::integer_type (true, 32),
587 : BUILTINS_LOCATION);
588 12809 : return;
589 :
590 12910 : case TyTy::UintType::U64:
591 12910 : translated = Backend::named_type ("u64", Backend::integer_type (true, 64),
592 : BUILTINS_LOCATION);
593 12910 : return;
594 :
595 4733 : case TyTy::UintType::U128:
596 4733 : translated
597 4733 : = Backend::named_type ("u128", Backend::integer_type (true, 128),
598 : BUILTINS_LOCATION);
599 4733 : return;
600 : }
601 : }
602 :
603 : void
604 14431 : TyTyResolveCompile::visit (const TyTy::FloatType &type)
605 : {
606 14431 : switch (type.get_float_kind ())
607 : {
608 7008 : case TyTy::FloatType::F32:
609 7008 : translated = Backend::named_type ("f32", Backend::float_type (32),
610 : BUILTINS_LOCATION);
611 7008 : return;
612 :
613 7423 : case TyTy::FloatType::F64:
614 7423 : translated = Backend::named_type ("f64", Backend::float_type (64),
615 : BUILTINS_LOCATION);
616 7423 : return;
617 : }
618 : }
619 :
620 : void
621 33943 : TyTyResolveCompile::visit (const TyTy::USizeType &)
622 : {
623 33943 : translated
624 33943 : = Backend::named_type ("usize",
625 : Backend::integer_type (true,
626 : Backend::get_pointer_size ()),
627 : BUILTINS_LOCATION);
628 33943 : }
629 :
630 : void
631 18271 : TyTyResolveCompile::visit (const TyTy::ISizeType &)
632 : {
633 18271 : translated
634 18271 : = Backend::named_type ("isize",
635 : Backend::integer_type (false,
636 : Backend::get_pointer_size ()),
637 : BUILTINS_LOCATION);
638 18271 : }
639 :
640 : void
641 5228 : TyTyResolveCompile::visit (const TyTy::CharType &)
642 : {
643 5228 : translated
644 5228 : = Backend::named_type ("char", Backend::wchar_type (), BUILTINS_LOCATION);
645 5228 : }
646 :
647 : void
648 18126 : TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
649 : {
650 18126 : const TyTy::SliceType *slice = nullptr;
651 18126 : const TyTy::StrType *str = nullptr;
652 18126 : const TyTy::DynamicObjectType *dyn = nullptr;
653 18126 : 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 17517 : else if (type.is_dyn_str_type (&str))
666 : {
667 4049 : tree type_record = create_str_type_record (*str);
668 4049 : std::string dyn_str_type_str
669 12147 : = std::string (type.is_mutable () ? "&mut " : "&") + "str";
670 :
671 4049 : translated = Backend::named_type (dyn_str_type_str, type_record,
672 : str->get_locus ());
673 :
674 4049 : return;
675 4049 : }
676 13468 : 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 12919 : tree base_compiled_type
689 12919 : = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
690 12919 : if (type.is_mutable ())
691 : {
692 1108 : translated = Backend::reference_type (base_compiled_type);
693 : }
694 : else
695 : {
696 11811 : auto base = Backend::immutable_type (base_compiled_type);
697 11811 : translated = Backend::reference_type (base);
698 : }
699 : }
700 :
701 : void
702 10179 : TyTyResolveCompile::visit (const TyTy::PointerType &type)
703 : {
704 10179 : const TyTy::SliceType *slice = nullptr;
705 10179 : const TyTy::StrType *str = nullptr;
706 10179 : const TyTy::DynamicObjectType *dyn = nullptr;
707 10179 : 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 9646 : else if (type.is_dyn_str_type (&str))
720 : {
721 2582 : tree type_record = create_str_type_record (*str);
722 2582 : std::string dyn_str_type_str
723 7746 : = std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
724 :
725 2582 : translated = Backend::named_type (dyn_str_type_str, type_record,
726 : str->get_locus ());
727 :
728 2582 : return;
729 2582 : }
730 7064 : 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 7064 : tree base_compiled_type
744 7064 : = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
745 7064 : if (type.is_mutable ())
746 : {
747 1681 : translated = Backend::pointer_type (base_compiled_type);
748 : }
749 : else
750 : {
751 5383 : auto base = Backend::immutable_type (base_compiled_type);
752 5383 : translated = Backend::pointer_type (base);
753 : }
754 : }
755 :
756 : void
757 4301 : TyTyResolveCompile::visit (const TyTy::StrType &type)
758 : {
759 4301 : tree raw_str = create_str_type_record (type);
760 4301 : translated = Backend::named_type ("str", raw_str, BUILTINS_LOCATION);
761 4301 : }
762 :
763 : void
764 4561 : TyTyResolveCompile::visit (const TyTy::NeverType &)
765 : {
766 4561 : translated = get_unit_type (ctx);
767 4561 : }
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 10932 : TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
844 : {
845 : // lookup usize
846 10932 : TyTy::BaseType *usize = nullptr;
847 10932 : bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
848 10932 : rust_assert (ok);
849 :
850 10932 : tree char_ptr = build_pointer_type (char_type_node);
851 10932 : tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
852 :
853 10932 : tree element_type = const_char_type;
854 10932 : tree data_field_ty = build_pointer_type (element_type);
855 10932 : Backend::typed_identifier data_field ("data", data_field_ty,
856 10932 : type.get_locus ());
857 :
858 10932 : tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
859 10932 : Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
860 :
861 10932 : tree record = Backend::struct_type ({data_field, len_field});
862 10932 : RS_DST_FLAG (record) = 1;
863 10932 : TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
864 :
865 10932 : return record;
866 : }
867 :
868 : } // namespace Compile
869 : } // namespace Rust
|