Intel SPMD Program Compiler  1.3.0
type.cpp
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.cpp
00035     @brief Definitions for classes related to type representation
00036 */
00037 
00038 #include "type.h"
00039 #include "expr.h"
00040 #include "sym.h"
00041 #include "llvmutil.h"
00042 #include "module.h"
00043 
00044 #include <stdio.h>
00045 #include <map>
00046 #include <llvm/Value.h>
00047 #include <llvm/Module.h>
00048 #include <llvm/Analysis/DIBuilder.h>
00049 #if defined(LLVM_3_0) || defined(LLVM_3_1)
00050   #include <llvm/Analysis/DebugInfo.h>
00051 #else
00052   #include <llvm/DebugInfo.h>
00053 #endif
00054 #include <llvm/Support/Dwarf.h>
00055 
00056 
00057 /** Utility routine used in code that prints out declarations; returns true
00058     if the given name should be printed, false otherwise.  This allows us
00059     to omit the names for various internal things (whose names start with
00060     double underscores) and emit anonymous declarations for them instead.
00061  */
00062 
00063 static bool
00064 lShouldPrintName(const std::string &name) {
00065     if (name.size() == 0)
00066         return false;
00067     else if (name[0] != '_' && name[0] != '$')
00068         return true;
00069     else
00070         return (name.size() == 1) || (name[1] != '_');
00071 }
00072 
00073 
00074 /** Utility routine to create a llvm DIArray type of the given number of
00075     the given element type. */
00076 static llvm::DIType 
00077 lCreateDIArray(llvm::DIType eltType, int count) {
00078     int lowerBound = 0, upperBound = count-1;
00079 
00080     if (count == 0) {
00081         // unsized array -> indicate with low > high
00082         lowerBound = 1;
00083         upperBound = 0;
00084     }
00085 
00086     llvm::Value *sub = m->diBuilder->getOrCreateSubrange(lowerBound, upperBound);
00087     std::vector<llvm::Value *> subs;
00088     subs.push_back(sub);
00089     llvm::DIArray subArray = m->diBuilder->getOrCreateArray(subs);
00090 
00091     uint64_t size = eltType.getSizeInBits() * count;
00092     uint64_t align = eltType.getAlignInBits();
00093 
00094     return m->diBuilder->createArrayType(size, align, eltType, subArray);
00095 }
00096 
00097 
00098 ///////////////////////////////////////////////////////////////////////////
00099 // Variability
00100 
00101 std::string
00102 Variability::GetString() const {
00103     switch (type) {
00104     case Uniform: return "uniform";
00105     case Varying: return "varying";
00106     case SOA: {
00107         char buf[32];
00108         sprintf(buf, "soa<%d>", soaWidth);
00109         return buf;
00110     }
00111     case Unbound: return "/*unbound*/";
00112     default:
00113         FATAL("Unhandled variability");
00114         return "";
00115     }
00116 }
00117 
00118 
00119 std::string
00120 Variability::MangleString() const {
00121     switch (type) {
00122     case Uniform: 
00123         return "un";
00124     case Varying: 
00125         return "vy";
00126     case SOA: {
00127         char buf[32];
00128         sprintf(buf, "soa<%d>", soaWidth);
00129         return buf;
00130     }
00131     case Unbound:
00132         FATAL("Unbound unexpected in Variability::MangleString()");
00133     default:
00134         FATAL("Unhandled variability");
00135         return "";
00136     }
00137 }
00138 
00139 ///////////////////////////////////////////////////////////////////////////
00140 // AtomicType
00141 
00142 const AtomicType *AtomicType::UniformBool =
00143     new AtomicType(AtomicType::TYPE_BOOL, Variability::Uniform, false);
00144 const AtomicType *AtomicType::VaryingBool =
00145     new AtomicType(AtomicType::TYPE_BOOL, Variability::Varying, false);
00146 const AtomicType *AtomicType::UniformInt8 =
00147     new AtomicType(AtomicType::TYPE_INT8, Variability::Uniform, false);
00148 const AtomicType *AtomicType::VaryingInt8 =
00149     new AtomicType(AtomicType::TYPE_INT8, Variability::Varying, false);
00150 const AtomicType *AtomicType::UniformUInt8 =
00151     new AtomicType(AtomicType::TYPE_UINT8, Variability::Uniform, false);
00152 const AtomicType *AtomicType::VaryingUInt8 =
00153     new AtomicType(AtomicType::TYPE_UINT8, Variability::Varying, false);
00154 const AtomicType *AtomicType::UniformInt16 =
00155     new AtomicType(AtomicType::TYPE_INT16, Variability::Uniform, false);
00156 const AtomicType *AtomicType::VaryingInt16 =
00157     new AtomicType(AtomicType::TYPE_INT16, Variability::Varying, false);
00158 const AtomicType *AtomicType::UniformUInt16 =
00159     new AtomicType(AtomicType::TYPE_UINT16, Variability::Uniform, false);
00160 const AtomicType *AtomicType::VaryingUInt16 =
00161     new AtomicType(AtomicType::TYPE_UINT16, Variability::Varying, false);
00162 const AtomicType *AtomicType::UniformInt32 =
00163     new AtomicType(AtomicType::TYPE_INT32, Variability::Uniform, false);
00164 const AtomicType *AtomicType::VaryingInt32 =
00165     new AtomicType(AtomicType::TYPE_INT32, Variability::Varying, false);
00166 const AtomicType *AtomicType::UniformUInt32 =
00167     new AtomicType(AtomicType::TYPE_UINT32, Variability::Uniform, false);
00168 const AtomicType *AtomicType::VaryingUInt32 =
00169     new AtomicType(AtomicType::TYPE_UINT32, Variability::Varying, false);
00170 const AtomicType *AtomicType::UniformFloat =
00171     new AtomicType(AtomicType::TYPE_FLOAT, Variability::Uniform, false);
00172 const AtomicType *AtomicType::VaryingFloat =
00173     new AtomicType(AtomicType::TYPE_FLOAT, Variability::Varying, false);
00174 const AtomicType *AtomicType::UniformInt64 =
00175     new AtomicType(AtomicType::TYPE_INT64, Variability::Uniform, false);
00176 const AtomicType *AtomicType::VaryingInt64 =
00177     new AtomicType(AtomicType::TYPE_INT64, Variability::Varying, false);
00178 const AtomicType *AtomicType::UniformUInt64 =
00179     new AtomicType(AtomicType::TYPE_UINT64, Variability::Uniform, false);
00180 const AtomicType *AtomicType::VaryingUInt64 =
00181     new AtomicType(AtomicType::TYPE_UINT64, Variability::Varying, false);
00182 const AtomicType *AtomicType::UniformDouble =
00183     new AtomicType(AtomicType::TYPE_DOUBLE, Variability::Uniform, false);
00184 const AtomicType *AtomicType::VaryingDouble =
00185     new AtomicType(AtomicType::TYPE_DOUBLE, Variability::Varying, false);
00186 const AtomicType *AtomicType::Void = 
00187     new AtomicType(TYPE_VOID, Variability::Uniform, false);
00188 
00189 
00190 AtomicType::AtomicType(BasicType bt, Variability v, bool ic) 
00191     : Type(ATOMIC_TYPE), basicType(bt), variability(v), isConst(ic) {
00192     asOtherConstType = NULL;
00193     asUniformType = asVaryingType = NULL;
00194 }
00195 
00196 
00197 Variability
00198 AtomicType::GetVariability() const {
00199     return variability;
00200 }
00201 
00202 
00203 bool
00204 Type::IsPointerType() const {
00205     return (CastType<PointerType>(this) != NULL);
00206 }
00207 
00208 
00209 bool
00210 Type::IsArrayType() const {
00211     return (CastType<ArrayType>(this) != NULL);
00212 }
00213 
00214 bool
00215 Type::IsReferenceType() const {
00216     return (CastType<ReferenceType>(this) != NULL);
00217 }
00218 
00219 bool
00220 Type::IsVoidType() const {
00221     return this == AtomicType::Void;
00222 }
00223 
00224 bool
00225 AtomicType::IsFloatType() const {
00226     return (basicType == TYPE_FLOAT || basicType == TYPE_DOUBLE);
00227 }
00228 
00229 bool
00230 AtomicType::IsIntType() const {
00231     return (basicType == TYPE_INT8  || basicType == TYPE_UINT8  ||
00232             basicType == TYPE_INT16 || basicType == TYPE_UINT16 ||
00233             basicType == TYPE_INT32 || basicType == TYPE_UINT32 ||
00234             basicType == TYPE_INT64 || basicType == TYPE_UINT64);
00235 }
00236 
00237 
00238 bool
00239 AtomicType::IsUnsignedType() const {
00240     return (basicType == TYPE_UINT8  || basicType == TYPE_UINT16 ||
00241             basicType == TYPE_UINT32 || basicType == TYPE_UINT64);
00242 }
00243 
00244 
00245 bool
00246 AtomicType::IsBoolType() const {
00247     return basicType == TYPE_BOOL;
00248 }
00249 
00250 
00251 bool
00252 AtomicType::IsConstType() const { 
00253     return isConst; 
00254 }
00255 
00256 
00257 const AtomicType *
00258 AtomicType::GetAsUnsignedType() const {
00259     if (IsUnsignedType() == true) 
00260         return this;
00261 
00262     if (IsIntType() == false)
00263         return NULL;
00264 
00265     switch (basicType) {
00266     case TYPE_INT8:
00267         return new AtomicType(TYPE_UINT8, variability, isConst);
00268     case TYPE_INT16:
00269         return new AtomicType(TYPE_UINT16, variability, isConst);
00270     case TYPE_INT32:
00271         return new AtomicType(TYPE_UINT32, variability, isConst);
00272     case TYPE_INT64:
00273         return new AtomicType(TYPE_UINT64, variability, isConst);
00274     default:
00275         FATAL("Unexpected basicType in GetAsUnsignedType()");
00276         return NULL;
00277     }
00278 }
00279 
00280 
00281 const AtomicType *
00282 AtomicType::GetAsConstType() const {
00283     if (basicType == TYPE_VOID || isConst == true) 
00284         return this;
00285     
00286     if (asOtherConstType == NULL) {
00287         asOtherConstType = new AtomicType(basicType, variability, true);
00288         asOtherConstType->asOtherConstType = this;
00289     }
00290     return asOtherConstType;
00291 }
00292 
00293 
00294 const AtomicType *
00295 AtomicType::GetAsNonConstType() const {
00296     if (basicType == TYPE_VOID || isConst == false) 
00297         return this;
00298 
00299     if (asOtherConstType == NULL) {
00300         asOtherConstType = new AtomicType(basicType, variability, false);
00301         asOtherConstType->asOtherConstType = this;
00302     }
00303     return asOtherConstType;
00304 }
00305 
00306 
00307 const AtomicType *
00308 AtomicType::GetBaseType() const {
00309     return this;
00310 }
00311 
00312 
00313 const AtomicType *
00314 AtomicType::GetAsVaryingType() const {
00315     Assert(basicType != TYPE_VOID);
00316     if (variability == Variability::Varying)
00317         return this;
00318 
00319     if (asVaryingType == NULL) {
00320         asVaryingType = new AtomicType(basicType, Variability::Varying, isConst);
00321         if (variability == Variability::Uniform)
00322             asVaryingType->asUniformType = this;
00323     }
00324     return asVaryingType;
00325 }
00326 
00327 
00328 const AtomicType *
00329 AtomicType::GetAsUniformType() const {
00330     Assert(basicType != TYPE_VOID);
00331     if (variability == Variability::Uniform)
00332         return this;
00333 
00334     if (asUniformType == NULL) {
00335         asUniformType = new AtomicType(basicType, Variability::Uniform, isConst);
00336         if (variability == Variability::Varying)
00337             asUniformType->asVaryingType = this;
00338     }
00339     return asUniformType;
00340 }
00341 
00342 
00343 const AtomicType *
00344 AtomicType::GetAsUnboundVariabilityType() const {
00345     Assert(basicType != TYPE_VOID);
00346     if (variability == Variability::Unbound)
00347         return this;
00348     return new AtomicType(basicType, Variability::Unbound, isConst);
00349 }
00350 
00351 
00352 const AtomicType *
00353 AtomicType::GetAsSOAType(int width) const {
00354     Assert(basicType != TYPE_VOID);
00355     if (variability == Variability(Variability::SOA, width))
00356         return this;
00357     return new AtomicType(basicType, Variability(Variability::SOA, width), isConst);
00358 }
00359 
00360 
00361 const AtomicType *
00362 AtomicType::ResolveUnboundVariability(Variability v) const {
00363     Assert(v != Variability::Unbound);
00364     if (variability != Variability::Unbound)
00365         return this;
00366     return new AtomicType(basicType, v, isConst);
00367 }
00368 
00369 
00370 std::string
00371 AtomicType::GetString() const {
00372     std::string ret;
00373     if (basicType != TYPE_VOID) {
00374         if (isConst)   ret += "const ";
00375         ret += variability.GetString();
00376         ret += " ";
00377     }
00378 
00379     switch (basicType) {
00380     case TYPE_VOID:   ret += "void";            break;
00381     case TYPE_BOOL:   ret += "bool";            break;
00382     case TYPE_INT8:   ret += "int8";            break;
00383     case TYPE_UINT8:  ret += "unsigned int8";   break;
00384     case TYPE_INT16:  ret += "int16";           break;
00385     case TYPE_UINT16: ret += "unsigned int16";  break;
00386     case TYPE_INT32:  ret += "int32";           break;
00387     case TYPE_UINT32: ret += "unsigned int32";  break;
00388     case TYPE_FLOAT:  ret += "float";           break;
00389     case TYPE_INT64:  ret += "int64";           break;
00390     case TYPE_UINT64: ret += "unsigned int64";  break;
00391     case TYPE_DOUBLE: ret += "double";          break;
00392     default: FATAL("Logic error in AtomicType::GetString()");
00393     }
00394     return ret;
00395 }
00396 
00397 
00398 std::string
00399 AtomicType::Mangle() const {
00400     std::string ret;
00401     if (isConst)   ret += "C";
00402     ret += variability.MangleString();
00403 
00404     switch (basicType) {
00405     case TYPE_VOID:   ret += "v"; break;
00406     case TYPE_BOOL:   ret += "b"; break;
00407     case TYPE_INT8:   ret += "t"; break;
00408     case TYPE_UINT8:  ret += "T"; break;
00409     case TYPE_INT16:  ret += "s"; break;
00410     case TYPE_UINT16: ret += "S"; break;
00411     case TYPE_INT32:  ret += "i"; break;
00412     case TYPE_UINT32: ret += "u"; break;
00413     case TYPE_FLOAT:  ret += "f"; break;
00414     case TYPE_INT64:  ret += "I"; break;
00415     case TYPE_UINT64: ret += "U"; break;
00416     case TYPE_DOUBLE: ret += "d"; break;
00417     default: FATAL("Logic error in AtomicType::Mangle()");
00418     }
00419     return ret;
00420 }
00421 
00422 
00423 std::string
00424 AtomicType::GetCDeclaration(const std::string &name) const {
00425     std::string ret;
00426     if (variability != Variability::Uniform && 
00427         variability != Variability::SOA) {
00428         Assert(m->errorCount > 0);
00429         return ret;
00430     }
00431     if (isConst) ret += "const ";
00432 
00433     switch (basicType) {
00434     case TYPE_VOID:   ret += "void";     break;
00435     case TYPE_BOOL:   ret += "bool";     break;
00436     case TYPE_INT8:   ret += "int8_t";   break;
00437     case TYPE_UINT8:  ret += "uint8_t";  break;
00438     case TYPE_INT16:  ret += "int16_t";  break;
00439     case TYPE_UINT16: ret += "uint16_t"; break;
00440     case TYPE_INT32:  ret += "int32_t";  break;
00441     case TYPE_UINT32: ret += "uint32_t"; break;
00442     case TYPE_FLOAT:  ret += "float";    break;
00443     case TYPE_INT64:  ret += "int64_t";  break;
00444     case TYPE_UINT64: ret += "uint64_t"; break;
00445     case TYPE_DOUBLE: ret += "double";   break;
00446     default: FATAL("Logic error in AtomicType::GetCDeclaration()");
00447     }
00448 
00449     if (lShouldPrintName(name)) {
00450         ret += " ";
00451         ret += name;
00452     }
00453 
00454     if (variability == Variability::SOA) {
00455         char buf[32];
00456         sprintf(buf, "[%d]", variability.soaWidth);
00457         ret += buf;
00458     }
00459 
00460     return ret;
00461 }
00462 
00463 
00464 llvm::Type *
00465 AtomicType::LLVMType(llvm::LLVMContext *ctx) const {
00466     Assert(variability.type != Variability::Unbound);
00467     bool isUniform = (variability == Variability::Uniform);
00468     bool isVarying = (variability == Variability::Varying);
00469 
00470     if (isUniform || isVarying) {
00471         switch (basicType) {
00472         case TYPE_VOID:
00473             return llvm::Type::getVoidTy(*ctx);
00474         case TYPE_BOOL:
00475             return isUniform ? LLVMTypes::BoolType : LLVMTypes::BoolVectorType;
00476         case TYPE_INT8:
00477         case TYPE_UINT8:
00478             return isUniform ? LLVMTypes::Int8Type : LLVMTypes::Int8VectorType;
00479         case TYPE_INT16:
00480         case TYPE_UINT16:
00481             return isUniform ? LLVMTypes::Int16Type : LLVMTypes::Int16VectorType;
00482         case TYPE_INT32:
00483         case TYPE_UINT32:
00484             return isUniform ? LLVMTypes::Int32Type : LLVMTypes::Int32VectorType;
00485         case TYPE_FLOAT:
00486             return isUniform ? LLVMTypes::FloatType : LLVMTypes::FloatVectorType;
00487         case TYPE_INT64:
00488         case TYPE_UINT64:
00489             return isUniform ? LLVMTypes::Int64Type : LLVMTypes::Int64VectorType;
00490         case TYPE_DOUBLE:
00491             return isUniform ? LLVMTypes::DoubleType : LLVMTypes::DoubleVectorType;
00492         default:
00493             FATAL("logic error in AtomicType::LLVMType");
00494             return NULL;
00495         }
00496     }
00497     else {
00498         ArrayType at(GetAsUniformType(), variability.soaWidth);
00499         return at.LLVMType(ctx);
00500     }
00501 }
00502 
00503 
00504 llvm::DIType
00505 AtomicType::GetDIType(llvm::DIDescriptor scope) const {
00506     Assert(variability.type != Variability::Unbound);
00507 
00508     if (variability.type == Variability::Uniform) {
00509         switch (basicType) {
00510         case TYPE_VOID:
00511             return llvm::DIType();
00512         case TYPE_BOOL:
00513             return m->diBuilder->createBasicType("bool", 32 /* size */, 32 /* align */,
00514                                                  llvm::dwarf::DW_ATE_unsigned);
00515             break;
00516         case TYPE_INT8:
00517             return m->diBuilder->createBasicType("int8", 8 /* size */, 8 /* align */,
00518                                                  llvm::dwarf::DW_ATE_signed);
00519             break;
00520         case TYPE_UINT8:
00521             return m->diBuilder->createBasicType("uint8", 8 /* size */, 8 /* align */,
00522                                                  llvm::dwarf::DW_ATE_unsigned);
00523             break;
00524         case TYPE_INT16:
00525             return m->diBuilder->createBasicType("int16", 16 /* size */, 16 /* align */,
00526                                                  llvm::dwarf::DW_ATE_signed);
00527             break;
00528         case TYPE_UINT16:
00529             return m->diBuilder->createBasicType("uint16", 16 /* size */, 16 /* align */,
00530                                                  llvm::dwarf::DW_ATE_unsigned);
00531             break;
00532         case TYPE_INT32:
00533             return m->diBuilder->createBasicType("int32", 32 /* size */, 32 /* align */,
00534                                                  llvm::dwarf::DW_ATE_signed);
00535             break;
00536         case TYPE_UINT32:
00537             return m->diBuilder->createBasicType("uint32", 32 /* size */, 32 /* align */,
00538                                                  llvm::dwarf::DW_ATE_unsigned);
00539             break;
00540         case TYPE_FLOAT:
00541             return m->diBuilder->createBasicType("float", 32 /* size */, 32 /* align */,
00542                                                  llvm::dwarf::DW_ATE_float);
00543             break;
00544         case TYPE_DOUBLE:
00545             return m->diBuilder->createBasicType("double", 64 /* size */, 64 /* align */,
00546                                                  llvm::dwarf::DW_ATE_float);
00547             break;
00548         case TYPE_INT64:
00549             return m->diBuilder->createBasicType("int64", 64 /* size */, 64 /* align */,
00550                                                  llvm::dwarf::DW_ATE_signed);
00551             break;
00552         case TYPE_UINT64:
00553             return m->diBuilder->createBasicType("uint64", 64 /* size */, 64 /* align */,
00554                                                  llvm::dwarf::DW_ATE_unsigned);
00555             break;
00556         default:
00557             FATAL("unhandled basic type in AtomicType::GetDIType()");
00558             return llvm::DIType();
00559         }
00560     }
00561     else if (variability == Variability::Varying) {
00562         llvm::DIType unifType = GetAsUniformType()->GetDIType(scope);
00563         llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, g->target.vectorWidth-1);
00564         llvm::DIArray subArray = m->diBuilder->getOrCreateArray(sub);
00565         uint64_t size =  unifType.getSizeInBits()  * g->target.vectorWidth;
00566         uint64_t align = unifType.getAlignInBits() * g->target.vectorWidth;
00567         return m->diBuilder->createVectorType(size, align, unifType, subArray);
00568     }
00569     else {
00570         Assert(variability == Variability::SOA);
00571         ArrayType at(GetAsUniformType(), variability.soaWidth);
00572         return at.GetDIType(scope);
00573     }
00574 }
00575 
00576 
00577 ///////////////////////////////////////////////////////////////////////////
00578 // EnumType
00579 
00580 EnumType::EnumType(SourcePos p) 
00581     : Type(ENUM_TYPE), pos(p) {
00582     //    name = "/* (anonymous) */";
00583     isConst = false;
00584     variability = Variability(Variability::Unbound);
00585 }
00586 
00587 
00588 EnumType::EnumType(const char *n, SourcePos p) 
00589     : Type(ENUM_TYPE), pos(p), name(n) {
00590     isConst = false;
00591     variability = Variability(Variability::Unbound);
00592 }
00593 
00594 
00595 Variability
00596 EnumType::GetVariability() const {
00597     return variability;
00598 }
00599 
00600 
00601 bool 
00602 EnumType::IsBoolType() const {
00603     return false;
00604 }
00605 
00606 
00607 bool 
00608 EnumType::IsFloatType() const {
00609     return false;
00610 }
00611 
00612 
00613 bool 
00614 EnumType::IsIntType() const {
00615     return true;
00616 }
00617 
00618 
00619 bool 
00620 EnumType::IsUnsignedType() const {
00621     return true;
00622 }
00623 
00624 
00625 bool 
00626 EnumType::IsConstType() const {
00627     return isConst;
00628 }
00629 
00630 
00631 const EnumType *
00632 EnumType::GetBaseType() const {
00633     return this;
00634 }
00635 
00636 
00637 const EnumType *
00638 EnumType::GetAsUniformType() const {
00639     if (IsUniformType())
00640         return this;
00641     else {
00642         EnumType *enumType = new EnumType(*this);
00643         enumType->variability = Variability::Uniform;
00644         return enumType;
00645     }
00646 }
00647 
00648 
00649 const EnumType *
00650 EnumType::ResolveUnboundVariability(Variability v) const {
00651     if (variability != Variability::Unbound)
00652         return this;
00653     else {
00654         EnumType *enumType = new EnumType(*this);
00655         enumType->variability = v;
00656         return enumType;
00657     }
00658 }
00659 
00660 
00661 const EnumType *
00662 EnumType::GetAsVaryingType() const {
00663     if (IsVaryingType())
00664         return this;
00665     else {
00666         EnumType *enumType = new EnumType(*this);
00667         enumType->variability = Variability(Variability::Varying);
00668         return enumType;
00669     }
00670 }
00671 
00672 
00673 const EnumType *
00674 EnumType::GetAsUnboundVariabilityType() const {
00675     if (HasUnboundVariability())
00676         return this;
00677     else {
00678         EnumType *enumType = new EnumType(*this);
00679         enumType->variability = Variability(Variability::Unbound);
00680         return enumType;
00681     }
00682 }
00683 
00684 
00685 const EnumType *
00686 EnumType::GetAsSOAType(int width) const {
00687     if (GetSOAWidth() == width)
00688         return this;
00689     else {
00690         EnumType *enumType = new EnumType(*this);
00691         enumType->variability = Variability(Variability::SOA, width);
00692         return enumType;
00693     }
00694 }
00695 
00696 
00697 const EnumType *
00698 EnumType::GetAsConstType() const {
00699     if (isConst)
00700         return this;
00701     else {
00702         EnumType *enumType = new EnumType(*this);
00703         enumType->isConst = true;
00704         return enumType;
00705     }
00706 }
00707 
00708 
00709 const EnumType *
00710 EnumType::GetAsNonConstType() const {
00711     if (!isConst)
00712         return this;
00713     else {
00714         EnumType *enumType = new EnumType(*this);
00715         enumType->isConst = false;
00716         return enumType;
00717     }
00718 }
00719 
00720 
00721 std::string 
00722 EnumType::GetString() const {
00723     std::string ret;
00724     if (isConst) ret += "const ";
00725     ret += variability.GetString();
00726 
00727     ret += " enum ";
00728     if (name.size())
00729         ret += name;
00730     return ret;
00731 }
00732 
00733 
00734 std::string 
00735 EnumType::Mangle() const {
00736     Assert(variability != Variability::Unbound);
00737 
00738     std::string ret;
00739     if (isConst) ret += "C";
00740     ret += variability.MangleString();
00741     ret += std::string("enum[") + name + std::string("]");
00742     return ret;
00743 }
00744 
00745 
00746 std::string 
00747 EnumType::GetCDeclaration(const std::string &varName) const {
00748     if (variability != Variability::Uniform &&
00749         variability != Variability::SOA) {
00750         Assert(m->errorCount > 0);
00751         return "";
00752     }
00753 
00754     std::string ret;
00755     if (isConst) ret += "const ";
00756     ret += "enum";
00757     if (name.size())
00758         ret += std::string(" ") + name;
00759 
00760     if (lShouldPrintName(varName)) {
00761         ret += " ";
00762         ret += varName;
00763     }
00764 
00765     if (variability == Variability::SOA) {
00766         char buf[32];
00767         sprintf(buf, "[%d]", variability.soaWidth);
00768         ret += buf;
00769     }
00770 
00771     return ret;
00772 }
00773 
00774 
00775 llvm::Type *
00776 EnumType::LLVMType(llvm::LLVMContext *ctx) const {
00777     Assert(variability != Variability::Unbound);
00778 
00779     switch (variability.type) {
00780     case Variability::Uniform:
00781         return LLVMTypes::Int32Type;
00782     case Variability::Varying:
00783         return LLVMTypes::Int32VectorType;
00784     case Variability::SOA: {
00785         ArrayType at(AtomicType::UniformInt32, variability.soaWidth);
00786         return at.LLVMType(ctx);
00787     }
00788     default:
00789         FATAL("Unexpected variability in EnumType::LLVMType()");
00790         return NULL;
00791     }
00792 }
00793 
00794 
00795 llvm::DIType 
00796 EnumType::GetDIType(llvm::DIDescriptor scope) const {
00797     std::vector<llvm::Value *> enumeratorDescriptors;
00798     for (unsigned int i = 0; i < enumerators.size(); ++i) {
00799         unsigned int enumeratorValue;
00800         Assert(enumerators[i]->constValue != NULL);
00801         int count = enumerators[i]->constValue->AsUInt32(&enumeratorValue);
00802         Assert(count == 1);
00803 
00804         llvm::Value *descriptor = 
00805             m->diBuilder->createEnumerator(enumerators[i]->name, enumeratorValue);
00806         enumeratorDescriptors.push_back(descriptor);
00807     }
00808     llvm::DIArray elementArray = 
00809         m->diBuilder->getOrCreateArray(enumeratorDescriptors);
00810 
00811     llvm::DIFile diFile = pos.GetDIFile();
00812     llvm::DIType diType =
00813         m->diBuilder->createEnumerationType(scope, name, diFile, pos.first_line,
00814                                             32 /* size in bits */,
00815                                             32 /* align in bits */,
00816                                             elementArray
00817 #if !defined(LLVM_3_0) && !defined(LLVM_3_1)
00818                                             , llvm::DIType(), 0
00819 #endif
00820                                             );
00821 
00822 
00823     switch (variability.type) {
00824     case Variability::Uniform:
00825         return diType;
00826     case Variability::Varying: {
00827         llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, g->target.vectorWidth-1);
00828         llvm::DIArray subArray = m->diBuilder->getOrCreateArray(sub);
00829         uint64_t size =  diType.getSizeInBits()  * g->target.vectorWidth;
00830         uint64_t align = diType.getAlignInBits() * g->target.vectorWidth;
00831         return m->diBuilder->createVectorType(size, align, diType, subArray);
00832     }
00833     case Variability::SOA: {
00834         return lCreateDIArray(diType, variability.soaWidth);
00835     }
00836     default:
00837         FATAL("Unexpected variability in EnumType::GetDIType()");
00838         return llvm::DIType();
00839     }
00840 }
00841 
00842 
00843 void
00844 EnumType::SetEnumerators(const std::vector<Symbol *> &e) {
00845     enumerators = e;
00846 }
00847 
00848 
00849 int
00850 EnumType::GetEnumeratorCount() const {
00851     return (int)enumerators.size();
00852 }
00853 
00854 
00855 const Symbol *
00856 EnumType::GetEnumerator(int i) const {
00857     return enumerators[i];
00858 }
00859 
00860 
00861 ///////////////////////////////////////////////////////////////////////////
00862 // PointerType
00863 
00864 PointerType *PointerType::Void = 
00865     new PointerType(AtomicType::Void, Variability(Variability::Uniform), false);
00866 
00867 
00868 PointerType::PointerType(const Type *t, Variability v, bool ic, bool is, 
00869                          bool fr)
00870     : Type(POINTER_TYPE), variability(v), isConst(ic), isSlice(is), isFrozen(fr) {
00871     baseType = t;
00872 }
00873 
00874 
00875 PointerType *
00876 PointerType::GetUniform(const Type *t) {
00877     return new PointerType(t, Variability(Variability::Uniform), false);
00878 }
00879 
00880 
00881 PointerType *
00882 PointerType::GetVarying(const Type *t) {
00883     return new PointerType(t, Variability(Variability::Varying), false);
00884 }
00885 
00886 
00887 bool
00888 PointerType::IsVoidPointer(const Type *t) {
00889     return Type::EqualIgnoringConst(t->GetAsUniformType(),
00890                                     PointerType::Void);
00891 }
00892 
00893 
00894 Variability
00895 PointerType::GetVariability() const {
00896     return variability;
00897 }
00898 
00899 
00900 bool
00901 PointerType::IsBoolType() const {
00902     return false;
00903 }
00904 
00905 
00906 bool
00907 PointerType::IsFloatType() const {
00908     return false;
00909 }
00910 
00911 
00912 bool
00913 PointerType::IsIntType() const {
00914     return false;
00915 }
00916 
00917 
00918 bool
00919 PointerType::IsUnsignedType() const {
00920     return false;
00921 }
00922 
00923 
00924 bool
00925 PointerType::IsConstType() const {
00926     return isConst;
00927 }
00928 
00929 
00930 const Type *
00931 PointerType::GetBaseType() const {
00932     return baseType;
00933 }
00934 
00935 
00936 const PointerType *
00937 PointerType::GetAsVaryingType() const {
00938     if (variability == Variability::Varying)
00939         return this;
00940     else
00941         return new PointerType(baseType, Variability(Variability::Varying),
00942                                isConst, isSlice, isFrozen);
00943 }
00944 
00945 
00946 const PointerType *
00947 PointerType::GetAsUniformType() const {
00948     if (variability == Variability::Uniform)
00949         return this;
00950     else
00951         return new PointerType(baseType, Variability(Variability::Uniform),
00952                                isConst, isSlice, isFrozen);
00953 }
00954 
00955 
00956 const PointerType *
00957 PointerType::GetAsUnboundVariabilityType() const {
00958     if (variability == Variability::Unbound)
00959         return this;
00960     else
00961         return new PointerType(baseType, Variability(Variability::Unbound),
00962                                isConst, isSlice, isFrozen);
00963 }
00964 
00965 
00966 const PointerType *
00967 PointerType::GetAsSOAType(int width) const {
00968     if (GetSOAWidth() == width)
00969         return this;
00970     else
00971         return new PointerType(baseType, Variability(Variability::SOA, width),
00972                                isConst, isSlice, isFrozen);
00973 }
00974 
00975 
00976 const PointerType *
00977 PointerType::GetAsSlice() const {
00978     if (isSlice)
00979         return this;
00980     return new PointerType(baseType, variability, isConst, true);
00981 }
00982 
00983 
00984 const PointerType *
00985 PointerType::GetAsNonSlice() const {
00986     if (isSlice == false)
00987         return this;
00988     return new PointerType(baseType, variability, isConst, false);
00989 }
00990 
00991 
00992 const PointerType *
00993 PointerType::GetAsFrozenSlice() const {
00994     if (isFrozen)
00995         return this;
00996     return new PointerType(baseType, variability, isConst, true, true);
00997 }
00998 
00999 
01000 const PointerType *
01001 PointerType::ResolveUnboundVariability(Variability v) const {
01002     if (baseType == NULL) {
01003         Assert(m->errorCount > 0);
01004         return NULL;
01005     }
01006 
01007     Assert(v != Variability::Unbound);
01008     Variability ptrVariability = (variability == Variability::Unbound) ? v :
01009         variability;
01010     const Type *resolvedBaseType = 
01011         baseType->ResolveUnboundVariability(Variability::Uniform);
01012     return new PointerType(resolvedBaseType, ptrVariability, isConst, isSlice,
01013                            isFrozen);
01014 }
01015 
01016 
01017 const PointerType *
01018 PointerType::GetAsConstType() const {
01019     if (isConst == true)
01020         return this;
01021     else
01022         return new PointerType(baseType, variability, true, isSlice);
01023 }
01024 
01025 
01026 const PointerType *
01027 PointerType::GetAsNonConstType() const {
01028     if (isConst == false)
01029         return this;
01030     else
01031         return new PointerType(baseType, variability, false, isSlice);
01032 }
01033 
01034 
01035 std::string 
01036 PointerType::GetString() const {
01037     if (baseType == NULL) {
01038         Assert(m->errorCount > 0);
01039         return "";
01040     }
01041 
01042     std::string ret = baseType->GetString();
01043 
01044     ret += std::string(" * ");
01045     if (isConst) ret += "const ";
01046     if (isSlice) ret += "slice ";
01047     if (isFrozen) ret += "/*frozen*/ ";
01048     ret += variability.GetString();
01049 
01050     return ret;
01051 }
01052 
01053 
01054 std::string
01055 PointerType::Mangle() const {
01056     Assert(variability != Variability::Unbound);
01057     if (baseType == NULL) {
01058         Assert(m->errorCount > 0);
01059         return "";
01060     }
01061 
01062     std::string ret = variability.MangleString() + std::string("<");
01063     if (isSlice || isFrozen)  ret += "-";
01064     if (isSlice) ret += "s";
01065     if (isFrozen) ret += "f";
01066     if (isSlice || isFrozen)  ret += "-";
01067     return ret + baseType->Mangle() + std::string(">");
01068 }
01069 
01070 
01071 std::string
01072 PointerType::GetCDeclaration(const std::string &name) const {
01073     if (isSlice ||
01074         (variability != Variability::Uniform &&
01075          variability != Variability::SOA)) {
01076         Assert(m->errorCount > 0);
01077         return "";
01078     }
01079 
01080     if (baseType == NULL) {
01081         Assert(m->errorCount > 0);
01082         return "";
01083     }
01084 
01085     std::string ret = baseType->GetCDeclaration("");
01086     ret += std::string(" *");
01087     if (isConst) ret += " const";
01088     ret += std::string(" ");
01089     ret += name;
01090 
01091     if (variability == Variability::SOA) {
01092         char buf[32];
01093         sprintf(buf, "[%d]", variability.soaWidth);
01094         ret += buf;
01095     }
01096 
01097     return ret;
01098 }
01099 
01100 
01101 llvm::Type *
01102 PointerType::LLVMType(llvm::LLVMContext *ctx) const {
01103     if (baseType == NULL) {
01104         Assert(m->errorCount > 0);
01105         return NULL;
01106     }
01107 
01108     if (isSlice) {
01109         llvm::Type *types[2];
01110         types[0] = GetAsNonSlice()->LLVMType(ctx);
01111         
01112         switch (variability.type) {
01113         case Variability::Uniform:
01114             types[1] = LLVMTypes::Int32Type;
01115             break;
01116         case Variability::Varying:
01117             types[1] = LLVMTypes::Int32VectorType;
01118             break;
01119         case Variability::SOA:
01120             types[1] = llvm::ArrayType::get(LLVMTypes::Int32Type,
01121                                             variability.soaWidth);
01122             break;
01123         default:
01124             FATAL("unexpected variability for slice pointer in "
01125                   "PointerType::LLVMType");
01126         }
01127 
01128         llvm::ArrayRef<llvm::Type *> typesArrayRef =
01129             llvm::ArrayRef<llvm::Type *>(types, 2);
01130         return llvm::StructType::get(*g->ctx, typesArrayRef);
01131     }
01132 
01133     switch (variability.type) {
01134     case Variability::Uniform: {
01135         llvm::Type *ptype = NULL;
01136         const FunctionType *ftype = CastType<FunctionType>(baseType);
01137         if (ftype != NULL) 
01138             ptype = llvm::PointerType::get(ftype->LLVMFunctionType(ctx), 0);
01139         else {
01140             if (baseType == AtomicType::Void)
01141                 ptype = LLVMTypes::VoidPointerType;
01142             else
01143                 ptype = llvm::PointerType::get(baseType->LLVMType(ctx), 0);
01144         }
01145         return ptype;
01146     }
01147     case Variability::Varying:
01148         // always the same, since we currently use int vectors for varying
01149         // pointers
01150         return LLVMTypes::VoidPointerVectorType;
01151     case Variability::SOA: {
01152         ArrayType at(GetAsUniformType(), variability.soaWidth);
01153         return at.LLVMType(ctx);
01154     }
01155     default:
01156         FATAL("Unexpected variability in PointerType::LLVMType()");
01157         return NULL;
01158     }
01159 }
01160 
01161 
01162 llvm::DIType
01163 PointerType::GetDIType(llvm::DIDescriptor scope) const {
01164     if (baseType == NULL) {
01165         Assert(m->errorCount > 0);
01166         return llvm::DIType();
01167     }
01168 
01169     llvm::DIType diTargetType = baseType->GetDIType(scope);
01170     int bitsSize = g->target.is32Bit ? 32 : 64;
01171     int ptrAlignBits = bitsSize;
01172     switch (variability.type) {
01173     case Variability::Uniform:
01174         return m->diBuilder->createPointerType(diTargetType, bitsSize, 
01175                                                ptrAlignBits);
01176     case Variability::Varying: {
01177         // emit them as an array of pointers
01178         llvm::DIType eltType = m->diBuilder->createPointerType(diTargetType, 
01179                                                                bitsSize, ptrAlignBits);
01180         return lCreateDIArray(eltType, g->target.vectorWidth);
01181     }
01182     case Variability::SOA: {
01183         ArrayType at(GetAsUniformType(), variability.soaWidth);
01184         return at.GetDIType(scope);
01185     }
01186     default:
01187         FATAL("Unexpected variability in PointerType::GetDIType()");
01188         return llvm::DIType();
01189     }
01190 }
01191 
01192 
01193 ///////////////////////////////////////////////////////////////////////////
01194 // SequentialType
01195 
01196 const Type *SequentialType::GetElementType(int index) const {
01197     return GetElementType();
01198 }
01199 
01200 
01201 ///////////////////////////////////////////////////////////////////////////
01202 // ArrayType
01203 
01204 ArrayType::ArrayType(const Type *c, int a) 
01205     : SequentialType(ARRAY_TYPE), child(c), numElements(a) {
01206     // 0 -> unsized array.
01207     Assert(numElements >= 0);
01208     Assert(Type::Equal(c, AtomicType::Void) == false);
01209 }
01210 
01211 
01212 llvm::ArrayType *
01213 ArrayType::LLVMType(llvm::LLVMContext *ctx) const {
01214     if (child == NULL) {
01215         Assert(m->errorCount > 0);
01216         return NULL;
01217     }
01218 
01219     llvm::Type *ct = child->LLVMType(ctx);
01220     if (ct == NULL) {
01221         Assert(m->errorCount > 0);
01222         return NULL;
01223     }
01224     return llvm::ArrayType::get(ct, numElements);
01225 }
01226 
01227 
01228 Variability
01229 ArrayType::GetVariability() const {
01230     return child ? child->GetVariability() : Variability(Variability::Uniform);
01231 }
01232 
01233 
01234 bool
01235 ArrayType::IsFloatType() const {
01236     return false; 
01237 }
01238 
01239 
01240 bool
01241 ArrayType::IsIntType() const {
01242     return false; 
01243 }
01244 
01245 
01246 bool
01247 ArrayType::IsUnsignedType() const {
01248     return false; 
01249 }
01250 
01251 
01252 bool
01253 ArrayType::IsBoolType() const {
01254     return false; 
01255 }
01256 
01257 
01258 bool
01259 ArrayType::IsConstType() const {
01260     return child ? child->IsConstType() : false;
01261 }
01262 
01263 
01264 const Type *
01265 ArrayType::GetBaseType() const {
01266     const Type *type = child;
01267     const ArrayType *at = CastType<ArrayType>(type);
01268     // Keep walking until we reach a child that isn't itself an array
01269     while (at) {
01270         type = at->child;
01271         at = CastType<ArrayType>(type);
01272     }
01273     return type;
01274 }
01275 
01276 
01277 const ArrayType *
01278 ArrayType::GetAsVaryingType() const {
01279     if (child == NULL) {
01280         Assert(m->errorCount > 0);
01281         return NULL;
01282     }
01283     return new ArrayType(child->GetAsVaryingType(), numElements);
01284 }
01285 
01286 
01287 const ArrayType *
01288 ArrayType::GetAsUniformType() const {
01289     if (child == NULL) {
01290         Assert(m->errorCount > 0);
01291         return NULL;
01292     }
01293     return new ArrayType(child->GetAsUniformType(), numElements);
01294 }
01295 
01296 
01297 const ArrayType *
01298 ArrayType::GetAsUnboundVariabilityType() const {
01299     if (child == NULL) {
01300         Assert(m->errorCount > 0);
01301         return NULL;
01302     }
01303     return new ArrayType(child->GetAsUnboundVariabilityType(), numElements);
01304 }
01305 
01306 
01307 const ArrayType *
01308 ArrayType::GetAsSOAType(int width) const {
01309     if (child == NULL) {
01310         Assert(m->errorCount > 0);
01311         return NULL;
01312     }
01313     return new ArrayType(child->GetAsSOAType(width), numElements);
01314 }
01315 
01316 
01317 const ArrayType *
01318 ArrayType::ResolveUnboundVariability(Variability v) const {
01319     if (child == NULL) {
01320         Assert(m->errorCount > 0);
01321         return NULL;
01322     }
01323     return new ArrayType(child->ResolveUnboundVariability(v), numElements);
01324 }
01325 
01326 
01327 const ArrayType *
01328 ArrayType::GetAsUnsignedType() const {
01329     if (child == NULL) {
01330         Assert(m->errorCount > 0);
01331         return NULL;
01332     }
01333     return new ArrayType(child->GetAsUnsignedType(), numElements);
01334 }
01335 
01336 
01337 const ArrayType *
01338 ArrayType::GetAsConstType() const {
01339     if (child == NULL) {
01340         Assert(m->errorCount > 0);
01341         return NULL;
01342     }
01343     return new ArrayType(child->GetAsConstType(), numElements);
01344 }
01345 
01346 
01347 const ArrayType *
01348 ArrayType::GetAsNonConstType() const {
01349     if (child == NULL) {
01350         Assert(m->errorCount > 0);
01351         return NULL;
01352     }
01353     return new ArrayType(child->GetAsNonConstType(), numElements);
01354 }
01355 
01356 
01357 int
01358 ArrayType::GetElementCount() const {
01359     return numElements;
01360 }
01361 
01362 
01363 const Type *
01364 ArrayType::GetElementType() const {
01365     return child;
01366 }
01367 
01368 
01369 std::string
01370 ArrayType::GetString() const {
01371     const Type *base = GetBaseType();
01372     if (base == NULL) {
01373         Assert(m->errorCount > 0);
01374         return "";
01375     }
01376     std::string s = base->GetString();
01377 
01378     const ArrayType *at = this;
01379     // Walk through this and any children arrays and print all of their
01380     // dimensions
01381     while (at) {
01382         char buf[16];
01383         if (at->numElements > 0)
01384             sprintf(buf, "%d", at->numElements);
01385         else
01386             buf[0] = '\0';
01387         s += std::string("[") + std::string(buf) + std::string("]");
01388         at = CastType<ArrayType>(at->child);
01389     }
01390     return s;
01391 }
01392 
01393 
01394 std::string
01395 ArrayType::Mangle() const {
01396     if (child == NULL) {
01397         Assert(m->errorCount > 0);
01398         return "(error)";
01399     }
01400     std::string s = child->Mangle();
01401     char buf[16];
01402     if (numElements > 0)
01403         sprintf(buf, "%d", numElements);
01404     else
01405         buf[0] = '\0';
01406     return s + "[" + buf + "]";
01407 }
01408 
01409 
01410 std::string
01411 ArrayType::GetCDeclaration(const std::string &name) const {
01412     const Type *base = GetBaseType();
01413     if (base == NULL) {
01414         Assert(m->errorCount > 0);
01415         return "";
01416     }
01417 
01418     int soaWidth = base->GetSOAWidth();
01419     base = base->GetAsUniformType();
01420 
01421     std::string s = base->GetCDeclaration(name);
01422 
01423     const ArrayType *at = this;
01424     while (at) {
01425         char buf[16];
01426         if (at->numElements > 0)
01427             sprintf(buf, "%d", at->numElements);
01428         else
01429             buf[0] = '\0';
01430         s += std::string("[") + std::string(buf) + std::string("]");
01431         at = CastType<ArrayType>(at->child);
01432     }
01433 
01434     if (soaWidth > 0) {
01435         char buf[16];
01436         sprintf(buf, "[%d]", soaWidth);
01437         s += buf;
01438     }
01439 
01440     return s;
01441 }
01442 
01443 
01444 int
01445 ArrayType::TotalElementCount() const {
01446     const ArrayType *ct = CastType<ArrayType>(child);
01447     if (ct != NULL)
01448         return numElements * ct->TotalElementCount();
01449     else
01450         return numElements;
01451 }
01452 
01453 
01454 llvm::DIType
01455 ArrayType::GetDIType(llvm::DIDescriptor scope) const {
01456     if (child == NULL) {
01457         Assert(m->errorCount > 0);
01458         return llvm::DIType();
01459     }
01460 
01461     llvm::DIType eltType = child->GetDIType(scope);
01462     return lCreateDIArray(eltType, numElements);
01463 }
01464 
01465 
01466 ArrayType *
01467 ArrayType::GetSizedArray(int sz) const {
01468     Assert(numElements == 0);
01469     return new ArrayType(child, sz);
01470 }
01471 
01472 
01473 const Type *
01474 ArrayType::SizeUnsizedArrays(const Type *type, Expr *initExpr) {
01475     const ArrayType *at = CastType<ArrayType>(type);
01476     if (at == NULL)
01477         return type;
01478 
01479     ExprList *exprList = dynamic_cast<ExprList *>(initExpr);
01480     if (exprList == NULL || exprList->exprs.size() == 0)
01481         return type;
01482 
01483     // If the current dimension is unsized, then size it according to the
01484     // length of the expression list
01485     if (at->GetElementCount() == 0) {
01486         type = at->GetSizedArray(exprList->exprs.size());
01487         at = CastType<ArrayType>(type);
01488     }
01489 
01490     // Is there another nested level of expression lists?  If not, bail out
01491     // now.  Otherwise we'll use the first one to size the next dimension
01492     // (after checking below that it has the same length as all of the
01493     // other ones.
01494     ExprList *nextList = dynamic_cast<ExprList *>(exprList->exprs[0]);
01495     if (nextList == NULL)
01496         return type;
01497 
01498     const Type *nextType = at->GetElementType();
01499     const ArrayType *nextArrayType = CastType<ArrayType>(nextType);
01500     if (nextArrayType != NULL && nextArrayType->GetElementCount() == 0) {
01501         // If the recursive call to SizeUnsizedArrays at the bottom of the
01502         // function is going to size an unsized dimension, make sure that
01503         // all of the sub-expression lists are the same length--i.e. issue
01504         // an error if we have something like
01505         // int x[][] = { { 1 }, { 1, 2, 3, 4 } };
01506         unsigned int nextSize = nextList->exprs.size();
01507         for (unsigned int i = 1; i < exprList->exprs.size(); ++i) {
01508             if (exprList->exprs[i] == NULL) {
01509                 // We should have seen an error earlier in this case.
01510                 Assert(m->errorCount > 0);
01511                 continue;
01512             }
01513 
01514             ExprList *el = dynamic_cast<ExprList *>(exprList->exprs[i]);
01515             if (el == NULL || el->exprs.size() != nextSize) {
01516                 Error(Union(exprList->exprs[0]->pos, exprList->exprs[i]->pos), 
01517                       "Inconsistent initializer expression list lengths "
01518                       "make it impossible to size unsized array dimensions.");
01519                 return NULL;
01520             }
01521         }
01522     }
01523 
01524     // Recursively call SizeUnsizedArrays() to get the child type for the
01525     // array that we were able to size here.
01526     return new ArrayType(SizeUnsizedArrays(at->GetElementType(), nextList),
01527                          at->GetElementCount());
01528 }
01529 
01530 
01531 ///////////////////////////////////////////////////////////////////////////
01532 // VectorType
01533 
01534 VectorType::VectorType(const AtomicType *b, int a) 
01535     : SequentialType(VECTOR_TYPE), base(b), numElements(a) {
01536     Assert(numElements > 0);
01537     Assert(base != NULL);
01538 }
01539 
01540 
01541 Variability
01542 VectorType::GetVariability() const {
01543     return base->GetVariability(); 
01544 }
01545 
01546 
01547 bool
01548 VectorType::IsFloatType() const {
01549     return base->IsFloatType(); 
01550 }
01551 
01552 
01553 bool
01554 VectorType::IsIntType() const {
01555     return base->IsIntType(); 
01556 }
01557 
01558 
01559 bool
01560 VectorType::IsUnsignedType() const {
01561     return base->IsUnsignedType(); 
01562 }
01563 
01564 
01565 bool
01566 VectorType::IsBoolType() const {
01567     return base->IsBoolType(); 
01568 }
01569 
01570 
01571 bool
01572 VectorType::IsConstType() const {
01573     return base->IsConstType(); 
01574 }
01575 
01576 
01577 const Type *
01578 VectorType::GetBaseType() const {
01579     return base;
01580 }
01581 
01582 
01583 const VectorType *
01584 VectorType::GetAsVaryingType() const {
01585     return new VectorType(base->GetAsVaryingType(), numElements);
01586 }
01587 
01588 
01589 const VectorType *
01590 VectorType::GetAsUniformType() const {
01591     return new VectorType(base->GetAsUniformType(), numElements);
01592 }
01593 
01594 
01595 const VectorType *
01596 VectorType::GetAsUnboundVariabilityType() const {
01597     return new VectorType(base->GetAsUnboundVariabilityType(), numElements);
01598 }
01599 
01600 
01601 const VectorType *
01602 VectorType::GetAsSOAType(int width) const {
01603     return new VectorType(base->GetAsSOAType(width), numElements);
01604 }
01605 
01606 
01607 const VectorType *
01608 VectorType::ResolveUnboundVariability(Variability v) const {
01609     return new VectorType(base->ResolveUnboundVariability(v), numElements);
01610 }
01611 
01612 
01613 const VectorType *
01614 VectorType::GetAsConstType() const {
01615     return new VectorType(base->GetAsConstType(), numElements);
01616 }
01617 
01618 
01619 const VectorType *
01620 VectorType::GetAsNonConstType() const {
01621     return new VectorType(base->GetAsNonConstType(), numElements);
01622 }
01623 
01624 
01625 std::string
01626 VectorType::GetString() const {
01627     std::string s = base->GetString();
01628     char buf[16];
01629     sprintf(buf, "<%d>", numElements);
01630     return s + std::string(buf);
01631 }
01632 
01633 
01634 std::string
01635 VectorType::Mangle() const {
01636     std::string s = base->Mangle();
01637     char buf[16];
01638     sprintf(buf, "<%d>", numElements);
01639     return s + std::string(buf);
01640 }
01641 
01642 
01643 std::string
01644 VectorType::GetCDeclaration(const std::string &name) const {
01645     std::string s = base->GetCDeclaration("");
01646     char buf[16];
01647     sprintf(buf, "%d", numElements);
01648     return s + std::string(buf) + "  " + name;
01649 }
01650 
01651 
01652 int
01653 VectorType::GetElementCount() const {
01654     return numElements;
01655 }
01656 
01657 
01658 const AtomicType *
01659 VectorType::GetElementType() const {
01660     return base;
01661 }
01662 
01663 
01664 llvm::Type *
01665 VectorType::LLVMType(llvm::LLVMContext *ctx) const {
01666     if (base == NULL) {
01667         Assert(m->errorCount > 0);
01668         return NULL;
01669     }
01670 
01671     llvm::Type *bt = base->LLVMType(ctx);
01672     if (!bt)
01673         return NULL;
01674 
01675     if (base->IsUniformType())
01676         // vectors of uniform types are laid out across LLVM vectors, with
01677         // the llvm vector size set to be a multiple of the machine's
01678         // natural vector size (e.g. 4 on SSE).  This is a roundabout way
01679         // of ensuring that LLVM lays them out into machine vector
01680         // registers so that e.g. if we want to add two uniform 4 float
01681         // vectors, that is turned into a single addps on SSE.
01682         return llvm::VectorType::get(bt, getVectorMemoryCount());
01683     else if (base->IsVaryingType())
01684         // varying types are already laid out to fill HW vector registers,
01685         // so a vector type here is just expanded out as an llvm array.
01686         return llvm::ArrayType::get(bt, getVectorMemoryCount());
01687     else if (base->IsSOAType())
01688         return llvm::ArrayType::get(bt, numElements);
01689     else {
01690         FATAL("Unexpected variability in VectorType::LLVMType()");
01691         return NULL;
01692     }
01693 }
01694 
01695 
01696 llvm::DIType
01697 VectorType::GetDIType(llvm::DIDescriptor scope) const {
01698     llvm::DIType eltType = base->GetDIType(scope);
01699     llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, numElements-1);
01700     llvm::DIArray subArray = m->diBuilder->getOrCreateArray(sub);
01701 
01702     uint64_t sizeBits = eltType.getSizeInBits() * numElements;
01703 
01704     // vectors of varying types are already naturally aligned to the
01705     // machine's vector width, but arrays of uniform types need to be
01706     // explicitly aligned to the machines natural vector alignment.
01707     uint64_t align = eltType.getAlignInBits();
01708     if (IsUniformType())
01709         align = 4 * g->target.nativeVectorWidth;
01710 
01711     if (IsUniformType() || IsVaryingType())
01712         return m->diBuilder->createVectorType(sizeBits, align, eltType, subArray);
01713     else if (IsSOAType()) {
01714         ArrayType at(base, numElements);
01715         return at.GetDIType(scope);
01716     }
01717     else {
01718         FATAL("Unexpected variability in VectorType::GetDIType()");
01719         return llvm::DIType();
01720     }
01721 }
01722 
01723 
01724 int
01725 VectorType::getVectorMemoryCount() const {
01726     if (base->IsVaryingType())
01727         return numElements;
01728     else if (base->IsUniformType()) {
01729         int nativeWidth = g->target.nativeVectorWidth;
01730         if (Type::Equal(base->GetAsUniformType(), AtomicType::UniformInt64) ||
01731             Type::Equal(base->GetAsUniformType(), AtomicType::UniformUInt64) ||
01732             Type::Equal(base->GetAsUniformType(), AtomicType::UniformDouble))
01733             // target.nativeVectorWidth should be in terms of 32-bit
01734             // values, so for the 64-bit guys, it takes half as many of
01735             // them to fill the native width
01736             nativeWidth /= 2;
01737         // and now round up the element count to be a multiple of
01738         // nativeWidth
01739         return (numElements + (nativeWidth - 1)) & ~(nativeWidth-1);
01740     }
01741     else if (base->IsSOAType()) {
01742         FATAL("VectorType SOA getVectorMemoryCount");
01743         return -1;
01744     }
01745     else {
01746         FATAL("Unexpected variability in VectorType::getVectorMemoryCount()");
01747         return -1;
01748     }
01749 }
01750 
01751 
01752 ///////////////////////////////////////////////////////////////////////////
01753 // StructType
01754 
01755 // We maintain a map from struct names to LLVM struct types so that we can
01756 // uniquely get the llvm::StructType * for a given ispc struct type.  Note
01757 // that we need to mangle the name a bit so that we can e.g. differentiate
01758 // between the uniform and varying variants of a given struct type.  This
01759 // is handled by lMangleStructName() below.
01760 static std::map<std::string, llvm::StructType *> lStructTypeMap;
01761 
01762 /** Using a struct's name, its variability, and the vector width for the
01763     current compilation target, this function generates a string that
01764     encodes that full structure type, for use in the lStructTypeMap.  Note
01765     that the vector width is needed in order to differentiate between
01766     'varying' structs with different compilation targets, which have
01767     different memory layouts...
01768  */
01769 static std::string
01770 lMangleStructName(const std::string &name, Variability variability) {
01771     char buf[32];
01772     std::string n;
01773 
01774     // Encode vector width
01775     sprintf(buf, "v%d", g->target.vectorWidth);
01776     n += buf;
01777 
01778     // Variability
01779     switch (variability.type) {
01780     case Variability::Uniform:
01781         n += "_uniform_";
01782         break;
01783     case Variability::Varying:
01784         n += "_varying_";
01785         break;
01786     case Variability::SOA:
01787         sprintf(buf, "_soa%d_", variability.soaWidth);
01788         n += buf;
01789         break;
01790     default:
01791         FATAL("Unexpected varaibility in lMangleStructName()");
01792     }
01793     
01794     // And stuff the name at the end....
01795     n += name;
01796     return n;
01797 }
01798 
01799         
01800 StructType::StructType(const std::string &n, const llvm::SmallVector<const Type *, 8> &elts, 
01801                        const llvm::SmallVector<std::string, 8> &en,
01802                        const llvm::SmallVector<SourcePos, 8> &ep,
01803                        bool ic, Variability v, SourcePos p) 
01804     : CollectionType(STRUCT_TYPE), name(n), elementTypes(elts), elementNames(en), 
01805       elementPositions(ep), variability(v), isConst(ic), pos(p) {
01806     oppositeConstStructType = NULL;
01807     finalElementTypes.resize(elts.size(), NULL);
01808     
01809     if (variability != Variability::Unbound) {
01810         // For structs with non-unbound variability, we'll create the
01811         // correspoing LLVM struct type now, if one hasn't been made
01812         // already.
01813 
01814         // Create a unique anonymous struct name if we have an anonymous
01815         // struct (name == ""), or if we are creating a derived type from
01816         // an anonymous struct (e.g. the varying variant--name == '$').
01817         if (name == "" || name[0] == '$') {
01818             char buf[16];
01819             static int count = 0;
01820             sprintf(buf, "$anon%d", count);
01821             name = buf;
01822             ++count;
01823         }
01824 
01825         // If a non-opaque LLVM struct for this type has already been
01826         // created, we're done.  For an opaque struct type, we'll override
01827         // the old definition now that we have a full definition.
01828         std::string mname = lMangleStructName(name, variability);
01829         if (lStructTypeMap.find(mname) != lStructTypeMap.end() &&
01830             lStructTypeMap[mname]->isOpaque() == false)
01831             return;
01832 
01833         // Actually make the LLVM struct
01834         std::vector<llvm::Type *> elementTypes;
01835         int nElements = GetElementCount();
01836         if (nElements == 0) {
01837             elementTypes.push_back(LLVMTypes::Int8Type);
01838         }
01839         else {
01840             for (int i = 0; i < nElements; ++i) {
01841                 const Type *type = GetElementType(i);
01842                 if (type == NULL) {
01843                     Assert(m->errorCount > 0);
01844                     return;
01845                 }
01846                 else if (CastType<FunctionType>(type) != NULL) {
01847                     Error(elementPositions[i], "Method declarations are not "
01848                           "supported.");
01849                     return;
01850                 }
01851                 else
01852                     elementTypes.push_back(type->LLVMType(g->ctx));
01853             }
01854         }
01855 
01856         if (lStructTypeMap.find(mname) == lStructTypeMap.end()) {
01857             // New struct definition
01858             llvm::StructType *st =
01859                 llvm::StructType::create(*g->ctx, elementTypes, mname);
01860             lStructTypeMap[mname] = st;
01861         }
01862         else {
01863             // Definition for what was before just a declaration
01864             lStructTypeMap[mname]->setBody(elementTypes);
01865         }
01866     }
01867 }
01868 
01869 
01870 Variability
01871 StructType::GetVariability() const  {
01872     return variability; 
01873 }
01874 
01875 
01876 bool
01877 StructType::IsBoolType() const {
01878     return false; 
01879 }
01880 
01881 
01882 bool
01883 StructType::IsFloatType() const {
01884     return false; 
01885 }
01886 
01887 
01888 bool
01889 StructType::IsIntType() const  {
01890     return false; 
01891 }
01892 
01893 
01894 bool
01895 StructType::IsUnsignedType() const {
01896     return false; 
01897 }
01898 
01899 
01900 bool
01901 StructType::IsConstType() const {
01902     return isConst; 
01903 }
01904 
01905 
01906 const Type *
01907 StructType::GetBaseType() const {
01908     return this;
01909 }
01910 
01911 
01912 const StructType *
01913 StructType::GetAsVaryingType() const {
01914     if (IsVaryingType()) 
01915         return this;
01916     else
01917         return new StructType(name, elementTypes, elementNames, elementPositions,
01918                               isConst, Variability(Variability::Varying), pos);
01919 }
01920 
01921 
01922 const StructType *
01923 StructType::GetAsUniformType() const {
01924     if (IsUniformType()) 
01925         return this;
01926     else
01927         return new StructType(name, elementTypes, elementNames, elementPositions,
01928                               isConst, Variability(Variability::Uniform), pos);
01929 }
01930 
01931 
01932 const StructType *
01933 StructType::GetAsUnboundVariabilityType() const {
01934     if (HasUnboundVariability()) 
01935         return this;
01936     else
01937         return new StructType(name, elementTypes, elementNames, elementPositions,
01938                               isConst, Variability(Variability::Unbound), pos);
01939 }
01940 
01941 
01942 const StructType *
01943 StructType::GetAsSOAType(int width) const {
01944     if (GetSOAWidth() == width)
01945         return this;
01946 
01947     if (checkIfCanBeSOA(this) == false)
01948         return NULL;
01949 
01950     return new StructType(name, elementTypes, elementNames, elementPositions,
01951                           isConst, Variability(Variability::SOA, width), pos);
01952 }
01953 
01954 
01955 const StructType *
01956 StructType::ResolveUnboundVariability(Variability v) const {
01957     Assert(v != Variability::Unbound);
01958 
01959     if (variability != Variability::Unbound)
01960         return this;
01961 
01962     // We don't resolve the members here but leave them unbound, so that if
01963     // resolve to varying but later want to get the uniform version of this
01964     // type, for example, then we still have the information around about
01965     // which element types were originally unbound...
01966     return new StructType(name, elementTypes, elementNames, elementPositions,
01967                           isConst, v, pos);
01968 }
01969 
01970 
01971 const StructType *
01972 StructType::GetAsConstType() const {
01973     if (isConst == true)
01974         return this;
01975     else if (oppositeConstStructType != NULL)
01976         return oppositeConstStructType;
01977     else {
01978         oppositeConstStructType = 
01979             new StructType(name, elementTypes, elementNames, elementPositions,
01980                            true, variability, pos);
01981         oppositeConstStructType->oppositeConstStructType = this;
01982         return oppositeConstStructType;
01983     }
01984 }
01985 
01986 
01987 const StructType *
01988 StructType::GetAsNonConstType() const {
01989     if (isConst == false)
01990         return this;
01991     else if (oppositeConstStructType != NULL)
01992         return oppositeConstStructType;
01993     else {
01994         oppositeConstStructType = 
01995             new StructType(name, elementTypes, elementNames, elementPositions,
01996                            false, variability, pos);
01997         oppositeConstStructType->oppositeConstStructType = this;
01998         return oppositeConstStructType;
01999     }
02000 }
02001 
02002 
02003 std::string
02004 StructType::GetString() const {
02005     std::string ret;
02006     if (isConst)
02007         ret += "const ";
02008     ret += variability.GetString();
02009     ret += " ";
02010 
02011     if (name[0] == '$') {
02012         // Print the whole anonymous struct declaration
02013         ret += std::string("struct { ") + name;
02014         for (unsigned int i = 0; i < elementTypes.size(); ++i) {
02015             ret += elementTypes[i]->GetString();
02016             ret += " ";
02017             ret += elementNames[i];
02018             ret += "; ";
02019         }
02020         ret += "}";
02021     }
02022     else {
02023         ret += "struct ";
02024         ret += name;
02025     }
02026 
02027     return ret;
02028 }
02029 
02030 
02031 /** Mangle a struct name for use in function name mangling. */
02032 static std::string
02033 lMangleStruct(Variability variability, bool isConst, const std::string &name) {
02034     Assert(variability != Variability::Unbound);
02035 
02036     std::string ret;
02037     ret += "s[";
02038     if (isConst)
02039         ret += "_c_";
02040     ret += variability.MangleString();
02041 
02042     ret += name + std::string("]");
02043     return ret;
02044 }
02045 
02046 
02047 std::string
02048 StructType::Mangle() const {
02049     return lMangleStruct(variability, isConst, name);
02050 }
02051     
02052 
02053 std::string
02054 StructType::GetCDeclaration(const std::string &n) const {
02055     std::string ret;
02056     if (isConst) ret += "const ";
02057     ret += std::string("struct ") + name;
02058     if (lShouldPrintName(n)) {
02059         ret += std::string(" ") + n;
02060 
02061         if (variability.soaWidth > 0) {
02062             char buf[32];
02063             // This has to match the naming scheme used in lEmitStructDecls()
02064             // in module.cpp
02065             sprintf(buf, "_SOA%d", variability.soaWidth);
02066             ret += buf;
02067         }
02068     }
02069 
02070     return ret;
02071 }
02072 
02073 
02074 llvm::Type *
02075 StructType::LLVMType(llvm::LLVMContext *ctx) const {
02076     Assert(variability != Variability::Unbound);
02077     std::string mname = lMangleStructName(name, variability);
02078     if (lStructTypeMap.find(mname) == lStructTypeMap.end()) {
02079         Assert(m->errorCount > 0);
02080         return NULL;
02081     }
02082     return lStructTypeMap[mname];
02083 }
02084 
02085 
02086 llvm::DIType
02087 StructType::GetDIType(llvm::DIDescriptor scope) const {
02088     uint64_t currentSize = 0, align = 0;
02089 
02090     std::vector<llvm::Value *> elementLLVMTypes;
02091     // Walk through the elements of the struct; for each one figure out its
02092     // alignment and size, using that to figure out its offset w.r.t. the
02093     // start of the structure.
02094     for (unsigned int i = 0; i < elementTypes.size(); ++i) {
02095         llvm::DIType eltType = GetElementType(i)->GetDIType(scope);
02096         uint64_t eltAlign = eltType.getAlignInBits();
02097         uint64_t eltSize = eltType.getSizeInBits();
02098         Assert(eltAlign != 0);
02099 
02100         // The alignment for the entire structure is the maximum of the
02101         // required alignments of its elements
02102         align = std::max(align, eltAlign);
02103 
02104         // Move the current size forward if needed so that the current
02105         // element starts at an offset that's the correct alignment.
02106         if (currentSize > 0 && (currentSize % eltAlign))
02107             currentSize += eltAlign - (currentSize % eltAlign);
02108         Assert((currentSize == 0) || (currentSize % eltAlign) == 0);
02109 
02110         llvm::DIFile diFile = elementPositions[i].GetDIFile();
02111         int line = elementPositions[i].first_line;
02112         llvm::DIType fieldType = 
02113             m->diBuilder->createMemberType(scope, elementNames[i], diFile, 
02114                                            line, eltSize, eltAlign, 
02115                                            currentSize, 0, eltType);
02116         elementLLVMTypes.push_back(fieldType);
02117 
02118         currentSize += eltSize;
02119     }
02120 
02121     // Round up the struct's entire size so that it's a multiple of the
02122     // required alignment that we figured out along the way...
02123     if (currentSize > 0 && (currentSize % align))
02124         currentSize += align - (currentSize % align);
02125 
02126     llvm::DIArray elements = m->diBuilder->getOrCreateArray(elementLLVMTypes);
02127     llvm::DIFile diFile = pos.GetDIFile();
02128     return m->diBuilder->createStructType(scope, name, diFile, pos.first_line, currentSize, 
02129                                           align, 0, elements);
02130 }
02131 
02132 
02133 const Type *
02134 StructType::GetElementType(int i) const {
02135     Assert(variability != Variability::Unbound);
02136     Assert(i < (int)elementTypes.size());
02137 
02138     if (finalElementTypes[i] == NULL) {
02139         const Type *type = elementTypes[i];
02140         if (type == NULL) {
02141             Assert(m->errorCount > 0);
02142             return NULL;
02143         }
02144 
02145         // If the element has unbound variability, resolve its variability to
02146         // the struct type's variability
02147         type = type ->ResolveUnboundVariability(variability);
02148         if (isConst)
02149             type = type->GetAsConstType();
02150         finalElementTypes[i] = type;
02151     }
02152 
02153     return finalElementTypes[i];
02154 }
02155 
02156 
02157 const Type *
02158 StructType::GetElementType(const std::string &n) const {
02159     for (unsigned int i = 0; i < elementNames.size(); ++i)
02160         if (elementNames[i] == n)
02161             return GetElementType(i);
02162     return NULL;
02163 }
02164 
02165 
02166 int
02167 StructType::GetElementNumber(const std::string &n) const {
02168     for (unsigned int i = 0; i < elementNames.size(); ++i)
02169         if (elementNames[i] == n)
02170             return i;
02171     return -1;
02172 }
02173 
02174 
02175 bool
02176 StructType::checkIfCanBeSOA(const StructType *st) {
02177     bool ok = true;
02178     for (int i = 0; i < (int)st->elementTypes.size(); ++i) {
02179         const Type *eltType = st->elementTypes[i];
02180         const StructType *childStructType = CastType<StructType>(eltType);
02181 
02182         if (childStructType != NULL)
02183             ok &= checkIfCanBeSOA(childStructType);
02184         else if (eltType->HasUnboundVariability() == false) {
02185             Error(st->elementPositions[i], "Unable to apply SOA conversion to "
02186                   "struct due to \"%s\" member \"%s\" with bound \"%s\" "
02187                   "variability.", eltType->GetString().c_str(),
02188                   st->elementNames[i].c_str(), 
02189                   eltType->IsUniformType() ? "uniform" : "varying");
02190             ok = false;
02191         }
02192         else if (CastType<ReferenceType>(eltType)) {
02193             Error(st->elementPositions[i], "Unable to apply SOA conversion to "
02194                   "struct due to member \"%s\" with reference type \"%s\".",
02195                   st->elementNames[i].c_str(), eltType->GetString().c_str());
02196             ok = false;
02197         }
02198     }
02199     return ok;
02200 }
02201 
02202 
02203 ///////////////////////////////////////////////////////////////////////////
02204 // UndefinedStructType
02205 
02206 UndefinedStructType::UndefinedStructType(const std::string &n, 
02207                                          const Variability var, bool ic,
02208                                          SourcePos p) 
02209     : Type(UNDEFINED_STRUCT_TYPE), name(n), variability(var), isConst(ic), pos(p) {
02210     Assert(name != "");
02211     if (variability != Variability::Unbound) {
02212         // Create a new opaque LLVM struct type for this struct name
02213         std::string mname = lMangleStructName(name, variability);
02214         if (lStructTypeMap.find(mname) == lStructTypeMap.end())
02215             lStructTypeMap[mname] = llvm::StructType::create(*g->ctx, mname);
02216     }
02217 }
02218 
02219 
02220 Variability
02221 UndefinedStructType::GetVariability() const {
02222     return variability;
02223 }
02224 
02225 
02226 bool
02227 UndefinedStructType::IsBoolType() const {
02228     return false;
02229 }
02230 
02231 
02232 bool
02233 UndefinedStructType::IsFloatType() const {
02234     return false;
02235 }
02236 
02237 
02238 bool
02239 UndefinedStructType::IsIntType() const {
02240     return false;
02241 }
02242 
02243 
02244 bool
02245 UndefinedStructType::IsUnsignedType() const {
02246     return false;
02247 }
02248 
02249 
02250 bool
02251 UndefinedStructType::IsConstType() const {
02252     return isConst;
02253 }
02254 
02255 
02256 const Type *
02257 UndefinedStructType::GetBaseType() const {
02258     return this;
02259 }
02260 
02261 
02262 const UndefinedStructType *
02263 UndefinedStructType::GetAsVaryingType() const {
02264     if (variability == Variability::Varying)
02265         return this;
02266     return new UndefinedStructType(name, Variability::Varying, isConst, pos);
02267 }
02268 
02269 
02270 const UndefinedStructType *
02271 UndefinedStructType::GetAsUniformType() const {
02272     if (variability == Variability::Uniform)
02273         return this;
02274     return new UndefinedStructType(name, Variability::Uniform, isConst, pos);
02275 }
02276 
02277 
02278 const UndefinedStructType *
02279 UndefinedStructType::GetAsUnboundVariabilityType() const {
02280     if (variability == Variability::Unbound)
02281         return this;
02282     return new UndefinedStructType(name, Variability::Unbound, isConst, pos);
02283 }
02284 
02285 
02286 const UndefinedStructType *
02287 UndefinedStructType::GetAsSOAType(int width) const {
02288     FATAL("UndefinedStructType::GetAsSOAType() shouldn't be called.");
02289     return NULL;
02290 }
02291 
02292 
02293 const UndefinedStructType *
02294 UndefinedStructType::ResolveUnboundVariability(Variability v) const {
02295     if (variability != Variability::Unbound)
02296         return this;
02297     return new UndefinedStructType(name, v, isConst, pos);
02298 }
02299 
02300 
02301 const UndefinedStructType *
02302 UndefinedStructType::GetAsConstType() const {
02303     if (isConst)
02304         return this;
02305     return new UndefinedStructType(name, variability, true, pos);
02306 }
02307 
02308 
02309 const UndefinedStructType *
02310 UndefinedStructType::GetAsNonConstType() const {
02311     if (isConst == false)
02312         return this;
02313     return new UndefinedStructType(name, variability, false, pos);
02314 }
02315 
02316 
02317 std::string
02318 UndefinedStructType::GetString() const {
02319     std::string ret;
02320     if (isConst)   ret += "const ";
02321     ret += variability.GetString();
02322     ret += " struct ";
02323     ret += name;
02324     return ret;
02325 }
02326 
02327 
02328 std::string
02329 UndefinedStructType::Mangle() const {
02330     return lMangleStruct(variability, isConst, name);
02331 }
02332 
02333 
02334 std::string
02335 UndefinedStructType::GetCDeclaration(const std::string &n) const {
02336     std::string ret;
02337     if (isConst) ret += "const ";
02338     ret += std::string("struct ") + name;
02339     if (lShouldPrintName(n))
02340         ret += std::string(" ") + n;
02341     return ret;
02342 }
02343 
02344 
02345 llvm::Type *
02346 UndefinedStructType::LLVMType(llvm::LLVMContext *ctx) const {
02347     Assert(variability != Variability::Unbound);
02348     std::string mname = lMangleStructName(name, variability);
02349     if (lStructTypeMap.find(mname) == lStructTypeMap.end()) {
02350         Assert(m->errorCount > 0);
02351         return NULL;
02352     }
02353     return lStructTypeMap[mname];
02354 }
02355 
02356 
02357 llvm::DIType
02358 UndefinedStructType::GetDIType(llvm::DIDescriptor scope) const {
02359     llvm::DIFile diFile = pos.GetDIFile();
02360     llvm::DIArray elements;
02361     return m->diBuilder->createStructType(scope, name, diFile, pos.first_line, 
02362                                           0 /* size */, 0 /* align */, 
02363                                           0 /* flags */, elements); 
02364 }
02365 
02366 
02367 ///////////////////////////////////////////////////////////////////////////
02368 // ReferenceType
02369 
02370 ReferenceType::ReferenceType(const Type *t) 
02371     : Type(REFERENCE_TYPE), targetType(t) {
02372     asOtherConstType = NULL;
02373 }
02374 
02375 
02376 Variability
02377 ReferenceType::GetVariability() const {
02378     if (targetType == NULL) {
02379         Assert(m->errorCount > 0);
02380         return Variability(Variability::Unbound);
02381     }
02382     return targetType->GetVariability(); 
02383 }
02384 
02385 
02386 bool
02387 ReferenceType::IsBoolType() const {
02388     if (targetType == NULL) {
02389         Assert(m->errorCount > 0);
02390         return false;
02391     }
02392     return targetType->IsBoolType(); 
02393 }
02394 
02395 
02396 bool
02397 ReferenceType::IsFloatType() const {
02398     if (targetType == NULL) {
02399         Assert(m->errorCount > 0);
02400         return false;
02401     }
02402     return targetType->IsFloatType(); 
02403 }
02404 
02405 
02406 bool
02407 ReferenceType::IsIntType() const {
02408     if (targetType == NULL) {
02409         Assert(m->errorCount > 0);
02410         return false;
02411     }
02412     return targetType->IsIntType(); 
02413 }
02414 
02415 
02416 bool
02417 ReferenceType::IsUnsignedType() const {
02418     if (targetType == NULL) {
02419         Assert(m->errorCount > 0);
02420         return false;
02421     }
02422     return targetType->IsUnsignedType(); 
02423 }
02424 
02425 
02426 bool
02427 ReferenceType::IsConstType() const {
02428     if (targetType == NULL) {
02429         Assert(m->errorCount > 0);
02430         return false;
02431     }
02432     return targetType->IsConstType();
02433 }
02434 
02435 
02436 const Type *
02437 ReferenceType::GetReferenceTarget() const {
02438     return targetType;
02439 }
02440 
02441 
02442 const Type *
02443 ReferenceType::GetBaseType() const {
02444     if (targetType == NULL) {
02445         Assert(m->errorCount > 0);
02446         return NULL;
02447     }
02448     return targetType->GetBaseType();
02449 }
02450 
02451 
02452 const ReferenceType *
02453 ReferenceType::GetAsVaryingType() const {
02454     if (targetType == NULL) {
02455         Assert(m->errorCount > 0);
02456         return NULL;
02457     }
02458     if (IsVaryingType()) 
02459         return this;
02460     return new ReferenceType(targetType->GetAsVaryingType());
02461 }
02462 
02463 
02464 const ReferenceType *
02465 ReferenceType::GetAsUniformType() const {
02466     if (targetType == NULL) {
02467         Assert(m->errorCount > 0);
02468         return NULL;
02469     }
02470     if (IsUniformType()) 
02471         return this;
02472     return new ReferenceType(targetType->GetAsUniformType());
02473 }
02474 
02475 
02476 const ReferenceType *
02477 ReferenceType::GetAsUnboundVariabilityType() const {
02478     if (targetType == NULL) {
02479         Assert(m->errorCount > 0);
02480         return NULL;
02481     }
02482     if (HasUnboundVariability()) 
02483         return this;
02484     return new ReferenceType(targetType->GetAsUnboundVariabilityType());
02485 }
02486 
02487 
02488 const Type *
02489 ReferenceType::GetAsSOAType(int width) const {
02490     // FIXME: is this right?
02491     return new ArrayType(this, width);
02492 }
02493 
02494 
02495 const ReferenceType *
02496 ReferenceType::ResolveUnboundVariability(Variability v) const {
02497     if (targetType == NULL) {
02498         Assert(m->errorCount > 0);
02499         return NULL;
02500     }
02501     return new ReferenceType(targetType->ResolveUnboundVariability(v));
02502 }
02503     
02504 
02505 const ReferenceType *
02506 ReferenceType::GetAsConstType() const {
02507     if (targetType == NULL) {
02508         Assert(m->errorCount > 0);
02509         return NULL;
02510     }
02511     if (IsConstType())
02512         return this;
02513 
02514     if (asOtherConstType == NULL) {
02515         asOtherConstType = new ReferenceType(targetType->GetAsConstType());
02516         asOtherConstType->asOtherConstType = this;
02517     }
02518     return asOtherConstType;
02519 }
02520 
02521 
02522 const ReferenceType *
02523 ReferenceType::GetAsNonConstType() const {
02524     if (targetType == NULL) {
02525         Assert(m->errorCount > 0);
02526         return NULL;
02527     }
02528     if (!IsConstType())
02529         return this;
02530 
02531     if (asOtherConstType == NULL) {
02532         asOtherConstType = new ReferenceType(targetType->GetAsNonConstType());
02533         asOtherConstType->asOtherConstType = this;
02534     }
02535     return asOtherConstType;
02536 }
02537 
02538 
02539 std::string
02540 ReferenceType::GetString() const {
02541     if (targetType == NULL) {
02542         Assert(m->errorCount > 0);
02543         return "";
02544     }
02545 
02546     std::string ret = targetType->GetString();
02547 
02548     ret += std::string(" &");
02549     return ret;
02550 }
02551 
02552 
02553 std::string
02554 ReferenceType::Mangle() const {
02555     if (targetType == NULL) {
02556         Assert(m->errorCount > 0);
02557         return "";
02558     }
02559     std::string ret;
02560     ret += std::string("REF") + targetType->Mangle();
02561     return ret;
02562 }
02563 
02564 
02565 std::string
02566 ReferenceType::GetCDeclaration(const std::string &name) const {
02567     if (targetType == NULL) {
02568         Assert(m->errorCount > 0);
02569         return "";
02570     }
02571 
02572     const ArrayType *at = CastType<ArrayType>(targetType);
02573     if (at != NULL) {
02574         if (at->GetElementCount() == 0) {
02575             // emit unsized arrays as pointers to the base type..
02576             std::string ret;
02577             ret += at->GetElementType()->GetAsNonConstType()->GetCDeclaration("") + 
02578                 std::string(" *");
02579             if (lShouldPrintName(name))
02580                 ret += name;
02581             return ret;
02582         }
02583         else
02584             // otherwise forget about the reference part if it's an
02585             // array since C already passes arrays by reference...
02586             return targetType->GetCDeclaration(name);
02587     }
02588     else {
02589         std::string ret;
02590         ret += targetType->GetCDeclaration("") + std::string(" &");
02591         if (lShouldPrintName(name))
02592             ret += name;
02593         return ret;
02594     }
02595 }
02596 
02597 
02598 llvm::Type *
02599 ReferenceType::LLVMType(llvm::LLVMContext *ctx) const {
02600     if (targetType == NULL) {
02601         Assert(m->errorCount > 0);
02602         return NULL;
02603     }
02604 
02605     llvm::Type *t = targetType->LLVMType(ctx);
02606     if (t == NULL) {
02607         Assert(m->errorCount > 0);
02608         return NULL;
02609     }
02610 
02611     return llvm::PointerType::get(t, 0);
02612 }
02613 
02614 
02615 llvm::DIType
02616 ReferenceType::GetDIType(llvm::DIDescriptor scope) const {
02617     if (targetType == NULL) {
02618         Assert(m->errorCount > 0);
02619         return llvm::DIType();
02620     }
02621 
02622     llvm::DIType diTargetType = targetType->GetDIType(scope);
02623 #if defined(LLVM_3_0) || defined(LLVM_3_1)
02624     return m->diBuilder->createReferenceType(diTargetType);
02625 #else
02626     return m->diBuilder->createReferenceType(llvm::dwarf::DW_TAG_reference_type,
02627                                              diTargetType);
02628 #endif
02629 }
02630 
02631 
02632 ///////////////////////////////////////////////////////////////////////////
02633 // FunctionType
02634 
02635 FunctionType::FunctionType(const Type *r, 
02636                            const llvm::SmallVector<const Type *, 8> &a, 
02637                            SourcePos p)
02638     : Type(FUNCTION_TYPE), isTask(false), isExported(false), isExternC(false), 
02639       isUnmasked(false), returnType(r), paramTypes(a), 
02640       paramNames(llvm::SmallVector<std::string, 8>(a.size(), "")),
02641       paramDefaults(llvm::SmallVector<Expr *, 8>(a.size(), NULL)),
02642       paramPositions(llvm::SmallVector<SourcePos, 8>(a.size(), p)) {
02643     Assert(returnType != NULL);
02644     isSafe = false;
02645     costOverride = -1;
02646 }
02647 
02648 
02649 FunctionType::FunctionType(const Type *r,
02650                            const llvm::SmallVector<const Type *, 8> &a, 
02651                            const llvm::SmallVector<std::string, 8> &an, 
02652                            const llvm::SmallVector<Expr *, 8> &ad,
02653                            const llvm::SmallVector<SourcePos, 8> &ap,
02654                            bool it, bool is, bool ec, bool ium)
02655     : Type(FUNCTION_TYPE), isTask(it), isExported(is), isExternC(ec), 
02656       isUnmasked(ium), returnType(r), paramTypes(a), paramNames(an), 
02657       paramDefaults(ad), paramPositions(ap) {
02658     Assert(paramTypes.size() == paramNames.size() && 
02659            paramNames.size() == paramDefaults.size() &&
02660            paramDefaults.size() == paramPositions.size());
02661     Assert(returnType != NULL);
02662     isSafe = false;
02663     costOverride = -1;
02664 }
02665 
02666 
02667 Variability
02668 FunctionType::GetVariability() const {
02669     return Variability(Variability::Uniform);
02670 }
02671 
02672 
02673 bool
02674 FunctionType::IsFloatType() const {
02675     return false;
02676 }
02677 
02678 
02679 bool
02680 FunctionType::IsIntType() const {
02681     return false;
02682 }
02683 
02684 
02685 bool
02686 FunctionType::IsBoolType() const {
02687     return false;
02688 }
02689 
02690 
02691 bool
02692 FunctionType::IsUnsignedType() const {
02693     return false;
02694 }
02695 
02696 
02697 bool
02698 FunctionType::IsConstType() const {
02699     return false;
02700 }
02701 
02702 
02703 const Type *
02704 FunctionType::GetBaseType() const {
02705     FATAL("FunctionType::GetBaseType() shouldn't be called");
02706     return NULL;
02707 }
02708 
02709 
02710 const Type *
02711 FunctionType::GetAsVaryingType() const {
02712     FATAL("FunctionType::GetAsVaryingType shouldn't be called");
02713     return NULL;
02714 }
02715 
02716 
02717 const Type *
02718 FunctionType::GetAsUniformType() const {
02719     FATAL("FunctionType::GetAsUniformType shouldn't be called");
02720     return NULL;
02721 }
02722 
02723 
02724 const Type *
02725 FunctionType::GetAsUnboundVariabilityType() const {
02726     FATAL("FunctionType::GetAsUnboundVariabilityType shouldn't be called");
02727     return NULL;
02728 }
02729 
02730 
02731 const Type *
02732 FunctionType::GetAsSOAType(int width) const {
02733     FATAL("FunctionType::GetAsSOAType() shouldn't be called");
02734     return NULL;
02735 }
02736 
02737 
02738 const FunctionType *
02739 FunctionType::ResolveUnboundVariability(Variability v) const {
02740     if (returnType == NULL) {
02741         Assert(m->errorCount > 0);
02742         return NULL;
02743     }
02744     const Type *rt = returnType->ResolveUnboundVariability(v);
02745 
02746     llvm::SmallVector<const Type *, 8> pt;
02747     for (unsigned int i = 0; i < paramTypes.size(); ++i) {
02748         if (paramTypes[i] == NULL) {
02749             Assert(m->errorCount > 0);
02750             return NULL;
02751         }
02752         pt.push_back(paramTypes[i]->ResolveUnboundVariability(v));
02753     }
02754 
02755     FunctionType *ret = new FunctionType(rt, pt, paramNames, paramDefaults,
02756                                          paramPositions, isTask, isExported,
02757                                          isExternC, isUnmasked);
02758     ret->isSafe = isSafe;
02759     ret->costOverride = costOverride;
02760 
02761     return ret;
02762 }
02763 
02764 
02765 const Type *
02766 FunctionType::GetAsConstType() const {
02767     return this;
02768 }
02769 
02770 
02771 const Type *
02772 FunctionType::GetAsNonConstType() const {
02773     return this;
02774 }
02775 
02776 
02777 std::string
02778 FunctionType::GetString() const {
02779     std::string ret = GetReturnTypeString();
02780     ret += "(";
02781     for (unsigned int i = 0; i < paramTypes.size(); ++i) {
02782         if (paramTypes[i] == NULL)
02783             ret += "/* ERROR */";
02784         else
02785             ret += paramTypes[i]->GetString();
02786 
02787         if (i != paramTypes.size() - 1)
02788             ret += ", ";
02789     }
02790     ret += ")";
02791     return ret;
02792 }
02793 
02794 
02795 std::string
02796 FunctionType::Mangle() const {
02797     std::string ret = "___";
02798     if (isUnmasked)
02799         ret += "UM_";
02800 
02801     for (unsigned int i = 0; i < paramTypes.size(); ++i)
02802         if (paramTypes[i] == NULL)
02803             Assert(m->errorCount > 0);
02804         else
02805             ret += paramTypes[i]->Mangle();
02806 
02807     return ret;
02808 }
02809 
02810 
02811 std::string
02812 FunctionType::GetCDeclaration(const std::string &fname) const {
02813     std::string ret;
02814     ret += returnType->GetCDeclaration("");
02815     ret += " ";
02816     ret += fname;
02817     ret += "(";
02818     for (unsigned int i = 0; i < paramTypes.size(); ++i) {
02819         const Type *type = paramTypes[i];
02820 
02821         // Convert pointers to arrays to unsized arrays, which are more clear
02822         // to print out for multidimensional arrays (i.e. "float foo[][4] "
02823         // versus "float (foo *)[4]").
02824         const PointerType *pt = CastType<PointerType>(type);
02825         if (pt != NULL && 
02826             CastType<ArrayType>(pt->GetBaseType()) != NULL) {
02827             type = new ArrayType(pt->GetBaseType(), 0);
02828         }
02829 
02830         if (paramNames[i] != "")
02831             ret += type->GetCDeclaration(paramNames[i]);
02832         else
02833             ret += type->GetString();
02834         if (i != paramTypes.size() - 1)
02835             ret += ", ";
02836     }
02837     ret += ")";
02838     return ret;
02839 }
02840 
02841 
02842 llvm::Type *
02843 FunctionType::LLVMType(llvm::LLVMContext *ctx) const {
02844     FATAL("FunctionType::LLVMType() shouldn't be called");
02845     return NULL;
02846 }
02847 
02848 
02849 llvm::DIType
02850 FunctionType::GetDIType(llvm::DIDescriptor scope) const {
02851     std::vector<llvm::Value *> retArgTypes;
02852 
02853     retArgTypes.push_back(returnType->GetDIType(scope));
02854     for (int i = 0; i < GetNumParameters(); ++i) {
02855         const Type *t = GetParameterType(i);
02856         if (t == NULL)
02857             return llvm::DIType();
02858         retArgTypes.push_back(t->GetDIType(scope));
02859     }
02860 
02861     llvm::DIArray retArgTypesArray = 
02862         m->diBuilder->getOrCreateArray(llvm::ArrayRef<llvm::Value *>(retArgTypes));
02863     llvm::DIType diType = 
02864         // FIXME: DIFile 
02865         m->diBuilder->createSubroutineType(llvm::DIFile(), retArgTypesArray);
02866     return diType;
02867 }
02868 
02869 
02870 const std::string
02871 FunctionType::GetReturnTypeString() const {
02872     if (returnType == NULL)
02873         return "/* ERROR */";
02874 
02875     std::string ret;
02876     if (isTask)
02877         ret += "task ";
02878     if (isExported)
02879         ret += "export ";
02880     if (isExternC)
02881         ret += "extern \"C\" ";
02882     if (isUnmasked)
02883         ret += "unmasked ";
02884     if (isSafe) 
02885         ret += "/*safe*/ ";
02886     if (costOverride > 0) {
02887         char buf[32];
02888         sprintf(buf, "/*cost=%d*/ ", costOverride);
02889         ret += buf;
02890     }
02891 
02892     return ret + returnType->GetString();
02893 }
02894 
02895 
02896 llvm::FunctionType *
02897 FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
02898     if (isTask == true) 
02899         Assert(removeMask == false);
02900 
02901     // Get the LLVM Type *s for the function arguments
02902     std::vector<llvm::Type *> llvmArgTypes;
02903     for (unsigned int i = 0; i < paramTypes.size(); ++i) {
02904         if (paramTypes[i] == NULL) {
02905             Assert(m->errorCount > 0);
02906             return NULL;
02907         }
02908         Assert(Type::Equal(paramTypes[i], AtomicType::Void) == false);
02909 
02910         llvm::Type *t = paramTypes[i]->LLVMType(ctx);
02911         if (t == NULL) {
02912             Assert(m->errorCount > 0);
02913             return NULL;
02914         }
02915         llvmArgTypes.push_back(t);
02916     }
02917 
02918     // And add the function mask, if asked for
02919     if (!(removeMask || isUnmasked))
02920         llvmArgTypes.push_back(LLVMTypes::MaskType);
02921 
02922     std::vector<llvm::Type *> callTypes;
02923     if (isTask) {
02924         // Tasks take three arguments: a pointer to a struct that holds the
02925         // actual task arguments, the thread index, and the total number of
02926         // threads the tasks system has running.  (Task arguments are
02927         // marshalled in a struct so that it's easy to allocate space to
02928         // hold them until the task actually runs.)
02929         llvm::Type *st = llvm::StructType::get(*ctx, llvmArgTypes);
02930         callTypes.push_back(llvm::PointerType::getUnqual(st));
02931         callTypes.push_back(LLVMTypes::Int32Type); // threadIndex
02932         callTypes.push_back(LLVMTypes::Int32Type); // threadCount
02933         callTypes.push_back(LLVMTypes::Int32Type); // taskIndex
02934         callTypes.push_back(LLVMTypes::Int32Type); // taskCount
02935     }
02936     else
02937         // Otherwise we already have the types of the arguments 
02938         callTypes = llvmArgTypes;
02939 
02940     if (returnType == NULL) {
02941         Assert(m->errorCount > 0);
02942         return NULL;
02943     }
02944 
02945     llvm::Type *llvmReturnType = returnType->LLVMType(g->ctx);
02946     if (llvmReturnType == NULL)
02947         return NULL;
02948 
02949     return llvm::FunctionType::get(llvmReturnType, callTypes, false);
02950 }
02951 
02952 
02953 const Type *
02954 FunctionType::GetParameterType(int i) const { 
02955     Assert(i < (int)paramTypes.size());
02956     return paramTypes[i];
02957 }
02958 
02959 
02960 Expr *
02961 FunctionType::GetParameterDefault(int i) const { 
02962     Assert(i < (int)paramDefaults.size());
02963     return paramDefaults[i]; 
02964 }
02965 
02966 
02967 const SourcePos &
02968 FunctionType::GetParameterSourcePos(int i) const { 
02969     Assert(i < (int)paramPositions.size());
02970     return paramPositions[i];
02971 }
02972 
02973 
02974 const std::string &
02975 FunctionType::GetParameterName(int i) const { 
02976     Assert(i < (int)paramNames.size());
02977     return paramNames[i]; 
02978 }
02979 
02980 
02981 ///////////////////////////////////////////////////////////////////////////
02982 // Type
02983 
02984 const Type *
02985 Type::GetReferenceTarget() const {
02986     // only ReferenceType needs to override this method
02987     return this;
02988 }
02989 
02990 
02991 const Type *
02992 Type::GetAsUnsignedType() const {
02993     // For many types, this doesn't make any sesne
02994     return NULL;
02995 }
02996 
02997 
02998 /** Given an atomic or vector type, return a vector type of the given
02999     vecSize.  Issue an error if given a vector type that isn't already that
03000     size.
03001  */
03002 static const Type *
03003 lVectorConvert(const Type *type, SourcePos pos, const char *reason, int vecSize) {
03004     const VectorType *vt = CastType<VectorType>(type);
03005     if (vt) {
03006         if (vt->GetElementCount() != vecSize) {
03007             Error(pos, "Implicit conversion between from vector type "
03008                   "\"%s\" to vector type of length %d for %s is not possible.", 
03009                   type->GetString().c_str(), vecSize, reason);
03010             return NULL;
03011         }
03012         return vt;
03013     }
03014     else {
03015         const AtomicType *at = CastType<AtomicType>(type);
03016         if (!at) {
03017             Error(pos, "Non-atomic type \"%s\" can't be converted to vector type "
03018                   "for %s.", type->GetString().c_str(), reason);
03019             return NULL;
03020         }
03021         return new VectorType(at, vecSize);
03022     }
03023 }
03024 
03025 
03026 const Type *
03027 Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char *reason, 
03028                       bool forceVarying, int vecSize) {
03029     Assert(reason != NULL);
03030 
03031     // First, if one or both types are function types, convert them to
03032     // pointer to function types and then try again.
03033     if (CastType<FunctionType>(t0) || CastType<FunctionType>(t1)) {
03034         if (CastType<FunctionType>(t0))
03035             t0 = PointerType::GetUniform(t0);
03036         if (CastType<FunctionType>(t1))
03037             t1 = PointerType::GetUniform(t1);
03038         return MoreGeneralType(t0, t1, pos, reason, forceVarying, vecSize);
03039     }
03040 
03041     // First, if we need to go varying, promote both of the types to be
03042     // varying.
03043     if (t0->IsVaryingType() || t1->IsVaryingType() || forceVarying) {
03044         t0 = t0->GetAsVaryingType();
03045         t1 = t1->GetAsVaryingType();
03046     }
03047 
03048     // And similarly, promote them both to vectors if the caller requested
03049     // a particular vector size
03050     if (vecSize > 0) {
03051         t0 = lVectorConvert(t0, pos, reason, vecSize);
03052         t1 = lVectorConvert(t1, pos, reason, vecSize);
03053         if (!t0 || !t1)
03054             return NULL;
03055     }
03056 
03057     // Are they both the same type?  If so, we're done, QED.
03058     if (Type::Equal(t0, t1)) 
03059         return t0;
03060     
03061     // If they're function types, it's hopeless if they didn't match in the
03062     // Type::Equal() call above.  Fail here so that we don't get into
03063     // trouble calling GetAsConstType()...
03064     if (CastType<FunctionType>(t0) || CastType<FunctionType>(t1)) {
03065         Error(pos, "Incompatible function types \"%s\" and \"%s\" in %s.",
03066               t0->GetString().c_str(), t1->GetString().c_str(), reason);
03067         return NULL;
03068     }
03069 
03070     // Not the same types, but only a const/non-const difference?  Return
03071     // the non-const type as the more general one.
03072     if (Type::EqualIgnoringConst(t0, t1))
03073         return t0->GetAsNonConstType();
03074 
03075     const PointerType *pt0 = CastType<PointerType>(t0);
03076     const PointerType *pt1 = CastType<PointerType>(t1);
03077     if (pt0 != NULL && pt1 != NULL) {
03078         if (PointerType::IsVoidPointer(pt0))
03079             return pt1;
03080         else if (PointerType::IsVoidPointer(pt1))
03081             return pt0;
03082         else {
03083             Error(pos, "Conversion between incompatible pointer types \"%s\" "
03084                   "and \"%s\" isn't possible.", t0->GetString().c_str(),
03085                   t1->GetString().c_str());
03086             return NULL;
03087         }
03088     }
03089 
03090     const VectorType *vt0 = CastType<VectorType>(t0);
03091     const VectorType *vt1 = CastType<VectorType>(t1);
03092     if (vt0 && vt1) {
03093         // both are vectors; convert their base types and make a new vector
03094         // type, as long as their lengths match
03095         if (vt0->GetElementCount() != vt1->GetElementCount()) {
03096             Error(pos, "Implicit conversion between differently sized vector types "
03097                   "(%s, %s) for %s is not possible.", t0->GetString().c_str(),
03098                   t1->GetString().c_str(), reason);
03099             return NULL;
03100         }
03101         const Type *t = MoreGeneralType(vt0->GetElementType(), vt1->GetElementType(),
03102                                         pos, reason, forceVarying);
03103         if (!t) 
03104             return NULL;
03105 
03106         // The 'more general' version of the two vector element types must
03107         // be an AtomicType (that's all that vectors can hold...)
03108         const AtomicType *at = CastType<AtomicType>(t);
03109         Assert(at != NULL);
03110 
03111         return new VectorType(at, vt0->GetElementCount());
03112     }
03113     else if (vt0) {
03114         // If one type is a vector type but the other isn't, see if we can
03115         // promote the other one to a vector type.  This will fail and
03116         // return NULL if t1 is e.g. an array type and it's illegal to have
03117         // a vector of it..
03118         const Type *t = MoreGeneralType(vt0->GetElementType(), t1, pos, 
03119                                         reason, forceVarying);
03120         if (!t) 
03121             return NULL;
03122 
03123         const AtomicType *at = CastType<AtomicType>(t);
03124         Assert(at != NULL);
03125         return new VectorType(at, vt0->GetElementCount());
03126     }
03127     else if (vt1) {
03128         // As in the above case, see if we can promote t0 to make a vector
03129         // that matches vt1.
03130         const Type *t = MoreGeneralType(t0, vt1->GetElementType(), pos, 
03131                                         reason, forceVarying);
03132         if (!t) 
03133             return NULL;
03134 
03135         const AtomicType *at = CastType<AtomicType>(t);
03136         Assert(at != NULL);
03137         return new VectorType(at, vt1->GetElementCount());
03138     }
03139 
03140     // TODO: what do we need to do about references here, if anything??
03141 
03142     const AtomicType *at0 = CastType<AtomicType>(t0->GetReferenceTarget());
03143     const AtomicType *at1 = CastType<AtomicType>(t1->GetReferenceTarget());
03144 
03145     const EnumType *et0 = CastType<EnumType>(t0->GetReferenceTarget());
03146     const EnumType *et1 = CastType<EnumType>(t1->GetReferenceTarget());
03147     if (et0 != NULL && et1 != NULL) {
03148         // Two different enum types -> make them uint32s...
03149         Assert(et0->IsVaryingType() == et1->IsVaryingType());
03150         return et0->IsVaryingType() ? AtomicType::VaryingUInt32 :
03151                 AtomicType::UniformUInt32;
03152     }
03153     else if (et0 != NULL) {
03154         if (at1 != NULL)
03155             // Enum type and atomic type -> convert the enum to the atomic type
03156             // TODO: should we return uint32 here, unless the atomic type is
03157             // a 64-bit atomic type, in which case we return that?
03158             return at1;
03159         else {
03160             Error(pos, "Implicit conversion from enum type \"%s\" to "
03161                   "non-atomic type \"%s\" for %s not possible.",
03162                   t0->GetString().c_str(), t1->GetString().c_str(), reason);
03163             return NULL;
03164         }
03165     }
03166     else if (et1 != NULL) {
03167         if (at0 != NULL)
03168             // Enum type and atomic type; see TODO above here as well...
03169             return at0;
03170         else {
03171             Error(pos, "Implicit conversion from enum type \"%s\" to "
03172                   "non-atomic type \"%s\" for %s not possible.",
03173                   t1->GetString().c_str(), t0->GetString().c_str(), reason);
03174             return NULL;
03175         }
03176     }
03177 
03178     // Now all we can do is promote atomic types...
03179     if (at0 == NULL || at1 == NULL) {
03180         Assert(reason != NULL);
03181         Error(pos, "Implicit conversion from type \"%s\" to \"%s\" for %s not possible.",
03182               t0->GetString().c_str(), t1->GetString().c_str(), reason);
03183         return NULL;
03184     }
03185 
03186     // Finally, to determine which of the two atomic types is more general,
03187     // use the ordering of entries in the AtomicType::BasicType enumerator.
03188     return (int(at0->basicType) >= int(at1->basicType)) ? at0 : at1;
03189 }
03190 
03191 
03192 bool
03193 Type::IsBasicType(const Type *type) {
03194     return (CastType<AtomicType>(type) != NULL ||
03195             CastType<EnumType>(type) != NULL ||
03196             CastType<PointerType>(type) != NULL);
03197 }
03198 
03199 
03200 static bool
03201 lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
03202     if (a == NULL || b == NULL)
03203         return false;
03204 
03205     if (ignoreConst == false &&
03206         a->IsConstType() != b->IsConstType())
03207         return false;
03208 
03209     const AtomicType *ata = CastType<AtomicType>(a);
03210     const AtomicType *atb = CastType<AtomicType>(b);
03211     if (ata != NULL && atb != NULL) {
03212         return ((ata->basicType == atb->basicType) && 
03213                 (ata->GetVariability() == atb->GetVariability()));
03214     }
03215 
03216     // For all of the other types, we need to see if we have the same two
03217     // general types.  If so, then we dig into the details of the type and
03218     // see if all of the relevant bits are equal...
03219     const EnumType *eta = CastType<EnumType>(a);
03220     const EnumType *etb = CastType<EnumType>(b);
03221     if (eta != NULL && etb != NULL)
03222         // Kind of goofy, but this sufficies to check
03223         return (eta->pos == etb->pos &&
03224                 eta->GetVariability() == etb->GetVariability());
03225 
03226     const ArrayType *arta = CastType<ArrayType>(a);
03227     const ArrayType *artb = CastType<ArrayType>(b);
03228     if (arta != NULL && artb != NULL)
03229         return (arta->GetElementCount() == artb->GetElementCount() && 
03230                 lCheckTypeEquality(arta->GetElementType(), artb->GetElementType(), 
03231                                    ignoreConst));
03232 
03233     const VectorType *vta = CastType<VectorType>(a);
03234     const VectorType *vtb = CastType<VectorType>(b);
03235     if (vta != NULL && vtb != NULL)
03236         return (vta->GetElementCount() == vtb->GetElementCount() && 
03237                 lCheckTypeEquality(vta->GetElementType(), vtb->GetElementType(),
03238                                    ignoreConst));
03239 
03240     const StructType *sta = CastType<StructType>(a);
03241     const StructType *stb = CastType<StructType>(b);
03242     const UndefinedStructType *usta = CastType<UndefinedStructType>(a);
03243     const UndefinedStructType *ustb = CastType<UndefinedStructType>(b);
03244     if ((sta != NULL || usta != NULL) && (stb != NULL || ustb != NULL)) {
03245         // Report both defuned and undefined structs as equal if their
03246         // names are the same.
03247         if (a->GetVariability() != b->GetVariability())
03248             return false;
03249 
03250         const std::string &namea = sta ? sta->GetStructName() : 
03251             usta->GetStructName();
03252         const std::string &nameb = stb ? stb->GetStructName() :
03253             ustb->GetStructName();
03254         return (namea == nameb);
03255     }
03256 
03257     const PointerType *pta = CastType<PointerType>(a);
03258     const PointerType *ptb = CastType<PointerType>(b);
03259     if (pta != NULL && ptb != NULL)
03260         return (pta->IsUniformType() == ptb->IsUniformType() &&
03261                 pta->IsSlice() == ptb->IsSlice() &&
03262                 pta->IsFrozenSlice() == ptb->IsFrozenSlice() &&
03263                 lCheckTypeEquality(pta->GetBaseType(), ptb->GetBaseType(), 
03264                                    ignoreConst));
03265 
03266     const ReferenceType *rta = CastType<ReferenceType>(a);
03267     const ReferenceType *rtb = CastType<ReferenceType>(b);
03268     if (rta != NULL && rtb != NULL)
03269         return (lCheckTypeEquality(rta->GetReferenceTarget(),
03270                                    rtb->GetReferenceTarget(), ignoreConst));
03271 
03272     const FunctionType *fta = CastType<FunctionType>(a);
03273     const FunctionType *ftb = CastType<FunctionType>(b);
03274     if (fta != NULL && ftb != NULL) {
03275         // Both the return types and all of the argument types must match
03276         // for function types to match
03277         if (!lCheckTypeEquality(fta->GetReturnType(), ftb->GetReturnType(), 
03278                                 ignoreConst))
03279             return false;
03280 
03281         if (fta->isTask != ftb->isTask ||
03282             fta->isExported != ftb->isExported ||
03283             fta->isExternC != ftb->isExternC ||
03284             fta->isUnmasked != ftb->isUnmasked)
03285             return false;
03286 
03287         if (fta->GetNumParameters() != ftb->GetNumParameters())
03288             return false;
03289 
03290         for (int i = 0; i < fta->GetNumParameters(); ++i)
03291             if (!lCheckTypeEquality(fta->GetParameterType(i),
03292                        ftb->GetParameterType(i), ignoreConst))
03293                 return false;
03294 
03295         return true;
03296     }
03297 
03298     return false;
03299 }
03300 
03301 
03302 bool
03303 Type::Equal(const Type *a, const Type *b) {
03304     return lCheckTypeEquality(a, b, false);
03305 }
03306 
03307 
03308 bool
03309 Type::EqualIgnoringConst(const Type *a, const Type *b) {
03310     return lCheckTypeEquality(a, b, true);
03311 }