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