| // Copyright (C) 2020-2023 Free Software Foundation, Inc. |
| |
| // This file is part of GCC. |
| |
| // GCC is free software; you can redistribute it and/or modify it under |
| // the terms of the GNU General Public License as published by the Free |
| // Software Foundation; either version 3, or (at your option) any later |
| // version. |
| |
| // GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| // for more details. |
| |
| // You should have received a copy of the GNU General Public License |
| // along with GCC; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| #include "rust-compile-type.h" |
| #include "rust-compile-expr.h" |
| #include "rust-constexpr.h" |
| #include "rust-gcc.h" |
| |
| #include "tree.h" |
| |
| namespace Rust { |
| namespace Compile { |
| |
| static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"; |
| |
| TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode) |
| : ctx (ctx), trait_object_mode (trait_object_mode), |
| translated (error_mark_node), recurisve_ops (0) |
| {} |
| |
| tree |
| TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty, |
| bool trait_object_mode) |
| { |
| TyTyResolveCompile compiler (ctx, trait_object_mode); |
| ty->accept_vis (compiler); |
| |
| if (compiler.translated != error_mark_node |
| && TYPE_NAME (compiler.translated) != NULL) |
| { |
| // canonicalize the type |
| compiler.translated = ctx->insert_compiled_type (compiler.translated); |
| } |
| |
| return compiler.translated; |
| } |
| |
| // see: gcc/c/c-decl.cc:8230-8241 |
| // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241 |
| tree |
| TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx) |
| { |
| // static tree enum_node = NULL_TREE; |
| // if (enum_node == NULL_TREE) |
| // { |
| // enum_node = make_node (ENUMERAL_TYPE); |
| // SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node)); |
| // SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node)); |
| // TYPE_USER_ALIGN (enum_node) = 0; |
| // TYPE_UNSIGNED (enum_node) = 1; |
| // TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node); |
| // TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node); |
| // TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node); |
| |
| // // tree identifier = ctx->get_backend ()->get_identifier_node |
| // // ("enumeral"); tree enum_decl |
| // // = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier, |
| // enum_node); |
| // // TYPE_NAME (enum_node) = enum_decl; |
| // } |
| // return enum_node; |
| |
| static tree enum_node = NULL_TREE; |
| if (enum_node == NULL_TREE) |
| { |
| enum_node = ctx->get_backend ()->named_type ( |
| "enumeral", ctx->get_backend ()->integer_type (false, 64), |
| Linemap::predeclared_location ()); |
| } |
| return enum_node; |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ErrorType &) |
| { |
| translated = error_mark_node; |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::InferType &) |
| { |
| translated = error_mark_node; |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ClosureType &type) |
| { |
| auto mappings = ctx->get_mappings (); |
| |
| std::vector<Backend::typed_identifier> fields; |
| |
| size_t i = 0; |
| for (const auto &capture : type.get_captures ()) |
| { |
| // lookup the HirId |
| HirId ref = UNKNOWN_HIRID; |
| bool ok = mappings->lookup_node_to_hir (capture, &ref); |
| rust_assert (ok); |
| |
| // lookup the var decl type |
| TyTy::BaseType *lookup = nullptr; |
| bool found = ctx->get_tyctx ()->lookup_type (ref, &lookup); |
| rust_assert (found); |
| |
| // FIXME get the var pattern name |
| std::string mappings_name = "capture_" + std::to_string (i); |
| |
| // FIXME |
| // this should be based on the closure move-ability |
| tree decl_type = TyTyResolveCompile::compile (ctx, lookup); |
| tree capture_type = build_reference_type (decl_type); |
| fields.push_back (Backend::typed_identifier (mappings_name, capture_type, |
| type.get_ident ().locus)); |
| } |
| |
| tree type_record = ctx->get_backend ()->struct_type (fields); |
| RS_CLOSURE_FLAG (type_record) = 1; |
| |
| std::string named_struct_str |
| = type.get_ident ().path.get () + "::{{closure}}"; |
| translated = ctx->get_backend ()->named_type (named_struct_str, type_record, |
| type.get_ident ().locus); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ProjectionType &type) |
| { |
| type.get ()->accept_vis (*this); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::PlaceholderType &type) |
| { |
| type.resolve ()->accept_vis (*this); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ParamType ¶m) |
| { |
| if (recurisve_ops++ >= rust_max_recursion_depth) |
| { |
| rust_error_at (Location (), |
| "%<recursion depth%> count exceeds limit of %i (use " |
| "%<frust-max-recursion-depth=%> to increase the limit)", |
| rust_max_recursion_depth); |
| translated = error_mark_node; |
| return; |
| } |
| |
| param.resolve ()->accept_vis (*this); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::FnType &type) |
| { |
| Backend::typed_identifier receiver; |
| std::vector<Backend::typed_identifier> parameters; |
| std::vector<Backend::typed_identifier> results; |
| |
| if (!type.get_return_type ()->is_unit ()) |
| { |
| auto hir_type = type.get_return_type (); |
| auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode); |
| results.push_back (Backend::typed_identifier ( |
| "_", ret, |
| ctx->get_mappings ()->lookup_location (hir_type->get_ref ()))); |
| } |
| |
| for (auto ¶m_pair : type.get_params ()) |
| { |
| auto param_tyty = param_pair.second; |
| auto compiled_param_type |
| = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode); |
| |
| auto compiled_param = Backend::typed_identifier ( |
| param_pair.first->as_string (), compiled_param_type, |
| ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); |
| |
| parameters.push_back (compiled_param); |
| } |
| |
| if (!type.is_varadic ()) |
| translated |
| = ctx->get_backend ()->function_type (receiver, parameters, results, NULL, |
| type.get_ident ().locus); |
| else |
| translated |
| = ctx->get_backend ()->function_type_varadic (receiver, parameters, |
| results, NULL, |
| type.get_ident ().locus); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::FnPtr &type) |
| { |
| tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ()); |
| |
| std::vector<tree> parameters; |
| |
| auto ¶ms = type.get_params (); |
| for (auto &p : params) |
| { |
| tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ()); |
| parameters.push_back (pty); |
| } |
| |
| translated = ctx->get_backend ()->function_ptr_type (result_type, parameters, |
| type.get_ident ().locus); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ADTType &type) |
| { |
| tree type_record = error_mark_node; |
| if (!type.is_enum ()) |
| { |
| rust_assert (type.number_of_variants () == 1); |
| |
| TyTy::VariantDef &variant = *type.get_variants ().at (0); |
| std::vector<Backend::typed_identifier> fields; |
| for (size_t i = 0; i < variant.num_fields (); i++) |
| { |
| const TyTy::StructFieldType *field = variant.get_field_at_index (i); |
| tree compiled_field_ty |
| = TyTyResolveCompile::compile (ctx, field->get_field_type ()); |
| |
| Backend::typed_identifier f (field->get_name (), compiled_field_ty, |
| ctx->get_mappings ()->lookup_location ( |
| type.get_ty_ref ())); |
| fields.push_back (std::move (f)); |
| } |
| |
| type_record = type.is_union () |
| ? ctx->get_backend ()->union_type (fields) |
| : ctx->get_backend ()->struct_type (fields); |
| } |
| else |
| { |
| // see: |
| // https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241 |
| // |
| // enums are actually a big union so for example the rust enum: |
| // |
| // enum AnEnum { |
| // A, |
| // B, |
| // C (char), |
| // D { x: i64, y: i64 }, |
| // } |
| // |
| // we actually turn this into |
| // |
| // union { |
| // struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant |
| // struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant |
| // struct C { int RUST$ENUM$DISR; char __0; }; |
| // struct D { int RUST$ENUM$DISR; i64 x; i64 y; }; |
| // } |
| // |
| // Ada, qual_union_types might still work for this but I am not 100% sure. |
| // I ran into some issues lets reuse our normal union and ask Ada people |
| // about it. |
| |
| std::vector<tree> variant_records; |
| for (auto &variant : type.get_variants ()) |
| { |
| std::vector<Backend::typed_identifier> fields; |
| |
| // add in the qualifier field for the variant |
| tree enumeral_type |
| = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx); |
| Backend::typed_identifier f (RUST_ENUM_DISR_FIELD_NAME, enumeral_type, |
| ctx->get_mappings ()->lookup_location ( |
| variant->get_id ())); |
| fields.push_back (std::move (f)); |
| |
| // compile the rest of the fields |
| for (size_t i = 0; i < variant->num_fields (); i++) |
| { |
| const TyTy::StructFieldType *field |
| = variant->get_field_at_index (i); |
| tree compiled_field_ty |
| = TyTyResolveCompile::compile (ctx, field->get_field_type ()); |
| |
| std::string field_name = field->get_name (); |
| if (variant->get_variant_type () |
| == TyTy::VariantDef::VariantType::TUPLE) |
| field_name = "__" + field->get_name (); |
| |
| Backend::typed_identifier f ( |
| field_name, compiled_field_ty, |
| ctx->get_mappings ()->lookup_location (type.get_ty_ref ())); |
| fields.push_back (std::move (f)); |
| } |
| |
| tree variant_record = ctx->get_backend ()->struct_type (fields); |
| tree named_variant_record = ctx->get_backend ()->named_type ( |
| variant->get_ident ().path.get (), variant_record, |
| variant->get_ident ().locus); |
| |
| // set the qualifier to be a builtin |
| DECL_ARTIFICIAL (TYPE_FIELDS (variant_record)) = 1; |
| |
| // add them to the list |
| variant_records.push_back (named_variant_record); |
| } |
| |
| // now we need to make the actual union, but first we need to make |
| // named_type TYPE_DECL's out of the variants |
| |
| size_t i = 0; |
| std::vector<Backend::typed_identifier> enum_fields; |
| for (auto &variant_record : variant_records) |
| { |
| TyTy::VariantDef *variant = type.get_variants ().at (i++); |
| std::string implicit_variant_name = variant->get_identifier (); |
| |
| Backend::typed_identifier f (implicit_variant_name, variant_record, |
| ctx->get_mappings ()->lookup_location ( |
| type.get_ty_ref ())); |
| enum_fields.push_back (std::move (f)); |
| } |
| |
| // finally make the union or the enum |
| type_record = ctx->get_backend ()->union_type (enum_fields); |
| } |
| |
| // Handle repr options |
| // TODO: "packed" should only narrow type alignment and "align" should only |
| // widen it. Do we need to check and enforce this here, or is it taken care of |
| // later on in the gcc middle-end? |
| TyTy::ADTType::ReprOptions repr = type.get_repr_options (); |
| if (repr.pack) |
| { |
| TYPE_PACKED (type_record) = 1; |
| if (repr.pack > 1) |
| { |
| SET_TYPE_ALIGN (type_record, repr.pack * 8); |
| TYPE_USER_ALIGN (type_record) = 1; |
| } |
| } |
| else if (repr.align) |
| { |
| SET_TYPE_ALIGN (type_record, repr.align * 8); |
| TYPE_USER_ALIGN (type_record) = 1; |
| } |
| |
| std::string named_struct_str |
| = type.get_ident ().path.get () + type.subst_as_string (); |
| translated = ctx->get_backend ()->named_type (named_struct_str, type_record, |
| type.get_ident ().locus); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::TupleType &type) |
| { |
| if (type.num_fields () == 0) |
| { |
| translated = ctx->get_backend ()->unit_type (); |
| return; |
| } |
| |
| // create implicit struct |
| std::vector<Backend::typed_identifier> fields; |
| for (size_t i = 0; i < type.num_fields (); i++) |
| { |
| TyTy::BaseType *field = type.get_field (i); |
| tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field); |
| |
| // rustc uses the convention __N, where N is an integer, to |
| // name the fields of a tuple. We follow this as well, |
| // because this is used by GDB. One further reason to prefer |
| // this, rather than simply emitting the integer, is that this |
| // approach makes it simpler to use a C-only debugger, or |
| // GDB's C mode, when debugging Rust. |
| Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty, |
| ctx->get_mappings ()->lookup_location ( |
| type.get_ty_ref ())); |
| fields.push_back (std::move (f)); |
| } |
| |
| tree struct_type_record = ctx->get_backend ()->struct_type (fields); |
| translated |
| = ctx->get_backend ()->named_type (type.as_string (), struct_type_record, |
| type.get_ident ().locus); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ArrayType &type) |
| { |
| tree element_type |
| = TyTyResolveCompile::compile (ctx, type.get_element_type ()); |
| |
| ctx->push_const_context (); |
| tree capacity_expr = CompileExpr::Compile (&type.get_capacity_expr (), ctx); |
| ctx->pop_const_context (); |
| |
| tree folded_capacity_expr = fold_expr (capacity_expr); |
| |
| translated |
| = ctx->get_backend ()->array_type (element_type, folded_capacity_expr); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::SliceType &type) |
| { |
| tree type_record = create_slice_type_record (type); |
| |
| std::string named_struct_str |
| = std::string ("[") + type.get_element_type ()->get_name () + "]"; |
| translated = ctx->get_backend ()->named_type (named_struct_str, type_record, |
| type.get_ident ().locus); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::BoolType &) |
| { |
| translated |
| = ctx->get_backend ()->named_type ("bool", |
| ctx->get_backend ()->bool_type (), |
| Linemap::predeclared_location ()); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::IntType &type) |
| { |
| switch (type.get_int_kind ()) |
| { |
| case TyTy::IntType::I8: |
| translated = ctx->get_backend ()->named_type ( |
| "i8", ctx->get_backend ()->integer_type (false, 8), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::IntType::I16: |
| translated = ctx->get_backend ()->named_type ( |
| "i16", ctx->get_backend ()->integer_type (false, 16), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::IntType::I32: |
| translated = ctx->get_backend ()->named_type ( |
| "i32", ctx->get_backend ()->integer_type (false, 32), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::IntType::I64: |
| translated = ctx->get_backend ()->named_type ( |
| "i64", ctx->get_backend ()->integer_type (false, 64), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::IntType::I128: |
| translated = ctx->get_backend ()->named_type ( |
| "i128", ctx->get_backend ()->integer_type (false, 128), |
| Linemap::predeclared_location ()); |
| return; |
| } |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::UintType &type) |
| { |
| switch (type.get_uint_kind ()) |
| { |
| case TyTy::UintType::U8: |
| translated = ctx->get_backend ()->named_type ( |
| "u8", ctx->get_backend ()->integer_type (true, 8), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::UintType::U16: |
| translated = ctx->get_backend ()->named_type ( |
| "u16", ctx->get_backend ()->integer_type (true, 16), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::UintType::U32: |
| translated = ctx->get_backend ()->named_type ( |
| "u32", ctx->get_backend ()->integer_type (true, 32), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::UintType::U64: |
| translated = ctx->get_backend ()->named_type ( |
| "u64", ctx->get_backend ()->integer_type (true, 64), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::UintType::U128: |
| translated = ctx->get_backend ()->named_type ( |
| "u128", ctx->get_backend ()->integer_type (true, 128), |
| Linemap::predeclared_location ()); |
| return; |
| } |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::FloatType &type) |
| { |
| switch (type.get_float_kind ()) |
| { |
| case TyTy::FloatType::F32: |
| translated |
| = ctx->get_backend ()->named_type ("f32", |
| ctx->get_backend ()->float_type (32), |
| Linemap::predeclared_location ()); |
| return; |
| |
| case TyTy::FloatType::F64: |
| translated |
| = ctx->get_backend ()->named_type ("f64", |
| ctx->get_backend ()->float_type (64), |
| Linemap::predeclared_location ()); |
| return; |
| } |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::USizeType &) |
| { |
| translated = ctx->get_backend ()->named_type ( |
| "usize", |
| ctx->get_backend ()->integer_type ( |
| true, ctx->get_backend ()->get_pointer_size ()), |
| Linemap::predeclared_location ()); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ISizeType &) |
| { |
| translated = ctx->get_backend ()->named_type ( |
| "isize", |
| ctx->get_backend ()->integer_type ( |
| false, ctx->get_backend ()->get_pointer_size ()), |
| Linemap::predeclared_location ()); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::CharType &) |
| { |
| translated |
| = ctx->get_backend ()->named_type ("char", |
| ctx->get_backend ()->wchar_type (), |
| Linemap::predeclared_location ()); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::ReferenceType &type) |
| { |
| const TyTy::SliceType *slice = nullptr; |
| const TyTy::StrType *str = nullptr; |
| if (type.is_dyn_slice_type (&slice)) |
| { |
| tree type_record = create_slice_type_record (*slice); |
| std::string dyn_slice_type_str |
| = std::string (type.is_mutable () ? "&mut " : "&") + "[" |
| + slice->get_element_type ()->get_name () + "]"; |
| |
| translated |
| = ctx->get_backend ()->named_type (dyn_slice_type_str, type_record, |
| slice->get_locus ()); |
| |
| return; |
| } |
| else if (type.is_dyn_str_type (&str)) |
| { |
| tree type_record = create_str_type_record (*str); |
| std::string dyn_str_type_str |
| = std::string (type.is_mutable () ? "&mut " : "&") + "str"; |
| |
| translated |
| = ctx->get_backend ()->named_type (dyn_str_type_str, type_record, |
| str->get_locus ()); |
| |
| return; |
| } |
| |
| tree base_compiled_type |
| = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); |
| if (type.is_mutable ()) |
| { |
| translated = ctx->get_backend ()->reference_type (base_compiled_type); |
| } |
| else |
| { |
| auto base = ctx->get_backend ()->immutable_type (base_compiled_type); |
| translated = ctx->get_backend ()->reference_type (base); |
| } |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::PointerType &type) |
| { |
| const TyTy::SliceType *slice = nullptr; |
| const TyTy::StrType *str = nullptr; |
| if (type.is_dyn_slice_type (&slice)) |
| { |
| tree type_record = create_slice_type_record (*slice); |
| std::string dyn_slice_type_str |
| = std::string (type.is_mutable () ? "*mut " : "*const ") + "[" |
| + slice->get_element_type ()->get_name () + "]"; |
| |
| translated |
| = ctx->get_backend ()->named_type (dyn_slice_type_str, type_record, |
| slice->get_locus ()); |
| |
| return; |
| } |
| else if (type.is_dyn_str_type (&str)) |
| { |
| tree type_record = create_str_type_record (*str); |
| std::string dyn_str_type_str |
| = std::string (type.is_mutable () ? "*mut " : "*const ") + "str"; |
| |
| translated |
| = ctx->get_backend ()->named_type (dyn_str_type_str, type_record, |
| str->get_locus ()); |
| |
| return; |
| } |
| |
| tree base_compiled_type |
| = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); |
| if (type.is_mutable ()) |
| { |
| translated = ctx->get_backend ()->pointer_type (base_compiled_type); |
| } |
| else |
| { |
| auto base = ctx->get_backend ()->immutable_type (base_compiled_type); |
| translated = ctx->get_backend ()->pointer_type (base); |
| } |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::StrType &type) |
| { |
| tree raw_str = create_str_type_record (type); |
| translated |
| = ctx->get_backend ()->named_type ("str", raw_str, |
| Linemap::predeclared_location ()); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::NeverType &) |
| { |
| translated = ctx->get_backend ()->unit_type (); |
| } |
| |
| void |
| TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) |
| { |
| if (trait_object_mode) |
| { |
| translated = ctx->get_backend ()->integer_type ( |
| true, ctx->get_backend ()->get_pointer_size ()); |
| return; |
| } |
| |
| // create implicit struct |
| auto items = type.get_object_items (); |
| std::vector<Backend::typed_identifier> fields; |
| |
| tree uint = ctx->get_backend ()->integer_type ( |
| true, ctx->get_backend ()->get_pointer_size ()); |
| tree uintptr_ty = build_pointer_type (uint); |
| |
| Backend::typed_identifier f ("pointer", uintptr_ty, |
| ctx->get_mappings ()->lookup_location ( |
| type.get_ty_ref ())); |
| fields.push_back (std::move (f)); |
| |
| tree vtable_size = build_int_cst (size_type_node, items.size ()); |
| tree vtable_type = ctx->get_backend ()->array_type (uintptr_ty, vtable_size); |
| Backend::typed_identifier vtf ("vtable", vtable_type, |
| ctx->get_mappings ()->lookup_location ( |
| type.get_ty_ref ())); |
| fields.push_back (std::move (vtf)); |
| |
| tree type_record = ctx->get_backend ()->struct_type (fields); |
| translated = ctx->get_backend ()->named_type (type.get_name (), type_record, |
| type.get_ident ().locus); |
| } |
| |
| tree |
| TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type) |
| { |
| // lookup usize |
| TyTy::BaseType *usize = nullptr; |
| bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize); |
| rust_assert (ok); |
| |
| tree element_type |
| = TyTyResolveCompile::compile (ctx, type.get_element_type ()); |
| tree data_field_ty = build_pointer_type (element_type); |
| Backend::typed_identifier data_field ("data", data_field_ty, |
| type.get_locus ()); |
| |
| tree len_field_ty = TyTyResolveCompile::compile (ctx, usize); |
| Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ()); |
| |
| tree record = ctx->get_backend ()->struct_type ({data_field, len_field}); |
| SLICE_FLAG (record) = 1; |
| TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record); |
| |
| return record; |
| } |
| |
| tree |
| TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type) |
| { |
| // lookup usize |
| TyTy::BaseType *usize = nullptr; |
| bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize); |
| rust_assert (ok); |
| |
| tree char_ptr = build_pointer_type (char_type_node); |
| tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST); |
| |
| tree element_type = const_char_type; |
| tree data_field_ty = build_pointer_type (element_type); |
| Backend::typed_identifier data_field ("data", data_field_ty, |
| type.get_locus ()); |
| |
| tree len_field_ty = TyTyResolveCompile::compile (ctx, usize); |
| Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ()); |
| |
| tree record = ctx->get_backend ()->struct_type ({data_field, len_field}); |
| SLICE_FLAG (record) = 1; |
| TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record); |
| |
| return record; |
| } |
| |
| } // namespace Compile |
| } // namespace Rust |