Intel SPMD Program Compiler  1.9.2
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  /** Returns the number of elements stored in memory for the vector.
683  For uniform vectors, this is rounded up so that the number of
684  elements evenly divides the target's native vector width. */
685  int getVectorMemoryCount() const;
686 };
687 
688 
689 /** @brief Representation of a structure holding a number of members.
690  */
691 class StructType : public CollectionType {
692 public:
693  StructType(const std::string &name, const llvm::SmallVector<const Type *, 8> &elts,
694  const llvm::SmallVector<std::string, 8> &eltNames,
695  const llvm::SmallVector<SourcePos, 8> &eltPositions, bool isConst,
696  Variability variability, SourcePos pos);
697 
698  Variability GetVariability() const;
699 
700  bool IsBoolType() const;
701  bool IsFloatType() const;
702  bool IsIntType() const;
703  bool IsUnsignedType() const;
704  bool IsConstType() const;
705  bool IsDefined() const;
706 
707  const Type *GetBaseType() const;
708  const StructType *GetAsVaryingType() const;
709  const StructType *GetAsUniformType() const;
710  const StructType *GetAsUnboundVariabilityType() const;
711  const StructType *GetAsSOAType(int width) const;
712  const StructType *ResolveUnboundVariability(Variability v) const;
713 
714  const StructType *GetAsConstType() const;
715  const StructType *GetAsNonConstType() const;
716 
717  std::string GetString() const;
718  std::string Mangle() const;
719  std::string GetCDeclaration(const std::string &name) const;
720 
721  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
722 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
723  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
724 #else // LLVM 3.7++
725  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
726 #endif
727 
728  /** Returns the type of the structure element with the given name (if any).
729  Returns NULL if there is no such named element. */
730  const Type *GetElementType(const std::string &name) const;
731 
732  /** Returns the type of the i'th structure element. The value of \c i must
733  be between 0 and NumElements()-1. */
734  const Type *GetElementType(int i) const;
735 
736  /** Returns which structure element number (starting from zero) that
737  has the given name. If there is no such element, return -1. */
738  int GetElementNumber(const std::string &name) const;
739 
740  /** Returns the name of the i'th element of the structure. */
741  const std::string &GetElementName(int i) const { return elementNames[i]; }
742 
743  /** Returns the total number of elements in the structure. */
744  int GetElementCount() const { return int(elementTypes.size()); }
745 
746  const SourcePos &GetElementPosition(int i) const { return elementPositions[i]; }
747 
748  /** Returns the name of the structure type. (e.g. struct Foo -> "Foo".) */
749  const std::string &GetStructName() const { return name; }
750  const std::string GetCStructName() const;
751 
752 private:
753  static bool checkIfCanBeSOA(const StructType *st);
754 
755  /*const*/ std::string name;
756  /** The types of the struct elements. Note that we store these with
757  uniform/varying exactly as they were declared in the source file.
758  (In other words, even if this struct has a varying qualifier and
759  thus all of its members are going to be widened out to be varying,
760  we still store any members that were declared as uniform as uniform
761  types in the elementTypes array, converting them to varying as
762  needed in the implementation.) This is so that if we later need to
763  make a uniform version of the struct, we've maintained the original
764  information about the member types.
765  */
766  const llvm::SmallVector<const Type *, 8> elementTypes;
767  const llvm::SmallVector<std::string, 8> elementNames;
768  /** Source file position at which each structure element declaration
769  appeared. */
770  const llvm::SmallVector<SourcePos, 8> elementPositions;
772  const bool isConst;
773  const SourcePos pos;
774 
775  mutable llvm::SmallVector<const Type *, 8> finalElementTypes;
776 
778 };
779 
780 
781 /** Type implementation representing a struct name that has been declared
782  but where the struct members haven't been defined (i.e. "struct Foo;").
783  This class doesn't do much besides serve as a placeholder that other
784  code can use to detect the presence of such as truct.
785  */
786 class UndefinedStructType : public Type {
787 public:
788  UndefinedStructType(const std::string &name, const Variability variability,
789  bool isConst, SourcePos pos);
790 
791  Variability GetVariability() const;
792 
793  bool IsBoolType() const;
794  bool IsFloatType() const;
795  bool IsIntType() const;
796  bool IsUnsignedType() const;
797  bool IsConstType() const;
798 
799  const Type *GetBaseType() const;
800  const UndefinedStructType *GetAsVaryingType() const;
801  const UndefinedStructType *GetAsUniformType() const;
802  const UndefinedStructType *GetAsUnboundVariabilityType() const;
803  const UndefinedStructType *GetAsSOAType(int width) const;
804  const UndefinedStructType *ResolveUnboundVariability(Variability v) const;
805 
806  const UndefinedStructType *GetAsConstType() const;
807  const UndefinedStructType *GetAsNonConstType() const;
808 
809  std::string GetString() const;
810  std::string Mangle() const;
811  std::string GetCDeclaration(const std::string &name) const;
812 
813  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
814 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
815  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
816 #else // LLVM 3.7++
817  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
818 #endif
819 
820  /** Returns the name of the structure type. (e.g. struct Foo -> "Foo".) */
821  const std::string &GetStructName() const { return name; }
822 
823 private:
824  const std::string name;
826  const bool isConst;
827  const SourcePos pos;
828 };
829 
830 
831 /** @brief Type representing a reference to another (non-reference) type.
832  */
833 class ReferenceType : public Type {
834 public:
835  ReferenceType(const Type *targetType);
836 
837  Variability GetVariability() const;
838 
839  bool IsBoolType() const;
840  bool IsFloatType() const;
841  bool IsIntType() const;
842  bool IsUnsignedType() const;
843  bool IsConstType() const;
844 
845  const Type *GetBaseType() const;
846  const Type *GetReferenceTarget() const;
847  const ReferenceType *GetAsVaryingType() const;
848  const ReferenceType *GetAsUniformType() const;
849  const ReferenceType *GetAsUnboundVariabilityType() const;
850  const Type *GetAsSOAType(int width) const;
851  const ReferenceType *ResolveUnboundVariability(Variability v) const;
852 
853  const ReferenceType *GetAsConstType() const;
854  const ReferenceType *GetAsNonConstType() const;
855 
856  std::string GetString() const;
857  std::string Mangle() const;
858  std::string GetCDeclaration(const std::string &name) const;
859 
860  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
861 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
862  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
863 #else // LLVM 3.7++
864  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
865 #endif
866 
867 private:
868  const Type * const targetType;
870 };
871 
872 
873 /** @brief Type representing a function (return type + argument types)
874 
875  FunctionType encapsulates the information related to a function's type,
876  including the return type and the types of the arguments.
877 
878  @todo This class has a fair number of methods inherited from Type that
879  don't make sense here (e.g. IsUniformType(), GetBaseType(), LLVMType(), etc.
880  Would be nice to refactor the inheritance hierarchy to move most of
881  those interface methods to a sub-class of Type, which in turn all of
882  the other Type implementations inherit from.
883  */
884 class FunctionType : public Type {
885 public:
886  FunctionType(const Type *returnType,
887  const llvm::SmallVector<const Type *, 8> &argTypes, SourcePos pos);
888  FunctionType(const Type *returnType,
889  const llvm::SmallVector<const Type *, 8> &argTypes,
890  const llvm::SmallVector<std::string, 8> &argNames,
891  const llvm::SmallVector<Expr *, 8> &argDefaults,
892  const llvm::SmallVector<SourcePos, 8> &argPos,
893  bool isTask, bool isExported, bool isExternC, bool isUnmasked);
894 
895  Variability GetVariability() const;
896 
897  bool IsBoolType() const;
898  bool IsFloatType() const;
899  bool IsIntType() const;
900  bool IsUnsignedType() const;
901  bool IsConstType() const;
902 
903  const Type *GetBaseType() const;
904  const Type *GetAsVaryingType() const;
905  const Type *GetAsUniformType() const;
906  const Type *GetAsUnboundVariabilityType() const;
907  const Type *GetAsSOAType(int width) const;
908  const FunctionType *ResolveUnboundVariability(Variability v) const;
909 
910  const Type *GetAsConstType() const;
911  const Type *GetAsNonConstType() const;
912 
913  std::string GetString() const;
914  std::string Mangle() const;
915  std::string GetCDeclaration(const std::string &fname) const;
916  std::string GetCDeclarationForDispatch(const std::string &fname) const;
917 
918  llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
919 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
920  llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
921 #else // LLVM 3.7++
922  llvm::DIType *GetDIType(llvm::DIScope *scope) const;
923 #endif
924 
925  const Type *GetReturnType() const { return returnType; }
926 
927  const std::string GetReturnTypeString() const;
928 
929  /** This method returns the LLVM FunctionType that corresponds to this
930  function type. The \c disableMask parameter indicates whether the
931  llvm::FunctionType should have the trailing mask parameter, if
932  present, removed from the return function signature. */
933  llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx,
934  bool disableMask = false) const;
935 
936  int GetNumParameters() const { return (int)paramTypes.size(); }
937  const Type *GetParameterType(int i) const;
938  Expr * GetParameterDefault(int i) const;
939  const SourcePos &GetParameterSourcePos(int i) const;
940  const std::string &GetParameterName(int i) const;
941 
942  /** This value is true if the function had a 'task' qualifier in the
943  source program. */
944  const bool isTask;
945 
946  /** This value is true if the function had a 'export' qualifier in the
947  source program. */
948  const bool isExported;
949 
950  /** This value is true if the function was declared as an 'extern "C"'
951  function in the source program. */
952  const bool isExternC;
953 
954  /** Indicates whether the function doesn't take an implicit mask
955  parameter (and thus should start execution with an "all on"
956  mask). */
957  const bool isUnmasked;
958 
959  /** Indicates whether this function has been declared to be safe to run
960  with an all-off mask. */
961  bool isSafe;
962 
963  /** If non-negative, this provides a user-supplied override to the cost
964  function estimate for the function. */
966 
967 private:
968  const Type * const returnType;
969 
970  // The following four vectors should all have the same length (which is
971  // in turn the length returned by GetNumParameters()).
972  const llvm::SmallVector<const Type *, 8> paramTypes;
973  const llvm::SmallVector<std::string, 8> paramNames;
974  /** Default values of the function's arguments. For arguments without
975  default values provided, NULL is stored. */
976  mutable llvm::SmallVector<Expr *, 8> paramDefaults;
977  /** The names provided (if any) with the function arguments in the
978  function's signature. These should only be used for error messages
979  and the like and so not affect testing function types for equality,
980  etc. */
981  const llvm::SmallVector<SourcePos, 8> paramPositions;
982 };
983 
984 
985 /* Efficient dynamic casting of Types. First, we specify a default
986  template function that returns NULL, indicating a failed cast, for
987  arbitrary types. */
988 template <typename T> inline const T *
989 CastType(const Type *type) {
990  return NULL;
991 }
992 
993 
994 /* Now we have template specializaitons for the Types implemented in this
995  file. Each one checks the Type::typeId member and then performs the
996  corresponding static cast if it's safe as per the typeId.
997  */
998 template <> inline const AtomicType *
999 CastType(const Type *type) {
1000  if (type != NULL && type->typeId == ATOMIC_TYPE)
1001  return (const AtomicType *)type;
1002  else
1003  return NULL;
1004 }
1005 
1006 template <> inline const EnumType *
1007 CastType(const Type *type) {
1008  if (type != NULL && type->typeId == ENUM_TYPE)
1009  return (const EnumType *)type;
1010  else
1011  return NULL;
1012 }
1013 
1014 template <> inline const PointerType *
1015 CastType(const Type *type) {
1016  if (type != NULL && type->typeId == POINTER_TYPE)
1017  return (const PointerType *)type;
1018  else
1019  return NULL;
1020 }
1021 
1022 template <> inline const ArrayType *
1023 CastType(const Type *type) {
1024  if (type != NULL && type->typeId == ARRAY_TYPE)
1025  return (const ArrayType *)type;
1026  else
1027  return NULL;
1028 }
1029 
1030 template <> inline const VectorType *
1031 CastType(const Type *type) {
1032  if (type != NULL && type->typeId == VECTOR_TYPE)
1033  return (const VectorType *)type;
1034  else
1035  return NULL;
1036 }
1037 
1038 template <> inline const SequentialType *
1039 CastType(const Type *type) {
1040  // Note that this function must be updated if other sequential type
1041  // implementations are added.
1042  if (type != NULL &&
1043  (type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE))
1044  return (const SequentialType *)type;
1045  else
1046  return NULL;
1047 }
1048 
1049 template <> inline const CollectionType *
1050 CastType(const Type *type) {
1051  // Similarly a new collection type implementation requires updating
1052  // this function.
1053  if (type != NULL &&
1054  (type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE ||
1055  type->typeId == STRUCT_TYPE))
1056  return (const CollectionType *)type;
1057  else
1058  return NULL;
1059 }
1060 
1061 template <> inline const StructType *
1062 CastType(const Type *type) {
1063  if (type != NULL && type->typeId == STRUCT_TYPE)
1064  return (const StructType *)type;
1065  else
1066  return NULL;
1067 }
1068 
1069 template <> inline const UndefinedStructType *
1070 CastType(const Type *type) {
1071  if (type != NULL && type->typeId == UNDEFINED_STRUCT_TYPE)
1072  return (const UndefinedStructType *)type;
1073  else
1074  return NULL;
1075 }
1076 
1077 template <> inline const ReferenceType *
1078 CastType(const Type *type) {
1079  if (type != NULL && type->typeId == REFERENCE_TYPE)
1080  return (const ReferenceType *)type;
1081  else
1082  return NULL;
1083 }
1084 
1085 template <> inline const FunctionType *
1086 CastType(const Type *type) {
1087  if (type != NULL && type->typeId == FUNCTION_TYPE)
1088  return (const FunctionType *)type;
1089  else
1090  return NULL;
1091 }
1092 
1093 
1094 inline bool IsReferenceType(const Type *t) {
1095  return CastType<ReferenceType>(t) != NULL;
1096 }
1097 
1098 
1099 #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:976
bool IsVaryingType() const
Definition: type.h:150
const StructType * oppositeConstStructType
Definition: type.h:777
static const AtomicType * VaryingInt16
Definition: type.h:348
const std::string & GetStructName() const
Definition: type.h:821
const bool isConst
Definition: type.h:826
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:771
Type implementation for pointers to other types.
Definition: type.h:446
const int numElements
Definition: type.h:624
const Variability variability
Definition: type.h:825
const llvm::SmallVector< std::string, 8 > paramNames
Definition: type.h:973
int GetSOAWidth() const
Definition: type.h:160
int costOverride
Definition: type.h:965
Type representing a reference to another (non-reference) type.
Definition: type.h:833
bool IsNumericType() const
Definition: type.h:139
const Type * baseType
Definition: type.h:500
const llvm::SmallVector< std::string, 8 > elementNames
Definition: type.h:767
std::vector< Symbol * > enumerators
Definition: type.h:422
bool IsReferenceType(const Type *t)
Definition: type.h:1094
bool operator!=(const Variability &v) const
Definition: type.h:66
bool IsUniformType() const
Definition: type.h:145
const bool isExternC
Definition: type.h:952
const llvm::SmallVector< SourcePos, 8 > elementPositions
Definition: type.h:770
llvm::SmallVector< const Type *, 8 > finalElementTypes
Definition: type.h:775
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:691
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:755
AtomicType represents basic types like floats, ints, etc.
Definition: type.h:292
const Type *const returnType
Definition: type.h:968
const std::string & GetElementName(int i) const
Definition: type.h:741
const bool isConst
Definition: type.h:498
Representation of a range of positions in a source file.
Definition: ispc.h:136
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:132
bool isConst
Definition: type.h:421
const BasicType basicType
Definition: type.h:344
const Type *const targetType
Definition: type.h:868
static const AtomicType * VaryingInt64
Definition: type.h:354
std::string MangleString() const
Definition: type.cpp:150
const SourcePos pos
Definition: type.h:773
const Type * GetReturnType() const
Definition: type.h:925
const int numElements
Definition: type.h:680
const llvm::SmallVector< const Type *, 8 > elementTypes
Definition: type.h:766
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:981
const T * CastType(const Type *type)
Definition: type.h:989
const std::string & GetStructName() const
Definition: type.h:749
static const AtomicType * VaryingUInt16
Definition: type.h:351
const SourcePos & GetElementPosition(int i) const
Definition: type.h:746
const bool isTask
Definition: type.h:944
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:884
Representation of a program symbol.
Definition: sym.h:63
const llvm::SmallVector< const Type *, 8 > paramTypes
Definition: type.h:972
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:957
const SourcePos pos
Definition: type.h:827
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:824
bool isSafe
Definition: type.h:961
bool operator!=(const VarType &t) const
Definition: type.h:71
const bool isExported
Definition: type.h:948
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:869
static const AtomicType * VaryingUInt32
Definition: type.h:352
int GetNumParameters() const
Definition: type.h:936
static const AtomicType * VaryingFloat
Definition: type.h:353
int GetElementCount() const
Definition: type.h:744
const bool isConst
Definition: type.h:772
One-dimensional array type.
Definition: type.h:555
const Variability variability
Definition: type.h:497