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-borrow-checker.h"
20 : #include "rust-borrow-checker-diagnostics.h"
21 : #include "rust-function-collector.h"
22 : #include "rust-bir-fact-collector.h"
23 : #include "rust-bir-builder.h"
24 : #include "rust-bir-drop-analysis.h"
25 : #include "rust-bir-dump.h"
26 : #include "polonius/rust-polonius.h"
27 :
28 : namespace Rust {
29 : namespace HIR {
30 :
31 : void
32 7 : dump_function_bir (const std::string &filename, BIR::Function &func,
33 : const std::string &name)
34 : {
35 7 : std::ofstream file;
36 7 : file.open (filename);
37 7 : if (file.fail ())
38 : {
39 0 : rust_error_at (UNKNOWN_LOCATION, "Failed to open file %s",
40 : filename.c_str ());
41 0 : return;
42 : }
43 7 : BIR::Dump (file, func, name).go ();
44 7 : file.close ();
45 7 : }
46 :
47 : void
48 17 : BorrowChecker::go (HIR::Crate &crate)
49 : {
50 17 : std::string crate_name;
51 :
52 17 : BIR::DropAnalysis::get ().clear ();
53 :
54 17 : if (enable_dump_bir)
55 : {
56 2 : mkdir ("bir_dump", 0755);
57 2 : auto &mappings = Analysis::Mappings::get ();
58 2 : crate_name
59 2 : = *mappings.get_crate_name (crate.get_mappings ().get_crate_num ());
60 2 : mkdir ("nll_facts_gccrs", 0755);
61 : }
62 :
63 17 : FunctionCollector collector;
64 17 : collector.go (crate);
65 :
66 74 : for (auto func : collector.get_functions ())
67 : {
68 57 : rust_debug_loc (func->get_locus (), "\nChecking function %s\n",
69 : func->get_function_name ().as_string ().c_str ());
70 :
71 57 : BIR::BuilderContext ctx;
72 57 : BIR::Builder builder (ctx);
73 57 : auto bir = builder.build (*func);
74 :
75 57 : BIR::DropAnalysis::get ().analyze (bir);
76 :
77 57 : if (enable_dump_bir)
78 : {
79 14 : std::string filename = "bir_dump/" + crate_name + "."
80 21 : + func->get_function_name ().as_string ()
81 7 : + ".bir.dump";
82 7 : dump_function_bir (filename, bir,
83 14 : func->get_function_name ().as_string ());
84 7 : }
85 :
86 57 : auto facts = BIR::FactCollector::collect (bir);
87 :
88 57 : if (enable_dump_bir)
89 : {
90 7 : auto dir
91 7 : = "nll_facts_gccrs/" + func->get_function_name ().as_string ();
92 7 : mkdir (dir.c_str (), 0755);
93 7 : auto dump_facts_to_file
94 126 : = [&] (const std::string &suffix,
95 : void (Polonius::Facts::*fn) (std::ostream &) const) {
96 126 : std::string filename = "nll_facts_gccrs/"
97 252 : + func->get_function_name ().as_string ()
98 252 : + "/" + suffix + ".facts";
99 126 : std::ofstream file;
100 126 : file.open (filename);
101 126 : if (file.fail ())
102 : {
103 0 : abort ();
104 : }
105 :
106 : // Run dump
107 : // BEWARE: this callback charade is a workaround because gcc48
108 : // won't let me return a file from a function
109 126 : (facts.*fn) (file);
110 126 : };
111 :
112 7 : dump_facts_to_file ("loan_issued_at",
113 : &Polonius::Facts::dump_loan_issued_at);
114 7 : dump_facts_to_file ("loan_killed_at",
115 : &Polonius::Facts::dump_loan_killed_at);
116 7 : dump_facts_to_file ("loan_invalidated_at",
117 : &Polonius::Facts::dump_loan_invalidated_at);
118 7 : dump_facts_to_file ("subset_base",
119 : &Polonius::Facts::dump_subset_base);
120 7 : dump_facts_to_file ("universal_region",
121 : &Polonius::Facts::dump_universal_region);
122 7 : dump_facts_to_file ("cfg_edge", &Polonius::Facts::dump_cfg_edge);
123 7 : dump_facts_to_file ("var_used_at",
124 : &Polonius::Facts::dump_var_used_at);
125 7 : dump_facts_to_file ("var_defined_at",
126 : &Polonius::Facts::dump_var_defined_at);
127 7 : dump_facts_to_file ("var_dropped_at",
128 : &Polonius::Facts::dump_var_dropped_at);
129 7 : dump_facts_to_file ("use_of_var_derefs_origin",
130 : &Polonius::Facts::dump_use_of_var_derefs_origin);
131 7 : dump_facts_to_file ("drop_of_var_derefs_origin",
132 : &Polonius::Facts::dump_drop_of_var_derefs_origin);
133 7 : dump_facts_to_file ("child_path", &Polonius::Facts::dump_child_path);
134 7 : dump_facts_to_file ("path_is_var",
135 : &Polonius::Facts::dump_path_is_var);
136 7 : dump_facts_to_file ("known_placeholder_subset",
137 : &Polonius::Facts::dump_known_placeholder_subset);
138 7 : dump_facts_to_file ("path_moved_at_base",
139 : &Polonius::Facts::dump_path_moved_at_base);
140 7 : dump_facts_to_file ("path_accessed_at_base",
141 : &Polonius::Facts::dump_path_accessed_at_base);
142 7 : dump_facts_to_file ("path_assigned_at_base",
143 : &Polonius::Facts::dump_path_assigned_at_base);
144 7 : dump_facts_to_file ("placeholder",
145 : &Polonius::Facts::dump_placeholder);
146 7 : }
147 :
148 57 : auto result
149 57 : = Polonius::polonius_run (facts.freeze (), rust_be_debug_p ());
150 :
151 : // convert to std::vector variation for easier navigation
152 57 : auto loan_errors = make_vector (result.loan_errors);
153 57 : auto move_errors = make_vector (result.move_errors);
154 57 : auto subset_errors = make_vector (result.subset_errors);
155 :
156 : // free allocated data
157 114 : delete result.loan_errors;
158 114 : delete result.move_errors;
159 114 : delete result.subset_errors;
160 :
161 57 : BIR::BorrowCheckerDiagnostics (func, bir, facts, move_errors, loan_errors,
162 57 : subset_errors)
163 57 : .report_errors ();
164 57 : }
165 :
166 17 : for (auto closure ATTRIBUTE_UNUSED : collector.get_closures ())
167 0 : rust_sorry_at (closure->get_locus (),
168 : "Closure borrow checking is not implemented yet.");
169 17 : }
170 :
171 : } // namespace HIR
172 : } // namespace Rust
|