Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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_POLONIUS_H
20 : : #define RUST_POLONIUS_H
21 : :
22 : : // Interface to the Polonius borrow checker engine.
23 : : // See (https://github.com/rust-lang/polonius/blob/master/polonius-engine/)
24 : :
25 : : #include <ostream>
26 : : #include "rust-polonius-ffi.h"
27 : :
28 : : namespace Rust {
29 : : namespace Polonius {
30 : :
31 : : struct FullPoint
32 : : {
33 : : uint32_t bb;
34 : : uint32_t stmt;
35 : : bool mid;
36 : :
37 : : /** Expands a compressed `Point` into its components.
38 : : * See `Point` docs for encoding details in ./rust-polonius-ffi.h
39 : : */
40 : 0 : explicit FullPoint (Point point)
41 : 0 : : bb (extract_bb (point)), stmt (extract_stmt (point)),
42 : 0 : mid (extract_mid (point))
43 : : {}
44 : :
45 : 30 : static uint32_t extract_bb (Point point) { return point >> 16; }
46 : 30 : static uint32_t extract_stmt (Point point)
47 : : {
48 : : // Point is a 32 bit unsigned integer
49 : : // 16 15 1
50 : : // xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxx x
51 : : // ^~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~ ^
52 : : // | | |
53 : : // basic_block | start/mid
54 : : // statement
55 : : // the left most 16 bits store the basic block number
56 : : // the right most bit, represents the start/mid status
57 : : // the remaining 15 bits between these two represent the statement number
58 : : // which we need to extract in this fucntion
59 : : //
60 : : // firstly we can get rid of right most bit by performing left shift once
61 : 30 : auto hide_left_most_bit = point >> 1;
62 : : // now we only need the 15 bits on the right
63 : : // we can mask the remaining bits by performing bitwise AND with fifteen
64 : : // 1's which in hexadecimal is 0x7FFF
65 : 30 : return hide_left_most_bit & 0x7FFF;
66 : : }
67 : 0 : static bool extract_mid (Point point) { return point & 1; }
68 : :
69 : 0 : friend std::ostream &operator<< (std::ostream &os, const FullPoint &point)
70 : : {
71 : 0 : return os << ((point.mid) ? "Mid" : "Start") << "(bb" << point.bb << "["
72 : 0 : << point.stmt << "])";
73 : : }
74 : : };
75 : :
76 : : struct Facts
77 : : {
78 : : // See (https://rust-lang.github.io/polonius/rules/relations.html)
79 : : std::vector<FFI::Triple<Origin, Loan, Point>> loan_issued_at;
80 : : std::vector<Origin> universal_region;
81 : : std::vector<FFI::Pair<Point, Point>> cfg_edge;
82 : : std::vector<FFI::Pair<Loan, Point>> loan_killed_at;
83 : : std::vector<FFI::Triple<Origin, Origin, Point>> subset_base;
84 : : std::vector<FFI::Pair<Point, Loan>> loan_invalidated_at;
85 : : std::vector<FFI::Pair<Variable, Point>> var_used_at;
86 : : std::vector<FFI::Pair<Variable, Point>> var_defined_at;
87 : : std::vector<FFI::Pair<Variable, Point>> var_dropped_at;
88 : : std::vector<FFI::Pair<Variable, Origin>> use_of_var_derefs_origin;
89 : : std::vector<FFI::Pair<Variable, Origin>> drop_of_var_derefs_origin;
90 : : std::vector<FFI::Pair<Path, Path>> child_path;
91 : : std::vector<FFI::Pair<Path, Variable>> path_is_var;
92 : : std::vector<FFI::Pair<Path, Point>> path_assigned_at_base;
93 : : std::vector<FFI::Pair<Path, Point>> path_moved_at_base;
94 : : std::vector<FFI::Pair<Path, Point>> path_accessed_at_base;
95 : : std::vector<FFI::Pair<Origin, Origin>> known_placeholder_subset;
96 : : std::vector<FFI::Pair<Origin, Loan>> placeholder;
97 : :
98 : : /**
99 : : * Create a const view for the struct for FFI.
100 : : *
101 : : * This view uses the original vector storage.
102 : : * Therefore any resizing operation of Facts member may invalidate the view.
103 : : */
104 : 36 : FFI::FactsView freeze ()
105 : : {
106 : 36 : return FFI::FactsView{loan_issued_at,
107 : 36 : universal_region,
108 : 36 : cfg_edge,
109 : 36 : loan_killed_at,
110 : 36 : subset_base,
111 : 36 : loan_invalidated_at,
112 : 36 : var_used_at,
113 : 36 : var_defined_at,
114 : 36 : var_dropped_at,
115 : 36 : use_of_var_derefs_origin,
116 : 36 : drop_of_var_derefs_origin,
117 : 36 : child_path,
118 : 36 : path_is_var,
119 : 36 : path_assigned_at_base,
120 : 36 : path_moved_at_base,
121 : 36 : path_accessed_at_base,
122 : 36 : known_placeholder_subset,
123 : 36 : placeholder};
124 : : }
125 : :
126 : 0 : void dump_loan_issued_at (std::ostream &os) const
127 : : {
128 : 0 : for (auto &e : loan_issued_at)
129 : 0 : os << "\"'?" << e.first << "\"\t\"bw" << e.second << "\"\t\""
130 : 0 : << FullPoint (e.third) << "\"\n";
131 : 0 : }
132 : :
133 : 0 : void dump_universal_region (std::ostream &os) const
134 : : {
135 : 0 : for (auto &e : universal_region)
136 : 0 : os << e << "\n";
137 : 0 : }
138 : :
139 : 0 : void dump_cfg_edge (std::ostream &os) const
140 : : {
141 : 0 : for (auto &e : cfg_edge)
142 : 0 : os << FullPoint (e.first) << " " << FullPoint (e.second) << "\n";
143 : 0 : }
144 : :
145 : 0 : void dump_loan_killed_at (std::ostream &os) const
146 : : {
147 : 0 : for (auto &e : loan_killed_at)
148 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
149 : 0 : }
150 : :
151 : 0 : void dump_subset_base (std::ostream &os) const
152 : : {
153 : 0 : for (auto &e : subset_base)
154 : 0 : os << "\"'?" << e.first << "\"\t\"'?" << e.second << "\"\t\""
155 : 0 : << FullPoint (e.third) << "\"\n";
156 : 0 : }
157 : :
158 : 0 : void dump_loan_invalidated_at (std::ostream &os) const
159 : : {
160 : 0 : for (auto &e : loan_invalidated_at)
161 : 0 : os << FullPoint (e.first) << " " << e.second << "\n";
162 : 0 : }
163 : :
164 : 0 : void dump_var_used_at (std::ostream &os) const
165 : : {
166 : 0 : for (auto &e : var_used_at)
167 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
168 : 0 : }
169 : :
170 : 0 : void dump_var_defined_at (std::ostream &os) const
171 : : {
172 : 0 : for (auto &e : var_defined_at)
173 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
174 : 0 : }
175 : :
176 : 0 : void dump_var_dropped_at (std::ostream &os) const
177 : : {
178 : 0 : for (auto &e : var_dropped_at)
179 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
180 : 0 : }
181 : :
182 : 0 : void dump_use_of_var_derefs_origin (std::ostream &os) const
183 : : {
184 : 0 : for (auto &e : use_of_var_derefs_origin)
185 : 0 : os << e.first << " " << e.second << "\n";
186 : 0 : }
187 : :
188 : 0 : void dump_drop_of_var_derefs_origin (std::ostream &os) const
189 : : {
190 : 0 : for (auto &e : drop_of_var_derefs_origin)
191 : 0 : os << e.first << " " << e.second << "\n";
192 : 0 : }
193 : :
194 : 0 : void dump_child_path (std::ostream &os) const
195 : : {
196 : 0 : for (auto &e : child_path)
197 : 0 : os << e.first << " " << e.second << "\n";
198 : 0 : }
199 : :
200 : 0 : void dump_path_is_var (std::ostream &os) const
201 : : {
202 : 0 : for (auto &e : path_is_var)
203 : 0 : os << e.first << " " << e.second << "\n";
204 : 0 : }
205 : :
206 : 0 : void dump_path_assigned_at_base (std::ostream &os) const
207 : : {
208 : 0 : for (auto &e : path_assigned_at_base)
209 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
210 : 0 : }
211 : :
212 : 0 : void dump_path_moved_at_base (std::ostream &os) const
213 : : {
214 : 0 : for (auto &e : path_moved_at_base)
215 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
216 : 0 : }
217 : :
218 : 0 : void dump_path_accessed_at_base (std::ostream &os) const
219 : : {
220 : 0 : for (auto &e : path_accessed_at_base)
221 : 0 : os << e.first << " " << FullPoint (e.second) << "\n";
222 : 0 : }
223 : :
224 : 0 : void dump_known_placeholder_subset (std::ostream &os) const
225 : : {
226 : 0 : for (auto &e : known_placeholder_subset)
227 : 0 : os << e.first << " " << e.second << "\n";
228 : 0 : }
229 : :
230 : 0 : void dump_placeholder (std::ostream &os) const
231 : : {
232 : 0 : for (auto &e : placeholder)
233 : 0 : os << e.first << " " << e.second << "\n";
234 : 0 : }
235 : : };
236 : :
237 : : /**
238 : : * Check a single function for borrow errors.
239 : : *
240 : : * Output is not yet implemented and is only dumped to stdout.
241 : : */
242 : : extern "C" FFI::Output
243 : : polonius_run (FFI::FactsView input, bool dump_enabled);
244 : :
245 : : // Helper functions for FFIVector to be used on Rust side
246 : : extern "C" {
247 : :
248 : : FFI::FFIVector<size_t> *
249 : : FFIVector__new ();
250 : :
251 : : FFI::FFIVectorPair *
252 : : FFIVector__new_vec_pair ();
253 : :
254 : : FFI::FFIVectorTriple *
255 : : FFIVector__new_vec_triple ();
256 : :
257 : : void
258 : : FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
259 : :
260 : : void
261 : : FFIVector__push_vec_pair (FFI::FFIVectorPair *vector,
262 : : FFI::Pair<size_t, FFI::FFIVector<size_t> *> element);
263 : :
264 : : void
265 : : FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
266 : : FFI::Triple<size_t, size_t, size_t> element);
267 : : }
268 : :
269 : : } // namespace Polonius
270 : : } // namespace Rust
271 : :
272 : : #endif /* !RUST_POLONIUS_H */
|