Intel SPMD Program Compiler  1.3.0
decl.cpp
Go to the documentation of this file.
00001 /*
00002   Copyright (c) 2010-2012, Intel Corporation
00003   All rights reserved.
00004 
00005   Redistribution and use in source and binary forms, with or without
00006   modification, are permitted provided that the following conditions are
00007   met:
00008 
00009     * Redistributions of source code must retain the above copyright
00010       notice, this list of conditions and the following disclaimer.
00011 
00012     * Redistributions in binary form must reproduce the above copyright
00013       notice, this list of conditions and the following disclaimer in the
00014       documentation and/or other materials provided with the distribution.
00015 
00016     * Neither the name of Intel Corporation nor the names of its
00017       contributors may be used to endorse or promote products derived from
00018       this software without specific prior written permission.
00019 
00020 
00021    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00022    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00023    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00024    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00025    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00026    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00027    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
00032 */
00033 
00034 /** @file decl.cpp
00035     @brief Implementations of classes related to turning declarations into 
00036            symbol names and types.
00037 */
00038 
00039 #include "decl.h"
00040 #include "util.h"
00041 #include "module.h"
00042 #include "sym.h"
00043 #include "type.h"
00044 #include "stmt.h"
00045 #include "expr.h"
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <set>
00049 
00050 static void
00051 lPrintTypeQualifiers(int typeQualifiers) {
00052     if (typeQualifiers & TYPEQUAL_INLINE)    printf("inline ");
00053     if (typeQualifiers & TYPEQUAL_CONST)     printf("const ");
00054     if (typeQualifiers & TYPEQUAL_UNIFORM)   printf("uniform ");
00055     if (typeQualifiers & TYPEQUAL_VARYING)   printf("varying ");
00056     if (typeQualifiers & TYPEQUAL_TASK)      printf("task ");
00057     if (typeQualifiers & TYPEQUAL_SIGNED)    printf("signed ");
00058     if (typeQualifiers & TYPEQUAL_UNSIGNED)  printf("unsigned ");
00059     if (typeQualifiers & TYPEQUAL_EXPORT)    printf("export ");
00060     if (typeQualifiers & TYPEQUAL_UNMASKED)  printf("unmasked ");
00061 }
00062 
00063 
00064 /** Given a Type and a set of type qualifiers, apply the type qualifiers to
00065     the type, returning the type that is the result. 
00066 */
00067 static const Type *
00068 lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
00069     if (type == NULL)
00070         return NULL;
00071 
00072     if ((typeQualifiers & TYPEQUAL_CONST) != 0)
00073         type = type->GetAsConstType();
00074 
00075     if ((typeQualifiers & TYPEQUAL_UNIFORM) != 0) {
00076         if (Type::Equal(type, AtomicType::Void))
00077             Error(pos, "\"uniform\" qualifier is illegal with \"void\" type.");
00078         else
00079             type = type->GetAsUniformType();
00080     }
00081     else if ((typeQualifiers & TYPEQUAL_VARYING) != 0) {
00082         if (Type::Equal(type, AtomicType::Void))
00083             Error(pos, "\"varying\" qualifier is illegal with \"void\" type.");
00084         else
00085             type = type->GetAsVaryingType();
00086     }
00087     else
00088         if (Type::Equal(type, AtomicType::Void) == false)
00089             type = type->GetAsUnboundVariabilityType();
00090 
00091     if ((typeQualifiers & TYPEQUAL_UNSIGNED) != 0) {
00092         if ((typeQualifiers & TYPEQUAL_SIGNED) != 0)
00093             Error(pos, "Illegal to apply both \"signed\" and \"unsigned\" "
00094                   "qualifiers.");
00095 
00096         const Type *unsignedType = type->GetAsUnsignedType();
00097         if (unsignedType != NULL)
00098             type = unsignedType;
00099         else {
00100             const Type *resolvedType = 
00101                 type->ResolveUnboundVariability(Variability::Varying);
00102             Error(pos, "\"unsigned\" qualifier is illegal with \"%s\" type.",
00103                   resolvedType->GetString().c_str());
00104         }
00105     }
00106 
00107     if ((typeQualifiers & TYPEQUAL_SIGNED) != 0 && type->IsIntType() == false) {
00108         const Type *resolvedType = 
00109             type->ResolveUnboundVariability(Variability::Varying);
00110         Error(pos, "\"signed\" qualifier is illegal with non-integer type "
00111               "\"%s\".", resolvedType->GetString().c_str());
00112     }
00113 
00114     return type;
00115 }
00116 
00117 
00118 ///////////////////////////////////////////////////////////////////////////
00119 // DeclSpecs
00120 
00121 DeclSpecs::DeclSpecs(const Type *t, StorageClass sc, int tq) {
00122     baseType = t;
00123     storageClass = sc;
00124     typeQualifiers = tq;
00125     soaWidth = 0;
00126     vectorSize = 0;
00127 }
00128 
00129 
00130 const Type *
00131 DeclSpecs::GetBaseType(SourcePos pos) const {
00132     const Type *retType = baseType;
00133 
00134     if (retType == NULL) {
00135         Warning(pos, "No type specified in declaration.  Assuming int32.");
00136         retType = AtomicType::UniformInt32->GetAsUnboundVariabilityType();
00137     }
00138 
00139     if (vectorSize > 0) {
00140         const AtomicType *atomicType = CastType<AtomicType>(retType);
00141         if (atomicType == NULL) {
00142             Error(pos, "Only atomic types (int, float, ...) are legal for vector "
00143                   "types.");
00144             return NULL;
00145         }
00146         retType = new VectorType(atomicType, vectorSize);
00147     }
00148 
00149     retType = lApplyTypeQualifiers(typeQualifiers, retType, pos);
00150     
00151     if (soaWidth > 0) {
00152         const StructType *st = CastType<StructType>(retType);
00153 
00154         if (st == NULL) {
00155             Error(pos, "Illegal to provide soa<%d> qualifier with non-struct "
00156                   "type \"%s\".", soaWidth, retType->GetString().c_str());
00157             return NULL;
00158         }
00159         else if (soaWidth <= 0 || (soaWidth & (soaWidth - 1)) != 0) {
00160             Error(pos, "soa<%d> width illegal.  Value must be positive power "
00161                   "of two.", soaWidth);
00162             return NULL;
00163         }
00164 
00165         if (st->IsUniformType()) {
00166             Error(pos, "\"uniform\" qualifier and \"soa<%d>\" qualifier can't "
00167                   "both be used in a type declaration.", soaWidth);
00168             return NULL;
00169         }
00170         else if (st->IsVaryingType()) {
00171             Error(pos, "\"varying\" qualifier and \"soa<%d>\" qualifier can't "
00172                   "both be used in a type declaration.", soaWidth);
00173             return NULL;
00174         }
00175         else
00176             retType = st->GetAsSOAType(soaWidth);
00177 
00178         if (soaWidth < g->target.vectorWidth)
00179             PerformanceWarning(pos, "soa<%d> width smaller than gang size %d "
00180                                "currently leads to inefficient code to access "
00181                                "soa types.", soaWidth, g->target.vectorWidth);
00182     }
00183     
00184     return retType;
00185 }
00186 
00187 
00188 static const char *
00189 lGetStorageClassName(StorageClass storageClass) {
00190     switch (storageClass) {
00191     case SC_NONE:     return "";
00192     case SC_EXTERN:   return "extern";
00193     case SC_EXTERN_C: return "extern \"C\"";
00194     case SC_STATIC:   return "static";
00195     case SC_TYPEDEF:  return "typedef";
00196     default:          FATAL("Unhandled storage class in lGetStorageClassName");
00197                       return "";
00198     }
00199 }
00200 
00201 
00202 void
00203 DeclSpecs::Print() const {
00204     printf("Declspecs: [%s ", lGetStorageClassName(storageClass));
00205 
00206     if (soaWidth > 0) printf("soa<%d> ", soaWidth);
00207     lPrintTypeQualifiers(typeQualifiers);
00208     printf("base type: %s", baseType->GetString().c_str());
00209 
00210     if (vectorSize > 0) printf("<%d>", vectorSize);
00211     printf("]");
00212 }
00213 
00214 
00215 ///////////////////////////////////////////////////////////////////////////
00216 // Declarator
00217 
00218 Declarator::Declarator(DeclaratorKind dk, SourcePos p) 
00219     : pos(p), kind(dk) { 
00220     child = NULL;
00221     typeQualifiers = 0;
00222     storageClass = SC_NONE;
00223     arraySize = -1;
00224     type = NULL;
00225     initExpr = NULL;
00226 }
00227 
00228 
00229 void
00230 Declarator::InitFromDeclSpecs(DeclSpecs *ds) {
00231     const Type *baseType = ds->GetBaseType(pos);
00232     InitFromType(baseType, ds);
00233 
00234     if (type == NULL) {
00235         AssertPos(pos, m->errorCount > 0);
00236         return;
00237     }
00238 
00239     storageClass = ds->storageClass;
00240 
00241     if (ds->declSpecList.size() > 0 && 
00242         CastType<FunctionType>(type) == NULL) {
00243         Error(pos, "__declspec specifiers for non-function type \"%s\" are "
00244               "not used.", type->GetString().c_str());
00245     }
00246 }
00247 
00248 
00249 void
00250 Declarator::Print(int indent) const {
00251     printf("%*cdeclarator: [", indent, ' ');
00252     pos.Print();
00253 
00254     lPrintTypeQualifiers(typeQualifiers);
00255     printf("%s ", lGetStorageClassName(storageClass));
00256     if (name.size() > 0)
00257         printf("%s", name.c_str());
00258     else
00259         printf("(unnamed)");
00260 
00261     printf(", array size = %d", arraySize);
00262 
00263     printf(", kind = ");
00264     switch (kind) {
00265     case DK_BASE:      printf("base");      break;
00266     case DK_POINTER:   printf("pointer");   break;
00267     case DK_REFERENCE: printf("reference"); break;
00268     case DK_ARRAY:     printf("array");     break;
00269     case DK_FUNCTION:  printf("function");  break;
00270     default:           FATAL("Unhandled declarator kind");
00271     }
00272 
00273     if (initExpr != NULL) {
00274         printf(" = (");
00275         initExpr->Print();
00276         printf(")");
00277     }
00278 
00279     if (functionParams.size() > 0) {
00280         for (unsigned int i = 0; i < functionParams.size(); ++i) {
00281             printf("\n%*cfunc param %d:\n", indent, ' ', i);
00282             functionParams[i]->Print(indent+4);
00283         }
00284     }
00285 
00286     if (child != NULL)
00287         child->Print(indent + 4);
00288 
00289     printf("]\n");
00290 }
00291 
00292 
00293 void
00294 Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
00295     bool hasUniformQual = ((typeQualifiers & TYPEQUAL_UNIFORM) != 0);
00296     bool hasVaryingQual = ((typeQualifiers & TYPEQUAL_VARYING) != 0);
00297     bool isTask =         ((typeQualifiers & TYPEQUAL_TASK) != 0);
00298     bool isExported =     ((typeQualifiers & TYPEQUAL_EXPORT) != 0);
00299     bool isConst =        ((typeQualifiers & TYPEQUAL_CONST) != 0);
00300     bool isUnmasked =     ((typeQualifiers & TYPEQUAL_UNMASKED) != 0);
00301 
00302     if (hasUniformQual && hasVaryingQual) {
00303         Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers.");
00304         return;
00305     }
00306     if (kind != DK_FUNCTION && isTask) {
00307         Error(pos, "\"task\" qualifier illegal in variable declaration.");
00308         return;
00309     }
00310     if (kind != DK_FUNCTION && isUnmasked) {
00311         Error(pos, "\"unmasked\" qualifier illegal in variable declaration.");
00312         return;
00313     }
00314     if (kind != DK_FUNCTION && isExported) {
00315         Error(pos, "\"export\" qualifier illegal in variable declaration.");
00316         return;
00317     }
00318     
00319     Variability variability(Variability::Unbound);
00320     if (hasUniformQual)
00321         variability = Variability::Uniform;
00322     else if (hasVaryingQual)
00323         variability = Variability::Varying;
00324 
00325     if (kind == DK_BASE) {
00326         // All of the type qualifiers should be in the DeclSpecs for the
00327         // base declarator
00328         AssertPos(pos, typeQualifiers == 0);
00329         AssertPos(pos, child == NULL);
00330         type = baseType;
00331     }
00332     else if (kind == DK_POINTER) {
00333         /* For now, any pointer to an SOA type gets the slice property; if
00334            we add the capability to declare pointers as slices or not,
00335            we'll want to set this based on a type qualifier here. */
00336         const Type *ptrType = new PointerType(baseType, variability, isConst,
00337                                               baseType->IsSOAType());
00338         if (child != NULL) {
00339             child->InitFromType(ptrType, ds);
00340             type = child->type;
00341             name = child->name;
00342         }
00343         else
00344             type = ptrType;
00345     }
00346     else if (kind == DK_REFERENCE) {
00347         if (hasUniformQual) {
00348             Error(pos, "\"uniform\" qualifier is illegal to apply to references.");
00349             return;
00350         }
00351         if (hasVaryingQual) {
00352             Error(pos, "\"varying\" qualifier is illegal to apply to references.");
00353             return;
00354         }
00355         if (isConst) {
00356             Error(pos, "\"const\" qualifier is to illegal apply to references.");
00357             return;
00358         }
00359         // The parser should disallow this already, but double check.
00360         if (CastType<ReferenceType>(baseType) != NULL) {
00361             Error(pos, "References to references are illegal.");
00362             return;
00363         }
00364 
00365         const Type *refType = new ReferenceType(baseType);
00366         if (child != NULL) {
00367             child->InitFromType(refType, ds);
00368             type = child->type;
00369             name = child->name;
00370         }
00371         else
00372             type = refType;
00373     }
00374     else if (kind == DK_ARRAY) {
00375         if (Type::Equal(baseType, AtomicType::Void)) {
00376             Error(pos, "Arrays of \"void\" type are illegal.");
00377             return;
00378         }
00379         if (CastType<ReferenceType>(baseType)) {
00380             Error(pos, "Arrays of references (type \"%s\") are illegal.",
00381                   baseType->GetString().c_str());
00382             return;
00383         }
00384 
00385         const Type *arrayType = new ArrayType(baseType, arraySize);
00386         if (child != NULL) {
00387             child->InitFromType(arrayType, ds);
00388             type = child->type;
00389             name = child->name;
00390         }
00391         else
00392             type = arrayType;
00393     }
00394     else if (kind == DK_FUNCTION) {
00395         llvm::SmallVector<const Type *, 8> args;
00396         llvm::SmallVector<std::string, 8> argNames;
00397         llvm::SmallVector<Expr *, 8> argDefaults;
00398         llvm::SmallVector<SourcePos, 8> argPos;
00399         
00400         // Loop over the function arguments and store the names, types,
00401         // default values (if any), and source file positions each one in
00402         // the corresponding vector.
00403         for (unsigned int i = 0; i < functionParams.size(); ++i) {
00404             Declaration *d = functionParams[i];
00405 
00406             if (d == NULL) {
00407                 AssertPos(pos, m->errorCount > 0);
00408                 continue;
00409             }
00410             if (d->declarators.size() == 0) {
00411                 // function declaration like foo(float), w/o a name for the
00412                 // parameter; wire up a placeholder Declarator for it
00413                 d->declarators.push_back(new Declarator(DK_BASE, pos));
00414                 d->declarators[0]->InitFromDeclSpecs(d->declSpecs);
00415             }
00416 
00417             AssertPos(pos, d->declarators.size() == 1);
00418             Declarator *decl = d->declarators[0];
00419             if (decl == NULL || decl->type == NULL) {
00420                 AssertPos(pos, m->errorCount > 0);
00421                 continue;
00422             }
00423 
00424             if (decl->name == "") {
00425                 // Give a name to any anonymous parameter declarations
00426                 char buf[32];
00427                 sprintf(buf, "__anon_parameter_%d", i);
00428                 decl->name = buf;
00429             }
00430             decl->type = decl->type->ResolveUnboundVariability(Variability::Varying);
00431 
00432             if (d->declSpecs->storageClass != SC_NONE)
00433                 Error(decl->pos, "Storage class \"%s\" is illegal in "
00434                       "function parameter declaration for parameter \"%s\".", 
00435                       lGetStorageClassName(d->declSpecs->storageClass),
00436                       decl->name.c_str());
00437             if (Type::Equal(decl->type, AtomicType::Void)) {
00438                 Error(decl->pos, "Parameter with type \"void\" illegal in function "
00439                       "parameter list.");
00440                 decl->type = NULL;
00441             }
00442 
00443             const ArrayType *at = CastType<ArrayType>(decl->type);
00444             if (at != NULL) {
00445                 // As in C, arrays are passed to functions as pointers to
00446                 // their element type.  We'll just immediately make this
00447                 // change now.  (One shortcoming of losing the fact that
00448                 // the it was originally an array is that any warnings or
00449                 // errors later issued that print the function type will
00450                 // report this differently than it was originally declared
00451                 // in the function, but it's not clear that this is a
00452                 // significant problem.)
00453                 const Type *targetType = at->GetElementType();
00454                 if (targetType == NULL) {
00455                     AssertPos(pos, m->errorCount > 0);
00456                     return;
00457                 }
00458 
00459                 decl->type = PointerType::GetUniform(targetType);
00460 
00461                 // Make sure there are no unsized arrays (other than the
00462                 // first dimension) in function parameter lists.
00463                 at = CastType<ArrayType>(targetType);
00464                 while (at != NULL) {
00465                     if (at->GetElementCount() == 0)
00466                         Error(decl->pos, "Arrays with unsized dimensions in "
00467                               "dimensions after the first one are illegal in "
00468                               "function parameter lists.");
00469                     at = CastType<ArrayType>(at->GetElementType());
00470                 }
00471             }
00472 
00473             args.push_back(decl->type);
00474             argNames.push_back(decl->name);
00475             argPos.push_back(decl->pos);
00476 
00477             Expr *init = NULL;
00478             // Try to find an initializer expression.
00479             while (decl != NULL) {
00480                 if (decl->initExpr != NULL) {
00481                     decl->initExpr = TypeCheck(decl->initExpr);
00482                     decl->initExpr = Optimize(decl->initExpr);
00483                     if (decl->initExpr != NULL) {
00484                         init = dynamic_cast<ConstExpr *>(decl->initExpr);
00485                         if (init == NULL)
00486                             init = dynamic_cast<NullPointerExpr *>(decl->initExpr);
00487                         if (init == NULL)
00488                             Error(decl->initExpr->pos, "Default value for parameter "
00489                                   "\"%s\" must be a compile-time constant.", 
00490                                   decl->name.c_str());
00491                     }
00492                     break;
00493                 }
00494                 else
00495                     decl = decl->child;
00496             }
00497             argDefaults.push_back(init);
00498         }
00499 
00500         const Type *returnType = baseType;
00501         if (returnType == NULL) {
00502             Error(pos, "No return type provided in function declaration.");
00503             return;
00504         }
00505 
00506         if (CastType<FunctionType>(returnType) != NULL) {
00507             Error(pos, "Illegal to return function type from function.");
00508             return;
00509         }
00510         
00511         returnType = returnType->ResolveUnboundVariability(Variability::Varying);
00512 
00513         bool isExternC =  ds && (ds->storageClass == SC_EXTERN_C);
00514         bool isExported = ds && ((ds->typeQualifiers & TYPEQUAL_EXPORT) != 0);
00515         bool isTask =     ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0);
00516         bool isUnmasked = ds && ((ds->typeQualifiers & TYPEQUAL_UNMASKED) != 0);
00517         
00518         if (isExported && isTask) {
00519             Error(pos, "Function can't have both \"task\" and \"export\" "
00520                   "qualifiers");
00521             return;
00522         }
00523         if (isExternC && isTask) {
00524             Error(pos, "Function can't have both \"extern \"C\"\" and \"task\" "
00525                   "qualifiers");
00526             return;
00527         }
00528         if (isExternC && isExported) {
00529             Error(pos, "Function can't have both \"extern \"C\"\" and \"export\" "
00530                   "qualifiers");
00531             return;
00532         }
00533         if (isUnmasked && isExported)
00534             Warning(pos, "\"unmasked\" qualifier is redundant for exported "
00535                     "functions.");
00536 
00537         if (child == NULL) {
00538             AssertPos(pos, m->errorCount > 0);
00539             return;
00540         }
00541 
00542         const FunctionType *functionType = 
00543             new FunctionType(returnType, args, argNames, argDefaults,
00544                              argPos, isTask, isExported, isExternC, isUnmasked);
00545 
00546         // handle any explicit __declspecs on the function
00547         if (ds != NULL) {
00548             for (int i = 0; i < (int)ds->declSpecList.size(); ++i) {
00549                 std::string str = ds->declSpecList[i].first;
00550                 SourcePos pos = ds->declSpecList[i].second;
00551 
00552                 if (str == "safe")
00553                     (const_cast<FunctionType *>(functionType))->isSafe = true;
00554                 else if (!strncmp(str.c_str(), "cost", 4)) {
00555                     int cost = atoi(str.c_str() + 4);
00556                     if (cost < 0)
00557                         Error(pos, "Negative function cost %d is illegal.",
00558                               cost);
00559                     (const_cast<FunctionType *>(functionType))->costOverride = cost;
00560                 }
00561                 else
00562                     Error(pos, "__declspec parameter \"%s\" unknown.", str.c_str());
00563             }
00564         }
00565 
00566         child->InitFromType(functionType, ds);
00567         type = child->type;
00568         name = child->name;
00569     }
00570 }
00571 
00572 ///////////////////////////////////////////////////////////////////////////
00573 // Declaration
00574 
00575 Declaration::Declaration(DeclSpecs *ds, std::vector<Declarator *> *dlist) {
00576     declSpecs = ds;
00577     if (dlist != NULL)
00578         declarators = *dlist;
00579     for (unsigned int i = 0; i < declarators.size(); ++i)
00580         if (declarators[i] != NULL)
00581             declarators[i]->InitFromDeclSpecs(declSpecs);
00582 }
00583 
00584 
00585 Declaration::Declaration(DeclSpecs *ds, Declarator *d) {
00586     declSpecs = ds;
00587     if (d != NULL) {
00588         d->InitFromDeclSpecs(ds);
00589         declarators.push_back(d);
00590     }
00591 }
00592 
00593 
00594 std::vector<VariableDeclaration>
00595 Declaration::GetVariableDeclarations() const {
00596     Assert(declSpecs->storageClass != SC_TYPEDEF);
00597     std::vector<VariableDeclaration> vars;
00598 
00599     for (unsigned int i = 0; i < declarators.size(); ++i) {
00600         Declarator *decl = declarators[i];
00601         if (decl == NULL || decl->type == NULL) {
00602             // Ignore earlier errors
00603             Assert(m->errorCount > 0);
00604             continue;
00605         }
00606 
00607         if (Type::Equal(decl->type, AtomicType::Void))
00608             Error(decl->pos, "\"void\" type variable illegal in declaration.");
00609         else if (CastType<FunctionType>(decl->type) == NULL) {
00610             decl->type = decl->type->ResolveUnboundVariability(Variability::Varying);
00611             Symbol *sym = new Symbol(decl->name, decl->pos, decl->type,
00612                                      decl->storageClass);
00613             m->symbolTable->AddVariable(sym);
00614             vars.push_back(VariableDeclaration(sym, decl->initExpr));
00615         }
00616     }
00617 
00618     return vars;
00619 }
00620 
00621 
00622 void
00623 Declaration::DeclareFunctions() {
00624     Assert(declSpecs->storageClass != SC_TYPEDEF);
00625 
00626     for (unsigned int i = 0; i < declarators.size(); ++i) {
00627         Declarator *decl = declarators[i];
00628         if (decl == NULL || decl->type == NULL) {
00629             // Ignore earlier errors
00630             Assert(m->errorCount > 0);
00631             continue;
00632         }
00633 
00634         const FunctionType *ftype = CastType<FunctionType>(decl->type);
00635         if (ftype == NULL)
00636             continue;
00637 
00638         bool isInline = (declSpecs->typeQualifiers & TYPEQUAL_INLINE);
00639         m->AddFunctionDeclaration(decl->name, ftype, decl->storageClass,
00640                                   isInline, decl->pos);
00641     }
00642 }
00643 
00644 
00645 void
00646 Declaration::Print(int indent) const {
00647     printf("%*cDeclaration: specs [", indent, ' ');
00648     declSpecs->Print();
00649     printf("], declarators:\n");
00650     for (unsigned int i = 0 ; i < declarators.size(); ++i)
00651         declarators[i]->Print(indent+4);
00652 }
00653 
00654 
00655 ///////////////////////////////////////////////////////////////////////////
00656 
00657 void
00658 GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
00659                              llvm::SmallVector<const Type *, 8> *elementTypes,
00660                              llvm::SmallVector<std::string, 8> *elementNames,
00661                              llvm::SmallVector<SourcePos, 8> *elementPositions) {
00662     std::set<std::string> seenNames;
00663     for (unsigned int i = 0; i < sd.size(); ++i) {
00664         const Type *type = sd[i]->type;
00665         if (type == NULL)
00666             continue;
00667 
00668         // FIXME: making this fake little DeclSpecs here is really
00669         // disgusting
00670         DeclSpecs ds(type);
00671         if (Type::Equal(type, AtomicType::Void) == false) {
00672             if (type->IsUniformType()) 
00673                 ds.typeQualifiers |= TYPEQUAL_UNIFORM;
00674             else if (type->IsVaryingType())
00675                 ds.typeQualifiers |= TYPEQUAL_VARYING;
00676             else if (type->GetSOAWidth() != 0)
00677                 ds.soaWidth = type->GetSOAWidth();
00678             // FIXME: ds.vectorSize?
00679         }
00680 
00681         for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) {
00682             Declarator *d = (*sd[i]->declarators)[j];
00683             d->InitFromDeclSpecs(&ds);
00684 
00685             if (Type::Equal(d->type, AtomicType::Void))
00686                 Error(d->pos, "\"void\" type illegal for struct member.");
00687 
00688             elementTypes->push_back(d->type);
00689 
00690             if (seenNames.find(d->name) != seenNames.end())
00691                 Error(d->pos, "Struct member \"%s\" has same name as a "
00692                       "previously-declared member.", d->name.c_str());
00693             else
00694                 seenNames.insert(d->name);
00695 
00696             elementNames->push_back(d->name);
00697             elementPositions->push_back(d->pos);
00698         }
00699     }
00700 
00701     for (int i = 0; i < (int)elementTypes->size() - 1; ++i) {
00702         const ArrayType *arrayType = CastType<ArrayType>((*elementTypes)[i]);
00703 
00704         if (arrayType != NULL && arrayType->GetElementCount() == 0)
00705             Error((*elementPositions)[i], "Unsized arrays aren't allowed except "
00706                   "for the last member in a struct definition.");
00707     }
00708 }