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