Home | History | Annotate | Download | only in program
      1 %{
      2 /*
      3  * Copyright  2009 Intel Corporation
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  */
     24 #include "main/glheader.h"
     25 #include "main/imports.h"
     26 #include "program/prog_instruction.h"
     27 #include "program/prog_statevars.h"
     28 #include "program/symbol_table.h"
     29 #include "program/program_parser.h"
     30 #include "program/program_parse.tab.h"
     31 #include "util/strtod.h"
     32 
     33 #define require_ARB_vp (yyextra->mode == ARB_vertex)
     34 #define require_ARB_fp (yyextra->mode == ARB_fragment)
     35 #define require_shadow (yyextra->option.Shadow)
     36 #define require_rect   (yyextra->option.TexRect)
     37 #define require_texarray        (yyextra->option.TexArray)
     38 
     39 #ifndef HAVE_UNISTD_H
     40 #define YY_NO_UNISTD_H
     41 #endif
     42 
     43 #define return_token_or_IDENTIFIER(condition, token)	\
     44    do {							\
     45       if (condition) {					\
     46 	 return token;					\
     47       } else {						\
     48 	 return handle_ident(yyextra, yytext, yylval);	\
     49       }							\
     50    } while (0)
     51 
     52 #define return_token_or_DOT(condition, token)		\
     53    do {							\
     54       if (condition) {					\
     55 	 return token;					\
     56       } else {						\
     57 	 yyless(1);					\
     58 	 return DOT;					\
     59       }							\
     60    } while (0)
     61 
     62 
     63 #define return_opcode(condition, token, opcode, len)	\
     64    do {							\
     65       if (condition &&					\
     66 	  _mesa_parse_instruction_suffix(yyextra,	\
     67 					 yytext + len,	\
     68 					 & yylval->temp_inst)) {	\
     69 	 yylval->temp_inst.Opcode = OPCODE_ ## opcode;	\
     70 	 return token;					\
     71       } else {						\
     72 	 return handle_ident(yyextra, yytext, yylval);	\
     73       }							\
     74    } while (0)
     75 
     76 #define SWIZZLE_INVAL  MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
     77 				     SWIZZLE_NIL, SWIZZLE_NIL)
     78 
     79 static unsigned
     80 mask_from_char(char c)
     81 {
     82    switch (c) {
     83    case 'x':
     84    case 'r':
     85       return WRITEMASK_X;
     86    case 'y':
     87    case 'g':
     88       return WRITEMASK_Y;
     89    case 'z':
     90    case 'b':
     91       return WRITEMASK_Z;
     92    case 'w':
     93    case 'a':
     94       return WRITEMASK_W;
     95    }
     96 
     97    return 0;
     98 }
     99 
    100 static unsigned
    101 swiz_from_char(char c)
    102 {
    103    switch (c) {
    104    case 'x':
    105    case 'r':
    106       return SWIZZLE_X;
    107    case 'y':
    108    case 'g':
    109       return SWIZZLE_Y;
    110    case 'z':
    111    case 'b':
    112       return SWIZZLE_Z;
    113    case 'w':
    114    case 'a':
    115       return SWIZZLE_W;
    116    }
    117 
    118    return 0;
    119 }
    120 
    121 static int
    122 handle_ident(struct asm_parser_state *state, const char *text, YYSTYPE *lval)
    123 {
    124    lval->string = strdup(text);
    125 
    126    return (_mesa_symbol_table_find_symbol(state->st, text) == NULL)
    127       ? IDENTIFIER : USED_IDENTIFIER;
    128 }
    129 
    130 #define YY_USER_ACTION							\
    131    do {									\
    132       yylloc->first_column = yylloc->last_column;			\
    133       yylloc->last_column += yyleng;					\
    134       if ((yylloc->first_line == 1)					\
    135 	  && (yylloc->first_column == 1)) {				\
    136 	 yylloc->position = 1;						\
    137       } else {								\
    138 	 yylloc->position += yylloc->last_column - yylloc->first_column; \
    139       }									\
    140    } while(0);
    141 
    142 #define YY_NO_INPUT
    143 
    144 /* Yes, this is intentionally doing nothing. We have this line of code
    145 here only to avoid the compiler complaining about an unput function
    146 that is defined, but never called. */
    147 #define YY_USER_INIT while (0) { unput(0); }
    148 
    149 #define YY_EXTRA_TYPE struct asm_parser_state *
    150 
    151 /* Flex defines a couple of functions with no declarations nor the
    152 static keyword. Declare them here to avoid a compiler warning. */
    153 int yyget_column  (yyscan_t yyscanner);
    154 void yyset_column (int  column_no , yyscan_t yyscanner);
    155 
    156 %}
    157 
    158 num    [0-9]+
    159 exp    [Ee][-+]?[0-9]+
    160 frac   "."[0-9]+
    161 dot    "."[ \t]*
    162 
    163 sat    (_SAT)?
    164 
    165 %option prefix="_mesa_program_lexer_"
    166 %option bison-bridge bison-locations reentrant noyywrap
    167 %%
    168 
    169 "!!ARBvp1.0"              { return ARBvp_10; }
    170 "!!ARBfp1.0"              { return ARBfp_10; }
    171 ADDRESS                   {
    172    yylval->integer = at_address;
    173    return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
    174 }
    175 ALIAS                     { return ALIAS; }
    176 ATTRIB                    { return ATTRIB; }
    177 END                       { return END; }
    178 OPTION                    { return OPTION; }
    179 OUTPUT                    { return OUTPUT; }
    180 PARAM                     { return PARAM; }
    181 TEMP                      { yylval->integer = at_temp; return TEMP; }
    182 
    183 ABS{sat}           { return_opcode(             1, VECTOR_OP, ABS, 3); }
    184 ADD{sat}           { return_opcode(             1, BIN_OP, ADD, 3); }
    185 ARL                { return_opcode(require_ARB_vp, ARL, ARL, 3); }
    186 
    187 CMP{sat}           { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); }
    188 COS{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); }
    189 
    190 DP3{sat}           { return_opcode(             1, BIN_OP, DP3, 3); }
    191 DP4{sat}           { return_opcode(             1, BIN_OP, DP4, 3); }
    192 DPH{sat}           { return_opcode(             1, BIN_OP, DPH, 3); }
    193 DST{sat}           { return_opcode(             1, BIN_OP, DST, 3); }
    194 
    195 EX2{sat}           { return_opcode(             1, SCALAR_OP, EX2, 3); }
    196 EXP                { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); }
    197 
    198 FLR{sat}           { return_opcode(             1, VECTOR_OP, FLR, 3); }
    199 FRC{sat}           { return_opcode(             1, VECTOR_OP, FRC, 3); }
    200 
    201 KIL                { return_opcode(require_ARB_fp, KIL, KIL, 3); }
    202 
    203 LIT{sat}           { return_opcode(             1, VECTOR_OP, LIT, 3); }
    204 LG2{sat}           { return_opcode(             1, SCALAR_OP, LG2, 3); }
    205 LOG                { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); }
    206 LRP{sat}           { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); }
    207 
    208 MAD{sat}           { return_opcode(             1, TRI_OP, MAD, 3); }
    209 MAX{sat}           { return_opcode(             1, BIN_OP, MAX, 3); }
    210 MIN{sat}           { return_opcode(             1, BIN_OP, MIN, 3); }
    211 MOV{sat}           { return_opcode(             1, VECTOR_OP, MOV, 3); }
    212 MUL{sat}           { return_opcode(             1, BIN_OP, MUL, 3); }
    213 
    214 POW{sat}           { return_opcode(             1, BINSC_OP, POW, 3); }
    215 
    216 RCP{sat}           { return_opcode(             1, SCALAR_OP, RCP, 3); }
    217 RSQ{sat}           { return_opcode(             1, SCALAR_OP, RSQ, 3); }
    218 
    219 SCS{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); }
    220 SGE{sat}           { return_opcode(             1, BIN_OP, SGE, 3); }
    221 SIN{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); }
    222 SLT{sat}           { return_opcode(             1, BIN_OP, SLT, 3); }
    223 SUB{sat}           { return_opcode(             1, BIN_OP, SUB, 3); }
    224 SWZ{sat}           { return_opcode(             1, SWZ, SWZ, 3); }
    225 
    226 TEX{sat}           { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); }
    227 TXB{sat}           { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); }
    228 TXP{sat}           { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); }
    229 
    230 XPD{sat}           { return_opcode(             1, BIN_OP, XPD, 3); }
    231 
    232 vertex                    { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
    233 fragment                  { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
    234 program                   { return PROGRAM; }
    235 state                     { return STATE; }
    236 result                    { return RESULT; }
    237 
    238 {dot}ambient              { return AMBIENT; }
    239 {dot}attenuation          { return ATTENUATION; }
    240 {dot}back                 { return BACK; }
    241 {dot}clip                 { return_token_or_DOT(require_ARB_vp, CLIP); }
    242 {dot}color                { return COLOR; }
    243 {dot}depth                { return_token_or_DOT(require_ARB_fp, DEPTH); }
    244 {dot}diffuse              { return DIFFUSE; }
    245 {dot}direction            { return DIRECTION; }
    246 {dot}emission             { return EMISSION; }
    247 {dot}env                  { return ENV; }
    248 {dot}eye                  { return EYE; }
    249 {dot}fogcoord             { return FOGCOORD; }
    250 {dot}fog                  { return FOG; }
    251 {dot}front                { return FRONT; }
    252 {dot}half                 { return HALF; }
    253 {dot}inverse              { return INVERSE; }
    254 {dot}invtrans             { return INVTRANS; }
    255 {dot}light                { return LIGHT; }
    256 {dot}lightmodel           { return LIGHTMODEL; }
    257 {dot}lightprod            { return LIGHTPROD; }
    258 {dot}local                { return LOCAL; }
    259 {dot}material             { return MATERIAL; }
    260 {dot}program              { return MAT_PROGRAM; }
    261 {dot}matrix               { return MATRIX; }
    262 {dot}matrixindex          { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
    263 {dot}modelview            { return MODELVIEW; }
    264 {dot}mvp                  { return MVP; }
    265 {dot}normal               { return_token_or_DOT(require_ARB_vp, NORMAL); }
    266 {dot}object               { return OBJECT; }
    267 {dot}palette              { return PALETTE; }
    268 {dot}params               { return PARAMS; }
    269 {dot}plane                { return PLANE; }
    270 {dot}point                { return_token_or_DOT(require_ARB_vp, POINT_TOK); }
    271 {dot}pointsize            { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
    272 {dot}position             { return POSITION; }
    273 {dot}primary              { return PRIMARY; }
    274 {dot}projection           { return PROJECTION; }
    275 {dot}range                { return_token_or_DOT(require_ARB_fp, RANGE); }
    276 {dot}row                  { return ROW; }
    277 {dot}scenecolor           { return SCENECOLOR; }
    278 {dot}secondary            { return SECONDARY; }
    279 {dot}shininess            { return SHININESS; }
    280 {dot}size                 { return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
    281 {dot}specular             { return SPECULAR; }
    282 {dot}spot                 { return SPOT; }
    283 {dot}texcoord             { return TEXCOORD; }
    284 {dot}texenv               { return_token_or_DOT(require_ARB_fp, TEXENV); }
    285 {dot}texgen               { return_token_or_DOT(require_ARB_vp, TEXGEN); }
    286 {dot}q                    { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
    287 {dot}s                    { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
    288 {dot}t                    { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
    289 {dot}texture              { return TEXTURE; }
    290 {dot}transpose            { return TRANSPOSE; }
    291 {dot}attrib               { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
    292 {dot}weight               { return_token_or_DOT(require_ARB_vp, WEIGHT); }
    293 
    294 texture                   { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
    295 1D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
    296 2D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
    297 3D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
    298 CUBE                      { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
    299 RECT                      { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
    300 SHADOW1D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
    301 SHADOW2D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
    302 SHADOWRECT                { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
    303 ARRAY1D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
    304 ARRAY2D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
    305 ARRAYSHADOW1D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
    306 ARRAYSHADOW2D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
    307 
    308 [_a-zA-Z$][_a-zA-Z0-9$]*  { return handle_ident(yyextra, yytext, yylval); }
    309 
    310 ".."                      { return DOT_DOT; }
    311 
    312 {num}                     {
    313    yylval->integer = strtol(yytext, NULL, 10);
    314    return INTEGER;
    315 }
    316 {num}?{frac}{exp}?        {
    317    yylval->real = _mesa_strtof(yytext, NULL);
    318    return REAL;
    319 }
    320 {num}"."/[^.]             {
    321    yylval->real = _mesa_strtof(yytext, NULL);
    322    return REAL;
    323 }
    324 {num}{exp}                {
    325    yylval->real = _mesa_strtof(yytext, NULL);
    326    return REAL;
    327 }
    328 {num}"."{exp}             {
    329    yylval->real = _mesa_strtof(yytext, NULL);
    330    return REAL;
    331 }
    332 
    333 ".xyzw"                   {
    334    yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
    335    yylval->swiz_mask.mask = WRITEMASK_XYZW;
    336    return MASK4;
    337 }
    338 
    339 ".xy"[zw]                 {
    340    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    341    yylval->swiz_mask.mask = WRITEMASK_XY
    342       | mask_from_char(yytext[3]);
    343    return MASK3;
    344 }
    345 ".xzw"                    {
    346    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    347    yylval->swiz_mask.mask = WRITEMASK_XZW;
    348    return MASK3;
    349 }
    350 ".yzw"                    {
    351    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    352    yylval->swiz_mask.mask = WRITEMASK_YZW;
    353    return MASK3;
    354 }
    355 
    356 ".x"[yzw]                 {
    357    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    358    yylval->swiz_mask.mask = WRITEMASK_X
    359       | mask_from_char(yytext[2]);
    360    return MASK2;
    361 }
    362 ".y"[zw]                  {
    363    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    364    yylval->swiz_mask.mask = WRITEMASK_Y
    365       | mask_from_char(yytext[2]);
    366    return MASK2;
    367 }
    368 ".zw"                     {
    369    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    370    yylval->swiz_mask.mask = WRITEMASK_ZW;
    371    return MASK2;
    372 }
    373 
    374 "."[xyzw]                 {
    375    const unsigned s = swiz_from_char(yytext[1]);
    376    yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
    377    yylval->swiz_mask.mask = mask_from_char(yytext[1]);
    378    return MASK1;
    379 }
    380 
    381 "."[xyzw]{4}              {
    382    yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
    383 					    swiz_from_char(yytext[2]),
    384 					    swiz_from_char(yytext[3]),
    385 					    swiz_from_char(yytext[4]));
    386    yylval->swiz_mask.mask = 0;
    387    return SWIZZLE;
    388 }
    389 
    390 ".rgba"                   {
    391    yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
    392    yylval->swiz_mask.mask = WRITEMASK_XYZW;
    393    return_token_or_DOT(require_ARB_fp, MASK4);
    394 }
    395 
    396 ".rg"[ba]                 {
    397    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    398    yylval->swiz_mask.mask = WRITEMASK_XY
    399       | mask_from_char(yytext[3]);
    400    return_token_or_DOT(require_ARB_fp, MASK3);
    401 }
    402 ".rba"                    {
    403    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    404    yylval->swiz_mask.mask = WRITEMASK_XZW;
    405    return_token_or_DOT(require_ARB_fp, MASK3);
    406 }
    407 ".gba"                    {
    408    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    409    yylval->swiz_mask.mask = WRITEMASK_YZW;
    410    return_token_or_DOT(require_ARB_fp, MASK3);
    411 }
    412 
    413 ".r"[gba]                 {
    414    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    415    yylval->swiz_mask.mask = WRITEMASK_X
    416       | mask_from_char(yytext[2]);
    417    return_token_or_DOT(require_ARB_fp, MASK2);
    418 }
    419 ".g"[ba]                  {
    420    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    421    yylval->swiz_mask.mask = WRITEMASK_Y
    422       | mask_from_char(yytext[2]);
    423    return_token_or_DOT(require_ARB_fp, MASK2);
    424 }
    425 ".ba"                     {
    426    yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
    427    yylval->swiz_mask.mask = WRITEMASK_ZW;
    428    return_token_or_DOT(require_ARB_fp, MASK2);
    429 }
    430 
    431 "."[gba]                  {
    432    const unsigned s = swiz_from_char(yytext[1]);
    433    yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
    434    yylval->swiz_mask.mask = mask_from_char(yytext[1]);
    435    return_token_or_DOT(require_ARB_fp, MASK1);
    436 }
    437 
    438 
    439 ".r"                      {
    440    if (require_ARB_vp) {
    441       return TEXGEN_R;
    442    } else {
    443       yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
    444 						SWIZZLE_X, SWIZZLE_X);
    445       yylval->swiz_mask.mask = WRITEMASK_X;
    446       return MASK1;
    447    }
    448 }
    449 
    450 "."[rgba]{4}              {
    451    yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
    452 					    swiz_from_char(yytext[2]),
    453 					    swiz_from_char(yytext[3]),
    454 					    swiz_from_char(yytext[4]));
    455    yylval->swiz_mask.mask = 0;
    456    return_token_or_DOT(require_ARB_fp, SWIZZLE);
    457 }
    458 
    459 "."                       { return DOT; }
    460 
    461 \n                        {
    462    yylloc->first_line++;
    463    yylloc->first_column = 1;
    464    yylloc->last_line++;
    465    yylloc->last_column = 1;
    466    yylloc->position++;
    467 }
    468 [ \t\r]+                  /* eat whitespace */ ;
    469 #.*$                      /* eat comments */ ;
    470 .                         { return yytext[0]; }
    471 %%
    472 
    473 void
    474 _mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
    475 			 const char *string, size_t len)
    476 {
    477    yylex_init_extra(state, scanner);
    478    yy_scan_bytes(string, len, *scanner);
    479 }
    480 
    481 void
    482 _mesa_program_lexer_dtor(void *scanner)
    483 {
    484    yylex_destroy(scanner);
    485 }
    486