From: Philip Herron <herron.phi...@googlemail.com>

In order to handle the tuple pattern of: fn test ((x _) : (i32, i32)) -> i32 { 
x }
we need to recognize that ABI wise this function still takes a tuple as the 
parameter
to this function its just how we can address the "pattern" of the tuple changes.

So reall if this was C it would look like:

  void test (struct tuple_type __prameter)
  {
    return __parameter.0
  }

The code here reuses our existing pattern code so that we generate these 
implicit
bindings of the paramter with a field access so any time x is referenced it's 
really
just emplacing __parameter.0 for the field access into the struct which is a 
tuple.

Fixes Rust-GCC#2847

gcc/rust/ChangeLog:

        * backend/rust-compile-fnparam.cc (CompileFnParam::visit): compile 
tuple patterns
        (CompileSelfParam::compile): update return type
        (CompileFnParam::create_tmp_param_var): return Bvariable not tree to 
stop ICE
        * backend/rust-compile-fnparam.h: update prototype
        * backend/rust-compile-pattern.cc (CompilePatternBindings::visit): 
implement TuplePattern
        * backend/rust-compile-pattern.h: update prototype

gcc/testsuite/ChangeLog:

        * rust/compile/issue-2847.rs: New test.

Signed-off-by: Philip Herron <herron.phi...@googlemail.com>
---
 gcc/rust/backend/rust-compile-fnparam.cc | 31 ++++++---
 gcc/rust/backend/rust-compile-fnparam.h  |  4 +-
 gcc/rust/backend/rust-compile-pattern.cc | 86 ++++++++++++++++++++++++
 gcc/rust/backend/rust-compile-pattern.h  |  2 +-
 gcc/testsuite/rust/compile/issue-2847.rs |  8 +++
 5 files changed, 117 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-2847.rs

diff --git a/gcc/rust/backend/rust-compile-fnparam.cc 
b/gcc/rust/backend/rust-compile-fnparam.cc
index c00092d219e..b40065e110d 100644
--- a/gcc/rust/backend/rust-compile-fnparam.cc
+++ b/gcc/rust/backend/rust-compile-fnparam.cc
@@ -68,25 +68,36 @@ CompileFnParam::visit (HIR::WildcardPattern &pattern)
   compiled_param = Backend::parameter_variable (fndecl, "_", decl_type, locus);
 }
 
+void
+CompileFnParam::visit (HIR::TuplePattern &pattern)
+{
+  compiled_param = create_tmp_param_var (decl_type);
+  CompilePatternBindings::Compile (
+    pattern, Backend::var_expression (compiled_param, locus), ctx);
+}
+
 void
 CompileFnParam::visit (HIR::StructPattern &pattern)
 {
-  tree tmp_param_var = create_tmp_param_var (decl_type);
-  CompilePatternBindings::Compile (pattern, tmp_param_var, ctx);
+  compiled_param = create_tmp_param_var (decl_type);
+  CompilePatternBindings::Compile (
+    pattern, Backend::var_expression (compiled_param, locus), ctx);
 }
 
 void
 CompileFnParam::visit (HIR::TupleStructPattern &pattern)
 {
-  tree tmp_param_var = create_tmp_param_var (decl_type);
-  CompilePatternBindings::Compile (pattern, tmp_param_var, ctx);
+  compiled_param = create_tmp_param_var (decl_type);
+  CompilePatternBindings::Compile (
+    pattern, Backend::var_expression (compiled_param, locus), ctx);
 }
 
 void
 CompileFnParam::visit (HIR::ReferencePattern &pattern)
 {
-  tree tmp_param_var = create_tmp_param_var (decl_type);
-  CompilePatternBindings::Compile (pattern, tmp_param_var, ctx);
+  compiled_param = create_tmp_param_var (decl_type);
+  CompilePatternBindings::Compile (
+    pattern, Backend::var_expression (compiled_param, locus), ctx);
 }
 
 Bvariable *
@@ -102,7 +113,7 @@ CompileSelfParam::compile (Context *ctx, tree fndecl, 
HIR::SelfParam &self,
   return Backend::parameter_variable (fndecl, "self", decl_type, locus);
 }
 
-tree
+Bvariable *
 CompileFnParam::create_tmp_param_var (tree decl_type)
 {
   // generate the anon param
@@ -110,10 +121,8 @@ CompileFnParam::create_tmp_param_var (tree decl_type)
   std::string cpp_str_identifier = std::string (IDENTIFIER_POINTER 
(tmp_ident));
 
   decl_type = Backend::immutable_type (decl_type);
-  compiled_param = Backend::parameter_variable (fndecl, cpp_str_identifier,
-                                               decl_type, locus);
-
-  return Backend::var_expression (compiled_param, locus);
+  return Backend::parameter_variable (fndecl, cpp_str_identifier, decl_type,
+                                     locus);
 }
 
 } // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-fnparam.h 
