Line data Source code
1 : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
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
8 : // version.
9 :
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
13 : // for more details.
14 :
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/>.
18 :
19 : #include "rust-compile-block.h"
20 : #include "rust-compile-drop.h"
21 : #include "rust-compile-expr.h"
22 : #include "rust-compile-stmt.h"
23 : #include "rust-hir-expr.h"
24 :
25 : namespace Rust {
26 : namespace Compile {
27 :
28 : static bool
29 254 : is_control_flow_expr (HIR::Expr &expr)
30 : {
31 254 : HIR::Expr::ExprType expr_type = expr.get_expression_type ();
32 :
33 254 : return expr_type == HIR::Expr::ExprType::Break
34 254 : || expr_type == HIR::Expr::ExprType::Continue;
35 : }
36 :
37 8812 : CompileBlock::CompileBlock (Context *ctx, Bvariable *result)
38 8812 : : HIRCompileBase (ctx), translated (nullptr), result (result)
39 8812 : {}
40 :
41 : tree
42 8812 : CompileBlock::compile (HIR::BlockExpr &expr, Context *ctx, Bvariable *result)
43 : {
44 8812 : CompileBlock compiler (ctx, result);
45 8812 : compiler.visit (expr);
46 8812 : return compiler.translated;
47 8812 : }
48 :
49 : void
50 8812 : CompileBlock::visit (HIR::BlockExpr &expr)
51 : {
52 8812 : fncontext fnctx = ctx->peek_fn ();
53 8812 : tree fndecl = fnctx.fndecl;
54 8812 : location_t start_location = expr.get_locus ();
55 8812 : location_t end_location = expr.get_end_locus ();
56 :
57 8812 : tree enclosing_scope = ctx->peek_enclosing_scope ();
58 8812 : tree new_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
59 : start_location, end_location);
60 8812 : ctx->push_block (new_block);
61 :
62 18095 : for (auto &s : expr.get_statements ())
63 : {
64 9283 : auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
65 9283 : if (compiled_expr != nullptr)
66 : {
67 5755 : tree s = convert_to_void (compiled_expr, ICV_STATEMENT);
68 5755 : ctx->add_statement (s);
69 : }
70 : }
71 :
72 8812 : if (expr.has_expr ())
73 : {
74 4899 : HIR::Expr &final_expr = expr.get_final_expr ();
75 4899 : tree compiled_expr = CompileExpr::Compile (final_expr, ctx);
76 :
77 4899 : if (result != nullptr)
78 : {
79 4645 : location_t locus = final_expr.get_locus ();
80 4645 : tree result_reference = Backend::var_expression (result, locus);
81 :
82 4645 : tree assignment
83 4645 : = Backend::assignment_statement (result_reference, compiled_expr,
84 : expr.get_locus ());
85 4645 : ctx->add_statement (assignment);
86 : }
87 254 : else if (compiled_expr != nullptr && is_control_flow_expr (final_expr)
88 258 : && compiled_expr != error_mark_node)
89 : {
90 4 : tree stmt = convert_to_void (compiled_expr, ICV_STATEMENT);
91 4 : ctx->add_statement (stmt);
92 : }
93 : }
94 3913 : else if (result != nullptr)
95 : {
96 2654 : location_t locus = expr.get_locus ();
97 2654 : tree compiled_expr = unit_expression (expr.get_locus ());
98 2654 : tree result_reference = Backend::var_expression (result, locus);
99 :
100 2654 : tree assignment
101 2654 : = Backend::assignment_statement (result_reference, compiled_expr,
102 : expr.get_locus ());
103 2654 : ctx->add_statement (assignment);
104 : }
105 8812 : tree cleanup = CompileDrop (ctx).build_current_scope_drop_cleanup ();
106 :
107 8812 : ctx->pop_block_with_cleanup (cleanup, expr.get_locus ());
108 8812 : translated = new_block;
109 8812 : }
110 :
111 : void
112 1278 : CompileConditionalBlocks::visit (HIR::IfExpr &expr)
113 : {
114 1278 : fncontext fnctx = ctx->peek_fn ();
115 1278 : tree fndecl = fnctx.fndecl;
116 1278 : tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx);
117 1278 : tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result);
118 :
119 1278 : translated = Backend::if_statement (fndecl, condition_expr, then_block, NULL,
120 : expr.get_locus ());
121 1278 : }
122 :
123 : void
124 1188 : CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr)
125 : {
126 1188 : fncontext fnctx = ctx->peek_fn ();
127 1188 : tree fndecl = fnctx.fndecl;
128 1188 : tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx);
129 1188 : tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result);
130 :
131 : // else block
132 1188 : std::vector<Bvariable *> locals;
133 1188 : location_t start_location = expr.get_else_block ().get_locus ();
134 1188 : location_t end_location = expr.get_else_block ().get_locus (); // FIXME
135 1188 : tree enclosing_scope = ctx->peek_enclosing_scope ();
136 1188 : tree else_block = Backend::block (fndecl, enclosing_scope, locals,
137 : start_location, end_location);
138 1188 : ctx->push_block (else_block);
139 :
140 1188 : tree else_stmt_decl
141 1188 : = CompileExprWithBlock::compile (&expr.get_else_block (), ctx, result);
142 :
143 1188 : ctx->add_statement (else_stmt_decl);
144 :
145 1188 : ctx->pop_block ();
146 :
147 1188 : translated = Backend::if_statement (fndecl, condition_expr, then_block,
148 : else_block, expr.get_locus ());
149 1188 : }
150 :
151 : } // namespace Compile
152 : } // namespace Rust
|