public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-7563] gccrs: unify how we handle DST's
@ 2024-01-16 17:40 Arthur Cohen
  0 siblings, 0 replies; only message in thread
From: Arthur Cohen @ 2024-01-16 17:40 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c9600aa54d7412f5bbff97be2046c8054e201c3c

commit r14-7563-gc9600aa54d7412f5bbff97be2046c8054e201c3c
Author: Philip Herron <herron.philip@googlemail.com>
Date:   Mon May 8 14:10:57 2023 +0100

    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 <herron.philip@googlemail.com>

Diff:
---
 gcc/rust/backend/rust-compile-expr.cc            | 27 ++++-------
 gcc/rust/backend/rust-compile-type.cc            | 47 ++++++++++++++++--
 gcc/rust/backend/rust-compile-type.h             |  1 +
 gcc/rust/backend/rust-compile.cc                 | 14 ++++--
 gcc/rust/backend/rust-tree.h                     |  4 +-
 gcc/rust/typecheck/rust-tyty.cc                  | 30 +++++++++++-
 gcc/rust/typecheck/rust-tyty.h                   | 62 ++++++++++++------------
 gcc/testsuite/rust/execute/torture/issue-2180.rs | 34 +++++++++++++
 8 files changed, 157 insertions(+), 62 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 07e5d79e0e3..59afc01f3da 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 29f7cca2e40..76b38c58bb3 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<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;
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index ce13795b568..44bd218686e 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 ea7cc15e04d..a5d6abb1f82 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 1f0e12f635a..b4c058fe009 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 1c673181e82..5e9af52c47b 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<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)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index cd6be349b38..a6a373a0c62 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<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
index 00000000000..3a7ea104472
--- /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;
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-16 17:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-16 17:40 [gcc r14-7563] gccrs: unify how we handle DST's Arthur Cohen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).