1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
19 #include "rust-compile-block.h"
20 #include "rust-compile-stmt.h"
21 #include "rust-compile-expr.h"
26 CompileBlock::CompileBlock (Context
*ctx
, Bvariable
*result
)
27 : HIRCompileBase (ctx
), translated (nullptr), result (result
)
31 CompileBlock::compile (HIR::BlockExpr
*expr
, Context
*ctx
, Bvariable
*result
)
33 CompileBlock
compiler (ctx
, result
);
34 compiler
.visit (*expr
);
35 return compiler
.translated
;
39 CompileBlock::visit (HIR::BlockExpr
&expr
)
41 fncontext fnctx
= ctx
->peek_fn ();
42 tree fndecl
= fnctx
.fndecl
;
43 Location start_location
= expr
.get_locus ();
44 Location end_location
= expr
.get_end_locus ();
45 auto body_mappings
= expr
.get_mappings ();
47 Resolver::Rib
*rib
= nullptr;
48 if (!ctx
->get_resolver ()->find_name_rib (body_mappings
.get_nodeid (), &rib
))
50 rust_fatal_error (expr
.get_locus (), "failed to setup locals per block");
54 std::vector
<Bvariable
*> locals
55 = compile_locals_for_block (ctx
, *rib
, fndecl
);
57 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
58 tree new_block
= ctx
->get_backend ()->block (fndecl
, enclosing_scope
, locals
,
59 start_location
, end_location
);
60 ctx
->push_block (new_block
);
62 for (auto &s
: expr
.get_statements ())
64 auto compiled_expr
= CompileStmt::Compile (s
.get (), ctx
);
65 if (compiled_expr
!= nullptr)
67 tree s
= convert_to_void (compiled_expr
, ICV_STATEMENT
);
68 ctx
->add_statement (s
);
74 // the previous passes will ensure this is a valid return or
75 // a valid trailing expression
76 tree compiled_expr
= CompileExpr::Compile (expr
.expr
.get (), ctx
);
77 if (compiled_expr
!= nullptr)
79 if (result
== nullptr)
81 ctx
->add_statement (compiled_expr
);
85 tree result_reference
= ctx
->get_backend ()->var_expression (
86 result
, expr
.get_final_expr ()->get_locus ());
89 = ctx
->get_backend ()->assignment_statement (result_reference
,
92 ctx
->add_statement (assignment
);
98 translated
= new_block
;
102 CompileConditionalBlocks::visit (HIR::IfExpr
&expr
)
104 fncontext fnctx
= ctx
->peek_fn ();
105 tree fndecl
= fnctx
.fndecl
;
106 tree condition_expr
= CompileExpr::Compile (expr
.get_if_condition (), ctx
);
107 tree then_block
= CompileBlock::compile (expr
.get_if_block (), ctx
, result
);
110 = ctx
->get_backend ()->if_statement (fndecl
, condition_expr
, then_block
,
111 NULL
, expr
.get_locus ());
115 CompileConditionalBlocks::visit (HIR::IfExprConseqElse
&expr
)
117 fncontext fnctx
= ctx
->peek_fn ();
118 tree fndecl
= fnctx
.fndecl
;
119 tree condition_expr
= CompileExpr::Compile (expr
.get_if_condition (), ctx
);
120 tree then_block
= CompileBlock::compile (expr
.get_if_block (), ctx
, result
);
121 tree else_block
= CompileBlock::compile (expr
.get_else_block (), ctx
, result
);
124 = ctx
->get_backend ()->if_statement (fndecl
, condition_expr
, then_block
,
125 else_block
, expr
.get_locus ());
129 CompileConditionalBlocks::visit (HIR::IfExprConseqIf
&expr
)
131 fncontext fnctx
= ctx
->peek_fn ();
132 tree fndecl
= fnctx
.fndecl
;
133 tree condition_expr
= CompileExpr::Compile (expr
.get_if_condition (), ctx
);
134 tree then_block
= CompileBlock::compile (expr
.get_if_block (), ctx
, result
);
137 std::vector
<Bvariable
*> locals
;
138 Location start_location
= expr
.get_conseq_if_expr ()->get_locus ();
139 Location end_location
= expr
.get_conseq_if_expr ()->get_locus (); // FIXME
140 tree enclosing_scope
= ctx
->peek_enclosing_scope ();
141 tree else_block
= ctx
->get_backend ()->block (fndecl
, enclosing_scope
, locals
,
142 start_location
, end_location
);
143 ctx
->push_block (else_block
);
146 = CompileConditionalBlocks::compile (expr
.get_conseq_if_expr (), ctx
,
148 ctx
->add_statement (else_stmt_decl
);
153 = ctx
->get_backend ()->if_statement (fndecl
, condition_expr
, then_block
,
154 else_block
, expr
.get_locus ());
157 } // namespace Compile