Intel SPMD Program Compiler  1.3.0
type.h
Go to the documentation of this file.
00001 /*
00002   Copyright (c) 2010-2012, Intel Corporation
00003   All rights reserved.
00004 
00005   Redistribution and use in source and binary forms, with or without
00006   modification, are permitted provided that the following conditions are
00007   met:
00008 
00009     * Redistributions of source code must retain the above copyright
00010       notice, this list of conditions and the following disclaimer.
00011 
00012     * Redistributions in binary form must reproduce the above copyright
00013       notice, this list of conditions and the following disclaimer in the
00014       documentation and/or other materials provided with the distribution.
00015 
00016     * Neither the name of Intel Corporation nor the names of its
00017       contributors may be used to endorse or promote products derived from
00018       this software without specific prior written permission.
00019 
00020 
00021    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00022    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00023    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00024    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00025    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00026    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00027    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
00032 */
00033 
00034 /** @file type.h
00035     @brief File with declarations for classes related to type representation
00036 */
00037 
00038 #ifndef ISPC_TYPE_H
00039 #define ISPC_TYPE_H 1
00040 
00041 #include "ispc.h"
00042 #include "util.h"
00043 #include <llvm/Type.h>
00044 #include <llvm/DerivedTypes.h>
00045 #include <llvm/ADT/SmallVector.h>
00046 
00047 class ConstExpr;
00048 class StructType;
00049 
00050 /** Types may have uniform, varying, SOA, or unbound variability; this
00051     struct is used by Type implementations to record their variability. 
00052 */
00053 struct Variability {
00054     enum VarType { Unbound, Uniform, Varying, SOA };
00055 
00056     Variability(VarType t = Unbound, int w = 0) : type(t), soaWidth(w) { }
00057 
00058     bool operator==(const Variability &v) const { 
00059         return v.type == type && v.soaWidth == soaWidth; 
00060     }
00061     bool operator!=(const Variability &v) const { 
00062         return v.type != type || v.soaWidth != soaWidth;
00063     }
00064 
00065     bool operator==(const VarType &t) const { return type == t; }
00066     bool operator!=(const VarType &t) const { return type != t; }
00067 
00068     std::string GetString() const;
00069     std::string MangleString() const;
00070     
00071     VarType type;
00072     int soaWidth;
00073 };
00074 
00075 
00076 /** Enumerant that records each of the types that inherit from the Type
00077     baseclass. */
00078 enum TypeId {
00079     ATOMIC_TYPE,
00080     ENUM_TYPE,
00081     POINTER_TYPE,
00082     ARRAY_TYPE,
00083     VECTOR_TYPE,
00084     STRUCT_TYPE,
00085     UNDEFINED_STRUCT_TYPE,
00086     REFERENCE_TYPE,
00087     FUNCTION_TYPE
00088 };
00089 
00090 
00091 /** @brief Interface class that defines the type abstraction.
00092 
00093     Abstract base class that defines the interface that must be implemented
00094     for all types in the language.
00095  */
00096 class Type {
00097 public:
00098     /** Returns true if the underlying type is boolean.  In other words,
00099         this is true for individual bools and for short-vectors with
00100         underlying bool type, but not for arrays of bools. */
00101     virtual bool IsBoolType() const = 0;
00102 
00103     /** Returns true if the underlying type is float or double.  In other
00104         words, this is true for individual floats/doubles and for
00105         short-vectors of them, but not for arrays of them. */
00106     virtual bool IsFloatType() const = 0;
00107 
00108     /** Returns true if the underlying type is an integer type.  In other
00109         words, this is true for individual integers and for short-vectors
00110         of integer types, but not for arrays of integer types. */
00111     virtual bool IsIntType() const = 0;
00112 
00113     /** Returns true if the underlying type is unsigned.  In other words,
00114         this is true for unsigned integers and short vectors of unsigned
00115         integer types. */
00116     virtual bool IsUnsignedType() const = 0;
00117 
00118     /** Returns true if the underlying type is either a pointer type */
00119     bool IsPointerType() const;
00120   
00121     /** Returns true if the underlying type is a array type */
00122     bool IsArrayType() const;
00123   
00124     /** Returns true if the underlying type is a array type */
00125     bool IsReferenceType() const;
00126   
00127     /** Returns true if the underlying type is either a pointer or an array */
00128     bool IsVoidType() const;
00129 
00130     /** Returns true if this type is 'const'-qualified. */
00131     virtual bool IsConstType() const = 0;
00132     
00133     /** Returns true if the underlying type is a float or integer type. */
00134     bool IsNumericType() const { return IsFloatType() || IsIntType(); }
00135 
00136     /** Returns the variability of the type. */
00137     virtual Variability GetVariability() const = 0;
00138 
00139     /** Returns true if the underlying type is uniform */
00140     bool IsUniformType() const { 
00141         return GetVariability() == Variability::Uniform; 
00142     }
00143 
00144     /** Returns true if the underlying type is varying */
00145     bool IsVaryingType() const { 
00146         return GetVariability() == Variability::Varying; 
00147     }
00148 
00149     /** Returns true if the type is laid out in "structure of arrays"
00150         layout. */
00151     bool IsSOAType() const { return GetVariability() == Variability::SOA; }
00152 
00153     /** Returns the structure of arrays width for SOA types.  This method
00154         returns zero for types with non-SOA variability. */
00155     int GetSOAWidth() const { return GetVariability().soaWidth; }
00156 
00157     /** Returns true if the underlying type's uniform/varying-ness is
00158         unbound. */
00159     bool HasUnboundVariability() const { 
00160         return GetVariability() == Variability::Unbound; 
00161     }
00162 
00163     /* Returns a type wherein any elements of the original type and
00164        contained types that have unbound variability have their variability
00165        set to the given variability. */
00166     virtual const Type *ResolveUnboundVariability(Variability v) const = 0;
00167 
00168     /** Return a "uniform" instance of this type.  If the type is already
00169         uniform, its "this" pointer will be returned. */
00170     virtual const Type *GetAsUniformType() const = 0;
00171 
00172     /** Return a "varying" instance of this type.  If the type is already
00173         varying, its "this" pointer will be returned. */
00174     virtual const Type *GetAsVaryingType() const = 0;
00175 
00176     /** Get an instance of the type with unbound variability. */
00177     virtual const Type *GetAsUnboundVariabilityType() const = 0;
00178 
00179     virtual const Type *GetAsSOAType(int width) const = 0;
00180 
00181     /** If this is a signed integer type, return the unsigned version of
00182         the type.  Otherwise, return the original type. */
00183     virtual const Type *GetAsUnsignedType() const;
00184 
00185     /** Returns the basic root type of the given type.  For example, for an
00186         array or short-vector, this returns the element type.  For a struct
00187         or atomic type, it returns itself. */
00188     virtual const Type *GetBaseType() const = 0;
00189 
00190     /** If this is a reference type, returns the type it is referring to.
00191         For all other types, just returns its own type. */
00192     virtual const Type *GetReferenceTarget() const;
00193 
00194     /** Get a const version of this type.  If it's already const, then the old 
00195         Type pointer is returned. */
00196     virtual const Type *GetAsConstType() const = 0;
00197 
00198     /** Get a non-const version of this type.  If it's already not const,
00199         then the old Type pointer is returned. */
00200     virtual const Type *GetAsNonConstType() const = 0;
00201 
00202     /** Returns a text representation of the type (for example, for use in
00203         warning and error messages). */
00204     virtual std::string GetString() const = 0;
00205 
00206     /** Returns a string that represents the mangled type (for use in
00207         mangling function symbol names for function overloading).  The
00208         various Types implementations of this method should collectively
00209         ensure that all of them use mangling schemes that are guaranteed
00210         not to clash. */
00211     virtual std::string Mangle() const = 0;
00212 
00213     /** Returns a string that is the declaration of the same type in C
00214         syntax. */
00215     virtual std::string GetCDeclaration(const std::string &name) const = 0;
00216 
00217     /** Returns the LLVM type corresponding to this ispc type */
00218     virtual llvm::Type *LLVMType(llvm::LLVMContext *ctx) const = 0;
00219 
00220     /** Returns the DIType (LLVM's debugging information structure),
00221         corresponding to this type. */
00222     virtual llvm::DIType GetDIType(llvm::DIDescriptor scope) const = 0;
00223 
00224     /** Checks two types for equality.  Returns true if they are exactly
00225         the same, false otherwise. */
00226     static bool Equal(const Type *a, const Type *b);
00227 
00228     /** Checks two types for equality.  Returns true if they are exactly
00229         the same (ignoring const-ness of the type), false otherwise. */
00230     static bool EqualIgnoringConst(const Type *a, const Type *b);
00231 
00232     /** Given two types, returns the least general Type that is more general
00233         than both of them.  (i.e. that can represent their values without
00234         any loss of data.)  If there is no such Type, return NULL.
00235 
00236         @param type0        First of the two types
00237         @param type1        Second of the two types
00238         @param pos          Source file position where the general type is
00239                             needed.
00240         @param reason       String describing the context of why the general
00241                             type is needed (e.g. "+ operator").
00242         @param forceVarying If \c true, then make sure that the returned 
00243                             type is "varying".
00244         @param vecSize      The vector size of the returned type.  If non-zero,
00245                             the returned type will be a VectorType of the
00246                             more general type with given length.  If zero,
00247                             this parameter has no effect.
00248         @return             The more general type, based on the provided parameters.
00249 
00250         @todo the vecSize and forceVarying parts of this should probably be
00251         factored out and done separately in the cases when needed.
00252         
00253     */
00254     static const Type *MoreGeneralType(const Type *type0, const Type *type1,
00255                                        SourcePos pos, const char *reason,
00256                                        bool forceVarying = false, int vecSize = 0);
00257 
00258     /** Returns true if the given type is an atomic, enum, or pointer type
00259         (i.e. not an aggregation of multiple instances of a type or
00260         types.) */
00261     static bool IsBasicType(const Type *type);
00262 
00263     /** Indicates which Type implementation this type is.  This value can
00264         be used to determine the actual type much more efficiently than
00265         using dynamic_cast. */
00266     const TypeId typeId;
00267 
00268 protected:
00269     Type(TypeId id) : typeId(id) { }
00270 };
00271 
00272 
00273 /** @brief AtomicType represents basic types like floats, ints, etc.  
00274 
00275     AtomicTypes can be either uniform or varying.  Unique instances of all
00276     of the possible <tt>AtomicType</tt>s are available in the static members
00277     like AtomicType::UniformInt32.  It is thus possible to compare
00278     AtomicTypes for equality with simple pointer equality tests; this is
00279     not true for the other Type implementations.
00280  */
00281 class AtomicType : public Type {
00282 public:
00283     Variability GetVariability() const;
00284 
00285     bool IsBoolType() const;
00286     bool IsFloatType() const;
00287     bool IsIntType() const;
00288     bool IsUnsignedType() const;
00289     bool IsConstType() const;
00290 
00291     /** For AtomicTypes, the base type is just the same as the AtomicType
00292         itself. */
00293     const AtomicType *GetBaseType() const;
00294     const AtomicType *GetAsUniformType() const;
00295     const AtomicType *GetAsVaryingType() const;
00296     const AtomicType *GetAsUnboundVariabilityType() const;
00297     const AtomicType *GetAsSOAType(int width) const;
00298 
00299     const AtomicType *ResolveUnboundVariability(Variability v) const;
00300     const AtomicType *GetAsUnsignedType() const;
00301     const AtomicType *GetAsConstType() const;
00302     const AtomicType *GetAsNonConstType() const;
00303 
00304     std::string GetString() const;
00305     std::string Mangle() const;
00306     std::string GetCDeclaration(const std::string &name) const;
00307 
00308     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00309     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00310 
00311     /** This enumerator records the basic types that AtomicTypes can be 
00312         built from.  */
00313     enum BasicType {
00314         TYPE_VOID,
00315         TYPE_BOOL,
00316         TYPE_INT8,
00317         TYPE_UINT8,
00318         TYPE_INT16,
00319         TYPE_UINT16,
00320         TYPE_INT32,
00321         TYPE_UINT32,
00322         TYPE_FLOAT,
00323         TYPE_INT64,
00324         TYPE_UINT64,
00325         TYPE_DOUBLE,
00326         NUM_BASIC_TYPES
00327     };
00328 
00329     const BasicType basicType;
00330 
00331     static const AtomicType *UniformBool, *VaryingBool;
00332     static const AtomicType *UniformInt8, *VaryingInt8;
00333     static const AtomicType *UniformInt16, *VaryingInt16;
00334     static const AtomicType *UniformInt32, *VaryingInt32;
00335     static const AtomicType *UniformUInt8, *VaryingUInt8;
00336     static const AtomicType *UniformUInt16, *VaryingUInt16;
00337     static const AtomicType *UniformUInt32, *VaryingUInt32;
00338     static const AtomicType *UniformFloat, *VaryingFloat;
00339     static const AtomicType *UniformInt64, *VaryingInt64;
00340     static const AtomicType *UniformUInt64, *VaryingUInt64;
00341     static const AtomicType *UniformDouble, *VaryingDouble;
00342     static const AtomicType *Void;
00343 
00344 private:
00345     const Variability variability;
00346     const bool isConst;
00347     AtomicType(BasicType basicType, Variability v, bool isConst);
00348 
00349     mutable const AtomicType *asOtherConstType, *asUniformType, *asVaryingType;
00350 };
00351 
00352 
00353 /** @brief Type implementation for enumerated types
00354  */
00355 class EnumType : public Type {
00356 public:
00357     /** Constructor for anonymous enumerated types */
00358     EnumType(SourcePos pos);
00359     /** Constructor for named enumerated types */
00360     EnumType(const char *name, SourcePos pos);
00361 
00362     Variability GetVariability() const;
00363 
00364     bool IsBoolType() const;
00365     bool IsFloatType() const;
00366     bool IsIntType() const;
00367     bool IsUnsignedType() const;
00368     bool IsConstType() const;
00369 
00370     const EnumType *GetBaseType() const;
00371     const EnumType *GetAsVaryingType() const;
00372     const EnumType *GetAsUniformType() const;
00373     const EnumType *GetAsUnboundVariabilityType() const;
00374     const EnumType *GetAsSOAType(int width) const;
00375 
00376     const EnumType *ResolveUnboundVariability(Variability v) const;
00377     const EnumType *GetAsConstType() const;
00378     const EnumType *GetAsNonConstType() const;
00379 
00380     std::string GetString() const;
00381     std::string Mangle() const;
00382     std::string GetCDeclaration(const std::string &name) const;
00383 
00384     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00385     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00386 
00387     /** Provides the enumerators defined in the enum definition. */
00388     void SetEnumerators(const std::vector<Symbol *> &enumerators);
00389     /** Returns the total number of enuemrators in this enum type. */
00390     int GetEnumeratorCount() const;
00391     /** Returns the symbol for the given enumerator number. */
00392     const Symbol *GetEnumerator(int i) const;
00393 
00394     const SourcePos pos;
00395 
00396 private:
00397     const std::string name;
00398     Variability variability;
00399     bool isConst;
00400     std::vector<Symbol *> enumerators;
00401 };
00402 
00403 
00404 /** @brief Type implementation for pointers to other types
00405 
00406     Pointers can have two additional properties beyond their variability
00407     and the type of object that they are pointing to.  Both of these
00408     properties are used for internal bookkeeping and aren't directly
00409     accessible from the language.
00410 
00411     - Slice: pointers that point to data with SOA layout have this
00412       property--it indicates that the pointer has two components, where the
00413       first (major) component is a regular pointer that points to an
00414       instance of the soa<> type being indexed, and where the second
00415       (minor) component is an integer that indicates which of the soa
00416       slices in that instance the pointer points to.
00417 
00418     - Frozen: only slice pointers may have this property--it indicates that
00419       any further indexing calculations should only be applied to the major
00420       pointer, and the value of the minor offset should be left unchanged.
00421       Pointers to lvalues from structure member access have the frozen
00422       property; see discussion in comments in the StructMemberExpr class.
00423  */
00424 class PointerType : public Type {
00425 public:
00426     PointerType(const Type *t, Variability v, bool isConst, 
00427                 bool isSlice = false, bool frozen = false);
00428 
00429     /** Helper method to return a uniform pointer to the given type. */
00430     static PointerType *GetUniform(const Type *t);
00431     /** Helper method to return a varying pointer to the given type. */
00432     static PointerType *GetVarying(const Type *t);
00433 
00434     /** Returns true if the given type is a void * type. */
00435     static bool IsVoidPointer(const Type *t);
00436 
00437     Variability GetVariability() const;
00438 
00439     bool IsBoolType() const;
00440     bool IsFloatType() const;
00441     bool IsIntType() const;
00442     bool IsUnsignedType() const;
00443     bool IsConstType() const;
00444 
00445     bool IsSlice() const { return isSlice; }
00446     bool IsFrozenSlice() const { return isFrozen; }
00447     const PointerType *GetAsSlice() const;
00448     const PointerType *GetAsNonSlice() const;
00449     const PointerType *GetAsFrozenSlice() const;
00450 
00451     const Type *GetBaseType() const;
00452     const PointerType *GetAsVaryingType() const;
00453     const PointerType *GetAsUniformType() const;
00454     const PointerType *GetAsUnboundVariabilityType() const;
00455     const PointerType *GetAsSOAType(int width) const;
00456 
00457     const PointerType *ResolveUnboundVariability(Variability v) const;
00458     const PointerType *GetAsConstType() const;
00459     const PointerType *GetAsNonConstType() const;
00460 
00461     std::string GetString() const;
00462     std::string Mangle() const;
00463     std::string GetCDeclaration(const std::string &name) const;
00464 
00465     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00466     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00467 
00468     static PointerType *Void;
00469 
00470 private:
00471     const Variability variability;
00472     const bool isConst;
00473     const bool isSlice, isFrozen;
00474     const Type *baseType;
00475 };
00476 
00477 
00478 /** @brief Abstract base class for types that represent collections of
00479     other types.
00480 
00481     This is a common base class that StructTypes, ArrayTypes, and
00482     VectorTypes all inherit from.
00483 */ 
00484 class CollectionType : public Type {
00485 public:
00486     /** Returns the total number of elements in the collection. */
00487     virtual int GetElementCount() const = 0;
00488 
00489     /** Returns the type of the element given by index.  (The value of
00490         index must be between 0 and GetElementCount()-1.
00491      */
00492     virtual const Type *GetElementType(int index) const = 0;
00493 
00494 protected:
00495     CollectionType(TypeId id) : Type(id) { }
00496 };
00497 
00498 
00499 /** @brief Abstract base class for types that represent sequences
00500 
00501     SequentialType is an abstract base class that adds interface routines
00502     for types that represent linear sequences of other types (i.e., arrays
00503     and vectors).
00504  */
00505 class SequentialType : public CollectionType {
00506 public:
00507     /** Returns the Type of the elements that the sequence stores; for
00508         SequentialTypes, all elements have the same type . */
00509     virtual const Type *GetElementType() const = 0;
00510 
00511     /** SequentialType provides an implementation of this CollectionType
00512         method, just passing the query on to the GetElementType(void)
00513         implementation, since all of the elements of a SequentialType have
00514         the same type.
00515      */
00516     const Type *GetElementType(int index) const;
00517 
00518 protected:
00519     SequentialType(TypeId id) : CollectionType(id) { }
00520 };
00521 
00522 
00523 /** @brief One-dimensional array type.
00524 
00525     ArrayType represents a one-dimensional array of instances of some other
00526     type.  (Multi-dimensional arrays are represented by ArrayTypes that in
00527     turn hold ArrayTypes as their child types.)  
00528 */
00529 class ArrayType : public SequentialType {
00530 public:
00531     /** An ArrayType is created by providing the type of the elements that
00532         it stores, and the SOA width to use in laying out the array in
00533         memory.
00534 
00535         @param elementType  Type of the array elements
00536         @param numElements  Total number of elements in the array.  This
00537                             parameter may be zero, in which case this is an
00538                             "unsized" array type.  (Arrays of specific size
00539                             can be converted to unsized arrays to be passed
00540                             to functions that take array parameters, for
00541                             example).
00542      */
00543     ArrayType(const Type *elementType, int numElements);
00544 
00545     Variability GetVariability() const;
00546 
00547     bool IsBoolType() const;
00548     bool IsFloatType() const;
00549     bool IsIntType() const;
00550     bool IsUnsignedType() const;
00551     bool IsConstType() const;
00552 
00553     const Type *GetBaseType() const;
00554     const ArrayType *GetAsVaryingType() const;
00555     const ArrayType *GetAsUniformType() const;
00556     const ArrayType *GetAsUnboundVariabilityType() const;
00557     const ArrayType *GetAsSOAType(int width) const;
00558     const ArrayType *ResolveUnboundVariability(Variability v) const;
00559 
00560     const ArrayType *GetAsUnsignedType() const;
00561     const ArrayType *GetAsConstType() const;
00562     const ArrayType *GetAsNonConstType() const;
00563 
00564     std::string GetString() const;
00565     std::string Mangle() const;
00566     std::string GetCDeclaration(const std::string &name) const;
00567 
00568     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00569     llvm::ArrayType *LLVMType(llvm::LLVMContext *ctx) const;
00570 
00571     /** This method returns the total number of elements in the array,
00572         including all dimensions if this is a multidimensional array. */
00573     int TotalElementCount() const;
00574 
00575     int GetElementCount() const;
00576     const Type *GetElementType() const;
00577 
00578     /** Returns a new array of the same child type, but with the given
00579         length. */
00580     virtual ArrayType *GetSizedArray(int length) const;
00581 
00582     /** If the given type is a (possibly multi-dimensional) array type and
00583         the initializer expression is an expression list, set the size of
00584         any array dimensions that are unsized according to the number of
00585         elements in the corresponding sectoin of the initializer
00586         expression.
00587      */ 
00588     static const Type *SizeUnsizedArrays(const Type *type, Expr *initExpr);
00589 
00590 private:
00591     /** Type of the elements of the array. */
00592     const Type * const child;
00593     /** Number of elements in the array. */
00594     const int numElements;
00595 };
00596 
00597 
00598 /** @brief A (short) vector of atomic types.
00599 
00600     VectorType is used to represent a fixed-size array of elements of an
00601     AtomicType.  Vectors are similar to arrays in that they support
00602     indexing of the elements, but have two key differences.  First, all
00603     arithmetic and logical operations that are value for the element type
00604     can be performed on corresponding VectorTypes (as long as the two
00605     VectorTypes have the same size). Second, VectorTypes of uniform
00606     elements are laid out in memory aligned to the target's vector size;
00607     this allows them to be packed 'horizontally' into vector registers.
00608  */
00609 class VectorType : public SequentialType {
00610 public:
00611     VectorType(const AtomicType *base, int size);
00612 
00613     Variability GetVariability() const;
00614 
00615     bool IsBoolType() const;
00616     bool IsFloatType() const;
00617     bool IsIntType() const;
00618     bool IsUnsignedType() const;
00619     bool IsConstType() const;
00620 
00621     const Type *GetBaseType() const;
00622     const VectorType *GetAsVaryingType() const;
00623     const VectorType *GetAsUniformType() const;
00624     const VectorType *GetAsUnboundVariabilityType() const;
00625     const VectorType *GetAsSOAType(int width) const;
00626     const VectorType *ResolveUnboundVariability(Variability v) const;
00627 
00628     const VectorType *GetAsConstType() const;
00629     const VectorType *GetAsNonConstType() const;
00630 
00631     std::string GetString() const;
00632     std::string Mangle() const;
00633     std::string GetCDeclaration(const std::string &name) const;
00634 
00635     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00636     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00637 
00638     int GetElementCount() const;
00639     const AtomicType *GetElementType() const;
00640 
00641 private:
00642     /** Base type that the vector holds elements of */
00643     const AtomicType * const base;
00644     /** Number of elements in the vector */
00645     const int numElements;
00646 
00647     /** Returns the number of elements stored in memory for the vector.
00648         For uniform vectors, this is rounded up so that the number of
00649         elements evenly divides the target's native vector width. */
00650     int getVectorMemoryCount() const;
00651 };
00652 
00653 
00654 /** @brief Representation of a structure holding a number of members.
00655  */
00656 class StructType : public CollectionType {
00657 public:
00658     StructType(const std::string &name, const llvm::SmallVector<const Type *, 8> &elts, 
00659                const llvm::SmallVector<std::string, 8> &eltNames, 
00660                const llvm::SmallVector<SourcePos, 8> &eltPositions, bool isConst, 
00661                Variability variability, SourcePos pos);
00662 
00663     Variability GetVariability() const;
00664 
00665     bool IsBoolType() const;
00666     bool IsFloatType() const;
00667     bool IsIntType() const;
00668     bool IsUnsignedType() const;
00669     bool IsConstType() const;
00670 
00671     const Type *GetBaseType() const;
00672     const StructType *GetAsVaryingType() const;
00673     const StructType *GetAsUniformType() const;
00674     const StructType *GetAsUnboundVariabilityType() const;
00675     const StructType *GetAsSOAType(int width) const;
00676     const StructType *ResolveUnboundVariability(Variability v) const;
00677 
00678     const StructType *GetAsConstType() const;
00679     const StructType *GetAsNonConstType() const;
00680 
00681     std::string GetString() const;
00682     std::string Mangle() const;
00683     std::string GetCDeclaration(const std::string &name) const;
00684 
00685     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00686     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00687 
00688     /** Returns the type of the structure element with the given name (if any).
00689         Returns NULL if there is no such named element. */
00690     const Type *GetElementType(const std::string &name) const;
00691 
00692     /** Returns the type of the i'th structure element.  The value of \c i must
00693         be between 0 and NumElements()-1. */
00694     const Type *GetElementType(int i) const;
00695 
00696     /** Returns which structure element number (starting from zero) that
00697         has the given name.  If there is no such element, return -1. */
00698     int GetElementNumber(const std::string &name) const;
00699 
00700     /** Returns the name of the i'th element of the structure. */
00701     const std::string &GetElementName(int i) const { return elementNames[i]; }
00702     
00703     /** Returns the total number of elements in the structure. */
00704     int GetElementCount() const { return int(elementTypes.size()); }
00705 
00706     const SourcePos &GetElementPosition(int i) const { return elementPositions[i]; }
00707 
00708     /** Returns the name of the structure type.  (e.g. struct Foo -> "Foo".) */
00709     const std::string &GetStructName() const { return name; }
00710 
00711 private:
00712     static bool checkIfCanBeSOA(const StructType *st);
00713 
00714     /*const*/ std::string name;
00715     /** The types of the struct elements.  Note that we store these with
00716         uniform/varying exactly as they were declared in the source file.
00717         (In other words, even if this struct has a varying qualifier and
00718         thus all of its members are going to be widened out to be varying,
00719         we still store any members that were declared as uniform as uniform
00720         types in the elementTypes array, converting them to varying as
00721         needed in the implementation.)  This is so that if we later need to
00722         make a uniform version of the struct, we've maintained the original
00723         information about the member types.
00724      */
00725     const llvm::SmallVector<const Type *, 8> elementTypes;
00726     const llvm::SmallVector<std::string, 8> elementNames;
00727     /** Source file position at which each structure element declaration
00728         appeared. */
00729     const llvm::SmallVector<SourcePos, 8> elementPositions;
00730     const Variability variability;
00731     const bool isConst;
00732     const SourcePos pos;
00733 
00734     mutable llvm::SmallVector<const Type *, 8> finalElementTypes;
00735 
00736     mutable const StructType *oppositeConstStructType;
00737 };
00738 
00739 
00740 /** Type implementation representing a struct name that has been declared
00741     but where the struct members haven't been defined (i.e. "struct Foo;").
00742     This class doesn't do much besides serve as a placeholder that other
00743     code can use to detect the presence of such as truct.
00744  */
00745 class UndefinedStructType : public Type {
00746 public:
00747     UndefinedStructType(const std::string &name, const Variability variability,
00748                         bool isConst, SourcePos pos);
00749 
00750     Variability GetVariability() const;
00751 
00752     bool IsBoolType() const;
00753     bool IsFloatType() const;
00754     bool IsIntType() const;
00755     bool IsUnsignedType() const;
00756     bool IsConstType() const;
00757 
00758     const Type *GetBaseType() const;
00759     const UndefinedStructType *GetAsVaryingType() const;
00760     const UndefinedStructType *GetAsUniformType() const;
00761     const UndefinedStructType *GetAsUnboundVariabilityType() const;
00762     const UndefinedStructType *GetAsSOAType(int width) const;
00763     const UndefinedStructType *ResolveUnboundVariability(Variability v) const;
00764 
00765     const UndefinedStructType *GetAsConstType() const;
00766     const UndefinedStructType *GetAsNonConstType() const;
00767 
00768     std::string GetString() const;
00769     std::string Mangle() const;
00770     std::string GetCDeclaration(const std::string &name) const;
00771 
00772     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00773     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00774 
00775     /** Returns the name of the structure type.  (e.g. struct Foo -> "Foo".) */
00776     const std::string &GetStructName() const { return name; }
00777 
00778 private:
00779     const std::string name;
00780     const Variability variability;
00781     const bool isConst;
00782     const SourcePos pos;
00783 };
00784 
00785 
00786 /** @brief Type representing a reference to another (non-reference) type.
00787  */
00788 class ReferenceType : public Type {
00789 public:
00790     ReferenceType(const Type *targetType);
00791 
00792     Variability GetVariability() const;
00793 
00794     bool IsBoolType() const;
00795     bool IsFloatType() const;
00796     bool IsIntType() const;
00797     bool IsUnsignedType() const;
00798     bool IsConstType() const;
00799 
00800     const Type *GetBaseType() const;
00801     const Type *GetReferenceTarget() const;
00802     const ReferenceType *GetAsVaryingType() const;
00803     const ReferenceType *GetAsUniformType() const;
00804     const ReferenceType *GetAsUnboundVariabilityType() const;
00805     const Type *GetAsSOAType(int width) const;
00806     const ReferenceType *ResolveUnboundVariability(Variability v) const;
00807 
00808     const ReferenceType *GetAsConstType() const;
00809     const ReferenceType *GetAsNonConstType() const;
00810 
00811     std::string GetString() const;
00812     std::string Mangle() const;
00813     std::string GetCDeclaration(const std::string &name) const;
00814 
00815     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00816     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00817 
00818 private:
00819     const Type * const targetType;
00820     mutable const ReferenceType *asOtherConstType;
00821 };
00822 
00823 
00824 /** @brief Type representing a function (return type + argument types)
00825 
00826     FunctionType encapsulates the information related to a function's type,
00827     including the return type and the types of the arguments.
00828 
00829     @todo This class has a fair number of methods inherited from Type that
00830     don't make sense here (e.g. IsUniformType(), GetBaseType(), LLVMType(), etc.
00831     Would be nice to refactor the inheritance hierarchy to move most of
00832     those interface methods to a sub-class of Type, which in turn all of
00833     the other Type implementations inherit from.
00834  */
00835 class FunctionType : public Type {
00836 public:
00837     FunctionType(const Type *returnType, 
00838                  const llvm::SmallVector<const Type *, 8> &argTypes, SourcePos pos);
00839     FunctionType(const Type *returnType, 
00840                  const llvm::SmallVector<const Type *, 8> &argTypes,
00841                  const llvm::SmallVector<std::string, 8> &argNames,
00842                  const llvm::SmallVector<Expr *, 8> &argDefaults,
00843                  const llvm::SmallVector<SourcePos, 8> &argPos,
00844                  bool isTask, bool isExported, bool isExternC, bool isUnmasked);
00845 
00846     Variability GetVariability() const;
00847 
00848     bool IsBoolType() const;
00849     bool IsFloatType() const;
00850     bool IsIntType() const;
00851     bool IsUnsignedType() const;
00852     bool IsConstType() const;
00853 
00854     const Type *GetBaseType() const;
00855     const Type *GetAsVaryingType() const;
00856     const Type *GetAsUniformType() const;
00857     const Type *GetAsUnboundVariabilityType() const;
00858     const Type *GetAsSOAType(int width) const;
00859     const FunctionType *ResolveUnboundVariability(Variability v) const;
00860 
00861     const Type *GetAsConstType() const;
00862     const Type *GetAsNonConstType() const;
00863 
00864     std::string GetString() const;
00865     std::string Mangle() const;
00866     std::string GetCDeclaration(const std::string &fname) const;
00867 
00868     llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
00869     llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
00870 
00871     const Type *GetReturnType() const { return returnType; }
00872 
00873     const std::string GetReturnTypeString() const;
00874 
00875     /** This method returns the LLVM FunctionType that corresponds to this
00876         function type.  The \c disableMask parameter indicates whether the
00877         llvm::FunctionType should have the trailing mask parameter, if
00878         present, removed from the return function signature. */
00879     llvm::FunctionType *LLVMFunctionType(llvm::LLVMContext *ctx, 
00880                                          bool disableMask = false) const;
00881 
00882     int GetNumParameters() const { return (int)paramTypes.size(); }
00883     const Type *GetParameterType(int i) const;
00884     Expr * GetParameterDefault(int i) const;
00885     const SourcePos &GetParameterSourcePos(int i) const;
00886     const std::string &GetParameterName(int i) const;
00887 
00888     /** This value is true if the function had a 'task' qualifier in the
00889         source program. */
00890     const bool isTask;
00891 
00892     /** This value is true if the function had a 'export' qualifier in the
00893         source program. */
00894     const bool isExported;
00895 
00896     /** This value is true if the function was declared as an 'extern "C"'
00897         function in the source program. */
00898     const bool isExternC;
00899 
00900     /** Indicates whether the function doesn't take an implicit mask
00901         parameter (and thus should start execution with an "all on"
00902         mask). */
00903     const bool isUnmasked;
00904 
00905     /** Indicates whether this function has been declared to be safe to run
00906         with an all-off mask. */
00907     bool isSafe;
00908 
00909     /** If non-negative, this provides a user-supplied override to the cost
00910         function estimate for the function. */ 
00911     int costOverride;
00912 
00913 private:
00914     const Type * const returnType;
00915 
00916     // The following four vectors should all have the same length (which is
00917     // in turn the length returned by GetNumParameters()).
00918     const llvm::SmallVector<const Type *, 8> paramTypes;
00919     const llvm::SmallVector<std::string, 8> paramNames;
00920     /** Default values of the function's arguments.  For arguments without
00921         default values provided, NULL is stored. */
00922     mutable llvm::SmallVector<Expr *, 8> paramDefaults;
00923     /** The names provided (if any) with the function arguments in the
00924         function's signature.  These should only be used for error messages
00925         and the like and so not affect testing function types for equality,
00926         etc. */
00927     const llvm::SmallVector<SourcePos, 8> paramPositions;
00928 };
00929 
00930 
00931 /* Efficient dynamic casting of Types.  First, we specify a default
00932    template function that returns NULL, indicating a failed cast, for
00933    arbitrary types. */
00934 template <typename T> inline const T *
00935 CastType(const Type *type) {
00936     return NULL;
00937 }
00938 
00939 
00940 /* Now we have template specializaitons for the Types implemented in this
00941    file.  Each one checks the Type::typeId member and then performs the
00942    corresponding static cast if it's safe as per the typeId.
00943  */
00944 template <> inline const AtomicType *
00945 CastType(const Type *type) {
00946     if (type != NULL && type->typeId == ATOMIC_TYPE)
00947         return (const AtomicType *)type;
00948     else
00949         return NULL;
00950 }
00951 
00952 template <> inline const EnumType *
00953 CastType(const Type *type) {
00954     if (type != NULL && type->typeId == ENUM_TYPE)
00955         return (const EnumType *)type;
00956     else
00957         return NULL;
00958 }
00959 
00960 template <> inline const PointerType *
00961 CastType(const Type *type) {
00962     if (type != NULL && type->typeId == POINTER_TYPE)
00963         return (const PointerType *)type;
00964     else
00965         return NULL;
00966 }
00967 
00968 template <> inline const ArrayType *
00969 CastType(const Type *type) {
00970     if (type != NULL && type->typeId == ARRAY_TYPE)
00971         return (const ArrayType *)type;
00972     else
00973         return NULL;
00974 }
00975 
00976 template <> inline const VectorType *
00977 CastType(const Type *type) {
00978     if (type != NULL && type->typeId == VECTOR_TYPE)
00979         return (const VectorType *)type;
00980     else
00981         return NULL;
00982 }
00983 
00984 template <> inline const SequentialType *
00985 CastType(const Type *type) {
00986     // Note that this function must be updated if other sequential type
00987     // implementations are added.
00988     if (type != NULL && 
00989         (type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE))
00990         return (const SequentialType *)type;
00991     else
00992         return NULL;
00993 }
00994 
00995 template <> inline const CollectionType *
00996 CastType(const Type *type) {
00997     // Similarly a new collection type implementation requires updating
00998     // this function.
00999     if (type != NULL && 
01000         (type->typeId == ARRAY_TYPE || type->typeId == VECTOR_TYPE ||
01001          type->typeId == STRUCT_TYPE))
01002         return (const CollectionType *)type;
01003     else
01004         return NULL;
01005 }
01006 
01007 template <> inline const StructType *
01008 CastType(const Type *type) {
01009     if (type != NULL && type->typeId == STRUCT_TYPE)
01010         return (const StructType *)type;
01011     else
01012         return NULL;
01013 }
01014 
01015 template <> inline const UndefinedStructType *
01016 CastType(const Type *type) {
01017     if (type != NULL && type->typeId == UNDEFINED_STRUCT_TYPE)
01018         return (const UndefinedStructType *)type;
01019     else
01020         return NULL;
01021 }
01022 
01023 template <> inline const ReferenceType *
01024 CastType(const Type *type) {
01025     if (type != NULL && type->typeId == REFERENCE_TYPE)
01026         return (const ReferenceType *)type;
01027     else
01028         return NULL;
01029 }
01030 
01031 template <> inline const FunctionType *
01032 CastType(const Type *type) {
01033     if (type != NULL && type->typeId == FUNCTION_TYPE)
01034         return (const FunctionType *)type;
01035     else
01036         return NULL;
01037 }
01038 
01039 
01040 inline bool IsReferenceType(const Type *t) {
01041     return CastType<ReferenceType>(t) != NULL;
01042 }
01043 
01044 
01045 #endif // ISPC_TYPE_H