summaryrefslogtreecommitdiff
path: root/include/llvm/Type.h
blob: 5854062df0c8a660435822736e57cdd33fa93b1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
//===-- llvm/Type.h - Classes for handling data types ------------*- C++ -*--=//
//
// This file contains the declaration of the Type class.  For more "Type" type
// stuff, look in DerivedTypes.h and Opt/ConstantHandling.h
//
// Note that instances of the Type class are immutable: once they are created,
// they are never changed.  Also note that only one instance of a particular 
// type is ever created.  Thus seeing if two types are equal is a matter of 
// doing a trivial pointer comparison.
//
// Types, once allocated, are never free'd.
//
// Opaque types are simple derived types with no state.  There may be many
// different Opaque type objects floating around, but two are only considered
// identical if they are pointer equals of each other.  This allows us to have 
// two opaque types that end up resolving to different concrete types later.
//
// Opaque types are also kinda wierd and scary and different because they have
// to keep a list of uses of the type.  When, through linking, parsing, or
// bytecode reading, they become resolved, they need to find and update all
// users of the unknown type, causing them to reference a new, more concrete
// type.  Opaque types are deleted when their use list dwindles to zero users.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TYPE_H
#define LLVM_TYPE_H

#include "llvm/Value.h"
#include "llvm/Support/GraphTraits.h"

class DerivedType;
class MethodType;
class ArrayType;
class PointerType;
class StructType;
class OpaqueType;

class Type : public Value {
public:
  //===--------------------------------------------------------------------===//
  // Definitions of all of the base types for the Type system.  Based on this
  // value, you can cast to a "DerivedType" subclass (see DerivedTypes.h)
  // Note: If you add an element to this, you need to add an element to the 
  // Type::getPrimitiveType function, or else things will break!
  //
  enum PrimitiveID {
    VoidTyID = 0  , BoolTyID,           //  0, 1: Basics...
    UByteTyID     , SByteTyID,          //  2, 3: 8 bit types...
    UShortTyID    , ShortTyID,          //  4, 5: 16 bit types...
    UIntTyID      , IntTyID,            //  6, 7: 32 bit types...
    ULongTyID     , LongTyID,           //  8, 9: 64 bit types...

    FloatTyID     , DoubleTyID,         // 10,11: Floating point types...

    TypeTyID,                           // 12   : Type definitions
    LabelTyID     ,                     // 13   : Labels... 

    // Derived types... see DerivedTypes.h file...
    // Make sure FirstDerivedTyID stays up to date!!!
    MethodTyID    , StructTyID,         // Methods... Structs...
    ArrayTyID     , PointerTyID,        // Array... pointer...
    OpaqueTyID,                         // Opaque type instances...
    //PackedTyID  ,                     // SIMD 'packed' format... TODO
    //...

    NumPrimitiveIDs,                    // Must remain as last defined ID
    FirstDerivedTyID = MethodTyID,
  };

private:
  PrimitiveID ID;        // The current base type of this type...
  unsigned    UID;       // The unique ID number for this class
  string      Desc;      // The printed name of the string...
  bool        Abstract;  // True if type contains an OpaqueType
  bool        Recursive; // True if the type is recursive

protected:
  // ctor is protected, so only subclasses can create Type objects...
  Type(const string &Name, PrimitiveID id);
  virtual ~Type() {}

  // When types are refined, they update their description to be more concrete.
  //
  inline void setDescription(const string &D) { Desc = D; }
  
  // setName - Associate the name with this type in the symbol table, but don't
  // set the local name to be equal specified name.
  //
  virtual void setName(const string &Name, SymbolTable *ST = 0);

  // Types can become nonabstract later, if they are refined.
  //
  inline void setAbstract(bool Val) { Abstract = Val; }

  // Types can become recursive later, if they are refined.
  //
  inline void setRecursive(bool Val) { Recursive = Val; }

public:

  //===--------------------------------------------------------------------===//
  // Property accessors for dealing with types...
  //

  // getPrimitiveID - Return the base type of the type.  This will return one
  // of the PrimitiveID enum elements defined above.
  //
  inline PrimitiveID getPrimitiveID() const { return ID; }

  // getUniqueID - Returns the UID of the type.  This can be thought of as a 
  // small integer version of the pointer to the type class.  Two types that are
  // structurally different have different UIDs.  This can be used for indexing
  // types into an array.
  //
  inline unsigned getUniqueID() const { return UID; }

  // getDescription - Return the string representation of the type...
  inline const string &getDescription() const { return Desc; }

  // isSigned - Return whether a numeric type is signed.
  virtual bool isSigned() const { return 0; }
  
  // isUnsigned - Return whether a numeric type is unsigned.  This is not 
  // quite the complement of isSigned... nonnumeric types return false as they
  // do with isSigned.
  // 
  virtual bool isUnsigned() const { return 0; }

  // isIntegral - Equilivent to isSigned() || isUnsigned, but with only a single
  // virtual function invocation.
  //
  virtual bool isIntegral() const { return 0; }

  // isAbstract - True if the type is either an Opaque type, or is a derived
  // type that includes an opaque type somewhere in it.  
  //
  inline bool isAbstract() const { return Abstract; }

  // isRecursive - True if the type graph contains a cycle.
  //
  inline bool isRecursive() const { return Recursive; }

  //===--------------------------------------------------------------------===//
  // Type Iteration support
  //
  class TypeIterator;
  typedef TypeIterator subtype_iterator;
  inline subtype_iterator subtype_begin() const;   // DEFINED BELOW
  inline subtype_iterator subtype_end() const;     // DEFINED BELOW

