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 32 #define require_ARB_vp (yyextra->mode == ARB_vertex) 33 #define require_ARB_fp (yyextra->mode == ARB_fragment) 34 #define require_NV_fp (yyextra->option.NV_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, 0, 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 sz [HRX]? 164 szf [HR]? 165 cc C? 166 sat (_SAT)? 167 168 %option prefix="_mesa_program_" 169 %option bison-bridge bison-locations reentrant noyywrap 170 %% 171 172 "!!ARBvp1.0" { return ARBvp_10; } 173 "!!ARBfp1.0" { return ARBfp_10; } 174 ADDRESS { 175 yylval->integer = at_address; 176 return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS); 177 } 178 ALIAS { return ALIAS; } 179 ATTRIB { return ATTRIB; } 180 END { return END; } 181 OPTION { return OPTION; } 182 OUTPUT { return OUTPUT; } 183 PARAM { return PARAM; } 184 TEMP { yylval->integer = at_temp; return TEMP; } 185 186 ABS{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, ABS, 3); } 187 ADD{sz}{cc}{sat} { return_opcode( 1, BIN_OP, ADD, 3); } 188 ARL { return_opcode(require_ARB_vp, ARL, ARL, 3); } 189 190 CMP{sat} { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); } 191 COS{szf}{cc}{sat} { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); } 192 193 DDX{szf}{cc}{sat} { return_opcode(require_NV_fp, VECTOR_OP, DDX, 3); } 194 DDY{szf}{cc}{sat} { return_opcode(require_NV_fp, VECTOR_OP, DDY, 3); } 195 DP3{sz}{cc}{sat} { return_opcode( 1, BIN_OP, DP3, 3); } 196 DP4{sz}{cc}{sat} { return_opcode( 1, BIN_OP, DP4, 3); } 197 DPH{sz}{cc}{sat} { return_opcode( 1, BIN_OP, DPH, 3); } 198 DST{szf}{cc}{sat} { return_opcode( 1, BIN_OP, DST, 3); } 199 200 EX2{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, EX2, 3); } 201 EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); } 202 203 FLR{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, FLR, 3); } 204 FRC{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, FRC, 3); } 205 206 KIL { return_opcode(require_ARB_fp, KIL, KIL, 3); } 207 208 LIT{szf}{cc}{sat} { return_opcode( 1, VECTOR_OP, LIT, 3); } 209 LG2{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, LG2, 3); } 210 LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); } 211 LRP{sz}{cc}{sat} { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); } 212 213 MAD{sz}{cc}{sat} { return_opcode( 1, TRI_OP, MAD, 3); } 214 MAX{sz}{cc}{sat} { return_opcode( 1, BIN_OP, MAX, 3); } 215 MIN{sz}{cc}{sat} { return_opcode( 1, BIN_OP, MIN, 3); } 216 MOV{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, MOV, 3); } 217 MUL{sz}{cc}{sat} { return_opcode( 1, BIN_OP, MUL, 3); } 218 219 PK2H { return_opcode(require_NV_fp, VECTOR_OP, PK2H, 4); } 220 PK2US { return_opcode(require_NV_fp, VECTOR_OP, PK2US, 5); } 221 PK4B { return_opcode(require_NV_fp, VECTOR_OP, PK4B, 4); } 222 PK4UB { return_opcode(require_NV_fp, VECTOR_OP, PK4UB, 5); } 223 POW{szf}{cc}{sat} { return_opcode( 1, BINSC_OP, POW, 3); } 224 225 RCP{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, RCP, 3); } 226 RFL{szf}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, RFL, 3); } 227 RSQ{szf}{cc}{sat} { return_opcode( 1, SCALAR_OP, RSQ, 3); } 228 229 SCS{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); } 230 SEQ{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SEQ, 3); } 231 SFL{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SFL, 3); } 232 SGE{sz}{cc}{sat} { return_opcode( 1, BIN_OP, SGE, 3); } 233 SGT{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SGT, 3); } 234 SIN{szf}{cc}{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); } 235 SLE{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SLE, 3); } 236 SLT{sz}{cc}{sat} { return_opcode( 1, BIN_OP, SLT, 3); } 237 SNE{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, SNE, 3); } 238 STR{sz}{cc}{sat} { return_opcode(require_NV_fp, BIN_OP, STR, 3); } 239 SUB{sz}{cc}{sat} { return_opcode( 1, BIN_OP, SUB, 3); } 240 SWZ{sat} { return_opcode( 1, SWZ, SWZ, 3); } 241 242 TEX{cc}{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); } 243 TXB{cc}{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); } 244 TXD{cc}{sat} { return_opcode(require_NV_fp, TXD_OP, TXD, 3); } 245 TXP{cc}{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); } 246 247 UP2H{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP2H, 4); } 248 UP2US{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP2US, 5); } 249 UP4B{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP4B, 4); } 250 UP4UB{cc}{sat} { return_opcode(require_NV_fp, SCALAR_OP, UP4UB, 5); } 251 252 X2D{szf}{cc}{sat} { return_opcode(require_NV_fp, TRI_OP, X2D, 3); } 253 XPD{sat} { return_opcode( 1, BIN_OP, XPD, 3); } 254 255 vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); } 256 fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); } 257 program { return PROGRAM; } 258 state { return STATE; } 259 result { return RESULT; } 260 261 {dot}ambient { return AMBIENT; } 262 {dot}attenuation { return ATTENUATION; } 263 {dot}back { return BACK; } 264 {dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); } 265 {dot}color { return COLOR; } 266 {dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); } 267 {dot}diffuse { return DIFFUSE; } 268 {dot}direction { return DIRECTION; } 269 {dot}emission { return EMISSION; } 270 {dot}env { return ENV; } 271 {dot}eye { return EYE; } 272 {dot}fogcoord { return FOGCOORD; } 273 {dot}fog { return FOG; } 274 {dot}front { return FRONT; } 275 {dot}half { return HALF; } 276 {dot}inverse { return INVERSE; } 277 {dot}invtrans { return INVTRANS; } 278 {dot}light { return LIGHT; } 279 {dot}lightmodel { return LIGHTMODEL; } 280 {dot}lightprod { return LIGHTPROD; } 281 {dot}local { return LOCAL; } 282 {dot}material { return MATERIAL; } 283 {dot}program { return MAT_PROGRAM; } 284 {dot}matrix { return MATRIX; } 285 {dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); } 286 {dot}modelview { return MODELVIEW; } 287 {dot}mvp { return MVP; } 288 {dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); } 289 {dot}object { return OBJECT; } 290 {dot}palette { return PALETTE; } 291 {dot}params { return PARAMS; } 292 {dot}plane { return PLANE; } 293 {dot}point { return_token_or_DOT(require_ARB_vp, POINT_TOK); } 294 {dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); } 295 {dot}position { return POSITION; } 296 {dot}primary { return PRIMARY; } 297 {dot}projection { return PROJECTION; } 298 {dot}range { return_token_or_DOT(require_ARB_fp, RANGE); } 299 {dot}row { return ROW; } 300 {dot}scenecolor { return SCENECOLOR; } 301 {dot}secondary { return SECONDARY; } 302 {dot}shininess { return SHININESS; } 303 {dot}size { return_token_or_DOT(require_ARB_vp, SIZE_TOK); } 304 {dot}specular { return SPECULAR; } 305 {dot}spot { return SPOT; } 306 {dot}texcoord { return TEXCOORD; } 307 {dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); } 308 {dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); } 309 {dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); } 310 {dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); } 311 {dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); } 312 {dot}texture { return TEXTURE; } 313 {dot}transpose { return TRANSPOSE; } 314 {dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); } 315 {dot}weight { return_token_or_DOT(require_ARB_vp, WEIGHT); } 316 317 texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); } 318 1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); } 319 2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); } 320 3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); } 321 CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); } 322 RECT { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); } 323 SHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); } 324 SHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); } 325 SHADOWRECT { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); } 326 ARRAY1D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); } 327 ARRAY2D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); } 328 ARRAYSHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); } 329 ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); } 330 331 [_a-zA-Z$][_a-zA-Z0-9$]* { return handle_ident(yyextra, yytext, yylval); } 332 333 ".." { return DOT_DOT; } 334 335 {num} { 336 yylval->integer = strtol(yytext, NULL, 10); 337 return INTEGER; 338 } 339 {num}?{frac}{exp}? { 340 yylval->real = _mesa_strtof(yytext, NULL); 341 return REAL; 342 } 343 {num}"."/[^.] { 344 yylval->real = _mesa_strtof(yytext, NULL); 345 return REAL; 346 } 347 {num}{exp} { 348 yylval->real = _mesa_strtof(yytext, NULL); 349 return REAL; 350 } 351 {num}"."{exp} { 352 yylval->real = _mesa_strtof(yytext, NULL); 353 return REAL; 354 } 355 356 ".xyzw" { 357 yylval->swiz_mask.swizzle = SWIZZLE_NOOP; 358 yylval->swiz_mask.mask = WRITEMASK_XYZW; 359 return MASK4; 360 } 361 362 ".xy"[zw] { 363 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 364 yylval->swiz_mask.mask = WRITEMASK_XY 365 | mask_from_char(yytext[3]); 366 return MASK3; 367 } 368 ".xzw" { 369 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 370 yylval->swiz_mask.mask = WRITEMASK_XZW; 371 return MASK3; 372 } 373 ".yzw" { 374 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 375 yylval->swiz_mask.mask = WRITEMASK_YZW; 376 return MASK3; 377 } 378 379 ".x"[yzw] { 380 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 381 yylval->swiz_mask.mask = WRITEMASK_X 382 | mask_from_char(yytext[2]); 383 return MASK2; 384 } 385 ".y"[zw] { 386 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 387 yylval->swiz_mask.mask = WRITEMASK_Y 388 | mask_from_char(yytext[2]); 389 return MASK2; 390 } 391 ".zw" { 392 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 393 yylval->swiz_mask.mask = WRITEMASK_ZW; 394 return MASK2; 395 } 396 397 "."[xyzw] { 398 const unsigned s = swiz_from_char(yytext[1]); 399 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s); 400 yylval->swiz_mask.mask = mask_from_char(yytext[1]); 401 return MASK1; 402 } 403 404 "."[xyzw]{4} { 405 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]), 406 swiz_from_char(yytext[2]), 407 swiz_from_char(yytext[3]), 408 swiz_from_char(yytext[4])); 409 yylval->swiz_mask.mask = 0; 410 return SWIZZLE; 411 } 412 413 ".rgba" { 414 yylval->swiz_mask.swizzle = SWIZZLE_NOOP; 415 yylval->swiz_mask.mask = WRITEMASK_XYZW; 416 return_token_or_DOT(require_ARB_fp, MASK4); 417 } 418 419 ".rg"[ba] { 420 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 421 yylval->swiz_mask.mask = WRITEMASK_XY 422 | mask_from_char(yytext[3]); 423 return_token_or_DOT(require_ARB_fp, MASK3); 424 } 425 ".rba" { 426 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 427 yylval->swiz_mask.mask = WRITEMASK_XZW; 428 return_token_or_DOT(require_ARB_fp, MASK3); 429 } 430 ".gba" { 431 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 432 yylval->swiz_mask.mask = WRITEMASK_YZW; 433 return_token_or_DOT(require_ARB_fp, MASK3); 434 } 435 436 ".r"[gba] { 437 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 438 yylval->swiz_mask.mask = WRITEMASK_X 439 | mask_from_char(yytext[2]); 440 return_token_or_DOT(require_ARB_fp, MASK2); 441 } 442 ".g"[ba] { 443 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 444 yylval->swiz_mask.mask = WRITEMASK_Y 445 | mask_from_char(yytext[2]); 446 return_token_or_DOT(require_ARB_fp, MASK2); 447 } 448 ".ba" { 449 yylval->swiz_mask.swizzle = SWIZZLE_INVAL; 450 yylval->swiz_mask.mask = WRITEMASK_ZW; 451 return_token_or_DOT(require_ARB_fp, MASK2); 452 } 453 454 "."[gba] { 455 const unsigned s = swiz_from_char(yytext[1]); 456 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s); 457 yylval->swiz_mask.mask = mask_from_char(yytext[1]); 458 return_token_or_DOT(require_ARB_fp, MASK1); 459 } 460 461 462 ".r" { 463 if (require_ARB_vp) { 464 return TEXGEN_R; 465 } else { 466 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, 467 SWIZZLE_X, SWIZZLE_X); 468 yylval->swiz_mask.mask = WRITEMASK_X; 469 return MASK1; 470 } 471 } 472 473 "."[rgba]{4} { 474 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]), 475 swiz_from_char(yytext[2]), 476 swiz_from_char(yytext[3]), 477 swiz_from_char(yytext[4])); 478 yylval->swiz_mask.mask = 0; 479 return_token_or_DOT(require_ARB_fp, SWIZZLE); 480 } 481 482 "." { return DOT; } 483 484 \n { 485 yylloc->first_line++; 486 yylloc->first_column = 1; 487 yylloc->last_line++; 488 yylloc->last_column = 1; 489 yylloc->position++; 490 } 491 [ \t\r]+ /* eat whitespace */ ; 492 #.*$ /* eat comments */ ; 493 . { return yytext[0]; } 494 %% 495 496 void 497 _mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state, 498 const char *string, size_t len) 499 { 500 yylex_init_extra(state, scanner); 501 yy_scan_bytes(string, len, *scanner); 502 } 503 504 void 505 _mesa_program_lexer_dtor(void *scanner) 506 { 507 yylex_destroy(scanner); 508 } 509