|
Intel SPMD Program Compiler
1.3.0
|
00001 /* 00002 Copyright (c) 2010-2012, Intel Corporation 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions are 00007 met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in the 00014 documentation and/or other materials provided with the distribution. 00015 00016 * Neither the name of Intel Corporation nor the names of its 00017 contributors may be used to endorse or promote products derived from 00018 this software without specific prior written permission. 00019 00020 00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00022 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00023 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00024 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00025 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00027 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 */ 00033 00034 /** @file type.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 }
1.7.5.1