Intel SPMD Program Compiler  1.9.1
decl.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2013, Intel Corporation
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15 
16  * Neither the name of Intel Corporation nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /** @file decl.cpp
35  @brief Implementations of classes related to turning declarations into
36  symbol names and types.
37 */
38 
39 #include "decl.h"
40 #include "util.h"
41 #include "module.h"
42 #include "sym.h"
43 #include "type.h"
44 #include "stmt.h"
45 #include "expr.h"
46 #include <stdio.h>
47 #include <string.h>
48 #include <set>
49 
50 static void
51 lPrintTypeQualifiers(int typeQualifiers) {
52  if (typeQualifiers & TYPEQUAL_INLINE) printf("inline ");
53  if (typeQualifiers & TYPEQUAL_CONST) printf("const ");
54  if (typeQualifiers & TYPEQUAL_UNIFORM) printf("uniform ");
55  if (typeQualifiers & TYPEQUAL_VARYING) printf("varying ");
56  if (typeQualifiers & TYPEQUAL_TASK) printf("task ");
57  if (typeQualifiers & TYPEQUAL_SIGNED) printf("signed ");
58  if (typeQualifiers & TYPEQUAL_UNSIGNED) printf("unsigned ");
59  if (typeQualifiers & TYPEQUAL_EXPORT) printf("export ");
60  if (typeQualifiers & TYPEQUAL_UNMASKED) printf("unmasked ");
61 }
62 
63 
64 /** Given a Type and a set of type qualifiers, apply the type qualifiers to
65  the type, returning the type that is the result.
66 */
67 static const Type *
68 lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos) {
69  if (type == NULL)
70  return NULL;
71 
72  if ((typeQualifiers & TYPEQUAL_CONST) != 0) {
73  type = type->GetAsConstType();
74  }
75 
76  if ( ((typeQualifiers & TYPEQUAL_UNIFORM) != 0)
77  && ((typeQualifiers & TYPEQUAL_VARYING) != 0) ) {
78  Error(pos, "Type \"%s\" cannot be qualified with both uniform and varying.",
79  type->GetString().c_str());
80  }
81 
82  if ((typeQualifiers & TYPEQUAL_UNIFORM) != 0) {
83  if (type->IsVoidType())
84  Error(pos, "\"uniform\" qualifier is illegal with \"void\" type.");
85  else
86  type = type->GetAsUniformType();
87  }
88  else if ((typeQualifiers & TYPEQUAL_VARYING) != 0) {
89  if (type->IsVoidType())
90  Error(pos, "\"varying\" qualifier is illegal with \"void\" type.");
91  else
92  type = type->GetAsVaryingType();
93  }
94  else {
95  if (type->IsVoidType() == false)
96  type = type->GetAsUnboundVariabilityType();
97  }
98 
99  if ((typeQualifiers & TYPEQUAL_UNSIGNED) != 0) {
100  if ((typeQualifiers & TYPEQUAL_SIGNED) != 0)
101  Error(pos, "Illegal to apply both \"signed\" and \"unsigned\" "
102  "qualifiers.");
103 
104  const Type *unsignedType = type->GetAsUnsignedType();
105  if (unsignedType != NULL)
106  type = unsignedType;
107  else {
108  const Type *resolvedType =
110  Error(pos, "\"unsigned\" qualifier is illegal with \"%s\" type.",
111  resolvedType->GetString().c_str());
112  }
113  }
114 
115  if ((typeQualifiers & TYPEQUAL_SIGNED) != 0 && type->IsIntType() == false) {
116  const Type *resolvedType =
118  Error(pos, "\"signed\" qualifier is illegal with non-integer type "
119  "\"%s\".", resolvedType->GetString().c_str());
120  }
121 
122  return type;
123 }
124 
125 
126 ///////////////////////////////////////////////////////////////////////////
127 // DeclSpecs
128 
129 DeclSpecs::DeclSpecs(const Type *t, StorageClass sc, int tq) {
130  baseType = t;
131  storageClass = sc;
132  typeQualifiers = tq;
133  soaWidth = 0;
134  vectorSize = 0;
135  if (t != NULL) {
136  if (m->symbolTable->ContainsType(t)) {
137  // Typedefs might have uniform/varying qualifiers inside.
138  if (t->IsVaryingType()) {
140  }
141  else if (t->IsUniformType()) {
143  }
144  }
145  }
146 }
147 
148 
149 const Type *
151  const Type *retType = baseType;
152 
153  if (retType == NULL) {
154  Warning(pos, "No type specified in declaration. Assuming int32.");
156  }
157 
158  if (vectorSize > 0) {
159  const AtomicType *atomicType = CastType<AtomicType>(retType);
160  if (atomicType == NULL) {
161  Error(pos, "Only atomic types (int, float, ...) are legal for vector "
162  "types.");
163  return NULL;
164  }
165  retType = new VectorType(atomicType, vectorSize);
166  }
167 
168  retType = lApplyTypeQualifiers(typeQualifiers, retType, pos);
169 
170  if (soaWidth > 0) {
171 #ifdef ISPC_NVPTX_ENABLED
172 #if 0 /* see stmt.cpp in DeclStmt::EmitCode for work-around of SOAType Declaration */
173  if (g->target->getISA() == Target::NVPTX)
174  {
175  Error(pos, "\"soa\" data types are currently not supported with \"nvptx\" target.");
176  return NULL;
177  }
178 #endif
179 #endif /* ISPC_NVPTX_ENABLED */
180  const StructType *st = CastType<StructType>(retType);
181 
182  if (st == NULL) {
183  Error(pos, "Illegal to provide soa<%d> qualifier with non-struct "
184  "type \"%s\".", soaWidth, retType->GetString().c_str());
185  return NULL;
186  }
187  else if (soaWidth <= 0 || (soaWidth & (soaWidth - 1)) != 0) {
188  Error(pos, "soa<%d> width illegal. Value must be positive power "
189  "of two.", soaWidth);
190  return NULL;
191  }
192 
193  if (st->IsUniformType()) {
194  Error(pos, "\"uniform\" qualifier and \"soa<%d>\" qualifier can't "
195  "both be used in a type declaration.", soaWidth);
196  return NULL;
197  }
198  else if (st->IsVaryingType()) {
199  Error(pos, "\"varying\" qualifier and \"soa<%d>\" qualifier can't "
200  "both be used in a type declaration.", soaWidth);
201  return NULL;
202  }
203  else
204  retType = st->GetAsSOAType(soaWidth);
205 
206  if (soaWidth < g->target->getVectorWidth())
207  PerformanceWarning(pos, "soa<%d> width smaller than gang size %d "
208  "currently leads to inefficient code to access "
209  "soa types.", soaWidth, g->target->getVectorWidth());
210  }
211 
212  return retType;
213 }
214 
215 
216 static const char *
218  switch (storageClass) {
219  case SC_NONE: return "";
220  case SC_EXTERN: return "extern";
221  case SC_EXTERN_C: return "extern \"C\"";
222  case SC_STATIC: return "static";
223  case SC_TYPEDEF: return "typedef";
224  default: FATAL("Unhandled storage class in lGetStorageClassName");
225  return "";
226  }
227 }
228 
229 
230 void
232  printf("Declspecs: [%s ", lGetStorageClassName(storageClass));
233 
234  if (soaWidth > 0) printf("soa<%d> ", soaWidth);
236  printf("base type: %s", baseType->GetString().c_str());
237 
238  if (vectorSize > 0) printf("<%d>", vectorSize);
239  printf("]");
240 }
241 
242 
243 ///////////////////////////////////////////////////////////////////////////
244 // Declarator
245 
247  : pos(p), kind(dk) {
248  child = NULL;
249  typeQualifiers = 0;
251  arraySize = -1;
252  type = NULL;
253  initExpr = NULL;
254 }
255 
256 
257 void
259  const Type *baseType = ds->GetBaseType(pos);
260 
261  InitFromType(baseType, ds);
262 
263  if (type == NULL) {
264  AssertPos(pos, m->errorCount > 0);
265  return;
266  }
267 
269 
270  if (ds->declSpecList.size() > 0 &&
271  CastType<FunctionType>(type) == NULL) {
272  Error(pos, "__declspec specifiers for non-function type \"%s\" are "
273  "not used.", type->GetString().c_str());
274  }
275 }
276 
277 
278 void
279 Declarator::Print(int indent) const {
280  printf("%*cdeclarator: [", indent, ' ');
281  pos.Print();
282 
284  printf("%s ", lGetStorageClassName(storageClass));
285  if (name.size() > 0)
286  printf("%s", name.c_str());
287  else
288  printf("(unnamed)");
289 
290  printf(", array size = %d", arraySize);
291 
292  printf(", kind = ");
293  switch (kind) {
294  case DK_BASE: printf("base"); break;
295  case DK_POINTER: printf("pointer"); break;
296  case DK_REFERENCE: printf("reference"); break;
297  case DK_ARRAY: printf("array"); break;
298  case DK_FUNCTION: printf("function"); break;
299  default: FATAL("Unhandled declarator kind");
300  }
301 
302  if (initExpr != NULL) {
303  printf(" = (");
304  initExpr->Print();
305  printf(")");
306  }
307 
308  if (functionParams.size() > 0) {
309  for (unsigned int i = 0; i < functionParams.size(); ++i) {
310  printf("\n%*cfunc param %d:\n", indent, ' ', i);
311  functionParams[i]->Print(indent+4);
312  }
313  }
314 
315  if (child != NULL)
316  child->Print(indent + 4);
317 
318  printf("]\n");
319 }
320 
321 
322 void
323 Declarator::InitFromType(const Type *baseType, DeclSpecs *ds) {
324  bool hasUniformQual = ((typeQualifiers & TYPEQUAL_UNIFORM) != 0);
325  bool hasVaryingQual = ((typeQualifiers & TYPEQUAL_VARYING) != 0);
326  bool isTask = ((typeQualifiers & TYPEQUAL_TASK) != 0);
327  bool isExported = ((typeQualifiers & TYPEQUAL_EXPORT) != 0);
328  bool isConst = ((typeQualifiers & TYPEQUAL_CONST) != 0);
329  bool isUnmasked = ((typeQualifiers & TYPEQUAL_UNMASKED) != 0);
330 
331  if (hasUniformQual && hasVaryingQual) {
332  Error(pos, "Can't provide both \"uniform\" and \"varying\" qualifiers.");
333  return;
334  }
335  if (kind != DK_FUNCTION && isTask) {
336  Error(pos, "\"task\" qualifier illegal in variable declaration.");
337  return;
338  }
339  if (kind != DK_FUNCTION && isUnmasked) {
340  Error(pos, "\"unmasked\" qualifier illegal in variable declaration.");
341  return;
342  }
343  if (kind != DK_FUNCTION && isExported) {
344  Error(pos, "\"export\" qualifier illegal in variable declaration.");
345  return;
346  }
347 
348  Variability variability(Variability::Unbound);
349  if (hasUniformQual)
350  variability = Variability::Uniform;
351  else if (hasVaryingQual)
352  variability = Variability::Varying;
353 
354  if (kind == DK_BASE) {
355  // All of the type qualifiers should be in the DeclSpecs for the
356  // base declarator
358  AssertPos(pos, child == NULL);
359  type = baseType;
360  }
361  else if (kind == DK_POINTER) {
362  /* For now, any pointer to an SOA type gets the slice property; if
363  we add the capability to declare pointers as slices or not,
364  we'll want to set this based on a type qualifier here. */
365  const Type *ptrType = new PointerType(baseType, variability, isConst,
366  baseType->IsSOAType());
367  if (child != NULL) {
368  child->InitFromType(ptrType, ds);
369  type = child->type;
370  name = child->name;
371  }
372  else
373  type = ptrType;
374  }
375  else if (kind == DK_REFERENCE) {
376  if (hasUniformQual) {
377  Error(pos, "\"uniform\" qualifier is illegal to apply to references.");
378  return;
379  }
380  if (hasVaryingQual) {
381  Error(pos, "\"varying\" qualifier is illegal to apply to references.");
382  return;
383  }
384  if (isConst) {
385  Error(pos, "\"const\" qualifier is to illegal apply to references.");
386  return;
387  }
388  // The parser should disallow this already, but double check.
389  if (CastType<ReferenceType>(baseType) != NULL) {
390  Error(pos, "References to references are illegal.");
391  return;
392  }
393 
394  const Type *refType = new ReferenceType(baseType);
395  if (child != NULL) {
396  child->InitFromType(refType, ds);
397  type = child->type;
398  name = child->name;
399  }
400  else
401  type = refType;
402  }
403  else if (kind == DK_ARRAY) {
404  if (baseType->IsVoidType()) {
405  Error(pos, "Arrays of \"void\" type are illegal.");
406  return;
407  }
408  if (CastType<ReferenceType>(baseType)) {
409  Error(pos, "Arrays of references (type \"%s\") are illegal.",
410  baseType->GetString().c_str());
411  return;
412  }
413 
414 #ifdef ISPC_NVPTX_ENABLED
415 #if 0 /* NVPTX */
416  if (baseType->IsUniformType())
417  {
418  fprintf(stderr, " detected uniform array of size= %d array= %s\n" ,arraySize,
419  baseType->IsArrayType() ? " true " : " false ");
420  }
421 #endif
422 #endif /* ISPC_NVPTX_ENABLED */
423  const Type *arrayType = new ArrayType(baseType, arraySize);
424  if (child != NULL) {
425  child->InitFromType(arrayType, ds);
426  type = child->type;
427  name = child->name;
428  }
429  else
430  type = arrayType;
431  }
432  else if (kind == DK_FUNCTION) {
433  llvm::SmallVector<const Type *, 8> args;
434  llvm::SmallVector<std::string, 8> argNames;
435  llvm::SmallVector<Expr *, 8> argDefaults;
436  llvm::SmallVector<SourcePos, 8> argPos;
437 
438  // Loop over the function arguments and store the names, types,
439  // default values (if any), and source file positions each one in
440  // the corresponding vector.
441  for (unsigned int i = 0; i < functionParams.size(); ++i) {
442  Declaration *d = functionParams[i];
443 
444  if (d == NULL) {
445  AssertPos(pos, m->errorCount > 0);
446  continue;
447  }
448  if (d->declarators.size() == 0) {
449  // function declaration like foo(float), w/o a name for the
450  // parameter; wire up a placeholder Declarator for it
451  d->declarators.push_back(new Declarator(DK_BASE, pos));
452  d->declarators[0]->InitFromDeclSpecs(d->declSpecs);
453  }
454 
455  AssertPos(pos, d->declarators.size() == 1);
456  Declarator *decl = d->declarators[0];
457  if (decl == NULL || decl->type == NULL) {
458  AssertPos(pos, m->errorCount > 0);
459  continue;
460  }
461 
462  if (decl->name == "") {
463  // Give a name to any anonymous parameter declarations
464  char buf[32];
465  sprintf(buf, "__anon_parameter_%d", i);
466  decl->name = buf;
467  }
468  decl->type = decl->type->ResolveUnboundVariability(Variability::Varying);
469 
470  if (d->declSpecs->storageClass != SC_NONE)
471  Error(decl->pos, "Storage class \"%s\" is illegal in "
472  "function parameter declaration for parameter \"%s\".",
474  decl->name.c_str());
475  if (decl->type->IsVoidType()) {
476  Error(decl->pos, "Parameter with type \"void\" illegal in function "
477  "parameter list.");
478  decl->type = NULL;
479  }
480 
481  const ArrayType *at = CastType<ArrayType>(decl->type);
482  if (at != NULL) {
483  // As in C, arrays are passed to functions as pointers to
484  // their element type. We'll just immediately make this
485  // change now. (One shortcoming of losing the fact that
486  // the it was originally an array is that any warnings or
487  // errors later issued that print the function type will
488  // report this differently than it was originally declared
489  // in the function, but it's not clear that this is a
490  // significant problem.)
491  const Type *targetType = at->GetElementType();
492  if (targetType == NULL) {
493  AssertPos(pos, m->errorCount > 0);
494  return;
495  }
496 
497  decl->type = PointerType::GetUniform(targetType, at->IsSOAType());
498 
499  // Make sure there are no unsized arrays (other than the
500  // first dimension) in function parameter lists.
501  at = CastType<ArrayType>(targetType);
502  while (at != NULL) {
503  if (at->GetElementCount() == 0)
504  Error(decl->pos, "Arrays with unsized dimensions in "
505  "dimensions after the first one are illegal in "
506  "function parameter lists.");
507  at = CastType<ArrayType>(at->GetElementType());
508  }
509  }
510 
511  args.push_back(decl->type);
512  argNames.push_back(decl->name);
513  argPos.push_back(decl->pos);
514 
515  Expr *init = NULL;
516  // Try to find an initializer expression.
517  while (decl != NULL) {
518  if (decl->initExpr != NULL) {
519  decl->initExpr = TypeCheck(decl->initExpr);
520  decl->initExpr = Optimize(decl->initExpr);
521  if (decl->initExpr != NULL) {
522  init = llvm::dyn_cast<ConstExpr>(decl->initExpr);
523  if (init == NULL)
524  init = llvm::dyn_cast<NullPointerExpr>(decl->initExpr);
525  if (init == NULL)
526  Error(decl->initExpr->pos, "Default value for parameter "
527  "\"%s\" must be a compile-time constant.",
528  decl->name.c_str());
529  }
530  break;
531  }
532  else
533  decl = decl->child;
534  }
535  argDefaults.push_back(init);
536  }
537 
538  const Type *returnType = baseType;
539  if (returnType == NULL) {
540  Error(pos, "No return type provided in function declaration.");
541  return;
542  }
543 
544  if (CastType<FunctionType>(returnType) != NULL) {
545  Error(pos, "Illegal to return function type from function.");
546  return;
547  }
548 
549  returnType = returnType->ResolveUnboundVariability(Variability::Varying);
550 
551  bool isExternC = ds && (ds->storageClass == SC_EXTERN_C);
552  bool isExported = ds && ((ds->typeQualifiers & TYPEQUAL_EXPORT) != 0);
553  bool isTask = ds && ((ds->typeQualifiers & TYPEQUAL_TASK) != 0);
554  bool isUnmasked = ds && ((ds->typeQualifiers & TYPEQUAL_UNMASKED) != 0);
555 
556  if (isExported && isTask) {
557  Error(pos, "Function can't have both \"task\" and \"export\" "
558  "qualifiers");
559  return;
560  }
561  if (isExternC && isTask) {
562  Error(pos, "Function can't have both \"extern \"C\"\" and \"task\" "
563  "qualifiers");
564  return;
565  }
566  if (isExternC && isExported) {
567  Error(pos, "Function can't have both \"extern \"C\"\" and \"export\" "
568  "qualifiers");
569  return;
570  }
571  if (isUnmasked && isExported)
572  Warning(pos, "\"unmasked\" qualifier is redundant for exported "
573  "functions.");
574 
575  if (child == NULL) {
576  AssertPos(pos, m->errorCount > 0);
577  return;
578  }
579 
580  const FunctionType *functionType =
581  new FunctionType(returnType, args, argNames, argDefaults,
582  argPos, isTask, isExported, isExternC, isUnmasked);
583 
584  // handle any explicit __declspecs on the function
585  if (ds != NULL) {
586  for (int i = 0; i < (int)ds->declSpecList.size(); ++i) {
587  std::string str = ds->declSpecList[i].first;
588  SourcePos pos = ds->declSpecList[i].second;
589 
590  if (str == "safe")
591  (const_cast<FunctionType *>(functionType))->isSafe = true;
592  else if (!strncmp(str.c_str(), "cost", 4)) {
593  int cost = atoi(str.c_str() + 4);
594  if (cost < 0)
595  Error(pos, "Negative function cost %d is illegal.",
596  cost);
597  (const_cast<FunctionType *>(functionType))->costOverride = cost;
598  }
599  else
600  Error(pos, "__declspec parameter \"%s\" unknown.", str.c_str());
601  }
602  }
603 
604  child->InitFromType(functionType, ds);
605  type = child->type;
606  name = child->name;
607  }
608 }
609 
610 ///////////////////////////////////////////////////////////////////////////
611 // Declaration
612 
613 Declaration::Declaration(DeclSpecs *ds, std::vector<Declarator *> *dlist) {
614  declSpecs = ds;
615  if (dlist != NULL)
616  declarators = *dlist;
617  for (unsigned int i = 0; i < declarators.size(); ++i)
618  if (declarators[i] != NULL)
619  declarators[i]->InitFromDeclSpecs(declSpecs);
620 }
621 
622 
624  declSpecs = ds;
625  if (d != NULL) {
626  d->InitFromDeclSpecs(ds);
627  declarators.push_back(d);
628  }
629 }
630 
631 
632 
633 std::vector<VariableDeclaration>
636  std::vector<VariableDeclaration> vars;
637 
638  for (unsigned int i = 0; i < declarators.size(); ++i) {
639  Declarator *decl = declarators[i];
640  if (decl == NULL || decl->type == NULL) {
641  // Ignore earlier errors
642  Assert(m->errorCount > 0);
643  continue;
644  }
645 
646  if (decl->type->IsVoidType())
647  Error(decl->pos, "\"void\" type variable illegal in declaration.");
648  else if (CastType<FunctionType>(decl->type) == NULL) {
650  Symbol *sym = new Symbol(decl->name, decl->pos, decl->type,
651  decl->storageClass);
652  m->symbolTable->AddVariable(sym);
653  vars.push_back(VariableDeclaration(sym, decl->initExpr));
654  }
655  }
656 
657  return vars;
658 }
659 
660 
661 void
664 
665  for (unsigned int i = 0; i < declarators.size(); ++i) {
666  Declarator *decl = declarators[i];
667  if (decl == NULL || decl->type == NULL) {
668  // Ignore earlier errors
669  Assert(m->errorCount > 0);
670  continue;
671  }
672 
673  const FunctionType *ftype = CastType<FunctionType>(decl->type);
674  if (ftype == NULL)
675  continue;
676 
677  bool isInline = (declSpecs->typeQualifiers & TYPEQUAL_INLINE);
678  m->AddFunctionDeclaration(decl->name, ftype, decl->storageClass,
679  isInline, decl->pos);
680  }
681 }
682 
683 
684 void
685 Declaration::Print(int indent) const {
686  printf("%*cDeclaration: specs [", indent, ' ');
687  declSpecs->Print();
688  printf("], declarators:\n");
689  for (unsigned int i = 0 ; i < declarators.size(); ++i)
690  declarators[i]->Print(indent+4);
691 }
692 
693 
694 ///////////////////////////////////////////////////////////////////////////
695 
696 void
697 GetStructTypesNamesPositions(const std::vector<StructDeclaration *> &sd,
698  llvm::SmallVector<const Type *, 8> *elementTypes,
699  llvm::SmallVector<std::string, 8> *elementNames,
700  llvm::SmallVector<SourcePos, 8> *elementPositions) {
701  std::set<std::string> seenNames;
702  for (unsigned int i = 0; i < sd.size(); ++i) {
703  const Type *type = sd[i]->type;
704  if (type == NULL)
705  continue;
706 
707  // FIXME: making this fake little DeclSpecs here is really
708  // disgusting
709  DeclSpecs ds(type);
710  if (type->IsVoidType() == false) {
711  if (type->IsUniformType())
713  else if (type->IsVaryingType())
715  else if (type->GetSOAWidth() != 0)
716  ds.soaWidth = type->GetSOAWidth();
717  // FIXME: ds.vectorSize?
718  }
719 
720  for (unsigned int j = 0; j < sd[i]->declarators->size(); ++j) {
721  Declarator *d = (*sd[i]->declarators)[j];
722  d->InitFromDeclSpecs(&ds);
723 
724  if (d->type->IsVoidType())
725  Error(d->pos, "\"void\" type illegal for struct member.");
726 
727  elementTypes->push_back(d->type);
728 
729  if (seenNames.find(d->name) != seenNames.end())
730  Error(d->pos, "Struct member \"%s\" has same name as a "
731  "previously-declared member.", d->name.c_str());
732  else
733  seenNames.insert(d->name);
734 
735  elementNames->push_back(d->name);
736  elementPositions->push_back(d->pos);
737  }
738  }
739 
740  for (int i = 0; i < (int)elementTypes->size() - 1; ++i) {
741  const ArrayType *arrayType = CastType<ArrayType>((*elementTypes)[i]);
742 
743  if (arrayType != NULL && arrayType->GetElementCount() == 0)
744  Error((*elementPositions)[i], "Unsized arrays aren't allowed except "
745  "for the last member in a struct definition.");
746  }
747 }
bool IsVoidType() const
Definition: type.cpp:246
bool IsVaryingType() const
Definition: type.h:150
const Type * baseType
Definition: decl.h:101
void InitFromType(const Type *base, DeclSpecs *ds)
Definition: decl.cpp:323
int GetElementCount() const
Definition: type.cpp:1470
const Type * type
Definition: decl.h:176
int arraySize
Definition: decl.h:166
bool ContainsType(const Type *type) const
Definition: sym.cpp:218
Definition: decl.h:123
DeclSpecs * declSpecs
Definition: decl.h:205
void PerformanceWarning(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:426
virtual void Print() const =0
#define TYPEQUAL_SIGNED
Definition: decl.h:73
std::vector< std::pair< std::string, SourcePos > > declSpecList
Definition: decl.h:115
bool IsArrayType() const
Definition: type.cpp:236
int getVectorWidth() const
Definition: ispc.h:283
Module * m
Definition: ispc.cpp:89
An expression that represents a NULL pointer.
Definition: expr.h:776
virtual const Type * GetAsUnboundVariabilityType() const =0
#define TYPEQUAL_CONST
Definition: decl.h:69
#define TYPEQUAL_UNSIGNED
Definition: decl.h:74
Target * target
Definition: ispc.h:543
bool AddVariable(Symbol *symbol)
Definition: sym.cpp:98
Expression representing a compile-time constant value.
Definition: expr.h:390
void GetStructTypesNamesPositions(const std::vector< StructDeclaration * > &sd, llvm::SmallVector< const Type *, 8 > *elementTypes, llvm::SmallVector< std::string, 8 > *elementNames, llvm::SmallVector< SourcePos, 8 > *elementPositions)
Definition: decl.cpp:697
int soaWidth
Definition: decl.h:113
void InitFromDeclSpecs(DeclSpecs *ds)
Definition: decl.cpp:258
#define TYPEQUAL_INLINE
Definition: decl.h:75
#define Assert(expr)
Definition: ispc.h:170
const Type * GetBaseType(SourcePos pos) const
Definition: decl.cpp:150
StorageClass storageClass
Definition: decl.h:162
#define TYPEQUAL_EXPORT
Definition: decl.h:76
Declarator(DeclaratorKind dk, SourcePos p)
Definition: decl.cpp:246
virtual const Type * GetAsUniformType() const =0
int vectorSize
Definition: decl.h:108
Type implementation for pointers to other types.
Definition: type.h:446
virtual std::string GetString() const =0
int GetSOAWidth() const
Definition: type.h:160
static PointerType * GetUniform(const Type *t, bool isSlice=false)
Definition: type.cpp:963
Expr * initExpr
Definition: decl.h:172
const SourcePos pos
Definition: decl.h:146
header file with declarations for symbol and symbol table classes.
Type representing a reference to another (non-reference) type.
Definition: type.h:832
std::string name
Definition: decl.h:169
ASTNode * Optimize(ASTNode *root)
Definition: ast.cpp:282
ASTNode * TypeCheck(ASTNode *root)
Definition: ast.cpp:306
File with declarations for classes related to statements in the language.
Declaration(DeclSpecs *ds, std::vector< Declarator * > *dlist=NULL)
Definition: decl.cpp:613
Globals * g
Definition: ispc.cpp:88
bool IsUniformType() const
Definition: type.h:145
void Print(int indent) const
Definition: decl.cpp:685
void Error(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:385
#define TYPEQUAL_TASK
Definition: decl.h:72
void AddFunctionDeclaration(const std::string &name, const FunctionType *ftype, StorageClass sc, bool isInline, SourcePos pos)
Definition: module.cpp:876
static const Type * lApplyTypeQualifiers(int typeQualifiers, const Type *type, SourcePos pos)
Definition: decl.cpp:68
DeclSpecs(const Type *t=NULL, StorageClass sc=SC_NONE, int tq=TYPEQUAL_NONE)
Definition: decl.cpp:129
Representation of a structure holding a number of members.
Definition: type.h:690
std::vector< Declaration * > functionParams
Definition: decl.h:180
virtual bool IsIntType() const =0
#define AssertPos(pos, expr)
Definition: ispc.h:173
ISA getISA() const
Definition: ispc.h:267
virtual const Type * GetAsConstType() const =0
AtomicType represents basic types like floats, ints, etc.
Definition: type.h:292
#define TYPEQUAL_UNMASKED
Definition: decl.h:77
Representation of a range of positions in a source file.
Definition: ispc.h:134
StorageClass storageClass
Definition: decl.h:91
Representation of a full declaration of one or more variables, including the shared DeclSpecs as well...
Definition: decl.h:187
Declarations related to type declarations; the parser basically creates instances of these classes...
StorageClass
Definition: ispc.h:118
DeclaratorKind
Definition: decl.h:119
void Warning(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:410
#define FATAL(message)
Definition: util.h:113
A (short) vector of atomic types.
Definition: type.h:639
std::vector< VariableDeclaration > GetVariableDeclarations() const
Definition: decl.cpp:634
Representation of the declaration of a single variable.
Definition: decl.h:132
std::vector< Declarator * > declarators
Definition: decl.h:206
void Print() const
Definition: ispc.cpp:1588
Definition: ispc.h:119
Declarator * child
Definition: decl.h:157
const DeclaratorKind kind
Definition: decl.h:153
virtual const Type * GetAsVaryingType() const =0
#define TYPEQUAL_VARYING
Definition: decl.h:71
#define TYPEQUAL_UNIFORM
Definition: decl.h:70
const AtomicType * GetAsUnboundVariabilityType() const
Definition: type.cpp:370
const StructType * GetAsSOAType(int width) const
Definition: type.cpp:2121
static const AtomicType * UniformInt32
Definition: type.h:349
Type representing a function (return type + argument types)
Definition: type.h:883
Representation of a program symbol.
Definition: sym.h:63
Interface class that defines the type abstraction.
Definition: type.h:101
Expr abstract base class and expression implementations.
void Print() const
Definition: decl.cpp:231
Expr is the abstract base class that defines the interface that all expression types must implement...
Definition: expr.h:48
int typeQualifiers
Definition: decl.h:94
void DeclareFunctions()
Definition: decl.cpp:662
static const char * lGetStorageClassName(StorageClass storageClass)
Definition: decl.cpp:217
const Type * GetElementType() const
Definition: type.cpp:1476
void Print(int indent) const
Definition: decl.cpp:279
virtual const Type * GetAsUnsignedType() const
Definition: type.cpp:3308
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
int errorCount
Definition: module.h:151
static void lPrintTypeQualifiers(int typeQualifiers)
Definition: decl.cpp:51
bool IsSOAType() const
Definition: type.h:156
Definition: decl.h:120
SymbolTable * symbolTable
Definition: module.h:155
virtual const Type * ResolveUnboundVariability(Variability v) const =0
File with declarations for classes related to type representation.
Representation of the declaration specifiers in a declaration.
Definition: decl.h:84
One-dimensional array type.
Definition: type.h:555
int typeQualifiers
Definition: decl.h:160