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