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