aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend/rust-compile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend/rust-compile.cc')
-rw-r--r--gcc/rust/backend/rust-compile.cc201
1 files changed, 185 insertions, 16 deletions
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