Intel SPMD Program Compiler  1.12.0
type.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2013, Intel Corporation
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15 
16  * Neither the name of Intel Corporation nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /** @file type.h
35  @brief File with declarations for classes related to type representation
36 */
37 
38 #ifndef ISPC_TYPE_H
39 #define ISPC_TYPE_H 1
40 
41 #include "ispc.h"
42 #include "util.h"
43 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
44 #include <llvm/DerivedTypes.h>
45 #include <llvm/Type.h>
46 #else // >= 3.3
47 #include <llvm/IR/DerivedTypes.h>
48 #include <llvm/IR/Type.h>
49 #endif
50 #include <llvm/ADT/SmallVector.h>
51 
52 class ConstExpr;
53 class StructType;
54 
55 /** Types may have uniform, varying, SOA, or unbound variability; this
56  struct is used by Type implementations to record their variability.
57 */
58 struct Variability {
60 
61  Variability(VarType t = Unbound, int w = 0) : type(t), soaWidth(w) {}
62 
63  bool operator==(const Variability &v) const { return v.type == type && v.soaWidth == soaWidth; }
64  bool operator!=(const Variability &v) const { return v.type != type || v.soaWidth != soaWidth; }
65 
66  bool operator==(const VarType &t) const { return type == t; }
67  bool operator!=(const VarType &t) const { return type != t; }
68 
69  std::string GetString() const;
70  std::string MangleString() const;
71 
73  int soaWidth;
74 };
75 
76 /** Enumerant that records each of the types that inherit from the Type
77  baseclass. */
78 enum TypeId {
80  ENUM_TYPE, // 1
82  ARRAY_TYPE, // 3
88 };
89 
90 /** @brief Interface class that defines the type abstraction.
91 
92  Abstract base class that defines the interface that must be implemented
93  for all types in the language.
94  */
95 class Type {
96  public:
97  /** Returns true if the underlying type is boolean. In other words,
98  this is true for individual bools and for short-vectors with
99  underlying bool type, but not for arrays of bools. */
100  virtual bool IsBoolType() const = 0;
101 
102  /** Returns true if the underlying type is float or double. In other
103  words, this is true for individual floats/doubles and for
104  short-vectors of them, but not for arrays of them. */
105  virtual bool IsFloatType() const = 0;
106 
107  /** Returns true if the underlying type is an integer type. In other
108  words, this is true for individual integers and for short-vectors
109  of integer types, but not for arrays of integer types. */
110  virtual bool IsIntType() const = 0;
111 
112  /** Returns true if the underlying type is unsigned. In other words,
113  this is true for unsigned integers and short vectors of unsigned
114  integer types. */
115  virtual bool IsUnsignedType() const = 0;
116 
117  /** Returns true if the underlying type is either a pointer type */
118  bool IsPointerType() const;
119 
120  /** Returns true if the underlying type is a array type */
121  bool IsArrayType() const;
122 
123  /** Returns true if the underlying type is a array type */
124  bool IsReferenceType() const;
125 
126  /** Returns true if the underlying type is either a pointer or an array */
127  bool IsVoidType() const;
128 
129  /** Returns true if this type is 'const'-qualified. */
130  virtual bool IsConstType() const = 0;
131 
132  /** Returns true if the underlying type is a float or integer type. */
133  bool IsNumericType() const { return IsFloatType() || IsIntType(); }
134 
135  /** Returns the variability of the type. */
136  virtual Variability GetVariability() const = 0;
137 
138  /** Returns true if the underlying type is uniform */
139  bool IsUniformType() const { return GetVariability() == Variability::Uniform; }
140 
141  /** Returns true if the underlying type is varying */
142  bool IsVaryingType() const { return GetVariability() == Variability::Varying; }
143 
144  /** Returns true if the type is laid out in "structure of arrays"
145  layout. */
146  bool IsSOAType() const { return GetVariability() == Variability::SOA; }
147 
148  /** Returns the structure of arrays width for SOA types. This method
149  returns zero for types with non-SOA variability. */
150  int GetSOAWidth() const { return GetVariability().soaWidth; }
151 
152  /** Returns true if the underlying type's uniform/varying-ness is
153  unbound. */
154  bool HasUnboundVariability() const { return GetVariability() == Variability::Unbound; }
155 
156  /* Returns a type wherein any elements of the original type and
157  contained types that have unbound variability have their variability
158  set to the given variability. */
159  virtual const Type *ResolveUnboundVariability(Variability v) const = 0;
160 
161  /** Return a "uniform" instance of this type. If the type is already
162  uniform, its "this" pointer will be returned. */
163  virtual const Type *GetAsUniformType() const = 0;
164 
165  /** Return a "varying" instance of this type. If the type is already
166  varying, its "this" pointer will be returned. */
167  virtual const Type *GetAsVaryingType() const = 0;
168 
169  /** Get an instance of the type with unbound variability. */
170  virtual const Type *GetAsUnboundVariabilityType() const = 0;
171 
172  virtual const Type *GetAsSOAType(int width) const = 0;
173 
174  /** If this is a signed integer type, return the unsigned version of
175  the type. Otherwise, return the original type. */
176  virtual const Type *GetAsUnsignedType() const;
177 
178  /** Returns the basic root type of the given type. For example, for an
179  array or short-vector, this returns the element type. For a struct
180  or atomic type, it returns itself. */
181  virtual const Type *GetBaseType() const = 0;
182 
183  /** If this is a reference type, returns the type it is referring to.
184  For all other types, just returns its own type. */
185  virtual const Type *GetReferenceTarget() const;
186 
187  /** Get a const version of this type. If it's already const, then the old
188  Type pointer is returned. */
189  virtual const Type *GetAsConstType() const = 0;
190 
191  /** Get a non-const version of this type. If it's already not const,
192  then the old Type pointer is returned. */
193  virtual const Type *GetAsNonConstType() const = 0;
194 
195  /** Returns a text representation of the type (for example, for use in
196  warning and error messages). */
197  virtual std::string GetString() const = 0;
198 
199  /** Returns a string that represents the mangled type (for use in
200  mangling function symbol names for function overloading). The
201  various Types implementations of this method should collectively
202  ensure that all of them use mangling schemes that are guaranteed
203  not to clash. */
204  virtual std::string Mangle() const = 0;
205 
206  /** Returns a string that is the declaration of the same type in C
207  syntax. */
208  virtual std::string GetCDeclaration(const std::string &name) const = 0;
209 
210  /** Returns the LLVM type corresponding to this ispc type */
211  virtual llvm::Type *LLVMType(llvm::LLVMContext *ctx) const = 0;
212 
213 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
214  /** Returns the DIType (LLVM's debugging information structure),
215  corresponding to this type. */
216  virtual llvm::DIType GetDIType(llvm::DIDescriptor scope) const = 0;
217 #else
218  /** Returns the DIType (LLVM's debugging information structure),
219  corresponding to this type. */
220  virtual llvm::DIType *GetDIType(llvm::DIScope *scope) const = 0;
221 #endif
222 
223  /** Checks two types for equality. Returns true if they are exactly
224  the same, false otherwise. */
225  static bool Equal(const Type *a, const Type *b);
226 
227  /** Checks two types for equality. Returns true if they are exactly
228  the same (ignoring const-ness of the type), false otherwise. */
229  static bool EqualIgnoringConst(const Type *a, const Type *b);
230 
231  /** Given two types, returns the least general Type that is more general
232  than both of them. (i.e. that can represent their values without
233  any loss of data.) If there is no such Type, return NULL.
234 
235  @param type0 First of the two types
236  @param type1 Second of the two types
237  @param pos Source file position where the general type is
238  needed.
239  @param reason String describing the context of why the general
240  type is needed (e.g. "+ operator").
241  @param forceVarying If \c true, then make sure that the returned
242  type is "varying".
243  @param vecSize The vector size of the returned type. If non-zero,
244  the returned type will be a VectorType of the
245  more general type with given length. If zero,
246  this parameter has no effect.
247  @return The more general type, based on the provided parameters.
248 
249  @todo the vecSize and forceVarying parts of this should probably be
250  factored out and done separately in the cases when needed.
251 
252  */
253  static const Type *MoreGeneralType(const Type *type0, const Type *type1, SourcePos pos, const char *reason,
254  bool forceVarying = false, int vecSize = 0);
255 
256  /** Returns true if the given type is an atomic, enum, or pointer type
257  (i.e. not an aggregation of multiple instances of a type or
258  types.) */
259  static bool IsBasicType(const Type *type);
260 
261  /** Indicates which Type implementation this type is. This value can
262  be used to determine the actual type much more efficiently than
263  using dynamic_cast. */
264  const TypeId typeId;
265 
266  protected:
267  Type(TypeId id) : typeId(id) {}
268 };
269 
270 /** @brief AtomicType represents basic types like floats, ints, etc.
271 
272  AtomicTypes can be either uniform or varying. Unique instances of all
273  of the possible <tt>AtomicType</tt>s are available in the static members
274  like AtomicType::UniformInt32. It is thus possible to compare
275  AtomicTypes for equality with simple pointer equality tests; this is
276  not true for the other Type implementations.
277  */
278 class AtomicType : public Type {
279  public:
280  Variability GetVariability() const;
281 
282  bool IsBoolType() const;
283  bool IsFloatType() const;
284  bool IsIntType() const;
285  bool IsUnsignedType() const;
286  bool IsConstType() const;
287 
288  /** For AtomicTypes, the base type is just the same as the AtomicType
289  itself. */
290  const AtomicType *GetBaseType() const;
291  const AtomicType *GetAsUniformType() const;
292  const AtomicType *GetAsVaryingType() const;
293  const AtomicType *GetAsUnboundVariabilityType() const;
294  const AtomicType *GetAsSOAType(int width) const;
295 
296  const AtomicType *ResolveUnboundVariability(Variability v) const;
297  const AtomicType *GetAsUnsignedType() const;
298  const AtomicType *GetAsConstType() const;
299  const AtomicType *GetAsNonConstType() const;
300 
301  std::string GetString() const;
302  std::string Mangle() const;
303  std::string GetCDeclaration(const std::string &name) const;
304 
305  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
306 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
307  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
308 #else // LLVM 3.7++
309  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
310 #endif
311 
312  /** This enumerator records the basic types that AtomicTypes can be
313  built from. */
314  enum BasicType {
327  NUM_BASIC_TYPES
328  };
329 
331 
332  static const AtomicType *UniformBool, *VaryingBool;
333  static const AtomicType *UniformInt8, *VaryingInt8;
334  static const AtomicType *UniformInt16, *VaryingInt16;
335  static const AtomicType *UniformInt32, *VaryingInt32;
336  static const AtomicType *UniformUInt8, *VaryingUInt8;
337  static const AtomicType *UniformUInt16, *VaryingUInt16;
338  static const AtomicType *UniformUInt32, *VaryingUInt32;
339  static const AtomicType *UniformFloat, *VaryingFloat;
340  static const AtomicType *UniformInt64, *VaryingInt64;
341  static const AtomicType *UniformUInt64, *VaryingUInt64;
342  static const AtomicType *UniformDouble, *VaryingDouble;
343  static const AtomicType *Void;
344 
345  private:
347  const bool isConst;
348  AtomicType(BasicType basicType, Variability v, bool isConst);
349 
350  mutable const AtomicType *asOtherConstType, *asUniformType, *asVaryingType;
351 };
352 
353 /** @brief Type implementation for enumerated types
354  */
355 class EnumType : public Type {
356  public:
357  /** Constructor for anonymous enumerated types */
358  EnumType(SourcePos pos);
359  /** Constructor for named enumerated types */
360  EnumType(const char *name, SourcePos pos);
361 
362  Variability GetVariability() const;
363 
364  bool IsBoolType() const;
365  bool IsFloatType() const;
366  bool IsIntType() const;
367  bool IsUnsignedType() const;
368  bool IsConstType() const;
369 
370  const EnumType *GetBaseType() const;
371  const EnumType *GetAsVaryingType() const;
372  const EnumType *GetAsUniformType() const;
373  const EnumType *GetAsUnboundVariabilityType() const;
374  const EnumType *GetAsSOAType(int width) const;
375 
376  const EnumType *ResolveUnboundVariability(Variability v) const;
377  const EnumType *GetAsConstType() const;
378  const EnumType *GetAsNonConstType() const;
379 
380  std::string GetString() const;
381  std::string Mangle() const;
382  std::string GetCDeclaration(const std::string &name) const;
383 
384  /** Returns the name of the enum type. (e.g. struct Foo -> "Foo".) */
385  const std::string &GetEnumName() const { return name; }
386 
387  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
388 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
389  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
390 #else // LLVM 3.7++
391  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
392 #endif
393 
394  /** Provides the enumerators defined in the enum definition. */
395  void SetEnumerators(const std::vector<Symbol *> &enumerators);
396  /** Returns the total number of enuemrators in this enum type. */
397  int GetEnumeratorCount() const;
398  /** Returns the symbol for the given enumerator number. */
399  const Symbol *GetEnumerator(int i) const;
400 
401  const SourcePos pos;
402 
403  private:
404  const std::string name;
406  bool isConst;
407  std::vector<Symbol *> enumerators;
408 };
409 
410 /** @brief Type implementation for pointers to other types
411 
412  Pointers can have two additional properties beyond their variability
413  and the type of object that they are pointing to. Both of these
414  properties are used for internal bookkeeping and aren't directly
415  accessible from the language.
416 
417  - Slice: pointers that point to data with SOA layout have this
418  property--it indicates that the pointer has two components, where the
419  first (major) component is a regular pointer that points to an
420  instance of the soa<> type being indexed, and where the second
421  (minor) component is an integer that indicates which of the soa
422  slices in that instance the pointer points to.
423 
424  - Frozen: only slice pointers may have this property--it indicates that
425  any further indexing calculations should only be applied to the major
426  pointer, and the value of the minor offset should be left unchanged.
427  Pointers to lvalues from structure member access have the frozen
428  property; see discussion in comments in the StructMemberExpr class.
429  */
430 class PointerType : public Type {
431  public:
432  PointerType(const Type *t, Variability v, bool isConst, bool isSlice = false, bool frozen = false);
433 
434  /** Helper method to return a uniform pointer to the given type. */
435  static PointerType *GetUniform(const Type *t, bool isSlice = false);
436  /** Helper method to return a varying pointer to the given type. */
437  static PointerType *GetVarying(const Type *t);
438 
439  /** Returns true if the given type is a void * type. */
440  static bool IsVoidPointer(const Type *t);
441 
442  Variability GetVariability() const;
443 
444  bool IsBoolType() const;
445  bool IsFloatType() const;
446  bool IsIntType() const;
447  bool IsUnsignedType() const;
448  bool IsConstType() const;
449 
450  bool IsSlice() const { return isSlice; }
451  bool IsFrozenSlice() const { return isFrozen; }
452  const PointerType *GetAsSlice() const;
453  const PointerType *GetAsNonSlice() const;
454  const PointerType *GetAsFrozenSlice() const;
455 
456  const Type *GetBaseType() const;
457  const PointerType *GetAsVaryingType() const;
458  const PointerType *GetAsUniformType() const;
459  const PointerType *GetAsUnboundVariabilityType() const;
460  const PointerType *GetAsSOAType(int width) const;
461 
462  const PointerType *ResolveUnboundVariability(Variability v) const;
463  const PointerType *GetAsConstType() const;
464  const PointerType *GetAsNonConstType() const;
465 
466  std::string GetString() const;
467  std::string Mangle() const;
468  std::string GetCDeclaration(const std::string &name) const;
469 
470  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
471 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
472  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
473 #else // LLVM 3.7++
474  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
475 #endif
476 
477  static PointerType *Void;
478 
479  private:
481  const bool isConst;
482  const bool isSlice, isFrozen;
483  const Type *baseType;
484 };
485 
486 /** @brief Abstract base class for types that represent collections of
487  other types.
488 
489  This is a common base class that StructTypes, ArrayTypes, and
490  VectorTypes all inherit from.
491 */
492 class CollectionType : public Type {
493  public:
494  /** Returns the total number of elements in the collection. */
495  virtual int GetElementCount() const = 0;
496 
497  /** Returns the type of the element given by index. (The value of
498  index must be between 0 and GetElementCount()-1.
499  */
500  virtual const Type *GetElementType(int index) const = 0;
501 
502  protected:
504 };
505 
506 /** @brief Abstract base class for types that represent sequences
507 
508  SequentialType is an abstract base class that adds interface routines
509  for types that represent linear sequences of other types (i.e., arrays
510  and vectors).
511  */
513  public:
514  /** Returns the Type of the elements that the sequence stores; for
515  SequentialTypes, all elements have the same type . */
516  virtual const Type *GetElementType() const = 0;
517 
518  /** SequentialType provides an implementation of this CollectionType
519  method, just passing the query on to the GetElementType(void)
520  implementation, since all of the elements of a SequentialType have
521  the same type.
522  */
523  const Type *GetElementType(int index) const;
524 
525  protected:
527 };
528 
529 /** @brief One-dimensional array type.
530 
531  ArrayType represents a one-dimensional array of instances of some other
532  type. (Multi-dimensional arrays are represented by ArrayTypes that in
533  turn hold ArrayTypes as their child types.)
534 */
535 class ArrayType : public SequentialType {
536  public:
537  /** An ArrayType is created by providing the type of the elements that
538  it stores, and the SOA width to use in laying out the array in
539  memory.
540 
541  @param elementType Type of the array elements
542  @param numElements Total number of elements in the array. This
543  parameter may be zero, in which case this is an
544  "unsized" array type. (Arrays of specific size
545  can be converted to unsized arrays to be passed
546  to functions that take array parameters, for
547  example).
548  */
549  ArrayType(const Type *elementType, int numElements);
550 
551  Variability GetVariability() const;
552 
553  bool IsBoolType() const;
554  bool IsFloatType() const;
555  bool IsIntType() const;
556  bool IsUnsignedType() const;
557  bool IsConstType() const;
558 
559  const Type *GetBaseType() const;
560  const ArrayType *GetAsVaryingType() const;
561  const ArrayType *GetAsUniformType() const;
562  const ArrayType *GetAsUnboundVariabilityType() const;
563  const ArrayType *GetAsSOAType(int width) const;
564  const ArrayType *ResolveUnboundVariability(Variability v) const;
565 
566  const ArrayType *GetAsUnsignedType() const;
567  const ArrayType *GetAsConstType() const;
568  const ArrayType *GetAsNonConstType() const;
569 
570  std::string GetString() const;
571  std::string Mangle() const;
572  std::string GetCDeclaration(const std::string &name) const;
573 
574 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
575  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
576 #else // LLVM 3.7++
577  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
578 #endif
579  llvm::ArrayType *LLVMType(llvm::LLVMContext *ctx) const;
580 
581  /** This method returns the total number of elements in the array,
582  including all dimensions if this is a multidimensional array. */
583  int TotalElementCount() const;
584 
585  int GetElementCount() const;
586  const Type *GetElementType() const;
587 
588  /** Returns a new array of the same child type, but with the given
589  length. */
590  virtual ArrayType *GetSizedArray(int length) const;
591 
592  /** If the given type is a (possibly multi-dimensional) array type and
593  the initializer expression is an expression list, set the size of
594  any array dimensions that are unsized according to the number of
595  elements in the corresponding sectoin of the initializer
596  expression.
597  */
598  static const Type *SizeUnsizedArrays(const Type *type, Expr *initExpr);
599 
600  private:
601  /** Type of the elements of the array. */
602  const Type *const child;
603  /** Number of elements in the array. */
604  const int numElements;
605 };
606 
607 /** @brief A (short) vector of atomic types.
608 
609  VectorType is used to represent a fixed-size array of elements of an
610  AtomicType. Vectors are similar to arrays in that they support
611  indexing of the elements, but have two key differences. First, all
612  arithmetic and logical operations that are value for the element type
613  can be performed on corresponding VectorTypes (as long as the two
614  VectorTypes have the same size). Second, VectorTypes of uniform
615  elements are laid out in memory aligned to the target's vector size;
616  this allows them to be packed 'horizontally' into vector registers.
617  */
618 class VectorType : public SequentialType {
619  public:
620  VectorType(const AtomicType *base, int size);
621 
622  Variability GetVariability() const;
623 
624  bool IsBoolType() const;
625  bool IsFloatType() const;
626  bool IsIntType() const;
627  bool IsUnsignedType() const;
628  bool IsConstType() const;
629 
630  const Type *GetBaseType() const;
631  const VectorType *GetAsVaryingType() const;
632  const VectorType *GetAsUniformType() const;
633  const VectorType *GetAsUnboundVariabilityType() const;
634  const VectorType *GetAsSOAType(int width) const;
635  const VectorType *ResolveUnboundVariability(Variability v) const;
636 
637  const VectorType *GetAsUnsignedType() const;
638  const VectorType *GetAsConstType() const;
639  const VectorType *GetAsNonConstType() const;
640 
641  std::string GetString() const;
642  std::string Mangle() const;
643  std::string GetCDeclaration(const std::string &name) const;
644 
645  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
646 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
647  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
648 #else // LLVM 3.7++
649  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
650 #endif
651 
652  int GetElementCount() const;
653  const AtomicType *GetElementType() const;
654 
655  private:
656  /** Base type that the vector holds elements of */
657  const AtomicType *const base;
658  /** Number of elements in the vector */
659  const int numElements;
660 
661  public:
662  /** Returns the number of elements stored in memory for the vector.
663  For uniform vectors, this is rounded up so that the number of
664  elements evenly divides the target's native vector width. */
665  int getVectorMemoryCount() const;
666 };
667 
668 /** @brief Representation of a structure holding a number of members.
669  */
670 class StructType : public CollectionType {
671  public:
672  StructType(const std::string &name, const llvm::SmallVector<const Type *, 8> &elts,
673  const llvm::SmallVector<std::string, 8> &eltNames, const llvm::SmallVector<SourcePos, 8> &eltPositions,
674  bool isConst, Variability variability, SourcePos pos);
675 
676  Variability GetVariability() const;
677 
678  bool IsBoolType() const;
679  bool IsFloatType() const;
680  bool IsIntType() const;
681  bool IsUnsignedType() const;
682  bool IsConstType() const;
683  bool IsDefined() const;
684 
685  const Type *GetBaseType() const;
686  const StructType *GetAsVaryingType() const;
687  const StructType *GetAsUniformType() const;
688  const StructType *GetAsUnboundVariabilityType() const;
689  const StructType *GetAsSOAType(int width) const;
690  const StructType *ResolveUnboundVariability(Variability v) const;
691 
692  const StructType *GetAsConstType() const;
693  const StructType *GetAsNonConstType() const;
694 
695  std::string GetString() const;
696  std::string Mangle() const;
697  std::string GetCDeclaration(const std::string &name) const;
698 
699  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
700 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
701  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
702 #else // LLVM 3.7++
703  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
704 #endif
705 
706  /** Returns the type of the structure element with the given name (if any).
707  Returns NULL if there is no such named element. */
708  const Type *GetElementType(const std::string &name) const;
709 
710  /** Returns the type of the i'th structure element. The value of \c i must
711  be between 0 and NumElements()-1. */
712  const Type *GetElementType(int i) const;
713 
714  /** Returns which structure element number (starting from zero) that
715  has the given name. If there is no such element, return -1. */
716  int GetElementNumber(const std::string &name) const;
717 
718  /** Returns the name of the i'th element of the structure. */
719  const std::string &GetElementName(int i) const { return elementNames[i]; }
720 
721  /** Returns the total number of elements in the structure. */
722  int GetElementCount() const { return int(elementTypes.size()); }
723 
724  const SourcePos &GetElementPosition(int i) const { return elementPositions[i]; }
725 
726  /** Returns the name of the structure type. (e.g. struct Foo -> "Foo".) */
727  const std::string &GetStructName() const { return name; }
728  const std::string GetCStructName() const;
729 
730  private:
731  static bool checkIfCanBeSOA(const StructType *st);
732 
733  /*const*/ std::string name;
734  /** The types of the struct elements. Note that we store these with
735  uniform/varying exactly as they were declared in the source file.
736  (In other words, even if this struct has a varying qualifier and
737  thus all of its members are going to be widened out to be varying,
738  we still store any members that were declared as uniform as uniform
739  types in the elementTypes array, converting them to varying as
740  needed in the implementation.) This is so that if we later need to
741  make a uniform version of the struct, we've maintained the original
742  information about the member types.
743  */
744  const llvm::SmallVector<const Type *, 8> elementTypes;
745  const llvm::SmallVector<std::string, 8> elementNames;
746  /** Source file position at which each structure element declaration
747  appeared. */
748  const llvm::SmallVector<SourcePos, 8> elementPositions;
750  const bool isConst;
751  const SourcePos pos;
752 
753  mutable llvm::SmallVector<const Type *, 8> finalElementTypes;
754 
756 };
757 
758 /** Type implementation representing a struct name that has been declared
759  but where the struct members haven't been defined (i.e. "struct Foo;").
760  This class doesn't do much besides serve as a placeholder that other
761  code can use to detect the presence of such as truct.
762  */
763 class UndefinedStructType : public Type {
764  public:
765  UndefinedStructType(const std::string &name, const Variability variability, bool isConst, SourcePos pos);
766 
767  Variability GetVariability() const;
768 
769  bool IsBoolType() const;
770  bool IsFloatType() const;
771  bool IsIntType() const;
772  bool IsUnsignedType() const;
773  bool IsConstType() const;
774 
775  const Type *GetBaseType() const;
776  const UndefinedStructType *GetAsVaryingType() const;
777  const UndefinedStructType *GetAsUniformType() const;
778  const UndefinedStructType *GetAsUnboundVariabilityType() const;
779  const UndefinedStructType *GetAsSOAType(int width) const;
780  const UndefinedStructType *ResolveUnboundVariability(Variability v) const;
781 
782  const UndefinedStructType *GetAsConstType() const;
783  const UndefinedStructType *GetAsNonConstType() const;
784 
785  std::string GetString() const;
786  std::string Mangle() const;
787  std::string GetCDeclaration(const std::string &name) const;
788 
789  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
790 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
791  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
792 #else // LLVM 3.7++
793  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
794 #endif
795 
796  /** Returns the name of the structure type. (e.g. struct Foo -> "Foo".) */
797  const std::string &GetStructName() const { return name; }
798 
799  private:
800  const std::string name;
802  const bool isConst;
803  const SourcePos pos;
804 };
805 
806 /** @brief Type representing a reference to another (non-reference) type.
807  */
808 class ReferenceType : public Type {
809  public:
810  ReferenceType(const Type *targetType);
811 
812  Variability GetVariability() const;
813 
814  bool IsBoolType() const;
815  bool IsFloatType() const;
816  bool IsIntType() const;
817  bool IsUnsignedType() const;
818  bool IsConstType() const;
819 
820  const Type *GetBaseType() const;
821  const Type *GetReferenceTarget() const;
822  const ReferenceType *GetAsVaryingType() const;
823  const ReferenceType *GetAsUniformType() const;
824  const ReferenceType *GetAsUnboundVariabilityType() const;
825  const Type *GetAsSOAType(int width) const;
826  const ReferenceType *ResolveUnboundVariability(Variability v) const;
827 
828  const ReferenceType *GetAsConstType() const;
829  const ReferenceType *GetAsNonConstType() const;
830 
831  std::string GetString() const;
832  std::string Mangle() const;
833  std::string GetCDeclaration(const std::string &name) const;
834 
835  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
836 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
837  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
838 #else // LLVM 3.7++
839  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
840 #endif
841 
842  private:
843  const Type *const targetType;
845 };
846 
847 /** @brief Type representing a function (return type + argument types)
848 
849  FunctionType encapsulates the information related to a function's type,
850  including the return type and the types of the arguments.
851 
852  @todo This class has a fair number of methods inherited from Type that
853  don't make sense here (e.g. IsUniformType(), GetBaseType(), LLVMType(), etc.
854  Would be nice to refactor the inheritance hierarchy to move most of
855  those interface methods to a sub-class of Type, which in turn all of
856  the other Type implementations inherit from.
857  */
858 class FunctionType : public Type {
859  public:
860  FunctionType(const Type *returnType, const llvm::SmallVector<const Type *, 8> &argTypes, SourcePos pos);
861  FunctionType(const Type *returnType, const llvm::SmallVector<const Type *, 8> &argTypes,
862  const llvm::SmallVector<std::string, 8> &argNames, const llvm::SmallVector<Expr *, 8> &argDefaults,
863  const llvm::SmallVector<SourcePos, 8> &argPos, bool isTask, bool isExported, bool isExternC,
864  bool isUnmasked);
865 
866  Variability GetVariability() const;
867 
868  bool IsBoolType() const;
869  bool IsFloatType() const;
870  bool IsIntType() const;
871  bool IsUnsignedType() const;
872  bool IsConstType() const;
873 
874  const Type *GetBaseType() const;
875  const Type *GetAsVaryingType() const;
876  const Type *GetAsUniformType() const;
877  const Type *GetAsUnboundVariabilityType() const;
878  const Type *GetAsSOAType(int width) const;
879  const FunctionType *ResolveUnboundVariability(Variability v) const;
880 
881  const Type *GetAsConstType() const;
882  const Type *GetAsNonConstType() const;
883 
884  std::string GetString() const;
885  std::string Mangle() const;
886  std::string GetCDeclaration(const std::string &fname) const;
887  std::string GetCDeclarationForDispatch(const std::string &fname) const;
888 
889  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
890 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
891  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
892 #else // LLVM 3.7++
893  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
894 #endif
895 
896  const Type *GetReturnType() const { return returnType; }
897 
898  const std::string GetReturnTypeString() const;
899 
900  /** This method returns the LLVM FunctionType that corresponds to this
901  function type. The \c disableMask parameter indicates whether the
902  llvm::FunctionType should have the trailing mask parameter, if
903  present, removed from the return function signature. */
904  llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx, bool disableMask = false) const;
905 
906  int GetNumParameters() const { return (int)paramTypes.size(); }
907  const Type *GetParameterType(int i) const;
908  Expr *GetParameterDefault(int i) const;
909  const SourcePos &GetParameterSourcePos(int i) const;
910  const std::string &GetParameterName(int i) const;
911 
912  /** This value is true if the function had a 'task' qualifier in the
913  source program. */
914  const bool isTask;
915 
916  /** This value is true if the function had a 'export' qualifier in the
917  source program. */
918  const bool isExported;
919 
920  /** This value is true if the function was declared as an 'extern "C"'
921  function in the source program. */
922  const bool isExternC;
923 
924  /** Indicates whether the function doesn't take an implicit mask
925  parameter (and thus should start execution with an "all on"
926  mask). */
927  const bool isUnmasked;
928 
929  /** Indicates whether this function has been declared to be safe to run
930  with an all-off mask. */
931  bool isSafe;
932 
933  /** If non-negative, this provides a user-supplied override to the cost
934  function estimate for the function. */
936 
937  private:
938  const Type *const returnType;
939 
940  // The following four vectors should all have the same length (which is
941  // in turn the length returned by GetNumParameters()).
942  const llvm::SmallVector<const Type *, 8> paramTypes;
943  const llvm::SmallVector<std::string, 8> paramNames;
944  /** Default values of the function's arguments. For arguments without
945  default values provided, NULL is stored. */
946  mutable llvm::SmallVector<Expr *, 8> paramDefaults;
947  /** The names provided (if any) with the function arguments in the
948  function's signature. These should only be used for error messages
949  and the like and so not affect testing function types for equality,
950  etc. */
951  const llvm::SmallVector<SourcePos, 8> paramPositions;
952 };
953 
954 /* Efficient dynamic casting of Types. First, we specify a default
955  template function that returns NULL, indicating a failed cast, for
956  arbitrary types. */
957 template <typename T> inline const T *CastType(const Type *type) { return NULL; }
958 
959 /* Now we have template specializaitons for the Types implemented in this
960  file. Each one checks the Type::typeId member and then performs the
961  corresponding static cast if it's safe as per the typeId.
962  */
963 template <> inline const AtomicType *CastType(const Type *type) {
964  if (type != NULL && type->typeId == ATOMIC_TYPE)
965  return (const AtomicType *)type;
966  else
967  return NULL;
968 }
969 
970 template <> inline const EnumType *CastType(const Type *type) {
971  if (type != NULL && type->typeId == ENUM_TYPE)
972  return (const EnumType *)type;
973  else
974  return NULL;
975 }
976 
977 template <> inline const PointerType *CastType(const Type *type) {
978  if (type != NULL && type->typeId == POINTER_TYPE)
979  return (const PointerType *)type;
980  else
981  return NULL;
982 }
983 
984 template <> inline const ArrayType *CastType(const Type *type) {
985  if (type != NULL && type->typeId == ARRAY_TYPE)
986  return (const ArrayType *)type;
987  else
988  return NULL;
989 }
990 
991 template <> inline const VectorType *CastType(const Type *type) {
992  if (type != NULL && type->typeId == VECTOR_TYPE)
993  return (const VectorType *)type;
994  else
995  return NULL;
996 }
997 
998 template <> inline const SequentialType *CastType(const Type *type) {
999  // Note that this function must be updated if other sequential type
1000  // implementations are added.
1001  if (type != NULL && (type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE))
1002  return (const SequentialType *)type;
1003  else
1004  return NULL;
1005 }
1006 
1007 template <> inline const CollectionType *CastType(const Type *type) {
1008  // Similarly a new collection type implementation requires updating
1009  // this function.
1010  if (type != NULL && (type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE || type->typeId == STRUCT_TYPE))
1011  return (const CollectionType *)type;
1012  else
1013  return NULL;
1014 }
1015 
1016 template <> inline const StructType *CastType(const Type *type) {
1017  if (type != NULL && type->typeId == STRUCT_TYPE)
1018  return (const StructType *)type;
1019  else
1020  return NULL;
1021 }
1022 
1023 template <> inline const UndefinedStructType *CastType(const Type *type) {
1024  if (type != NULL && type->typeId == UNDEFINED_STRUCT_TYPE)
1025  return (const UndefinedStructType *)type;
1026  else
1027  return NULL;
1028 }
1029 
1030 template <> inline const ReferenceType *CastType(const Type *type) {
1031  if (type != NULL && type->typeId == REFERENCE_TYPE)
1032  return (const ReferenceType *)type;
1033  else
1034  return NULL;
1035 }
1036 
1037 template <> inline const FunctionType *CastType(const Type *type) {
1038  if (type != NULL && type->typeId == FUNCTION_TYPE)
1039  return (const FunctionType *)type;
1040  else
1041  return NULL;
1042 }
1043 
1044 inline bool IsReferenceType(const Type *t) { return CastType<ReferenceType>(t) != NULL; }
1045 
1046 #endif // ISPC_TYPE_H
static const AtomicType * VaryingInt32
Definition: type.h:335
llvm::SmallVector< Expr *, 8 > paramDefaults
Definition: type.h:946
bool operator!=(const VarType &t) const
Definition: type.h:67
const StructType * oppositeConstStructType
Definition: type.h:755
static const AtomicType * VaryingInt16
Definition: type.h:334
bool IsUniformType() const
Definition: type.h:139
bool operator!=(const Variability &v) const
Definition: type.h:64
const bool isConst
Definition: type.h:802
const Type * GetReturnType() const
Definition: type.h:896
static const AtomicType * VaryingUInt64
Definition: type.h:341
bool IsVaryingType() const
Definition: type.h:142
const bool isConst
Definition: type.h:347
bool IsSOAType() const
Definition: type.h:146
static PointerType * Void
Definition: type.h:477
bool IsFrozenSlice() const
Definition: type.h:451
std::string GetString() const
Definition: type.cpp:128
Type(TypeId id)
Definition: type.h:267
int GetSOAWidth() const
Definition: type.h:150
static const AtomicType * VaryingDouble
Definition: type.h:342
Expression representing a compile-time constant value.
Definition: expr.h:362
Abstract base class for types that represent sequences.
Definition: type.h:512
TypeId
Definition: type.h:78
const std::string & GetStructName() const
Definition: type.h:727
Variability variability
Definition: type.h:405
const std::string name
Definition: type.h:404
const std::string & GetStructName() const
Definition: type.h:797
int soaWidth
Definition: type.h:73
int GetNumParameters() const
Definition: type.h:906
const Variability variability
Definition: type.h:749
bool operator==(const Variability &v) const
Definition: type.h:63
Type implementation for pointers to other types.
Definition: type.h:430
const int numElements
Definition: type.h:604
const Variability variability
Definition: type.h:801
const llvm::SmallVector< std::string, 8 > paramNames
Definition: type.h:943
std::string MangleString() const
Definition: type.cpp:147
int costOverride
Definition: type.h:935
Type representing a reference to another (non-reference) type.
Definition: type.h:808
const std::string & GetEnumName() const
Definition: type.h:385
const Type * baseType
Definition: type.h:483
const llvm::SmallVector< std::string, 8 > elementNames
Definition: type.h:745
std::vector< Symbol * > enumerators
Definition: type.h:407
bool IsReferenceType(const Type *t)
Definition: type.h:1044
const SourcePos & GetElementPosition(int i) const
Definition: type.h:724
bool IsSlice() const
Definition: type.h:450
const bool isExternC
Definition: type.h:922
const llvm::SmallVector< SourcePos, 8 > elementPositions
Definition: type.h:748
llvm::SmallVector< const Type *, 8 > finalElementTypes
Definition: type.h:753
Definition: type.h:80
const SourcePos pos
Definition: type.h:401
Representation of a structure holding a number of members.
Definition: type.h:670
const std::string & GetElementName(int i) const
Definition: type.h:719
const AtomicType *const base
Definition: type.h:657
const AtomicType * asVaryingType
Definition: type.h:350
CollectionType(TypeId id)
Definition: type.h:503
std::string name
Definition: type.h:733
AtomicType represents basic types like floats, ints, etc.
Definition: type.h:278
const Type *const returnType
Definition: type.h:938
const bool isConst
Definition: type.h:481
Representation of a range of positions in a source file.
Definition: ispc.h:131
SequentialType(TypeId id)
Definition: type.h:526
Type implementation for enumerated types.
Definition: type.h:355
static const AtomicType * VaryingBool
Definition: type.h:332
Abstract base class for types that represent collections of other types.
Definition: type.h:492
int GetElementCount() const
Definition: type.h:722
bool isConst
Definition: type.h:406
const BasicType basicType
Definition: type.h:330
const Type *const targetType
Definition: type.h:843
static const AtomicType * VaryingInt64
Definition: type.h:340
const SourcePos pos
Definition: type.h:751
const int numElements
Definition: type.h:659
const llvm::SmallVector< const Type *, 8 > elementTypes
Definition: type.h:744
const Variability variability
Definition: type.h:346
A (short) vector of atomic types.
Definition: type.h:618
const bool isSlice
Definition: type.h:482
const llvm::SmallVector< SourcePos, 8 > paramPositions
Definition: type.h:951
const T * CastType(const Type *type)
Definition: type.h:957
static const AtomicType * VaryingUInt16
Definition: type.h:337
const bool isTask
Definition: type.h:914
const Type *const child
Definition: type.h:602
static const AtomicType * VaryingInt8
Definition: type.h:333
BasicType
Definition: type.h:314
Type representing a function (return type + argument types)
Definition: type.h:858
Representation of a program symbol.
Definition: sym.h:63
const llvm::SmallVector< const Type *, 8 > paramTypes
Definition: type.h:942
Variability(VarType t=Unbound, int w=0)
Definition: type.h:61
Interface class that defines the type abstraction.
Definition: type.h:95
static const AtomicType * Void
Definition: type.h:343
const bool isUnmasked
Definition: type.h:927
const SourcePos pos
Definition: type.h:803
Expr is the abstract base class that defines the interface that all expression types must implement...
Definition: expr.h:48
VarType type
Definition: type.h:72
const std::string name
Definition: type.h:800
bool isSafe
Definition: type.h:931
const bool isExported
Definition: type.h:918
static const AtomicType * VaryingUInt8
Definition: type.h:336
const TypeId typeId
Definition: type.h:264
Main ispc.header file. Defines Target, Globals and Opt classes.
const ReferenceType * asOtherConstType
Definition: type.h:844
bool IsNumericType() const
Definition: type.h:133
static const AtomicType * VaryingUInt32
Definition: type.h:338
static const AtomicType * VaryingFloat
Definition: type.h:339
bool operator==(const VarType &t) const
Definition: type.h:66
bool HasUnboundVariability() const
Definition: type.h:154
const bool isConst
Definition: type.h:750
One-dimensional array type.
Definition: type.h:535
const Variability variability
Definition: type.h:480