From eaac4f2e3cd2031ca1910843762fc57267dca324 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Fri, 13 Dec 2024 15:51:55 +0000 Subject: [PATCH] gccrs: implement the TuplePattern and use it for function patterns 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 --- 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 f73e23359252..bb3e06ce6110 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 c36f7914f346..fed01680c4b0 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -47,12 +47,12 @@ class CompileFnParam : private HIRCompileBase, protected HIR::HIRPatternVisitor 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 a1d2e68914f6..b25c1ae55853 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 (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 (*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 ( + 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 01fd0973e47a..fc12859a4646 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -82,6 +82,7 @@ class CompilePatternBindings : public HIRCompileBase, 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 @@ class CompilePatternBindings : public HIRCompileBase, 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 000000000000..2bc556666c19 --- /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 +}