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 : #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 polonius_run (FFI::FactsView input, bool dump_enabled);
243 :
244 : // Helper functions for FFIVector to be used on Rust side
245 : extern "C" {
246 :
247 : FFI::FFIVector<size_t> *FFIVector__new ();
248 :
249 : FFI::FFIVectorPair *FFIVector__new_vec_pair ();
250 :
251 : FFI::FFIVectorTriple *FFIVector__new_vec_triple ();
252 :
253 : void FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
254 :
255 : void
256 : FFIVector__push_vec_pair (FFI::FFIVectorPair *vector,
257 : FFI::Pair<size_t, FFI::FFIVector<size_t> *> element);
258 :
259 : void FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
260 : FFI::Triple<size_t, size_t, size_t> element);
261 : }
262 :
263 : } // namespace Polonius
264 : } // namespace Rust
265 :
266 : #endif /* !RUST_POLONIUS_H */
|