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