tgsi_text.c revision f90524a01bc159cde09a50ebdb8c5b5b7c4b9895
1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/************************************************************************** 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * All Rights Reserved. 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Permission is hereby granted, free of charge, to any person obtaining a 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * copy of this software and associated documentation files (the 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * "Software"), to deal in the Software without restriction, including 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * without limitation the rights to use, copy, modify, merge, publish, 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * distribute, sub license, and/or sell copies of the Software, and to 11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * permit persons to whom the Software is furnished to do so, subject to 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * the following conditions: 13f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org * 14f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org * The above copyright notice and this permission notice (including the 15f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org * next paragraph) shall be included in all copies or substantial portions 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * of the Software. 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 18f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2498b201189e601aa1863085e0016e868d2db416b1pbos@webrtc.org * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org **************************************************************************/ 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_debug.h" 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_memory.h" 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_prim.h" 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pipe/p_defines.h" 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "util/u_inlines.h" 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tgsi_text.h" 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tgsi_build.h" 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tgsi_info.h" 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tgsi_parse.h" 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tgsi_sanity.h" 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "tgsi_util.h" 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic boolean is_alpha_underscore( const char *cur ) 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (*cur >= 'a' && *cur <= 'z') || 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (*cur >= 'A' && *cur <= 'Z') || 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *cur == '_'; 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic boolean is_digit( const char *cur ) 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return *cur >= '0' && *cur <= '9'; 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic boolean is_digit_alpha_underscore( const char *cur ) 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return is_digit( cur ) || is_alpha_underscore( cur ); 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic char uprcase( char c ) 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (c >= 'a' && c <= 'z') 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return c + 'A' - 'a'; 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return c; 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Ignore case of str1 and assume str1 is already uppercase. 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Return TRUE iff str1 and str2 are equal. 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic int 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstreq_nocase_uprcase(const char *str1, 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *str2) 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (*str1 && *str2) { 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (*str1 != uprcase(*str2)) 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return FALSE; 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org str1++; 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org str2++; 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return *str1 == 0 && *str2 == 0; 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic boolean str_match_no_case( const char **pcur, const char *str ) 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char *cur = *pcur; 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (*str != '\0' && *str == uprcase( *cur )) { 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org str++; 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org cur++; 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (*str == '\0') { 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *pcur = cur; 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return TRUE; 93 } 94 return FALSE; 95} 96 97/* Eat zero or more whitespaces. 98 */ 99static void eat_opt_white( const char **pcur ) 100{ 101 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n') 102 (*pcur)++; 103} 104 105/* Eat one or more whitespaces. 106 * Return TRUE if at least one whitespace eaten. 107 */ 108static boolean eat_white( const char **pcur ) 109{ 110 const char *cur = *pcur; 111 112 eat_opt_white( pcur ); 113 return *pcur > cur; 114} 115 116/* Parse unsigned integer. 117 * No checks for overflow. 118 */ 119static boolean parse_uint( const char **pcur, uint *val ) 120{ 121 const char *cur = *pcur; 122 123 if (is_digit( cur )) { 124 *val = *cur++ - '0'; 125 while (is_digit( cur )) 126 *val = *val * 10 + *cur++ - '0'; 127 *pcur = cur; 128 return TRUE; 129 } 130 return FALSE; 131} 132 133static boolean parse_identifier( const char **pcur, char *ret ) 134{ 135 const char *cur = *pcur; 136 int i = 0; 137 if (is_alpha_underscore( cur )) { 138 ret[i++] = *cur++; 139 while (is_alpha_underscore( cur )) 140 ret[i++] = *cur++; 141 ret[i++] = '\0'; 142 *pcur = cur; 143 return TRUE; 144 } 145 return FALSE; 146} 147 148/* Parse floating point. 149 */ 150static boolean parse_float( const char **pcur, float *val ) 151{ 152 const char *cur = *pcur; 153 boolean integral_part = FALSE; 154 boolean fractional_part = FALSE; 155 156 *val = (float) atof( cur ); 157 158 if (*cur == '-' || *cur == '+') 159 cur++; 160 if (is_digit( cur )) { 161 cur++; 162 integral_part = TRUE; 163 while (is_digit( cur )) 164 cur++; 165 } 166 if (*cur == '.') { 167 cur++; 168 if (is_digit( cur )) { 169 cur++; 170 fractional_part = TRUE; 171 while (is_digit( cur )) 172 cur++; 173 } 174 } 175 if (!integral_part && !fractional_part) 176 return FALSE; 177 if (uprcase( *cur ) == 'E') { 178 cur++; 179 if (*cur == '-' || *cur == '+') 180 cur++; 181 if (is_digit( cur )) { 182 cur++; 183 while (is_digit( cur )) 184 cur++; 185 } 186 else 187 return FALSE; 188 } 189 *pcur = cur; 190 return TRUE; 191} 192 193struct translate_ctx 194{ 195 const char *text; 196 const char *cur; 197 struct tgsi_token *tokens; 198 struct tgsi_token *tokens_cur; 199 struct tgsi_token *tokens_end; 200 struct tgsi_header *header; 201 unsigned processor : 4; 202 int implied_array_size : 5; 203}; 204 205static void report_error( struct translate_ctx *ctx, const char *msg ) 206{ 207 int line = 1; 208 int column = 1; 209 const char *itr = ctx->text; 210 211 while (itr != ctx->cur) { 212 if (*itr == '\n') { 213 column = 1; 214 ++line; 215 } 216 ++column; 217 ++itr; 218 } 219 220 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column ); 221} 222 223/* Parse shader header. 224 * Return TRUE for one of the following headers. 225 * FRAG 226 * GEOM 227 * VERT 228 */ 229static boolean parse_header( struct translate_ctx *ctx ) 230{ 231 uint processor; 232 233 if (str_match_no_case( &ctx->cur, "FRAG" )) 234 processor = TGSI_PROCESSOR_FRAGMENT; 235 else if (str_match_no_case( &ctx->cur, "VERT" )) 236 processor = TGSI_PROCESSOR_VERTEX; 237 else if (str_match_no_case( &ctx->cur, "GEOM" )) 238 processor = TGSI_PROCESSOR_GEOMETRY; 239 else { 240 report_error( ctx, "Unknown header" ); 241 return FALSE; 242 } 243 244 if (ctx->tokens_cur >= ctx->tokens_end) 245 return FALSE; 246 ctx->header = (struct tgsi_header *) ctx->tokens_cur++; 247 *ctx->header = tgsi_build_header(); 248 249 if (ctx->tokens_cur >= ctx->tokens_end) 250 return FALSE; 251 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header ); 252 ctx->processor = processor; 253 254 return TRUE; 255} 256 257static boolean parse_label( struct translate_ctx *ctx, uint *val ) 258{ 259 const char *cur = ctx->cur; 260 261 if (parse_uint( &cur, val )) { 262 eat_opt_white( &cur ); 263 if (*cur == ':') { 264 cur++; 265 ctx->cur = cur; 266 return TRUE; 267 } 268 } 269 return FALSE; 270} 271 272static const char *file_names[TGSI_FILE_COUNT] = 273{ 274 "NULL", 275 "CONST", 276 "IN", 277 "OUT", 278 "TEMP", 279 "SAMP", 280 "ADDR", 281 "IMM", 282 "PRED", 283 "SV", 284 "IMMX", 285 "TEMPX" 286}; 287 288static boolean 289parse_file( const char **pcur, uint *file ) 290{ 291 uint i; 292 293 for (i = 0; i < TGSI_FILE_COUNT; i++) { 294 const char *cur = *pcur; 295 296 if (str_match_no_case( &cur, file_names[i] )) { 297 if (!is_digit_alpha_underscore( cur )) { 298 *pcur = cur; 299 *file = i; 300 return TRUE; 301 } 302 } 303 } 304 return FALSE; 305} 306 307static boolean 308parse_opt_writemask( 309 struct translate_ctx *ctx, 310 uint *writemask ) 311{ 312 const char *cur; 313 314 cur = ctx->cur; 315 eat_opt_white( &cur ); 316 if (*cur == '.') { 317 cur++; 318 *writemask = TGSI_WRITEMASK_NONE; 319 eat_opt_white( &cur ); 320 if (uprcase( *cur ) == 'X') { 321 cur++; 322 *writemask |= TGSI_WRITEMASK_X; 323 } 324 if (uprcase( *cur ) == 'Y') { 325 cur++; 326 *writemask |= TGSI_WRITEMASK_Y; 327 } 328 if (uprcase( *cur ) == 'Z') { 329 cur++; 330 *writemask |= TGSI_WRITEMASK_Z; 331 } 332 if (uprcase( *cur ) == 'W') { 333 cur++; 334 *writemask |= TGSI_WRITEMASK_W; 335 } 336 337 if (*writemask == TGSI_WRITEMASK_NONE) { 338 report_error( ctx, "Writemask expected" ); 339 return FALSE; 340 } 341 342 ctx->cur = cur; 343 } 344 else { 345 *writemask = TGSI_WRITEMASK_XYZW; 346 } 347 return TRUE; 348} 349 350 351/* <register_file_bracket> ::= <file> `[' 352 */ 353static boolean 354parse_register_file_bracket( 355 struct translate_ctx *ctx, 356 uint *file ) 357{ 358 if (!parse_file( &ctx->cur, file )) { 359 report_error( ctx, "Unknown register file" ); 360 return FALSE; 361 } 362 eat_opt_white( &ctx->cur ); 363 if (*ctx->cur != '[') { 364 report_error( ctx, "Expected `['" ); 365 return FALSE; 366 } 367 ctx->cur++; 368 return TRUE; 369} 370 371/* <register_file_bracket_index> ::= <register_file_bracket> <uint> 372 */ 373static boolean 374parse_register_file_bracket_index( 375 struct translate_ctx *ctx, 376 uint *file, 377 int *index ) 378{ 379 uint uindex; 380 381 if (!parse_register_file_bracket( ctx, file )) 382 return FALSE; 383 eat_opt_white( &ctx->cur ); 384 if (!parse_uint( &ctx->cur, &uindex )) { 385 report_error( ctx, "Expected literal unsigned integer" ); 386 return FALSE; 387 } 388 *index = (int) uindex; 389 return TRUE; 390} 391 392/* Parse simple 1d register operand. 393 * <register_dst> ::= <register_file_bracket_index> `]' 394 */ 395static boolean 396parse_register_1d(struct translate_ctx *ctx, 397 uint *file, 398 int *index ) 399{ 400 if (!parse_register_file_bracket_index( ctx, file, index )) 401 return FALSE; 402 eat_opt_white( &ctx->cur ); 403 if (*ctx->cur != ']') { 404 report_error( ctx, "Expected `]'" ); 405 return FALSE; 406 } 407 ctx->cur++; 408 return TRUE; 409} 410 411struct parsed_bracket { 412 int index; 413 414 uint ind_file; 415 int ind_index; 416 uint ind_comp; 417}; 418 419 420static boolean 421parse_register_bracket( 422 struct translate_ctx *ctx, 423 struct parsed_bracket *brackets) 424{ 425 const char *cur; 426 uint uindex; 427 428 memset(brackets, 0, sizeof(struct parsed_bracket)); 429 430 eat_opt_white( &ctx->cur ); 431 432 cur = ctx->cur; 433 if (parse_file( &cur, &brackets->ind_file )) { 434 if (!parse_register_1d( ctx, &brackets->ind_file, 435 &brackets->ind_index )) 436 return FALSE; 437 eat_opt_white( &ctx->cur ); 438 439 if (*ctx->cur == '.') { 440 ctx->cur++; 441 eat_opt_white(&ctx->cur); 442 443 switch (uprcase(*ctx->cur)) { 444 case 'X': 445 brackets->ind_comp = TGSI_SWIZZLE_X; 446 break; 447 case 'Y': 448 brackets->ind_comp = TGSI_SWIZZLE_Y; 449 break; 450 case 'Z': 451 brackets->ind_comp = TGSI_SWIZZLE_Z; 452 break; 453 case 'W': 454 brackets->ind_comp = TGSI_SWIZZLE_W; 455 break; 456 default: 457 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'"); 458 return FALSE; 459 } 460 ctx->cur++; 461 eat_opt_white(&ctx->cur); 462 } 463 464 if (*ctx->cur == '+' || *ctx->cur == '-') { 465 boolean negate; 466 467 negate = *ctx->cur == '-'; 468 ctx->cur++; 469 eat_opt_white( &ctx->cur ); 470 if (!parse_uint( &ctx->cur, &uindex )) { 471 report_error( ctx, "Expected literal unsigned integer" ); 472 return FALSE; 473 } 474 if (negate) 475 brackets->index = -(int) uindex; 476 else 477 brackets->index = (int) uindex; 478 } 479 else { 480 brackets->index = 0; 481 } 482 } 483 else { 484 if (!parse_uint( &ctx->cur, &uindex )) { 485 report_error( ctx, "Expected literal unsigned integer" ); 486 return FALSE; 487 } 488 brackets->index = (int) uindex; 489 brackets->ind_file = TGSI_FILE_NULL; 490 brackets->ind_index = 0; 491 } 492 eat_opt_white( &ctx->cur ); 493 if (*ctx->cur != ']') { 494 report_error( ctx, "Expected `]'" ); 495 return FALSE; 496 } 497 ctx->cur++; 498 return TRUE; 499} 500 501static boolean 502parse_opt_register_src_bracket( 503 struct translate_ctx *ctx, 504 struct parsed_bracket *brackets, 505 int *parsed_brackets) 506{ 507 const char *cur = ctx->cur; 508 509 *parsed_brackets = 0; 510 511 eat_opt_white( &cur ); 512 if (cur[0] == '[') { 513 ++cur; 514 ctx->cur = cur; 515 516 if (!parse_register_bracket(ctx, brackets)) 517 return FALSE; 518 519 *parsed_brackets = 1; 520 } 521 522 return TRUE; 523} 524 525 526/* Parse source register operand. 527 * <register_src> ::= <register_file_bracket_index> `]' | 528 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' | 529 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' | 530 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]' 531 */ 532static boolean 533parse_register_src( 534 struct translate_ctx *ctx, 535 uint *file, 536 struct parsed_bracket *brackets) 537{ 538 brackets->ind_comp = TGSI_SWIZZLE_X; 539 if (!parse_register_file_bracket( ctx, file )) 540 return FALSE; 541 if (!parse_register_bracket( ctx, brackets )) 542 return FALSE; 543 544 return TRUE; 545} 546 547struct parsed_dcl_bracket { 548 uint first; 549 uint last; 550}; 551 552static boolean 553parse_register_dcl_bracket( 554 struct translate_ctx *ctx, 555 struct parsed_dcl_bracket *bracket) 556{ 557 uint uindex; 558 memset(bracket, 0, sizeof(struct parsed_dcl_bracket)); 559 560 eat_opt_white( &ctx->cur ); 561 562 if (!parse_uint( &ctx->cur, &uindex )) { 563 /* it can be an empty bracket [] which means its range 564 * is from 0 to some implied size */ 565 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) { 566 bracket->first = 0; 567 bracket->last = ctx->implied_array_size - 1; 568 goto cleanup; 569 } 570 report_error( ctx, "Expected literal unsigned integer" ); 571 return FALSE; 572 } 573 bracket->first = uindex; 574 575 eat_opt_white( &ctx->cur ); 576 577 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') { 578 uint uindex; 579 580 ctx->cur += 2; 581 eat_opt_white( &ctx->cur ); 582 if (!parse_uint( &ctx->cur, &uindex )) { 583 report_error( ctx, "Expected literal integer" ); 584 return FALSE; 585 } 586 bracket->last = (int) uindex; 587 eat_opt_white( &ctx->cur ); 588 } 589 else { 590 bracket->last = bracket->first; 591 } 592 593cleanup: 594 if (*ctx->cur != ']') { 595 report_error( ctx, "Expected `]' or `..'" ); 596 return FALSE; 597 } 598 ctx->cur++; 599 return TRUE; 600} 601 602/* Parse register declaration. 603 * <register_dcl> ::= <register_file_bracket_index> `]' | 604 * <register_file_bracket_index> `..' <index> `]' 605 */ 606static boolean 607parse_register_dcl( 608 struct translate_ctx *ctx, 609 uint *file, 610 struct parsed_dcl_bracket *brackets, 611 int *num_brackets) 612{ 613 const char *cur; 614 615 *num_brackets = 0; 616 617 if (!parse_register_file_bracket( ctx, file )) 618 return FALSE; 619 if (!parse_register_dcl_bracket( ctx, &brackets[0] )) 620 return FALSE; 621 622 *num_brackets = 1; 623 624 cur = ctx->cur; 625 eat_opt_white( &cur ); 626 627 if (cur[0] == '[') { 628 ++cur; 629 ctx->cur = cur; 630 if (!parse_register_dcl_bracket( ctx, &brackets[1] )) 631 return FALSE; 632 /* for geometry shader we don't really care about 633 * the first brackets it's always the size of the 634 * input primitive. so we want to declare just 635 * the index relevant to the semantics which is in 636 * the second bracket */ 637 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) { 638 brackets[0] = brackets[1]; 639 *num_brackets = 1; 640 } else { 641 *num_brackets = 2; 642 } 643 } 644 645 return TRUE; 646} 647 648 649/* Parse destination register operand.*/ 650static boolean 651parse_register_dst( 652 struct translate_ctx *ctx, 653 uint *file, 654 struct parsed_bracket *brackets) 655{ 656 brackets->ind_comp = TGSI_SWIZZLE_X; 657 if (!parse_register_file_bracket( ctx, file )) 658 return FALSE; 659 if (!parse_register_bracket( ctx, brackets )) 660 return FALSE; 661 662 return TRUE; 663} 664 665static boolean 666parse_dst_operand( 667 struct translate_ctx *ctx, 668 struct tgsi_full_dst_register *dst ) 669{ 670 uint file; 671 uint writemask; 672 const char *cur; 673 struct parsed_bracket bracket[2]; 674 int parsed_opt_brackets; 675 676 if (!parse_register_dst( ctx, &file, &bracket[0] )) 677 return FALSE; 678 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 679 return FALSE; 680 681 cur = ctx->cur; 682 eat_opt_white( &cur ); 683 684 if (!parse_opt_writemask( ctx, &writemask )) 685 return FALSE; 686 687 dst->Register.File = file; 688 if (parsed_opt_brackets) { 689 dst->Register.Dimension = 1; 690 dst->Dimension.Indirect = 0; 691 dst->Dimension.Dimension = 0; 692 dst->Dimension.Index = bracket[0].index; 693 bracket[0] = bracket[1]; 694 } 695 dst->Register.Index = bracket[0].index; 696 dst->Register.WriteMask = writemask; 697 if (bracket[0].ind_file != TGSI_FILE_NULL) { 698 dst->Register.Indirect = 1; 699 dst->Indirect.File = bracket[0].ind_file; 700 dst->Indirect.Index = bracket[0].ind_index; 701 dst->Indirect.SwizzleX = bracket[0].ind_comp; 702 dst->Indirect.SwizzleY = bracket[0].ind_comp; 703 dst->Indirect.SwizzleZ = bracket[0].ind_comp; 704 dst->Indirect.SwizzleW = bracket[0].ind_comp; 705 } 706 return TRUE; 707} 708 709static boolean 710parse_optional_swizzle( 711 struct translate_ctx *ctx, 712 uint swizzle[4], 713 boolean *parsed_swizzle ) 714{ 715 const char *cur = ctx->cur; 716 717 *parsed_swizzle = FALSE; 718 719 eat_opt_white( &cur ); 720 if (*cur == '.') { 721 uint i; 722 723 cur++; 724 eat_opt_white( &cur ); 725 for (i = 0; i < 4; i++) { 726 if (uprcase( *cur ) == 'X') 727 swizzle[i] = TGSI_SWIZZLE_X; 728 else if (uprcase( *cur ) == 'Y') 729 swizzle[i] = TGSI_SWIZZLE_Y; 730 else if (uprcase( *cur ) == 'Z') 731 swizzle[i] = TGSI_SWIZZLE_Z; 732 else if (uprcase( *cur ) == 'W') 733 swizzle[i] = TGSI_SWIZZLE_W; 734 else { 735 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" ); 736 return FALSE; 737 } 738 cur++; 739 } 740 *parsed_swizzle = TRUE; 741 ctx->cur = cur; 742 } 743 return TRUE; 744} 745 746static boolean 747parse_src_operand( 748 struct translate_ctx *ctx, 749 struct tgsi_full_src_register *src ) 750{ 751 uint file; 752 uint swizzle[4]; 753 boolean parsed_swizzle; 754 struct parsed_bracket bracket[2]; 755 int parsed_opt_brackets; 756 757 if (*ctx->cur == '-') { 758 ctx->cur++; 759 eat_opt_white( &ctx->cur ); 760 src->Register.Negate = 1; 761 } 762 763 if (*ctx->cur == '|') { 764 ctx->cur++; 765 eat_opt_white( &ctx->cur ); 766 src->Register.Absolute = 1; 767 } 768 769 if (!parse_register_src(ctx, &file, &bracket[0])) 770 return FALSE; 771 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 772 return FALSE; 773 774 src->Register.File = file; 775 if (parsed_opt_brackets) { 776 src->Register.Dimension = 1; 777 src->Dimension.Indirect = 0; 778 src->Dimension.Dimension = 0; 779 src->Dimension.Index = bracket[0].index; 780 bracket[0] = bracket[1]; 781 } 782 src->Register.Index = bracket[0].index; 783 if (bracket[0].ind_file != TGSI_FILE_NULL) { 784 src->Register.Indirect = 1; 785 src->Indirect.File = bracket[0].ind_file; 786 src->Indirect.Index = bracket[0].ind_index; 787 src->Indirect.SwizzleX = bracket[0].ind_comp; 788 src->Indirect.SwizzleY = bracket[0].ind_comp; 789 src->Indirect.SwizzleZ = bracket[0].ind_comp; 790 src->Indirect.SwizzleW = bracket[0].ind_comp; 791 } 792 793 /* Parse optional swizzle. 794 */ 795 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) { 796 if (parsed_swizzle) { 797 src->Register.SwizzleX = swizzle[0]; 798 src->Register.SwizzleY = swizzle[1]; 799 src->Register.SwizzleZ = swizzle[2]; 800 src->Register.SwizzleW = swizzle[3]; 801 } 802 } 803 804 if (src->Register.Absolute) { 805 eat_opt_white( &ctx->cur ); 806 if (*ctx->cur != '|') { 807 report_error( ctx, "Expected `|'" ); 808 return FALSE; 809 } 810 ctx->cur++; 811 } 812 813 814 return TRUE; 815} 816 817static const char *texture_names[TGSI_TEXTURE_COUNT] = 818{ 819 "UNKNOWN", 820 "1D", 821 "2D", 822 "3D", 823 "CUBE", 824 "RECT", 825 "SHADOW1D", 826 "SHADOW2D", 827 "SHADOWRECT" 828}; 829 830static boolean 831match_inst_mnemonic(const char **pcur, 832 const struct tgsi_opcode_info *info) 833{ 834 if (str_match_no_case(pcur, info->mnemonic)) { 835 return TRUE; 836 } 837 return FALSE; 838} 839 840static boolean 841parse_instruction( 842 struct translate_ctx *ctx, 843 boolean has_label ) 844{ 845 uint i; 846 uint saturate = TGSI_SAT_NONE; 847 const struct tgsi_opcode_info *info; 848 struct tgsi_full_instruction inst; 849 uint advance; 850 851 inst = tgsi_default_full_instruction(); 852 853 /* Parse predicate. 854 */ 855 eat_opt_white( &ctx->cur ); 856 if (*ctx->cur == '(') { 857 uint file; 858 int index; 859 uint swizzle[4]; 860 boolean parsed_swizzle; 861 862 inst.Instruction.Predicate = 1; 863 864 ctx->cur++; 865 if (*ctx->cur == '!') { 866 ctx->cur++; 867 inst.Predicate.Negate = 1; 868 } 869 870 if (!parse_register_1d( ctx, &file, &index )) 871 return FALSE; 872 873 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) { 874 if (parsed_swizzle) { 875 inst.Predicate.SwizzleX = swizzle[0]; 876 inst.Predicate.SwizzleY = swizzle[1]; 877 inst.Predicate.SwizzleZ = swizzle[2]; 878 inst.Predicate.SwizzleW = swizzle[3]; 879 } 880 } 881 882 if (*ctx->cur != ')') { 883 report_error( ctx, "Expected `)'" ); 884 return FALSE; 885 } 886 887 ctx->cur++; 888 } 889 890 /* Parse instruction name. 891 */ 892 eat_opt_white( &ctx->cur ); 893 for (i = 0; i < TGSI_OPCODE_LAST; i++) { 894 const char *cur = ctx->cur; 895 896 info = tgsi_get_opcode_info( i ); 897 if (match_inst_mnemonic(&cur, info)) { 898 if (str_match_no_case( &cur, "_SATNV" )) 899 saturate = TGSI_SAT_MINUS_PLUS_ONE; 900 else if (str_match_no_case( &cur, "_SAT" )) 901 saturate = TGSI_SAT_ZERO_ONE; 902 903 if (info->num_dst + info->num_src + info->is_tex == 0) { 904 if (!is_digit_alpha_underscore( cur )) { 905 ctx->cur = cur; 906 break; 907 } 908 } 909 else if (*cur == '\0' || eat_white( &cur )) { 910 ctx->cur = cur; 911 break; 912 } 913 } 914 } 915 if (i == TGSI_OPCODE_LAST) { 916 if (has_label) 917 report_error( ctx, "Unknown opcode" ); 918 else 919 report_error( ctx, "Expected `DCL', `IMM' or a label" ); 920 return FALSE; 921 } 922 923 inst.Instruction.Opcode = i; 924 inst.Instruction.Saturate = saturate; 925 inst.Instruction.NumDstRegs = info->num_dst; 926 inst.Instruction.NumSrcRegs = info->num_src; 927 928 /* Parse instruction operands. 929 */ 930 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { 931 if (i > 0) { 932 eat_opt_white( &ctx->cur ); 933 if (*ctx->cur != ',') { 934 report_error( ctx, "Expected `,'" ); 935 return FALSE; 936 } 937 ctx->cur++; 938 eat_opt_white( &ctx->cur ); 939 } 940 941 if (i < info->num_dst) { 942 if (!parse_dst_operand( ctx, &inst.Dst[i] )) 943 return FALSE; 944 } 945 else if (i < info->num_dst + info->num_src) { 946 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) 947 return FALSE; 948 } 949 else { 950 uint j; 951 952 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { 953 if (str_match_no_case( &ctx->cur, texture_names[j] )) { 954 if (!is_digit_alpha_underscore( ctx->cur )) { 955 inst.Instruction.Texture = 1; 956 inst.Texture.Texture = j; 957 break; 958 } 959 } 960 } 961 if (j == TGSI_TEXTURE_COUNT) { 962 report_error( ctx, "Expected texture target" ); 963 return FALSE; 964 } 965 } 966 } 967 968 if (info->is_branch) { 969 uint target; 970 971 eat_opt_white( &ctx->cur ); 972 if (*ctx->cur != ':') { 973 report_error( ctx, "Expected `:'" ); 974 return FALSE; 975 } 976 ctx->cur++; 977 eat_opt_white( &ctx->cur ); 978 if (!parse_uint( &ctx->cur, &target )) { 979 report_error( ctx, "Expected a label" ); 980 return FALSE; 981 } 982 inst.Instruction.Label = 1; 983 inst.Label.Label = target; 984 } 985 986 advance = tgsi_build_full_instruction( 987 &inst, 988 ctx->tokens_cur, 989 ctx->header, 990 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 991 if (advance == 0) 992 return FALSE; 993 ctx->tokens_cur += advance; 994 995 return TRUE; 996} 997 998static const char *semantic_names[TGSI_SEMANTIC_COUNT] = 999{ 1000 "POSITION", 1001 "COLOR", 1002 "BCOLOR", 1003 "FOG", 1004 "PSIZE", 1005 "GENERIC", 1006 "NORMAL", 1007 "FACE", 1008 "EDGEFLAG", 1009 "PRIM_ID", 1010 "INSTANCEID", 1011 "STENCIL" 1012}; 1013 1014static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] = 1015{ 1016 "CONSTANT", 1017 "LINEAR", 1018 "PERSPECTIVE" 1019}; 1020 1021 1022/* parses a 4-touple of the form {x, y, z, w} 1023 * where x, y, z, w are numbers */ 1024static boolean parse_immediate_data(struct translate_ctx *ctx, 1025 float *values) 1026{ 1027 unsigned i; 1028 1029 eat_opt_white( &ctx->cur ); 1030 if (*ctx->cur != '{') { 1031 report_error( ctx, "Expected `{'" ); 1032 return FALSE; 1033 } 1034 ctx->cur++; 1035 for (i = 0; i < 4; i++) { 1036 eat_opt_white( &ctx->cur ); 1037 if (i > 0) { 1038 if (*ctx->cur != ',') { 1039 report_error( ctx, "Expected `,'" ); 1040 return FALSE; 1041 } 1042 ctx->cur++; 1043 eat_opt_white( &ctx->cur ); 1044 } 1045 if (!parse_float( &ctx->cur, &values[i] )) { 1046 report_error( ctx, "Expected literal floating point" ); 1047 return FALSE; 1048 } 1049 } 1050 eat_opt_white( &ctx->cur ); 1051 if (*ctx->cur != '}') { 1052 report_error( ctx, "Expected `}'" ); 1053 return FALSE; 1054 } 1055 ctx->cur++; 1056 1057 return TRUE; 1058} 1059 1060static boolean parse_declaration( struct translate_ctx *ctx ) 1061{ 1062 struct tgsi_full_declaration decl; 1063 uint file; 1064 struct parsed_dcl_bracket brackets[2]; 1065 int num_brackets; 1066 uint writemask; 1067 const char *cur; 1068 uint advance; 1069 boolean is_vs_input; 1070 boolean is_imm_array; 1071 1072 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT); 1073 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT); 1074 1075 if (!eat_white( &ctx->cur )) { 1076 report_error( ctx, "Syntax error" ); 1077 return FALSE; 1078 } 1079 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) 1080 return FALSE; 1081 if (!parse_opt_writemask( ctx, &writemask )) 1082 return FALSE; 1083 1084 decl = tgsi_default_full_declaration(); 1085 decl.Declaration.File = file; 1086 decl.Declaration.UsageMask = writemask; 1087 1088 if (num_brackets == 1) { 1089 decl.Range.First = brackets[0].first; 1090 decl.Range.Last = brackets[0].last; 1091 } else { 1092 decl.Range.First = brackets[1].first; 1093 decl.Range.Last = brackets[1].last; 1094 1095 decl.Declaration.Dimension = 1; 1096 decl.Dim.Index2D = brackets[0].first; 1097 } 1098 1099 is_vs_input = (file == TGSI_FILE_INPUT && 1100 ctx->processor == TGSI_PROCESSOR_VERTEX); 1101 is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY); 1102 1103 cur = ctx->cur; 1104 eat_opt_white( &cur ); 1105 if (*cur == ',' && !is_vs_input) { 1106 uint i; 1107 1108 cur++; 1109 eat_opt_white( &cur ); 1110 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { 1111 if (str_match_no_case( &cur, semantic_names[i] )) { 1112 const char *cur2 = cur; 1113 uint index; 1114 1115 if (is_digit_alpha_underscore( cur )) 1116 continue; 1117 eat_opt_white( &cur2 ); 1118 if (*cur2 == '[') { 1119 cur2++; 1120 eat_opt_white( &cur2 ); 1121 if (!parse_uint( &cur2, &index )) { 1122 report_error( ctx, "Expected literal integer" ); 1123 return FALSE; 1124 } 1125 eat_opt_white( &cur2 ); 1126 if (*cur2 != ']') { 1127 report_error( ctx, "Expected `]'" ); 1128 return FALSE; 1129 } 1130 cur2++; 1131 1132 decl.Semantic.Index = index; 1133 1134 cur = cur2; 1135 } 1136 1137 decl.Declaration.Semantic = 1; 1138 decl.Semantic.Name = i; 1139 1140 ctx->cur = cur; 1141 break; 1142 } 1143 } 1144 } else if (is_imm_array) { 1145 unsigned i; 1146 float *vals_itr; 1147 /* we have our immediate data */ 1148 if (*cur != '{') { 1149 report_error( ctx, "Immediate array without data" ); 1150 return FALSE; 1151 } 1152 ++cur; 1153 ctx->cur = cur; 1154 1155 decl.ImmediateData.u = 1156 MALLOC(sizeof(union tgsi_immediate_data) * 4 * 1157 (decl.Range.Last + 1)); 1158 vals_itr = (float*)decl.ImmediateData.u; 1159 for (i = 0; i <= decl.Range.Last; ++i) { 1160 if (!parse_immediate_data(ctx, vals_itr)) { 1161 FREE(decl.ImmediateData.u); 1162 return FALSE; 1163 } 1164 vals_itr += 4; 1165 eat_opt_white( &ctx->cur ); 1166 if (*ctx->cur != ',') { 1167 if (i != decl.Range.Last) { 1168 report_error( ctx, "Not enough data in immediate array!" ); 1169 FREE(decl.ImmediateData.u); 1170 return FALSE; 1171 } 1172 } else 1173 ++ctx->cur; 1174 } 1175 eat_opt_white( &ctx->cur ); 1176 if (*ctx->cur != '}') { 1177 FREE(decl.ImmediateData.u); 1178 report_error( ctx, "Immediate array data missing closing '}'" ); 1179 return FALSE; 1180 } 1181 ++ctx->cur; 1182 } 1183 1184 cur = ctx->cur; 1185 eat_opt_white( &cur ); 1186 if (*cur == ',' && !is_vs_input) { 1187 uint i; 1188 1189 cur++; 1190 eat_opt_white( &cur ); 1191 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { 1192 if (str_match_no_case( &cur, interpolate_names[i] )) { 1193 if (is_digit_alpha_underscore( cur )) 1194 continue; 1195 decl.Declaration.Interpolate = i; 1196 1197 ctx->cur = cur; 1198 break; 1199 } 1200 } 1201 if (i == TGSI_INTERPOLATE_COUNT) { 1202 report_error( ctx, "Expected semantic or interpolate attribute" ); 1203 return FALSE; 1204 } 1205 } 1206 1207 advance = tgsi_build_full_declaration( 1208 &decl, 1209 ctx->tokens_cur, 1210 ctx->header, 1211 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1212 1213 if (is_imm_array) 1214 FREE(decl.ImmediateData.u); 1215 1216 if (advance == 0) 1217 return FALSE; 1218 ctx->tokens_cur += advance; 1219 1220 return TRUE; 1221} 1222 1223static boolean parse_immediate( struct translate_ctx *ctx ) 1224{ 1225 struct tgsi_full_immediate imm; 1226 float values[4]; 1227 uint advance; 1228 1229 if (!eat_white( &ctx->cur )) { 1230 report_error( ctx, "Syntax error" ); 1231 return FALSE; 1232 } 1233 if (!str_match_no_case( &ctx->cur, "FLT32" ) || 1234 is_digit_alpha_underscore( ctx->cur )) { 1235 report_error( ctx, "Expected `FLT32'" ); 1236 return FALSE; 1237 } 1238 1239 parse_immediate_data(ctx, values); 1240 1241 imm = tgsi_default_full_immediate(); 1242 imm.Immediate.NrTokens += 4; 1243 imm.Immediate.DataType = TGSI_IMM_FLOAT32; 1244 imm.u[0].Float = values[0]; 1245 imm.u[1].Float = values[1]; 1246 imm.u[2].Float = values[2]; 1247 imm.u[3].Float = values[3]; 1248 1249 advance = tgsi_build_full_immediate( 1250 &imm, 1251 ctx->tokens_cur, 1252 ctx->header, 1253 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1254 if (advance == 0) 1255 return FALSE; 1256 ctx->tokens_cur += advance; 1257 1258 return TRUE; 1259} 1260 1261static const char *property_names[] = 1262{ 1263 "GS_INPUT_PRIMITIVE", 1264 "GS_OUTPUT_PRIMITIVE", 1265 "GS_MAX_OUTPUT_VERTICES", 1266 "FS_COORD_ORIGIN", 1267 "FS_COORD_PIXEL_CENTER" 1268}; 1269 1270static const char *primitive_names[] = 1271{ 1272 "POINTS", 1273 "LINES", 1274 "LINE_LOOP", 1275 "LINE_STRIP", 1276 "TRIANGLES", 1277 "TRIANGLE_STRIP", 1278 "TRIANGLE_FAN", 1279 "QUADS", 1280 "QUAD_STRIP", 1281 "POLYGON" 1282}; 1283 1284static const char *fs_coord_origin_names[] = 1285{ 1286 "UPPER_LEFT", 1287 "LOWER_LEFT" 1288}; 1289 1290static const char *fs_coord_pixel_center_names[] = 1291{ 1292 "HALF_INTEGER", 1293 "INTEGER" 1294}; 1295 1296 1297static boolean 1298parse_primitive( const char **pcur, uint *primitive ) 1299{ 1300 uint i; 1301 1302 for (i = 0; i < PIPE_PRIM_MAX; i++) { 1303 const char *cur = *pcur; 1304 1305 if (str_match_no_case( &cur, primitive_names[i])) { 1306 *primitive = i; 1307 *pcur = cur; 1308 return TRUE; 1309 } 1310 } 1311 return FALSE; 1312} 1313 1314static boolean 1315parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) 1316{ 1317 uint i; 1318 1319 for (i = 0; i < sizeof(fs_coord_origin_names) / sizeof(fs_coord_origin_names[0]); i++) { 1320 const char *cur = *pcur; 1321 1322 if (str_match_no_case( &cur, fs_coord_origin_names[i])) { 1323 *fs_coord_origin = i; 1324 *pcur = cur; 1325 return TRUE; 1326 } 1327 } 1328 return FALSE; 1329} 1330 1331static boolean 1332parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) 1333{ 1334 uint i; 1335 1336 for (i = 0; i < sizeof(fs_coord_pixel_center_names) / sizeof(fs_coord_pixel_center_names[0]); i++) { 1337 const char *cur = *pcur; 1338 1339 if (str_match_no_case( &cur, fs_coord_pixel_center_names[i])) { 1340 *fs_coord_pixel_center = i; 1341 *pcur = cur; 1342 return TRUE; 1343 } 1344 } 1345 return FALSE; 1346} 1347 1348 1349static boolean parse_property( struct translate_ctx *ctx ) 1350{ 1351 struct tgsi_full_property prop; 1352 uint property_name; 1353 uint values[8]; 1354 uint advance; 1355 char id[64]; 1356 1357 if (!eat_white( &ctx->cur )) { 1358 report_error( ctx, "Syntax error" ); 1359 return FALSE; 1360 } 1361 if (!parse_identifier( &ctx->cur, id )) { 1362 report_error( ctx, "Syntax error" ); 1363 return FALSE; 1364 } 1365 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; 1366 ++property_name) { 1367 if (streq_nocase_uprcase(property_names[property_name], id)) { 1368 break; 1369 } 1370 } 1371 if (property_name >= TGSI_PROPERTY_COUNT) { 1372 debug_printf( "\nError: Unknown property : '%s'", id ); 1373 return FALSE; 1374 } 1375 1376 eat_opt_white( &ctx->cur ); 1377 switch(property_name) { 1378 case TGSI_PROPERTY_GS_INPUT_PRIM: 1379 case TGSI_PROPERTY_GS_OUTPUT_PRIM: 1380 if (!parse_primitive(&ctx->cur, &values[0] )) { 1381 report_error( ctx, "Unknown primitive name as property!" ); 1382 return FALSE; 1383 } 1384 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && 1385 ctx->processor == TGSI_PROCESSOR_GEOMETRY) { 1386 ctx->implied_array_size = u_vertices_per_prim(values[0]); 1387 } 1388 break; 1389 case TGSI_PROPERTY_FS_COORD_ORIGIN: 1390 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { 1391 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); 1392 return FALSE; 1393 } 1394 break; 1395 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: 1396 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { 1397 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); 1398 return FALSE; 1399 } 1400 break; 1401 default: 1402 if (!parse_uint(&ctx->cur, &values[0] )) { 1403 report_error( ctx, "Expected unsigned integer as property!" ); 1404 return FALSE; 1405 } 1406 } 1407 1408 prop = tgsi_default_full_property(); 1409 prop.Property.PropertyName = property_name; 1410 prop.Property.NrTokens += 1; 1411 prop.u[0].Data = values[0]; 1412 1413 advance = tgsi_build_full_property( 1414 &prop, 1415 ctx->tokens_cur, 1416 ctx->header, 1417 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1418 if (advance == 0) 1419 return FALSE; 1420 ctx->tokens_cur += advance; 1421 1422 return TRUE; 1423} 1424 1425 1426static boolean translate( struct translate_ctx *ctx ) 1427{ 1428 eat_opt_white( &ctx->cur ); 1429 if (!parse_header( ctx )) 1430 return FALSE; 1431 1432 while (*ctx->cur != '\0') { 1433 uint label_val = 0; 1434 if (!eat_white( &ctx->cur )) { 1435 report_error( ctx, "Syntax error" ); 1436 return FALSE; 1437 } 1438 1439 if (*ctx->cur == '\0') 1440 break; 1441 if (parse_label( ctx, &label_val )) { 1442 if (!parse_instruction( ctx, TRUE )) 1443 return FALSE; 1444 } 1445 else if (str_match_no_case( &ctx->cur, "DCL" )) { 1446 if (!parse_declaration( ctx )) 1447 return FALSE; 1448 } 1449 else if (str_match_no_case( &ctx->cur, "IMM" )) { 1450 if (!parse_immediate( ctx )) 1451 return FALSE; 1452 } 1453 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) { 1454 if (!parse_property( ctx )) 1455 return FALSE; 1456 } 1457 else if (!parse_instruction( ctx, FALSE )) { 1458 return FALSE; 1459 } 1460 } 1461 1462 return TRUE; 1463} 1464 1465boolean 1466tgsi_text_translate( 1467 const char *text, 1468 struct tgsi_token *tokens, 1469 uint num_tokens ) 1470{ 1471 struct translate_ctx ctx; 1472 1473 ctx.text = text; 1474 ctx.cur = text; 1475 ctx.tokens = tokens; 1476 ctx.tokens_cur = tokens; 1477 ctx.tokens_end = tokens + num_tokens; 1478 1479 if (!translate( &ctx )) 1480 return FALSE; 1481 1482 return tgsi_sanity_check( tokens ); 1483} 1484