|
1 | 1 | #include "syntax/dependency_graph.h" |
2 | 2 |
|
| 3 | +#include <algorithm> |
3 | 4 | #include <chrono> |
4 | 5 |
|
5 | 6 | #include "command/toolchain.h" |
@@ -101,6 +102,109 @@ std::size_t DependencyGraph::edge_count() const { |
101 | 102 | return count; |
102 | 103 | } |
103 | 104 |
|
| 105 | +void DependencyGraph::build_reverse_map() { |
| 106 | + reverse_includes_.clear(); |
| 107 | + for(auto& [key, ids]: includes) { |
| 108 | + for(auto flagged_id: ids) { |
| 109 | + auto included_id = flagged_id & PATH_ID_MASK; |
| 110 | + auto& vec = reverse_includes_[included_id]; |
| 111 | + if(llvm::find(vec, key.path_id) == vec.end()) { |
| 112 | + vec.push_back(key.path_id); |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +llvm::ArrayRef<std::uint32_t> DependencyGraph::get_includers(std::uint32_t path_id) const { |
| 119 | + auto it = reverse_includes_.find(path_id); |
| 120 | + if(it != reverse_includes_.end()) { |
| 121 | + return it->second; |
| 122 | + } |
| 123 | + return {}; |
| 124 | +} |
| 125 | + |
| 126 | +llvm::SmallVector<std::uint32_t, 4> |
| 127 | + DependencyGraph::find_host_sources(std::uint32_t header_path_id) const { |
| 128 | + llvm::SmallVector<std::uint32_t, 4> result; |
| 129 | + llvm::DenseSet<std::uint32_t> visited; |
| 130 | + llvm::SmallVector<std::uint32_t, 16> queue; |
| 131 | + |
| 132 | + queue.push_back(header_path_id); |
| 133 | + visited.insert(header_path_id); |
| 134 | + |
| 135 | + while(!queue.empty()) { |
| 136 | + auto current = queue.pop_back_val(); |
| 137 | + auto includers = get_includers(current); |
| 138 | + if(includers.empty()) { |
| 139 | + // No includers: this is a root (source file). |
| 140 | + // Exclude the starting header itself. |
| 141 | + if(current != header_path_id) { |
| 142 | + result.push_back(current); |
| 143 | + } |
| 144 | + continue; |
| 145 | + } |
| 146 | + for(auto includer: includers) { |
| 147 | + if(visited.insert(includer).second) { |
| 148 | + queue.push_back(includer); |
| 149 | + } |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + return result; |
| 154 | +} |
| 155 | + |
| 156 | +std::vector<std::uint32_t> DependencyGraph::find_include_chain(std::uint32_t host_path_id, |
| 157 | + std::uint32_t target_path_id) const { |
| 158 | + if(host_path_id == target_path_id) { |
| 159 | + return {host_path_id}; |
| 160 | + } |
| 161 | + |
| 162 | + // BFS: predecessor map for path reconstruction. |
| 163 | + llvm::DenseMap<std::uint32_t, std::uint32_t> prev; |
| 164 | + llvm::SmallVector<std::uint32_t, 16> queue; |
| 165 | + |
| 166 | + prev[host_path_id] = host_path_id; |
| 167 | + queue.push_back(host_path_id); |
| 168 | + |
| 169 | + bool found = false; |
| 170 | + while(!queue.empty() && !found) { |
| 171 | + llvm::SmallVector<std::uint32_t, 16> next_queue; |
| 172 | + for(auto current: queue) { |
| 173 | + auto includes_union = get_all_includes(current); |
| 174 | + for(auto flagged_id: includes_union) { |
| 175 | + auto child = flagged_id & PATH_ID_MASK; |
| 176 | + if(prev.find(child) == prev.end()) { |
| 177 | + prev[child] = current; |
| 178 | + if(child == target_path_id) { |
| 179 | + found = true; |
| 180 | + break; |
| 181 | + } |
| 182 | + next_queue.push_back(child); |
| 183 | + } |
| 184 | + } |
| 185 | + if(found) { |
| 186 | + break; |
| 187 | + } |
| 188 | + } |
| 189 | + queue = std::move(next_queue); |
| 190 | + } |
| 191 | + |
| 192 | + if(!found) { |
| 193 | + return {}; |
| 194 | + } |
| 195 | + |
| 196 | + // Reconstruct path from target back to host. |
| 197 | + std::vector<std::uint32_t> chain; |
| 198 | + auto node = target_path_id; |
| 199 | + while(node != host_path_id) { |
| 200 | + chain.push_back(node); |
| 201 | + node = prev[node]; |
| 202 | + } |
| 203 | + chain.push_back(host_path_id); |
| 204 | + std::reverse(chain.begin(), chain.end()); |
| 205 | + return chain; |
| 206 | +} |
| 207 | + |
104 | 208 | // ============================================================================ |
105 | 209 | // Wavefront BFS scanner — async implementation |
106 | 210 | // ============================================================================ |
|
0 commit comments