]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: unify how we handle DST's
authorPhilip Herron <herron.philip@googlemail.com>
Mon, 8 May 2023 13:10:57 +0000 (14:10 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:37:15 +0000 (18:37 +0100)
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 <herron.philip@googlemail.com>
gcc/rust/backend/rust-compile-expr.cc
gcc/rust/backend/rust-compile-type.cc
gcc/rust/backend/rust-compile-type.h
gcc/rust/backend/rust-compile.cc
gcc/rust/backend/rust-tree.h
gcc/rust/typecheck/rust-tyty.cc
gcc/rust/typecheck/rust-tyty.h
gcc/testsuite/rust/execute/torture/issue-2180.rs [new file with mode: 0644]

index 07e5d79e0e36d60fd4626ae4a47a2a1827f81f2e..59afc01f3da45248bad9b26229c494a53b751f41 100644 (file)
@@ -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);
              }
index 29f7cca2e40e7a370885fa3efcd3dd69a5db8b6a..76b38c58bb3805c467fc555465fafe36b4107835 100644 (file)
@@ -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<Backend::typed_identifier> 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;
index ce13795b5682ac20f25819929b3a07536fb77a84..44bd218686ec4c4a9426e171af71601b8dc14a67 100644 (file)
@@ -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);
index ea7cc15e04dc0d48caae742b4df06bb2fc8a2da3..a5d6abb1f82e49bd2cc83d1366494f7454e5d14b 100644 (file)
@@ -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);
index 1f0e12f635adba359fad4e323d9b07c17ec6171f..b4c058fe009795d9875b196f204ba3086a317e4d 100644 (file)
@@ -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?
index 1c673181e821b2bd5db6300ca3123e90cffde796..5e9af52c47b4a23f752777d91874fedc661e0245 100644 (file)
@@ -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<const TyTy::DynamicObjectType *> (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<const TyTy::DynamicObjectType *> (element);
+  return true;
+}
+
 void
 PointerType::accept_vis (TyVisitor &vis)
 {
index cd6be349b38a9823cb614aa0231569d424bb248b..a6a373a0c62336c49b3d38954a0dffe1d7a7ca75 100644 (file)
@@ -1147,6 +1147,36 @@ public:
   BaseType *clone () const final override;
 };
 
+class DynamicObjectType : public BaseType
+{
+public:
+  DynamicObjectType (HirId ref, RustIdent ident,
+                    std::vector<TypeBoundPredicate> specified_bounds,
+                    std::set<HirId> refs = std::set<HirId> ());
+
+  DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
+                    std::vector<TypeBoundPredicate> specified_bounds,
+                    std::set<HirId> refs = std::set<HirId> ());
+
+  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<const Resolver::TraitItemReference *, const TypeBoundPredicate *>>
+  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<TypeBoundPredicate> specified_bounds,
-                    std::set<HirId> refs = std::set<HirId> ());
-
-  DynamicObjectType (HirId ref, HirId ty_ref, RustIdent ident,
-                    std::vector<TypeBoundPredicate> specified_bounds,
-                    std::set<HirId> refs = std::set<HirId> ());
-
-  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<const Resolver::TraitItemReference *, const TypeBoundPredicate *>>
-  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 (file)
index 0000000..3a7ea10
--- /dev/null
@@ -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;
+}