diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-05-23 14:57:55 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-23 14:57:55 +0000 |
commit | bf6d540b1043bb944450dfe9da4c91124cdf31d3 (patch) | |
tree | 6edb9359d5ac9d9b63938019e0fd9b336c1dd43e /gcc/rust/backend | |
parent | 63762cc243c643c10aca7e07dfd6abe9b78748f8 (diff) | |
parent | cd39861da5e1113207193bb8b3e6fb3dde92895f (diff) | |
download | gcc-bf6d540b1043bb944450dfe9da4c91124cdf31d3.zip gcc-bf6d540b1043bb944450dfe9da4c91124cdf31d3.tar.gz gcc-bf6d540b1043bb944450dfe9da4c91124cdf31d3.tar.bz2 |
Merge #1268
1268: Fix Slice Type Layout r=philberty a=philberty
Slices in Rust are represented by TypePaths such as '[i32]'. Though if you
actually try to use this explicit type-path you will hit errors such as
this type has an unknown size at compile time. This is because this is
actually what Rust calls a dynamically sized type. This means when you use
types such as: '&[i32]' it is not actually a reference type to a slice. Its
a slice in its entirety this means for lack of a better word when you use
'*const [i32]' or '&mut [i32]' we end up actually passing around a struct
by value _not_ at pointer/reference to it.
This patch changes the type-layout so that we handle this layout change
properly. This patch will also need to be applied to str types which I
believe have a similar layout for safety.
The patch also sets up TYPE_MAIN_VARIANT so that we can avoid unnessecary
view_convert_expressions between *const [i32] and &mut [i32] which will
have the same layout.
Reference:
https://doc.rust-lang.org/reference/dynamically-sized-types.html
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=672adac002939a2dab43b8d231adc1dc
Fixes #1232
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 12 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 56 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-type.cc | 82 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-type.h | 8 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 19 | ||||
-rw-r--r-- | gcc/rust/backend/rust-tree.h | 6 |
6 files changed, 156 insertions, 27 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 8378554..096b65f 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -67,6 +67,17 @@ public: return type; } + tree insert_main_variant (tree type) + { + hashval_t h = type_hasher (type); + auto it = main_variants.find (h); + if (it != main_variants.end ()) + return it->second; + + main_variants.insert ({h, type}); + return type; + } + ::Backend *get_backend () { return backend; } Resolver::Resolver *get_resolver () { return resolver; } Resolver::TypeCheckContext *get_tyctx () { return tyctx; } @@ -314,6 +325,7 @@ private: std::map<DefId, std::vector<std::pair<const TyTy::BaseType *, tree>>> mono_fns; std::map<HirId, tree> implicit_pattern_bindings; + std::map<hashval_t, tree> main_variants; // To GCC middle-end std::vector<tree> type_decls; diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 824d6d3..b176ed2 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -123,6 +123,11 @@ void CompileExpr::visit (HIR::BorrowExpr &expr) { tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + if (SLICE_TYPE_P (TREE_TYPE (main_expr))) + { + translated = main_expr; + return; + } TyTy::BaseType *tyty = nullptr; if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), @@ -164,6 +169,12 @@ CompileExpr::visit (HIR::DereferenceExpr &expr) } tree expected_type = TyTyResolveCompile::compile (ctx, tyty); + if (SLICE_TYPE_P (TREE_TYPE (main_expr)) && SLICE_TYPE_P (expected_type)) + { + translated = main_expr; + return; + } + bool known_valid = true; translated = ctx->get_backend ()->indirect_expression (expected_type, main_expr, @@ -1092,6 +1103,32 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree, return fold_build1_loc (location.gcc_location (), VIEW_CONVERT_EXPR, type_to_cast_to, expr_tree); } + else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE + && SLICE_TYPE_P (TREE_TYPE (expr_tree))) + { + // returning a raw cast using NOP_EXPR seems to resut in an ICE: + // + // Analyzing compilation unit + // Performing interprocedural optimizations + // <*free_lang_data> {heap 2644k} <visibility> {heap 2644k} + // <build_ssa_passes> {heap 2644k} <opt_local_passes> {heap 2644k}during + // GIMPLE pass: cddce + // In function ‘*T::as_ptr<i32>’: + // rust1: internal compiler error: in propagate_necessity, at + // tree-ssa-dce.cc:984 0x1d5b43e propagate_necessity + // ../../gccrs/gcc/tree-ssa-dce.cc:984 + // 0x1d5e180 perform_tree_ssa_dce + // ../../gccrs/gcc/tree-ssa-dce.cc:1876 + // 0x1d5e2c8 tree_ssa_cd_dce + // ../../gccrs/gcc/tree-ssa-dce.cc:1920 + // 0x1d5e49a execute + // ../../gccrs/gcc/tree-ssa-dce.cc:1992 + + // this is returning the direct raw pointer of the slice an assumes a very + // specific layout + return ctx->get_backend ()->struct_field_expression (expr_tree, 0, + location); + } return fold_convert_loc (location.gcc_location (), type_to_cast_to, expr_tree); @@ -1261,9 +1298,13 @@ HIRCompileBase::resolve_adjustements ( case Resolver::Adjustment::AdjustmentType::IMM_REF: case Resolver::Adjustment::AdjustmentType::MUT_REF: { - tree ptrtype - = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); - e = address_expression (e, ptrtype, locus); + if (!SLICE_TYPE_P (TREE_TYPE (e))) + { + tree ptrtype + = TyTyResolveCompile::compile (ctx, + adjustment.get_expected ()); + e = address_expression (e, ptrtype, locus); + } } break; @@ -1619,6 +1660,15 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr) index, expr.get_array_expr (), expr.get_index_expr ()); + tree actual_type = TREE_TYPE (operator_overload_call); + bool can_indirect = TYPE_PTR_P (actual_type) || TYPE_REF_P (actual_type); + if (!can_indirect) + { + // nothing to do + translated = operator_overload_call; + return; + } + // lookup the expected type for this expression TyTy::BaseType *tyty = nullptr; bool ok diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 102bc0a..707b2af 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -25,6 +25,13 @@ 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) @@ -42,8 +49,6 @@ TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty, return compiler.translated; } -static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"; - // see: gcc/c/c-decl.cc:8230-8241 // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241 tree @@ -375,24 +380,7 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) void TyTyResolveCompile::visit (const TyTy::SliceType &type) { - std::vector<Backend::typed_identifier> fields; - - 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, Location ()); - fields.push_back (std::move (data_field)); - - // lookup usize - TyTy::BaseType *usize = nullptr; - bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize); - rust_assert (ok); - - tree len_field_ty = TyTyResolveCompile::compile (ctx, usize); - Backend::typed_identifier len_field ("len", len_field_ty, Location ()); - fields.push_back (std::move (len_field)); - - tree type_record = ctx->get_backend ()->struct_type (fields); + tree type_record = create_slice_type_record (type); std::string named_struct_str = std::string ("[") + type.get_element_type ()->get_name () + "]"; @@ -536,6 +524,21 @@ TyTyResolveCompile::visit (const TyTy::CharType &type) void TyTyResolveCompile::visit (const TyTy::ReferenceType &type) { + const TyTy::SliceType *slice = 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; + } + tree base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); if (type.is_mutable ()) @@ -552,6 +555,21 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type) void TyTyResolveCompile::visit (const TyTy::PointerType &type) { + const TyTy::SliceType *slice = 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; + } + tree base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); if (type.is_mutable ()) @@ -615,5 +633,29 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) 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; +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index 262b8fc..aefacea 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -60,11 +60,11 @@ public: public: static hashval_t type_hasher (tree type); +protected: + tree create_slice_type_record (const TyTy::SliceType &type); + private: - TyTyResolveCompile (Context *ctx, bool trait_object_mode) - : ctx (ctx), trait_object_mode (trait_object_mode), - translated (error_mark_node), recurisve_ops (0) - {} + TyTyResolveCompile (Context *ctx, bool trait_object_mode); Context *ctx; bool trait_object_mode; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index d9349d5..18a2df6 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -218,6 +218,11 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, = static_cast<const TyTy::ReferenceType *> (expected); const TyTy::ReferenceType *act = static_cast<const TyTy::ReferenceType *> (actual); + if (act->is_dyn_slice_type ()) + { + // nothing to do + return rvalue; + } tree expected_type = TyTyResolveCompile::compile (ctx, act->get_base ()); tree deref_rvalue @@ -227,6 +232,8 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, tree coerced = coercion_site (deref_rvalue, act->get_base (), exp->get_base (), lvalue_locus, rvalue_locus); + if (exp->is_dyn_slice_type () && SLICE_TYPE_P (TREE_TYPE (coerced))) + return coerced; return address_expression (coerced, build_reference_type (TREE_TYPE (coerced)), @@ -249,6 +256,12 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, { const TyTy::ReferenceType *act = static_cast<const TyTy::ReferenceType *> (actual); + if (act->is_dyn_slice_type ()) + { + // nothing to do + return rvalue; + } + actual_base = act->get_base (); expected_type = TyTyResolveCompile::compile (ctx, act->get_base ()); } @@ -256,6 +269,12 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, { const TyTy::PointerType *act = static_cast<const TyTy::PointerType *> (actual); + if (act->is_dyn_slice_type ()) + { + // nothing to do + return rvalue; + } + actual_base = act->get_base (); expected_type = TyTyResolveCompile::compile (ctx, act->get_base ()); } diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index c50e090..2b480ad 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -74,6 +74,12 @@ (INDIRECT_REF_P (NODE) && TREE_TYPE (TREE_OPERAND (NODE, 0)) \ && TYPE_REF_P (TREE_TYPE (TREE_OPERAND ((NODE), 0)))) +// this is a helper to differentiate RECORD types between actual records and +// slices +#define SLICE_FLAG TREE_LANG_FLAG_0 +#define SLICE_TYPE_P(TYPE) \ + (TREE_CODE (TYPE) == RECORD_TYPE && TREE_LANG_FLAG_0 (TYPE)) + namespace Rust { // forked from gcc/cp/cvt.cc convert_to_void |