|
Intel SPMD Program Compiler
1.3.0
|
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
1.7.5.1