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