xref: /aosp_15_r20/external/llvm/lib/TableGen/SetTheory.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the SetTheory class that computes ordered sets of
11*9880d681SAndroid Build Coastguard Worker // Records from DAG expressions.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/SetTheory.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/Error.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/TableGen/Record.h"
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker using namespace llvm;
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker // Define the standard operators.
23*9880d681SAndroid Build Coastguard Worker namespace {
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker typedef SetTheory::RecSet RecSet;
26*9880d681SAndroid Build Coastguard Worker typedef SetTheory::RecVec RecVec;
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker // (add a, b, ...) Evaluate and union all arguments.
29*9880d681SAndroid Build Coastguard Worker struct AddOp : public SetTheory::Operator {
apply__anonb3b0c5000111::AddOp30*9880d681SAndroid Build Coastguard Worker   void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
31*9880d681SAndroid Build Coastguard Worker              ArrayRef<SMLoc> Loc) override {
32*9880d681SAndroid Build Coastguard Worker     ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc);
33*9880d681SAndroid Build Coastguard Worker   }
34*9880d681SAndroid Build Coastguard Worker };
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker // (sub Add, Sub, ...) Set difference.
37*9880d681SAndroid Build Coastguard Worker struct SubOp : public SetTheory::Operator {
apply__anonb3b0c5000111::SubOp38*9880d681SAndroid Build Coastguard Worker   void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
39*9880d681SAndroid Build Coastguard Worker              ArrayRef<SMLoc> Loc) override {
40*9880d681SAndroid Build Coastguard Worker     if (Expr->arg_size() < 2)
41*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Set difference needs at least two arguments: " +
42*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
43*9880d681SAndroid Build Coastguard Worker     RecSet Add, Sub;
44*9880d681SAndroid Build Coastguard Worker     ST.evaluate(*Expr->arg_begin(), Add, Loc);
45*9880d681SAndroid Build Coastguard Worker     ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub, Loc);
46*9880d681SAndroid Build Coastguard Worker     for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I)
47*9880d681SAndroid Build Coastguard Worker       if (!Sub.count(*I))
48*9880d681SAndroid Build Coastguard Worker         Elts.insert(*I);
49*9880d681SAndroid Build Coastguard Worker   }
50*9880d681SAndroid Build Coastguard Worker };
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker // (and S1, S2) Set intersection.
53*9880d681SAndroid Build Coastguard Worker struct AndOp : public SetTheory::Operator {
apply__anonb3b0c5000111::AndOp54*9880d681SAndroid Build Coastguard Worker   void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
55*9880d681SAndroid Build Coastguard Worker              ArrayRef<SMLoc> Loc) override {
56*9880d681SAndroid Build Coastguard Worker     if (Expr->arg_size() != 2)
57*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Set intersection requires two arguments: " +
58*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
59*9880d681SAndroid Build Coastguard Worker     RecSet S1, S2;
60*9880d681SAndroid Build Coastguard Worker     ST.evaluate(Expr->arg_begin()[0], S1, Loc);
61*9880d681SAndroid Build Coastguard Worker     ST.evaluate(Expr->arg_begin()[1], S2, Loc);
62*9880d681SAndroid Build Coastguard Worker     for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I)
63*9880d681SAndroid Build Coastguard Worker       if (S2.count(*I))
64*9880d681SAndroid Build Coastguard Worker         Elts.insert(*I);
65*9880d681SAndroid Build Coastguard Worker   }
66*9880d681SAndroid Build Coastguard Worker };
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker // SetIntBinOp - Abstract base class for (Op S, N) operators.
69*9880d681SAndroid Build Coastguard Worker struct SetIntBinOp : public SetTheory::Operator {
70*9880d681SAndroid Build Coastguard Worker   virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
71*9880d681SAndroid Build Coastguard Worker                       RecSet &Elts, ArrayRef<SMLoc> Loc) = 0;
72*9880d681SAndroid Build Coastguard Worker 
apply__anonb3b0c5000111::SetIntBinOp73*9880d681SAndroid Build Coastguard Worker   void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
74*9880d681SAndroid Build Coastguard Worker              ArrayRef<SMLoc> Loc) override {
75*9880d681SAndroid Build Coastguard Worker     if (Expr->arg_size() != 2)
76*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " +
77*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
78*9880d681SAndroid Build Coastguard Worker     RecSet Set;
79*9880d681SAndroid Build Coastguard Worker     ST.evaluate(Expr->arg_begin()[0], Set, Loc);
80*9880d681SAndroid Build Coastguard Worker     IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]);
81*9880d681SAndroid Build Coastguard Worker     if (!II)
82*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Second argument must be an integer: " +
83*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
84*9880d681SAndroid Build Coastguard Worker     apply2(ST, Expr, Set, II->getValue(), Elts, Loc);
85*9880d681SAndroid Build Coastguard Worker   }
86*9880d681SAndroid Build Coastguard Worker };
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker // (shl S, N) Shift left, remove the first N elements.
89*9880d681SAndroid Build Coastguard Worker struct ShlOp : public SetIntBinOp {
apply2__anonb3b0c5000111::ShlOp90*9880d681SAndroid Build Coastguard Worker   void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
91*9880d681SAndroid Build Coastguard Worker               RecSet &Elts, ArrayRef<SMLoc> Loc) override {
92*9880d681SAndroid Build Coastguard Worker     if (N < 0)
93*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Positive shift required: " +
94*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
95*9880d681SAndroid Build Coastguard Worker     if (unsigned(N) < Set.size())
96*9880d681SAndroid Build Coastguard Worker       Elts.insert(Set.begin() + N, Set.end());
97*9880d681SAndroid Build Coastguard Worker   }
98*9880d681SAndroid Build Coastguard Worker };
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker // (trunc S, N) Truncate after the first N elements.
101*9880d681SAndroid Build Coastguard Worker struct TruncOp : public SetIntBinOp {
apply2__anonb3b0c5000111::TruncOp102*9880d681SAndroid Build Coastguard Worker   void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
103*9880d681SAndroid Build Coastguard Worker               RecSet &Elts, ArrayRef<SMLoc> Loc) override {
104*9880d681SAndroid Build Coastguard Worker     if (N < 0)
105*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Positive length required: " +
106*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
107*9880d681SAndroid Build Coastguard Worker     if (unsigned(N) > Set.size())
108*9880d681SAndroid Build Coastguard Worker       N = Set.size();
109*9880d681SAndroid Build Coastguard Worker     Elts.insert(Set.begin(), Set.begin() + N);
110*9880d681SAndroid Build Coastguard Worker   }
111*9880d681SAndroid Build Coastguard Worker };
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker // Left/right rotation.
114*9880d681SAndroid Build Coastguard Worker struct RotOp : public SetIntBinOp {
115*9880d681SAndroid Build Coastguard Worker   const bool Reverse;
116*9880d681SAndroid Build Coastguard Worker 
RotOp__anonb3b0c5000111::RotOp117*9880d681SAndroid Build Coastguard Worker   RotOp(bool Rev) : Reverse(Rev) {}
118*9880d681SAndroid Build Coastguard Worker 
apply2__anonb3b0c5000111::RotOp119*9880d681SAndroid Build Coastguard Worker   void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
120*9880d681SAndroid Build Coastguard Worker               RecSet &Elts, ArrayRef<SMLoc> Loc) override {
121*9880d681SAndroid Build Coastguard Worker     if (Reverse)
122*9880d681SAndroid Build Coastguard Worker       N = -N;
123*9880d681SAndroid Build Coastguard Worker     // N > 0 -> rotate left, N < 0 -> rotate right.
124*9880d681SAndroid Build Coastguard Worker     if (Set.empty())
125*9880d681SAndroid Build Coastguard Worker       return;
126*9880d681SAndroid Build Coastguard Worker     if (N < 0)
127*9880d681SAndroid Build Coastguard Worker       N = Set.size() - (-N % Set.size());
128*9880d681SAndroid Build Coastguard Worker     else
129*9880d681SAndroid Build Coastguard Worker       N %= Set.size();
130*9880d681SAndroid Build Coastguard Worker     Elts.insert(Set.begin() + N, Set.end());
131*9880d681SAndroid Build Coastguard Worker     Elts.insert(Set.begin(), Set.begin() + N);
132*9880d681SAndroid Build Coastguard Worker   }
133*9880d681SAndroid Build Coastguard Worker };
134*9880d681SAndroid Build Coastguard Worker 
135*9880d681SAndroid Build Coastguard Worker // (decimate S, N) Pick every N'th element of S.
136*9880d681SAndroid Build Coastguard Worker struct DecimateOp : public SetIntBinOp {
apply2__anonb3b0c5000111::DecimateOp137*9880d681SAndroid Build Coastguard Worker   void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N,
138*9880d681SAndroid Build Coastguard Worker               RecSet &Elts, ArrayRef<SMLoc> Loc) override {
139*9880d681SAndroid Build Coastguard Worker     if (N <= 0)
140*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Positive stride required: " +
141*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
142*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0; I < Set.size(); I += N)
143*9880d681SAndroid Build Coastguard Worker       Elts.insert(Set[I]);
144*9880d681SAndroid Build Coastguard Worker   }
145*9880d681SAndroid Build Coastguard Worker };
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker // (interleave S1, S2, ...) Interleave elements of the arguments.
148*9880d681SAndroid Build Coastguard Worker struct InterleaveOp : public SetTheory::Operator {
apply__anonb3b0c5000111::InterleaveOp149*9880d681SAndroid Build Coastguard Worker   void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
150*9880d681SAndroid Build Coastguard Worker              ArrayRef<SMLoc> Loc) override {
151*9880d681SAndroid Build Coastguard Worker     // Evaluate the arguments individually.
152*9880d681SAndroid Build Coastguard Worker     SmallVector<RecSet, 4> Args(Expr->getNumArgs());
153*9880d681SAndroid Build Coastguard Worker     unsigned MaxSize = 0;
154*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) {
155*9880d681SAndroid Build Coastguard Worker       ST.evaluate(Expr->getArg(i), Args[i], Loc);
156*9880d681SAndroid Build Coastguard Worker       MaxSize = std::max(MaxSize, unsigned(Args[i].size()));
157*9880d681SAndroid Build Coastguard Worker     }
158*9880d681SAndroid Build Coastguard Worker     // Interleave arguments into Elts.
159*9880d681SAndroid Build Coastguard Worker     for (unsigned n = 0; n != MaxSize; ++n)
160*9880d681SAndroid Build Coastguard Worker       for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i)
161*9880d681SAndroid Build Coastguard Worker         if (n < Args[i].size())
162*9880d681SAndroid Build Coastguard Worker           Elts.insert(Args[i][n]);
163*9880d681SAndroid Build Coastguard Worker   }
164*9880d681SAndroid Build Coastguard Worker };
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker // (sequence "Format", From, To) Generate a sequence of records by name.
167*9880d681SAndroid Build Coastguard Worker struct SequenceOp : public SetTheory::Operator {
apply__anonb3b0c5000111::SequenceOp168*9880d681SAndroid Build Coastguard Worker   void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
169*9880d681SAndroid Build Coastguard Worker              ArrayRef<SMLoc> Loc) override {
170*9880d681SAndroid Build Coastguard Worker     int Step = 1;
171*9880d681SAndroid Build Coastguard Worker     if (Expr->arg_size() > 4)
172*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " +
173*9880d681SAndroid Build Coastguard Worker         Expr->getAsString());
174*9880d681SAndroid Build Coastguard Worker     else if (Expr->arg_size() == 4) {
175*9880d681SAndroid Build Coastguard Worker       if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) {
176*9880d681SAndroid Build Coastguard Worker         Step = II->getValue();
177*9880d681SAndroid Build Coastguard Worker       } else
178*9880d681SAndroid Build Coastguard Worker         PrintFatalError(Loc, "Stride must be an integer: " +
179*9880d681SAndroid Build Coastguard Worker           Expr->getAsString());
180*9880d681SAndroid Build Coastguard Worker     }
181*9880d681SAndroid Build Coastguard Worker 
182*9880d681SAndroid Build Coastguard Worker     std::string Format;
183*9880d681SAndroid Build Coastguard Worker     if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0]))
184*9880d681SAndroid Build Coastguard Worker       Format = SI->getValue();
185*9880d681SAndroid Build Coastguard Worker     else
186*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc,  "Format must be a string: " + Expr->getAsString());
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker     int64_t From, To;
189*9880d681SAndroid Build Coastguard Worker     if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]))
190*9880d681SAndroid Build Coastguard Worker       From = II->getValue();
191*9880d681SAndroid Build Coastguard Worker     else
192*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString());
193*9880d681SAndroid Build Coastguard Worker     if (From < 0 || From >= (1 << 30))
194*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "From out of range");
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker     if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[2]))
197*9880d681SAndroid Build Coastguard Worker       To = II->getValue();
198*9880d681SAndroid Build Coastguard Worker     else
199*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "To must be an integer: " + Expr->getAsString());
200*9880d681SAndroid Build Coastguard Worker     if (To < 0 || To >= (1 << 30))
201*9880d681SAndroid Build Coastguard Worker       PrintFatalError(Loc, "To out of range");
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker     RecordKeeper &Records =
204*9880d681SAndroid Build Coastguard Worker       cast<DefInit>(Expr->getOperator())->getDef()->getRecords();
205*9880d681SAndroid Build Coastguard Worker 
206*9880d681SAndroid Build Coastguard Worker     Step *= From <= To ? 1 : -1;
207*9880d681SAndroid Build Coastguard Worker     while (true) {
208*9880d681SAndroid Build Coastguard Worker       if (Step > 0 && From > To)
209*9880d681SAndroid Build Coastguard Worker         break;
210*9880d681SAndroid Build Coastguard Worker       else if (Step < 0 && From < To)
211*9880d681SAndroid Build Coastguard Worker         break;
212*9880d681SAndroid Build Coastguard Worker       std::string Name;
213*9880d681SAndroid Build Coastguard Worker       raw_string_ostream OS(Name);
214*9880d681SAndroid Build Coastguard Worker       OS << format(Format.c_str(), unsigned(From));
215*9880d681SAndroid Build Coastguard Worker       Record *Rec = Records.getDef(OS.str());
216*9880d681SAndroid Build Coastguard Worker       if (!Rec)
217*9880d681SAndroid Build Coastguard Worker         PrintFatalError(Loc, "No def named '" + Name + "': " +
218*9880d681SAndroid Build Coastguard Worker           Expr->getAsString());
219*9880d681SAndroid Build Coastguard Worker       // Try to reevaluate Rec in case it is a set.
220*9880d681SAndroid Build Coastguard Worker       if (const RecVec *Result = ST.expand(Rec))
221*9880d681SAndroid Build Coastguard Worker         Elts.insert(Result->begin(), Result->end());
222*9880d681SAndroid Build Coastguard Worker       else
223*9880d681SAndroid Build Coastguard Worker         Elts.insert(Rec);
224*9880d681SAndroid Build Coastguard Worker 
225*9880d681SAndroid Build Coastguard Worker       From += Step;
226*9880d681SAndroid Build Coastguard Worker     }
227*9880d681SAndroid Build Coastguard Worker   }
228*9880d681SAndroid Build Coastguard Worker };
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker // Expand a Def into a set by evaluating one of its fields.
231*9880d681SAndroid Build Coastguard Worker struct FieldExpander : public SetTheory::Expander {
232*9880d681SAndroid Build Coastguard Worker   StringRef FieldName;
233*9880d681SAndroid Build Coastguard Worker 
FieldExpander__anonb3b0c5000111::FieldExpander234*9880d681SAndroid Build Coastguard Worker   FieldExpander(StringRef fn) : FieldName(fn) {}
235*9880d681SAndroid Build Coastguard Worker 
expand__anonb3b0c5000111::FieldExpander236*9880d681SAndroid Build Coastguard Worker   void expand(SetTheory &ST, Record *Def, RecSet &Elts) override {
237*9880d681SAndroid Build Coastguard Worker     ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc());
238*9880d681SAndroid Build Coastguard Worker   }
239*9880d681SAndroid Build Coastguard Worker };
240*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker // Pin the vtables to this file.
anchor()243*9880d681SAndroid Build Coastguard Worker void SetTheory::Operator::anchor() {}
anchor()244*9880d681SAndroid Build Coastguard Worker void SetTheory::Expander::anchor() {}
245*9880d681SAndroid Build Coastguard Worker 
246*9880d681SAndroid Build Coastguard Worker 
SetTheory()247*9880d681SAndroid Build Coastguard Worker SetTheory::SetTheory() {
248*9880d681SAndroid Build Coastguard Worker   addOperator("add", llvm::make_unique<AddOp>());
249*9880d681SAndroid Build Coastguard Worker   addOperator("sub", llvm::make_unique<SubOp>());
250*9880d681SAndroid Build Coastguard Worker   addOperator("and", llvm::make_unique<AndOp>());
251*9880d681SAndroid Build Coastguard Worker   addOperator("shl", llvm::make_unique<ShlOp>());
252*9880d681SAndroid Build Coastguard Worker   addOperator("trunc", llvm::make_unique<TruncOp>());
253*9880d681SAndroid Build Coastguard Worker   addOperator("rotl", llvm::make_unique<RotOp>(false));
254*9880d681SAndroid Build Coastguard Worker   addOperator("rotr", llvm::make_unique<RotOp>(true));
255*9880d681SAndroid Build Coastguard Worker   addOperator("decimate", llvm::make_unique<DecimateOp>());
256*9880d681SAndroid Build Coastguard Worker   addOperator("interleave", llvm::make_unique<InterleaveOp>());
257*9880d681SAndroid Build Coastguard Worker   addOperator("sequence", llvm::make_unique<SequenceOp>());
258*9880d681SAndroid Build Coastguard Worker }
259*9880d681SAndroid Build Coastguard Worker 
addOperator(StringRef Name,std::unique_ptr<Operator> Op)260*9880d681SAndroid Build Coastguard Worker void SetTheory::addOperator(StringRef Name, std::unique_ptr<Operator> Op) {
261*9880d681SAndroid Build Coastguard Worker   Operators[Name] = std::move(Op);
262*9880d681SAndroid Build Coastguard Worker }
263*9880d681SAndroid Build Coastguard Worker 
addExpander(StringRef ClassName,std::unique_ptr<Expander> E)264*9880d681SAndroid Build Coastguard Worker void SetTheory::addExpander(StringRef ClassName, std::unique_ptr<Expander> E) {
265*9880d681SAndroid Build Coastguard Worker   Expanders[ClassName] = std::move(E);
266*9880d681SAndroid Build Coastguard Worker }
267*9880d681SAndroid Build Coastguard Worker 
addFieldExpander(StringRef ClassName,StringRef FieldName)268*9880d681SAndroid Build Coastguard Worker void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) {
269*9880d681SAndroid Build Coastguard Worker   addExpander(ClassName, llvm::make_unique<FieldExpander>(FieldName));
270*9880d681SAndroid Build Coastguard Worker }
271*9880d681SAndroid Build Coastguard Worker 
evaluate(Init * Expr,RecSet & Elts,ArrayRef<SMLoc> Loc)272*9880d681SAndroid Build Coastguard Worker void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
273*9880d681SAndroid Build Coastguard Worker   // A def in a list can be a just an element, or it may expand.
274*9880d681SAndroid Build Coastguard Worker   if (DefInit *Def = dyn_cast<DefInit>(Expr)) {
275*9880d681SAndroid Build Coastguard Worker     if (const RecVec *Result = expand(Def->getDef()))
276*9880d681SAndroid Build Coastguard Worker       return Elts.insert(Result->begin(), Result->end());
277*9880d681SAndroid Build Coastguard Worker     Elts.insert(Def->getDef());
278*9880d681SAndroid Build Coastguard Worker     return;
279*9880d681SAndroid Build Coastguard Worker   }
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker   // Lists simply expand.
282*9880d681SAndroid Build Coastguard Worker   if (ListInit *LI = dyn_cast<ListInit>(Expr))
283*9880d681SAndroid Build Coastguard Worker     return evaluate(LI->begin(), LI->end(), Elts, Loc);
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   // Anything else must be a DAG.
286*9880d681SAndroid Build Coastguard Worker   DagInit *DagExpr = dyn_cast<DagInit>(Expr);
287*9880d681SAndroid Build Coastguard Worker   if (!DagExpr)
288*9880d681SAndroid Build Coastguard Worker     PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString());
289*9880d681SAndroid Build Coastguard Worker   DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator());
290*9880d681SAndroid Build Coastguard Worker   if (!OpInit)
291*9880d681SAndroid Build Coastguard Worker     PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString());
292*9880d681SAndroid Build Coastguard Worker   auto I = Operators.find(OpInit->getDef()->getName());
293*9880d681SAndroid Build Coastguard Worker   if (I == Operators.end())
294*9880d681SAndroid Build Coastguard Worker     PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString());
295*9880d681SAndroid Build Coastguard Worker   I->second->apply(*this, DagExpr, Elts, Loc);
296*9880d681SAndroid Build Coastguard Worker }
297*9880d681SAndroid Build Coastguard Worker 
expand(Record * Set)298*9880d681SAndroid Build Coastguard Worker const RecVec *SetTheory::expand(Record *Set) {
299*9880d681SAndroid Build Coastguard Worker   // Check existing entries for Set and return early.
300*9880d681SAndroid Build Coastguard Worker   ExpandMap::iterator I = Expansions.find(Set);
301*9880d681SAndroid Build Coastguard Worker   if (I != Expansions.end())
302*9880d681SAndroid Build Coastguard Worker     return &I->second;
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker   // This is the first time we see Set. Find a suitable expander.
305*9880d681SAndroid Build Coastguard Worker   ArrayRef<std::pair<Record *, SMRange>> SC = Set->getSuperClasses();
306*9880d681SAndroid Build Coastguard Worker   for (const auto &SCPair : SC) {
307*9880d681SAndroid Build Coastguard Worker     // Skip unnamed superclasses.
308*9880d681SAndroid Build Coastguard Worker     if (!isa<StringInit>(SCPair.first->getNameInit()))
309*9880d681SAndroid Build Coastguard Worker       continue;
310*9880d681SAndroid Build Coastguard Worker     auto I = Expanders.find(SCPair.first->getName());
311*9880d681SAndroid Build Coastguard Worker     if (I != Expanders.end()) {
312*9880d681SAndroid Build Coastguard Worker       // This breaks recursive definitions.
313*9880d681SAndroid Build Coastguard Worker       RecVec &EltVec = Expansions[Set];
314*9880d681SAndroid Build Coastguard Worker       RecSet Elts;
315*9880d681SAndroid Build Coastguard Worker       I->second->expand(*this, Set, Elts);
316*9880d681SAndroid Build Coastguard Worker       EltVec.assign(Elts.begin(), Elts.end());
317*9880d681SAndroid Build Coastguard Worker       return &EltVec;
318*9880d681SAndroid Build Coastguard Worker     }
319*9880d681SAndroid Build Coastguard Worker   }
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker   // Set is not expandable.
322*9880d681SAndroid Build Coastguard Worker   return nullptr;
323*9880d681SAndroid Build Coastguard Worker }
324*9880d681SAndroid Build Coastguard Worker 
325