  // getContainedType - This method is used to implement the type iterator
  // (defined a the end of the file).  For derived types, this returns the types
  // 'contained' in the derived type, returning 0 when 'i' becomes invalid. This
  // allows the user to iterate over the types in a struct, for example, really
  // easily.
  //
  virtual const Type *getContainedType(unsigned i) const { return 0; }

  // getNumContainedTypes - Return the number of types in the derived type
  virtual unsigned getNumContainedTypes() const { return 0; }

  //===--------------------------------------------------------------------===//
  // Static members exported by the Type class itself.  Useful for getting
  // instances of Type.
  //

  // getPrimitiveType/getUniqueIDType - Return a type based on an identifier.
  static const Type *getPrimitiveType(PrimitiveID IDNumber);
  static const Type *getUniqueIDType(unsigned UID);

  //===--------------------------------------------------------------------===//
  // These are the builtin types that are always available...
  //
  static Type *VoidTy , *BoolTy;
  static Type *SByteTy, *UByteTy,
              *ShortTy, *UShortTy,
              *IntTy  , *UIntTy, 
              *LongTy , *ULongTy;
  static Type *FloatTy, *DoubleTy;

  static Type *TypeTy , *LabelTy;

  // Here are some useful little methods to query what type derived types are
  // Note that all other types can just compare to see if this == Type::xxxTy;
  //
  inline bool isPrimitiveType() const { return ID < FirstDerivedTyID;  }

  inline bool isDerivedType()   const { return ID >= FirstDerivedTyID; }
  inline const DerivedType *castDerivedType() const {
    return isDerivedType() ? (const DerivedType*)this : 0;
  }
  inline const DerivedType *castDerivedTypeAsserting() const {
    assert(isDerivedType());
    return (const DerivedType*)this;
  }

  // Methods for determining the subtype of this Type.  The cast*() methods are
  // equilivent to using dynamic_cast<>... if the cast is successful, this is
  // returned, otherwise you get a null pointer, allowing expressions like this:
  //
  // if (MethodType *MTy = Ty->dyncastMethodType()) { ... }
  //
  // This section also defines a family of isArrayType(), isLabelType(), 
  // etc functions...
  //
  // The family of functions Ty->cast<type>() is used in the same way as the
  // Ty->dyncast<type>() instructions, but they assert the expected type instead
  // of checking it at runtime.
  //
#define HANDLE_PRIM_TYPE(NAME, SIZE)                                      \
  inline bool is##NAME##Type() const { return ID == NAME##TyID; }
#define HANDLE_DERV_TYPE(NAME, CLASS)                                     \
  inline bool is##NAME##Type() const { return ID == NAME##TyID; }         \
  inline const CLASS *dyncast##NAME##Type() const { /*const version */    \
    return is##NAME##Type() ? (const CLASS*)this : 0;                     \
  }                                                                       \
  inline CLASS *dyncast##NAME##Type() {         /* nonconst version */    \
    return is##NAME##Type() ? (CLASS*)this : 0;                           \
  }                                                                       \
  inline const CLASS *cast##NAME##Type() const {    /*const version */    \
    assert(is##NAME##Type() && "Expected TypeTy: " #NAME);                \
    return (const CLASS*)this;                                            \
  }                                                                       \
  inline CLASS *cast##NAME##Type() {            /* nonconst version */    \
    assert(is##NAME##Type() && "Expected TypeTy: " #NAME);                \
    return (CLASS*)this;                                                  \
  }
#include "llvm/Type.def"

private:
  class TypeIterator : public std::bidirectional_iterator<const Type,
		                                          ptrdiff_t> {
    const Type * const Ty;
    unsigned Idx;

    typedef TypeIterator _Self;
  public:
    inline TypeIterator(const Type *ty, unsigned idx) : Ty(ty), Idx(idx) {}
    inline ~TypeIterator() {}
    
    inline bool operator==(const _Self& x) const { return Idx == x.Idx; }
    inline bool operator!=(const _Self& x) const { return !operator==(x); }
    
    inline pointer operator*() const { return Ty->getContainedType(Idx); }
    inline pointer operator->() const { return operator*(); }
    
    inline _Self& operator++() { ++Idx; return *this; } // Preincrement
    inline _Self operator++(int) { // Postincrement
      _Self tmp = *this; ++*this; return tmp; 
    }
    
    inline _Self& operator--() { --Idx; return *this; }  // Predecrement
    inline _Self operator--(int) { // Postdecrement
      _Self tmp = *this; --*this; return tmp;
    }
  };
};

inline Type::TypeIterator Type::subtype_begin() const {
  return TypeIterator(this, 0);
}

inline Type::TypeIterator Type::subtype_end() const {
  return TypeIterator(this, getNumContainedTypes());
}


// Provide specializations of GraphTraits to be able to treat a type as a 
// graph of sub types...

template <> struct GraphTraits<Type*> {
  typedef Type NodeType;
  typedef Type::subtype_iterator ChildIteratorType;

  static inline NodeType *getEntryNode(Type *T) { return T; }
  static inline ChildIteratorType child_begin(NodeType *N) { 
    return N->subtype_begin(); 
  }
  static inline ChildIteratorType child_end(NodeType *N) { 
    return N->subtype_end();
  }
};

template <> struct GraphTraits<const Type*> {
  typedef const Type NodeType;
  typedef Type::subtype_iterator ChildIteratorType;

  static inline NodeType *getEntryNode(const Type *T) { return T; }
  static inline ChildIteratorType child_begin(NodeType *N) { 
    return N->subtype_begin(); 
  }
  static inline ChildIteratorType child_end(NodeType *N) { 
    return N->subtype_end();
  }
};

#endif