xref: /aosp_15_r20/external/stg/unification.cc (revision 9e3b08ae94a55201065475453d799e8b1378bea6)
1*9e3b08aeSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2*9e3b08aeSAndroid Build Coastguard Worker // -*- mode: C++ -*-
3*9e3b08aeSAndroid Build Coastguard Worker //
4*9e3b08aeSAndroid Build Coastguard Worker // Copyright 2022-2024 Google LLC
5*9e3b08aeSAndroid Build Coastguard Worker //
6*9e3b08aeSAndroid Build Coastguard Worker // Licensed under the Apache License v2.0 with LLVM Exceptions (the
7*9e3b08aeSAndroid Build Coastguard Worker // "License"); you may not use this file except in compliance with the
8*9e3b08aeSAndroid Build Coastguard Worker // License.  You may obtain a copy of the License at
9*9e3b08aeSAndroid Build Coastguard Worker //
10*9e3b08aeSAndroid Build Coastguard Worker //     https://llvm.org/LICENSE.txt
11*9e3b08aeSAndroid Build Coastguard Worker //
12*9e3b08aeSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
13*9e3b08aeSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
14*9e3b08aeSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*9e3b08aeSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
16*9e3b08aeSAndroid Build Coastguard Worker // limitations under the License.
17*9e3b08aeSAndroid Build Coastguard Worker //
18*9e3b08aeSAndroid Build Coastguard Worker // Author: Giuliano Procida
19*9e3b08aeSAndroid Build Coastguard Worker 
20*9e3b08aeSAndroid Build Coastguard Worker #include "unification.h"
21*9e3b08aeSAndroid Build Coastguard Worker 
22*9e3b08aeSAndroid Build Coastguard Worker #include <cstddef>
23*9e3b08aeSAndroid Build Coastguard Worker #include <map>
24*9e3b08aeSAndroid Build Coastguard Worker #include <optional>
25*9e3b08aeSAndroid Build Coastguard Worker #include <utility>
26*9e3b08aeSAndroid Build Coastguard Worker #include <unordered_map>
27*9e3b08aeSAndroid Build Coastguard Worker #include <unordered_set>
28*9e3b08aeSAndroid Build Coastguard Worker #include <vector>
29*9e3b08aeSAndroid Build Coastguard Worker 
30*9e3b08aeSAndroid Build Coastguard Worker #include "graph.h"
31*9e3b08aeSAndroid Build Coastguard Worker 
32*9e3b08aeSAndroid Build Coastguard Worker namespace stg {
33*9e3b08aeSAndroid Build Coastguard Worker 
34*9e3b08aeSAndroid Build Coastguard Worker namespace {
35*9e3b08aeSAndroid Build Coastguard Worker 
36*9e3b08aeSAndroid Build Coastguard Worker // Type Unification
37*9e3b08aeSAndroid Build Coastguard Worker //
38*9e3b08aeSAndroid Build Coastguard Worker // This is very similar to Equals. The differences are the recursion control,
39*9e3b08aeSAndroid Build Coastguard Worker // caching and handling of StructUnion and Enum nodes.
40*9e3b08aeSAndroid Build Coastguard Worker //
41*9e3b08aeSAndroid Build Coastguard Worker // During unification, keep track of which pairs of types need to be equal, but
42*9e3b08aeSAndroid Build Coastguard Worker // do not add them immediately to the unification substitutions. The caller can
43*9e3b08aeSAndroid Build Coastguard Worker // do that if the whole unification succeeds.
44*9e3b08aeSAndroid Build Coastguard Worker //
45*9e3b08aeSAndroid Build Coastguard Worker // A declaration and definition of the same named type can be unified. This is
46*9e3b08aeSAndroid Build Coastguard Worker // forward declaration resolution.
47*9e3b08aeSAndroid Build Coastguard Worker struct Unifier {
48*9e3b08aeSAndroid Build Coastguard Worker   enum Winner { Neither, Right, Left };  // makes p ? Right : Neither a no-op
49*9e3b08aeSAndroid Build Coastguard Worker 
Unifierstg::__anon655e05910111::Unifier50*9e3b08aeSAndroid Build Coastguard Worker   Unifier(const Graph& graph, Unification& unification)
51*9e3b08aeSAndroid Build Coastguard Worker       : graph(graph), unification(unification) {}
52*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier53*9e3b08aeSAndroid Build Coastguard Worker   bool operator()(Id id1, Id id2) {
54*9e3b08aeSAndroid Build Coastguard Worker     Id fid1 = Find(id1);
55*9e3b08aeSAndroid Build Coastguard Worker     Id fid2 = Find(id2);
56*9e3b08aeSAndroid Build Coastguard Worker     if (fid1 == fid2) {
57*9e3b08aeSAndroid Build Coastguard Worker       return true;
58*9e3b08aeSAndroid Build Coastguard Worker     }
59*9e3b08aeSAndroid Build Coastguard Worker 
60*9e3b08aeSAndroid Build Coastguard Worker     // Check if the comparison has been (or is being) visited already. We don't
61*9e3b08aeSAndroid Build Coastguard Worker     // need an SCC finder as any failure to unify will poison the entire DFS.
62*9e3b08aeSAndroid Build Coastguard Worker     //
63*9e3b08aeSAndroid Build Coastguard Worker     // This prevents infinite recursion, but maybe not immediately as seen is
64*9e3b08aeSAndroid Build Coastguard Worker     // unaware of new mappings.
65*9e3b08aeSAndroid Build Coastguard Worker     if (!seen.emplace(fid1, fid2).second) {
66*9e3b08aeSAndroid Build Coastguard Worker       return true;
67*9e3b08aeSAndroid Build Coastguard Worker     }
68*9e3b08aeSAndroid Build Coastguard Worker 
69*9e3b08aeSAndroid Build Coastguard Worker     const auto winner = graph.Apply2(*this, fid1, fid2);
70*9e3b08aeSAndroid Build Coastguard Worker     if (winner == Neither) {
71*9e3b08aeSAndroid Build Coastguard Worker       return false;
72*9e3b08aeSAndroid Build Coastguard Worker     }
73*9e3b08aeSAndroid Build Coastguard Worker 
74*9e3b08aeSAndroid Build Coastguard Worker     // These will occasionally get substituted due to a recursive call.
75*9e3b08aeSAndroid Build Coastguard Worker     fid1 = Find(fid1);
76*9e3b08aeSAndroid Build Coastguard Worker     fid2 = Find(fid2);
77*9e3b08aeSAndroid Build Coastguard Worker     if (fid1 == fid2) {
78*9e3b08aeSAndroid Build Coastguard Worker       return true;
79*9e3b08aeSAndroid Build Coastguard Worker     }
80*9e3b08aeSAndroid Build Coastguard Worker 
81*9e3b08aeSAndroid Build Coastguard Worker     if (winner == Left) {
82*9e3b08aeSAndroid Build Coastguard Worker       std::swap(fid1, fid2);
83*9e3b08aeSAndroid Build Coastguard Worker     }
84*9e3b08aeSAndroid Build Coastguard Worker     mapping.insert({fid1, fid2});
85*9e3b08aeSAndroid Build Coastguard Worker 
86*9e3b08aeSAndroid Build Coastguard Worker     return true;
87*9e3b08aeSAndroid Build Coastguard Worker   }
88*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier89*9e3b08aeSAndroid Build Coastguard Worker   bool operator()(const std::optional<Id>& opt1,
90*9e3b08aeSAndroid Build Coastguard Worker                   const std::optional<Id>& opt2) {
91*9e3b08aeSAndroid Build Coastguard Worker     if (opt1.has_value() && opt2.has_value()) {
92*9e3b08aeSAndroid Build Coastguard Worker       return (*this)(opt1.value(), opt2.value());
93*9e3b08aeSAndroid Build Coastguard Worker     }
94*9e3b08aeSAndroid Build Coastguard Worker     return opt1.has_value() == opt2.has_value();
95*9e3b08aeSAndroid Build Coastguard Worker   }
96*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier97*9e3b08aeSAndroid Build Coastguard Worker   bool operator()(const std::vector<Id>& ids1, const std::vector<Id>& ids2) {
98*9e3b08aeSAndroid Build Coastguard Worker     bool result = ids1.size() == ids2.size();
99*9e3b08aeSAndroid Build Coastguard Worker     for (size_t ix = 0; result && ix < ids1.size(); ++ix) {
100*9e3b08aeSAndroid Build Coastguard Worker       result = (*this)(ids1[ix], ids2[ix]);
101*9e3b08aeSAndroid Build Coastguard Worker     }
102*9e3b08aeSAndroid Build Coastguard Worker     return result;
103*9e3b08aeSAndroid Build Coastguard Worker   }
104*9e3b08aeSAndroid Build Coastguard Worker 
105*9e3b08aeSAndroid Build Coastguard Worker   template <typename Key>
operator ()stg::__anon655e05910111::Unifier106*9e3b08aeSAndroid Build Coastguard Worker   bool operator()(const std::map<Key, Id>& ids1,
107*9e3b08aeSAndroid Build Coastguard Worker                   const std::map<Key, Id>& ids2) {
108*9e3b08aeSAndroid Build Coastguard Worker     bool result = ids1.size() == ids2.size();
109*9e3b08aeSAndroid Build Coastguard Worker     auto it1 = ids1.begin();
110*9e3b08aeSAndroid Build Coastguard Worker     auto it2 = ids2.begin();
111*9e3b08aeSAndroid Build Coastguard Worker     const auto end1 = ids1.end();
112*9e3b08aeSAndroid Build Coastguard Worker     const auto end2 = ids2.end();
113*9e3b08aeSAndroid Build Coastguard Worker     while (result && it1 != end1 && it2 != end2) {
114*9e3b08aeSAndroid Build Coastguard Worker       result = it1->first == it2->first
115*9e3b08aeSAndroid Build Coastguard Worker                && (*this)(it1->second, it2->second);
116*9e3b08aeSAndroid Build Coastguard Worker       ++it1;
117*9e3b08aeSAndroid Build Coastguard Worker       ++it2;
118*9e3b08aeSAndroid Build Coastguard Worker     }
119*9e3b08aeSAndroid Build Coastguard Worker     return result && it1 == end1 && it2 == end2;
120*9e3b08aeSAndroid Build Coastguard Worker   }
121*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier122*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Special& x1, const Special& x2) {
123*9e3b08aeSAndroid Build Coastguard Worker     return x1.kind == x2.kind
124*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
125*9e3b08aeSAndroid Build Coastguard Worker   }
126*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier127*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const PointerReference& x1,
128*9e3b08aeSAndroid Build Coastguard Worker                     const PointerReference& x2) {
129*9e3b08aeSAndroid Build Coastguard Worker     return x1.kind == x2.kind
130*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.pointee_type_id, x2.pointee_type_id)
131*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
132*9e3b08aeSAndroid Build Coastguard Worker   }
133*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier134*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const PointerToMember& x1, const PointerToMember& x2) {
135*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(x1.containing_type_id, x2.containing_type_id)
136*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.pointee_type_id, x2.pointee_type_id)
137*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
138*9e3b08aeSAndroid Build Coastguard Worker   }
139*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier140*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Typedef& x1, const Typedef& x2) {
141*9e3b08aeSAndroid Build Coastguard Worker     return x1.name == x2.name
142*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.referred_type_id, x2.referred_type_id)
143*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
144*9e3b08aeSAndroid Build Coastguard Worker   }
145*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier146*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Qualified& x1, const Qualified& x2) {
147*9e3b08aeSAndroid Build Coastguard Worker     return x1.qualifier == x2.qualifier
148*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.qualified_type_id, x2.qualified_type_id)
149*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
150*9e3b08aeSAndroid Build Coastguard Worker   }
151*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier152*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Primitive& x1, const Primitive& x2) {
153*9e3b08aeSAndroid Build Coastguard Worker     return x1.name == x2.name
154*9e3b08aeSAndroid Build Coastguard Worker         && x1.encoding == x2.encoding
155*9e3b08aeSAndroid Build Coastguard Worker         && x1.bytesize == x2.bytesize
156*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
157*9e3b08aeSAndroid Build Coastguard Worker   }
158*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier159*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Array& x1, const Array& x2) {
160*9e3b08aeSAndroid Build Coastguard Worker     return x1.number_of_elements == x2.number_of_elements
161*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.element_type_id, x2.element_type_id)
162*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
163*9e3b08aeSAndroid Build Coastguard Worker   }
164*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier165*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const BaseClass& x1, const BaseClass& x2) {
166*9e3b08aeSAndroid Build Coastguard Worker     return x1.offset == x2.offset
167*9e3b08aeSAndroid Build Coastguard Worker         && x1.inheritance == x2.inheritance
168*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.type_id, x2.type_id)
169*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
170*9e3b08aeSAndroid Build Coastguard Worker   }
171*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier172*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Method& x1, const Method& x2) {
173*9e3b08aeSAndroid Build Coastguard Worker     return x1.mangled_name == x2.mangled_name
174*9e3b08aeSAndroid Build Coastguard Worker         && x1.name == x2.name
175*9e3b08aeSAndroid Build Coastguard Worker         && x1.vtable_offset == x2.vtable_offset
176*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.type_id, x2.type_id)
177*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
178*9e3b08aeSAndroid Build Coastguard Worker   }
179*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier180*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Member& x1, const Member& x2) {
181*9e3b08aeSAndroid Build Coastguard Worker     return x1.name == x2.name
182*9e3b08aeSAndroid Build Coastguard Worker         && x1.offset == x2.offset
183*9e3b08aeSAndroid Build Coastguard Worker         && x1.bitsize == x2.bitsize
184*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.type_id, x2.type_id)
185*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
186*9e3b08aeSAndroid Build Coastguard Worker   }
187*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier188*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const VariantMember& x1, const VariantMember& x2) {
189*9e3b08aeSAndroid Build Coastguard Worker     return x1.name == x2.name
190*9e3b08aeSAndroid Build Coastguard Worker         && x1.discriminant_value == x2.discriminant_value
191*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.type_id, x2.type_id)
192*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
193*9e3b08aeSAndroid Build Coastguard Worker   }
194*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier195*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const StructUnion& x1, const StructUnion& x2) {
196*9e3b08aeSAndroid Build Coastguard Worker     const auto& definition1 = x1.definition;
197*9e3b08aeSAndroid Build Coastguard Worker     const auto& definition2 = x2.definition;
198*9e3b08aeSAndroid Build Coastguard Worker     bool result = x1.kind == x2.kind
199*9e3b08aeSAndroid Build Coastguard Worker                   && x1.name == x2.name;
200*9e3b08aeSAndroid Build Coastguard Worker     // allow mismatches as forward declarations are always unifiable
201*9e3b08aeSAndroid Build Coastguard Worker     if (result && definition1.has_value() && definition2.has_value()) {
202*9e3b08aeSAndroid Build Coastguard Worker       result = definition1->bytesize == definition2->bytesize
203*9e3b08aeSAndroid Build Coastguard Worker                && (*this)(definition1->base_classes, definition2->base_classes)
204*9e3b08aeSAndroid Build Coastguard Worker                && (*this)(definition1->methods, definition2->methods)
205*9e3b08aeSAndroid Build Coastguard Worker                && (*this)(definition1->members, definition2->members);
206*9e3b08aeSAndroid Build Coastguard Worker     }
207*9e3b08aeSAndroid Build Coastguard Worker     return result ? definition2.has_value() ? Right : Left : Neither;
208*9e3b08aeSAndroid Build Coastguard Worker   }
209*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier210*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Enumeration& x1, const Enumeration& x2) {
211*9e3b08aeSAndroid Build Coastguard Worker     const auto& definition1 = x1.definition;
212*9e3b08aeSAndroid Build Coastguard Worker     const auto& definition2 = x2.definition;
213*9e3b08aeSAndroid Build Coastguard Worker     bool result = x1.name == x2.name;
214*9e3b08aeSAndroid Build Coastguard Worker     // allow mismatches as forward declarations are always unifiable
215*9e3b08aeSAndroid Build Coastguard Worker     if (result && definition1.has_value() && definition2.has_value()) {
216*9e3b08aeSAndroid Build Coastguard Worker       result = (*this)(definition1->underlying_type_id,
217*9e3b08aeSAndroid Build Coastguard Worker                        definition2->underlying_type_id)
218*9e3b08aeSAndroid Build Coastguard Worker                && definition1->enumerators == definition2->enumerators;
219*9e3b08aeSAndroid Build Coastguard Worker     }
220*9e3b08aeSAndroid Build Coastguard Worker     return result ? definition2.has_value() ? Right : Left : Neither;
221*9e3b08aeSAndroid Build Coastguard Worker   }
222*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier223*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Variant& x1, const Variant& x2) {
224*9e3b08aeSAndroid Build Coastguard Worker     return x1.name == x2.name
225*9e3b08aeSAndroid Build Coastguard Worker         && x1.bytesize == x2.bytesize
226*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.discriminant, x2.discriminant)
227*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.members, x2.members)
228*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
229*9e3b08aeSAndroid Build Coastguard Worker   }
230*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier231*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Function& x1, const Function& x2) {
232*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(x1.parameters, x2.parameters)
233*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.return_type_id, x2.return_type_id)
234*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
235*9e3b08aeSAndroid Build Coastguard Worker   }
236*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier237*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const ElfSymbol& x1, const ElfSymbol& x2) {
238*9e3b08aeSAndroid Build Coastguard Worker     bool result = x1.symbol_name == x2.symbol_name
239*9e3b08aeSAndroid Build Coastguard Worker                   && x1.version_info == x2.version_info
240*9e3b08aeSAndroid Build Coastguard Worker                   && x1.is_defined == x2.is_defined
241*9e3b08aeSAndroid Build Coastguard Worker                   && x1.symbol_type == x2.symbol_type
242*9e3b08aeSAndroid Build Coastguard Worker                   && x1.binding == x2.binding
243*9e3b08aeSAndroid Build Coastguard Worker                   && x1.visibility == x2.visibility
244*9e3b08aeSAndroid Build Coastguard Worker                   && x1.crc == x2.crc
245*9e3b08aeSAndroid Build Coastguard Worker                   && x1.ns == x2.ns
246*9e3b08aeSAndroid Build Coastguard Worker                   && x1.full_name == x2.full_name
247*9e3b08aeSAndroid Build Coastguard Worker                   && x1.type_id.has_value() == x2.type_id.has_value();
248*9e3b08aeSAndroid Build Coastguard Worker     if (result && x1.type_id.has_value()) {
249*9e3b08aeSAndroid Build Coastguard Worker       result = (*this)(x1.type_id.value(), x2.type_id.value());
250*9e3b08aeSAndroid Build Coastguard Worker     }
251*9e3b08aeSAndroid Build Coastguard Worker     return result ? Right : Neither;
252*9e3b08aeSAndroid Build Coastguard Worker   }
253*9e3b08aeSAndroid Build Coastguard Worker 
operator ()stg::__anon655e05910111::Unifier254*9e3b08aeSAndroid Build Coastguard Worker   Winner operator()(const Interface& x1, const Interface& x2) {
255*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(x1.symbols, x2.symbols)
256*9e3b08aeSAndroid Build Coastguard Worker         && (*this)(x1.types, x2.types)
257*9e3b08aeSAndroid Build Coastguard Worker         ? Right : Neither;
258*9e3b08aeSAndroid Build Coastguard Worker   }
259*9e3b08aeSAndroid Build Coastguard Worker 
Mismatchstg::__anon655e05910111::Unifier260*9e3b08aeSAndroid Build Coastguard Worker   Winner Mismatch() {
261*9e3b08aeSAndroid Build Coastguard Worker     return Neither;
262*9e3b08aeSAndroid Build Coastguard Worker   }
263*9e3b08aeSAndroid Build Coastguard Worker 
Findstg::__anon655e05910111::Unifier264*9e3b08aeSAndroid Build Coastguard Worker   Id Find(Id id) {
265*9e3b08aeSAndroid Build Coastguard Worker     while (true) {
266*9e3b08aeSAndroid Build Coastguard Worker       id = unification.Find(id);
267*9e3b08aeSAndroid Build Coastguard Worker       auto it = mapping.find(id);
268*9e3b08aeSAndroid Build Coastguard Worker       if (it != mapping.end()) {
269*9e3b08aeSAndroid Build Coastguard Worker         id = it->second;
270*9e3b08aeSAndroid Build Coastguard Worker         continue;
271*9e3b08aeSAndroid Build Coastguard Worker       }
272*9e3b08aeSAndroid Build Coastguard Worker       return id;
273*9e3b08aeSAndroid Build Coastguard Worker     }
274*9e3b08aeSAndroid Build Coastguard Worker   }
275*9e3b08aeSAndroid Build Coastguard Worker 
276*9e3b08aeSAndroid Build Coastguard Worker   const Graph& graph;
277*9e3b08aeSAndroid Build Coastguard Worker   Unification& unification;
278*9e3b08aeSAndroid Build Coastguard Worker   std::unordered_set<Pair> seen;
279*9e3b08aeSAndroid Build Coastguard Worker   std::unordered_map<Id, Id> mapping;
280*9e3b08aeSAndroid Build Coastguard Worker };
281*9e3b08aeSAndroid Build Coastguard Worker 
282*9e3b08aeSAndroid Build Coastguard Worker }  // namespace
283*9e3b08aeSAndroid Build Coastguard Worker 
Unify(Id id1,Id id2)284*9e3b08aeSAndroid Build Coastguard Worker bool Unification::Unify(Id id1, Id id2) {
285*9e3b08aeSAndroid Build Coastguard Worker   // TODO: Unifier only needs access to Unification::Find
286*9e3b08aeSAndroid Build Coastguard Worker   Unifier unifier(graph_, *this);
287*9e3b08aeSAndroid Build Coastguard Worker   if (unifier(id1, id2)) {
288*9e3b08aeSAndroid Build Coastguard Worker     // commit
289*9e3b08aeSAndroid Build Coastguard Worker     for (const auto& s : unifier.mapping) {
290*9e3b08aeSAndroid Build Coastguard Worker       Union(s.first, s.second);
291*9e3b08aeSAndroid Build Coastguard Worker     }
292*9e3b08aeSAndroid Build Coastguard Worker     return true;
293*9e3b08aeSAndroid Build Coastguard Worker   }
294*9e3b08aeSAndroid Build Coastguard Worker   return false;
295*9e3b08aeSAndroid Build Coastguard Worker }
296*9e3b08aeSAndroid Build Coastguard Worker 
297*9e3b08aeSAndroid Build Coastguard Worker }  // namespace stg
298