From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id A2EAB3AA9C5D; Wed, 8 Jun 2022 12:05:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A2EAB3AA9C5D Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Refactor code to reuse a canonical way to compile functions and constants X-Act-Checkin: gcc X-Git-Author: Philip Herron X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 1b487d72cd2ba46671f5a1bcc20970f2dad1b759 X-Git-Newrev: b2aa172ff69591452e3566c105f2a4cd8450eab5 Message-Id: <20220608120527.A2EAB3AA9C5D@sourceware.org> Date: Wed, 8 Jun 2022 12:05:27 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Jun 2022 12:05:27 -0000 https://gcc.gnu.org/g:b2aa172ff69591452e3566c105f2a4cd8450eab5 commit b2aa172ff69591452e3566c105f2a4cd8450eab5 Author: Philip Herron Date: Thu Feb 10 17:08:13 2022 +0000 Refactor code to reuse a canonical way to compile functions and constants This is a big cleanup so all paths that compile functions and constants end up in the same path so we avoid any duplication in how we actually compile a function. Diff: --- gcc/rust/Make-lang.in | 2 + gcc/rust/backend/rust-compile-base.cc | 280 ++++++++++++++ gcc/rust/backend/rust-compile-base.h | 27 +- gcc/rust/backend/rust-compile-expr.cc | 9 +- gcc/rust/backend/rust-compile-extern.h | 6 - gcc/rust/backend/rust-compile-implitem.cc | 102 ++++++ gcc/rust/backend/rust-compile-implitem.h | 504 +------------------------- gcc/rust/backend/rust-compile-item.cc | 202 +++++++++++ gcc/rust/backend/rust-compile-item.h | 367 +------------------ gcc/rust/backend/rust-compile-resolve-path.cc | 10 +- gcc/rust/backend/rust-compile-stmt.h | 28 -- gcc/rust/backend/rust-compile.cc | 100 +---- gcc/rust/hir/tree/rust-hir-item.h | 16 +- gcc/rust/rust-backend.h | 4 - gcc/rust/rust-gcc.cc | 14 - 15 files changed, 648 insertions(+), 1023 deletions(-) diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 660ed235a74..4f762160a54 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -96,6 +96,8 @@ GRS_OBJS = \ rust/rust-compile-intrinsic.o \ rust/rust-compile-pattern.o \ rust/rust-base62.o \ + rust/rust-compile-item.o \ + rust/rust-compile-implitem.o \ rust/rust-compile-expr.o \ rust/rust-compile-type.o \ rust/rust-constexpr.o \ diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 81598c4dc5b..85d85b907ce 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -17,6 +17,11 @@ // . #include "rust-compile-base.h" +#include "rust-compile-item.h" +#include "rust-compile-stmt.h" +#include "rust-compile-fnparam.h" +#include "rust-compile-var-decl.h" + #include "fold-const.h" #include "stringpool.h" @@ -169,5 +174,280 @@ HIRCompileBase::address_expression (tree expr, Location location) return build_fold_addr_expr_loc (location.gcc_location (), expr); } +std::vector +HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib, + tree 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); + return true; + } + + Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); + locals.push_back (compiled); + + return true; + }); + + return locals; +} + +void +HIRCompileBase::compile_function_body (Context *ctx, tree fndecl, + HIR::BlockExpr &function_body, + bool has_return_type) +{ + for (auto &s : function_body.get_statements ()) + { + auto compiled_expr = CompileStmt::Compile (s.get (), ctx); + if (compiled_expr != nullptr) + { + tree compiled_stmt + = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); + ctx->add_statement (compiled_stmt); + } + } + + if (function_body.has_expr ()) + { + // the previous passes will ensure this is a valid return + // or a valid trailing expression + tree compiled_expr + = CompileExpr::Compile (function_body.expr.get (), ctx); + + if (compiled_expr != nullptr) + { + if (has_return_type) + { + std::vector retstmts; + retstmts.push_back (compiled_expr); + + auto ret = ctx->get_backend ()->return_statement ( + fndecl, retstmts, + function_body.get_final_expr ()->get_locus ()); + ctx->add_statement (ret); + } + else + { + tree final_stmt + = ctx->get_backend ()->expression_statement (fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + } + } +} + +tree +HIRCompileBase::compile_function ( + Context *ctx, const std::string &fn_name, HIR::SelfParam &self_param, + std::vector &function_params, + const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility, + AST::AttrVec &outer_attrs, Location locus, HIR::BlockExpr *function_body, + const Resolver::CanonicalPath *canonical_path, TyTy::FnType *fntype, + bool function_has_return) +{ + tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + std::string ir_symbol_name + = canonical_path->get () + fntype->subst_as_string (); + + // we don't mangle the main fn since we haven't implemented the main shim + bool is_main_fn = fn_name.compare ("main") == 0; + std::string asm_name = fn_name; + if (!is_main_fn) + asm_name = ctx->mangle_item (fntype, *canonical_path); + + unsigned int flags = 0; + tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, + asm_name, flags, locus); + setup_attributes_on_fndecl (fndecl, is_main_fn, !visibility.is_error (), + qualifiers, outer_attrs); + setup_abi_options (fndecl, fntype->get_abi ()); + + // insert into the context + ctx->insert_function_decl (fntype, fndecl); + + // setup the params + TyTy::BaseType *tyret = fntype->get_return_type (); + std::vector param_vars; + if (!self_param.is_error ()) + { + rust_assert (fntype->is_method ()); + TyTy::BaseType *self_tyty_lookup = fntype->get_self_type (); + + tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); + Bvariable *compiled_self_param + = CompileSelfParam::compile (ctx, fndecl, self_param, self_type, + self_param.get_locus ()); + + param_vars.push_back (compiled_self_param); + ctx->insert_var_decl (self_param.get_mappings ().get_hirid (), + compiled_self_param); + } + + // offset from + 1 for the TyTy::FnType being used when this is a method to + // skip over Self on the FnType + bool is_method = !self_param.is_error (); + size_t i = is_method ? 1 : 0; + for (auto &referenced_param : function_params) + { + auto tyty_param = fntype->param_at (i++); + auto param_tyty = tyty_param.second; + auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty); + + Location param_locus = referenced_param.get_locus (); + Bvariable *compiled_param_var + = CompileFnParam::compile (ctx, fndecl, &referenced_param, + compiled_param_type, param_locus); + + param_vars.push_back (compiled_param_var); + ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), + compiled_param_var); + } + + if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + // lookup locals + auto body_mappings = function_body->get_mappings (); + Resolver::Rib *rib = nullptr; + bool ok + = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib); + rust_assert (ok); + + std::vector locals + = compile_locals_for_block (ctx, *rib, fndecl); + + tree enclosing_scope = NULL_TREE; + Location start_location = function_body->get_locus (); + Location end_location = function_body->get_end_locus (); + + tree code_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); + ctx->push_block (code_block); + + Bvariable *return_address = nullptr; + if (function_has_return) + { + tree return_type = TyTyResolveCompile::compile (ctx, tyret); + + bool address_is_taken = false; + tree ret_var_stmt = NULL_TREE; + + return_address + = ctx->get_backend ()->temporary_variable (fndecl, code_block, + return_type, NULL, + address_is_taken, locus, + &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); + } + + ctx->push_fn (fndecl, return_address); + compile_function_body (ctx, fndecl, *function_body, function_has_return); + tree bind_tree = ctx->pop_block (); + + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + DECL_SAVED_TREE (fndecl) = bind_tree; + + ctx->pop_fn (); + ctx->push_function (fndecl); + + return fndecl; +} + +tree +HIRCompileBase::compile_constant_item ( + Context *ctx, TyTy::BaseType *resolved_type, + const Resolver::CanonicalPath *canonical_path, HIR::Expr *const_value_expr, + Location locus) +{ + const std::string &ident = canonical_path->get (); + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree const_type = build_qualified_type (type, TYPE_QUAL_CONST); + + bool is_block_expr + = const_value_expr->get_expression_type () == HIR::Expr::ExprType::Block; + + // compile the expression + tree folded_expr = error_mark_node; + if (!is_block_expr) + { + tree value = CompileExpr::Compile (const_value_expr, ctx); + folded_expr = ConstCtx::fold (value); + } + else + { + // in order to compile a block expr we want to reuse as much existing + // machineary that we already have. This means the best approach is to + // make a _fake_ function with a block so it can hold onto temps then + // use our constexpr code to fold it completely or error_mark_node + Backend::typed_identifier receiver; + tree compiled_fn_type = ctx->get_backend ()->function_type ( + receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, + NULL, locus); + + tree fndecl + = ctx->get_backend ()->function (compiled_fn_type, ident, "", 0, locus); + TREE_READONLY (fndecl) = 1; + + tree enclosing_scope = NULL_TREE; + HIR::BlockExpr *function_body + = static_cast (const_value_expr); + Location start_location = function_body->get_locus (); + Location end_location = function_body->get_end_locus (); + + tree code_block + = ctx->get_backend ()->block (fndecl, enclosing_scope, {}, + start_location, end_location); + ctx->push_block (code_block); + + bool address_is_taken = false; + tree ret_var_stmt = NULL_TREE; + Bvariable *return_address + = ctx->get_backend ()->temporary_variable (fndecl, code_block, + const_type, NULL, + address_is_taken, locus, + &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); + ctx->push_fn (fndecl, return_address); + + compile_function_body (ctx, fndecl, *function_body, true); + tree bind_tree = ctx->pop_block (); + + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + DECL_SAVED_TREE (fndecl) = bind_tree; + + ctx->pop_fn (); + + // lets fold it into a call expr + tree call = build_call_array_loc (locus.gcc_location (), const_type, + fndecl, 0, NULL); + folded_expr = ConstCtx::fold (call); + } + + return ctx->get_backend ()->named_constant_expression (const_type, ident, + folded_expr, locus); +} + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index ec7535648aa..17e889cd11a 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -35,14 +35,9 @@ protected: Context *ctx; +protected: Context *get_context () { return ctx; } - void compile_function_body (tree fndecl, HIR::BlockExpr &function_body, - bool has_return_type); - - bool compile_locals_for_block (Resolver::Rib &rib, tree fndecl, - std::vector &locals); - tree coercion_site (tree rvalue, TyTy::BaseType *actual, TyTy::BaseType *expected, Location lvalue_locus, Location rvalue_locus); @@ -81,6 +76,26 @@ protected: static tree address_expression (tree, Location); static bool mark_addressable (tree, Location); + + static std::vector + compile_locals_for_block (Context *ctx, Resolver::Rib &rib, tree fndecl); + + static void compile_function_body (Context *ctx, tree fndecl, + HIR::BlockExpr &function_body, + bool has_return_type); + + static tree compile_function ( + Context *ctx, const std::string &fn_name, HIR::SelfParam &self_param, + std::vector &function_params, + const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility, + AST::AttrVec &outer_attrs, Location locus, HIR::BlockExpr *function_body, + const Resolver::CanonicalPath *canonical_path, TyTy::FnType *fntype, + bool function_has_return); + + static tree + compile_constant_item (Context *ctx, TyTy::BaseType *resolved_type, + const Resolver::CanonicalPath *canonical_path, + HIR::Expr *const_value_expr, Location locus); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index f65e1fd54c8..ab560e8bf34 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -18,6 +18,7 @@ #include "rust-compile.h" #include "rust-compile-item.h" +#include "rust-compile-implitem.h" #include "rust-compile-expr.h" #include "rust-compile-struct-field-expr.h" #include "rust-hir-trait-resolve.h" @@ -713,7 +714,7 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref, tree fn = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) { - return ctx->get_backend ()->function_code_expression (fn, expr_locus); + return address_expression (fn, expr_locus); } // Now we can try and resolve the address since this might be a forward @@ -765,8 +766,7 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref, // contain an implementation we should actually return // error_mark_node - return CompileTraitItem::Compile (receiver, - trait_item_ref->get_hir_trait_item (), + return CompileTraitItem::Compile (trait_item_ref->get_hir_trait_item (), ctx, fntype, true, expr_locus); } else @@ -1343,8 +1343,7 @@ CompileExpr::visit (HIR::IdentifierExpr &expr) } else if (ctx->lookup_function_decl (ref, &fn)) { - translated - = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); + translated = address_expression (fn, expr.get_locus ()); } else if (ctx->lookup_var_decl (ref, &var)) { diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index 143b240e958..1412e7a42eb 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -21,12 +21,6 @@ #include "rust-compile-base.h" #include "rust-compile-intrinsic.h" -#include "rust-compile-tyty.h" -#include "rust-compile-implitem.h" -#include "rust-compile-var-decl.h" -#include "rust-compile-stmt.h" -#include "rust-compile-expr.h" -#include "rust-compile-fnparam.h" namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc new file mode 100644 index 00000000000..8dc18d3c5cc --- /dev/null +++ b/gcc/rust/backend/rust-compile-implitem.cc @@ -0,0 +1,102 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-compile-implitem.h" +#include "rust-compile-expr.h" +#include "rust-compile-fnparam.h" + +namespace Rust { +namespace Compile { + +void +CompileTraitItem::visit (HIR::TraitItemConst &constant) +{ + rust_assert (concrete != nullptr); + TyTy::BaseType *resolved_type = concrete; + + const Resolver::CanonicalPath *canonical_path = nullptr; + bool ok = ctx->get_mappings ()->lookup_canonical_path ( + constant.get_mappings ().get_crate_num (), + constant.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + HIR::Expr *const_value_expr = constant.get_expr ().get (); + tree const_expr + = compile_constant_item (ctx, resolved_type, canonical_path, + const_value_expr, constant.get_locus ()); + ctx->push_const (const_expr); + ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); + + reference = const_expr; +} + +void +CompileTraitItem::visit (HIR::TraitItemFunc &func) +{ + rust_assert (func.has_block_defined ()); + + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast (concrete); + + // items can be forward compiled which means we may not need to invoke this + // code. We might also have already compiled this generic function as well. + tree lookup = NULL_TREE; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, + fntype->get_id (), fntype)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + tree dummy = NULL_TREE; + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) + { + ctx->insert_function_decl (fntype, lookup); + } + reference = address_expression (lookup, ref_locus); + return; + } + } + + if (fntype->has_subsititions_defined ()) + { + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + + const Resolver::CanonicalPath *canonical_path = nullptr; + bool ok = ctx->get_mappings ()->lookup_canonical_path ( + func.get_mappings ().get_crate_num (), func.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + // FIXME + HIR::Visibility vis (HIR::Visibility::PublicVisType::NONE, + AST::SimplePath::create_empty ()); + HIR::TraitFunctionDecl &function = func.get_decl (); + tree fndecl + = compile_function (ctx, function.get_function_name (), + function.get_self (), function.get_function_params (), + function.get_qualifiers (), vis, + func.get_outer_attrs (), func.get_locus (), + func.get_block_expr ().get (), canonical_path, fntype, + function.has_return_type ()); + reference = address_expression (fndecl, ref_locus); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index 93202767f88..60b7246201d 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -19,19 +19,17 @@ #ifndef RUST_COMPILE_IMPLITEM_H #define RUST_COMPILE_IMPLITEM_H -#include "rust-compile-base.h" -#include "rust-compile-tyty.h" -#include "rust-compile-var-decl.h" -#include "rust-compile-stmt.h" +#include "rust-compile-item.h" #include "rust-compile-expr.h" #include "rust-compile-fnparam.h" namespace Rust { namespace Compile { -class CompileInherentImplItem : public HIRCompileBase +// this is a proxy for HIR::ImplItem's back to use the normel HIR::Item path +class CompileInherentImplItem : public CompileItem { - using Rust::Compile::HIRCompileBase::visit; + using Rust::Compile::CompileItem::visit; public: static tree Compile (HIR::ImplItem *item, Context *ctx, @@ -50,265 +48,11 @@ public: return compiler.reference; } - void visit (HIR::ConstantItem &constant) override - { - TyTy::BaseType *resolved_type = nullptr; - bool ok - = ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); - - tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tree value = CompileExpr::Compile (constant.get_expr (), ctx); - - const Resolver::CanonicalPath *canonical_path = nullptr; - ok = ctx->get_mappings ()->lookup_canonical_path ( - constant.get_mappings ().get_crate_num (), - constant.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - - std::string ident = canonical_path->get (); - tree const_expr = ctx->get_backend ()->named_constant_expression ( - type, constant.get_identifier (), value, constant.get_locus ()); - - ctx->push_const (const_expr); - ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); - - reference = const_expr; - } - - void visit (HIR::Function &function) override - { - TyTy::BaseType *fntype_tyty; - if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), - &fntype_tyty)) - { - rust_fatal_error (function.get_locus (), - "failed to lookup function type"); - return; - } - - rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF); - TyTy::FnType *fntype = static_cast (fntype_tyty); - if (fntype->has_subsititions_defined ()) - { - // we cant do anything for this only when it is used and a concrete type - // is given - if (concrete == nullptr) - return; - else - { - rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); - fntype = static_cast (concrete); - } - } - - // items can be forward compiled which means we may not need to invoke this - // code. We might also have already compiled this generic function as well. - tree lookup = NULL_TREE; - if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, - fntype->get_id (), fntype)) - { - // has this been added to the list then it must be finished - if (ctx->function_completed (lookup)) - { - tree dummy = NULL_TREE; - if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) - { - ctx->insert_function_decl (fntype, lookup); - } - reference - = ctx->get_backend ()->function_code_expression (lookup, - ref_locus); - return; - } - } - - if (fntype->has_subsititions_defined ()) - { - // override the Hir Lookups for the substituions in this context - fntype->override_context (); - } - - // convert to the actual function type - tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); - - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - function.get_mappings ().get_crate_num (), - function.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - - std::string ir_symbol_name - = canonical_path->get () + fntype->subst_as_string (); - std::string asm_name = ctx->mangle_item (fntype, *canonical_path); - - unsigned int flags = 0; - tree fndecl - = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, - asm_name, flags, function.get_locus ()); - setup_attributes_on_fndecl (fndecl, false, function.has_visibility (), - function.get_qualifiers (), - function.get_outer_attrs ()); - ctx->insert_function_decl (fntype, fndecl); - - // setup the params - TyTy::BaseType *tyret = fntype->get_return_type (); - std::vector param_vars; - - if (function.is_method ()) - { - // insert self - TyTy::BaseType *self_tyty_lookup = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - function.get_self_param ().get_mappings ().get_hirid (), - &self_tyty_lookup)) - { - rust_error_at (function.get_self_param ().get_locus (), - "failed to lookup self param type"); - return; - } - - tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); - if (self_type == nullptr) - { - rust_error_at (function.get_self_param ().get_locus (), - "failed to compile self param type"); - return; - } - - Bvariable *compiled_self_param - = CompileSelfParam::compile (ctx, fndecl, function.get_self_param (), - self_type, - function.get_self_param ().get_locus ()); - if (compiled_self_param == nullptr) - { - rust_error_at (function.get_self_param ().get_locus (), - "failed to compile self param variable"); - return; - } - - param_vars.push_back (compiled_self_param); - ctx->insert_var_decl ( - function.get_self_param ().get_mappings ().get_hirid (), - compiled_self_param); - } - - // offset from + 1 for the TyTy::FnType being used when this is a method to - // skip over Self on the FnType - size_t i = function.is_method () ? 1 : 0; - for (auto referenced_param : function.get_function_params ()) - { - auto tyty_param = fntype->param_at (i); - auto param_tyty = tyty_param.second; - - auto compiled_param_type - = TyTyResolveCompile::compile (ctx, param_tyty); - if (compiled_param_type == nullptr) - { - rust_error_at (referenced_param.get_locus (), - "failed to compile parameter type"); - return; - } - - Location param_locus - = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()); - Bvariable *compiled_param_var - = CompileFnParam::compile (ctx, fndecl, &referenced_param, - compiled_param_type, param_locus); - if (compiled_param_var == nullptr) - { - rust_error_at (param_locus, "Failed to compile parameter variable"); - return; - } - - param_vars.push_back (compiled_param_var); - - ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), - compiled_param_var); - i++; - } - - if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) - { - rust_fatal_error (function.get_locus (), - "failed to setup parameter variables"); - return; - } - - // lookup locals - auto block_expr = function.get_definition ().get (); - auto body_mappings = block_expr->get_mappings (); - - Resolver::Rib *rib = nullptr; - if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), - &rib)) - { - rust_fatal_error (function.get_locus (), - "failed to setup locals per block"); - return; - } - - std::vector locals; - ok = compile_locals_for_block (*rib, fndecl, locals); - rust_assert (ok); - - tree enclosing_scope = NULL_TREE; - HIR::BlockExpr *function_body = function.get_definition ().get (); - Location start_location = function_body->get_locus (); - Location end_location = function_body->get_end_locus (); - - tree code_block - = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, - start_location, end_location); - ctx->push_block (code_block); - - Bvariable *return_address = nullptr; - if (function.has_function_return_type ()) - { - tree return_type = TyTyResolveCompile::compile (ctx, tyret); - - bool address_is_taken = false; - tree ret_var_stmt = NULL_TREE; - - return_address = ctx->get_backend ()->temporary_variable ( - fndecl, code_block, return_type, NULL, address_is_taken, - function.get_locus (), &ret_var_stmt); - - ctx->add_statement (ret_var_stmt); - } - - ctx->push_fn (fndecl, return_address); - - compile_function_body (fndecl, *function.get_definition ().get (), - function.has_function_return_type ()); - - ctx->pop_block (); - auto body = ctx->get_backend ()->block_statement (code_block); - if (!ctx->get_backend ()->function_set_body (fndecl, body)) - { - rust_error_at (function.get_locus (), "failed to set body to function"); - return; - } - - ctx->pop_fn (); - ctx->push_function (fndecl); - - reference - = ctx->get_backend ()->function_code_expression (fndecl, ref_locus); - } - private: CompileInherentImplItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus) - : HIRCompileBase (ctx), concrete (concrete), - reference (ctx->get_backend ()->error_expression ()), - ref_locus (ref_locus) + : CompileItem (ctx, concrete, ref_locus) {} - - TyTy::BaseType *concrete; - tree reference; - Location ref_locus; }; class CompileTraitItem : public HIRCompileBase @@ -316,12 +60,11 @@ class CompileTraitItem : public HIRCompileBase using Rust::Compile::HIRCompileBase::visit; public: - static tree Compile (const TyTy::BaseType *self, HIR::TraitItem *item, - Context *ctx, TyTy::BaseType *concrete, - bool is_query_mode = false, + static tree Compile (HIR::TraitItem *item, Context *ctx, + TyTy::BaseType *concrete, bool is_query_mode = false, Location ref_locus = Location ()) { - CompileTraitItem compiler (self, ctx, concrete, ref_locus); + CompileTraitItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); if (is_query_mode @@ -332,240 +75,17 @@ public: return compiler.reference; } - void visit (HIR::TraitItemConst &constant) override - { - rust_assert (concrete != nullptr); - TyTy::BaseType *resolved_type = concrete; - - tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tree value = CompileExpr::Compile (constant.get_expr ().get (), ctx); - - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - constant.get_mappings ().get_crate_num (), - constant.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - - std::string ident = canonical_path->get (); - tree const_expr = ctx->get_backend ()->named_constant_expression ( - type, constant.get_name (), value, constant.get_locus ()); - - ctx->push_const (const_expr); - ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); - - reference = const_expr; - } - - void visit (HIR::TraitItemFunc &func) override - { - rust_assert (func.has_block_defined ()); - - rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); - TyTy::FnType *fntype = static_cast (concrete); - - // items can be forward compiled which means we may not need to invoke this - // code. We might also have already compiled this generic function as well. - tree lookup = NULL_TREE; - if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, - fntype->get_id (), fntype)) - { - // has this been added to the list then it must be finished - if (ctx->function_completed (lookup)) - { - tree dummy = NULL_TREE; - if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) - { - ctx->insert_function_decl (fntype, lookup); - } - reference - = ctx->get_backend ()->function_code_expression (lookup, - ref_locus); - return; - } - } - - if (fntype->has_subsititions_defined ()) - { - // override the Hir Lookups for the substituions in this context - fntype->override_context (); - } - - // convert to the actual function type - tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); - HIR::TraitFunctionDecl &function = func.get_decl (); - - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - func.get_mappings ().get_crate_num (), func.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - std::string fn_identifier = canonical_path->get (); - std::string asm_name = ctx->mangle_item (fntype, *canonical_path); - - unsigned int flags = 0; - tree fndecl - = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, - asm_name, flags, func.get_locus ()); - setup_attributes_on_fndecl (fndecl, false, false, - func.get_decl ().get_qualifiers (), - func.get_outer_attrs ()); - ctx->insert_function_decl (fntype, fndecl); - - // setup the params - TyTy::BaseType *tyret = fntype->get_return_type (); - std::vector param_vars; - - if (function.is_method ()) - { - // insert self - TyTy::BaseType *self_tyty_lookup = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - function.get_self ().get_mappings ().get_hirid (), - &self_tyty_lookup)) - { - rust_error_at (function.get_self ().get_locus (), - "failed to lookup self param type"); - return; - } - - tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); - if (self_type == nullptr) - { - rust_error_at (function.get_self ().get_locus (), - "failed to compile self param type"); - return; - } + void visit (HIR::TraitItemConst &constant) override; - Bvariable *compiled_self_param - = CompileSelfParam::compile (ctx, fndecl, function.get_self (), - self_type, - function.get_self ().get_locus ()); - if (compiled_self_param == nullptr) - { - rust_error_at (function.get_self ().get_locus (), - "failed to compile self param variable"); - return; - } - - param_vars.push_back (compiled_self_param); - ctx->insert_var_decl (function.get_self ().get_mappings ().get_hirid (), - compiled_self_param); - } - - // offset from + 1 for the TyTy::FnType being used when this is a method to - // skip over Self on the FnType - size_t i = function.is_method () ? 1 : 0; - for (auto referenced_param : function.get_function_params ()) - { - auto tyty_param = fntype->param_at (i); - auto param_tyty = tyty_param.second; - - auto compiled_param_type - = TyTyResolveCompile::compile (ctx, param_tyty); - if (compiled_param_type == nullptr) - { - rust_error_at (referenced_param.get_locus (), - "failed to compile parameter type"); - return; - } - - Location param_locus - = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()); - Bvariable *compiled_param_var - = CompileFnParam::compile (ctx, fndecl, &referenced_param, - compiled_param_type, param_locus); - if (compiled_param_var == nullptr) - { - rust_error_at (param_locus, "Failed to compile parameter variable"); - return; - } - - param_vars.push_back (compiled_param_var); - - ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), - compiled_param_var); - i++; - } - - if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) - { - rust_fatal_error (func.get_locus (), - "failed to setup parameter variables"); - return; - } - - // lookup locals - auto block_expr = func.get_block_expr ().get (); - auto body_mappings = block_expr->get_mappings (); - - Resolver::Rib *rib = nullptr; - if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), - &rib)) - { - rust_fatal_error (func.get_locus (), - "failed to setup locals per block"); - return; - } - - std::vector locals; - ok = compile_locals_for_block (*rib, fndecl, locals); - rust_assert (ok); - - tree enclosing_scope = NULL_TREE; - HIR::BlockExpr *function_body = func.get_block_expr ().get (); - Location start_location = function_body->get_locus (); - Location end_location = function_body->get_end_locus (); - - tree code_block - = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, - start_location, end_location); - ctx->push_block (code_block); - - Bvariable *return_address = nullptr; - if (function.has_return_type ()) - { - tree return_type = TyTyResolveCompile::compile (ctx, tyret); - - bool address_is_taken = false; - tree ret_var_stmt = NULL_TREE; - - return_address = ctx->get_backend ()->temporary_variable ( - fndecl, code_block, return_type, NULL, address_is_taken, - func.get_locus (), &ret_var_stmt); - - ctx->add_statement (ret_var_stmt); - } - - ctx->push_fn (fndecl, return_address); - - compile_function_body (fndecl, *func.get_block_expr ().get (), - function.has_return_type ()); - - ctx->pop_block (); - auto body = ctx->get_backend ()->block_statement (code_block); - if (!ctx->get_backend ()->function_set_body (fndecl, body)) - { - rust_error_at (func.get_locus (), "failed to set body to function"); - return; - } - - ctx->pop_fn (); - ctx->push_function (fndecl); - - reference - = ctx->get_backend ()->function_code_expression (fndecl, ref_locus); - } + void visit (HIR::TraitItemFunc &func) override; private: - CompileTraitItem (const TyTy::BaseType *self, Context *ctx, - TyTy::BaseType *concrete, Location ref_locus) - : HIRCompileBase (ctx), self (self), concrete (concrete), + CompileTraitItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus) + : HIRCompileBase (ctx), concrete (concrete), reference (ctx->get_backend ()->error_expression ()), ref_locus (ref_locus) {} - const TyTy::BaseType *self; TyTy::BaseType *concrete; tree reference; Location ref_locus; diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc new file mode 100644 index 00000000000..d42cc1ef998 --- /dev/null +++ b/gcc/rust/backend/rust-compile-item.cc @@ -0,0 +1,202 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-compile-item.h" +#include "rust-compile-implitem.h" +#include "rust-compile-expr.h" +#include "rust-compile-extern.h" +#include "rust-constexpr.h" + +namespace Rust { +namespace Compile { + +void +CompileItem::visit (HIR::StaticItem &var) +{ + // have we already compiled this? + Bvariable *static_decl_ref = nullptr; + if (ctx->lookup_var_decl (var.get_mappings ().get_hirid (), &static_decl_ref)) + { + reference + = ctx->get_backend ()->var_expression (static_decl_ref, ref_locus); + return; + } + + TyTy::BaseType *resolved_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + tree type = TyTyResolveCompile::compile (ctx, resolved_type); + tree value = CompileExpr::Compile (var.get_expr (), ctx); + + const Resolver::CanonicalPath *canonical_path = nullptr; + ok = ctx->get_mappings ()->lookup_canonical_path ( + var.get_mappings ().get_crate_num (), var.get_mappings ().get_nodeid (), + &canonical_path); + rust_assert (ok); + + std::string name = canonical_path->get (); + std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path); + + bool is_external = false; + bool is_hidden = false; + bool in_unique_section = true; + + Bvariable *static_global + = ctx->get_backend ()->global_variable (name, asm_name, type, is_external, + is_hidden, in_unique_section, + var.get_locus ()); + ctx->get_backend ()->global_variable_set_init (static_global, value); + + ctx->insert_var_decl (var.get_mappings ().get_hirid (), static_global); + ctx->push_var (static_global); + + reference = ctx->get_backend ()->var_expression (static_global, ref_locus); +} + +void +CompileItem::visit (HIR::ConstantItem &constant) +{ + // resolve the type + TyTy::BaseType *resolved_type = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + // canonical path + const Resolver::CanonicalPath *canonical_path = nullptr; + ok = ctx->get_mappings ()->lookup_canonical_path ( + constant.get_mappings ().get_crate_num (), + constant.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + HIR::Expr *const_value_expr = constant.get_expr (); + tree const_expr + = compile_constant_item (ctx, resolved_type, canonical_path, + const_value_expr, constant.get_locus ()); + + ctx->push_const (const_expr); + ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); + reference = const_expr; +} + +void +CompileItem::visit (HIR::Function &function) +{ + TyTy::BaseType *fntype_tyty; + if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), + &fntype_tyty)) + { + rust_fatal_error (function.get_locus (), + "failed to lookup function type"); + return; + } + + rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *fntype = static_cast (fntype_tyty); + if (fntype->has_subsititions_defined ()) + { + // we cant do anything for this only when it is used and a concrete type + // is given + if (concrete == nullptr) + return; + else + { + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + fntype = static_cast (concrete); + } + } + + // items can be forward compiled which means we may not need to invoke this + // code. We might also have already compiled this generic function as well. + tree lookup = NULL_TREE; + if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, + fntype->get_id (), fntype)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + tree dummy = NULL_TREE; + if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) + { + ctx->insert_function_decl (fntype, lookup); + } + + reference = address_expression (lookup, ref_locus); + return; + } + } + + if (fntype->has_subsititions_defined ()) + { + // override the Hir Lookups for the substituions in this context + fntype->override_context (); + } + + const Resolver::CanonicalPath *canonical_path = nullptr; + bool ok = ctx->get_mappings ()->lookup_canonical_path ( + function.get_mappings ().get_crate_num (), + function.get_mappings ().get_nodeid (), &canonical_path); + rust_assert (ok); + + tree fndecl + = compile_function (ctx, function.get_function_name (), + function.get_self_param (), + function.get_function_params (), + function.get_qualifiers (), function.get_visibility (), + function.get_outer_attrs (), function.get_locus (), + function.get_definition ().get (), canonical_path, + fntype, function.has_function_return_type ()); + reference = address_expression (fndecl, ref_locus); +} + +void +CompileItem::visit (HIR::ImplBlock &impl_block) +{ + TyTy::BaseType *self_lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + impl_block.get_type ()->get_mappings ().get_hirid (), &self_lookup)) + { + rust_error_at (impl_block.get_locus (), "failed to resolve type of impl"); + return; + } + + for (auto &impl_item : impl_block.get_impl_items ()) + CompileInherentImplItem::Compile (impl_item.get (), ctx); +} + +void +CompileItem::visit (HIR::ExternBlock &extern_block) +{ + for (auto &item : extern_block.get_extern_items ()) + { + CompileExternItem::compile (item.get (), ctx, concrete); + } +} + +void +CompileItem::visit (HIR::Module &module) +{ + for (auto &item : module.get_items ()) + CompileItem::compile (item.get (), ctx); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 70b54155fad..71f259f0643 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -20,14 +20,6 @@ #define RUST_COMPILE_ITEM #include "rust-compile-base.h" -#include "rust-compile-tyty.h" -#include "rust-compile-implitem.h" -#include "rust-compile-var-decl.h" -#include "rust-compile-stmt.h" -#include "rust-compile-expr.h" -#include "rust-compile-fnparam.h" -#include "rust-compile-extern.h" -#include "rust-constexpr.h" namespace Rust { namespace Compile { @@ -54,364 +46,17 @@ public: return compiler.reference; } - void visit (HIR::StaticItem &var) override - { - // have we already compiled this? - Bvariable *static_decl_ref = nullptr; - if (ctx->lookup_var_decl (var.get_mappings ().get_hirid (), - &static_decl_ref)) - { - reference - = ctx->get_backend ()->var_expression (static_decl_ref, ref_locus); - return; - } - - TyTy::BaseType *resolved_type = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); - - tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tree value = CompileExpr::Compile (var.get_expr (), ctx); - - const Resolver::CanonicalPath *canonical_path = nullptr; - ok = ctx->get_mappings ()->lookup_canonical_path ( - var.get_mappings ().get_crate_num (), var.get_mappings ().get_nodeid (), - &canonical_path); - rust_assert (ok); - - std::string name = canonical_path->get (); - std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path); - - bool is_external = false; - bool is_hidden = false; - bool in_unique_section = true; - - Bvariable *static_global - = ctx->get_backend ()->global_variable (name, asm_name, type, is_external, - is_hidden, in_unique_section, - var.get_locus ()); - ctx->get_backend ()->global_variable_set_init (static_global, value); - - ctx->insert_var_decl (var.get_mappings ().get_hirid (), static_global); - ctx->push_var (static_global); - - reference = ctx->get_backend ()->var_expression (static_global, ref_locus); - } - - void visit (HIR::ConstantItem &constant) override - { - // resolve the type - TyTy::BaseType *resolved_type = nullptr; - bool ok - = ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); - - // canonical path - const Resolver::CanonicalPath *canonical_path = nullptr; - ok = ctx->get_mappings ()->lookup_canonical_path ( - constant.get_mappings ().get_crate_num (), - constant.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - std::string ident = canonical_path->get (); - - // types - tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tree const_type = build_qualified_type (type, TYPE_QUAL_CONST); - - HIR::Expr *const_value_expr = constant.get_expr (); - bool is_block_expr - = const_value_expr->get_expression_type () == HIR::Expr::ExprType::Block; - - // compile the expression - tree folded_expr = error_mark_node; - if (!is_block_expr) - { - tree value = CompileExpr::Compile (constant.get_expr (), ctx); - folded_expr = ConstCtx::fold (value); - } - else - { - // in order to compile a block expr we want to reuse as much existing - // machineary that we already have. This means the best approach is to - // make a _fake_ function with a block so it can hold onto temps then - // use our constexpr code to fold it completely or error_mark_node - Backend::typed_identifier receiver; - tree compiled_fn_type = ctx->get_backend ()->function_type ( - receiver, {}, - {Backend::typed_identifier ("_", const_type, constant.get_locus ())}, - NULL, constant.get_locus ()); - - tree fndecl - = ctx->get_backend ()->function (compiled_fn_type, ident, "", 0, - constant.get_locus ()); - TREE_READONLY (fndecl) = 1; - - tree enclosing_scope = NULL_TREE; - HIR::BlockExpr *function_body - = static_cast (constant.get_expr ()); - Location start_location = function_body->get_locus (); - Location end_location = function_body->get_end_locus (); - - tree code_block - = ctx->get_backend ()->block (fndecl, enclosing_scope, {}, - start_location, end_location); - ctx->push_block (code_block); - - bool address_is_taken = false; - tree ret_var_stmt = NULL_TREE; - Bvariable *return_address = ctx->get_backend ()->temporary_variable ( - fndecl, code_block, const_type, NULL, address_is_taken, - constant.get_locus (), &ret_var_stmt); - - ctx->add_statement (ret_var_stmt); - ctx->push_fn (fndecl, return_address); - - compile_function_body (fndecl, *function_body, true); - - ctx->pop_block (); - - auto body = ctx->get_backend ()->block_statement (code_block); - if (!ctx->get_backend ()->function_set_body (fndecl, body)) - { - rust_error_at (constant.get_locus (), - "failed to set body to constant function"); - return; - } - - ctx->pop_fn (); - - // lets fold it into a call expr - tree call = build_call_array_loc (constant.get_locus ().gcc_location (), - const_type, fndecl, 0, NULL); - folded_expr = ConstCtx::fold (call); - } - - tree const_expr - = ctx->get_backend ()->named_constant_expression (const_type, ident, - folded_expr, - constant.get_locus ()); - - ctx->push_const (const_expr); - ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); - - reference = const_expr; - } - - void visit (HIR::Function &function) override - { - TyTy::BaseType *fntype_tyty; - if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), - &fntype_tyty)) - { - rust_fatal_error (function.get_locus (), - "failed to lookup function type"); - return; - } - - rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF); - TyTy::FnType *fntype = static_cast (fntype_tyty); - if (fntype->has_subsititions_defined ()) - { - // we cant do anything for this only when it is used and a concrete type - // is given - if (concrete == nullptr) - return; - else - { - rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); - fntype = static_cast (concrete); - } - } - - // items can be forward compiled which means we may not need to invoke this - // code. We might also have already compiled this generic function as well. - tree lookup = NULL_TREE; - if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup, - fntype->get_id (), fntype)) - { - // has this been added to the list then it must be finished - if (ctx->function_completed (lookup)) - { - tree dummy = NULL_TREE; - if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy)) - { - ctx->insert_function_decl (fntype, lookup); - } + void visit (HIR::StaticItem &var) override; - reference - = ctx->get_backend ()->function_code_expression (lookup, - ref_locus); - return; - } - } + void visit (HIR::ConstantItem &constant) override; - if (fntype->has_subsititions_defined ()) - { - // override the Hir Lookups for the substituions in this context - fntype->override_context (); - } + void visit (HIR::Function &function) override; - tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + void visit (HIR::ImplBlock &impl_block) override; - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - function.get_mappings ().get_crate_num (), - function.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); + void visit (HIR::ExternBlock &extern_block) override; - std::string ir_symbol_name - = canonical_path->get () + fntype->subst_as_string (); - std::string asm_name = function.get_function_name (); - - // we don't mangle the main fn since we haven't implemented the main shim - // yet - bool is_main_fn = function.get_function_name ().compare ("main") == 0; - if (!is_main_fn) - { - asm_name = ctx->mangle_item (fntype, *canonical_path); - } - - unsigned int flags = 0; - tree fndecl - = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, - asm_name, flags, function.get_locus ()); - setup_attributes_on_fndecl (fndecl, is_main_fn, function.has_visibility (), - function.get_qualifiers (), - function.get_outer_attrs ()); - - // insert into the context - ctx->insert_function_decl (fntype, fndecl); - - // setup the params - TyTy::BaseType *tyret = fntype->get_return_type (); - std::vector param_vars; - - size_t i = 0; - for (auto &it : fntype->get_params ()) - { - HIR::FunctionParam &referenced_param - = function.get_function_params ().at (i); - auto param_tyty = it.second; - auto compiled_param_type - = TyTyResolveCompile::compile (ctx, param_tyty); - - Location param_locus - = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()); - Bvariable *compiled_param_var - = CompileFnParam::compile (ctx, fndecl, &referenced_param, - compiled_param_type, param_locus); - if (compiled_param_var == nullptr) - { - rust_error_at (param_locus, "failed to compile parameter variable"); - return; - } - - param_vars.push_back (compiled_param_var); - - ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), - compiled_param_var); - i++; - } - - if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) - { - rust_fatal_error (function.get_locus (), - "failed to setup parameter variables"); - return; - } - - // lookup locals - auto block_expr = function.get_definition ().get (); - auto body_mappings = block_expr->get_mappings (); - - Resolver::Rib *rib = nullptr; - if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), - &rib)) - { - rust_fatal_error (function.get_locus (), - "failed to setup locals per block"); - return; - } - - std::vector locals; - ok = compile_locals_for_block (*rib, fndecl, locals); - rust_assert (ok); - - tree enclosing_scope = NULL_TREE; - HIR::BlockExpr *function_body = function.get_definition ().get (); - Location start_location = function_body->get_locus (); - Location end_location = function_body->get_end_locus (); - - tree code_block - = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, - start_location, end_location); - ctx->push_block (code_block); - - Bvariable *return_address = nullptr; - if (function.has_function_return_type ()) - { - tree return_type = TyTyResolveCompile::compile (ctx, tyret); - - bool address_is_taken = false; - tree ret_var_stmt = NULL_TREE; - - return_address = ctx->get_backend ()->temporary_variable ( - fndecl, code_block, return_type, NULL, address_is_taken, - function.get_locus (), &ret_var_stmt); - - ctx->add_statement (ret_var_stmt); - } - - ctx->push_fn (fndecl, return_address); - - compile_function_body (fndecl, *function.get_definition ().get (), - function.has_function_return_type ()); - - ctx->pop_block (); - auto body = ctx->get_backend ()->block_statement (code_block); - if (!ctx->get_backend ()->function_set_body (fndecl, body)) - { - rust_error_at (function.get_locus (), "failed to set body to function"); - return; - } - - ctx->pop_fn (); - ctx->push_function (fndecl); - - reference - = ctx->get_backend ()->function_code_expression (fndecl, ref_locus); - } - - void visit (HIR::ImplBlock &impl_block) override - { - TyTy::BaseType *self_lookup = nullptr; - if (!ctx->get_tyctx ()->lookup_type ( - impl_block.get_type ()->get_mappings ().get_hirid (), &self_lookup)) - { - rust_error_at (impl_block.get_locus (), - "failed to resolve type of impl"); - return; - } - - for (auto &impl_item : impl_block.get_impl_items ()) - CompileInherentImplItem::Compile (impl_item.get (), ctx); - } - - void visit (HIR::ExternBlock &extern_block) override - { - for (auto &item : extern_block.get_extern_items ()) - { - CompileExternItem::compile (item.get (), ctx, concrete); - } - } - - void visit (HIR::Module &module) override - { - for (auto &item : module.get_items ()) - CompileItem::compile (item.get (), ctx); - } + void visit (HIR::Module &module) override; protected: CompileItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index c6240463eae..2ef12320203 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -16,10 +16,10 @@ // along with GCC; see the file COPYING3. If not see // . -#include "rust-linemap.h" -#include "rust-backend.h" #include "rust-compile-resolve-path.h" #include "rust-compile-item.h" +#include "rust-compile-implitem.h" +#include "rust-compile-expr.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" @@ -131,7 +131,7 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, tree fn = NULL_TREE; if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn)) { - return ctx->get_backend ()->function_code_expression (fn, expr_locus); + return address_expression (fn, expr_locus); } } @@ -245,8 +245,8 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, associated->setup_associated_types (); return CompileTraitItem::Compile ( - receiver, trait_item_ref->get_hir_trait_item (), ctx, lookup, - true, expr_locus); + trait_item_ref->get_hir_trait_item (), ctx, lookup, true, + expr_locus); } else { diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index 10f9a52e149..24a2084bae2 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -48,34 +48,6 @@ public: translated = CompileExpr::Compile (stmt.get_expr (), ctx); } - void visit (HIR::ConstantItem &constant) override - { - TyTy::BaseType *resolved_type = nullptr; - bool ok - = ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); - - tree type = TyTyResolveCompile::compile (ctx, resolved_type); - tree value = CompileExpr::Compile (constant.get_expr (), ctx); - - const Resolver::CanonicalPath *canonical_path = nullptr; - ok = ctx->get_mappings ()->lookup_canonical_path ( - constant.get_mappings ().get_crate_num (), - constant.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); - - std::string ident = canonical_path->get (); - tree const_expr - = ctx->get_backend ()->named_constant_expression (type, ident, value, - constant.get_locus ()); - - ctx->push_const (const_expr); - ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); - - translated = const_expr; - } - void visit (HIR::LetStmt &stmt) override { // nothing to do diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 2299ddbb93c..fcbfc05a6c5 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -16,14 +16,16 @@ // along with GCC; see the file COPYING3. If not see // . -#include "rust-compile.h" -#include "rust-compile-item.h" -#include "rust-compile-expr.h" -#include "rust-compile-struct-field-expr.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" #include "rust-hir-type-bounds.h" #include "rust-hir-dot-operator.h" +#include "rust-compile.h" +#include "rust-compile-item.h" +#include "rust-compile-implitem.h" +#include "rust-compile-expr.h" +#include "rust-compile-struct-field-expr.h" +#include "rust-compile-stmt.h" namespace Rust { namespace Compile { @@ -67,9 +69,8 @@ CompileBlock::visit (HIR::BlockExpr &expr) return; } - std::vector locals; - bool ok = compile_locals_for_block (*rib, fndecl, locals); - rust_assert (ok); + std::vector locals + = compile_locals_for_block (ctx, *rib, fndecl); tree enclosing_scope = ctx->peek_enclosing_scope (); tree new_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, @@ -203,87 +204,6 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) // Shared methods in compilation -void -HIRCompileBase::compile_function_body (tree fndecl, - HIR::BlockExpr &function_body, - bool has_return_type) -{ - for (auto &s : function_body.get_statements ()) - { - auto compiled_expr = CompileStmt::Compile (s.get (), ctx); - if (compiled_expr != nullptr) - { - tree compiled_stmt - = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); - ctx->add_statement (compiled_stmt); - } - } - - if (function_body.has_expr ()) - { - // the previous passes will ensure this is a valid return - // or a valid trailing expression - tree compiled_expr - = CompileExpr::Compile (function_body.expr.get (), ctx); - - if (compiled_expr != nullptr) - { - if (has_return_type) - { - std::vector retstmts; - retstmts.push_back (compiled_expr); - - auto ret = ctx->get_backend ()->return_statement ( - fndecl, retstmts, - function_body.get_final_expr ()->get_locus ()); - ctx->add_statement (ret); - } - else - { - tree final_stmt - = ctx->get_backend ()->expression_statement (fndecl, - compiled_expr); - ctx->add_statement (final_stmt); - } - } - } -} - -bool -HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, tree 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); - return true; - } - - Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); - locals.push_back (compiled); - - return true; - }); - - return true; -} - tree HIRCompileBase::coercion_site (tree rvalue, TyTy::BaseType *actual, TyTy::BaseType *expected, Location lvalue_locus, @@ -533,8 +453,8 @@ HIRCompileBase::compute_address_for_trait_item ( rust_assert (trait_item_has_definition); HIR::TraitItem *trait_item = ref->get_hir_trait_item (); - return CompileTraitItem::Compile (root, trait_item, ctx, trait_item_fntype, - true, locus); + return CompileTraitItem::Compile (trait_item, ctx, trait_item_fntype, true, + locus); } bool diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 5fdf8060170..d1cb762dce2 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -510,7 +510,6 @@ struct FunctionParam { std::unique_ptr param_name; std::unique_ptr type; - Location locus; Analysis::NodeMapping mappings; @@ -1226,11 +1225,7 @@ public: bool is_method () const { return !self.is_error (); } - SelfParam &get_self_param () - { - rust_assert (is_method ()); - return self; - } + SelfParam &get_self_param () { return self; } protected: /* Use covariance to implement clone function as returning this object @@ -2242,11 +2237,7 @@ public: bool is_method () const { return !self.is_error (); } - SelfParam &get_self () - { - rust_assert (is_method ()); - return self; - } + SelfParam &get_self () { return self; } Identifier get_function_name () const { return function_name; } @@ -2341,7 +2332,8 @@ public: return TraitItemKind::FUNC; } - AST::AttrVec get_outer_attrs () const { return outer_attrs; } + AST::AttrVec &get_outer_attrs () { return outer_attrs; } + const AST::AttrVec &get_outer_attrs () const { return outer_attrs; } protected: // Clone function implementation as (not pure) virtual method diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index f7a1ac60471..ac856af9756 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -251,10 +251,6 @@ public: // Return an expression that converts EXPR to TYPE. virtual tree convert_expression (tree type, tree expr, Location) = 0; - // Create an expression for the address of a function. This is used to - // get the address of the code for a function. - virtual tree function_code_expression (tree, Location) = 0; - // Return an expression for the field at INDEX in BSTRUCT. virtual tree struct_field_expression (tree bstruct, size_t index, Location) = 0; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 86a4106162c..b648365f253 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -229,8 +229,6 @@ public: tree convert_expression (tree type, tree expr, Location); - tree function_code_expression (tree, Location); - tree struct_field_expression (tree, size_t, Location); tree compound_expression (tree, tree, Location); @@ -1305,18 +1303,6 @@ Gcc_backend::convert_expression (tree type_tree, tree expr_tree, return ret; } -// Get the address of a function. - -tree -Gcc_backend::function_code_expression (tree func, Location location) -{ - if (func == error_mark_node) - return this->error_expression (); - - tree ret = build_fold_addr_expr_loc (location.gcc_location (), func); - return ret; -} - // Return an expression for the field at INDEX in BSTRUCT. tree