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_FACTS_FFI_H
20 : #define RUST_POLONIUS_FACTS_FFI_H
21 :
22 : #include "rust-system.h"
23 :
24 : // This file defines the C++ side of the FFI interface to Polonius.
25 : // The corresponding Rust side is in `gccrs-ffi.rs`.
26 :
27 : // IMPORTANT:
28 : // This file intentionally does not include any C++ headers
29 : // to allow seamless binding generation on the Rust side.
30 :
31 : namespace Rust {
32 : namespace Polonius {
33 :
34 : using Origin = size_t;
35 : using Loan = size_t;
36 : /**
37 : * Compressed CFG point
38 : * Encoding:
39 : * - (bit size - 16) bits: basic block index
40 : * - 15 bits: stmt index inside basic block
41 : * - 1bit: start or mid
42 : *
43 : * Note: Polonius requires the holding type to be `size_t`/`usize`.
44 : */
45 : using Point = size_t;
46 : using Variable = size_t;
47 : using Path = size_t;
48 :
49 : namespace FFI {
50 :
51 : // NOTE: std::pair and std::tuple are complicating the bindings' generation.
52 : template <typename T1, typename T2> struct Pair
53 : {
54 : T1 first;
55 : T2 second;
56 :
57 3330 : Pair (T1 first, T2 second) : first (first), second (second) {}
58 : };
59 :
60 : template <typename T1, typename T2, typename T3> struct Triple
61 : {
62 : T1 first;
63 : T2 second;
64 : T3 third;
65 :
66 368 : Triple (T1 first, T2 second, T3 third)
67 368 : : first (first), second (second), third (third)
68 : {}
69 : };
70 :
71 : /** Frozen variant to vector for FFI */
72 : template <typename T> struct Slice
73 : {
74 : size_t len;
75 : const T *const data;
76 :
77 : template <typename vector>
78 36 : Slice (const vector &v) : len (v.size ()), data (v.data ())
79 : {}
80 : };
81 :
82 : /** Frozen variant of the facts with C ABI and no methods. */
83 : struct FactsView
84 : {
85 : Slice<Triple<Origin, Loan, Point>> loan_issued_at;
86 : Slice<Origin> universal_region;
87 : Slice<Pair<Point, Point>> cfg_edge;
88 : Slice<Pair<Loan, Point>> loan_killed_at;
89 : Slice<Triple<Origin, Origin, Point>> subset_base;
90 : Slice<Pair<Point, Loan>> loan_invalidated_at;
91 : Slice<Pair<Variable, Point>> var_used_at;
92 : Slice<Pair<Variable, Point>> var_defined_at;
93 : Slice<Pair<Variable, Point>> var_dropped_at;
94 : Slice<Pair<Variable, Origin>> use_of_var_derefs_origin;
95 : Slice<Pair<Variable, Origin>> drop_of_var_derefs_origin;
96 : Slice<Pair<Path, Path>> child_path;
97 : Slice<Pair<Path, Variable>> path_is_var;
98 : Slice<Pair<Path, Point>> path_assigned_at_base;
99 : Slice<Pair<Path, Point>> path_moved_at_base;
100 : Slice<Pair<Path, Point>> path_accessed_at_base;
101 : Slice<Pair<Origin, Origin>> known_placeholder_subset;
102 : Slice<Pair<Origin, Loan>> placeholder;
103 : };
104 :
105 : // Wrapper around std::vector to pass data from Rust to C++
106 235 : template <typename T> struct FFIVector
107 : {
108 : std::vector<T> data;
109 :
110 : public:
111 48 : void push (T new_element) { data.push_back (new_element); };
112 :
113 : // allocates memory to a new instance and returns the pointer
114 127 : static FFIVector *make_new () { return new FFIVector{}; }
115 :
116 : // returns current size
117 19 : size_t size () const { return data.size (); }
118 :
119 87 : T at (size_t index) const
120 : {
121 87 : rust_assert (index < data.size ());
122 87 : return data.at (index);
123 : }
124 : };
125 :
126 : // Some useful type aliases
127 : using FFIVectorPair = FFIVector<Pair<size_t, FFIVector<size_t> *>>;
128 : using FFIVectorTriple = FFIVector<Triple<size_t, size_t, size_t>>;
129 :
130 : inline std::vector<size_t>
131 19 : make_vector (const FFIVector<size_t> *vec_sizet)
132 : {
133 19 : std::vector<size_t> return_val (vec_sizet->size ());
134 38 : for (size_t i = 0; i < vec_sizet->size (); ++i)
135 : {
136 19 : return_val[i] = vec_sizet->at (i);
137 : }
138 19 : return return_val;
139 : }
140 :
141 : inline std::vector<std::pair<size_t, std::vector<size_t>>>
142 72 : make_vector (const FFIVectorPair *vec_pair)
143 : {
144 72 : std::vector<std::pair<size_t, std::vector<size_t>>> return_val (
145 72 : vec_pair->size ());
146 91 : for (size_t i = 0; i < vec_pair->size (); ++i)
147 : {
148 19 : std::pair<size_t, std::vector<size_t>> current_pair
149 19 : = {vec_pair->at (i).first, make_vector (vec_pair->at (i).second)};
150 19 : return_val[i] = current_pair;
151 19 : }
152 72 : return return_val;
153 : }
154 :
155 : inline std::vector<std::pair<size_t, std::pair<size_t, size_t>>>
156 36 : make_vector (const FFIVectorTriple *vec_triple)
157 : {
158 36 : std::vector<std::pair<size_t, std::pair<size_t, size_t>>> return_val (
159 36 : vec_triple->size ());
160 46 : for (size_t i = 0; i < vec_triple->size (); ++i)
161 : {
162 10 : auto current_element = std::pair<size_t, std::pair<size_t, size_t>>{
163 10 : vec_triple->at (i).first,
164 10 : {vec_triple->at (i).second, vec_triple->at (i).third}};
165 10 : return_val[i] = current_element;
166 : }
167 36 : return return_val;
168 : }
169 :
170 : struct Output
171 : {
172 : FFIVectorPair *loan_errors;
173 : FFIVectorPair *move_errors;
174 : FFIVectorTriple *subset_errors;
175 : };
176 :
177 : } // namespace FFI
178 : } // namespace Polonius
179 : } // namespace Rust
180 :
181 : #endif // RUST_POLONIUS_FACTS_FFI_H
|