b/gcc/rust/backend/rust-compile-fnparam.h
index 82a705fde7b..189216c9ba4 100644
--- a/gcc/rust/backend/rust-compile-fnparam.h
+++ b/gcc/rust/backend/rust-compile-fnparam.h
@@ -47,12 +47,12 @@ public:
   void visit (HIR::QualifiedPathInExpression &) override {}
   void visit (HIR::RangePattern &) override {}
   void visit (HIR::SlicePattern &) override {}
-  void visit (HIR::TuplePattern &) override {}
+  void visit (HIR::TuplePattern &) override;
 
 private:
   CompileFnParam (Context *ctx, tree fndecl, tree decl_type, location_t locus);
 
-  tree create_tmp_param_var (tree decl_type);
+  Bvariable *create_tmp_param_var (tree decl_type);
 
   tree fndecl;
   tree decl_type;
diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index d6161bd5e83..b2e7c351f95 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -613,6 +613,92 @@ CompilePatternBindings::visit (HIR::IdentifierPattern 
&pattern)
                               match_scrutinee_expr);
 }
 
+void
+CompilePatternBindings::visit (HIR::TuplePattern &pattern)
+{
+  rust_assert (pattern.has_tuple_pattern_items ());
+
+  // lookup the type
+  TyTy::BaseType *ty = nullptr;
+  bool ok
+    = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
+                                     &ty);
+  rust_assert (ok);
+
+  switch (pattern.get_items ().get_item_type ())
+    {
+      case HIR::TuplePatternItems::ItemType::RANGED: {
+       size_t tuple_idx = 0;
+       auto &items
+         = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+
+       auto &items_lower = items.get_lower_patterns ();
+       auto &items_upper = items.get_upper_patterns ();
+
+       for (auto &sub : items_lower)
+         {
+           TyTy::BaseType *ty_sub = nullptr;
+           HirId sub_id = sub->get_mappings ().get_hirid ();
+           bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
+           rust_assert (ok);
+
+           tree sub_init
+             = Backend::struct_field_expression (match_scrutinee_expr,
+                                                 tuple_idx, sub->get_locus ());
+
+           CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
+           tuple_idx++;
+         }
+
+       rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+       tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
+                   - items_upper.size ();
+
+       for (auto &sub : items_upper)
+         {
+           TyTy::BaseType *ty_sub = nullptr;
+           HirId sub_id = sub->get_mappings ().get_hirid ();
+           bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
+           rust_assert (ok);
+
+           tree sub_init
+             = Backend::struct_field_expression (match_scrutinee_expr,
+                                                 tuple_idx, sub->get_locus ());
+           CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
+           tuple_idx++;
+         }
+
+       return;
+      }
+      case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+       size_t tuple_idx = 0;
+       auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+         pattern.get_items ());
+
+       for (auto &sub : items.get_patterns ())
+         {
+           TyTy::BaseType *ty_sub = nullptr;
+           HirId sub_id = sub->get_mappings ().get_hirid ();
+           bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
+           rust_assert (ok);
+
+           tree sub_init
+             = Backend::struct_field_expression (match_scrutinee_expr,
+                                                 tuple_idx, sub->get_locus ());
+           CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
+           tuple_idx++;
+         }
+
+       return;
+      }
+      default: {
+       rust_unreachable ();
+      }
+    }
+}
+
+//
+
 void
 CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
 {
diff --git a/gcc/rust/backend/rust-compile-pattern.h 
b/gcc/rust/backend/rust-compile-pattern.h
index 0b785c6ce8c..c7a62fcbc53 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -82,6 +82,7 @@ public:
   void visit (HIR::TupleStructPattern &pattern) override;
   void visit (HIR::ReferencePattern &pattern) override;
   void visit (HIR::IdentifierPattern &) override;
+  void visit (HIR::TuplePattern &pattern) override;
 
   // Empty visit for unused Pattern HIR nodes.
   void visit (HIR::AltPattern &) override {}
@@ -90,7 +91,6 @@ public:
   void visit (HIR::QualifiedPathInExpression &) override {}
   void visit (HIR::RangePattern &) override {}
   void visit (HIR::SlicePattern &) override {}
-  void visit (HIR::TuplePattern &) override {}
   void visit (HIR::WildcardPattern &) override {}
 
 protected:
diff --git a/gcc/testsuite/rust/compile/issue-2847.rs 
b/gcc/testsuite/rust/compile/issue-2847.rs
new file mode 100644
index 00000000000..2bc556666c1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2847.rs
@@ -0,0 +1,8 @@
+pub fn myfun1((x, _): (i32, i32)) -> i32 {
+    x
+}
+
+pub fn myfun2() -> i32 {
+    let (x, _) = (1, 2);
+    x
+}
-- 
2.45.2

Reply via email to