Record.h revision 239462
1226584Sdim//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim//
10226584Sdim// This file defines the main TableGen data structures, including the TableGen
11226584Sdim// types, values, and high-level data structures.
12226584Sdim//
13226584Sdim//===----------------------------------------------------------------------===//
14226584Sdim
15226584Sdim#ifndef LLVM_TABLEGEN_RECORD_H
16226584Sdim#define LLVM_TABLEGEN_RECORD_H
17226584Sdim
18226584Sdim#include "llvm/ADT/ArrayRef.h"
19226584Sdim#include "llvm/ADT/FoldingSet.h"
20226584Sdim#include "llvm/Support/Allocator.h"
21226584Sdim#include "llvm/Support/SourceMgr.h"
22226584Sdim#include "llvm/Support/DataTypes.h"
23234353Sdim#include "llvm/Support/ErrorHandling.h"
24226584Sdim#include "llvm/Support/raw_ostream.h"
25226584Sdim#include <map>
26226584Sdim
27226584Sdimnamespace llvm {
28226584Sdimclass raw_ostream;
29226584Sdim
30226584Sdim// RecTy subclasses.
31226584Sdimclass BitRecTy;
32226584Sdimclass BitsRecTy;
33226584Sdimclass IntRecTy;
34226584Sdimclass StringRecTy;
35226584Sdimclass ListRecTy;
36226584Sdimclass DagRecTy;
37226584Sdimclass RecordRecTy;
38226584Sdim
39226584Sdim// Init subclasses.
40226584Sdimclass Init;
41226584Sdimclass UnsetInit;
42226584Sdimclass BitInit;
43226584Sdimclass BitsInit;
44226584Sdimclass IntInit;
45226584Sdimclass StringInit;
46226584Sdimclass ListInit;
47226584Sdimclass UnOpInit;
48226584Sdimclass BinOpInit;
49226584Sdimclass TernOpInit;
50226584Sdimclass DefInit;
51226584Sdimclass DagInit;
52226584Sdimclass TypedInit;
53226584Sdimclass VarInit;
54226584Sdimclass FieldInit;
55226584Sdimclass VarBitInit;
56226584Sdimclass VarListElementInit;
57226584Sdim
58226584Sdim// Other classes.
59226584Sdimclass Record;
60226584Sdimclass RecordVal;
61226584Sdimstruct MultiClass;
62226584Sdimclass RecordKeeper;
63226584Sdim
64226584Sdim//===----------------------------------------------------------------------===//
65226584Sdim//  Type Classes
66226584Sdim//===----------------------------------------------------------------------===//
67226584Sdim
68226584Sdimclass RecTy {
69226584Sdim  ListRecTy *ListTy;
70234353Sdim  virtual void anchor();
71226584Sdimpublic:
72226584Sdim  RecTy() : ListTy(0) {}
73226584Sdim  virtual ~RecTy() {}
74226584Sdim
75226584Sdim  virtual std::string getAsString() const = 0;
76226584Sdim  void print(raw_ostream &OS) const { OS << getAsString(); }
77226584Sdim  void dump() const;
78226584Sdim
79226584Sdim  /// typeIsConvertibleTo - Return true if all values of 'this' type can be
80226584Sdim  /// converted to the specified type.
81226584Sdim  virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0;
82226584Sdim
83226584Sdim  /// getListTy - Returns the type representing list<this>.
84226584Sdim  ListRecTy *getListTy();
85226584Sdim
86226584Sdimpublic:   // These methods should only be called from subclasses of Init
87226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return 0; }
88226584Sdim  virtual Init *convertValue(   BitInit *BI) { return 0; }
89226584Sdim  virtual Init *convertValue(  BitsInit *BI) { return 0; }
90226584Sdim  virtual Init *convertValue(   IntInit *II) { return 0; }
91226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
92226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
93226584Sdim  virtual Init *convertValue( UnOpInit *UI) {
94226584Sdim    return convertValue((TypedInit*)UI);
95226584Sdim  }
96226584Sdim  virtual Init *convertValue( BinOpInit *UI) {
97226584Sdim    return convertValue((TypedInit*)UI);
98226584Sdim  }
99226584Sdim  virtual Init *convertValue( TernOpInit *UI) {
100226584Sdim    return convertValue((TypedInit*)UI);
101226584Sdim  }
102226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
103226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
104226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
105226584Sdim  virtual Init *convertValue( TypedInit *TI) { return 0; }
106226584Sdim  virtual Init *convertValue(   VarInit *VI) {
107226584Sdim    return convertValue((TypedInit*)VI);
108226584Sdim  }
109226584Sdim  virtual Init *convertValue( FieldInit *FI) {
110226584Sdim    return convertValue((TypedInit*)FI);
111226584Sdim  }
112226584Sdim
113226584Sdimpublic:   // These methods should only be called by subclasses of RecTy.
114226584Sdim  // baseClassOf - These virtual methods should be overloaded to return true iff
115226584Sdim  // all values of type 'RHS' can be converted to the 'this' type.
116226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return false; }
117226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const { return false; }
118226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return false; }
119226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
120226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
121226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
122226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
123226584Sdim};
124226584Sdim
125226584Sdiminline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
126226584Sdim  Ty.print(OS);
127226584Sdim  return OS;
128226584Sdim}
129226584Sdim
130226584Sdim
131226584Sdim/// BitRecTy - 'bit' - Represent a single bit
132226584Sdim///
133226584Sdimclass BitRecTy : public RecTy {
134226584Sdim  static BitRecTy Shared;
135226584Sdim  BitRecTy() {}
136226584Sdimpublic:
137226584Sdim  static BitRecTy *get() { return &Shared; }
138226584Sdim
139226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
140226584Sdim  virtual Init *convertValue(   BitInit *BI) { return (Init*)BI; }
141226584Sdim  virtual Init *convertValue(  BitsInit *BI);
142226584Sdim  virtual Init *convertValue(   IntInit *II);
143226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
144226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
145226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
146226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
147226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
148226584Sdim  virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
149226584Sdim  virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
150226584Sdim  virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
151226584Sdim  virtual Init *convertValue( TypedInit *TI);
152226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
153226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
154226584Sdim
155226584Sdim  std::string getAsString() const { return "bit"; }
156226584Sdim
157226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
158226584Sdim    return RHS->baseClassOf(this);
159226584Sdim  }
160226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return true; }
161226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const;
162226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return true; }
163226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
164226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
165226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
166226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
167226584Sdim
168226584Sdim};
169226584Sdim
170226584Sdim
171226584Sdim// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
172226584Sdim/// BitsRecTy - 'bits&lt;n&gt;' - Represent a fixed number of bits
173226584Sdim///
174226584Sdimclass BitsRecTy : public RecTy {
175226584Sdim  unsigned Size;
176226584Sdim  explicit BitsRecTy(unsigned Sz) : Size(Sz) {}
177226584Sdimpublic:
178226584Sdim  static BitsRecTy *get(unsigned Sz);
179226584Sdim
180226584Sdim  unsigned getNumBits() const { return Size; }
181226584Sdim
182226584Sdim  virtual Init *convertValue( UnsetInit *UI);
183226584Sdim  virtual Init *convertValue(   BitInit *UI);
184226584Sdim  virtual Init *convertValue(  BitsInit *BI);
185226584Sdim  virtual Init *convertValue(   IntInit *II);
186226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
187226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
188226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
189226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
190226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
191226584Sdim  virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
192226584Sdim  virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
193226584Sdim  virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
194226584Sdim  virtual Init *convertValue( TypedInit *TI);
195226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
196226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
197226584Sdim
198226584Sdim  std::string getAsString() const;
199226584Sdim
200226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
201226584Sdim    return RHS->baseClassOf(this);
202226584Sdim  }
203226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return Size == 1; }
204226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const {
205226584Sdim    return RHS->Size == Size;
206226584Sdim  }
207226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return true; }
208226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
209226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
210226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
211226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
212226584Sdim
213226584Sdim};
214226584Sdim
215226584Sdim
216226584Sdim/// IntRecTy - 'int' - Represent an integer value of no particular size
217226584Sdim///
218226584Sdimclass IntRecTy : public RecTy {
219226584Sdim  static IntRecTy Shared;
220226584Sdim  IntRecTy() {}
221226584Sdimpublic:
222226584Sdim  static IntRecTy *get() { return &Shared; }
223226584Sdim
224226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
225226584Sdim  virtual Init *convertValue(   BitInit *BI);
226226584Sdim  virtual Init *convertValue(  BitsInit *BI);
227226584Sdim  virtual Init *convertValue(   IntInit *II) { return (Init*)II; }
228226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
229226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
230226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
231226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
232226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
233226584Sdim  virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
234226584Sdim  virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
235226584Sdim  virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
236226584Sdim  virtual Init *convertValue( TypedInit *TI);
237226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
238226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
239226584Sdim
240226584Sdim  std::string getAsString() const { return "int"; }
241226584Sdim
242226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
243226584Sdim    return RHS->baseClassOf(this);
244226584Sdim  }
245226584Sdim
246226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return true; }
247226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const { return true; }
248226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return true; }
249226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
250226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
251226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
252226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
253226584Sdim
254226584Sdim};
255226584Sdim
256226584Sdim/// StringRecTy - 'string' - Represent an string value
257226584Sdim///
258226584Sdimclass StringRecTy : public RecTy {
259226584Sdim  static StringRecTy Shared;
260226584Sdim  StringRecTy() {}
261226584Sdimpublic:
262226584Sdim  static StringRecTy *get() { return &Shared; }
263226584Sdim
264226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
265226584Sdim  virtual Init *convertValue(   BitInit *BI) { return 0; }
266226584Sdim  virtual Init *convertValue(  BitsInit *BI) { return 0; }
267226584Sdim  virtual Init *convertValue(   IntInit *II) { return 0; }
268226584Sdim  virtual Init *convertValue(StringInit *SI) { return (Init*)SI; }
269226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
270226584Sdim  virtual Init *convertValue( UnOpInit *BO);
271226584Sdim  virtual Init *convertValue( BinOpInit *BO);
272226584Sdim  virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
273226584Sdim
274226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
275226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
276226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
277226584Sdim  virtual Init *convertValue( TypedInit *TI);
278226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
279226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
280226584Sdim
281226584Sdim  std::string getAsString() const { return "string"; }
282226584Sdim
283226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
284226584Sdim    return RHS->baseClassOf(this);
285226584Sdim  }
286226584Sdim
287226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return false; }
288226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const { return false; }
289226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return false; }
290226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return true; }
291226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
292226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
293226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
294226584Sdim};
295226584Sdim
296226584Sdim// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
297226584Sdim// the specified type.
298226584Sdim/// ListRecTy - 'list&lt;Ty&gt;' - Represent a list of values, all of which must
299226584Sdim/// be of the specified type.
300226584Sdim///
301226584Sdimclass ListRecTy : public RecTy {
302226584Sdim  RecTy *Ty;
303226584Sdim  explicit ListRecTy(RecTy *T) : Ty(T) {}
304226584Sdim  friend ListRecTy *RecTy::getListTy();
305226584Sdimpublic:
306226584Sdim  static ListRecTy *get(RecTy *T) { return T->getListTy(); }
307226584Sdim  RecTy *getElementType() const { return Ty; }
308226584Sdim
309226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
310226584Sdim  virtual Init *convertValue(   BitInit *BI) { return 0; }
311226584Sdim  virtual Init *convertValue(  BitsInit *BI) { return 0; }
312226584Sdim  virtual Init *convertValue(   IntInit *II) { return 0; }
313226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
314226584Sdim  virtual Init *convertValue(  ListInit *LI);
315226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
316226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
317226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
318226584Sdim  virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
319226584Sdim  virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
320226584Sdim  virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
321226584Sdim  virtual Init *convertValue( TypedInit *TI);
322226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
323226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
324226584Sdim
325226584Sdim  std::string getAsString() const;
326226584Sdim
327226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
328226584Sdim    return RHS->baseClassOf(this);
329226584Sdim  }
330226584Sdim
331226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return false; }
332226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const { return false; }
333226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return false; }
334226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
335226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const {
336226584Sdim    return RHS->getElementType()->typeIsConvertibleTo(Ty);
337226584Sdim  }
338226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
339226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
340226584Sdim};
341226584Sdim
342226584Sdim/// DagRecTy - 'dag' - Represent a dag fragment
343226584Sdim///
344226584Sdimclass DagRecTy : public RecTy {
345226584Sdim  static DagRecTy Shared;
346226584Sdim  DagRecTy() {}
347226584Sdimpublic:
348226584Sdim  static DagRecTy *get() { return &Shared; }
349226584Sdim
350226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
351226584Sdim  virtual Init *convertValue(   BitInit *BI) { return 0; }
352226584Sdim  virtual Init *convertValue(  BitsInit *BI) { return 0; }
353226584Sdim  virtual Init *convertValue(   IntInit *II) { return 0; }
354226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
355226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
356226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
357226584Sdim  virtual Init *convertValue(   DefInit *DI) { return 0; }
358226584Sdim  virtual Init *convertValue( UnOpInit *BO);
359226584Sdim  virtual Init *convertValue( BinOpInit *BO);
360226584Sdim  virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
361226584Sdim  virtual Init *convertValue(   DagInit *CI) { return (Init*)CI; }
362226584Sdim  virtual Init *convertValue( TypedInit *TI);
363226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
364226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
365226584Sdim
366226584Sdim  std::string getAsString() const { return "dag"; }
367226584Sdim
368226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
369226584Sdim    return RHS->baseClassOf(this);
370226584Sdim  }
371226584Sdim
372226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return false; }
373226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const { return false; }
374226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return false; }
375226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
376226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
377226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return true; }
378226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
379226584Sdim};
380226584Sdim
381226584Sdim
382226584Sdim/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
383226584Sdim/// (R32 X = EAX).
384226584Sdim///
385226584Sdimclass RecordRecTy : public RecTy {
386226584Sdim  Record *Rec;
387226584Sdim  explicit RecordRecTy(Record *R) : Rec(R) {}
388226584Sdim  friend class Record;
389226584Sdimpublic:
390226584Sdim  static RecordRecTy *get(Record *R);
391226584Sdim
392226584Sdim  Record *getRecord() const { return Rec; }
393226584Sdim
394226584Sdim  virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
395226584Sdim  virtual Init *convertValue(   BitInit *BI) { return 0; }
396226584Sdim  virtual Init *convertValue(  BitsInit *BI) { return 0; }
397226584Sdim  virtual Init *convertValue(   IntInit *II) { return 0; }
398226584Sdim  virtual Init *convertValue(StringInit *SI) { return 0; }
399226584Sdim  virtual Init *convertValue(  ListInit *LI) { return 0; }
400226584Sdim  virtual Init *convertValue(VarBitInit *VB) { return 0; }
401226584Sdim  virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
402226584Sdim  virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
403226584Sdim  virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
404226584Sdim  virtual Init *convertValue(   DefInit *DI);
405226584Sdim  virtual Init *convertValue(   DagInit *DI) { return 0; }
406226584Sdim  virtual Init *convertValue( TypedInit *VI);
407226584Sdim  virtual Init *convertValue(   VarInit *VI) { return RecTy::convertValue(VI);}
408226584Sdim  virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
409226584Sdim
410226584Sdim  std::string getAsString() const;
411226584Sdim
412226584Sdim  bool typeIsConvertibleTo(const RecTy *RHS) const {
413226584Sdim    return RHS->baseClassOf(this);
414226584Sdim  }
415226584Sdim  virtual bool baseClassOf(const BitRecTy    *RHS) const { return false; }
416226584Sdim  virtual bool baseClassOf(const BitsRecTy   *RHS) const { return false; }
417226584Sdim  virtual bool baseClassOf(const IntRecTy    *RHS) const { return false; }
418226584Sdim  virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
419226584Sdim  virtual bool baseClassOf(const ListRecTy   *RHS) const { return false; }
420226584Sdim  virtual bool baseClassOf(const DagRecTy    *RHS) const { return false; }
421226584Sdim  virtual bool baseClassOf(const RecordRecTy *RHS) const;
422226584Sdim};
423226584Sdim
424226584Sdim/// resolveTypes - Find a common type that T1 and T2 convert to.
425226584Sdim/// Return 0 if no such type exists.
426226584Sdim///
427226584SdimRecTy *resolveTypes(RecTy *T1, RecTy *T2);
428226584Sdim
429226584Sdim//===----------------------------------------------------------------------===//
430226584Sdim//  Initializer Classes
431226584Sdim//===----------------------------------------------------------------------===//
432226584Sdim
433226584Sdimclass Init {
434226584Sdim  Init(const Init &);  // Do not define.
435226584Sdim  Init &operator=(const Init &);  // Do not define.
436234353Sdim  virtual void anchor();
437226584Sdim
438226584Sdimprotected:
439226584Sdim  Init(void) {}
440226584Sdim
441226584Sdimpublic:
442226584Sdim  virtual ~Init() {}
443226584Sdim
444226584Sdim  /// isComplete - This virtual method should be overridden by values that may
445226584Sdim  /// not be completely specified yet.
446226584Sdim  virtual bool isComplete() const { return true; }
447226584Sdim
448226584Sdim  /// print - Print out this value.
449226584Sdim  void print(raw_ostream &OS) const { OS << getAsString(); }
450226584Sdim
451226584Sdim  /// getAsString - Convert this value to a string form.
452226584Sdim  virtual std::string getAsString() const = 0;
453226584Sdim  /// getAsUnquotedString - Convert this value to a string form,
454226584Sdim  /// without adding quote markers.  This primaruly affects
455226584Sdim  /// StringInits where we will not surround the string value with
456226584Sdim  /// quotes.
457234982Sdim  virtual std::string getAsUnquotedString() const { return getAsString(); }
458226584Sdim
459226584Sdim  /// dump - Debugging method that may be called through a debugger, just
460226584Sdim  /// invokes print on stderr.
461226584Sdim  void dump() const;
462226584Sdim
463226584Sdim  /// convertInitializerTo - This virtual function is a simple call-back
464226584Sdim  /// function that should be overridden to call the appropriate
465226584Sdim  /// RecTy::convertValue method.
466226584Sdim  ///
467226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const = 0;
468226584Sdim
469226584Sdim  /// convertInitializerBitRange - This method is used to implement the bitrange
470226584Sdim  /// selection operator.  Given an initializer, it selects the specified bits
471226584Sdim  /// out, returning them as a new init of bits type.  If it is not legal to use
472226584Sdim  /// the bit subscript operator on this initializer, return null.
473226584Sdim  ///
474226584Sdim  virtual Init *
475226584Sdim  convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
476226584Sdim    return 0;
477226584Sdim  }
478226584Sdim
479226584Sdim  /// convertInitListSlice - This method is used to implement the list slice
480226584Sdim  /// selection operator.  Given an initializer, it selects the specified list
481226584Sdim  /// elements, returning them as a new init of list type.  If it is not legal
482226584Sdim  /// to take a slice of this, return null.
483226584Sdim  ///
484226584Sdim  virtual Init *
485226584Sdim  convertInitListSlice(const std::vector<unsigned> &Elements) const {
486226584Sdim    return 0;
487226584Sdim  }
488226584Sdim
489226584Sdim  /// getFieldType - This method is used to implement the FieldInit class.
490226584Sdim  /// Implementors of this method should return the type of the named field if
491226584Sdim  /// they are of record type.
492226584Sdim  ///
493226584Sdim  virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; }
494226584Sdim
495226584Sdim  /// getFieldInit - This method complements getFieldType to return the
496226584Sdim  /// initializer for the specified field.  If getFieldType returns non-null
497226584Sdim  /// this method should return non-null, otherwise it returns null.
498226584Sdim  ///
499226584Sdim  virtual Init *getFieldInit(Record &R, const RecordVal *RV,
500226584Sdim                             const std::string &FieldName) const {
501226584Sdim    return 0;
502226584Sdim  }
503226584Sdim
504226584Sdim  /// resolveReferences - This method is used by classes that refer to other
505226584Sdim  /// variables which may not be defined at the time the expression is formed.
506226584Sdim  /// If a value is set for the variable later, this method will be called on
507226584Sdim  /// users of the value to allow the value to propagate out.
508226584Sdim  ///
509226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const {
510226584Sdim    return const_cast<Init *>(this);
511226584Sdim  }
512226584Sdim};
513226584Sdim
514226584Sdiminline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
515226584Sdim  I.print(OS); return OS;
516226584Sdim}
517226584Sdim
518226584Sdim/// TypedInit - This is the common super-class of types that have a specific,
519226584Sdim/// explicit, type.
520226584Sdim///
521226584Sdimclass TypedInit : public Init {
522226584Sdim  RecTy *Ty;
523226584Sdim
524226584Sdim  TypedInit(const TypedInit &Other);  // Do not define.
525226584Sdim  TypedInit &operator=(const TypedInit &Other);  // Do not define.
526226584Sdim
527226584Sdimprotected:
528226584Sdim  explicit TypedInit(RecTy *T) : Ty(T) {}
529226584Sdim
530226584Sdimpublic:
531226584Sdim  RecTy *getType() const { return Ty; }
532226584Sdim
533226584Sdim  virtual Init *
534226584Sdim  convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
535226584Sdim  virtual Init *
536226584Sdim  convertInitListSlice(const std::vector<unsigned> &Elements) const;
537226584Sdim
538226584Sdim  /// getFieldType - This method is used to implement the FieldInit class.
539226584Sdim  /// Implementors of this method should return the type of the named field if
540226584Sdim  /// they are of record type.
541226584Sdim  ///
542226584Sdim  virtual RecTy *getFieldType(const std::string &FieldName) const;
543226584Sdim
544226584Sdim  /// resolveBitReference - This method is used to implement
545226584Sdim  /// VarBitInit::resolveReferences.  If the bit is able to be resolved, we
546226584Sdim  /// simply return the resolved value, otherwise we return null.
547226584Sdim  ///
548226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
549226584Sdim                                    unsigned Bit) const = 0;
550226584Sdim
551226584Sdim  /// resolveListElementReference - This method is used to implement
552226584Sdim  /// VarListElementInit::resolveReferences.  If the list element is resolvable
553226584Sdim  /// now, we return the resolved value, otherwise we return null.
554226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
555226584Sdim                                            unsigned Elt) const = 0;
556226584Sdim};
557226584Sdim
558226584Sdim
559226584Sdim/// UnsetInit - ? - Represents an uninitialized value
560226584Sdim///
561226584Sdimclass UnsetInit : public Init {
562226584Sdim  UnsetInit() : Init() {}
563226584Sdim  UnsetInit(const UnsetInit &);  // Do not define.
564226584Sdim  UnsetInit &operator=(const UnsetInit &Other);  // Do not define.
565234353Sdim  virtual void anchor();
566226584Sdim
567226584Sdimpublic:
568226584Sdim  static UnsetInit *get();
569226584Sdim
570226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
571226584Sdim    return Ty->convertValue(const_cast<UnsetInit *>(this));
572226584Sdim  }
573226584Sdim
574226584Sdim  virtual bool isComplete() const { return false; }
575226584Sdim  virtual std::string getAsString() const { return "?"; }
576226584Sdim};
577226584Sdim
578226584Sdim
579226584Sdim/// BitInit - true/false - Represent a concrete initializer for a bit.
580226584Sdim///
581226584Sdimclass BitInit : public Init {
582226584Sdim  bool Value;
583226584Sdim
584226584Sdim  explicit BitInit(bool V) : Value(V) {}
585226584Sdim  BitInit(const BitInit &Other);  // Do not define.
586226584Sdim  BitInit &operator=(BitInit &Other);  // Do not define.
587234353Sdim  virtual void anchor();
588226584Sdim
589226584Sdimpublic:
590226584Sdim  static BitInit *get(bool V);
591226584Sdim
592226584Sdim  bool getValue() const { return Value; }
593226584Sdim
594226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
595226584Sdim    return Ty->convertValue(const_cast<BitInit *>(this));
596226584Sdim  }
597226584Sdim
598226584Sdim  virtual std::string getAsString() const { return Value ? "1" : "0"; }
599226584Sdim};
600226584Sdim
601226584Sdim/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value.
602226584Sdim/// It contains a vector of bits, whose size is determined by the type.
603226584Sdim///
604226584Sdimclass BitsInit : public Init, public FoldingSetNode {
605226584Sdim  std::vector<Init*> Bits;
606226584Sdim
607226584Sdim  BitsInit(ArrayRef<Init *> Range) : Bits(Range.begin(), Range.end()) {}
608226584Sdim
609226584Sdim  BitsInit(const BitsInit &Other);  // Do not define.
610226584Sdim  BitsInit &operator=(const BitsInit &Other);  // Do not define.
611226584Sdim
612226584Sdimpublic:
613226584Sdim  static BitsInit *get(ArrayRef<Init *> Range);
614226584Sdim
615226584Sdim  void Profile(FoldingSetNodeID &ID) const;
616226584Sdim
617226584Sdim  unsigned getNumBits() const { return Bits.size(); }
618226584Sdim
619226584Sdim  Init *getBit(unsigned Bit) const {
620226584Sdim    assert(Bit < Bits.size() && "Bit index out of range!");
621226584Sdim    return Bits[Bit];
622226584Sdim  }
623226584Sdim
624226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
625226584Sdim    return Ty->convertValue(const_cast<BitsInit *>(this));
626226584Sdim  }
627226584Sdim  virtual Init *
628226584Sdim  convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
629226584Sdim
630226584Sdim  virtual bool isComplete() const {
631226584Sdim    for (unsigned i = 0; i != getNumBits(); ++i)
632226584Sdim      if (!getBit(i)->isComplete()) return false;
633226584Sdim    return true;
634226584Sdim  }
635226584Sdim  bool allInComplete() const {
636226584Sdim    for (unsigned i = 0; i != getNumBits(); ++i)
637226584Sdim      if (getBit(i)->isComplete()) return false;
638226584Sdim    return true;
639226584Sdim  }
640226584Sdim  virtual std::string getAsString() const;
641226584Sdim
642226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
643226584Sdim};
644226584Sdim
645226584Sdim
646226584Sdim/// IntInit - 7 - Represent an initalization by a literal integer value.
647226584Sdim///
648226584Sdimclass IntInit : public TypedInit {
649226584Sdim  int64_t Value;
650226584Sdim
651226584Sdim  explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {}
652226584Sdim
653226584Sdim  IntInit(const IntInit &Other);  // Do not define.
654226584Sdim  IntInit &operator=(const IntInit &Other);  // Do note define.
655226584Sdim
656226584Sdimpublic:
657226584Sdim  static IntInit *get(int64_t V);
658226584Sdim
659226584Sdim  int64_t getValue() const { return Value; }
660226584Sdim
661226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
662226584Sdim    return Ty->convertValue(const_cast<IntInit *>(this));
663226584Sdim  }
664226584Sdim  virtual Init *
665226584Sdim  convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
666226584Sdim
667226584Sdim  virtual std::string getAsString() const;
668226584Sdim
669226584Sdim  /// resolveBitReference - This method is used to implement
670226584Sdim  /// VarBitInit::resolveReferences.  If the bit is able to be resolved, we
671226584Sdim  /// simply return the resolved value, otherwise we return null.
672226584Sdim  ///
673226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
674226584Sdim                                    unsigned Bit) const {
675234353Sdim    llvm_unreachable("Illegal bit reference off int");
676226584Sdim  }
677226584Sdim
678226584Sdim  /// resolveListElementReference - This method is used to implement
679226584Sdim  /// VarListElementInit::resolveReferences.  If the list element is resolvable
680226584Sdim  /// now, we return the resolved value, otherwise we return null.
681226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
682226584Sdim                                            unsigned Elt) const {
683234353Sdim    llvm_unreachable("Illegal element reference off int");
684226584Sdim  }
685226584Sdim};
686226584Sdim
687226584Sdim
688226584Sdim/// StringInit - "foo" - Represent an initialization by a string value.
689226584Sdim///
690226584Sdimclass StringInit : public TypedInit {
691226584Sdim  std::string Value;
692226584Sdim
693226584Sdim  explicit StringInit(const std::string &V)
694226584Sdim    : TypedInit(StringRecTy::get()), Value(V) {}
695226584Sdim
696226584Sdim  StringInit(const StringInit &Other);  // Do not define.
697226584Sdim  StringInit &operator=(const StringInit &Other);  // Do not define.
698234353Sdim  virtual void anchor();
699226584Sdim
700226584Sdimpublic:
701234353Sdim  static StringInit *get(StringRef);
702226584Sdim
703226584Sdim  const std::string &getValue() const { return Value; }
704226584Sdim
705226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
706226584Sdim    return Ty->convertValue(const_cast<StringInit *>(this));
707226584Sdim  }
708226584Sdim
709226584Sdim  virtual std::string getAsString() const { return "\"" + Value + "\""; }
710226584Sdim  virtual std::string getAsUnquotedString() const { return Value; }
711226584Sdim
712226584Sdim  /// resolveBitReference - This method is used to implement
713226584Sdim  /// VarBitInit::resolveReferences.  If the bit is able to be resolved, we
714226584Sdim  /// simply return the resolved value, otherwise we return null.
715226584Sdim  ///
716226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
717226584Sdim                                    unsigned Bit) const {
718234353Sdim    llvm_unreachable("Illegal bit reference off string");
719226584Sdim  }
720226584Sdim
721226584Sdim  /// resolveListElementReference - This method is used to implement
722226584Sdim  /// VarListElementInit::resolveReferences.  If the list element is resolvable
723226584Sdim  /// now, we return the resolved value, otherwise we return null.
724226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
725226584Sdim                                            unsigned Elt) const {
726234353Sdim    llvm_unreachable("Illegal element reference off string");
727226584Sdim  }
728226584Sdim};
729226584Sdim
730226584Sdim/// ListInit - [AL, AH, CL] - Represent a list of defs
731226584Sdim///
732226584Sdimclass ListInit : public TypedInit, public FoldingSetNode {
733226584Sdim  std::vector<Init*> Values;
734226584Sdimpublic:
735226584Sdim  typedef std::vector<Init*>::const_iterator const_iterator;
736226584Sdim
737226584Sdimprivate:
738226584Sdim  explicit ListInit(ArrayRef<Init *> Range, RecTy *EltTy)
739226584Sdim      : TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {}
740226584Sdim
741226584Sdim  ListInit(const ListInit &Other);  // Do not define.
742226584Sdim  ListInit &operator=(const ListInit &Other);  // Do not define.
743226584Sdim
744226584Sdimpublic:
745226584Sdim  static ListInit *get(ArrayRef<Init *> Range, RecTy *EltTy);
746226584Sdim
747226584Sdim  void Profile(FoldingSetNodeID &ID) const;
748226584Sdim
749226584Sdim  unsigned getSize() const { return Values.size(); }
750226584Sdim  Init *getElement(unsigned i) const {
751226584Sdim    assert(i < Values.size() && "List element index out of range!");
752226584Sdim    return Values[i];
753226584Sdim  }
754226584Sdim
755226584Sdim  Record *getElementAsRecord(unsigned i) const;
756226584Sdim
757226584Sdim  Init *convertInitListSlice(const std::vector<unsigned> &Elements) const;
758226584Sdim
759226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
760226584Sdim    return Ty->convertValue(const_cast<ListInit *>(this));
761226584Sdim  }
762226584Sdim
763226584Sdim  /// resolveReferences - This method is used by classes that refer to other
764226584Sdim  /// variables which may not be defined at the time they expression is formed.
765226584Sdim  /// If a value is set for the variable later, this method will be called on
766226584Sdim  /// users of the value to allow the value to propagate out.
767226584Sdim  ///
768226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
769226584Sdim
770226584Sdim  virtual std::string getAsString() const;
771226584Sdim
772226584Sdim  ArrayRef<Init*> getValues() const { return Values; }
773226584Sdim
774226584Sdim  inline const_iterator begin() const { return Values.begin(); }
775226584Sdim  inline const_iterator end  () const { return Values.end();   }
776226584Sdim
777226584Sdim  inline size_t         size () const { return Values.size();  }
778226584Sdim  inline bool           empty() const { return Values.empty(); }
779226584Sdim
780226584Sdim  /// resolveBitReference - This method is used to implement
781226584Sdim  /// VarBitInit::resolveReferences.  If the bit is able to be resolved, we
782226584Sdim  /// simply return the resolved value, otherwise we return null.
783226584Sdim  ///
784226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
785226584Sdim                                    unsigned Bit) const {
786234353Sdim    llvm_unreachable("Illegal bit reference off list");
787226584Sdim  }
788226584Sdim
789226584Sdim  /// resolveListElementReference - This method is used to implement
790226584Sdim  /// VarListElementInit::resolveReferences.  If the list element is resolvable
791226584Sdim  /// now, we return the resolved value, otherwise we return null.
792226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
793226584Sdim                                            unsigned Elt) const;
794226584Sdim};
795226584Sdim
796226584Sdim
797226584Sdim/// OpInit - Base class for operators
798226584Sdim///
799226584Sdimclass OpInit : public TypedInit {
800226584Sdim  OpInit(const OpInit &Other);  // Do not define.
801226584Sdim  OpInit &operator=(OpInit &Other);  // Do not define.
802226584Sdim
803226584Sdimprotected:
804226584Sdim  explicit OpInit(RecTy *Type) : TypedInit(Type) {}
805226584Sdim
806226584Sdimpublic:
807226584Sdim  // Clone - Clone this operator, replacing arguments with the new list
808226584Sdim  virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;
809226584Sdim
810226584Sdim  virtual int getNumOperands() const = 0;
811226584Sdim  virtual Init *getOperand(int i) const = 0;
812226584Sdim
813226584Sdim  // Fold - If possible, fold this to a simpler init.  Return this if not
814226584Sdim  // possible to fold.
815226584Sdim  virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0;
816226584Sdim
817226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
818226584Sdim    return Ty->convertValue(const_cast<OpInit *>(this));
819226584Sdim  }
820226584Sdim
821226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
822226584Sdim                                    unsigned Bit) const;
823226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
824226584Sdim                                            unsigned Elt) const;
825226584Sdim};
826226584Sdim
827226584Sdim
828226584Sdim/// UnOpInit - !op (X) - Transform an init.
829226584Sdim///
830226584Sdimclass UnOpInit : public OpInit {
831226584Sdimpublic:
832226584Sdim  enum UnaryOp { CAST, HEAD, TAIL, EMPTY };
833226584Sdimprivate:
834226584Sdim  UnaryOp Opc;
835226584Sdim  Init *LHS;
836226584Sdim
837226584Sdim  UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
838226584Sdim      : OpInit(Type), Opc(opc), LHS(lhs) {}
839226584Sdim
840226584Sdim  UnOpInit(const UnOpInit &Other);  // Do not define.
841226584Sdim  UnOpInit &operator=(const UnOpInit &Other);  // Do not define.
842226584Sdim
843226584Sdimpublic:
844226584Sdim  static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);
845226584Sdim
846226584Sdim  // Clone - Clone this operator, replacing arguments with the new list
847226584Sdim  virtual OpInit *clone(std::vector<Init *> &Operands) const {
848226584Sdim    assert(Operands.size() == 1 &&
849226584Sdim           "Wrong number of operands for unary operation");
850226584Sdim    return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
851226584Sdim  }
852226584Sdim
853226584Sdim  int getNumOperands() const { return 1; }
854226584Sdim  Init *getOperand(int i) const {
855226584Sdim    assert(i == 0 && "Invalid operand id for unary operator");
856226584Sdim    return getOperand();
857226584Sdim  }
858226584Sdim
859226584Sdim  UnaryOp getOpcode() const { return Opc; }
860226584Sdim  Init *getOperand() const { return LHS; }
861226584Sdim
862226584Sdim  // Fold - If possible, fold this to a simpler init.  Return this if not
863226584Sdim  // possible to fold.
864226584Sdim  Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
865226584Sdim
866226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
867226584Sdim
868226584Sdim  virtual std::string getAsString() const;
869226584Sdim};
870226584Sdim
871226584Sdim/// BinOpInit - !op (X, Y) - Combine two inits.
872226584Sdim///
873226584Sdimclass BinOpInit : public OpInit {
874226584Sdimpublic:
875226584Sdim  enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ };
876226584Sdimprivate:
877226584Sdim  BinaryOp Opc;
878226584Sdim  Init *LHS, *RHS;
879226584Sdim
880226584Sdim  BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
881226584Sdim      OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {}
882226584Sdim
883226584Sdim  BinOpInit(const BinOpInit &Other);  // Do not define.
884226584Sdim  BinOpInit &operator=(const BinOpInit &Other);  // Do not define.
885226584Sdim
886226584Sdimpublic:
887226584Sdim  static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
888226584Sdim                        RecTy *Type);
889226584Sdim
890226584Sdim  // Clone - Clone this operator, replacing arguments with the new list
891226584Sdim  virtual OpInit *clone(std::vector<Init *> &Operands) const {
892226584Sdim    assert(Operands.size() == 2 &&
893226584Sdim           "Wrong number of operands for binary operation");
894226584Sdim    return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
895226584Sdim  }
896226584Sdim
897226584Sdim  int getNumOperands() const { return 2; }
898226584Sdim  Init *getOperand(int i) const {
899226584Sdim    assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
900226584Sdim    if (i == 0) {
901226584Sdim      return getLHS();
902226584Sdim    } else {
903226584Sdim      return getRHS();
904226584Sdim    }
905226584Sdim  }
906226584Sdim
907226584Sdim  BinaryOp getOpcode() const { return Opc; }
908226584Sdim  Init *getLHS() const { return LHS; }
909226584Sdim  Init *getRHS() const { return RHS; }
910226584Sdim
911226584Sdim  // Fold - If possible, fold this to a simpler init.  Return this if not
912226584Sdim  // possible to fold.
913226584Sdim  Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
914226584Sdim
915226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
916226584Sdim
917226584Sdim  virtual std::string getAsString() const;
918226584Sdim};
919226584Sdim
920226584Sdim/// TernOpInit - !op (X, Y, Z) - Combine two inits.
921226584Sdim///
922226584Sdimclass TernOpInit : public OpInit {
923226584Sdimpublic:
924226584Sdim  enum TernaryOp { SUBST, FOREACH, IF };
925226584Sdimprivate:
926226584Sdim  TernaryOp Opc;
927226584Sdim  Init *LHS, *MHS, *RHS;
928226584Sdim
929226584Sdim  TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs,
930226584Sdim             RecTy *Type) :
931226584Sdim      OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
932226584Sdim
933226584Sdim  TernOpInit(const TernOpInit &Other);  // Do not define.
934226584Sdim  TernOpInit &operator=(const TernOpInit &Other);  // Do not define.
935226584Sdim
936226584Sdimpublic:
937226584Sdim  static TernOpInit *get(TernaryOp opc, Init *lhs,
938226584Sdim                         Init *mhs, Init *rhs,
939226584Sdim                         RecTy *Type);
940226584Sdim
941226584Sdim  // Clone - Clone this operator, replacing arguments with the new list
942226584Sdim  virtual OpInit *clone(std::vector<Init *> &Operands) const {
943226584Sdim    assert(Operands.size() == 3 &&
944226584Sdim           "Wrong number of operands for ternary operation");
945226584Sdim    return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2],
946226584Sdim                           getType());
947226584Sdim  }
948226584Sdim
949226584Sdim  int getNumOperands() const { return 3; }
950226584Sdim  Init *getOperand(int i) const {
951226584Sdim    assert((i == 0 || i == 1 || i == 2) &&
952226584Sdim           "Invalid operand id for ternary operator");
953226584Sdim    if (i == 0) {
954226584Sdim      return getLHS();
955226584Sdim    } else if (i == 1) {
956226584Sdim      return getMHS();
957226584Sdim    } else {
958226584Sdim      return getRHS();
959226584Sdim    }
960226584Sdim  }
961226584Sdim
962226584Sdim  TernaryOp getOpcode() const { return Opc; }
963226584Sdim  Init *getLHS() const { return LHS; }
964226584Sdim  Init *getMHS() const { return MHS; }
965226584Sdim  Init *getRHS() const { return RHS; }
966226584Sdim
967226584Sdim  // Fold - If possible, fold this to a simpler init.  Return this if not
968226584Sdim  // possible to fold.
969226584Sdim  Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
970226584Sdim
971226584Sdim  virtual bool isComplete() const { return false; }
972226584Sdim
973226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
974226584Sdim
975226584Sdim  virtual std::string getAsString() const;
976226584Sdim};
977226584Sdim
978226584Sdim
979226584Sdim/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
980226584Sdim///
981226584Sdimclass VarInit : public TypedInit {
982234353Sdim  Init *VarName;
983226584Sdim
984226584Sdim  explicit VarInit(const std::string &VN, RecTy *T)
985234353Sdim      : TypedInit(T), VarName(StringInit::get(VN)) {}
986234353Sdim  explicit VarInit(Init *VN, RecTy *T)
987226584Sdim      : TypedInit(T), VarName(VN) {}
988226584Sdim
989226584Sdim  VarInit(const VarInit &Other);  // Do not define.
990226584Sdim  VarInit &operator=(const VarInit &Other);  // Do not define.
991226584Sdim
992226584Sdimpublic:
993226584Sdim  static VarInit *get(const std::string &VN, RecTy *T);
994226584Sdim  static VarInit *get(Init *VN, RecTy *T);
995226584Sdim
996226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
997226584Sdim    return Ty->convertValue(const_cast<VarInit *>(this));
998226584Sdim  }
999226584Sdim
1000234353Sdim  const std::string &getName() const;
1001234353Sdim  Init *getNameInit() const { return VarName; }
1002234353Sdim  std::string getNameInitAsString() const {
1003234353Sdim    return getNameInit()->getAsUnquotedString();
1004234353Sdim  }
1005226584Sdim
1006226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
1007226584Sdim                                    unsigned Bit) const;
1008226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
1009226584Sdim                                            unsigned Elt) const;
1010226584Sdim
1011226584Sdim  virtual RecTy *getFieldType(const std::string &FieldName) const;
1012226584Sdim  virtual Init *getFieldInit(Record &R, const RecordVal *RV,
1013226584Sdim                             const std::string &FieldName) const;
1014226584Sdim
1015226584Sdim  /// resolveReferences - This method is used by classes that refer to other
1016226584Sdim  /// variables which may not be defined at the time they expression is formed.
1017226584Sdim  /// If a value is set for the variable later, this method will be called on
1018226584Sdim  /// users of the value to allow the value to propagate out.
1019226584Sdim  ///
1020226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
1021226584Sdim
1022234353Sdim  virtual std::string getAsString() const { return getName(); }
1023226584Sdim};
1024226584Sdim
1025226584Sdim
1026226584Sdim/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
1027226584Sdim///
1028226584Sdimclass VarBitInit : public Init {
1029226584Sdim  TypedInit *TI;
1030226584Sdim  unsigned Bit;
1031226584Sdim
1032226584Sdim  VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
1033226584Sdim    assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) &&
1034226584Sdim           ((BitsRecTy*)T->getType())->getNumBits() > B &&
1035226584Sdim           "Illegal VarBitInit expression!");
1036226584Sdim  }
1037226584Sdim
1038226584Sdim  VarBitInit(const VarBitInit &Other);  // Do not define.
1039226584Sdim  VarBitInit &operator=(const VarBitInit &Other);  // Do not define.
1040226584Sdim
1041226584Sdimpublic:
1042226584Sdim  static VarBitInit *get(TypedInit *T, unsigned B);
1043226584Sdim
1044226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
1045226584Sdim    return Ty->convertValue(const_cast<VarBitInit *>(this));
1046226584Sdim  }
1047226584Sdim
1048226584Sdim  TypedInit *getVariable() const { return TI; }
1049226584Sdim  unsigned getBitNum() const { return Bit; }
1050226584Sdim
1051226584Sdim  virtual std::string getAsString() const;
1052226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
1053226584Sdim};
1054226584Sdim
1055226584Sdim/// VarListElementInit - List[4] - Represent access to one element of a var or
1056226584Sdim/// field.
1057226584Sdimclass VarListElementInit : public TypedInit {
1058226584Sdim  TypedInit *TI;
1059226584Sdim  unsigned Element;
1060226584Sdim
1061226584Sdim  VarListElementInit(TypedInit *T, unsigned E)
1062226584Sdim      : TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()),
1063226584Sdim          TI(T), Element(E) {
1064226584Sdim    assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) &&
1065226584Sdim           "Illegal VarBitInit expression!");
1066226584Sdim  }
1067226584Sdim
1068226584Sdim  VarListElementInit(const VarListElementInit &Other);  // Do not define.
1069226584Sdim  VarListElementInit &operator=(const VarListElementInit &Other);  // Do
1070226584Sdim                                                                   // not
1071226584Sdim                                                                   // define.
1072226584Sdim
1073226584Sdimpublic:
1074226584Sdim  static VarListElementInit *get(TypedInit *T, unsigned E);
1075226584Sdim
1076226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
1077226584Sdim    return Ty->convertValue(const_cast<VarListElementInit *>(this));
1078226584Sdim  }
1079226584Sdim
1080226584Sdim  TypedInit *getVariable() const { return TI; }
1081226584Sdim  unsigned getElementNum() const { return Element; }
1082226584Sdim
1083226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
1084226584Sdim                                    unsigned Bit) const;
1085226584Sdim
1086226584Sdim  /// resolveListElementReference - This method is used to implement
1087226584Sdim  /// VarListElementInit::resolveReferences.  If the list element is resolvable
1088226584Sdim  /// now, we return the resolved value, otherwise we return null.
1089226584Sdim  virtual Init *resolveListElementReference(Record &R,
1090226584Sdim                                            const RecordVal *RV,
1091226584Sdim                                            unsigned Elt) const;
1092226584Sdim
1093226584Sdim  virtual std::string getAsString() const;
1094226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
1095226584Sdim};
1096226584Sdim
1097226584Sdim/// DefInit - AL - Represent a reference to a 'def' in the description
1098226584Sdim///
1099226584Sdimclass DefInit : public TypedInit {
1100226584Sdim  Record *Def;
1101226584Sdim
1102226584Sdim  DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {}
1103226584Sdim  friend class Record;
1104226584Sdim
1105226584Sdim  DefInit(const DefInit &Other);  // Do not define.
1106226584Sdim  DefInit &operator=(const DefInit &Other);  // Do not define.
1107226584Sdim
1108226584Sdimpublic:
1109226584Sdim  static DefInit *get(Record*);
1110226584Sdim
1111226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
1112226584Sdim    return Ty->convertValue(const_cast<DefInit *>(this));
1113226584Sdim  }
1114226584Sdim
1115226584Sdim  Record *getDef() const { return Def; }
1116226584Sdim
1117226584Sdim  //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits);
1118226584Sdim
1119226584Sdim  virtual RecTy *getFieldType(const std::string &FieldName) const;
1120226584Sdim  virtual Init *getFieldInit(Record &R, const RecordVal *RV,
1121226584Sdim                             const std::string &FieldName) const;
1122226584Sdim
1123226584Sdim  virtual std::string getAsString() const;
1124226584Sdim
1125226584Sdim  /// resolveBitReference - This method is used to implement
1126226584Sdim  /// VarBitInit::resolveReferences.  If the bit is able to be resolved, we
1127226584Sdim  /// simply return the resolved value, otherwise we return null.
1128226584Sdim  ///
1129226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
1130226584Sdim                                    unsigned Bit) const {
1131234353Sdim    llvm_unreachable("Illegal bit reference off def");
1132226584Sdim  }
1133226584Sdim
1134226584Sdim  /// resolveListElementReference - This method is used to implement
1135226584Sdim  /// VarListElementInit::resolveReferences.  If the list element is resolvable
1136226584Sdim  /// now, we return the resolved value, otherwise we return null.
1137226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
1138226584Sdim                                            unsigned Elt) const {
1139234353Sdim    llvm_unreachable("Illegal element reference off def");
1140226584Sdim  }
1141226584Sdim};
1142226584Sdim
1143226584Sdim
1144226584Sdim/// FieldInit - X.Y - Represent a reference to a subfield of a variable
1145226584Sdim///
1146226584Sdimclass FieldInit : public TypedInit {
1147226584Sdim  Init *Rec;                // Record we are referring to
1148226584Sdim  std::string FieldName;    // Field we are accessing
1149226584Sdim
1150226584Sdim  FieldInit(Init *R, const std::string &FN)
1151226584Sdim      : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
1152226584Sdim    assert(getType() && "FieldInit with non-record type!");
1153226584Sdim  }
1154226584Sdim
1155226584Sdim  FieldInit(const FieldInit &Other);  // Do not define.
1156226584Sdim  FieldInit &operator=(const FieldInit &Other);  // Do not define.
1157226584Sdim
1158226584Sdimpublic:
1159226584Sdim  static FieldInit *get(Init *R, const std::string &FN);
1160226584Sdim  static FieldInit *get(Init *R, const Init *FN);
1161226584Sdim
1162226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
1163226584Sdim    return Ty->convertValue(const_cast<FieldInit *>(this));
1164226584Sdim  }
1165226584Sdim
1166226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
1167226584Sdim                                    unsigned Bit) const;
1168226584Sdim  virtual Init *resolveListElementReference(Record &R,
1169226584Sdim                                            const RecordVal *RV,
1170226584Sdim                                            unsigned Elt) const;
1171226584Sdim
1172226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
1173226584Sdim
1174226584Sdim  virtual std::string getAsString() const {
1175226584Sdim    return Rec->getAsString() + "." + FieldName;
1176226584Sdim  }
1177226584Sdim};
1178226584Sdim
1179226584Sdim/// DagInit - (v a, b) - Represent a DAG tree value.  DAG inits are required
1180226584Sdim/// to have at least one value then a (possibly empty) list of arguments.  Each
1181226584Sdim/// argument can have a name associated with it.
1182226584Sdim///
1183226584Sdimclass DagInit : public TypedInit, public FoldingSetNode {
1184226584Sdim  Init *Val;
1185226584Sdim  std::string ValName;
1186226584Sdim  std::vector<Init*> Args;
1187226584Sdim  std::vector<std::string> ArgNames;
1188226584Sdim
1189226584Sdim  DagInit(Init *V, const std::string &VN,
1190226584Sdim          ArrayRef<Init *> ArgRange,
1191226584Sdim          ArrayRef<std::string> NameRange)
1192226584Sdim      : TypedInit(DagRecTy::get()), Val(V), ValName(VN),
1193226584Sdim          Args(ArgRange.begin(), ArgRange.end()),
1194226584Sdim          ArgNames(NameRange.begin(), NameRange.end()) {}
1195226584Sdim
1196226584Sdim  DagInit(const DagInit &Other);  // Do not define.
1197226584Sdim  DagInit &operator=(const DagInit &Other);  // Do not define.
1198226584Sdim
1199226584Sdimpublic:
1200226584Sdim  static DagInit *get(Init *V, const std::string &VN,
1201226584Sdim                      ArrayRef<Init *> ArgRange,
1202226584Sdim                      ArrayRef<std::string> NameRange);
1203226584Sdim  static DagInit *get(Init *V, const std::string &VN,
1204226584Sdim                      const std::vector<
1205226584Sdim                        std::pair<Init*, std::string> > &args);
1206226584Sdim
1207226584Sdim  void Profile(FoldingSetNodeID &ID) const;
1208226584Sdim
1209226584Sdim  virtual Init *convertInitializerTo(RecTy *Ty) const {
1210226584Sdim    return Ty->convertValue(const_cast<DagInit *>(this));
1211226584Sdim  }
1212226584Sdim
1213226584Sdim  Init *getOperator() const { return Val; }
1214226584Sdim
1215226584Sdim  const std::string &getName() const { return ValName; }
1216226584Sdim
1217226584Sdim  unsigned getNumArgs() const { return Args.size(); }
1218226584Sdim  Init *getArg(unsigned Num) const {
1219226584Sdim    assert(Num < Args.size() && "Arg number out of range!");
1220226584Sdim    return Args[Num];
1221226584Sdim  }
1222226584Sdim  const std::string &getArgName(unsigned Num) const {
1223226584Sdim    assert(Num < ArgNames.size() && "Arg number out of range!");
1224226584Sdim    return ArgNames[Num];
1225226584Sdim  }
1226226584Sdim
1227226584Sdim  virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
1228226584Sdim
1229226584Sdim  virtual std::string getAsString() const;
1230226584Sdim
1231226584Sdim  typedef std::vector<Init*>::const_iterator       const_arg_iterator;
1232226584Sdim  typedef std::vector<std::string>::const_iterator const_name_iterator;
1233226584Sdim
1234226584Sdim  inline const_arg_iterator  arg_begin() const { return Args.begin(); }
1235226584Sdim  inline const_arg_iterator  arg_end  () const { return Args.end();   }
1236226584Sdim
1237226584Sdim  inline size_t              arg_size () const { return Args.size();  }
1238226584Sdim  inline bool                arg_empty() const { return Args.empty(); }
1239226584Sdim
1240226584Sdim  inline const_name_iterator name_begin() const { return ArgNames.begin(); }
1241226584Sdim  inline const_name_iterator name_end  () const { return ArgNames.end();   }
1242226584Sdim
1243226584Sdim  inline size_t              name_size () const { return ArgNames.size();  }
1244226584Sdim  inline bool                name_empty() const { return ArgNames.empty(); }
1245226584Sdim
1246226584Sdim  virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
1247226584Sdim                                    unsigned Bit) const {
1248234353Sdim    llvm_unreachable("Illegal bit reference off dag");
1249226584Sdim  }
1250226584Sdim
1251226584Sdim  virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
1252226584Sdim                                            unsigned Elt) const {
1253234353Sdim    llvm_unreachable("Illegal element reference off dag");
1254226584Sdim  }
1255226584Sdim};
1256226584Sdim
1257226584Sdim//===----------------------------------------------------------------------===//
1258226584Sdim//  High-Level Classes
1259226584Sdim//===----------------------------------------------------------------------===//
1260226584Sdim
1261226584Sdimclass RecordVal {
1262226584Sdim  Init *Name;
1263226584Sdim  RecTy *Ty;
1264226584Sdim  unsigned Prefix;
1265226584Sdim  Init *Value;
1266226584Sdimpublic:
1267226584Sdim  RecordVal(Init *N, RecTy *T, unsigned P);
1268226584Sdim  RecordVal(const std::string &N, RecTy *T, unsigned P);
1269226584Sdim
1270226584Sdim  const std::string &getName() const;
1271234353Sdim  const Init *getNameInit() const { return Name; }
1272234353Sdim  std::string getNameInitAsString() const {
1273234353Sdim    return getNameInit()->getAsUnquotedString();
1274234353Sdim  }
1275226584Sdim
1276226584Sdim  unsigned getPrefix() const { return Prefix; }
1277226584Sdim  RecTy *getType() const { return Ty; }
1278226584Sdim  Init *getValue() const { return Value; }
1279226584Sdim
1280226584Sdim  bool setValue(Init *V) {
1281226584Sdim    if (V) {
1282226584Sdim      Value = V->convertInitializerTo(Ty);
1283226584Sdim      return Value == 0;
1284226584Sdim    }
1285226584Sdim    Value = 0;
1286226584Sdim    return false;
1287226584Sdim  }
1288226584Sdim
1289226584Sdim  void dump() const;
1290226584Sdim  void print(raw_ostream &OS, bool PrintSem = true) const;
1291226584Sdim};
1292226584Sdim
1293226584Sdiminline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
1294226584Sdim  RV.print(OS << "  ");
1295226584Sdim  return OS;
1296226584Sdim}
1297226584Sdim
1298226584Sdimclass Record {
1299226584Sdim  static unsigned LastID;
1300226584Sdim
1301226584Sdim  // Unique record ID.
1302226584Sdim  unsigned ID;
1303226584Sdim  Init *Name;
1304226584Sdim  SMLoc Loc;
1305234353Sdim  std::vector<Init *> TemplateArgs;
1306226584Sdim  std::vector<RecordVal> Values;
1307226584Sdim  std::vector<Record*> SuperClasses;
1308226584Sdim
1309226584Sdim  // Tracks Record instances. Not owned by Record.
1310226584Sdim  RecordKeeper &TrackedRecords;
1311226584Sdim
1312226584Sdim  DefInit *TheInit;
1313226584Sdim
1314234353Sdim  void init();
1315226584Sdim  void checkName();
1316226584Sdim
1317226584Sdimpublic:
1318226584Sdim
1319226584Sdim  // Constructs a record.
1320226584Sdim  explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
1321234353Sdim    ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records),
1322234353Sdim      TheInit(0) {
1323234353Sdim    init();
1324234353Sdim  }
1325234353Sdim  explicit Record(Init *N, SMLoc loc, RecordKeeper &records) :
1326234353Sdim    ID(LastID++), Name(N), Loc(loc), TrackedRecords(records), TheInit(0) {
1327234353Sdim    init();
1328234353Sdim  }
1329226584Sdim  ~Record() {}
1330226584Sdim
1331226584Sdim
1332226584Sdim  static unsigned getNewUID() { return LastID++; }
1333226584Sdim
1334226584Sdim
1335226584Sdim  unsigned getID() const { return ID; }
1336226584Sdim
1337226584Sdim  const std::string &getName() const;
1338234353Sdim  Init *getNameInit() const {
1339234353Sdim    return Name;
1340234353Sdim  }
1341234353Sdim  const std::string getNameInitAsString() const {
1342234353Sdim    return getNameInit()->getAsUnquotedString();
1343234353Sdim  }
1344234353Sdim
1345226584Sdim  void setName(Init *Name);               // Also updates RecordKeeper.
1346226584Sdim  void setName(const std::string &Name);  // Also updates RecordKeeper.
1347226584Sdim
1348226584Sdim  SMLoc getLoc() const { return Loc; }
1349226584Sdim
1350226584Sdim  /// get the corresponding DefInit.
1351226584Sdim  DefInit *getDefInit();
1352226584Sdim
1353234353Sdim  const std::vector<Init *> &getTemplateArgs() const {
1354226584Sdim    return TemplateArgs;
1355226584Sdim  }
1356226584Sdim  const std::vector<RecordVal> &getValues() const { return Values; }
1357226584Sdim  const std::vector<Record*>   &getSuperClasses() const { return SuperClasses; }
1358226584Sdim
1359234353Sdim  bool isTemplateArg(Init *Name) const {
1360226584Sdim    for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
1361226584Sdim      if (TemplateArgs[i] == Name) return true;
1362226584Sdim    return false;
1363226584Sdim  }
1364234353Sdim  bool isTemplateArg(StringRef Name) const {
1365234353Sdim    return isTemplateArg(StringInit::get(Name.str()));
1366234353Sdim  }
1367226584Sdim
1368234353Sdim  const RecordVal *getValue(const Init *Name) const {
1369226584Sdim    for (unsigned i = 0, e = Values.size(); i != e; ++i)
1370234353Sdim      if (Values[i].getNameInit() == Name) return &Values[i];
1371226584Sdim    return 0;
1372226584Sdim  }
1373234353Sdim  const RecordVal *getValue(StringRef Name) const {
1374234353Sdim    return getValue(StringInit::get(Name));
1375234353Sdim  }
1376234353Sdim  RecordVal *getValue(const Init *Name) {
1377226584Sdim    for (unsigned i = 0, e = Values.size(); i != e; ++i)
1378234353Sdim      if (Values[i].getNameInit() == Name) return &Values[i];
1379226584Sdim    return 0;
1380226584Sdim  }
1381234353Sdim  RecordVal *getValue(StringRef Name) {
1382234353Sdim    return getValue(StringInit::get(Name));
1383234353Sdim  }
1384226584Sdim
1385234353Sdim  void addTemplateArg(Init *Name) {
1386226584Sdim    assert(!isTemplateArg(Name) && "Template arg already defined!");
1387226584Sdim    TemplateArgs.push_back(Name);
1388226584Sdim  }
1389234353Sdim  void addTemplateArg(StringRef Name) {
1390234353Sdim    addTemplateArg(StringInit::get(Name.str()));
1391234353Sdim  }
1392226584Sdim
1393226584Sdim  void addValue(const RecordVal &RV) {
1394234353Sdim    assert(getValue(RV.getNameInit()) == 0 && "Value already added!");
1395226584Sdim    Values.push_back(RV);
1396234353Sdim    if (Values.size() > 1)
1397234353Sdim      // Keep NAME at the end of the list.  It makes record dumps a
1398234353Sdim      // bit prettier and allows TableGen tests to be written more
1399234353Sdim      // naturally.  Tests can use CHECK-NEXT to look for Record
1400234353Sdim      // fields they expect to see after a def.  They can't do that if
1401234353Sdim      // NAME is the first Record field.
1402234353Sdim      std::swap(Values[Values.size() - 2], Values[Values.size() - 1]);
1403226584Sdim  }
1404226584Sdim
1405234353Sdim  void removeValue(Init *Name) {
1406226584Sdim    for (unsigned i = 0, e = Values.size(); i != e; ++i)
1407234353Sdim      if (Values[i].getNameInit() == Name) {
1408226584Sdim        Values.erase(Values.begin()+i);
1409226584Sdim        return;
1410226584Sdim      }
1411234353Sdim    llvm_unreachable("Cannot remove an entry that does not exist!");
1412226584Sdim  }
1413226584Sdim
1414234353Sdim  void removeValue(StringRef Name) {
1415234353Sdim    removeValue(StringInit::get(Name.str()));
1416234353Sdim  }
1417234353Sdim
1418226584Sdim  bool isSubClassOf(const Record *R) const {
1419226584Sdim    for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
1420226584Sdim      if (SuperClasses[i] == R)
1421226584Sdim        return true;
1422226584Sdim    return false;
1423226584Sdim  }
1424226584Sdim
1425226584Sdim  bool isSubClassOf(StringRef Name) const {
1426226584Sdim    for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
1427234353Sdim      if (SuperClasses[i]->getNameInitAsString() == Name)
1428226584Sdim        return true;
1429226584Sdim    return false;
1430226584Sdim  }
1431226584Sdim
1432226584Sdim  void addSuperClass(Record *R) {
1433226584Sdim    assert(!isSubClassOf(R) && "Already subclassing record!");
1434226584Sdim    SuperClasses.push_back(R);
1435226584Sdim  }
1436226584Sdim
1437226584Sdim  /// resolveReferences - If there are any field references that refer to fields
1438226584Sdim  /// that have been filled in, we can propagate the values now.
1439226584Sdim  ///
1440226584Sdim  void resolveReferences() { resolveReferencesTo(0); }
1441226584Sdim
1442226584Sdim  /// resolveReferencesTo - If anything in this record refers to RV, replace the
1443226584Sdim  /// reference to RV with the RHS of RV.  If RV is null, we resolve all
1444226584Sdim  /// possible references.
1445226584Sdim  void resolveReferencesTo(const RecordVal *RV);
1446226584Sdim
1447226584Sdim  RecordKeeper &getRecords() const {
1448226584Sdim    return TrackedRecords;
1449226584Sdim  }
1450226584Sdim
1451226584Sdim  void dump() const;
1452226584Sdim
1453226584Sdim  //===--------------------------------------------------------------------===//
1454226584Sdim  // High-level methods useful to tablegen back-ends
1455226584Sdim  //
1456226584Sdim
1457226584Sdim  /// getValueInit - Return the initializer for a value with the specified name,
1458226584Sdim  /// or throw an exception if the field does not exist.
1459226584Sdim  ///
1460226584Sdim  Init *getValueInit(StringRef FieldName) const;
1461226584Sdim
1462226584Sdim  /// getValueAsString - This method looks up the specified field and returns
1463226584Sdim  /// its value as a string, throwing an exception if the field does not exist
1464226584Sdim  /// or if the value is not a string.
1465226584Sdim  ///
1466226584Sdim  std::string getValueAsString(StringRef FieldName) const;
1467226584Sdim
1468226584Sdim  /// getValueAsBitsInit - This method looks up the specified field and returns
1469226584Sdim  /// its value as a BitsInit, throwing an exception if the field does not exist
1470226584Sdim  /// or if the value is not the right type.
1471226584Sdim  ///
1472226584Sdim  BitsInit *getValueAsBitsInit(StringRef FieldName) const;
1473226584Sdim
1474226584Sdim  /// getValueAsListInit - This method looks up the specified field and returns
1475226584Sdim  /// its value as a ListInit, throwing an exception if the field does not exist
1476226584Sdim  /// or if the value is not the right type.
1477226584Sdim  ///
1478226584Sdim  ListInit *getValueAsListInit(StringRef FieldName) const;
1479226584Sdim
1480226584Sdim  /// getValueAsListOfDefs - This method looks up the specified field and
1481226584Sdim  /// returns its value as a vector of records, throwing an exception if the
1482226584Sdim  /// field does not exist or if the value is not the right type.
1483226584Sdim  ///
1484226584Sdim  std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
1485226584Sdim
1486226584Sdim  /// getValueAsListOfInts - This method looks up the specified field and
1487226584Sdim  /// returns its value as a vector of integers, throwing an exception if the
1488226584Sdim  /// field does not exist or if the value is not the right type.
1489226584Sdim  ///
1490226584Sdim  std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
1491226584Sdim
1492226584Sdim  /// getValueAsListOfStrings - This method looks up the specified field and
1493226584Sdim  /// returns its value as a vector of strings, throwing an exception if the
1494226584Sdim  /// field does not exist or if the value is not the right type.
1495226584Sdim  ///
1496226584Sdim  std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
1497226584Sdim
1498226584Sdim  /// getValueAsDef - This method looks up the specified field and returns its
1499226584Sdim  /// value as a Record, throwing an exception if the field does not exist or if
1500226584Sdim  /// the value is not the right type.
1501226584Sdim  ///
1502226584Sdim  Record *getValueAsDef(StringRef FieldName) const;
1503226584Sdim
1504226584Sdim  /// getValueAsBit - This method looks up the specified field and returns its
1505226584Sdim  /// value as a bit, throwing an exception if the field does not exist or if
1506226584Sdim  /// the value is not the right type.
1507226584Sdim  ///
1508226584Sdim  bool getValueAsBit(StringRef FieldName) const;
1509226584Sdim
1510226584Sdim  /// getValueAsInt - This method looks up the specified field and returns its
1511226584Sdim  /// value as an int64_t, throwing an exception if the field does not exist or
1512226584Sdim  /// if the value is not the right type.
1513226584Sdim  ///
1514226584Sdim  int64_t getValueAsInt(StringRef FieldName) const;
1515226584Sdim
1516226584Sdim  /// getValueAsDag - This method looks up the specified field and returns its
1517226584Sdim  /// value as an Dag, throwing an exception if the field does not exist or if
1518226584Sdim  /// the value is not the right type.
1519226584Sdim  ///
1520226584Sdim  DagInit *getValueAsDag(StringRef FieldName) const;
1521226584Sdim};
1522226584Sdim
1523226584Sdimraw_ostream &operator<<(raw_ostream &OS, const Record &R);
1524226584Sdim
1525226584Sdimstruct MultiClass {
1526226584Sdim  Record Rec;  // Placeholder for template args and Name.
1527226584Sdim  typedef std::vector<Record*> RecordVector;
1528226584Sdim  RecordVector DefPrototypes;
1529226584Sdim
1530226584Sdim  void dump() const;
1531226584Sdim
1532234982Sdim  MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
1533226584Sdim    Rec(Name, Loc, Records) {}
1534226584Sdim};
1535226584Sdim
1536226584Sdimclass RecordKeeper {
1537226584Sdim  std::map<std::string, Record*> Classes, Defs;
1538234353Sdim
1539226584Sdimpublic:
1540226584Sdim  ~RecordKeeper() {
1541226584Sdim    for (std::map<std::string, Record*>::iterator I = Classes.begin(),
1542226584Sdim           E = Classes.end(); I != E; ++I)
1543226584Sdim      delete I->second;
1544226584Sdim    for (std::map<std::string, Record*>::iterator I = Defs.begin(),
1545226584Sdim           E = Defs.end(); I != E; ++I)
1546226584Sdim      delete I->second;
1547226584Sdim  }
1548226584Sdim
1549226584Sdim  const std::map<std::string, Record*> &getClasses() const { return Classes; }
1550226584Sdim  const std::map<std::string, Record*> &getDefs() const { return Defs; }
1551226584Sdim
1552226584Sdim  Record *getClass(const std::string &Name) const {
1553226584Sdim    std::map<std::string, Record*>::const_iterator I = Classes.find(Name);
1554226584Sdim    return I == Classes.end() ? 0 : I->second;
1555226584Sdim  }
1556226584Sdim  Record *getDef(const std::string &Name) const {
1557226584Sdim    std::map<std::string, Record*>::const_iterator I = Defs.find(Name);
1558226584Sdim    return I == Defs.end() ? 0 : I->second;
1559226584Sdim  }
1560226584Sdim  void addClass(Record *R) {
1561239462Sdim    bool Ins = Classes.insert(std::make_pair(R->getName(), R)).second;
1562239462Sdim    (void)Ins;
1563239462Sdim    assert(Ins && "Class already exists");
1564226584Sdim  }
1565226584Sdim  void addDef(Record *R) {
1566239462Sdim    bool Ins = Defs.insert(std::make_pair(R->getName(), R)).second;
1567239462Sdim    (void)Ins;
1568239462Sdim    assert(Ins && "Record already exists");
1569226584Sdim  }
1570226584Sdim
1571226584Sdim  /// removeClass - Remove, but do not delete, the specified record.
1572226584Sdim  ///
1573226584Sdim  void removeClass(const std::string &Name) {
1574226584Sdim    assert(Classes.count(Name) && "Class does not exist!");
1575226584Sdim    Classes.erase(Name);
1576226584Sdim  }
1577226584Sdim  /// removeDef - Remove, but do not delete, the specified record.
1578226584Sdim  ///
1579226584Sdim  void removeDef(const std::string &Name) {
1580226584Sdim    assert(Defs.count(Name) && "Def does not exist!");
1581226584Sdim    Defs.erase(Name);
1582226584Sdim  }
1583226584Sdim
1584226584Sdim  //===--------------------------------------------------------------------===//
1585226584Sdim  // High-level helper methods, useful for tablegen backends...
1586226584Sdim
1587226584Sdim  /// getAllDerivedDefinitions - This method returns all concrete definitions
1588226584Sdim  /// that derive from the specified class name.  If a class with the specified
1589226584Sdim  /// name does not exist, an exception is thrown.
1590226584Sdim  std::vector<Record*>
1591226584Sdim  getAllDerivedDefinitions(const std::string &ClassName) const;
1592226584Sdim
1593226584Sdim  void dump() const;
1594226584Sdim};
1595226584Sdim
1596226584Sdim/// LessRecord - Sorting predicate to sort record pointers by name.
1597226584Sdim///
1598226584Sdimstruct LessRecord {
1599226584Sdim  bool operator()(const Record *Rec1, const Record *Rec2) const {
1600226584Sdim    return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
1601226584Sdim  }
1602226584Sdim};
1603226584Sdim
1604226584Sdim/// LessRecordFieldName - Sorting predicate to sort record pointers by their
1605226584Sdim/// name field.
1606226584Sdim///
1607226584Sdimstruct LessRecordFieldName {
1608226584Sdim  bool operator()(const Record *Rec1, const Record *Rec2) const {
1609226584Sdim    return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
1610226584Sdim  }
1611226584Sdim};
1612226584Sdim
1613226584Sdimraw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
1614226584Sdim
1615234353Sdim/// QualifyName - Return an Init with a qualifier prefix referring
1616234353Sdim/// to CurRec's name.
1617234353SdimInit *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
1618234353Sdim                  Init *Name, const std::string &Scoper);
1619234353Sdim
1620234353Sdim/// QualifyName - Return an Init with a qualifier prefix referring
1621234353Sdim/// to CurRec's name.
1622234353SdimInit *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
1623234353Sdim                  const std::string &Name, const std::string &Scoper);
1624234353Sdim
1625226584Sdim} // End llvm namespace
1626226584Sdim
1627226584Sdim#endif
1628