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