Skip to content

Commit

Permalink
gccrs: implement the TuplePattern and use it for function patterns
Browse files Browse the repository at this point in the history
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 #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 <[email protected]>
  • Loading branch information
philberty committed Dec 13, 2024
1 parent cc2445c commit daa2977
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 14 deletions.
31 changes: 20 additions & 11 deletions gcc/rust/backend/rust-compile-fnparam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand All @@ -102,18 +113,16 @@ 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
tree tmp_ident = create_tmp_var_name ("RSTPRM");
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
Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/backend/rust-compile-fnparam.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
86 changes: 86 additions & 0 deletions gcc/rust/backend/rust-compile-pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion gcc/rust/backend/rust-compile-pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand All @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions gcc/testsuite/rust/compile/issue-2847.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub fn myfun1((x, _): (i32, i32)) -> i32 {
x
}

pub fn myfun2() -> i32 {
let (x, _) = (1, 2);
x
}

0 comments on commit daa2977

Please sign in to comment.