llvm.org GIT mirror llvm / 1de9982
Teach TableGen to evaluate DAG expressions as set operations. A TableGen backend can define how certain classes can be expanded into ordered sets of defs, typically by evaluating a specific field in the record. The SetTheory class can then evaluate DAG expressions that refer to these named sets. A number of standard set and list operations are predefined, and the backend can add more specialized operators if needed. The -print-sets backend is used by SetTheory.td to provide examples. This is intended to simplify how register classes are defined: def GR32_NOSP : RegisterClass<"X86", [i32], 32, (sub GR32, ESP)>; git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132621 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 8 years ago
5 changed file(s) with 593 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
0 // Test evaluation of set operations in dags.
1 // RUN: tblgen -print-sets %s | FileCheck %s
2 // XFAIL: vg_leak
3 //
4 // The -print-sets driver configures a primitive SetTheory instance that
5 // understands these sets:
6
7 class Set {
8 dag Elements = d;
9 }
10
11 // It prints all Set instances and their ordered set interpretation.
12
13 // Define some elements.
14 def a;
15 def b;
16 def c;
17 def d;
18
19 // The 'add' operator evaluates and concatenates its arguments.
20 def add;
21 def S0a : Set<(add)>;
22 def S0b : Set<(add a)>;
23 def S0c : Set<(add a, b)>;
24 def S0d : Set<(add b, a)>;
25 def S0e : Set<(add a, a)>;
26 def S0f : Set<(add a, a, b, a, c, b, d, a)>;
27 def S0g : Set<(add b, a, b)>;
28 // CHECK: S0a = [ ]
29 // CHECK: S0b = [ a ]
30 // CHECK: S0c = [ a b ]
31 // CHECK: S0d = [ b a ]
32 // CHECK: S0e = [ a ]
33 // CHECK: S0f = [ a b c d ]
34 // CHECK: S0g = [ b a ]
35
36 // Defs of Set class expand into their elements.
37 // Mixed sets and elements are flattened.
38 def S1a : Set<(add S0a)>;
39 def S1b : Set<(add S0a, S0a)>;
40 def S1c : Set<(add S0d, S0f)>;
41 def S1d : Set<(add d, S0d, S0f)>;
42 // CHECK: S1a = [ ]
43 // CHECK: S1b = [ ]
44 // CHECK: S1c = [ b a c d ]
45 // CHECK: S1d = [ d b a c ]
46
47 // The 'sub' operator returns the first argument with the following arguments
48 // removed.
49 def sub;
50 def S2a : Set<(sub S1a, S1c)>;
51 def S2b : Set<(sub S1c, S1d)>;
52 def S2c : Set<(sub S1c, b)>;
53 def S2d : Set<(sub S1c, S0c)>;
54 def S2e : Set<(sub S1c, S2d)>;
55 // CHECK: S2a = [ ]
56 // CHECK: S2b = [ ]
57 // CHECK: S2c = [ a c d ]
58 // CHECK: S2d = [ c d ]
59 // CHECK: S2e = [ b a ]
60
61 // The 'and' operator intersects two sets. The result has the same order as the
62 // first argument.
63 def and;
64 def S3a : Set<(and S2d, S2e)>;
65 def S3b : Set<(and S2d, S1d)>;
66 // CHECK: S3a = [ ]
67 // CHECK: S3b = [ c d ]
68
69 // The 'shl' operator removes the first N elements.
70 def shl;
71 def S4a : Set<(shl S0f, 0)>;
72 def S4b : Set<(shl S0f, 1)>;
73 def S4c : Set<(shl S0f, 3)>;
74 def S4d : Set<(shl S0f, 4)>;
75 def S4e : Set<(shl S0f, 5)>;
76 // CHECK: S4a = [ a b c d ]
77 // CHECK: S4b = [ b c d ]
78 // CHECK: S4c = [ d ]
79 // CHECK: S4d = [ ]
80 // CHECK: S4e = [ ]
81
82 // The 'trunc' operator truncates after the first N elements.
83 def trunc;
84 def S5a : Set<(trunc S0f, 0)>;
85 def S5b : Set<(trunc S0f, 1)>;
86 def S5c : Set<(trunc S0f, 3)>;
87 def S5d : Set<(trunc S0f, 4)>;
88 def S5e : Set<(trunc S0f, 5)>;
89 // CHECK: S5a = [ ]
90 // CHECK: S5b = [ a ]
91 // CHECK: S5c = [ a b c ]
92 // CHECK: S5d = [ a b c d ]
93 // CHECK: S5e = [ a b c d ]
94
95 // The 'rotl' operator rotates left, but also accepts a negative shift.
96 def rotl;
97 def S6a : Set<(rotl S0f, 0)>;
98 def S6b : Set<(rotl S0f, 1)>;
99 def S6c : Set<(rotl S0f, 3)>;
100 def S6d : Set<(rotl S0f, 4)>;
101 def S6e : Set<(rotl S0f, 5)>;
102 def S6f : Set<(rotl S0f, -1)>;
103 def S6g : Set<(rotl S0f, -4)>;
104 def S6h : Set<(rotl S0f, -5)>;
105 // CHECK: S6a = [ a b c d ]
106 // CHECK: S6b = [ b c d a ]
107 // CHECK: S6c = [ d a b c ]
108 // CHECK: S6d = [ a b c d ]
109 // CHECK: S6e = [ b c d a ]
110 // CHECK: S6f = [ d a b c ]
111 // CHECK: S6g = [ a b c d ]
112 // CHECK: S6h = [ d a b c ]
113
114 // The 'rotr' operator rotates right, but also accepts a negative shift.
115 def rotr;
116 def S7a : Set<(rotr S0f, 0)>;
117 def S7b : Set<(rotr S0f, 1)>;
118 def S7c : Set<(rotr S0f, 3)>;
119 def S7d : Set<(rotr S0f, 4)>;
120 def S7e : Set<(rotr S0f, 5)>;
121 def S7f : Set<(rotr S0f, -1)>;
122 def S7g : Set<(rotr S0f, -4)>;
123 def S7h : Set<(rotr S0f, -5)>;
124 // CHECK: S7a = [ a b c d ]
125 // CHECK: S7b = [ d a b c ]
126 // CHECK: S7c = [ b c d a ]
127 // CHECK: S7d = [ a b c d ]
128 // CHECK: S7e = [ d a b c ]
129 // CHECK: S7f = [ b c d a ]
130 // CHECK: S7g = [ a b c d ]
131 // CHECK: S7h = [ b c d a ]
132
133 // The 'decimate' operator picks every N'th element.
134 def decimate;
135 def e0;
136 def e1;
137 def e2;
138 def e3;
139 def e4;
140 def e5;
141 def e6;
142 def e7;
143 def e8;
144 def e9;
145 def E : Set<(add e0, e1, e2, e3, e4, e5, e6, e7, e8, e9)>;
146 def S8a : Set<(decimate E, 3)>;
147 def S8b : Set<(decimate E, 9)>;
148 def S8c : Set<(decimate E, 10)>;
149 def S8d : Set<(decimate (rotl E, 1), 2)>;
150 def S8e : Set<(add (decimate E, 2), (decimate (rotl E, 1), 2))>;
151 // CHECK: S8a = [ e0 e3 e6 e9 ]
152 // CHECK: S8b = [ e0 e9 ]
153 // CHECK: S8c = [ e0 ]
154 // CHECK: S8d = [ e1 e3 e5 e7 e9 ]
155 // CHECK: S8e = [ e0 e2 e4 e6 e8 e1 e3 e5 e7 e9 ]
156
157 // The 'sequence' operator finds a sequence of records from their name.
158 def sequence;
159 def S9a : Set<(sequence "e%u", 3, 7)>;
160 def S9b : Set<(sequence "e%u", 7, 3)>;
161 def S9c : Set<(sequence "e%u", 0, 0)>;
162 def S9d : Set<(sequence "S%ua", 7, 9)>;
163 // CHECK: S9a = [ e3 e4 e5 e6 e7 ]
164 // CHECK: S9b = [ e7 e6 e5 e4 e3 ]
165 // CHECK: S9c = [ e0 ]
166 // CHECK: S9d = [ a b c d e0 e3 e6 e9 e4 e5 e7 ]
3333 OptParserEmitter.cpp
3434 Record.cpp
3535 RegisterInfoEmitter.cpp
36 SetTheory.cpp
3637 StringMatcher.cpp
3738 SubtargetEmitter.cpp
3839 TGLexer.cpp
0 //===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the SetTheory class that computes ordered sets of
10 // Records from DAG expressions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SetTheory.h"
15 #include "Record.h"
16 #include "llvm/Support/Format.h"
17
18 using namespace llvm;
19
20 // Define the standard operators.
21 namespace {
22
23 typedef SetTheory::RecSet RecSet;
24 typedef SetTheory::RecVec RecVec;
25
26 // (add a, b, ...) Evaluate and union all arguments.
27 struct AddOp : public SetTheory::Operator {
28 void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
29 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts);
30 }
31 };
32
33 // (sub Add, Sub, ...) Set difference.
34 struct SubOp : public SetTheory::Operator {
35 void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
36 if (Expr->arg_size() < 2)
37 throw "Set difference needs at least two arguments: " +
38 Expr->getAsString();
39 RecSet Add, Sub;
40 ST.evaluate(*Expr->arg_begin(), Add);
41 ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub);
42 for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I)
43 if (!Sub.count(*I))
44 Elts.insert(*I);
45 }
46 };
47
48 // (and S1, S2) Set intersection.
49 struct AndOp : public SetTheory::Operator {
50 void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
51 if (Expr->arg_size() != 2)
52 throw "Set intersection requires two arguments: " + Expr->getAsString();
53 RecSet S1, S2;
54 ST.evaluate(Expr->arg_begin()[0], S1);
55 ST.evaluate(Expr->arg_begin()[1], S2);
56 for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I)
57 if (S2.count(*I))
58 Elts.insert(*I);
59 }
60 };
61
62 // SetIntBinOp - Abstract base class for (Op S, N) operators.
63 struct SetIntBinOp : public SetTheory::Operator {
64 virtual void apply(SetTheory &ST, DagInit *Expr,
65 RecSet &Set, int64_t N,
66 RecSet &Elts) =0;
67
68 void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
69 if (Expr->arg_size() != 2)
70 throw "Operator requires (Op Set, Int) arguments: " + Expr->getAsString();
71 RecSet Set;
72 ST.evaluate(Expr->arg_begin()[0], Set);
73 IntInit *II = dynamic_cast(Expr->arg_begin()[1]);
74 if (!II)
75 throw "Second argument must be an integer: " + Expr->getAsString();
76 apply(ST, Expr, Set, II->getValue(), Elts);
77 }
78 };
79
80 // (shl S, N) Shift left, remove the first N elements.
81 struct ShlOp : public SetIntBinOp {
82 void apply(SetTheory &ST, DagInit *Expr,
83 RecSet &Set, int64_t N,
84 RecSet &Elts) {
85 if (N < 0)
86 throw "Positive shift required: " + Expr->getAsString();
87 if (unsigned(N) < Set.size())
88 Elts.insert(Set.begin() + N, Set.end());
89 }
90 };
91
92 // (trunc S, N) Truncate after the first N elements.
93 struct TruncOp : public SetIntBinOp {
94 void apply(SetTheory &ST, DagInit *Expr,
95 RecSet &Set, int64_t N,
96 RecSet &Elts) {
97 if (N < 0)
98 throw "Positive length required: " + Expr->getAsString();
99 if (unsigned(N) > Set.size())
100 N = Set.size();
101 Elts.insert(Set.begin(), Set.begin() + N);
102 }
103 };
104
105 // Left/right rotation.
106 struct RotOp : public SetIntBinOp {
107 const bool Reverse;
108
109 RotOp(bool Rev) : Reverse(Rev) {}
110
111 void apply(SetTheory &ST, DagInit *Expr,
112 RecSet &Set, int64_t N,
113 RecSet &Elts) {
114 if (Reverse)
115 N = -N;
116 // N > 0 -> rotate left, N < 0 -> rotate right.
117 if (Set.empty())
118 return;
119 if (N < 0)
120 N = Set.size() - (-N % Set.size());
121 else
122 N %= Set.size();
123 Elts.insert(Set.begin() + N, Set.end());
124 Elts.insert(Set.begin(), Set.begin() + N);
125 }
126 };
127
128 // (decimate S, N) Pick every N'th element of S.
129 struct DecimateOp : public SetIntBinOp {
130 void apply(SetTheory &ST, DagInit *Expr,
131 RecSet &Set, int64_t N,
132 RecSet &Elts) {
133 if (N <= 0)
134 throw "Positive stride required: " + Expr->getAsString();
135 for (unsigned I = 0; I < Set.size(); I += N)
136 Elts.insert(Set[I]);
137 }
138 };
139
140 // (sequence "Format", From, To) Generate a sequence of records by name.
141 struct SequenceOp : public SetTheory::Operator {
142 RecordKeeper &Records;
143
144 SequenceOp(RecordKeeper&R) : Records(R) {}
145
146 void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
147 if (Expr->arg_size() != 3)
148 throw "Bad args to (sequence \"Format\", From, To): " +
149 Expr->getAsString();
150 std::string Format;
151 if (StringInit *SI = dynamic_cast(Expr->arg_begin()[0]))
152 Format = SI->getValue();
153 else
154 throw "Format must be a string: " + Expr->getAsString();
155
156 int64_t From, To;
157 if (IntInit *II = dynamic_cast(Expr->arg_begin()[1]))
158 From = II->getValue();
159 else
160 throw "From must be an integer: " + Expr->getAsString();
161 if (IntInit *II = dynamic_cast(Expr->arg_begin()[2]))
162 To = II->getValue();
163 else
164 throw "From must be an integer: " + Expr->getAsString();
165
166 int Step = From <= To ? 1 : -1;
167 for (To += Step; From != To; From += Step) {
168 std::string Name;
169 raw_string_ostream OS(Name);
170 OS << format(Format.c_str(), From);
171 Record *Rec = Records.getDef(OS.str());
172 if (!Rec)
173 throw "No def named '" + Name + "': " + Expr->getAsString();
174 // Try to reevaluate Rec in case it is a set.
175 if (const RecVec *Result = ST.expand(Rec))
176 Elts.insert(Result->begin(), Result->end());
177 else
178 Elts.insert(Rec);
179 }
180 }
181 };
182
183 // Expand a Def into a set by evaluating one of its fields.
184 struct FieldExpander : public SetTheory::Expander {
185 StringRef FieldName;
186
187 FieldExpander(StringRef fn) : FieldName(fn) {}
188
189 void expand(SetTheory &ST, Record *Def, RecSet &Elts) {
190 ST.evaluate(Def->getValueInit(FieldName), Elts);
191 }
192 };
193 } // end anonymous namespace
194
195 SetTheory::SetTheory(RecordKeeper *Records) {
196 addOperator("add", new AddOp);
197 addOperator("sub", new SubOp);
198 addOperator("and", new AndOp);
199 addOperator("shl", new ShlOp);
200 addOperator("trunc", new TruncOp);
201 addOperator("rotl", new RotOp(false));
202 addOperator("rotr", new RotOp(true));
203 addOperator("decimate", new DecimateOp);
204 if (Records)
205 addOperator("sequence", new SequenceOp(*Records));
206 }
207
208 void SetTheory::addOperator(StringRef Name, Operator *Op) {
209 Operators[Name] = Op;
210 }
211
212 void SetTheory::addExpander(StringRef ClassName, Expander *E) {
213 Expanders[ClassName] = E;
214 }
215
216 void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) {
217 addExpander(ClassName, new FieldExpander(FieldName));
218 }
219
220 void SetTheory::evaluate(Init *Expr, RecSet &Elts) {
221 // A def in a list can be a just an element, or it may expand.
222 if (DefInit *Def = dynamic_cast(Expr)) {
223 if (const RecVec *Result = expand(Def->getDef()))
224 return Elts.insert(Result->begin(), Result->end());
225 Elts.insert(Def->getDef());
226 return;
227 }
228
229 // Lists simply expand.
230 if (ListInit *LI = dynamic_cast(Expr))
231 return evaluate(LI->begin(), LI->end(), Elts);
232
233 // Anything else must be a DAG.
234 DagInit *DagExpr = dynamic_cast(Expr);
235 if (!DagExpr)
236 throw "Invalid set element: " + Expr->getAsString();
237 DefInit *OpInit = dynamic_cast(DagExpr->getOperator());
238 if (!OpInit)
239 throw "Bad set expression: " + Expr->getAsString();
240 Operator *Op = Operators.lookup(OpInit->getDef()->getName());
241 if (!Op)
242 throw "Unknown set operator: " + Expr->getAsString();
243 Op->apply(*this, DagExpr, Elts);
244 }
245
246 const RecVec *SetTheory::expand(Record *Set) {
247 // Check existing entries for Set and return early.
248 ExpandMap::iterator I = Expansions.find(Set);
249 if (I != Expansions.end())
250 return &I->second;
251
252 // This is the first time we see Set. Find a suitable expander.
253 try {
254 const std::vector &SC = Set->getSuperClasses();
255 for (unsigned i = 0, e = SC.size(); i != e; ++i)
256 if (Expander *Exp = Expanders.lookup(SC[i]->getName())) {
257 // This breaks recursive definitions.
258 RecVec &EltVec = Expansions[Set];
259 RecSet Elts;
260 Exp->expand(*this, Set, Elts);
261 EltVec.assign(Elts.begin(), Elts.end());
262 return &EltVec;
263 }
264 } catch (const std::string &Error) {
265 throw TGError(Set->getLoc(), Error);
266 }
267
268 // Set is not expandable.
269 return 0;
270 }
271
0 //===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the SetTheory class that computes ordered sets of
10 // Records from DAG expressions. Operators for standard set operations are
11 // predefined, and it is possible to add special purpose set operators as well.
12 //
13 // The user may define named sets as Records of predefined classes. Set
14 // expanders can be added to a SetTheory instance to teach it how to find the
15 // elements of such a named set.
16 //
17 // These are the predefined operators. The argument lists can be individual
18 // elements (defs), other sets (defs of expandable classes), lists, or DAG
19 // expressions that are evaluated recursively.
20 //
21 // - (add S1, S2 ...) Union sets. This is also how sets are created from element
22 // lists.
23 //
24 // - (sub S1, S2, ...) Set difference. Every element in S1 except for the
25 // elements in S2, ...
26 //
27 // - (and S1, S2) Set intersection. Every element in S1 that is also in S2.
28 //
29 // - (shl S, N) Shift left. Remove the first N elements from S.
30 //
31 // - (trunc S, N) Truncate. The first N elements of S.
32 //
33 // - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)).
34 //
35 // - (rotr S, N) Rotate right.
36 //
37 // - (decimate S, N) Decimate S by picking every N'th element, starting with
38 // the first one. For instance, (decimate S, 2) returns the even elements of
39 // S.
40 //
41 // - (sequence "Format", From, To) Generate a sequence of defs with printf.
42 // For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ]
43 //
44 //===----------------------------------------------------------------------===//
45
46 #ifndef SETTHEORY_H
47 #define SETTHEORY_H
48
49 #include "llvm/ADT/StringMap.h"
50 #include "llvm/ADT/SetVector.h"
51 #include
52 #include
53
54 namespace llvm {
55
56 class DagInit;
57 struct Init;
58 class Record;
59 class RecordKeeper;
60
61 class SetTheory {
62 public:
63 typedef std::vector RecVec;
64 typedef SmallSetVector RecSet;
65
66 /// Operator - A callback representing a DAG operator.
67 struct Operator {
68 /// apply - Apply this operator to Expr's arguments and insert the result
69 /// in Elts.
70 virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts) =0;
71 };
72
73 /// Expander - A callback function that can transform a Record representing a
74 /// set into a fully expanded list of elements. Expanders provide a way for
75 /// users to define named sets that can be used in DAG expressions.
76 struct Expander {
77 virtual void expand(SetTheory&, Record*, RecSet &Elts) =0;
78 };
79
80 private:
81 // Map set defs to their fully expanded contents. This serves as a memoization
82 // cache and it makes it possible to return const references on queries.
83 typedef std::map ExpandMap;
84 ExpandMap Expansions;
85
86 // Known DAG operators by name.
87 StringMap Operators;
88
89 // Typed expanders by class name.
90 StringMap Expanders;
91
92 public:
93 /// Create a SetTheory instance with only the standard operators.
94 /// A 'sequence' operator will only be added if a RecordKeeper is given.
95 SetTheory(RecordKeeper *Records = 0);
96
97 /// addExpander - Add an expander for Records with the named super class.
98 void addExpander(StringRef ClassName, Expander*);
99
100 /// addFieldExpander - Add an expander for ClassName that simply evaluates
101 /// FieldName in the Record to get the set elements. That is all that is
102 /// needed for a class like:
103 ///
104 /// class Set {
105 /// dag Elts = d;
106 /// }
107 ///
108 void addFieldExpander(StringRef ClassName, StringRef FieldName);
109
110 /// addOperator - Add a DAG operator.
111 void addOperator(StringRef Name, Operator*);
112
113 /// evaluate - Evaluate Expr and append the resulting set to Elts.
114 void evaluate(Init *Expr, RecSet &Elts);
115
116 /// evaluate - Evaluate a sequence of Inits and append to Elts.
117 template
118 void evaluate(Iter begin, Iter end, RecSet &Elts) {
119 while (begin != end)
120 evaluate(*begin++, Elts);
121 }
122
123 /// expand - Expand a record into a set of elements if possible. Return a
124 /// pointer to the expanded elements, or NULL if Set cannot be expanded
125 /// further.
126 const RecVec *expand(Record *Set);
127 };
128
129 } // end namespace llvm
130
131 #endif
132
3636 #include "RegisterInfoEmitter.h"
3737 #include "ARMDecoderEmitter.h"
3838 #include "SubtargetEmitter.h"
39 #include "SetTheory.h"
3940 #include "TGParser.h"
4041 #include "llvm/ADT/OwningPtr.h"
4142 #include "llvm/Support/CommandLine.h"
7980 GenArmNeon,
8081 GenArmNeonSema,
8182 GenArmNeonTest,
82 PrintEnums
83 PrintEnums,
84 PrintSets
8385 };
8486
8587 namespace {
161163 "Generate ARM NEON tests for clang"),
162164 clEnumValN(PrintEnums, "print-enums",
163165 "Print enum values for a class"),
166 clEnumValN(PrintSets, "print-sets",
167 "Print expanded sets for testing DAG exprs"),
164168 clEnumValEnd));
165169
166170 cl::opt
373377 Out.os() << "\n";
374378 break;
375379 }
380 case PrintSets:
381 {
382 SetTheory Sets(&Records);
383 Sets.addFieldExpander("Set", "Elements");
384 std::vector Recs = Records.getAllDerivedDefinitions("Set");
385 for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
386 Out.os() << Recs[i]->getName() << " = [";
387 const std::vector *Elts = Sets.expand(Recs[i]);
388 assert(Elts && "Couldn't expand Set instance");
389 for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei)
390 Out.os() << ' ' << (*Elts)[ei]->getName();
391 Out.os() << " ]\n";
392 }
393 break;
394 }
376395 default:
377396 assert(1 && "Invalid Action");
378397 return 1;