1/*
2  Copyright (c) 2010-2021, 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%locations
35
36/* supress shift-reduces conflict message for dangling else */
37/* one for 'if', one for 'cif' */
38%expect 2
39
40%define parse.error verbose
41
42%code requires {
43
44#define yytnamerr lYYTNameErr
45
46
47#define YYLTYPE SourcePos
48
49# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
50    do                                                                 \
51      if (N)                                                           \
52        {                                                              \
53          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;       \
54          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;     \
55          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;        \
56          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;      \
57          (Current).name         = YYRHSLOC (Rhs, 1).name    ;         \
58        }                                                              \
59      else                                                             \
60        { /* empty RHS */                                              \
61          (Current).first_line   = (Current).last_line   =             \
62            YYRHSLOC (Rhs, 0).last_line;                               \
63          (Current).first_column = (Current).last_column =             \
64            YYRHSLOC (Rhs, 0).last_column;                             \
65          (Current).name = NULL;                        /* new */ \
66        }                                                              \
67    while (0)
68
69struct ForeachDimension;
70
71struct PragmaAttributes {
72    enum class AttributeType { none, pragmaloop, pragmawarning };
73    PragmaAttributes() {
74        aType = AttributeType::none;
75        unrollType =  Globals::pragmaUnrollType::none;
76        count = -1;
77    }
78    AttributeType aType;
79    Globals::pragmaUnrollType unrollType;
80    int count;
81};
82
83}
84
85
86%{
87
88#include "ispc.h"
89#include "type.h"
90#include "module.h"
91#include "decl.h"
92#include "expr.h"
93#include "sym.h"
94#include "stmt.h"
95#include "util.h"
96
97#include <stdio.h>
98#include <llvm/IR/Constants.h>
99
100using namespace ispc;
101
102#define UNIMPLEMENTED \
103        Error(yylloc, "Unimplemented parser functionality %s:%d", \
104        __FILE__, __LINE__);
105
106union YYSTYPE;
107extern int yylex();
108
109extern char *yytext;
110
111void yyerror(const char *s);
112
113static int lYYTNameErr(char *yyres, const char *yystr);
114
115static void lSuggestBuiltinAlternates();
116static void lSuggestParamListAlternates();
117
118static void lAddDeclaration(DeclSpecs *ds, Declarator *decl);
119static void lAddFunctionParams(Declarator *decl);
120static void lAddMaskToSymbolTable(SourcePos pos);
121static void lAddThreadIndexCountToSymbolTable(SourcePos pos);
122static std::string lGetAlternates(std::vector<std::string> &alternates);
123static const char *lGetStorageClassString(StorageClass sc);
124static bool lGetConstantInt(Expr *expr, int *value, SourcePos pos, const char *usage);
125static EnumType *lCreateEnumType(const char *name, std::vector<Symbol *> *enums,
126                                 SourcePos pos);
127static void lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
128                                       const EnumType *enumType);
129
130static const char *lBuiltinTokens[] = {
131    "assert", "bool", "break", "case", "cdo",
132    "cfor", "cif", "cwhile", "const", "continue", "default",
133    "do", "delete", "double", "else", "enum", "export", "extern", "false",
134    "float", "for", "foreach", "foreach_active", "foreach_tiled",
135     "foreach_unique", "goto", "if", "in", "inline",
136    "int", "int8", "int16", "int32", "int64", "launch", "new", "NULL",
137    "print", "return", "signed", "sizeof", "static", "struct", "switch",
138    "sync", "task", "true", "typedef", "uniform", "unmasked", "unsigned",
139    "varying", "void", "while", NULL
140};
141
142static const char *lParamListTokens[] = {
143    "bool", "const", "double", "enum", "false", "float", "int",
144    "int8", "int16", "int32", "int64", "signed", "struct", "true",
145    "uniform", "unsigned", "varying", "void", NULL
146};
147
148struct ForeachDimension {
149    ForeachDimension(Symbol *s = NULL, Expr *b = NULL, Expr *e = NULL) {
150        sym = s;
151        beginExpr = b;
152        endExpr = e;
153    }
154    Symbol *sym;
155    Expr *beginExpr, *endExpr;
156};
157
158%}
159
160%union {
161    uint64_t intVal;
162    float  floatVal;
163    double doubleVal;
164    std::string *stringVal;
165    const char *constCharPtr;
166
167    Expr *expr;
168    ExprList *exprList;
169    const Type *type;
170    std::vector<std::pair<const Type *, SourcePos> > *typeList;
171    const AtomicType *atomicType;
172    int typeQualifier;
173    StorageClass storageClass;
174    Stmt *stmt;
175    DeclSpecs *declSpecs;
176    Declaration *declaration;
177    std::vector<Declarator *> *declarators;
178    std::vector<Declaration *> *declarationList;
179    Declarator *declarator;
180    std::vector<Declarator *> *structDeclaratorList;
181    StructDeclaration *structDeclaration;
182    std::vector<StructDeclaration *> *structDeclarationList;
183    const EnumType *enumType;
184    Symbol *symbol;
185    std::vector<Symbol *> *symbolList;
186    ForeachDimension *foreachDimension;
187    std::vector<ForeachDimension *> *foreachDimensionList;
188    std::pair<std::string, SourcePos> *declspecPair;
189    std::vector<std::pair<std::string, SourcePos> > *declspecList;
190    PragmaAttributes *pragmaAttributes;
191}
192
193
194%token TOKEN_INT8_CONSTANT TOKEN_UINT8_CONSTANT
195%token TOKEN_INT16_CONSTANT TOKEN_UINT16_CONSTANT
196%token TOKEN_INT32_CONSTANT TOKEN_UINT32_CONSTANT
197%token TOKEN_INT64_CONSTANT TOKEN_UINT64_CONSTANT
198%token TOKEN_INT32DOTDOTDOT_CONSTANT TOKEN_UINT32DOTDOTDOT_CONSTANT
199%token TOKEN_INT64DOTDOTDOT_CONSTANT TOKEN_UINT64DOTDOTDOT_CONSTANT
200%token TOKEN_FLOAT_CONSTANT TOKEN_DOUBLE_CONSTANT TOKEN_STRING_C_LITERAL
201%token TOKEN_IDENTIFIER TOKEN_STRING_LITERAL TOKEN_TYPE_NAME TOKEN_PRAGMA TOKEN_NULL
202%token TOKEN_PTR_OP TOKEN_INC_OP TOKEN_DEC_OP TOKEN_LEFT_OP TOKEN_RIGHT_OP
203%token TOKEN_LE_OP TOKEN_GE_OP TOKEN_EQ_OP TOKEN_NE_OP
204%token TOKEN_AND_OP TOKEN_OR_OP TOKEN_MUL_ASSIGN TOKEN_DIV_ASSIGN TOKEN_MOD_ASSIGN
205%token TOKEN_ADD_ASSIGN TOKEN_SUB_ASSIGN TOKEN_LEFT_ASSIGN TOKEN_RIGHT_ASSIGN
206%token TOKEN_AND_ASSIGN TOKEN_OR_ASSIGN TOKEN_XOR_ASSIGN
207%token TOKEN_SIZEOF TOKEN_NEW TOKEN_DELETE TOKEN_IN TOKEN_INTRINSIC_CALL TOKEN_ALLOCA
208
209%token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_NOINLINE TOKEN_VECTORCALL TOKEN_TASK TOKEN_DECLSPEC
210%token TOKEN_UNIFORM TOKEN_VARYING TOKEN_TYPEDEF TOKEN_SOA TOKEN_UNMASKED
211%token TOKEN_CHAR TOKEN_INT TOKEN_SIGNED TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE
212%token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL
213%token TOKEN_UINT8 TOKEN_UINT16 TOKEN_UINT TOKEN_UINT64
214%token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE
215
216%token TOKEN_CASE TOKEN_DEFAULT TOKEN_IF TOKEN_ELSE TOKEN_SWITCH
217%token TOKEN_WHILE TOKEN_DO TOKEN_LAUNCH TOKEN_FOREACH TOKEN_FOREACH_TILED
218%token TOKEN_FOREACH_UNIQUE TOKEN_FOREACH_ACTIVE TOKEN_DOTDOTDOT
219%token TOKEN_FOR TOKEN_GOTO TOKEN_CONTINUE TOKEN_BREAK TOKEN_RETURN
220%token TOKEN_CIF TOKEN_CDO TOKEN_CFOR TOKEN_CWHILE
221%token TOKEN_SYNC TOKEN_PRINT TOKEN_ASSERT
222
223%type <expr> primary_expression postfix_expression integer_dotdotdot
224%type <expr> unary_expression cast_expression funcall_expression launch_expression intrincall_expression
225%type <expr> multiplicative_expression additive_expression shift_expression
226%type <expr> relational_expression equality_expression and_expression
227%type <expr> exclusive_or_expression inclusive_or_expression
228%type <expr> logical_and_expression logical_or_expression new_expression
229%type <expr> conditional_expression assignment_expression expression
230%type <expr> initializer constant_expression for_test
231%type <exprList> argument_expression_list initializer_list
232
233%type <stmt> attributed_statement labeled_statement compound_statement for_init_statement statement
234%type <stmt> expression_statement selection_statement iteration_statement
235%type <stmt> jump_statement statement_list declaration_statement print_statement
236%type <stmt> assert_statement sync_statement delete_statement unmasked_statement
237
238%type <declaration> declaration parameter_declaration
239%type <declarators> init_declarator_list
240%type <declarationList> parameter_list parameter_type_list
241%type <declarator> declarator pointer reference
242%type <declarator> init_declarator direct_declarator struct_declarator
243%type <declarator> abstract_declarator direct_abstract_declarator
244
245%type <structDeclaratorList> struct_declarator_list
246%type <structDeclaration> struct_declaration
247%type <structDeclarationList> struct_declaration_list
248
249%type <symbolList> enumerator_list
250%type <symbol> enumerator foreach_identifier foreach_active_identifier
251%type <enumType> enum_specifier
252
253%type <type> specifier_qualifier_list struct_or_union_specifier
254%type <type> struct_or_union_and_name
255%type <type> type_specifier type_name rate_qualified_type_specifier
256%type <type> short_vec_specifier
257%type <typeList> type_specifier_list
258%type <atomicType> atomic_var_type_specifier
259
260%type <typeQualifier> type_qualifier type_qualifier_list
261%type <storageClass> storage_class_specifier
262%type <declSpecs> declaration_specifiers
263
264%type <stringVal> string_constant intrinsic_name
265%type <constCharPtr> struct_or_union_name enum_identifier goto_identifier
266%type <constCharPtr> foreach_unique_identifier
267
268%type <intVal> int_constant soa_width_specifier rate_qualified_new
269
270%type <pragmaAttributes> pragma
271%type <foreachDimension> foreach_dimension_specifier
272%type <foreachDimensionList> foreach_dimension_list
273
274%type <declspecPair> declspec_item
275%type <declspecList> declspec_specifier declspec_list
276
277%start translation_unit
278%%
279
280string_constant
281    : TOKEN_STRING_LITERAL { $$ = new std::string(*yylval.stringVal); }
282    | string_constant TOKEN_STRING_LITERAL
283    {
284        std::string s = *((std::string *)$1);
285        s += *yylval.stringVal;
286        $$ = new std::string(s);
287    }
288    ;
289
290primary_expression
291    : TOKEN_IDENTIFIER {
292        const char *name = yylval.stringVal->c_str();
293        Symbol *s = m->symbolTable->LookupVariable(name);
294        $$ = NULL;
295        if (s)
296            $$ = new SymbolExpr(s, @1);
297        else {
298            std::vector<Symbol *> funs;
299            m->symbolTable->LookupFunction(name, &funs);
300            if (funs.size() > 0)
301                $$ = new FunctionSymbolExpr(name, funs, @1);
302        }
303        if ($$ == NULL) {
304            std::vector<std::string> alternates =
305                m->symbolTable->ClosestVariableOrFunctionMatch(name);
306            std::string alts = lGetAlternates(alternates);
307            Error(@1, "Undeclared symbol \"%s\".%s", name, alts.c_str());
308        }
309    }
310    | TOKEN_INT8_CONSTANT {
311        $$ = new ConstExpr(AtomicType::UniformInt8->GetAsConstType(),
312                           (int8_t)yylval.intVal, @1);
313    }
314    | TOKEN_UINT8_CONSTANT {
315        $$ = new ConstExpr(AtomicType::UniformUInt8->GetAsConstType(),
316                           (uint8_t)yylval.intVal, @1);
317    }
318    | TOKEN_INT16_CONSTANT {
319        $$ = new ConstExpr(AtomicType::UniformInt16->GetAsConstType(),
320                           (int16_t)yylval.intVal, @1);
321    }
322    | TOKEN_UINT16_CONSTANT {
323        $$ = new ConstExpr(AtomicType::UniformUInt16->GetAsConstType(),
324                           (uint16_t)yylval.intVal, @1);
325    }
326    | TOKEN_INT32_CONSTANT {
327        $$ = new ConstExpr(AtomicType::UniformInt32->GetAsConstType(),
328                           (int32_t)yylval.intVal, @1);
329    }
330    | TOKEN_UINT32_CONSTANT {
331        $$ = new ConstExpr(AtomicType::UniformUInt32->GetAsConstType(),
332                           (uint32_t)yylval.intVal, @1);
333    }
334    | TOKEN_INT64_CONSTANT {
335        $$ = new ConstExpr(AtomicType::UniformInt64->GetAsConstType(),
336                           (int64_t)yylval.intVal, @1);
337    }
338    | TOKEN_UINT64_CONSTANT {
339        $$ = new ConstExpr(AtomicType::UniformUInt64->GetAsConstType(),
340                           (uint64_t)yylval.intVal, @1);
341    }
342    | TOKEN_FLOAT_CONSTANT {
343        $$ = new ConstExpr(AtomicType::UniformFloat->GetAsConstType(),
344                           yylval.floatVal, @1);
345    }
346    | TOKEN_DOUBLE_CONSTANT {
347        $$ = new ConstExpr(AtomicType::UniformDouble->GetAsConstType(),
348                           yylval.doubleVal, @1);
349    }
350    | TOKEN_TRUE {
351        $$ = new ConstExpr(AtomicType::UniformBool->GetAsConstType(), true, @1);
352    }
353    | TOKEN_FALSE {
354        $$ = new ConstExpr(AtomicType::UniformBool->GetAsConstType(), false, @1);
355    }
356    | TOKEN_NULL {
357        $$ = new NullPointerExpr(@1);
358    }
359/*    | TOKEN_STRING_LITERAL
360       { UNIMPLEMENTED }*/
361    | '(' expression ')' { $$ = $2; }
362    | '(' error ')' { $$ = NULL; }
363    ;
364
365launch_expression
366    : TOKEN_LAUNCH postfix_expression '(' argument_expression_list ')'
367      {
368          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @2);
369          Expr *launchCount[3] = {oneExpr, oneExpr, oneExpr};
370          $$ = new FunctionCallExpr($2, $4, Union(@2, @5), true, launchCount);
371      }
372    | TOKEN_LAUNCH postfix_expression '(' ')'
373      {
374          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @2);
375          Expr *launchCount[3] = {oneExpr, oneExpr, oneExpr};
376          $$ = new FunctionCallExpr($2, new ExprList(Union(@3,@4)), Union(@2, @4), true, launchCount);
377       }
378
379    | TOKEN_LAUNCH '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')'
380      {
381          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @5);
382          Expr *launchCount[3] = {$3, oneExpr, oneExpr};
383          $$ = new FunctionCallExpr($5, $7, Union(@5,@8), true, launchCount);
384      }
385    | TOKEN_LAUNCH '[' assignment_expression ']' postfix_expression '(' ')'
386      {
387          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @5);
388          Expr *launchCount[3] = {$3, oneExpr, oneExpr};
389          $$ = new FunctionCallExpr($5, new ExprList(Union(@5,@6)), Union(@5,@7), true, launchCount);
390      }
391
392    | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ']' postfix_expression '(' argument_expression_list ')'
393      {
394          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @7);
395          Expr *launchCount[3] = {$3, $5, oneExpr};
396          $$ = new FunctionCallExpr($7, $9, Union(@7,@10), true, launchCount);
397      }
398    | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ']' postfix_expression '(' ')'
399      {
400          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @7);
401          Expr *launchCount[3] = {$3, $5, oneExpr};
402          $$ = new FunctionCallExpr($7, new ExprList(Union(@7,@8)), Union(@7,@9), true, launchCount);
403      }
404    | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')'
405      {
406          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @8);
407          Expr *launchCount[3] = {$6, $3, oneExpr};
408          $$ = new FunctionCallExpr($8, $10, Union(@8,@11), true, launchCount);
409      }
410    | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' ')'
411      {
412          ConstExpr *oneExpr = new ConstExpr(AtomicType::UniformInt32, (int32_t)1, @8);
413          Expr *launchCount[3] = {$6, $3, oneExpr};
414          $$ = new FunctionCallExpr($8, new ExprList(Union(@8,@9)), Union(@8,@10), true, launchCount);
415      }
416
417    | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ',' assignment_expression ']' postfix_expression '(' argument_expression_list ')'
418      {
419          Expr *launchCount[3] = {$3, $5, $7};
420          $$ = new FunctionCallExpr($9, $11, Union(@9,@12), true, launchCount);
421      }
422    | TOKEN_LAUNCH '[' assignment_expression ',' assignment_expression ',' assignment_expression ']' postfix_expression '(' ')'
423      {
424          Expr *launchCount[3] = {$3, $5, $7};
425          $$ = new FunctionCallExpr($9, new ExprList(Union(@9,@10)), Union(@9,@11), true, launchCount);
426      }
427    | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' argument_expression_list ')'
428      {
429          Expr *launchCount[3] = {$9, $6, $3};
430          $$ = new FunctionCallExpr($11, $13, Union(@11,@14), true, launchCount);
431      }
432    | TOKEN_LAUNCH '[' assignment_expression ']' '[' assignment_expression ']' '[' assignment_expression ']' postfix_expression '(' ')'
433      {
434          Expr *launchCount[3] = {$9, $6, $3};
435          $$ = new FunctionCallExpr($11, new ExprList(Union(@11,@12)), Union(@11,@13), true, launchCount);
436      }
437
438
439    | TOKEN_LAUNCH '<' postfix_expression '(' argument_expression_list ')' '>'
440       {
441          Error(Union(@2, @7), "\"launch\" expressions no longer take '<' '>' "
442                "around function call expression.");
443          $$ = NULL;
444       }
445    | TOKEN_LAUNCH '<' postfix_expression '(' ')' '>'
446       {
447          Error(Union(@2, @6), "\"launch\" expressions no longer take '<' '>' "
448                "around function call expression.");
449          $$ = NULL;
450       }
451    | TOKEN_LAUNCH '[' assignment_expression ']' '<' postfix_expression '(' argument_expression_list ')' '>'
452       {
453          Error(Union(@5, @10), "\"launch\" expressions no longer take '<' '>' "
454                "around function call expression.");
455          $$ = NULL;
456       }
457    | TOKEN_LAUNCH '[' assignment_expression ']' '<' postfix_expression '(' ')' '>'
458       {
459          Error(Union(@5, @9), "\"launch\" expressions no longer take '<' '>' "
460                "around function call expression.");
461          $$ = NULL;
462       }
463    ;
464
465postfix_expression
466    : primary_expression
467    | postfix_expression '[' expression ']'
468      { $$ = new IndexExpr($1, $3, Union(@1,@4)); }
469    | postfix_expression '[' error ']'
470      { $$ = NULL; }
471    | launch_expression
472    | postfix_expression '.' TOKEN_IDENTIFIER
473      { $$ = MemberExpr::create($1, yytext, Union(@1,@3), @3, false); }
474    | postfix_expression TOKEN_PTR_OP TOKEN_IDENTIFIER
475      { $$ = MemberExpr::create($1, yytext, Union(@1,@3), @3, true); }
476    | postfix_expression TOKEN_INC_OP
477      { $$ = new UnaryExpr(UnaryExpr::PostInc, $1, Union(@1,@2)); }
478    | postfix_expression TOKEN_DEC_OP
479      { $$ = new UnaryExpr(UnaryExpr::PostDec, $1, Union(@1,@2)); }
480    ;
481
482intrinsic_name
483    : TOKEN_INTRINSIC_CALL
484      {
485          $$ = yylval.stringVal;
486      }
487    ;
488
489intrincall_expression
490    : intrinsic_name '(' argument_expression_list ')'
491      {
492          std::string *name = $1;
493          name->erase(0, 1);
494          Symbol* sym = m->AddLLVMIntrinsicDecl(*name, $3, Union(@1,@4));
495          const char *fname = name->c_str();
496          const std::vector<Symbol *> funcs{sym};
497          FunctionSymbolExpr *fSym = NULL;
498          if (sym != NULL)
499              fSym = new FunctionSymbolExpr(fname, funcs, @1);
500          $$ = new FunctionCallExpr(fSym, $3, Union(@1,@4));
501
502      }
503    ;
504
505funcall_expression
506    : postfix_expression
507    | postfix_expression '(' ')'
508      { $$ = new FunctionCallExpr($1, new ExprList(Union(@1,@2)), Union(@1,@3)); }
509    | postfix_expression '(' argument_expression_list ')'
510      { $$ = new FunctionCallExpr($1, $3, Union(@1,@4)); }
511    | postfix_expression '(' error ')'
512      { $$ = NULL; }
513    ;
514
515argument_expression_list
516    : assignment_expression      { $$ = new ExprList($1, @1); }
517    | argument_expression_list ',' assignment_expression
518      {
519          ExprList *argList = llvm::dyn_cast<ExprList>($1);
520          if (argList == NULL) {
521              AssertPos(@1, m->errorCount > 0);
522              argList = new ExprList(@3);
523          }
524          argList->exprs.push_back($3);
525          argList->pos = Union(argList->pos, @3);
526          $$ = argList;
527      }
528    ;
529
530unary_expression
531    : funcall_expression
532    | intrincall_expression
533    | TOKEN_INC_OP unary_expression
534      { $$ = new UnaryExpr(UnaryExpr::PreInc, $2, Union(@1, @2)); }
535    | TOKEN_DEC_OP unary_expression
536      { $$ = new UnaryExpr(UnaryExpr::PreDec, $2, Union(@1, @2)); }
537    | '&' unary_expression
538      { $$ = new AddressOfExpr($2, Union(@1, @2)); }
539    | '*' unary_expression
540      { $$ = new PtrDerefExpr($2, Union(@1, @2)); }
541    | '+' cast_expression
542      { $$ = $2; }
543    | '-' cast_expression
544      { $$ = new UnaryExpr(UnaryExpr::Negate, $2, Union(@1, @2)); }
545    | '~' cast_expression
546      { $$ = new UnaryExpr(UnaryExpr::BitNot, $2, Union(@1, @2)); }
547    | '!' cast_expression
548      { $$ = new UnaryExpr(UnaryExpr::LogicalNot, $2, Union(@1, @2)); }
549    | TOKEN_SIZEOF unary_expression
550      { $$ = new SizeOfExpr($2, Union(@1, @2)); }
551    | TOKEN_SIZEOF '(' type_name ')'
552      { $$ = new SizeOfExpr($3, Union(@1, @4)); }
553    | TOKEN_ALLOCA '(' assignment_expression ')'
554      {
555          $$ = new AllocaExpr($3, Union(@1, @4));
556      }
557    ;
558
559cast_expression
560    : unary_expression
561    | '(' type_name ')' cast_expression
562      {
563          $$ = new TypeCastExpr($2, $4, Union(@1,@4));
564      }
565    ;
566
567multiplicative_expression
568    : cast_expression
569    | multiplicative_expression '*' cast_expression
570      { $$ = MakeBinaryExpr(BinaryExpr::Mul, $1, $3, Union(@1, @3)); }
571    | multiplicative_expression '/' cast_expression
572      { $$ = MakeBinaryExpr(BinaryExpr::Div, $1, $3, Union(@1, @3)); }
573    | multiplicative_expression '%' cast_expression
574      { $$ = MakeBinaryExpr(BinaryExpr::Mod, $1, $3, Union(@1, @3)); }
575    ;
576
577additive_expression
578    : multiplicative_expression
579    | additive_expression '+' multiplicative_expression
580      { $$ = MakeBinaryExpr(BinaryExpr::Add, $1, $3, Union(@1, @3)); }
581    | additive_expression '-' multiplicative_expression
582      { $$ = MakeBinaryExpr(BinaryExpr::Sub, $1, $3, Union(@1, @3)); }
583    ;
584
585shift_expression
586    : additive_expression
587    | shift_expression TOKEN_LEFT_OP additive_expression
588      { $$ = MakeBinaryExpr(BinaryExpr::Shl, $1, $3, Union(@1, @3)); }
589    | shift_expression TOKEN_RIGHT_OP additive_expression
590      { $$ = MakeBinaryExpr(BinaryExpr::Shr, $1, $3, Union(@1, @3)); }
591    ;
592
593relational_expression
594    : shift_expression
595    | relational_expression '<' shift_expression
596      { $$ = new BinaryExpr(BinaryExpr::Lt, $1, $3, Union(@1, @3)); }
597    | relational_expression '>' shift_expression
598      { $$ = new BinaryExpr(BinaryExpr::Gt, $1, $3, Union(@1, @3)); }
599    | relational_expression TOKEN_LE_OP shift_expression
600      { $$ = new BinaryExpr(BinaryExpr::Le, $1, $3, Union(@1, @3)); }
601    | relational_expression TOKEN_GE_OP shift_expression
602      { $$ = new BinaryExpr(BinaryExpr::Ge, $1, $3, Union(@1, @3)); }
603    ;
604
605equality_expression
606    : relational_expression
607    | equality_expression TOKEN_EQ_OP relational_expression
608      { $$ = new BinaryExpr(BinaryExpr::Equal, $1, $3, Union(@1,@3)); }
609    | equality_expression TOKEN_NE_OP relational_expression
610      { $$ = new BinaryExpr(BinaryExpr::NotEqual, $1, $3, Union(@1,@3)); }
611    ;
612
613and_expression
614    : equality_expression
615    | and_expression '&' equality_expression
616      { $$ = new BinaryExpr(BinaryExpr::BitAnd, $1, $3, Union(@1, @3)); }
617    ;
618
619exclusive_or_expression
620    : and_expression
621    | exclusive_or_expression '^' and_expression
622      { $$ = new BinaryExpr(BinaryExpr::BitXor, $1, $3, Union(@1, @3)); }
623    ;
624
625inclusive_or_expression
626    : exclusive_or_expression
627    | inclusive_or_expression '|' exclusive_or_expression
628      { $$ = new BinaryExpr(BinaryExpr::BitOr, $1, $3, Union(@1, @3)); }
629    ;
630
631logical_and_expression
632    : inclusive_or_expression
633    | logical_and_expression TOKEN_AND_OP inclusive_or_expression
634      { $$ = new BinaryExpr(BinaryExpr::LogicalAnd, $1, $3, Union(@1, @3)); }
635    ;
636
637logical_or_expression
638    : logical_and_expression
639    | logical_or_expression TOKEN_OR_OP logical_and_expression
640      { $$ = new BinaryExpr(BinaryExpr::LogicalOr, $1, $3, Union(@1, @3)); }
641    ;
642
643conditional_expression
644    : logical_or_expression
645    | logical_or_expression '?' expression ':' conditional_expression
646      { $$ = new SelectExpr($1, $3, $5, Union(@1,@5)); }
647    ;
648
649rate_qualified_new
650    : TOKEN_NEW { $$ = 0; }
651    | TOKEN_UNIFORM TOKEN_NEW { $$ = TYPEQUAL_UNIFORM; }
652    | TOKEN_VARYING TOKEN_NEW { $$ = TYPEQUAL_VARYING; }
653    ;
654
655rate_qualified_type_specifier
656    : type_specifier { $$ = $1; }
657    | TOKEN_UNIFORM type_specifier
658    {
659        if ($2 == NULL)
660            $$ = NULL;
661        else if ($2->IsVoidType()) {
662            Error(@1, "\"uniform\" qualifier is illegal with \"void\" type.");
663            $$ = NULL;
664        }
665        else
666            $$ = $2->GetAsUniformType();
667    }
668    | TOKEN_VARYING type_specifier
669    {
670        if ($2 == NULL)
671            $$ = NULL;
672        else if ($2->IsVoidType()) {
673            Error(@1, "\"varying\" qualifier is illegal with \"void\" type.");
674            $$ = NULL;
675        }
676        else
677            $$ = $2->GetAsVaryingType();
678    }
679    | soa_width_specifier type_specifier
680    {
681        if ($2 == NULL)
682            $$ = NULL;
683        else {
684            int soaWidth = (int)$1;
685            const StructType *st = CastType<StructType>($2);
686            if (st == NULL) {
687                Error(@1, "\"soa\" qualifier is illegal with non-struct type \"%s\".",
688                      $2->GetString().c_str());
689                $$ = NULL;
690            }
691            else if (soaWidth <= 0 || (soaWidth & (soaWidth - 1)) != 0) {
692                Error(@1, "soa<%d> width illegal. Value must be positive power "
693                      "of two.", soaWidth);
694                $$ = NULL;
695            }
696            else
697                $$ = st->GetAsSOAType(soaWidth);
698        }
699    }
700    ;
701
702new_expression
703    : conditional_expression
704    | rate_qualified_new rate_qualified_type_specifier
705    {
706        $$ = new NewExpr((int32_t)$1, $2, NULL, NULL, @1, Union(@1, @2));
707    }
708    | rate_qualified_new rate_qualified_type_specifier '(' initializer_list ')'
709    {
710        $$ = new NewExpr((int32_t)$1, $2, $4, NULL, @1, Union(@1, @2));
711    }
712    | rate_qualified_new rate_qualified_type_specifier '[' expression ']'
713    {
714        $$ = new NewExpr((int32_t)$1, $2, NULL, $4, @1, Union(@1, @4));
715    }
716    ;
717
718assignment_expression
719    : new_expression
720    | unary_expression '=' assignment_expression
721      { $$ = new AssignExpr(AssignExpr::Assign, $1, $3, Union(@1, @3)); }
722    | unary_expression TOKEN_MUL_ASSIGN assignment_expression
723      { $$ = new AssignExpr(AssignExpr::MulAssign, $1, $3, Union(@1, @3)); }
724    | unary_expression TOKEN_DIV_ASSIGN assignment_expression
725      { $$ = new AssignExpr(AssignExpr::DivAssign, $1, $3, Union(@1, @3)); }
726    | unary_expression TOKEN_MOD_ASSIGN assignment_expression
727      { $$ = new AssignExpr(AssignExpr::ModAssign, $1, $3, Union(@1, @3)); }
728    | unary_expression TOKEN_ADD_ASSIGN assignment_expression
729      { $$ = new AssignExpr(AssignExpr::AddAssign, $1, $3, Union(@1, @3)); }
730    | unary_expression TOKEN_SUB_ASSIGN assignment_expression
731      { $$ = new AssignExpr(AssignExpr::SubAssign, $1, $3, Union(@1, @3)); }
732    | unary_expression TOKEN_LEFT_ASSIGN assignment_expression
733      { $$ = new AssignExpr(AssignExpr::ShlAssign, $1, $3, Union(@1, @3)); }
734    | unary_expression TOKEN_RIGHT_ASSIGN assignment_expression
735      { $$ = new AssignExpr(AssignExpr::ShrAssign, $1, $3, Union(@1, @3)); }
736    | unary_expression TOKEN_AND_ASSIGN assignment_expression
737      { $$ = new AssignExpr(AssignExpr::AndAssign, $1, $3, Union(@1, @3)); }
738    | unary_expression TOKEN_XOR_ASSIGN assignment_expression
739      { $$ = new AssignExpr(AssignExpr::XorAssign, $1, $3, Union(@1, @3)); }
740    | unary_expression TOKEN_OR_ASSIGN assignment_expression
741      { $$ = new AssignExpr(AssignExpr::OrAssign, $1, $3, Union(@1, @3)); }
742    ;
743
744expression
745    : assignment_expression
746    | expression ',' assignment_expression
747      { $$ = new BinaryExpr(BinaryExpr::Comma, $1, $3, Union(@1, @3)); }
748    ;
749
750constant_expression
751    : conditional_expression
752    ;
753
754declaration_statement
755    : declaration
756    {
757        if ($1 == NULL) {
758            AssertPos(@1, m->errorCount > 0);
759            $$ = NULL;
760        }
761        else if ($1->declSpecs->storageClass == SC_TYPEDEF) {
762            for (unsigned int i = 0; i < $1->declarators.size(); ++i) {
763                if ($1->declarators[i] == NULL)
764                    AssertPos(@1, m->errorCount > 0);
765                else
766                    m->AddTypeDef($1->declarators[i]->name,
767                                  $1->declarators[i]->type,
768                                  $1->declarators[i]->pos);
769            }
770            $$ = NULL;
771        }
772        else {
773            $1->DeclareFunctions();
774            std::vector<VariableDeclaration> vars = $1->GetVariableDeclarations();
775            $$ = new DeclStmt(vars, @1);
776        }
777    }
778    ;
779
780declaration
781    : declaration_specifiers ';'
782      {
783          $$ = new Declaration($1);
784      }
785    | declaration_specifiers init_declarator_list ';'
786      {
787          $$ = new Declaration($1, $2);
788      }
789    ;
790
791soa_width_specifier
792    : TOKEN_SOA '<' int_constant '>'
793      { $$ = $3; }
794    ;
795
796declspec_item
797    : TOKEN_IDENTIFIER
798    {
799        std::pair<std::string, SourcePos> *p = new std::pair<std::string, SourcePos>;
800        p->first = *(yylval.stringVal);
801        p->second = @1;
802        $$ = p;
803    }
804    ;
805
806declspec_list
807    : declspec_item
808    {
809        $$ = new std::vector<std::pair<std::string, SourcePos> >;
810        $$->push_back(*$1);
811    }
812    | declspec_list ',' declspec_item
813    {
814        if ($1 != NULL)
815            $1->push_back(*$3);
816        $$ = $1;
817    }
818    ;
819
820declspec_specifier
821    : TOKEN_DECLSPEC '(' declspec_list ')'
822    {
823        $$ = $3;
824    }
825    ;
826
827declaration_specifiers
828    : storage_class_specifier
829      {
830          $$ = new DeclSpecs(NULL, $1);
831      }
832    | storage_class_specifier declaration_specifiers
833      {
834          DeclSpecs *ds = (DeclSpecs *)$2;
835          if (ds != NULL) {
836              if (ds->storageClass != SC_NONE)
837                  Error(@1, "Multiple storage class specifiers in a declaration are illegal. "
838                        "(Have provided both \"%s\" and \"%s\".)",
839                        lGetStorageClassString(ds->storageClass),
840                        lGetStorageClassString($1));
841              else
842                  ds->storageClass = $1;
843          }
844          $$ = ds;
845      }
846    | declspec_specifier
847      {
848          $$ = new DeclSpecs;
849          if ($1 != NULL)
850              $$->declSpecList = *$1;
851      }
852    | declspec_specifier declaration_specifiers
853      {
854          DeclSpecs *ds = (DeclSpecs *)$2;
855          std::vector<std::pair<std::string, SourcePos> > *declSpecList = $1;
856          if (ds != NULL && declSpecList != NULL) {
857              for (int i = 0; i < (int)declSpecList->size(); ++i)
858                  ds->declSpecList.push_back((*declSpecList)[i]);
859          }
860          $$ = ds;
861      }
862    | soa_width_specifier
863      {
864          DeclSpecs *ds = new DeclSpecs;
865          ds->soaWidth = (int32_t)$1;
866          $$ = ds;
867      }
868    | soa_width_specifier declaration_specifiers
869      {
870          DeclSpecs *ds = (DeclSpecs *)$2;
871          if (ds != NULL) {
872              if (ds->soaWidth != 0)
873                  Error(@1, "soa<> qualifier supplied multiple times in declaration.");
874              else
875                  ds->soaWidth = (int32_t)$1;
876          }
877          $$ = ds;
878      }
879    | type_specifier
880      {
881          $$ = new DeclSpecs($1);
882      }
883    | type_specifier '<' int_constant '>'
884    {
885          DeclSpecs *ds = new DeclSpecs($1);
886          ds->vectorSize = (int32_t)$3;
887          $$ = ds;
888    }
889    | type_specifier declaration_specifiers
890      {
891          DeclSpecs *ds = (DeclSpecs *)$2;
892          if (ds != NULL) {
893              if (ds->baseType != NULL) {
894                  if( ds->baseType->IsUnsignedType()) {
895                      Error(@1, "Redefining uint8/uint16/uint32/uint64 type "
896                      "which is part of ISPC language since version 1.13. "
897                      "Remove this typedef or use ISPC_UINT_IS_DEFINED to "
898                      "detect that these types are defined.");
899                  }
900                  else
901                      Error(@1, "Multiple types provided for declaration.");
902              }
903              ds->baseType = $1;
904          }
905          $$ = ds;
906      }
907    | type_qualifier
908      {
909          $$ = new DeclSpecs(NULL, SC_NONE, $1);
910      }
911    | type_qualifier declaration_specifiers
912      {
913          DeclSpecs *ds = (DeclSpecs *)$2;
914          if (ds != NULL)
915              ds->typeQualifiers |= $1;
916          $$ = ds;
917      }
918    ;
919
920init_declarator_list
921    : init_declarator
922      {
923          std::vector<Declarator *> *dl = new std::vector<Declarator *>;
924          if ($1 != NULL)
925              dl->push_back($1);
926          $$ = dl;
927      }
928    | init_declarator_list ',' init_declarator
929      {
930          std::vector<Declarator *> *dl = (std::vector<Declarator *> *)$1;
931          if (dl == NULL) {
932              AssertPos(@1, m->errorCount > 0);
933              dl = new std::vector<Declarator *>;
934          }
935          if ($3 != NULL)
936              dl->push_back($3);
937          $$ = dl;
938      }
939    ;
940
941init_declarator
942    : declarator
943    | declarator '=' initializer
944      {
945          if ($1 != NULL)
946              $1->initExpr = $3;
947          $$ = $1;
948      }
949    ;
950
951storage_class_specifier
952    : TOKEN_TYPEDEF { $$ = SC_TYPEDEF; }
953    | TOKEN_EXTERN { $$ = SC_EXTERN; }
954    | TOKEN_EXTERN TOKEN_STRING_C_LITERAL  { $$ = SC_EXTERN_C; }
955    | TOKEN_STATIC { $$ = SC_STATIC; }
956    ;
957
958type_specifier
959    : atomic_var_type_specifier { $$ = $1; }
960    | TOKEN_TYPE_NAME
961    {
962        const Type *t = m->symbolTable->LookupType(yytext);
963        $$ = t;
964    }
965    | struct_or_union_specifier { $$ = $1; }
966    | enum_specifier { $$ = $1; }
967    ;
968
969type_specifier_list
970    : type_specifier
971    {
972        if ($1 == NULL)
973            $$ = NULL;
974        else {
975            std::vector<std::pair<const Type *, SourcePos> > *vec =
976                new std::vector<std::pair<const Type *, SourcePos> >;
977            vec->push_back(std::make_pair($1, @1));
978            $$ = vec;
979        }
980    }
981    | type_specifier_list ',' type_specifier
982    {
983        $$ = $1;
984        if ($1 == NULL)
985            Assert(m->errorCount > 0);
986        else
987            $$->push_back(std::make_pair($3, @3));
988    }
989    ;
990
991atomic_var_type_specifier
992    : TOKEN_VOID { $$ = AtomicType::Void; }
993    | TOKEN_BOOL { $$ = AtomicType::UniformBool->GetAsUnboundVariabilityType(); }
994    | TOKEN_INT8 { $$ = AtomicType::UniformInt8->GetAsUnboundVariabilityType(); }
995    | TOKEN_UINT8 { $$ = AtomicType::UniformUInt8->GetAsUnboundVariabilityType(); }
996    | TOKEN_INT16 { $$ = AtomicType::UniformInt16->GetAsUnboundVariabilityType(); }
997    | TOKEN_UINT16 { $$ = AtomicType::UniformUInt16->GetAsUnboundVariabilityType(); }
998    | TOKEN_INT { $$ = AtomicType::UniformInt32->GetAsUnboundVariabilityType(); }
999    | TOKEN_UINT { $$ = AtomicType::UniformUInt32->GetAsUnboundVariabilityType(); }
1000    | TOKEN_FLOAT { $$ = AtomicType::UniformFloat->GetAsUnboundVariabilityType(); }
1001    | TOKEN_DOUBLE { $$ = AtomicType::UniformDouble->GetAsUnboundVariabilityType(); }
1002    | TOKEN_INT64 { $$ = AtomicType::UniformInt64->GetAsUnboundVariabilityType(); }
1003    | TOKEN_UINT64 { $$ = AtomicType::UniformUInt64->GetAsUnboundVariabilityType(); }
1004    ;
1005
1006short_vec_specifier
1007    : atomic_var_type_specifier '<' int_constant '>'
1008    {
1009        $$ = $1 ? new VectorType($1, (int32_t)$3) : NULL;
1010    }
1011    ;
1012
1013struct_or_union_name
1014    : TOKEN_IDENTIFIER { $$ = strdup(yytext); }
1015    | TOKEN_TYPE_NAME  { $$ = strdup(yytext); }
1016    ;
1017
1018struct_or_union_and_name
1019    : struct_or_union struct_or_union_name
1020      {
1021          const Type *st = m->symbolTable->LookupType($2);
1022          if (st == NULL) {
1023              st = new UndefinedStructType($2, Variability::Unbound, false, @2);
1024              m->symbolTable->AddType($2, st, @2);
1025              $$ = st;
1026          }
1027          else {
1028              if (CastType<StructType>(st) == NULL &&
1029                  CastType<UndefinedStructType>(st) == NULL) {
1030                  Error(@2, "Type \"%s\" is not a struct type! (%s)", $2,
1031                        st->GetString().c_str());
1032                  $$ = NULL;
1033              }
1034              else
1035                  $$ = st;
1036         }
1037      }
1038    ;
1039
1040struct_or_union_specifier
1041    : struct_or_union_and_name
1042    | struct_or_union_and_name '{' struct_declaration_list '}'
1043      {
1044          if ($3 != NULL) {
1045              llvm::SmallVector<const Type *, 8> elementTypes;
1046              llvm::SmallVector<std::string, 8> elementNames;
1047              llvm::SmallVector<SourcePos, 8> elementPositions;
1048              GetStructTypesNamesPositions(*$3, &elementTypes, &elementNames,
1049                                           &elementPositions);
1050              const std::string &name = CastType<StructType>($1) ?
1051                  CastType<StructType>($1)->GetStructName() :
1052                  CastType<UndefinedStructType>($1)->GetStructName();
1053              StructType *st = new StructType(name, elementTypes, elementNames,
1054                                              elementPositions, false,
1055                                              Variability::Unbound, false, @1);
1056              m->symbolTable->AddType(name.c_str(), st, @1);
1057              $$ = st;
1058          }
1059          else
1060              $$ = NULL;
1061      }
1062    | struct_or_union '{' struct_declaration_list '}'
1063      {
1064          if ($3 != NULL) {
1065              llvm::SmallVector<const Type *, 8> elementTypes;
1066              llvm::SmallVector<std::string, 8> elementNames;
1067              llvm::SmallVector<SourcePos, 8> elementPositions;
1068              GetStructTypesNamesPositions(*$3, &elementTypes, &elementNames,
1069                                           &elementPositions);
1070              $$ = new StructType("", elementTypes, elementNames, elementPositions,
1071                                  false, Variability::Unbound, true, @1);
1072          }
1073          else
1074              $$ = NULL;
1075      }
1076    | struct_or_union '{' '}'
1077      {
1078          llvm::SmallVector<const Type *, 8> elementTypes;
1079          llvm::SmallVector<std::string, 8> elementNames;
1080          llvm::SmallVector<SourcePos, 8> elementPositions;
1081          $$ = new StructType("", elementTypes, elementNames, elementPositions,
1082                              false, Variability::Unbound, true, @1);
1083      }
1084    | struct_or_union_and_name '{' '}'
1085      {
1086          llvm::SmallVector<const Type *, 8> elementTypes;
1087          llvm::SmallVector<std::string, 8> elementNames;
1088          llvm::SmallVector<SourcePos, 8> elementPositions;
1089          const std::string &name = CastType<StructType>($1) ?
1090              CastType<StructType>($1)->GetStructName() :
1091              CastType<UndefinedStructType>($1)->GetStructName();
1092          StructType *st = new StructType(name, elementTypes,
1093                                          elementNames, elementPositions,
1094                                          false, Variability::Unbound, false, @1);
1095          m->symbolTable->AddType(name.c_str(), st, @2);
1096          $$ = st;
1097      }
1098    ;
1099
1100struct_or_union
1101    : TOKEN_STRUCT
1102    ;
1103
1104struct_declaration_list
1105    : struct_declaration
1106      {
1107          std::vector<StructDeclaration *> *sdl = new std::vector<StructDeclaration *>;
1108          if ($1 != NULL)
1109              sdl->push_back($1);
1110          $$ = sdl;
1111      }
1112    | struct_declaration_list struct_declaration
1113      {
1114          std::vector<StructDeclaration *> *sdl = (std::vector<StructDeclaration *> *)$1;
1115          if (sdl == NULL) {
1116              AssertPos(@1, m->errorCount > 0);
1117              sdl = new std::vector<StructDeclaration *>;
1118          }
1119          if ($2 != NULL)
1120              sdl->push_back($2);
1121          $$ = sdl;
1122      }
1123    ;
1124
1125struct_declaration
1126    : specifier_qualifier_list struct_declarator_list ';'
1127      { $$ = ($1 != NULL && $2 != NULL) ? new StructDeclaration($1, $2) : NULL; }
1128    ;
1129
1130specifier_qualifier_list
1131    : type_specifier specifier_qualifier_list
1132    | type_specifier
1133    | short_vec_specifier
1134    | type_qualifier specifier_qualifier_list
1135    {
1136        if ($2 != NULL) {
1137            if ($1 == TYPEQUAL_UNIFORM) {
1138                if ($2->IsVoidType()) {
1139                    Error(@1, "\"uniform\" qualifier is illegal with \"void\" type.");
1140                    $$ = NULL;
1141                }
1142                else
1143                    $$ = $2->GetAsUniformType();
1144            }
1145            else if ($1 == TYPEQUAL_VARYING) {
1146                if ($2->IsVoidType()) {
1147                    Error(@1, "\"varying\" qualifier is illegal with \"void\" type.");
1148                    $$ = NULL;
1149                }
1150                else
1151                    $$ = $2->GetAsVaryingType();
1152            }
1153            else if ($1 == TYPEQUAL_CONST)
1154                $$ = $2->GetAsConstType();
1155            else if ($1 == TYPEQUAL_SIGNED) {
1156                if ($2->IsIntType() == false) {
1157                    Error(@1, "Can't apply \"signed\" qualifier to \"%s\" type.",
1158                          $2->ResolveUnboundVariability(Variability::Varying)->GetString().c_str());
1159                    $$ = $2;
1160                }
1161            }
1162            else if ($1 == TYPEQUAL_UNSIGNED) {
1163                const Type *t = $2->GetAsUnsignedType();
1164                if (t)
1165                    $$ = t;
1166                else {
1167                    Error(@1, "Can't apply \"unsigned\" qualifier to \"%s\" type. Ignoring.",
1168                          $2->ResolveUnboundVariability(Variability::Varying)->GetString().c_str());
1169                    $$ = $2;
1170                }
1171            }
1172            else if ($1 == TYPEQUAL_INLINE) {
1173                Error(@1, "\"inline\" qualifier is illegal outside of "
1174                      "function declarations.");
1175                $$ = $2;
1176            }
1177            else if ($1 == TYPEQUAL_NOINLINE) {
1178                Error(@1, "\"noinline\" qualifier is illegal outside of "
1179                      "function declarations.");
1180                $$ = $2;
1181            }
1182            else if ($1 == TYPEQUAL_VECTORCALL) {
1183                Error(@1, "\"__vectorcall\" qualifier is illegal outside of "
1184                      "function declarations.");
1185                $$ = $2;
1186            }
1187            else if ($1 == TYPEQUAL_TASK) {
1188                Error(@1, "\"task\" qualifier is illegal outside of "
1189                      "function declarations.");
1190                $$ = $2;
1191            }
1192            else if ($1 == TYPEQUAL_UNMASKED) {
1193                Error(@1, "\"unmasked\" qualifier is illegal outside of "
1194                      "function declarations.");
1195                $$ = $2;
1196            }
1197            else if ($1 == TYPEQUAL_EXPORT) {
1198                Error(@1, "\"export\" qualifier is illegal outside of "
1199                      "function declarations.");
1200                $$ = $2;
1201            }
1202            else
1203                FATAL("Unhandled type qualifier in parser.");
1204        }
1205        else {
1206            if (m->errorCount == 0)
1207                Error(@1, "Lost type qualifier in parser.");
1208            $$ = NULL;
1209        }
1210    }
1211    ;
1212
1213
1214struct_declarator_list
1215    : struct_declarator
1216      {
1217          std::vector<Declarator *> *sdl = new std::vector<Declarator *>;
1218          if ($1 != NULL)
1219              sdl->push_back($1);
1220          $$ = sdl;
1221      }
1222    | struct_declarator_list ',' struct_declarator
1223      {
1224          std::vector<Declarator *> *sdl = (std::vector<Declarator *> *)$1;
1225          if (sdl == NULL) {
1226              AssertPos(@1, m->errorCount > 0);
1227              sdl = new std::vector<Declarator *>;
1228          }
1229          if ($3 != NULL)
1230              sdl->push_back($3);
1231          $$ = sdl;
1232      }
1233    ;
1234
1235struct_declarator
1236    : declarator { $$ = $1; }
1237/* bitfields
1238    | ':' constant_expression
1239    | declarator ':' constant_expression
1240*/
1241    ;
1242
1243enum_identifier
1244    : TOKEN_IDENTIFIER { $$ = strdup(yytext); }
1245
1246enum_specifier
1247    : TOKEN_ENUM '{' enumerator_list '}'
1248      {
1249          $$ = lCreateEnumType(NULL, $3, @1);
1250      }
1251    | TOKEN_ENUM enum_identifier '{' enumerator_list '}'
1252      {
1253          $$ = lCreateEnumType($2, $4, @2);
1254      }
1255    | TOKEN_ENUM '{' enumerator_list ',' '}'
1256      {
1257          $$ = lCreateEnumType(NULL, $3, @1);
1258      }
1259    | TOKEN_ENUM enum_identifier '{' enumerator_list ',' '}'
1260      {
1261          $$ = lCreateEnumType($2, $4, @2);
1262      }
1263    | TOKEN_ENUM enum_identifier
1264      {
1265          const Type *type = m->symbolTable->LookupType($2);
1266          if (type == NULL) {
1267              std::vector<std::string> alternates = m->symbolTable->ClosestEnumTypeMatch($2);
1268              std::string alts = lGetAlternates(alternates);
1269              Error(@2, "Enum type \"%s\" unknown.%s", $2, alts.c_str());
1270              $$ = NULL;
1271          }
1272          else {
1273              const EnumType *enumType = CastType<EnumType>(type);
1274              if (enumType == NULL) {
1275                  Error(@2, "Type \"%s\" is not an enum type (%s).", $2,
1276                        type->GetString().c_str());
1277                  $$ = NULL;
1278              }
1279              else
1280                  $$ = enumType;
1281          }
1282      }
1283    ;
1284
1285enumerator_list
1286    : enumerator
1287      {
1288          if ($1 == NULL)
1289              $$ = NULL;
1290          else {
1291              std::vector<Symbol *> *el = new std::vector<Symbol *>;
1292              el->push_back($1);
1293              $$ = el;
1294          }
1295      }
1296    | enumerator_list ',' enumerator
1297      {
1298          std::vector<Symbol *> *symList = $1;
1299          if (symList == NULL) {
1300              AssertPos(@1, m->errorCount > 0);
1301              symList = new std::vector<Symbol *>;
1302          }
1303          if ($3 != NULL)
1304              symList->push_back($3);
1305          $$ = symList;
1306      }
1307    ;
1308
1309enumerator
1310    : enum_identifier
1311      {
1312          $$ = new Symbol($1, @1);
1313      }
1314    | enum_identifier '=' constant_expression
1315      {
1316          int value;
1317          if ($1 != NULL && $3 != NULL &&
1318              lGetConstantInt($3, &value, @3, "Enumerator value")) {
1319              Symbol *sym = new Symbol($1, @1);
1320              sym->constValue = new ConstExpr(AtomicType::UniformUInt32->GetAsConstType(),
1321                                              (uint32_t)value, @3);
1322              $$ = sym;
1323          }
1324          else
1325              $$ = NULL;
1326      }
1327    ;
1328
1329type_qualifier
1330    : TOKEN_CONST      { $$ = TYPEQUAL_CONST; }
1331    | TOKEN_UNIFORM    { $$ = TYPEQUAL_UNIFORM; }
1332    | TOKEN_VARYING    { $$ = TYPEQUAL_VARYING; }
1333    | TOKEN_TASK       { $$ = TYPEQUAL_TASK; }
1334    | TOKEN_UNMASKED   { $$ = TYPEQUAL_UNMASKED; }
1335    | TOKEN_EXPORT     { $$ = TYPEQUAL_EXPORT; }
1336    | TOKEN_INLINE     { $$ = TYPEQUAL_INLINE; }
1337    | TOKEN_NOINLINE   { $$ = TYPEQUAL_NOINLINE; }
1338    | TOKEN_VECTORCALL { $$ = TYPEQUAL_VECTORCALL; }
1339    | TOKEN_SIGNED     { $$ = TYPEQUAL_SIGNED; }
1340    | TOKEN_UNSIGNED   { $$ = TYPEQUAL_UNSIGNED; }
1341    ;
1342
1343type_qualifier_list
1344    : type_qualifier
1345    {
1346        $$ = $1;
1347    }
1348    | type_qualifier_list type_qualifier
1349    {
1350        $$ = $1 | $2;
1351    }
1352    ;
1353
1354declarator
1355    : pointer direct_declarator
1356    {
1357        if ($1 != NULL) {
1358            Declarator *tail = $1;
1359            while (tail->child != NULL)
1360               tail = tail->child;
1361            tail->child = $2;
1362            $$ = $1;
1363        }
1364        else
1365            $$ = NULL;
1366    }
1367    | reference direct_declarator
1368    {
1369        if ($1 != NULL) {
1370            Declarator *tail = $1;
1371            while (tail->child != NULL)
1372               tail = tail->child;
1373            tail->child = $2;
1374            $$ = $1;
1375        }
1376        else
1377            $$ = NULL;
1378    }
1379    | direct_declarator
1380    ;
1381
1382int_constant
1383    : TOKEN_INT8_CONSTANT { $$ = yylval.intVal; }
1384    | TOKEN_INT16_CONSTANT { $$ = yylval.intVal; }
1385    | TOKEN_INT32_CONSTANT { $$ = yylval.intVal; }
1386    | TOKEN_INT64_CONSTANT { $$ = yylval.intVal; }
1387    ;
1388
1389direct_declarator
1390    : TOKEN_IDENTIFIER
1391      {
1392          Declarator *d = new Declarator(DK_BASE, @1);
1393          d->name = yytext;
1394          $$ = d;
1395      }
1396    | '(' declarator ')'
1397    {
1398        $$ = $2;
1399    }
1400    | direct_declarator '[' constant_expression ']'
1401    {
1402        int size;
1403        if ($1 != NULL && lGetConstantInt($3, &size, @3, "Array dimension")) {
1404            if (size < 0) {
1405                Error(@3, "Array dimension must be non-negative.");
1406                $$ = NULL;
1407            }
1408            else {
1409                Declarator *d = new Declarator(DK_ARRAY, Union(@1, @4));
1410                d->arraySize = size;
1411                d->child = $1;
1412                $$ = d;
1413            }
1414        }
1415        else
1416            $$ = NULL;
1417    }
1418    | direct_declarator '[' ']'
1419    {
1420        if ($1 != NULL) {
1421            Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
1422            d->arraySize = 0; // unsize
1423            d->child = $1;
1424            $$ = d;
1425        }
1426        else
1427            $$ = NULL;
1428    }
1429    | direct_declarator '[' error ']'
1430    {
1431         $$ = NULL;
1432    }
1433    | direct_declarator '(' parameter_type_list ')'
1434      {
1435          if ($1 != NULL) {
1436              Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @4));
1437              d->child = $1;
1438              if ($3 != NULL)
1439                  d->functionParams = *$3;
1440              $$ = d;
1441          }
1442          else
1443              $$ = NULL;
1444      }
1445    | direct_declarator '(' ')'
1446      {
1447          if ($1 != NULL) {
1448              Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
1449              d->child = $1;
1450              $$ = d;
1451          }
1452          else
1453              $$ = NULL;
1454      }
1455    | direct_declarator '(' error ')'
1456    {
1457        $$ = NULL;
1458    }
1459    ;
1460
1461
1462pointer
1463    : '*'
1464    {
1465        $$ = new Declarator(DK_POINTER, @1);
1466    }
1467    | '*' type_qualifier_list
1468      {
1469          Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
1470          d->typeQualifiers = $2;
1471          $$ = d;
1472      }
1473    | '*' pointer
1474      {
1475          Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
1476          d->child = $2;
1477          $$ = d;
1478      }
1479    | '*' type_qualifier_list pointer
1480      {
1481          Declarator *d = new Declarator(DK_POINTER, Union(@1, @3));
1482          d->typeQualifiers = $2;
1483          d->child = $3;
1484          $$ = d;
1485      }
1486    ;
1487
1488
1489reference
1490    : '&'
1491    {
1492        $$ = new Declarator(DK_REFERENCE, @1);
1493    }
1494    ;
1495
1496
1497parameter_type_list
1498    : parameter_list { $$ = $1; }
1499    ;
1500
1501parameter_list
1502    : parameter_declaration
1503    {
1504        std::vector<Declaration *> *dl = new std::vector<Declaration *>;
1505        if ($1 != NULL)
1506            dl->push_back($1);
1507        $$ = dl;
1508    }
1509    | parameter_list ',' parameter_declaration
1510    {
1511        std::vector<Declaration *> *dl = (std::vector<Declaration *> *)$1;
1512        if (dl == NULL)
1513            dl = new std::vector<Declaration *>;
1514        if ($3 != NULL)
1515            dl->push_back($3);
1516        $$ = dl;
1517    }
1518    | error ','
1519    {
1520        lSuggestParamListAlternates();
1521        $$ = NULL;
1522    }
1523    ;
1524
1525parameter_declaration
1526    : declaration_specifiers declarator
1527    {
1528        $$ = new Declaration($1, $2);
1529    }
1530    | declaration_specifiers declarator '=' initializer
1531    {
1532        if ($1 != NULL && $2 != NULL) {
1533            $2->initExpr = $4;
1534            $$ = new Declaration($1, $2);
1535        }
1536        else
1537            $$ = NULL;
1538    }
1539    | declaration_specifiers abstract_declarator
1540    {
1541        if ($1 != NULL && $2 != NULL)
1542            $$ = new Declaration($1, $2);
1543        else
1544            $$ = NULL;
1545    }
1546    | declaration_specifiers
1547    {
1548        if ($1 == NULL)
1549            $$ = NULL;
1550        else
1551            $$ = new Declaration($1);
1552    }
1553    ;
1554
1555/* K&R?
1556identifier_list
1557    : IDENTIFIER
1558    | identifier_list ',' IDENTIFIER
1559    ;
1560*/
1561
1562type_name
1563    : specifier_qualifier_list
1564    | specifier_qualifier_list abstract_declarator
1565    {
1566        if ($1 == NULL || $2 == NULL)
1567            $$ = NULL;
1568        else {
1569            $2->InitFromType($1, NULL);
1570            $$ = $2->type;
1571        }
1572    }
1573    ;
1574
1575abstract_declarator
1576    : pointer
1577      {
1578          $$ = $1;
1579      }
1580    | direct_abstract_declarator
1581    | pointer direct_abstract_declarator
1582      {
1583          if ($2 == NULL)
1584              $$ = NULL;
1585          else {
1586              Declarator *d = new Declarator(DK_POINTER, Union(@1, @2));
1587              d->child = $2;
1588              $$ = d;
1589          }
1590      }
1591    | reference
1592      {
1593          $$ = new Declarator(DK_REFERENCE, @1);
1594      }
1595    | reference direct_abstract_declarator
1596      {
1597          if ($2 == NULL)
1598              $$ = NULL;
1599          else {
1600              Declarator *d = new Declarator(DK_REFERENCE, Union(@1, @2));
1601              d->child = $2;
1602              $$ = d;
1603          }
1604      }
1605    ;
1606
1607direct_abstract_declarator
1608    : '(' abstract_declarator ')'
1609      { $$ = $2; }
1610    | '[' ']'
1611      {
1612          Declarator *d = new Declarator(DK_ARRAY, Union(@1, @2));
1613          d->arraySize = 0;
1614          $$ = d;
1615      }
1616    | '[' constant_expression ']'
1617      {
1618        int size;
1619        if ($2 != NULL && lGetConstantInt($2, &size, @2, "Array dimension")) {
1620            if (size < 0) {
1621                Error(@2, "Array dimension must be non-negative.");
1622                $$ = NULL;
1623            }
1624            else {
1625                Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
1626                d->arraySize = size;
1627                $$ = d;
1628            }
1629        }
1630        else
1631            $$ = NULL;
1632      }
1633    | direct_abstract_declarator '[' ']'
1634      {
1635          if ($1 == NULL)
1636              $$ = NULL;
1637          else {
1638              Declarator *d = new Declarator(DK_ARRAY, Union(@1, @3));
1639              d->arraySize = 0;
1640              d->child = $1;
1641              $$ = d;
1642          }
1643      }
1644    | direct_abstract_declarator '[' constant_expression ']'
1645      {
1646          int size;
1647          if ($1 != NULL && $3 != NULL && lGetConstantInt($3, &size, @3, "Array dimension")) {
1648              if (size < 0) {
1649                  Error(@3, "Array dimension must be non-negative.");
1650                  $$ = NULL;
1651              }
1652              else {
1653                  Declarator *d = new Declarator(DK_ARRAY, Union(@1, @4));
1654                  d->arraySize = size;
1655                  d->child = $1;
1656                  $$ = d;
1657              }
1658          }
1659          else
1660              $$ = NULL;
1661      }
1662    | '(' ')'
1663      { $$ = new Declarator(DK_FUNCTION, Union(@1, @2)); }
1664    | '(' parameter_type_list ')'
1665      {
1666          Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
1667          if ($2 != NULL) d->functionParams = *$2;
1668          $$ = d;
1669      }
1670    | direct_abstract_declarator '(' ')'
1671      {
1672          if ($1 == NULL)
1673              $$ = NULL;
1674          else {
1675              Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @3));
1676              d->child = $1;
1677              $$ = d;
1678          }
1679      }
1680    | direct_abstract_declarator '(' parameter_type_list ')'
1681      {
1682          if ($1 == NULL)
1683              $$ = NULL;
1684          else {
1685              Declarator *d = new Declarator(DK_FUNCTION, Union(@1, @4));
1686              d->child = $1;
1687              if ($3 != NULL) d->functionParams = *$3;
1688              $$ = d;
1689          }
1690      }
1691    ;
1692
1693initializer
1694    : assignment_expression
1695    | '{' initializer_list '}' { $$ = $2; }
1696    | '{' initializer_list ',' '}' { $$ = $2; }
1697    ;
1698
1699initializer_list
1700    : initializer
1701      { $$ = new ExprList($1, @1); }
1702    | initializer_list ',' initializer
1703      {
1704          ExprList *exprList = $1;
1705          if (exprList == NULL) {
1706              AssertPos(@1, m->errorCount > 0);
1707              exprList = new ExprList(@3);
1708          }
1709          exprList->exprs.push_back($3);
1710          exprList->pos = Union(exprList->pos, @3);
1711          $$ = exprList;
1712      }
1713    ;
1714
1715pragma
1716    : TOKEN_PRAGMA
1717    {
1718        $$ = (yylval.pragmaAttributes);
1719    }
1720    ;
1721
1722attributed_statement
1723    : pragma attributed_statement
1724    {
1725        if (($1->aType == PragmaAttributes::AttributeType::pragmaloop) && ($2 != NULL)) {
1726            std::pair<Globals::pragmaUnrollType, int> unrollVal = std::pair<Globals::pragmaUnrollType, int>($1->unrollType, $1->count);
1727            $2->SetLoopAttribute(unrollVal);
1728        }
1729        $$ = $2;
1730    }
1731    | statement
1732    ;
1733
1734statement
1735    : labeled_statement
1736    | compound_statement
1737    | expression_statement
1738    | selection_statement
1739    | iteration_statement
1740    | jump_statement
1741    | declaration_statement
1742    | print_statement
1743    | assert_statement
1744    | sync_statement
1745    | delete_statement
1746    | unmasked_statement
1747    | error ';'
1748    {
1749        lSuggestBuiltinAlternates();
1750        $$ = NULL;
1751    }
1752    ;
1753
1754labeled_statement
1755    : goto_identifier ':' attributed_statement
1756    {
1757        $$ = new LabeledStmt($1, $3, @1);
1758    }
1759    | TOKEN_CASE constant_expression ':' attributed_statement
1760      {
1761          int value;
1762          if ($2 != NULL &&
1763              lGetConstantInt($2, &value, @2, "Case statement value")) {
1764              $$ = new CaseStmt(value, $4, Union(@1, @2));
1765          }
1766          else
1767              $$ = NULL;
1768      }
1769    | TOKEN_DEFAULT ':' attributed_statement
1770      { $$ = new DefaultStmt($3, @1); }
1771    ;
1772
1773start_scope
1774    : '{' { m->symbolTable->PushScope(); }
1775    ;
1776
1777end_scope
1778    : '}' { m->symbolTable->PopScope(); }
1779    ;
1780
1781compound_statement
1782    : '{' '}' { $$ = NULL; }
1783    | start_scope statement_list end_scope { $$ = $2; }
1784    ;
1785
1786statement_list
1787    : attributed_statement
1788      {
1789          StmtList *sl = new StmtList(@1);
1790          sl->Add($1);
1791          $$ = sl;
1792      }
1793    | statement_list attributed_statement
1794      {
1795          StmtList *sl = (StmtList *)$1;
1796          if (sl == NULL) {
1797              AssertPos(@1, m->errorCount > 0);
1798              sl = new StmtList(@2);
1799          }
1800          sl->Add($2);
1801          $$ = sl;
1802      }
1803    ;
1804
1805expression_statement
1806    : ';' { $$ = NULL; }
1807    | expression ';' { $$ = $1 ? new ExprStmt($1, @1) : NULL; }
1808    ;
1809
1810selection_statement
1811    : TOKEN_IF '(' expression ')' attributed_statement
1812      { $$ = new IfStmt($3, $5, NULL, false, @1); }
1813    | TOKEN_IF '(' expression ')' attributed_statement TOKEN_ELSE attributed_statement
1814      { $$ = new IfStmt($3, $5, $7, false, @1); }
1815    | TOKEN_CIF '(' expression ')' attributed_statement
1816      { $$ = new IfStmt($3, $5, NULL, true, @1); }
1817    | TOKEN_CIF '(' expression ')' attributed_statement TOKEN_ELSE attributed_statement
1818      { $$ = new IfStmt($3, $5, $7, true, @1); }
1819    | TOKEN_SWITCH '(' expression ')' attributed_statement
1820      { $$ = new SwitchStmt($3, $5, @1); }
1821    ;
1822
1823for_test
1824    : ';'
1825      { $$ = NULL; }
1826    | expression ';'
1827      { $$ = $1; }
1828    ;
1829
1830for_init_statement
1831    : expression_statement
1832    | declaration_statement
1833    ;
1834
1835for_scope
1836    : TOKEN_FOR { m->symbolTable->PushScope(); }
1837    ;
1838
1839cfor_scope
1840    : TOKEN_CFOR { m->symbolTable->PushScope(); }
1841    ;
1842
1843foreach_scope
1844    : TOKEN_FOREACH { m->symbolTable->PushScope(); }
1845    ;
1846
1847foreach_tiled_scope
1848    : TOKEN_FOREACH_TILED { m->symbolTable->PushScope(); }
1849    ;
1850
1851foreach_identifier
1852    : TOKEN_IDENTIFIER
1853    {
1854        $$ = new Symbol(yytext, @1, AtomicType::VaryingInt32->GetAsConstType());
1855    }
1856    ;
1857
1858foreach_active_scope
1859    : TOKEN_FOREACH_ACTIVE { m->symbolTable->PushScope(); }
1860    ;
1861
1862foreach_active_identifier
1863    : TOKEN_IDENTIFIER
1864    {
1865        $$ = new Symbol(yytext, @1, AtomicType::UniformInt64->GetAsConstType());
1866    }
1867    ;
1868
1869integer_dotdotdot
1870    : TOKEN_INT32DOTDOTDOT_CONSTANT {
1871        $$ = new ConstExpr(AtomicType::UniformInt32->GetAsConstType(),
1872                           (int32_t)yylval.intVal, @1);
1873    }
1874    | TOKEN_UINT32DOTDOTDOT_CONSTANT {
1875        $$ = new ConstExpr(AtomicType::UniformUInt32->GetAsConstType(),
1876                           (uint32_t)yylval.intVal, @1);
1877    }
1878    | TOKEN_INT64DOTDOTDOT_CONSTANT {
1879        $$ = new ConstExpr(AtomicType::UniformInt64->GetAsConstType(),
1880                           (int64_t)yylval.intVal, @1);
1881    }
1882    | TOKEN_UINT64DOTDOTDOT_CONSTANT {
1883        $$ = new ConstExpr(AtomicType::UniformUInt64->GetAsConstType(),
1884                           (uint64_t)yylval.intVal, @1);
1885    }
1886    ;
1887
1888foreach_dimension_specifier
1889    : foreach_identifier '=' assignment_expression TOKEN_DOTDOTDOT assignment_expression
1890    {
1891        $$ = new ForeachDimension($1, $3, $5);
1892    }
1893    | foreach_identifier '=' integer_dotdotdot assignment_expression
1894    {
1895        $$ = new ForeachDimension($1, $3, $4);
1896    }
1897    ;
1898
1899foreach_dimension_list
1900    : foreach_dimension_specifier
1901    {
1902        $$ = new std::vector<ForeachDimension *>;
1903        $$->push_back($1);
1904    }
1905    | foreach_dimension_list ',' foreach_dimension_specifier
1906    {
1907        std::vector<ForeachDimension *> *dv = $1;
1908        if (dv == NULL) {
1909            AssertPos(@1, m->errorCount > 0);
1910            dv = new std::vector<ForeachDimension *>;
1911        }
1912        if ($3 != NULL)
1913            dv->push_back($3);
1914        $$ = dv;
1915    }
1916    ;
1917
1918foreach_unique_scope
1919    : TOKEN_FOREACH_UNIQUE { m->symbolTable->PushScope(); }
1920    ;
1921
1922foreach_unique_identifier
1923    : TOKEN_IDENTIFIER { $$ = yylval.stringVal->c_str(); }
1924    ;
1925
1926iteration_statement
1927    : TOKEN_WHILE '(' expression ')' attributed_statement
1928      { $$ = new ForStmt(NULL, $3, NULL, $5, false, @1); }
1929    | TOKEN_CWHILE '(' expression ')' attributed_statement
1930      { $$ = new ForStmt(NULL, $3, NULL, $5, true, @1); }
1931    | TOKEN_DO attributed_statement TOKEN_WHILE '(' expression ')' ';'
1932      { $$ = new DoStmt($5, $2, false, @1); }
1933    | TOKEN_CDO attributed_statement TOKEN_WHILE '(' expression ')' ';'
1934      { $$ = new DoStmt($5, $2, true, @1); }
1935    | for_scope '(' for_init_statement for_test ')' attributed_statement
1936      { $$ = new ForStmt($3, $4, NULL, $6, false, @1);
1937        m->symbolTable->PopScope();
1938      }
1939    | for_scope '(' for_init_statement for_test expression ')' attributed_statement
1940      { $$ = new ForStmt($3, $4, new ExprStmt($5, @5), $7, false, @1);
1941        m->symbolTable->PopScope();
1942      }
1943    | cfor_scope '(' for_init_statement for_test ')' attributed_statement
1944      { $$ = new ForStmt($3, $4, NULL, $6, true, @1);
1945        m->symbolTable->PopScope();
1946      }
1947    | cfor_scope '(' for_init_statement for_test expression ')' attributed_statement
1948      { $$ = new ForStmt($3, $4, new ExprStmt($5, @5), $7, true, @1);
1949        m->symbolTable->PopScope();
1950      }
1951    | foreach_scope '(' foreach_dimension_list ')'
1952     {
1953         std::vector<ForeachDimension *> *dims = $3;
1954         if (dims == NULL) {
1955             AssertPos(@3, m->errorCount > 0);
1956             dims = new std::vector<ForeachDimension *>;
1957         }
1958         for (unsigned int i = 0; i < dims->size(); ++i)
1959             m->symbolTable->AddVariable((*dims)[i]->sym);
1960     }
1961     attributed_statement
1962     {
1963         std::vector<ForeachDimension *> *dims = $3;
1964         if (dims == NULL) {
1965             AssertPos(@3, m->errorCount > 0);
1966             dims = new std::vector<ForeachDimension *>;
1967         }
1968
1969         std::vector<Symbol *> syms;
1970         std::vector<Expr *> begins, ends;
1971         for (unsigned int i = 0; i < dims->size(); ++i) {
1972             syms.push_back((*dims)[i]->sym);
1973             begins.push_back((*dims)[i]->beginExpr);
1974             ends.push_back((*dims)[i]->endExpr);
1975         }
1976         $$ = new ForeachStmt(syms, begins, ends, $6, false, @1);
1977         m->symbolTable->PopScope();
1978     }
1979    | foreach_tiled_scope '(' foreach_dimension_list ')'
1980     {
1981         std::vector<ForeachDimension *> *dims = $3;
1982         if (dims == NULL) {
1983             AssertPos(@3, m->errorCount > 0);
1984             dims = new std::vector<ForeachDimension *>;
1985         }
1986
1987         for (unsigned int i = 0; i < dims->size(); ++i)
1988             m->symbolTable->AddVariable((*dims)[i]->sym);
1989     }
1990     attributed_statement
1991     {
1992         std::vector<ForeachDimension *> *dims = $3;
1993         if (dims == NULL) {
1994             AssertPos(@1, m->errorCount > 0);
1995             dims = new std::vector<ForeachDimension *>;
1996         }
1997
1998         std::vector<Symbol *> syms;
1999         std::vector<Expr *> begins, ends;
2000         for (unsigned int i = 0; i < dims->size(); ++i) {
2001             syms.push_back((*dims)[i]->sym);
2002             begins.push_back((*dims)[i]->beginExpr);
2003             ends.push_back((*dims)[i]->endExpr);
2004         }
2005         $$ = new ForeachStmt(syms, begins, ends, $6, true, @1);
2006         m->symbolTable->PopScope();
2007     }
2008    | foreach_active_scope '(' foreach_active_identifier ')'
2009     {
2010         if ($3 != NULL)
2011             m->symbolTable->AddVariable($3);
2012     }
2013     attributed_statement
2014     {
2015         $$ = new ForeachActiveStmt($3, $6, Union(@1, @4));
2016         m->symbolTable->PopScope();
2017     }
2018    | foreach_unique_scope '(' foreach_unique_identifier TOKEN_IN
2019         expression ')'
2020     {
2021         Expr *expr = $5;
2022         const Type *type;
2023         if (expr != NULL &&
2024             (expr = TypeCheck(expr)) != NULL &&
2025             (type = expr->GetType()) != NULL) {
2026             const Type *iterType = type->GetAsUniformType()->GetAsConstType();
2027             Symbol *sym = new Symbol($3, @3, iterType);
2028             m->symbolTable->AddVariable(sym);
2029         }
2030     }
2031     attributed_statement
2032     {
2033         $$ = new ForeachUniqueStmt($3, $5, $8, @1);
2034         m->symbolTable->PopScope();
2035     }
2036    ;
2037
2038goto_identifier
2039    : TOKEN_IDENTIFIER { $$ = yylval.stringVal->c_str(); }
2040    ;
2041
2042jump_statement
2043    : TOKEN_GOTO goto_identifier ';'
2044      { $$ = new GotoStmt($2, @1, @2); }
2045    | TOKEN_CONTINUE ';'
2046      { $$ = new ContinueStmt(@1); }
2047    | TOKEN_BREAK ';'
2048      { $$ = new BreakStmt(@1); }
2049    | TOKEN_RETURN ';'
2050      { $$ = new ReturnStmt(NULL, @1); }
2051    | TOKEN_RETURN expression ';'
2052      { $$ = new ReturnStmt($2, @1); }
2053    ;
2054
2055sync_statement
2056    : TOKEN_SYNC ';'
2057      { $$ = new ExprStmt(new SyncExpr(@1), @1); }
2058    ;
2059
2060delete_statement
2061    : TOKEN_DELETE expression ';'
2062    {
2063        $$ = new DeleteStmt($2, Union(@1, @2));
2064    }
2065    ;
2066
2067unmasked_statement
2068    : TOKEN_UNMASKED '{' statement_list '}'
2069    {
2070        $$ = new UnmaskedStmt($3, @1);
2071    }
2072    ;
2073
2074print_statement
2075    : TOKEN_PRINT '(' string_constant ')' ';'
2076      {
2077           $$ = new PrintStmt(*$3, NULL, @1);
2078      }
2079    | TOKEN_PRINT '(' string_constant ',' argument_expression_list ')' ';'
2080      {
2081           $$ = new PrintStmt(*$3, $5, @1);
2082      }
2083    ;
2084
2085assert_statement
2086    : TOKEN_ASSERT '(' string_constant ',' expression ')' ';'
2087      {
2088          $$ = new AssertStmt(*$3, $5, @1);
2089      }
2090    ;
2091
2092translation_unit
2093    : external_declaration
2094    | translation_unit external_declaration
2095    | error ';'
2096    ;
2097
2098external_declaration
2099    : function_definition
2100    | TOKEN_EXTERN TOKEN_STRING_C_LITERAL '{' declaration '}'
2101    | TOKEN_EXPORT '{' type_specifier_list '}' ';'
2102    {
2103        if ($3 != NULL)
2104            m->AddExportedTypes(*$3);
2105    }
2106    | declaration
2107    {
2108        if ($1 != NULL)
2109            for (unsigned int i = 0; i < $1->declarators.size(); ++i)
2110                lAddDeclaration($1->declSpecs, $1->declarators[i]);
2111    }
2112    | ';'
2113    ;
2114
2115function_definition
2116    : declaration_specifiers declarator
2117    {
2118        lAddDeclaration($1, $2);
2119        lAddFunctionParams($2);
2120        lAddMaskToSymbolTable(@2);
2121        if ($1->typeQualifiers & TYPEQUAL_TASK)
2122            lAddThreadIndexCountToSymbolTable(@2);
2123    }
2124    compound_statement
2125    {
2126        if ($2 != NULL) {
2127            $2->InitFromDeclSpecs($1);
2128            const FunctionType *funcType = CastType<FunctionType>($2->type);
2129            if (funcType == NULL)
2130                AssertPos(@1, m->errorCount > 0);
2131            else if ($1->storageClass == SC_TYPEDEF)
2132                Error(@1, "Illegal \"typedef\" provided with function definition.");
2133            else {
2134                Stmt *code = $4;
2135                if (code == NULL) code = new StmtList(@4);
2136                m->AddFunctionDefinition($2->name, funcType, code);
2137            }
2138        }
2139        m->symbolTable->PopScope(); // push in lAddFunctionParams();
2140    }
2141/* function with no declared return type??
2142func(...)
2143    | declarator { lAddFunctionParams($1); } compound_statement
2144    {
2145        m->AddFunction(new DeclSpecs(XXX, $1, $3);
2146        m->symbolTable->PopScope(); // push in lAddFunctionParams();
2147    }
2148*/
2149    ;
2150
2151%%
2152
2153
2154void yyerror(const char *s) {
2155    if (strlen(yytext) == 0)
2156        Error(yylloc, "Premature end of file: %s.", s);
2157    else
2158        Error(yylloc, "%s.", s);
2159}
2160
2161
2162static int
2163lYYTNameErr (char *yyres, const char *yystr)
2164{
2165  extern std::map<std::string, std::string> tokenNameRemap;
2166  Assert(tokenNameRemap.size() > 0);
2167  if (tokenNameRemap.find(yystr) != tokenNameRemap.end()) {
2168      std::string n = tokenNameRemap[yystr];
2169      if (yyres == NULL)
2170          return n.size();
2171      else
2172          return yystpcpy(yyres, n.c_str()) - yyres;
2173  }
2174
2175  if (*yystr == '"')
2176    {
2177      YYSIZE_T yyn = 0;
2178      char const *yyp = yystr;
2179
2180      for (;;)
2181        switch (*++yyp)
2182          {
2183          case '\'':
2184          case ',':
2185            goto do_not_strip_quotes;
2186
2187          case '\\':
2188            if (*++yyp != '\\')
2189              goto do_not_strip_quotes;
2190            /* Fall through.  */
2191          default:
2192            if (yyres)
2193              yyres[yyn] = *yyp;
2194            yyn++;
2195            break;
2196
2197          case '"':
2198            if (yyres)
2199              yyres[yyn] = '\0';
2200            return yyn;
2201          }
2202    do_not_strip_quotes: ;
2203    }
2204
2205  if (! yyres)
2206    return yystrlen (yystr);
2207
2208  return yystpcpy (yyres, yystr) - yyres;
2209}
2210
2211static void
2212lSuggestBuiltinAlternates() {
2213    std::vector<std::string> builtinTokens;
2214    const char **token = lBuiltinTokens;
2215    while (*token) {
2216        builtinTokens.push_back(*token);
2217        ++token;
2218    }
2219    std::vector<std::string> alternates = MatchStrings(yytext, builtinTokens);
2220    std::string alts = lGetAlternates(alternates);
2221    if (alts.size() > 0)
2222         Error(yylloc, "%s", alts.c_str());
2223}
2224
2225
2226static void
2227lSuggestParamListAlternates() {
2228    std::vector<std::string> builtinTokens;
2229    const char **token = lParamListTokens;
2230    while (*token) {
2231        builtinTokens.push_back(*token);
2232        ++token;
2233    }
2234    std::vector<std::string> alternates = MatchStrings(yytext, builtinTokens);
2235    std::string alts = lGetAlternates(alternates);
2236    if (alts.size() > 0)
2237        Error(yylloc, "%s", alts.c_str());
2238}
2239
2240
2241static void
2242lAddDeclaration(DeclSpecs *ds, Declarator *decl) {
2243    if (ds == NULL || decl == NULL)
2244        // Error happened earlier during parsing
2245        return;
2246
2247    decl->InitFromDeclSpecs(ds);
2248    if (ds->storageClass == SC_TYPEDEF)
2249        m->AddTypeDef(decl->name, decl->type, decl->pos);
2250    else {
2251        if (decl->type == NULL) {
2252            Assert(m->errorCount > 0);
2253            return;
2254        }
2255
2256        decl->type = decl->type->ResolveUnboundVariability(Variability::Varying);
2257
2258        const FunctionType *ft = CastType<FunctionType>(decl->type);
2259        if (ft != NULL) {
2260            bool isInline = (ds->typeQualifiers & TYPEQUAL_INLINE);
2261            bool isNoInline = (ds->typeQualifiers & TYPEQUAL_NOINLINE);
2262            bool isVectorCall = (ds->typeQualifiers & TYPEQUAL_VECTORCALL);
2263            m->AddFunctionDeclaration(decl->name, ft, ds->storageClass,
2264                                      isInline, isNoInline, isVectorCall, decl->pos);
2265        }
2266        else {
2267            bool isConst = (ds->typeQualifiers & TYPEQUAL_CONST) != 0;
2268            m->AddGlobalVariable(decl->name, decl->type, decl->initExpr,
2269                                 isConst, decl->storageClass, decl->pos);
2270        }
2271    }
2272}
2273
2274
2275/** We're about to start parsing the body of a function; add all of the
2276    parameters to the symbol table so that they're available.
2277*/
2278static void
2279lAddFunctionParams(Declarator *decl) {
2280    m->symbolTable->PushScope();
2281
2282    if (decl == NULL) {
2283        return;
2284    }
2285
2286    // walk down to the declarator for the function itself
2287    while (decl->kind != DK_FUNCTION && decl->child != NULL)
2288        decl = decl->child;
2289    if (decl->kind != DK_FUNCTION) {
2290        AssertPos(decl->pos, m->errorCount > 0);
2291        return;
2292    }
2293
2294    // now loop over its parameters and add them to the symbol table
2295    for (unsigned int i = 0; i < decl->functionParams.size(); ++i) {
2296        Declaration *pdecl = decl->functionParams[i];
2297        Assert(pdecl != NULL && pdecl->declarators.size() == 1);
2298        Declarator *declarator = pdecl->declarators[0];
2299        if (declarator == NULL)
2300            AssertPos(decl->pos, m->errorCount > 0);
2301        else {
2302            Symbol *sym = new Symbol(declarator->name, declarator->pos,
2303                                     declarator->type, declarator->storageClass);
2304#ifndef NDEBUG
2305            bool ok = m->symbolTable->AddVariable(sym);
2306            if (ok == false)
2307                AssertPos(decl->pos, m->errorCount > 0);
2308#else
2309            m->symbolTable->AddVariable(sym);
2310#endif
2311        }
2312    }
2313
2314    // The corresponding pop scope happens in function_definition rules
2315    // above...
2316}
2317
2318
2319/** Add a symbol for the built-in mask variable to the symbol table */
2320static void lAddMaskToSymbolTable(SourcePos pos) {
2321    const Type *t = NULL;
2322    switch (g->target->getMaskBitCount()) {
2323    case 1:
2324        t = AtomicType::VaryingBool;
2325        break;
2326    case 8:
2327        t = AtomicType::VaryingUInt8;
2328        break;
2329    case 16:
2330        t = AtomicType::VaryingUInt16;
2331        break;
2332    case 32:
2333        t = AtomicType::VaryingUInt32;
2334        break;
2335    case 64:
2336        t = AtomicType::VaryingUInt64;
2337        break;
2338    default:
2339        FATAL("Unhandled mask bitsize in lAddMaskToSymbolTable");
2340    }
2341
2342    t = t->GetAsConstType();
2343    Symbol *maskSymbol = new Symbol("__mask", pos, t);
2344    m->symbolTable->AddVariable(maskSymbol);
2345}
2346
2347
2348/** Add the thread index and thread count variables to the symbol table
2349    (this should only be done for 'task'-qualified functions. */
2350static void lAddThreadIndexCountToSymbolTable(SourcePos pos) {
2351    const Type *type = AtomicType::UniformUInt32->GetAsConstType();
2352
2353    Symbol *threadIndexSym = new Symbol("threadIndex", pos, type);
2354    m->symbolTable->AddVariable(threadIndexSym);
2355
2356    Symbol *threadCountSym = new Symbol("threadCount", pos, type);
2357    m->symbolTable->AddVariable(threadCountSym);
2358
2359    Symbol *taskIndexSym = new Symbol("taskIndex", pos, type);
2360    m->symbolTable->AddVariable(taskIndexSym);
2361
2362    Symbol *taskCountSym = new Symbol("taskCount", pos, type);
2363    m->symbolTable->AddVariable(taskCountSym);
2364
2365    Symbol *taskIndexSym0 = new Symbol("taskIndex0", pos, type);
2366    m->symbolTable->AddVariable(taskIndexSym0);
2367    Symbol *taskIndexSym1 = new Symbol("taskIndex1", pos, type);
2368    m->symbolTable->AddVariable(taskIndexSym1);
2369    Symbol *taskIndexSym2 = new Symbol("taskIndex2", pos, type);
2370    m->symbolTable->AddVariable(taskIndexSym2);
2371
2372
2373    Symbol *taskCountSym0 = new Symbol("taskCount0", pos, type);
2374    m->symbolTable->AddVariable(taskCountSym0);
2375    Symbol *taskCountSym1 = new Symbol("taskCount1", pos, type);
2376    m->symbolTable->AddVariable(taskCountSym1);
2377    Symbol *taskCountSym2 = new Symbol("taskCount2", pos, type);
2378    m->symbolTable->AddVariable(taskCountSym2);
2379}
2380
2381
2382/** Small utility routine to construct a string for error messages that
2383    suggests alternate tokens for possibly-misspelled ones... */
2384static std::string lGetAlternates(std::vector<std::string> &alternates) {
2385    std::string alts;
2386    if (alternates.size()) {
2387        alts += " Did you mean ";
2388        for (unsigned int i = 0; i < alternates.size(); ++i) {
2389            alts += std::string("\"") + alternates[i] + std::string("\"");
2390            if (i < alternates.size() - 1) alts += ", or ";
2391        }
2392        alts += "?";
2393    }
2394    return alts;
2395}
2396
2397static const char *
2398lGetStorageClassString(StorageClass sc) {
2399    switch (sc) {
2400    case SC_NONE:
2401        return "";
2402    case SC_EXTERN:
2403        return "extern";
2404    case SC_STATIC:
2405        return "static";
2406    case SC_TYPEDEF:
2407        return "typedef";
2408    case SC_EXTERN_C:
2409        return "extern \"C\"";
2410    default:
2411        Assert(!"logic error in lGetStorageClassString()");
2412        return "";
2413    }
2414}
2415
2416
2417/** Given an expression, see if it is equal to a compile-time constant
2418    integer value.  If so, return true and return the value in *value.
2419    If the expression isn't a compile-time constant or isn't an integer
2420    type, return false.
2421*/
2422static bool
2423lGetConstantInt(Expr *expr, int *value, SourcePos pos, const char *usage) {
2424    if (expr == NULL)
2425        return false;
2426    expr = TypeCheck(expr);
2427    if (expr == NULL)
2428        return false;
2429    expr = Optimize(expr);
2430    if (expr == NULL)
2431        return false;
2432
2433    std::pair<llvm::Constant *, bool> cValPair = expr->GetConstant(expr->GetType());
2434    llvm::Constant *cval = cValPair.first;
2435    if (cval == NULL) {
2436        Error(pos, "%s must be a compile-time constant.", usage);
2437        return false;
2438    }
2439    else {
2440        llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(cval);
2441        if (ci == NULL) {
2442            Error(pos, "%s must be a compile-time integer constant.", usage);
2443            return false;
2444        }
2445        if ((int64_t)((int32_t)ci->getSExtValue()) != ci->getSExtValue()) {
2446            Error(pos, "%s must be representable with a 32-bit integer.", usage);
2447            return false;
2448        }
2449        const Type *type = expr->GetType();
2450        if (type->IsUnsignedType())
2451            *value = (int)ci->getZExtValue();
2452        else
2453            *value = (int)ci->getSExtValue();
2454        return true;
2455    }
2456}
2457
2458
2459static EnumType *
2460lCreateEnumType(const char *name, std::vector<Symbol *> *enums, SourcePos pos) {
2461    if (enums == NULL)
2462        return NULL;
2463
2464    EnumType *enumType = name ? new EnumType(name, pos) : new EnumType(pos);
2465    if (name != NULL)
2466        m->symbolTable->AddType(name, enumType, pos);
2467
2468    lFinalizeEnumeratorSymbols(*enums, enumType);
2469    for (unsigned int i = 0; i < enums->size(); ++i)
2470        m->symbolTable->AddVariable((*enums)[i]);
2471    enumType->SetEnumerators(*enums);
2472    return enumType;
2473}
2474
2475
2476/** Given an array of enumerator symbols, make sure each of them has a
2477    ConstExpr * in their Symbol::constValue member that stores their
2478    unsigned integer value.  Symbols that had values explicitly provided
2479    in the source file will already have ConstExpr * set; we just need
2480    to set the values for the others here.
2481*/
2482static void
2483lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
2484                           const EnumType *enumType) {
2485    enumType = enumType->GetAsConstType();
2486    enumType = enumType->GetAsUniformType();
2487
2488    /* nextVal tracks the value for the next enumerant.  It starts from
2489       zero and goes up with each successive enumerant.  If any of them
2490       has a value specified, then nextVal is ignored for that one and is
2491       set to one plus that one's value for the default value for the next
2492       one. */
2493    uint32_t nextVal = 0;
2494
2495    for (unsigned int i = 0; i < enums.size(); ++i) {
2496        enums[i]->type = enumType;
2497        if (enums[i]->constValue != NULL) {
2498            /* Already has a value, so first update nextVal with it. */
2499            int count = enums[i]->constValue->GetValues(&nextVal);
2500            AssertPos(enums[i]->pos, count == 1);
2501            ++nextVal;
2502
2503            /* When the source file as being parsed, the ConstExpr for any
2504               enumerant with a specified value was set to have unsigned
2505               int32 type, since we haven't created the parent EnumType
2506               by then.  Therefore, add a little type cast from uint32 to
2507               the actual enum type here and optimize it, which will have
2508               us end up with a ConstExpr with the desired EnumType... */
2509            Expr *castExpr = new TypeCastExpr(enumType, enums[i]->constValue,
2510                                              enums[i]->pos);
2511            castExpr = Optimize(castExpr);
2512            enums[i]->constValue = llvm::dyn_cast<ConstExpr>(castExpr);
2513            AssertPos(enums[i]->pos, enums[i]->constValue != NULL);
2514        }
2515        else {
2516            enums[i]->constValue = new ConstExpr(enumType, nextVal++,
2517                                                 enums[i]->pos);
2518        }
2519    }
2520}
2521