]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/checks/errors/borrowck/rust-bir.h
bcb32c9659b82cc74c365fb7ad6b5abe5f4a557b
[thirdparty/gcc.git] / gcc / rust / checks / errors / borrowck / rust-bir.h
1 // Copyright (C) 2020-2023 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 #ifndef RUST_BIR_BASE_H
20 #define RUST_BIR_BASE_H
21
22 #include "rust-bir-place.h"
23 #include "rust-bir-visitor.h"
24
25 namespace Rust {
26
27 namespace BIR {
28
29 struct BasicBlock;
30 class Node;
31 class AbstractExpr;
32
33 /**
34 * Top-level entity of the Borrow-checker IR (BIR).
35 * It represents a single function (method, closure, etc.), which is also the
36 * basic unit of Polonius borrow-checking.
37 */
38 struct Function
39 {
40 PlaceDB place_db;
41 std::vector<PlaceId> arguments; // Only used for dump.
42 std::vector<BasicBlock> basic_blocks;
43 };
44
45 /** Single "instruction" of BIR. */
46 class Node
47 {
48 public:
49 enum class Kind
50 {
51 ASSIGNMENT, // <place> = <expr>
52 SWITCH, // switch <place>
53 RETURN, // return
54 GOTO, // goto
55 STORAGE_DEAD, // StorageDead(<place>)
56 STORAGE_LIVE, // StorageLive(<place>)
57 };
58
59 private:
60 Kind kind;
61 // ASSIGNMENT: lhs
62 // SWITCH: switch_val
63 // StorageDead/StorageLive: place
64 // otherwise: <unused>
65 PlaceId place;
66 // ASSIGNMENT: rhs
67 // otherwise: <unused>
68 std::unique_ptr<AbstractExpr> expr;
69
70 public:
71 Node (PlaceId lhs, AbstractExpr *rhs)
72 : kind (Kind::ASSIGNMENT), place (lhs), expr (rhs)
73 {}
74
75 explicit Node (Kind kind, PlaceId place = INVALID_PLACE,
76 AbstractExpr *expr = nullptr)
77 : kind (kind), place (place), expr (expr)
78 {}
79
80 public:
81 WARN_UNUSED_RESULT Kind get_kind () const { return kind; }
82 WARN_UNUSED_RESULT PlaceId get_place () const { return place; }
83 WARN_UNUSED_RESULT AbstractExpr &get_expr () const { return *expr; }
84 };
85
86 /** Unique identifier for a basic block in the BIR. */
87 using BasicBlockId = uint32_t;
88
89 static constexpr BasicBlockId INVALID_BB
90 = std::numeric_limits<BasicBlockId>::max ();
91
92 struct BasicBlock
93 {
94 // BIR "instructions".
95 std::vector<Node> statements;
96 // A basic block can end with: goto, return or switch
97 std::vector<BasicBlockId> successors;
98
99 public:
100 WARN_UNUSED_RESULT bool is_terminated () const
101 {
102 if (statements.empty ())
103 return false;
104 switch (statements.back ().get_kind ())
105 {
106 case Node::Kind::GOTO:
107 case Node::Kind::RETURN:
108 case Node::Kind::SWITCH:
109 return true;
110 default:
111 return false;
112 }
113 }
114
115 WARN_UNUSED_RESULT bool is_goto_terminated () const
116 {
117 return is_terminated ()
118 && statements.back ().get_kind () == Node::Kind::GOTO;
119 }
120 };
121
122 // Rhs expression of BIR assignment node (abstract).
123 class AbstractExpr : public Visitable
124 {
125 };
126
127 class InitializerExpr : public VisitableImpl<AbstractExpr, InitializerExpr>
128 {
129 std::vector<PlaceId> values;
130
131 public:
132 explicit InitializerExpr (std::vector<PlaceId> &&values) : values (values) {}
133
134 public:
135 std::vector<PlaceId> &get_values () { return values; }
136 };
137
138 template <unsigned ARITY>
139 class Operator : public VisitableImpl<AbstractExpr, Operator<ARITY>>
140 {
141 std::array<PlaceId, ARITY> operands;
142
143 public:
144 explicit Operator (std::array<PlaceId, ARITY> &&operands)
145 : operands (operands)
146 {}
147
148 public:
149 template <size_t I> WARN_UNUSED_RESULT PlaceId get_operand () const
150 {
151 static_assert (I < ARITY, "Index out of bounds");
152 return operands[I];
153 }
154 };
155
156 class BorrowExpr : public VisitableImpl<AbstractExpr, BorrowExpr>
157 {
158 PlaceId place;
159
160 public:
161 explicit BorrowExpr (PlaceId place) : place (place) {}
162 WARN_UNUSED_RESULT PlaceId get_place () const { return place; }
163 };
164
165 /**
166 * This expression is only to be used inside the assignment node and acts as
167 * identity wrapper for a place value. It is separated from `Operator<1>` to
168 * render it more explicitly in the dump.
169 */
170 class Assignment : public VisitableImpl<AbstractExpr, Assignment>
171 {
172 PlaceId rhs;
173
174 public:
175 explicit Assignment (PlaceId rhs) : rhs (rhs) {}
176
177 public:
178 WARN_UNUSED_RESULT PlaceId get_rhs () const { return rhs; }
179 };
180
181 class CallExpr : public VisitableImpl<AbstractExpr, CallExpr>
182 {
183 std::vector<PlaceId> arguments;
184 PlaceId callable;
185
186 public:
187 explicit CallExpr (PlaceId callable, std::vector<PlaceId> &&arguments)
188 : arguments (arguments), callable (callable)
189 {}
190
191 public:
192 const std::vector<PlaceId> &get_arguments () { return arguments; }
193 WARN_UNUSED_RESULT PlaceId get_callable () const { return callable; }
194 };
195
196 } // namespace BIR
197
198 } // namespace Rust
199
200 #endif // RUST_BIR_BASE_H