From: Philip Herron Date: Mon, 8 May 2023 13:10:57 +0000 (+0100) Subject: gccrs: unify how we handle DST's X-Git-Tag: basepoints/gcc-15~2576 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9600aa54d7412f5bbff97be2046c8054e201c3c;p=thirdparty%2Fgcc.git gccrs: unify how we handle DST's DST's are not truely reference types they are "unsized types" so the exact size of them is not known at compile time. We actually achieve this by pretending they are a reference but really its struct we pass around. Fixes #2180 gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): refactr (CompileExpr::get_fn_addr_from_dyn): likewise (CompileExpr::get_receiver_from_dyn): likewise (CompileExpr::type_cast_expression): likewise * backend/rust-compile-type.cc (TyTyResolveCompile::visit): likewise (TyTyResolveCompile::create_dyn_obj_record): likewise (TyTyResolveCompile::create_slice_type_record): likewise (TyTyResolveCompile::create_str_type_record): likewise * backend/rust-compile-type.h: likewise * backend/rust-compile.cc (HIRCompileBase::coercion_site1): likewise (HIRCompileBase::coerce_to_dyn_object): refactor * backend/rust-tree.h (SLICE_FLAG): removed (SLICE_TYPE_P): removed (RS_DST_FLAG): new flag (RS_DST_FLAG_P): new predicate * typecheck/rust-tyty.cc (ReferenceType::is_dyn_object): new helper (ReferenceType::is_dyn_obj_type): likewise (PointerType::is_dyn_object): likewise (PointerType::is_dyn_obj_type): likewise * typecheck/rust-tyty.h (class DynamicObjectType): moved up gcc/testsuite/ChangeLog: * rust/execute/torture/issue-2180.rs: New test. Signed-off-by: Philip Herron --- diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 07e5d79e0e36..59afc01f3da4 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -29,6 +29,7 @@ #include "fold-const.h" #include "realmpfr.h" #include "convert.h" +#include "print-tree.h" namespace Rust { namespace Compile { @@ -791,7 +792,7 @@ void CompileExpr::visit (HIR::BorrowExpr &expr) { tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); - if (SLICE_TYPE_P (TREE_TYPE (main_expr))) + if (RS_DST_FLAG_P (TREE_TYPE (main_expr))) { translated = main_expr; return; @@ -836,7 +837,7 @@ 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)) + if (RS_DST_FLAG_P (TREE_TYPE (main_expr)) && RS_DST_FLAG_P (expected_type)) { translated = main_expr; return; @@ -908,6 +909,10 @@ CompileExpr::visit (HIR::AssignmentExpr &expr) expected, expr.get_lhs ()->get_locus (), expr.get_rhs ()->get_locus ()); + // rust_debug_loc (expr.get_locus (), "XXXXXX assignment"); + // debug_tree (rvalue); + // debug_tree (lvalue); + tree assignment = ctx->get_backend ()->assignment_statement (lvalue, rvalue, expr.get_locus ()); @@ -1810,13 +1815,6 @@ CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn, if (ref == nullptr) return error_mark_node; - // get any indirection sorted out - if (receiver->get_kind () == TyTy::TypeKind::REF) - { - tree indirect = indirect_expression (receiver_ref, expr_locus); - receiver_ref = indirect; - } - // cast it to the correct fntype tree expected_fntype = TyTyResolveCompile::compile (ctx, fntype, true); tree idx = build_int_cst (size_type_node, offs); @@ -1841,13 +1839,6 @@ CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn, TyTy::FnType *fntype, tree receiver_ref, Location expr_locus) { - // get any indirection sorted out - if (receiver->get_kind () == TyTy::TypeKind::REF) - { - tree indirect = indirect_expression (receiver_ref, expr_locus); - receiver_ref = indirect; - } - // access the offs + 1 for the fnptr and offs=0 for the reciever obj return ctx->get_backend ()->struct_field_expression (receiver_ref, 0, expr_locus); @@ -2130,7 +2121,7 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree, type_to_cast_to, expr_tree); } else if (TREE_CODE (type_to_cast_to) == POINTER_TYPE - && SLICE_TYPE_P (TREE_TYPE (expr_tree))) + && RS_DST_FLAG (TREE_TYPE (expr_tree))) { // returning a raw cast using NOP_EXPR seems to resut in an ICE: // @@ -2327,7 +2318,7 @@ HIRCompileBase::resolve_adjustements ( case Resolver::Adjustment::AdjustmentType::IMM_REF: case Resolver::Adjustment::AdjustmentType::MUT_REF: { - if (!SLICE_TYPE_P (TREE_TYPE (e))) + if (!RS_DST_FLAG (TREE_TYPE (e))) { e = address_expression (e, locus); } diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 29f7cca2e40e..76b38c58bb38 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -576,6 +576,7 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type) { const TyTy::SliceType *slice = nullptr; const TyTy::StrType *str = nullptr; + const TyTy::DynamicObjectType *dyn = nullptr; if (type.is_dyn_slice_type (&slice)) { tree type_record = create_slice_type_record (*slice); @@ -601,6 +602,18 @@ TyTyResolveCompile::visit (const TyTy::ReferenceType &type) return; } + else if (type.is_dyn_obj_type (&dyn)) + { + tree type_record = create_dyn_obj_record (*dyn); + std::string dyn_str_type_str + = std::string (type.is_mutable () ? "&mut " : "& ") + dyn->get_name (); + + translated + = ctx->get_backend ()->named_type (dyn_str_type_str, type_record, + dyn->get_locus ()); + + return; + } tree base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); @@ -620,6 +633,7 @@ TyTyResolveCompile::visit (const TyTy::PointerType &type) { const TyTy::SliceType *slice = nullptr; const TyTy::StrType *str = nullptr; + const TyTy::DynamicObjectType *dyn = nullptr; if (type.is_dyn_slice_type (&slice)) { tree type_record = create_slice_type_record (*slice); @@ -645,6 +659,19 @@ TyTyResolveCompile::visit (const TyTy::PointerType &type) return; } + else if (type.is_dyn_obj_type (&dyn)) + { + tree type_record = create_dyn_obj_record (*dyn); + std::string dyn_str_type_str + = std::string (type.is_mutable () ? "*mut " : "*const ") + + dyn->get_name (); + + translated + = ctx->get_backend ()->named_type (dyn_str_type_str, type_record, + dyn->get_locus ()); + + return; + } tree base_compiled_type = TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode); @@ -684,6 +711,14 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) return; } + tree type_record = create_dyn_obj_record (type); + translated = ctx->get_backend ()->named_type (type.get_name (), type_record, + type.get_ident ().locus); +} + +tree +TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type) +{ // create implicit struct auto items = type.get_object_items (); std::vector fields; @@ -704,9 +739,11 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) 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 record = ctx->get_backend ()->struct_type (fields); + RS_DST_FLAG (record) = 1; + TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record); + + return record; } tree @@ -727,7 +764,7 @@ TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type) 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; + RS_DST_FLAG (record) = 1; TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record); return record; @@ -753,7 +790,7 @@ TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type) 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; + RS_DST_FLAG (record) = 1; TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record); return record; diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index ce13795b5682..44bd218686ec 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -65,6 +65,7 @@ public: protected: tree create_slice_type_record (const TyTy::SliceType &type); tree create_str_type_record (const TyTy::StrType &type); + tree create_dyn_obj_record (const TyTy::DynamicObjectType &type); private: TyTyResolveCompile (Context *ctx, bool trait_object_mode); diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index ea7cc15e04dc..a5d6abb1f82e 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -78,7 +78,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval, if (expected->get_kind () == TyTy::TypeKind::REF) { // this is a dyn object - if (SLICE_TYPE_P (TREE_TYPE (rvalue))) + if (RS_DST_FLAG_P (TREE_TYPE (rvalue))) { return rvalue; } @@ -96,7 +96,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval, tree coerced = coercion_site1 (deref_rvalue, act->get_base (), exp->get_base (), lvalue_locus, rvalue_locus); - if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced))) + if (exp->is_dyn_object () && RS_DST_FLAG_P (TREE_TYPE (coerced))) return coerced; return address_expression (coerced, rvalue_locus); @@ -104,7 +104,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval, else if (expected->get_kind () == TyTy::TypeKind::POINTER) { // this is a dyn object - if (SLICE_TYPE_P (TREE_TYPE (rvalue))) + if (RS_DST_FLAG_P (TREE_TYPE (rvalue))) { return rvalue; } @@ -140,7 +140,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval, = coercion_site1 (deref_rvalue, actual_base, exp->get_base (), lvalue_locus, rvalue_locus); - if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced))) + if (exp->is_dyn_object () && RS_DST_FLAG_P (TREE_TYPE (coerced))) return coerced; return address_expression (coerced, rvalue_locus); @@ -183,7 +183,11 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, const TyTy::DynamicObjectType *ty, Location locus) { - tree dynamic_object = TyTyResolveCompile::compile (ctx, ty); + // DST's get wrapped in a pseudo reference that doesnt exist... + const TyTy::ReferenceType r (ctx->get_mappings ()->get_next_hir_id (), + TyTy::TyVar (ty->get_ref ()), Mutability::Imm); + + tree dynamic_object = TyTyResolveCompile::compile (ctx, &r); tree dynamic_object_fields = TYPE_FIELDS (dynamic_object); tree vtable_field = DECL_CHAIN (dynamic_object_fields); rust_assert (TREE_CODE (TREE_TYPE (vtable_field)) == ARRAY_TYPE); diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index 1f0e12f635ad..b4c058fe0097 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -78,8 +78,8 @@ // 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) \ +#define RS_DST_FLAG TREE_LANG_FLAG_0 +#define RS_DST_FLAG_P(TYPE) \ (TREE_CODE (TYPE) == RECORD_TYPE && TREE_LANG_FLAG_0 (TYPE)) // lambda? diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 1c673181e821..5e9af52c47b4 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2961,7 +2961,7 @@ ReferenceType::is_mutable () const bool ReferenceType::is_dyn_object () const { - return is_dyn_slice_type () || is_dyn_str_type (); + return is_dyn_slice_type () || is_dyn_str_type () || is_dyn_obj_type (); } bool @@ -2990,6 +2990,19 @@ ReferenceType::is_dyn_str_type (const TyTy::StrType **str) const return true; } +bool +ReferenceType::is_dyn_obj_type (const TyTy::DynamicObjectType **dyn) const +{ + const TyTy::BaseType *element = get_base ()->destructure (); + if (element->get_kind () != TyTy::TypeKind::DYNAMIC) + return false; + if (dyn == nullptr) + return true; + + *dyn = static_cast (element); + return true; +} + void ReferenceType::accept_vis (TyVisitor &vis) { @@ -3112,7 +3125,7 @@ PointerType::is_const () const bool PointerType::is_dyn_object () const { - return is_dyn_slice_type () || is_dyn_str_type (); + return is_dyn_slice_type () || is_dyn_str_type () || is_dyn_obj_type (); } bool @@ -3141,6 +3154,19 @@ PointerType::is_dyn_str_type (const TyTy::StrType **str) const return true; } +bool +PointerType::is_dyn_obj_type (const TyTy::DynamicObjectType **dyn) const +{ + const TyTy::BaseType *element = get_base ()->destructure (); + if (element->get_kind () != TyTy::TypeKind::DYNAMIC) + return false; + if (dyn == nullptr) + return true; + + *dyn = static_cast (element); + return true; +} + void PointerType::accept_vis (TyVisitor &vis) { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index cd6be349b38a..a6a373a0c623 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1147,6 +1147,36 @@ public: BaseType *clone () const final override; }; +class DynamicObjectType : public BaseType +{ +public: + DynamicObjectType (HirId ref, RustIdent ident, + std::vector specified_bounds, + std::set refs = std::set ()); + + DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident, + std::vector specified_bounds, + std::set refs = std::set ()); + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + bool can_eq (const BaseType *other, bool emit_errors) const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *clone () const final override; + + std::string get_name () const override final; + + // this returns a flat list of items including super trait bounds + const std::vector< + std::pair> + get_object_items () const; +}; + class ReferenceType : public BaseType { public: @@ -1179,6 +1209,7 @@ public: bool is_dyn_object () const; bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const; bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const; + bool is_dyn_obj_type (const TyTy::DynamicObjectType **dyn = nullptr) const; private: TyVar base; @@ -1216,6 +1247,7 @@ public: bool is_dyn_object () const; bool is_dyn_slice_type (const TyTy::SliceType **slice = nullptr) const; bool is_dyn_str_type (const TyTy::StrType **str = nullptr) const; + bool is_dyn_obj_type (const TyTy::DynamicObjectType **dyn = nullptr) const; private: TyVar base; @@ -1328,36 +1360,6 @@ private: DefId item; }; -class DynamicObjectType : public BaseType -{ -public: - DynamicObjectType (HirId ref, RustIdent ident, - std::vector specified_bounds, - std::set refs = std::set ()); - - DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident, - std::vector specified_bounds, - std::set refs = std::set ()); - - void accept_vis (TyVisitor &vis) override; - void accept_vis (TyConstVisitor &vis) const override; - - std::string as_string () const override; - - bool can_eq (const BaseType *other, bool emit_errors) const override final; - - bool is_equal (const BaseType &other) const override; - - BaseType *clone () const final override; - - std::string get_name () const override final; - - // this returns a flat list of items including super trait bounds - const std::vector< - std::pair> - get_object_items () const; -}; - } // namespace TyTy } // namespace Rust diff --git a/gcc/testsuite/rust/execute/torture/issue-2180.rs b/gcc/testsuite/rust/execute/torture/issue-2180.rs new file mode 100644 index 000000000000..3a7ea1044724 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-2180.rs @@ -0,0 +1,34 @@ +// { dg-output "123\n" } +trait A { + fn get_int(&self) -> i32; +} + +impl A for i32 { + fn get_int(&self) -> i32 { + *self + } +} + +fn get_dyn_a(x: &i32) -> &dyn A { + x as &dyn A +} + +fn clobber_stack() { + let _z: [usize; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; +} + +extern "C" { + fn printf(s: *const i8, ...) -> i32; +} + +fn main() -> i32 { + let x = 123; + let y = get_dyn_a(&x); + clobber_stack(); + let value = y.get_int(); + let fmt_string = "%d\n\0" as *const str as *const i8; + unsafe { + printf(fmt_string, value); + } + return 0; +}