From 92a434a33904608f5659cf7b5d4df3d2a99bd5bd Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 23 Jun 2021 17:22:12 +0100 Subject: Add support for nested functions We missed that stmts in rust can be items like functions. This adds support for resolution and compilation of nested functions. Rust allows nested functions which are distinct to closures. Nested functions are not allowed to encapsulate the enclosing scope so they can be extracted as normal functions. --- gcc/rust/backend/rust-compile-base.h | 3 ++ gcc/rust/backend/rust-compile-implitem.h | 44 ++++----------------------- gcc/rust/backend/rust-compile-item.h | 22 ++------------ gcc/rust/backend/rust-compile.cc | 51 +++++++++++++++++++++++--------- 4 files changed, 49 insertions(+), 71 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index ed33515..c346af5 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -210,6 +210,9 @@ protected: void compile_function_body (Bfunction *fndecl, std::unique_ptr &function_body, bool has_return_type); + + bool compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl, + std::vector &locals); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index d6698d1..70f76b7 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -183,26 +183,10 @@ public: } std::vector locals; - rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool { - Resolver::Definition d; - bool ok = ctx->get_resolver ()->lookup_definition (n, &d); - rust_assert (ok); - - HIR::Stmt *decl = nullptr; - ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); - rust_assert (ok); - - Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); - locals.push_back (compiled); - - return true; - }); - - bool toplevel_item - = function.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID; - Bblock *enclosing_scope - = toplevel_item ? NULL : ctx->peek_enclosing_scope (); + bool ok = compile_locals_for_block (*rib, fndecl, locals); + rust_assert (ok); + Bblock *enclosing_scope = NULL; HIR::BlockExpr *function_body = function.get_definition ().get (); Location start_location = function_body->get_locus (); Location end_location = function_body->get_closing_locus (); @@ -409,26 +393,10 @@ public: } std::vector locals; - rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool { - Resolver::Definition d; - bool ok = ctx->get_resolver ()->lookup_definition (n, &d); - rust_assert (ok); - - HIR::Stmt *decl = nullptr; - ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); - rust_assert (ok); - - Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); - locals.push_back (compiled); - - return true; - }); - - bool toplevel_item - = method.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID; - Bblock *enclosing_scope - = toplevel_item ? NULL : ctx->peek_enclosing_scope (); + bool ok = compile_locals_for_block (*rib, fndecl, locals); + rust_assert (ok); + Bblock *enclosing_scope = NULL; HIR::BlockExpr *function_body = method.get_function_body ().get (); Location start_location = function_body->get_locus (); Location end_location = function_body->get_closing_locus (); diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 8a521e7..eacfda9 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -213,26 +213,10 @@ public: } std::vector locals; - rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool { - Resolver::Definition d; - bool ok = ctx->get_resolver ()->lookup_definition (n, &d); - rust_assert (ok); - - HIR::Stmt *decl = nullptr; - ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); - rust_assert (ok); - - Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); - locals.push_back (compiled); - - return true; - }); - - bool toplevel_item - = function.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID; - Bblock *enclosing_scope - = toplevel_item ? NULL : ctx->peek_enclosing_scope (); + bool ok = compile_locals_for_block (*rib, fndecl, locals); + rust_assert (ok); + Bblock *enclosing_scope = NULL; HIR::BlockExpr *function_body = function.get_definition ().get (); Location start_location = function_body->get_locus (); Location end_location = function_body->get_closing_locus (); diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 351271c..5ffd11a 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -212,20 +212,8 @@ CompileBlock::visit (HIR::BlockExpr &expr) } std::vector locals; - rib->iterate_decls ([&] (NodeId n, Location) mutable -> bool { - Resolver::Definition d; - bool ok = ctx->get_resolver ()->lookup_definition (n, &d); - rust_assert (ok); - - HIR::Stmt *decl = nullptr; - ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); - rust_assert (ok); - - Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); - locals.push_back (compiled); - - return true; - }); + bool ok = compile_locals_for_block (*rib, fndecl, locals); + rust_assert (ok); Bblock *enclosing_scope = ctx->peek_enclosing_scope (); Bblock *new_block @@ -415,6 +403,41 @@ HIRCompileBase::compile_function_body ( } } +bool +HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, Bfunction *fndecl, + std::vector &locals) +{ + rib.iterate_decls ([&] (NodeId n, Location) mutable -> bool { + Resolver::Definition d; + bool ok = ctx->get_resolver ()->lookup_definition (n, &d); + rust_assert (ok); + + HIR::Stmt *decl = nullptr; + ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); + rust_assert (ok); + + // if its a function we extract this out side of this fn context + // and it is not a local to this function + bool is_item = ctx->get_mappings ()->lookup_hir_item ( + decl->get_mappings ().get_crate_num (), + decl->get_mappings ().get_hirid ()) + != nullptr; + if (is_item) + { + HIR::Item *item = static_cast (decl); + CompileItem::compile (item, ctx, true); + return true; + } + + Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); + locals.push_back (compiled); + + return true; + }); + + return true; +} + // Mr Mangle time static const std::string kMangledSymbolPrefix = "_ZN"; -- cgit v1.1