diff options
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r-- | gcc/rust/backend/cscope.h | 160 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-base.h | 6 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-block.h | 41 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 16 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 54 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-fnparam.h | 16 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-implitem.h | 248 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-item.h | 38 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-stmt.h | 26 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-tyty.h | 23 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 201 |
11 files changed, 531 insertions, 298 deletions
diff --git a/gcc/rust/backend/cscope.h b/gcc/rust/backend/cscope.h deleted file mode 100644 index 3ba837c..0000000 --- a/gcc/rust/backend/cscope.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (C) 2020 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 -// <http://www.gnu.org/licenses/>. - -#pragma once - -#include "rust-system.h" -#include "rust-backend.h" -#include "scope.h" - -namespace Rust { -namespace Compile { - -class Scope -{ -public: - Scope (Backend *backend) : backend (backend) {} - - ~Scope () {} - - void Push () - { - fndecls.Push (); - vars.Push (); - types.Push (); - structDecls.Push (); - } - - void Pop () - { - fndecls.Pop (); - vars.Pop (); - types.Pop (); - structDecls.Pop (); - } - - void PushCurrentFunction (std::string name, Bfunction *fn, Btype *retType, - Bvariable *retDecl) - { - fns.push_back (fn); - fnRetType.push_back (retType); - fnRetDecl.push_back (retDecl); - } - - Bfunction *PopCurrentFunction () - { - auto ret = fns.back (); - fns.pop_back (); - fnRetType.pop_back (); - fnRetDecl.pop_back (); - return ret; - } - - Bfunction *GetCurrentFndecl () { return fns.back (); } - - Btype *GetCurrentFnRetType () { return fnRetType.back (); } - - Bvariable *GetCurrentFnRetDecl () { return fnRetDecl.back (); } - - Btype *GetFnRetType (Bfunction *fn) - { - auto it = fnRetTypeMapping.find (fn); - if (it == fnRetTypeMapping.end ()) - { - return NULL; - } - return it->second; - } - - void PushBlock (Bblock *block) - { - blocks.push_back (block); - std::vector<Bstatement *> empty; - context.push_back (empty); - } - - Bblock *PopBlock () - { - auto ret = blocks.back (); - blocks.pop_back (); - - auto stmts = context.back (); - context.pop_back (); - - backend->block_add_statements (ret, stmts); - - return ret; - } - - Bblock *CurBlock () { return blocks.back (); } - - void AddStatement (Bstatement *stmt) { context.back ().push_back (stmt); } - - void InsertStructDecl (std::string name, AST::StructStruct *decl) - { - structDecls.Insert (name, decl); - } - - bool LookupStructDecl (std::string name, AST::StructStruct **decl) - { - return structDecls.Lookup (name, decl); - } - - void InsertFunction (std::string name, Bfunction *fn, Btype *retType) - { - fndecls.Insert (name, fn); - fnRetTypeMapping[fn] = retType; - } - - bool LookupFunction (std::string name, Bfunction **fn) - { - return fndecls.Lookup (name, fn); - } - - void InsertType (std::string name, Btype *type) { types.Insert (name, type); } - - bool LookupType (std::string name, Btype **type) - { - return types.Lookup (name, type); - } - - void InsertVar (std::string name, Bvariable *var) { vars.Insert (name, var); } - - bool LookupVar (std::string name, Bvariable **var) - { - return vars.Lookup (name, var); - } - -private: - Backend *backend; - - ::std::vector<Bfunction *> fns; - ::std::vector<Bblock *> blocks; - ::std::vector< ::std::vector<Bstatement *> > context; - ::std::vector< ::Btype *> fnRetType; - ::std::vector< ::Bvariable *> fnRetDecl; - ::std::map<Bfunction *, Btype *> fnRetTypeMapping; - - Analysis::Scope<Bfunction *> fndecls; - Analysis::Scope<Bvariable *> vars; - Analysis::Scope<Btype *> types; - Analysis::Scope<AST::StructStruct *> structDecls; -}; - -} // namespace Compile -} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index fdc5ad9..ec7c13a 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -237,9 +237,13 @@ public: protected: HIRCompileBase (Context *ctx) : ctx (ctx) {} + Context *ctx; + Context *get_context () { return ctx; } - Context *ctx; + void compile_function_body (Bfunction *fndecl, + std::unique_ptr<HIR::BlockExpr> &function_body, + bool has_return_type); }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index b17fb05..879e32d 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -28,35 +28,35 @@ namespace Compile { class CompileBlock : public HIRCompileBase { public: - static Bblock *compile (HIR::BlockExpr *expr, Context *ctx) + static Bblock *compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) { - CompileBlock compiler (ctx); + CompileBlock compiler (ctx, result); expr->accept_vis (compiler); return compiler.translated; } - ~CompileBlock () {} - void visit (HIR::BlockExpr &expr); private: - CompileBlock (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} + CompileBlock (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) + {} Bblock *translated; + Bvariable *result; }; class CompileConditionalBlocks : public HIRCompileBase { public: - static Bstatement *compile (HIR::IfExpr *expr, Context *ctx) + static Bstatement *compile (HIR::IfExpr *expr, Context *ctx, + Bvariable *result) { - CompileConditionalBlocks resolver (ctx); + CompileConditionalBlocks resolver (ctx, result); expr->accept_vis (resolver); return resolver.translated; } - ~CompileConditionalBlocks () {} - void visit (HIR::IfExpr &expr); void visit (HIR::IfExprConseqElse &expr); @@ -64,46 +64,47 @@ public: void visit (HIR::IfExprConseqIf &expr); private: - CompileConditionalBlocks (Context *ctx) - : HIRCompileBase (ctx), translated (nullptr) + CompileConditionalBlocks (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) {} Bstatement *translated; + Bvariable *result; }; class CompileExprWithBlock : public HIRCompileBase { public: - static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx) + static Bstatement *compile (HIR::ExprWithBlock *expr, Context *ctx, + Bvariable *result) { - CompileExprWithBlock resolver (ctx); + CompileExprWithBlock resolver (ctx, result); expr->accept_vis (resolver); return resolver.translated; } - ~CompileExprWithBlock () {} - void visit (HIR::IfExpr &expr) { - translated = CompileConditionalBlocks::compile (&expr, ctx); + translated = CompileConditionalBlocks::compile (&expr, ctx, result); } void visit (HIR::IfExprConseqElse &expr) { - translated = CompileConditionalBlocks::compile (&expr, ctx); + translated = CompileConditionalBlocks::compile (&expr, ctx, result); } void visit (HIR::IfExprConseqIf &expr) { - translated = CompileConditionalBlocks::compile (&expr, ctx); + translated = CompileConditionalBlocks::compile (&expr, ctx, result); } private: - CompileExprWithBlock (Context *ctx) - : HIRCompileBase (ctx), translated (nullptr) + CompileExprWithBlock (Context *ctx, Bvariable *result) + : HIRCompileBase (ctx), translated (nullptr), result (result) {} Bstatement *translated; + Bvariable *result; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 034568f..25c9b89 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -110,6 +110,11 @@ public: return scope_stack.back (); } + void add_statement_to_enclosing_scope (Bstatement *stmt) + { + statements.at (statements.size () - 2).push_back (stmt); + } + void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); } void insert_var_decl (HirId id, ::Bvariable *decl) @@ -222,11 +227,11 @@ public: virtual ~TyTyResolveCompile () {} - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } + void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + void visit (TyTy::StructFieldType &) override { gcc_unreachable (); } void visit (TyTy::FnType &type) override { @@ -261,7 +266,7 @@ public: ctx->get_mappings ()->lookup_location (type.get_ref ())); } - void visit (TyTy::UnitType &type) override + void visit (TyTy::UnitType &) override { translated = ctx->get_backend ()->void_type (); } @@ -278,8 +283,7 @@ public: { TyTy::StructFieldType *field = type.get_field (i); Btype *compiled_field_ty - = TyTyCompile::compile (ctx->get_backend (), - field->get_field_type ()); + = TyTyResolveCompile::compile (ctx, field->get_field_type ()); Backend::Btyped_identifier f (field->get_name (), compiled_field_ty, ctx->get_mappings ()->lookup_location ( diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index ccff51a..b823d29 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -99,6 +99,8 @@ public: void visit (HIR::CallExpr &expr); + void visit (HIR::MethodCallExpr &expr); + void visit (HIR::IdentifierExpr &expr) { // need to look up the reference for this identifier @@ -409,27 +411,71 @@ public: void visit (HIR::IfExpr &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx); + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); ctx->add_statement (stmt); } void visit (HIR::IfExprConseqElse &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx); + // this can be a return expression + TyTy::TyBase *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + Bvariable *tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); ctx->add_statement (stmt); + + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); } void visit (HIR::IfExprConseqIf &expr) { - auto stmt = CompileConditionalBlocks::compile (&expr, ctx); + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); ctx->add_statement (stmt); } void visit (HIR::BlockExpr &expr) { - auto code_block = CompileBlock::compile (&expr, ctx); + TyTy::TyBase *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + + fncontext fnctx = ctx->peek_fn (); + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + Btype *block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + Bstatement *ret_var_stmt = nullptr; + Bvariable *tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + + auto code_block = CompileBlock::compile (&expr, ctx, tmp); auto block_stmt = ctx->get_backend ()->block_statement (code_block); ctx->add_statement (block_stmt); + + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); } void visit (HIR::StructExprStructFields &struct_expr) diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h index cf6e6f7..1ea0c9f 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -61,6 +61,22 @@ private: ::Bvariable *translated; }; +class CompileSelfParam : public HIRCompileBase +{ +public: + static Bvariable *compile (Context *ctx, Bfunction *fndecl, + HIR::SelfParam &self, Btype *decl_type, + Location locus) + { + if (!self.get_is_mut ()) + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + return ctx->get_backend ()->parameter_variable (fndecl, "self", decl_type, + false /* address_taken */, + locus); + } +}; + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index fe2abf1..6d180c8 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -32,10 +32,10 @@ namespace Compile { class CompileInherentImplItem : public HIRCompileBase { public: - static void Compile (HIR::Type *base, HIR::InherentImplItem *item, + static void Compile (TyTy::TyBase *self, HIR::InherentImplItem *item, Context *ctx, bool compile_fns) { - CompileInherentImplItem compiler (base, ctx, compile_fns); + CompileInherentImplItem compiler (self, ctx, compile_fns); item->accept_vis (compiler); } @@ -50,7 +50,7 @@ public: ::Btype *type = TyTyResolveCompile::compile (ctx, resolved_type); Bexpression *value = CompileExpr::Compile (constant.get_expr (), ctx); - std::string ident = base->as_string () + "::" + constant.get_identifier (); + std::string ident = self->as_string () + "::" + constant.get_identifier (); Bexpression *const_expr = ctx->get_backend ()->named_constant_expression ( type, constant.get_identifier (), value, constant.get_locus ()); @@ -78,7 +78,8 @@ public: if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), &fntype_tyty)) { - rust_fatal_error (function.locus, "failed to lookup function type"); + rust_fatal_error (function.get_locus (), + "failed to lookup function type"); return; } @@ -93,23 +94,15 @@ public: ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); unsigned int flags = 0; - bool is_main_fn = function.function_name.compare ("main") == 0; - std::string fn_identifier - = base->as_string () + "::" + function.function_name; + = self->as_string () + "::" + function.function_name; // if its the main fn or pub visibility mark its as DECL_PUBLIC // please see https://github.com/Rust-GCC/gccrs/pull/137 - if (is_main_fn || function.has_visibility ()) + if (function.has_visibility ()) flags |= Backend::function_is_visible; std::string asm_name = fn_identifier; - if (!is_main_fn) - { - // FIXME need name mangling - asm_name = "__" + function.function_name; - } - Bfunction *fndecl = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, asm_name, flags, function.get_locus ()); @@ -213,34 +206,219 @@ public: ctx->push_fn (fndecl, return_address); - // compile the block - function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - CompileStmt::Compile (s, ctx); + compile_function_body (fndecl, function.function_body, + 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); + } + + void visit (HIR::Method &method) + { + if (!compile_fns) + return; + + // items can be forward compiled which means we may not need to invoke this + // code + Bfunction *lookup = nullptr; + if (ctx->lookup_function_decl (method.get_mappings ().get_hirid (), + &lookup)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + return; + } + + TyTy::TyBase *fntype_tyty; + if (!ctx->get_tyctx ()->lookup_type (method.get_mappings ().get_hirid (), + &fntype_tyty)) + { + rust_fatal_error (method.get_locus (), + "failed to lookup function type"); + return; + } + + if (fntype_tyty->get_kind () != TyTy::TypeKind::FNDEF) + { + rust_error_at (method.get_locus (), "invalid TyTy for function item"); + return; + } + + TyTy::FnType *fntype = (TyTy::FnType *) fntype_tyty; + // convert to the actual function type + ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); + + unsigned int flags = 0; + std::string fn_identifier + = self->as_string () + "::" + method.get_method_name (); + + // if its the main fn or pub visibility mark its as DECL_PUBLIC + // please see https://github.com/Rust-GCC/gccrs/pull/137 + if (method.has_visibility ()) + flags |= Backend::function_is_visible; + + std::string asm_name = fn_identifier; + Bfunction *fndecl + = ctx->get_backend ()->function (compiled_fn_type, fn_identifier, + asm_name, flags, method.get_locus ()); + ctx->insert_function_decl (method.get_mappings ().get_hirid (), fndecl); + + // setup the params + TyTy::TyBase *tyret = fntype->return_type (); + std::vector<Bvariable *> param_vars; + + // insert self + TyTy::TyBase *self_tyty_lookup = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + method.get_self_param ().get_mappings ().get_hirid (), + &self_tyty_lookup)) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to lookup self param type"); + return; + } + + Btype *self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); + if (self_type == nullptr) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to compile self param type"); + return; + } + + Bvariable *compiled_self_param + = CompileSelfParam::compile (ctx, fndecl, method.get_self_param (), + self_type, + method.get_self_param ().get_locus ()); + if (compiled_self_param == nullptr) + { + rust_error_at (method.get_self_param ().get_locus (), + "failed to compile self param variable"); + return; + } + + param_vars.push_back (compiled_self_param); + ctx->insert_var_decl (method.get_self_param ().get_mappings ().get_hirid (), + compiled_self_param); + + // offset from + 1 for the TyTy::FnType being used + size_t i = 1; + for (auto referenced_param : method.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 (method.get_locus (), + "failed to setup parameter variables"); + return; + } + + // lookup locals + auto block_expr = method.get_function_body ().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 (method.get_locus (), + "failed to setup locals per block"); + return; + } + + std::vector<Bvariable *> 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; }); - if (function_body->has_expr () && function_body->tail_expr_reachable ()) + bool toplevel_item + = method.get_mappings ().get_local_defid () != UNKNOWN_LOCAL_DEFID; + Bblock *enclosing_scope + = toplevel_item ? NULL : ctx->peek_enclosing_scope (); + + HIR::BlockExpr *function_body = method.get_function_body ().get (); + Location start_location = function_body->get_locus (); + Location end_location = function_body->get_closing_locus (); + + Bblock *code_block + = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); + ctx->push_block (code_block); + + Bvariable *return_address = nullptr; + if (method.has_function_return_type ()) { - // the previous passes will ensure this is a valid return - // dead code elimination should remove any bad trailing expressions - Bexpression *compiled_expr - = CompileExpr::Compile (function_body->expr.get (), ctx); - rust_assert (compiled_expr != nullptr); - - auto fncontext = ctx->peek_fn (); - - std::vector<Bexpression *> retstmts; - retstmts.push_back (compiled_expr); - auto s = ctx->get_backend ()->return_statement ( - fncontext.fndecl, retstmts, function_body->expr->get_locus_slow ()); - ctx->add_statement (s); + Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); + + bool address_is_taken = false; + Bstatement *ret_var_stmt = nullptr; + + return_address = ctx->get_backend ()->temporary_variable ( + fndecl, code_block, return_type, NULL, address_is_taken, + method.get_locus (), &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); } + ctx->push_fn (fndecl, return_address); + + compile_function_body (fndecl, method.get_function_body (), + method.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"); + rust_error_at (method.get_locus (), "failed to set body to function"); return; } @@ -250,11 +428,11 @@ public: } private: - CompileInherentImplItem (HIR::Type *base, Context *ctx, bool compile_fns) - : HIRCompileBase (ctx), base (base), compile_fns (compile_fns) + CompileInherentImplItem (TyTy::TyBase *self, Context *ctx, bool compile_fns) + : HIRCompileBase (ctx), self (self), compile_fns (compile_fns) {} - HIR::Type *base; + TyTy::TyBase *self; bool compile_fns; }; diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 83e4451..7f93af9f 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -265,28 +265,8 @@ public: ctx->push_fn (fndecl, return_address); - // compile the block - function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - CompileStmt::Compile (s, ctx); - return true; - }); - - if (function_body->has_expr () && function_body->tail_expr_reachable ()) - { - // the previous passes will ensure this is a valid return - // dead code elimination should remove any bad trailing expressions - Bexpression *compiled_expr - = CompileExpr::Compile (function_body->expr.get (), ctx); - rust_assert (compiled_expr != nullptr); - - auto fncontext = ctx->peek_fn (); - - std::vector<Bexpression *> retstmts; - retstmts.push_back (compiled_expr); - auto s = ctx->get_backend ()->return_statement ( - fncontext.fndecl, retstmts, function_body->expr->get_locus_slow ()); - ctx->add_statement (s); - } + compile_function_body (fndecl, function.function_body, + function.has_function_return_type ()); ctx->pop_block (); auto body = ctx->get_backend ()->block_statement (code_block); @@ -297,15 +277,23 @@ public: } ctx->pop_fn (); - ctx->push_function (fndecl); } void visit (HIR::InherentImpl &impl_block) { + TyTy::TyBase *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_block.get_type ().get (), - impl_item.get (), ctx, compile_fns); + CompileInherentImplItem::Compile (self_lookup, impl_item.get (), ctx, + compile_fns); } private: diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index c52f605..d021240e4 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -29,37 +29,24 @@ namespace Compile { class CompileStmt : public HIRCompileBase { public: - static void Compile (HIR::Stmt *stmt, Context *ctx) + static Bexpression *Compile (HIR::Stmt *stmt, Context *ctx) { CompileStmt compiler (ctx); stmt->accept_vis (compiler); rust_assert (compiler.ok); + return compiler.translated; } - virtual ~CompileStmt () {} - void visit (HIR::ExprStmtWithBlock &stmt) { ok = true; - auto translated = CompileExpr::Compile (stmt.get_expr (), ctx); - - // these can be null - if (translated == nullptr) - return; - - gcc_unreachable (); + translated = CompileExpr::Compile (stmt.get_expr (), ctx); } void visit (HIR::ExprStmtWithoutBlock &stmt) { ok = true; - auto translated = CompileExpr::Compile (stmt.get_expr (), ctx); - - // these can be null - if (translated == nullptr) - return; - - gcc_unreachable (); + translated = CompileExpr::Compile (stmt.get_expr (), ctx); } void visit (HIR::LetStmt &stmt) @@ -99,9 +86,12 @@ public: } private: - CompileStmt (Context *ctx) : HIRCompileBase (ctx), ok (false) {} + CompileStmt (Context *ctx) + : HIRCompileBase (ctx), ok (false), translated (nullptr) + {} bool ok; + Bexpression *translated; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 2c54b17..0629cbe 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -44,22 +44,19 @@ public: ~TyTyCompile () {} - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } + void visit (TyTy::InferType &) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + void visit (TyTy::StructFieldType &) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &) override { gcc_unreachable (); } - void visit (TyTy::TupleType &type) override { gcc_unreachable (); } + void visit (TyTy::TupleType &) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &) override { gcc_unreachable (); } - void visit (TyTy::UnitType &type) override - { - translated = backend->void_type (); - } + void visit (TyTy::UnitType &) override { translated = backend->void_type (); } void visit (TyTy::FnType &type) override { @@ -93,7 +90,7 @@ public: mappings->lookup_location (type.get_ref ())); } - void visit (TyTy::BoolType &type) override + void visit (TyTy::BoolType &) override { translated = backend->named_type ("bool", backend->bool_type (), Linemap::predeclared_location ()); @@ -190,14 +187,14 @@ public: gcc_unreachable (); } - void visit (TyTy::USizeType &type) override + void visit (TyTy::USizeType &) override { translated = backend->named_type ( "usize", backend->integer_type (true, backend->get_pointer_size ()), Linemap::predeclared_location ()); } - void visit (TyTy::ISizeType &type) override + void visit (TyTy::ISizeType &) override { translated = backend->named_type ( "isize", backend->integer_type (false, backend->get_pointer_size ()), diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index ce6d827..0b83c72 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -95,6 +95,83 @@ CompileExpr::visit (HIR::CallExpr &expr) } } +void +CompileExpr::visit (HIR::MethodCallExpr &expr) +{ + // lookup the resolved name + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at (expr.get_locus (), "failed to lookup resolved MethodCall"); + return; + } + + // reverse lookup + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + // lookup compiled functions + Bfunction *fn = nullptr; + if (!ctx->lookup_function_decl (ref, &fn)) + { + // this might fail because its a forward decl so we can attempt to + // resolve it now + HIR::InherentImplItem *resolved_item + = ctx->get_mappings ()->lookup_hir_implitem ( + expr.get_mappings ().get_crate_num (), ref); + if (resolved_item == nullptr) + { + rust_error_at (expr.get_locus (), "failed to lookup forward decl"); + return; + } + + TyTy::TyBase *self_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver ()->get_mappings ().get_hirid (), &self_type)) + { + rust_error_at (expr.get_locus (), + "failed to resolve type for self param"); + return; + } + + CompileInherentImplItem::Compile (self_type, resolved_item, ctx, true); + if (!ctx->lookup_function_decl (ref, &fn)) + { + rust_error_at (expr.get_locus (), "forward decl was not compiled"); + return; + } + } + + Bexpression *fn_expr + = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); + + std::vector<Bexpression *> args; + + // method receiver + Bexpression *self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); + rust_assert (self != nullptr); + args.push_back (self); + + // normal args + expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); + rust_assert (compiled_expr != nullptr); + args.push_back (compiled_expr); + return true; + }); + + auto fncontext = ctx->peek_fn (); + translated + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn_expr, args, + nullptr, expr.get_locus ()); +} + // rust-compile-block.h void @@ -135,10 +212,30 @@ CompileBlock::visit (HIR::BlockExpr &expr) start_location, end_location); ctx->push_block (new_block); - expr.iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { - CompileStmt::Compile (s, ctx); - return true; - }); + for (auto &s : expr.get_statements ()) + { + auto compiled_expr = CompileStmt::Compile (s.get (), ctx); + if (compiled_expr == nullptr) + continue; + + if (result == nullptr) + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + else + { + Bexpression *result_reference + = ctx->get_backend ()->var_expression (result, + s->get_locus_slow ()); + + Bstatement *assignment = ctx->get_backend ()->assignment_statement ( + fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ()); + ctx->add_statement (assignment); + } + } if (expr.has_expr () && expr.tail_expr_reachable ()) { @@ -147,14 +244,22 @@ CompileBlock::visit (HIR::BlockExpr &expr) Bexpression *compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); rust_assert (compiled_expr != nullptr); - auto fncontext = ctx->peek_fn (); + if (result == nullptr) + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + else + { + Bexpression *result_reference = ctx->get_backend ()->var_expression ( + result, expr.get_final_expr ()->get_locus_slow ()); - std::vector<Bexpression *> retstmts; - retstmts.push_back (compiled_expr); - auto s - = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, - expr.expr->get_locus_slow ()); - ctx->add_statement (s); + Bstatement *assignment = ctx->get_backend ()->assignment_statement ( + fnctx.fndecl, result_reference, compiled_expr, expr.get_locus ()); + ctx->add_statement (assignment); + } } ctx->pop_block (); @@ -168,7 +273,8 @@ CompileConditionalBlocks::visit (HIR::IfExpr &expr) Bfunction *fndecl = fnctx.fndecl; Bexpression *condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx); + Bblock *then_block + = CompileBlock::compile (expr.get_if_block (), ctx, result); translated = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, @@ -182,8 +288,10 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr) Bfunction *fndecl = fnctx.fndecl; Bexpression *condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx); - Bblock *else_block = CompileBlock::compile (expr.get_else_block (), ctx); + Bblock *then_block + = CompileBlock::compile (expr.get_if_block (), ctx, result); + Bblock *else_block + = CompileBlock::compile (expr.get_else_block (), ctx, result); translated = ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block, @@ -197,7 +305,8 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) Bfunction *fndecl = fnctx.fndecl; Bexpression *condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); - Bblock *then_block = CompileBlock::compile (expr.get_if_block (), ctx); + Bblock *then_block + = CompileBlock::compile (expr.get_if_block (), ctx, result); // else block std::vector<Bvariable *> locals; @@ -210,7 +319,8 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr) ctx->push_block (else_block); Bstatement *else_stmt_decl - = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx); + = CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx, + result); ctx->add_statement (else_stmt_decl); ctx->pop_block (); @@ -244,5 +354,64 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) translated = CompileExpr::Compile (&expr, ctx); } +// Shared methods in compilation + +void +HIRCompileBase::compile_function_body ( + Bfunction *fndecl, std::unique_ptr<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) + { + if (has_return_type) + { + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + + auto ret + = ctx->get_backend ()->return_statement (fndecl, retstmts, + s->get_locus_slow ()); + ctx->add_statement (ret); + } + else + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fndecl, + compiled_expr); + ctx->add_statement (final_stmt); + } + } + } + + if (function_body->has_expr () && function_body->tail_expr_reachable ()) + { + // the previous passes will ensure this is a valid return + // dead code elimination should remove any bad trailing expressions + Bexpression *compiled_expr + = CompileExpr::Compile (function_body->expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + if (has_return_type) + { + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + + auto ret = ctx->get_backend ()->return_statement ( + fndecl, retstmts, + function_body->get_final_expr ()->get_locus_slow ()); + ctx->add_statement (ret); + } + else + { + Bstatement *final_stmt + = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); + ctx->add_statement (final_stmt); + } + } +} + } // namespace Compile } // namespace Rust |