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