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 42 static boolean is_alpha_underscore( const char *cur ) 43 { 44 return 45 (*cur >= 'a' && *cur <= 'z') || 46 (*cur >= 'A' && *cur <= 'Z') || 47 *cur == '_'; 48 } 49 50 static boolean is_digit( const char *cur ) 51 { 52 return *cur >= '0' && *cur <= '9'; 53 } 54 55 static boolean is_digit_alpha_underscore( const char *cur ) 56 { 57 return is_digit( cur ) || is_alpha_underscore( cur ); 58 } 59 60 static 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 */ 71 static int 72 streq_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 */ 89 static 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 */ 110 static 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 /* Return the array index that matches starting at *pcur, where the string at 123 * *pcur is terminated by a non-digit non-letter non-underscore. 124 * Returns -1 if no match is found. 125 * 126 * On success, the pointer to the first string is moved to the end of the read 127 * word. 128 */ 129 static int str_match_name_from_array(const char **pcur, 130 const char * const *array, 131 unsigned array_size) 132 { 133 for (unsigned j = 0; j < array_size; ++j) { 134 if (str_match_nocase_whole(pcur, array[j])) 135 return j; 136 } 137 return -1; 138 } 139 140 /* Return the format corresponding to the name at *pcur. 141 * Returns -1 if there is no format name. 142 * 143 * On success, the pointer to the string is moved to the end of the read format 144 * name. 145 */ 146 static int str_match_format(const char **pcur) 147 { 148 for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) { 149 const struct util_format_description *desc = 150 util_format_description(i); 151 if (desc && str_match_nocase_whole(pcur, desc->name)) { 152 return i; 153 } 154 } 155 return -1; 156 } 157 158 /* Eat zero or more whitespaces. 159 */ 160 static void eat_opt_white( const char **pcur ) 161 { 162 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n') 163 (*pcur)++; 164 } 165 166 /* Eat one or more whitespaces. 167 * Return TRUE if at least one whitespace eaten. 168 */ 169 static boolean eat_white( const char **pcur ) 170 { 171 const char *cur = *pcur; 172 173 eat_opt_white( pcur ); 174 return *pcur > cur; 175 } 176 177 /* Parse unsigned integer. 178 * No checks for overflow. 179 */ 180 static boolean parse_uint( const char **pcur, uint *val ) 181 { 182 const char *cur = *pcur; 183 184 if (is_digit( cur )) { 185 *val = *cur++ - '0'; 186 while (is_digit( cur )) 187 *val = *val * 10 + *cur++ - '0'; 188 *pcur = cur; 189 return TRUE; 190 } 191 return FALSE; 192 } 193 194 static boolean parse_int( const char **pcur, int *val ) 195 { 196 const char *cur = *pcur; 197 int sign = (*cur == '-' ? -1 : 1); 198 199 if (*cur == '+' || *cur == '-') 200 cur++; 201 202 if (parse_uint(&cur, (uint *)val)) { 203 *val *= sign; 204 *pcur = cur; 205 return TRUE; 206 } 207 208 return FALSE; 209 } 210 211 static boolean parse_identifier( const char **pcur, char *ret, size_t len ) 212 { 213 const char *cur = *pcur; 214 int i = 0; 215 if (is_alpha_underscore( cur )) { 216 ret[i++] = *cur++; 217 while (is_alpha_underscore( cur ) || is_digit( cur )) { 218 if (i == len - 1) 219 return FALSE; 220 ret[i++] = *cur++; 221 } 222 ret[i++] = '\0'; 223 *pcur = cur; 224 return TRUE; 225 } 226 return FALSE; 227 } 228 229 /* Parse floating point. 230 */ 231 static boolean parse_float( const char **pcur, float *val ) 232 { 233 const char *cur = *pcur; 234 boolean integral_part = FALSE; 235 boolean fractional_part = FALSE; 236 237 if (*cur == '0' && *(cur + 1) == 'x') { 238 union fi fi; 239 fi.ui = strtoul(cur, NULL, 16); 240 *val = fi.f; 241 cur += 10; 242 goto out; 243 } 244 245 *val = (float) atof( cur ); 246 if (*cur == '-' || *cur == '+') 247 cur++; 248 if (is_digit( cur )) { 249 cur++; 250 integral_part = TRUE; 251 while (is_digit( cur )) 252 cur++; 253 } 254 if (*cur == '.') { 255 cur++; 256 if (is_digit( cur )) { 257 cur++; 258 fractional_part = TRUE; 259 while (is_digit( cur )) 260 cur++; 261 } 262 } 263 if (!integral_part && !fractional_part) 264 return FALSE; 265 if (uprcase( *cur ) == 'E') { 266 cur++; 267 if (*cur == '-' || *cur == '+') 268 cur++; 269 if (is_digit( cur )) { 270 cur++; 271 while (is_digit( cur )) 272 cur++; 273 } 274 else 275 return FALSE; 276 } 277 278 out: 279 *pcur = cur; 280 return TRUE; 281 } 282 283 static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1) 284 { 285 const char *cur = *pcur; 286 union { 287 double dval; 288 uint32_t uval[2]; 289 } v; 290 291 v.dval = strtod(cur, (char**)pcur); 292 if (*pcur == cur) 293 return FALSE; 294 295 *val0 = v.uval[0]; 296 *val1 = v.uval[1]; 297 298 return TRUE; 299 } 300 301 static boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1) 302 { 303 const char *cur = *pcur; 304 union { 305 int64_t i64val; 306 uint32_t uval[2]; 307 } v; 308 309 v.i64val = strtoll(cur, (char**)pcur, 0); 310 if (*pcur == cur) 311 return FALSE; 312 313 *val0 = v.uval[0]; 314 *val1 = v.uval[1]; 315 316 return TRUE; 317 } 318 319 static boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1) 320 { 321 const char *cur = *pcur; 322 union { 323 uint64_t u64val; 324 uint32_t uval[2]; 325 } v; 326 327 v.u64val = strtoull(cur, (char**)pcur, 0); 328 if (*pcur == cur) 329 return FALSE; 330 331 *val0 = v.uval[0]; 332 *val1 = v.uval[1]; 333 334 return TRUE; 335 } 336 337 struct translate_ctx 338 { 339 const char *text; 340 const char *cur; 341 struct tgsi_token *tokens; 342 struct tgsi_token *tokens_cur; 343 struct tgsi_token *tokens_end; 344 struct tgsi_header *header; 345 unsigned processor : 4; 346 unsigned implied_array_size : 6; 347 unsigned num_immediates; 348 }; 349 350 static void report_error( struct translate_ctx *ctx, const char *msg ) 351 { 352 int line = 1; 353 int column = 1; 354 const char *itr = ctx->text; 355 356 while (itr != ctx->cur) { 357 if (*itr == '\n') { 358 column = 1; 359 ++line; 360 } 361 ++column; 362 ++itr; 363 } 364 365 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column ); 366 } 367 368 /* Parse shader header. 369 * Return TRUE for one of the following headers. 370 * FRAG 371 * GEOM 372 * VERT 373 */ 374 static boolean parse_header( struct translate_ctx *ctx ) 375 { 376 uint processor; 377 378 if (str_match_nocase_whole( &ctx->cur, "FRAG" )) 379 processor = PIPE_SHADER_FRAGMENT; 380 else if (str_match_nocase_whole( &ctx->cur, "VERT" )) 381 processor = PIPE_SHADER_VERTEX; 382 else if (str_match_nocase_whole( &ctx->cur, "GEOM" )) 383 processor = PIPE_SHADER_GEOMETRY; 384 else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" )) 385 processor = PIPE_SHADER_TESS_CTRL; 386 else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" )) 387 processor = PIPE_SHADER_TESS_EVAL; 388 else if (str_match_nocase_whole( &ctx->cur, "COMP" )) 389 processor = PIPE_SHADER_COMPUTE; 390 else { 391 report_error( ctx, "Unknown header" ); 392 return FALSE; 393 } 394 395 if (ctx->tokens_cur >= ctx->tokens_end) 396 return FALSE; 397 ctx->header = (struct tgsi_header *) ctx->tokens_cur++; 398 *ctx->header = tgsi_build_header(); 399 400 if (ctx->tokens_cur >= ctx->tokens_end) 401 return FALSE; 402 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header ); 403 ctx->processor = processor; 404 405 return TRUE; 406 } 407 408 static boolean parse_label( struct translate_ctx *ctx, uint *val ) 409 { 410 const char *cur = ctx->cur; 411 412 if (parse_uint( &cur, val )) { 413 eat_opt_white( &cur ); 414 if (*cur == ':') { 415 cur++; 416 ctx->cur = cur; 417 return TRUE; 418 } 419 } 420 return FALSE; 421 } 422 423 static boolean 424 parse_file( const char **pcur, uint *file ) 425 { 426 uint i; 427 428 for (i = 0; i < TGSI_FILE_COUNT; i++) { 429 const char *cur = *pcur; 430 431 if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) { 432 *pcur = cur; 433 *file = i; 434 return TRUE; 435 } 436 } 437 return FALSE; 438 } 439 440 static boolean 441 parse_opt_writemask( 442 struct translate_ctx *ctx, 443 uint *writemask ) 444 { 445 const char *cur; 446 447 cur = ctx->cur; 448 eat_opt_white( &cur ); 449 if (*cur == '.') { 450 cur++; 451 *writemask = TGSI_WRITEMASK_NONE; 452 eat_opt_white( &cur ); 453 if (uprcase( *cur ) == 'X') { 454 cur++; 455 *writemask |= TGSI_WRITEMASK_X; 456 } 457 if (uprcase( *cur ) == 'Y') { 458 cur++; 459 *writemask |= TGSI_WRITEMASK_Y; 460 } 461 if (uprcase( *cur ) == 'Z') { 462 cur++; 463 *writemask |= TGSI_WRITEMASK_Z; 464 } 465 if (uprcase( *cur ) == 'W') { 466 cur++; 467 *writemask |= TGSI_WRITEMASK_W; 468 } 469 470 if (*writemask == TGSI_WRITEMASK_NONE) { 471 report_error( ctx, "Writemask expected" ); 472 return FALSE; 473 } 474 475 ctx->cur = cur; 476 } 477 else { 478 *writemask = TGSI_WRITEMASK_XYZW; 479 } 480 return TRUE; 481 } 482 483 484 /* <register_file_bracket> ::= <file> `[' 485 */ 486 static boolean 487 parse_register_file_bracket( 488 struct translate_ctx *ctx, 489 uint *file ) 490 { 491 if (!parse_file( &ctx->cur, file )) { 492 report_error( ctx, "Unknown register file" ); 493 return FALSE; 494 } 495 eat_opt_white( &ctx->cur ); 496 if (*ctx->cur != '[') { 497 report_error( ctx, "Expected `['" ); 498 return FALSE; 499 } 500 ctx->cur++; 501 return TRUE; 502 } 503 504 /* <register_file_bracket_index> ::= <register_file_bracket> <uint> 505 */ 506 static boolean 507 parse_register_file_bracket_index( 508 struct translate_ctx *ctx, 509 uint *file, 510 int *index ) 511 { 512 uint uindex; 513 514 if (!parse_register_file_bracket( ctx, file )) 515 return FALSE; 516 eat_opt_white( &ctx->cur ); 517 if (!parse_uint( &ctx->cur, &uindex )) { 518 report_error( ctx, "Expected literal unsigned integer" ); 519 return FALSE; 520 } 521 *index = (int) uindex; 522 return TRUE; 523 } 524 525 /* Parse simple 1d register operand. 526 * <register_dst> ::= <register_file_bracket_index> `]' 527 */ 528 static boolean 529 parse_register_1d(struct translate_ctx *ctx, 530 uint *file, 531 int *index ) 532 { 533 if (!parse_register_file_bracket_index( ctx, file, index )) 534 return FALSE; 535 eat_opt_white( &ctx->cur ); 536 if (*ctx->cur != ']') { 537 report_error( ctx, "Expected `]'" ); 538 return FALSE; 539 } 540 ctx->cur++; 541 return TRUE; 542 } 543 544 struct parsed_bracket { 545 int index; 546 547 uint ind_file; 548 int ind_index; 549 uint ind_comp; 550 uint ind_array; 551 }; 552 553 554 static boolean 555 parse_register_bracket( 556 struct translate_ctx *ctx, 557 struct parsed_bracket *brackets) 558 { 559 const char *cur; 560 uint uindex; 561 562 memset(brackets, 0, sizeof(struct parsed_bracket)); 563 564 eat_opt_white( &ctx->cur ); 565 566 cur = ctx->cur; 567 if (parse_file( &cur, &brackets->ind_file )) { 568 if (!parse_register_1d( ctx, &brackets->ind_file, 569 &brackets->ind_index )) 570 return FALSE; 571 eat_opt_white( &ctx->cur ); 572 573 if (*ctx->cur == '.') { 574 ctx->cur++; 575 eat_opt_white(&ctx->cur); 576 577 switch (uprcase(*ctx->cur)) { 578 case 'X': 579 brackets->ind_comp = TGSI_SWIZZLE_X; 580 break; 581 case 'Y': 582 brackets->ind_comp = TGSI_SWIZZLE_Y; 583 break; 584 case 'Z': 585 brackets->ind_comp = TGSI_SWIZZLE_Z; 586 break; 587 case 'W': 588 brackets->ind_comp = TGSI_SWIZZLE_W; 589 break; 590 default: 591 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'"); 592 return FALSE; 593 } 594 ctx->cur++; 595 eat_opt_white(&ctx->cur); 596 } 597 598 if (*ctx->cur == '+' || *ctx->cur == '-') 599 parse_int( &ctx->cur, &brackets->index ); 600 else 601 brackets->index = 0; 602 } 603 else { 604 if (!parse_uint( &ctx->cur, &uindex )) { 605 report_error( ctx, "Expected literal unsigned integer" ); 606 return FALSE; 607 } 608 brackets->index = (int) uindex; 609 brackets->ind_file = TGSI_FILE_NULL; 610 brackets->ind_index = 0; 611 } 612 eat_opt_white( &ctx->cur ); 613 if (*ctx->cur != ']') { 614 report_error( ctx, "Expected `]'" ); 615 return FALSE; 616 } 617 ctx->cur++; 618 if (*ctx->cur == '(') { 619 ctx->cur++; 620 eat_opt_white( &ctx->cur ); 621 if (!parse_uint( &ctx->cur, &brackets->ind_array )) { 622 report_error( ctx, "Expected literal unsigned integer" ); 623 return FALSE; 624 } 625 eat_opt_white( &ctx->cur ); 626 if (*ctx->cur != ')') { 627 report_error( ctx, "Expected `)'" ); 628 return FALSE; 629 } 630 ctx->cur++; 631 } 632 return TRUE; 633 } 634 635 static boolean 636 parse_opt_register_src_bracket( 637 struct translate_ctx *ctx, 638 struct parsed_bracket *brackets, 639 int *parsed_brackets) 640 { 641 const char *cur = ctx->cur; 642 643 *parsed_brackets = 0; 644 645 eat_opt_white( &cur ); 646 if (cur[0] == '[') { 647 ++cur; 648 ctx->cur = cur; 649 650 if (!parse_register_bracket(ctx, brackets)) 651 return FALSE; 652 653 *parsed_brackets = 1; 654 } 655 656 return TRUE; 657 } 658 659 660 /* Parse source register operand. 661 * <register_src> ::= <register_file_bracket_index> `]' | 662 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' | 663 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' | 664 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]' 665 */ 666 static boolean 667 parse_register_src( 668 struct translate_ctx *ctx, 669 uint *file, 670 struct parsed_bracket *brackets) 671 { 672 brackets->ind_comp = TGSI_SWIZZLE_X; 673 if (!parse_register_file_bracket( ctx, file )) 674 return FALSE; 675 if (!parse_register_bracket( ctx, brackets )) 676 return FALSE; 677 678 return TRUE; 679 } 680 681 struct parsed_dcl_bracket { 682 uint first; 683 uint last; 684 }; 685 686 static boolean 687 parse_register_dcl_bracket( 688 struct translate_ctx *ctx, 689 struct parsed_dcl_bracket *bracket) 690 { 691 uint uindex; 692 memset(bracket, 0, sizeof(struct parsed_dcl_bracket)); 693 694 eat_opt_white( &ctx->cur ); 695 696 if (!parse_uint( &ctx->cur, &uindex )) { 697 /* it can be an empty bracket [] which means its range 698 * is from 0 to some implied size */ 699 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) { 700 bracket->first = 0; 701 bracket->last = ctx->implied_array_size - 1; 702 goto cleanup; 703 } 704 report_error( ctx, "Expected literal unsigned integer" ); 705 return FALSE; 706 } 707 bracket->first = uindex; 708 709 eat_opt_white( &ctx->cur ); 710 711 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') { 712 uint uindex; 713 714 ctx->cur += 2; 715 eat_opt_white( &ctx->cur ); 716 if (!parse_uint( &ctx->cur, &uindex )) { 717 report_error( ctx, "Expected literal integer" ); 718 return FALSE; 719 } 720 bracket->last = (int) uindex; 721 eat_opt_white( &ctx->cur ); 722 } 723 else { 724 bracket->last = bracket->first; 725 } 726 727 cleanup: 728 if (*ctx->cur != ']') { 729 report_error( ctx, "Expected `]' or `..'" ); 730 return FALSE; 731 } 732 ctx->cur++; 733 return TRUE; 734 } 735 736 /* Parse register declaration. 737 * <register_dcl> ::= <register_file_bracket_index> `]' | 738 * <register_file_bracket_index> `..' <index> `]' 739 */ 740 static boolean 741 parse_register_dcl( 742 struct translate_ctx *ctx, 743 uint *file, 744 struct parsed_dcl_bracket *brackets, 745 int *num_brackets) 746 { 747 const char *cur; 748 749 *num_brackets = 0; 750 751 if (!parse_register_file_bracket( ctx, file )) 752 return FALSE; 753 if (!parse_register_dcl_bracket( ctx, &brackets[0] )) 754 return FALSE; 755 756 *num_brackets = 1; 757 758 cur = ctx->cur; 759 eat_opt_white( &cur ); 760 761 if (cur[0] == '[') { 762 bool is_in = *file == TGSI_FILE_INPUT; 763 bool is_out = *file == TGSI_FILE_OUTPUT; 764 765 ++cur; 766 ctx->cur = cur; 767 if (!parse_register_dcl_bracket( ctx, &brackets[1] )) 768 return FALSE; 769 /* for geometry shader we don't really care about 770 * the first brackets it's always the size of the 771 * input primitive. so we want to declare just 772 * the index relevant to the semantics which is in 773 * the second bracket */ 774 775 /* tessellation has similar constraints to geometry shader */ 776 if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) || 777 (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) || 778 (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) { 779 brackets[0] = brackets[1]; 780 *num_brackets = 1; 781 } else { 782 *num_brackets = 2; 783 } 784 } 785 786 return TRUE; 787 } 788 789 790 /* Parse destination register operand.*/ 791 static boolean 792 parse_register_dst( 793 struct translate_ctx *ctx, 794 uint *file, 795 struct parsed_bracket *brackets) 796 { 797 brackets->ind_comp = TGSI_SWIZZLE_X; 798 if (!parse_register_file_bracket( ctx, file )) 799 return FALSE; 800 if (!parse_register_bracket( ctx, brackets )) 801 return FALSE; 802 803 return TRUE; 804 } 805 806 static boolean 807 parse_dst_operand( 808 struct translate_ctx *ctx, 809 struct tgsi_full_dst_register *dst ) 810 { 811 uint file; 812 uint writemask; 813 const char *cur; 814 struct parsed_bracket bracket[2]; 815 int parsed_opt_brackets; 816 817 if (!parse_register_dst( ctx, &file, &bracket[0] )) 818 return FALSE; 819 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 820 return FALSE; 821 822 cur = ctx->cur; 823 eat_opt_white( &cur ); 824 825 if (!parse_opt_writemask( ctx, &writemask )) 826 return FALSE; 827 828 dst->Register.File = file; 829 if (parsed_opt_brackets) { 830 dst->Register.Dimension = 1; 831 dst->Dimension.Indirect = 0; 832 dst->Dimension.Dimension = 0; 833 dst->Dimension.Index = bracket[0].index; 834 835 if (bracket[0].ind_file != TGSI_FILE_NULL) { 836 dst->Dimension.Indirect = 1; 837 dst->DimIndirect.File = bracket[0].ind_file; 838 dst->DimIndirect.Index = bracket[0].ind_index; 839 dst->DimIndirect.Swizzle = bracket[0].ind_comp; 840 dst->DimIndirect.ArrayID = bracket[0].ind_array; 841 } 842 bracket[0] = bracket[1]; 843 } 844 dst->Register.Index = bracket[0].index; 845 dst->Register.WriteMask = writemask; 846 if (bracket[0].ind_file != TGSI_FILE_NULL) { 847 dst->Register.Indirect = 1; 848 dst->Indirect.File = bracket[0].ind_file; 849 dst->Indirect.Index = bracket[0].ind_index; 850 dst->Indirect.Swizzle = bracket[0].ind_comp; 851 dst->Indirect.ArrayID = bracket[0].ind_array; 852 } 853 return TRUE; 854 } 855 856 static boolean 857 parse_optional_swizzle( 858 struct translate_ctx *ctx, 859 uint *swizzle, 860 boolean *parsed_swizzle, 861 int components) 862 { 863 const char *cur = ctx->cur; 864 865 *parsed_swizzle = FALSE; 866 867 eat_opt_white( &cur ); 868 if (*cur == '.') { 869 uint i; 870 871 cur++; 872 eat_opt_white( &cur ); 873 for (i = 0; i < components; i++) { 874 if (uprcase( *cur ) == 'X') 875 swizzle[i] = TGSI_SWIZZLE_X; 876 else if (uprcase( *cur ) == 'Y') 877 swizzle[i] = TGSI_SWIZZLE_Y; 878 else if (uprcase( *cur ) == 'Z') 879 swizzle[i] = TGSI_SWIZZLE_Z; 880 else if (uprcase( *cur ) == 'W') 881 swizzle[i] = TGSI_SWIZZLE_W; 882 else { 883 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" ); 884 return FALSE; 885 } 886 cur++; 887 } 888 *parsed_swizzle = TRUE; 889 ctx->cur = cur; 890 } 891 return TRUE; 892 } 893 894 static boolean 895 parse_src_operand( 896 struct translate_ctx *ctx, 897 struct tgsi_full_src_register *src ) 898 { 899 uint file; 900 uint swizzle[4]; 901 boolean parsed_swizzle; 902 struct parsed_bracket bracket[2]; 903 int parsed_opt_brackets; 904 905 if (*ctx->cur == '-') { 906 ctx->cur++; 907 eat_opt_white( &ctx->cur ); 908 src->Register.Negate = 1; 909 } 910 911 if (*ctx->cur == '|') { 912 ctx->cur++; 913 eat_opt_white( &ctx->cur ); 914 src->Register.Absolute = 1; 915 } 916 917 if (!parse_register_src(ctx, &file, &bracket[0])) 918 return FALSE; 919 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) 920 return FALSE; 921 922 src->Register.File = file; 923 if (parsed_opt_brackets) { 924 src->Register.Dimension = 1; 925 src->Dimension.Indirect = 0; 926 src->Dimension.Dimension = 0; 927 src->Dimension.Index = bracket[0].index; 928 if (bracket[0].ind_file != TGSI_FILE_NULL) { 929 src->Dimension.Indirect = 1; 930 src->DimIndirect.File = bracket[0].ind_file; 931 src->DimIndirect.Index = bracket[0].ind_index; 932 src->DimIndirect.Swizzle = bracket[0].ind_comp; 933 src->DimIndirect.ArrayID = bracket[0].ind_array; 934 } 935 bracket[0] = bracket[1]; 936 } 937 src->Register.Index = bracket[0].index; 938 if (bracket[0].ind_file != TGSI_FILE_NULL) { 939 src->Register.Indirect = 1; 940 src->Indirect.File = bracket[0].ind_file; 941 src->Indirect.Index = bracket[0].ind_index; 942 src->Indirect.Swizzle = bracket[0].ind_comp; 943 src->Indirect.ArrayID = bracket[0].ind_array; 944 } 945 946 /* Parse optional swizzle. 947 */ 948 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { 949 if (parsed_swizzle) { 950 src->Register.SwizzleX = swizzle[0]; 951 src->Register.SwizzleY = swizzle[1]; 952 src->Register.SwizzleZ = swizzle[2]; 953 src->Register.SwizzleW = swizzle[3]; 954 } 955 } 956 957 if (src->Register.Absolute) { 958 eat_opt_white( &ctx->cur ); 959 if (*ctx->cur != '|') { 960 report_error( ctx, "Expected `|'" ); 961 return FALSE; 962 } 963 ctx->cur++; 964 } 965 966 967 return TRUE; 968 } 969 970 static boolean 971 parse_texoffset_operand( 972 struct translate_ctx *ctx, 973 struct tgsi_texture_offset *src ) 974 { 975 uint file; 976 uint swizzle[3]; 977 boolean parsed_swizzle; 978 struct parsed_bracket bracket; 979 980 if (!parse_register_src(ctx, &file, &bracket)) 981 return FALSE; 982 983 src->File = file; 984 src->Index = bracket.index; 985 986 /* Parse optional swizzle. 987 */ 988 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) { 989 if (parsed_swizzle) { 990 src->SwizzleX = swizzle[0]; 991 src->SwizzleY = swizzle[1]; 992 src->SwizzleZ = swizzle[2]; 993 } 994 } 995 996 return TRUE; 997 } 998 999 static boolean 1000 match_inst(const char **pcur, 1001 unsigned *saturate, 1002 const struct tgsi_opcode_info *info) 1003 { 1004 const char *cur = *pcur; 1005 1006 /* simple case: the whole string matches the instruction name */ 1007 if (str_match_nocase_whole(&cur, info->mnemonic)) { 1008 *pcur = cur; 1009 *saturate = 0; 1010 return TRUE; 1011 } 1012 1013 if (str_match_no_case(&cur, info->mnemonic)) { 1014 /* the instruction has a suffix, figure it out */ 1015 if (str_match_nocase_whole(&cur, "_SAT")) { 1016 *pcur = cur; 1017 *saturate = 1; 1018 return TRUE; 1019 } 1020 } 1021 1022 return FALSE; 1023 } 1024 1025 static boolean 1026 parse_instruction( 1027 struct translate_ctx *ctx, 1028 boolean has_label ) 1029 { 1030 uint i; 1031 uint saturate = 0; 1032 const struct tgsi_opcode_info *info; 1033 struct tgsi_full_instruction inst; 1034 const char *cur; 1035 uint advance; 1036 1037 inst = tgsi_default_full_instruction(); 1038 1039 /* Parse predicate. 1040 */ 1041 eat_opt_white( &ctx->cur ); 1042 if (*ctx->cur == '(') { 1043 uint file; 1044 int index; 1045 uint swizzle[4]; 1046 boolean parsed_swizzle; 1047 1048 inst.Instruction.Predicate = 1; 1049 1050 ctx->cur++; 1051 if (*ctx->cur == '!') { 1052 ctx->cur++; 1053 inst.Predicate.Negate = 1; 1054 } 1055 1056 if (!parse_register_1d( ctx, &file, &index )) 1057 return FALSE; 1058 1059 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { 1060 if (parsed_swizzle) { 1061 inst.Predicate.SwizzleX = swizzle[0]; 1062 inst.Predicate.SwizzleY = swizzle[1]; 1063 inst.Predicate.SwizzleZ = swizzle[2]; 1064 inst.Predicate.SwizzleW = swizzle[3]; 1065 } 1066 } 1067 1068 if (*ctx->cur != ')') { 1069 report_error( ctx, "Expected `)'" ); 1070 return FALSE; 1071 } 1072 1073 ctx->cur++; 1074 } 1075 1076 /* Parse instruction name. 1077 */ 1078 eat_opt_white( &ctx->cur ); 1079 for (i = 0; i < TGSI_OPCODE_LAST; i++) { 1080 cur = ctx->cur; 1081 1082 info = tgsi_get_opcode_info( i ); 1083 if (match_inst(&cur, &saturate, info)) { 1084 if (info->num_dst + info->num_src + info->is_tex == 0) { 1085 ctx->cur = cur; 1086 break; 1087 } 1088 else if (*cur == '\0' || eat_white( &cur )) { 1089 ctx->cur = cur; 1090 break; 1091 } 1092 } 1093 } 1094 if (i == TGSI_OPCODE_LAST) { 1095 if (has_label) 1096 report_error( ctx, "Unknown opcode" ); 1097 else 1098 report_error( ctx, "Expected `DCL', `IMM' or a label" ); 1099 return FALSE; 1100 } 1101 1102 inst.Instruction.Opcode = i; 1103 inst.Instruction.Saturate = saturate; 1104 inst.Instruction.NumDstRegs = info->num_dst; 1105 inst.Instruction.NumSrcRegs = info->num_src; 1106 1107 if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { 1108 /* 1109 * These are not considered tex opcodes here (no additional 1110 * target argument) however we're required to set the Texture 1111 * bit so we can set the number of tex offsets. 1112 */ 1113 inst.Instruction.Texture = 1; 1114 inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; 1115 } 1116 1117 if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || 1118 i == TGSI_OPCODE_RESQ) { 1119 inst.Instruction.Memory = 1; 1120 inst.Memory.Qualifier = 0; 1121 } 1122 1123 assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); 1124 assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); 1125 1126 /* Parse instruction operands. 1127 */ 1128 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { 1129 if (i > 0) { 1130 eat_opt_white( &ctx->cur ); 1131 if (*ctx->cur != ',') { 1132 report_error( ctx, "Expected `,'" ); 1133 return FALSE; 1134 } 1135 ctx->cur++; 1136 eat_opt_white( &ctx->cur ); 1137 } 1138 1139 if (i < info->num_dst) { 1140 if (!parse_dst_operand( ctx, &inst.Dst[i] )) 1141 return FALSE; 1142 } 1143 else if (i < info->num_dst + info->num_src) { 1144 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) 1145 return FALSE; 1146 } 1147 else { 1148 uint j; 1149 1150 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { 1151 if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { 1152 inst.Instruction.Texture = 1; 1153 inst.Texture.Texture = j; 1154 break; 1155 } 1156 } 1157 if (j == TGSI_TEXTURE_COUNT) { 1158 report_error( ctx, "Expected texture target" ); 1159 return FALSE; 1160 } 1161 } 1162 } 1163 1164 cur = ctx->cur; 1165 eat_opt_white( &cur ); 1166 for (i = 0; inst.Instruction.Texture && *cur == ','; i++) { 1167 cur++; 1168 eat_opt_white( &cur ); 1169 ctx->cur = cur; 1170 if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) 1171 return FALSE; 1172 cur = ctx->cur; 1173 eat_opt_white( &cur ); 1174 } 1175 inst.Texture.NumOffsets = i; 1176 1177 cur = ctx->cur; 1178 eat_opt_white(&cur); 1179 1180 for (; inst.Instruction.Memory && *cur == ','; 1181 ctx->cur = cur, eat_opt_white(&cur)) { 1182 int j; 1183 1184 cur++; 1185 eat_opt_white(&cur); 1186 1187 j = str_match_name_from_array(&cur, tgsi_memory_names, 1188 ARRAY_SIZE(tgsi_memory_names)); 1189 if (j >= 0) { 1190 inst.Memory.Qualifier |= 1U << j; 1191 continue; 1192 } 1193 1194 j = str_match_name_from_array(&cur, tgsi_texture_names, 1195 ARRAY_SIZE(tgsi_texture_names)); 1196 if (j >= 0) { 1197 inst.Memory.Texture = j; 1198 continue; 1199 } 1200 1201 j = str_match_format(&cur); 1202 if (j >= 0) { 1203 inst.Memory.Format = j; 1204 continue; 1205 } 1206 1207 ctx->cur = cur; 1208 report_error(ctx, "Expected memory qualifier, texture target, or format\n"); 1209 return FALSE; 1210 } 1211 1212 cur = ctx->cur; 1213 eat_opt_white( &cur ); 1214 if (info->is_branch && *cur == ':') { 1215 uint target; 1216 1217 cur++; 1218 eat_opt_white( &cur ); 1219 if (!parse_uint( &cur, &target )) { 1220 report_error( ctx, "Expected a label" ); 1221 return FALSE; 1222 } 1223 inst.Instruction.Label = 1; 1224 inst.Label.Label = target; 1225 ctx->cur = cur; 1226 } 1227 1228 advance = tgsi_build_full_instruction( 1229 &inst, 1230 ctx->tokens_cur, 1231 ctx->header, 1232 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1233 if (advance == 0) 1234 return FALSE; 1235 ctx->tokens_cur += advance; 1236 1237 return TRUE; 1238 } 1239 1240 /* parses a 4-touple of the form {x, y, z, w} 1241 * where x, y, z, w are numbers */ 1242 static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type, 1243 union tgsi_immediate_data *values) 1244 { 1245 unsigned i; 1246 int ret; 1247 1248 eat_opt_white( &ctx->cur ); 1249 if (*ctx->cur != '{') { 1250 report_error( ctx, "Expected `{'" ); 1251 return FALSE; 1252 } 1253 ctx->cur++; 1254 for (i = 0; i < 4; i++) { 1255 eat_opt_white( &ctx->cur ); 1256 if (i > 0) { 1257 if (*ctx->cur != ',') { 1258 report_error( ctx, "Expected `,'" ); 1259 return FALSE; 1260 } 1261 ctx->cur++; 1262 eat_opt_white( &ctx->cur ); 1263 } 1264 1265 switch (type) { 1266 case TGSI_IMM_FLOAT64: 1267 ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1268 i++; 1269 break; 1270 case TGSI_IMM_INT64: 1271 ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1272 i++; 1273 break; 1274 case TGSI_IMM_UINT64: 1275 ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1276 i++; 1277 break; 1278 case TGSI_IMM_FLOAT32: 1279 ret = parse_float(&ctx->cur, &values[i].Float); 1280 break; 1281 case TGSI_IMM_UINT32: 1282 ret = parse_uint(&ctx->cur, &values[i].Uint); 1283 break; 1284 case TGSI_IMM_INT32: 1285 ret = parse_int(&ctx->cur, &values[i].Int); 1286 break; 1287 default: 1288 assert(0); 1289 ret = FALSE; 1290 break; 1291 } 1292 1293 if (!ret) { 1294 report_error( ctx, "Expected immediate constant" ); 1295 return FALSE; 1296 } 1297 } 1298 eat_opt_white( &ctx->cur ); 1299 if (*ctx->cur != '}') { 1300 report_error( ctx, "Expected `}'" ); 1301 return FALSE; 1302 } 1303 ctx->cur++; 1304 1305 return TRUE; 1306 } 1307 1308 static boolean parse_declaration( struct translate_ctx *ctx ) 1309 { 1310 struct tgsi_full_declaration decl; 1311 uint file; 1312 struct parsed_dcl_bracket brackets[2]; 1313 int num_brackets; 1314 uint writemask; 1315 const char *cur, *cur2; 1316 uint advance; 1317 boolean is_vs_input; 1318 1319 if (!eat_white( &ctx->cur )) { 1320 report_error( ctx, "Syntax error" ); 1321 return FALSE; 1322 } 1323 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) 1324 return FALSE; 1325 if (!parse_opt_writemask( ctx, &writemask )) 1326 return FALSE; 1327 1328 decl = tgsi_default_full_declaration(); 1329 decl.Declaration.File = file; 1330 decl.Declaration.UsageMask = writemask; 1331 1332 if (num_brackets == 1) { 1333 decl.Range.First = brackets[0].first; 1334 decl.Range.Last = brackets[0].last; 1335 } else { 1336 decl.Range.First = brackets[1].first; 1337 decl.Range.Last = brackets[1].last; 1338 1339 decl.Declaration.Dimension = 1; 1340 decl.Dim.Index2D = brackets[0].first; 1341 } 1342 1343 is_vs_input = (file == TGSI_FILE_INPUT && 1344 ctx->processor == PIPE_SHADER_VERTEX); 1345 1346 cur = ctx->cur; 1347 eat_opt_white( &cur ); 1348 if (*cur == ',') { 1349 cur2 = cur; 1350 cur2++; 1351 eat_opt_white( &cur2 ); 1352 if (str_match_nocase_whole( &cur2, "ARRAY" )) { 1353 int arrayid; 1354 if (*cur2 != '(') { 1355 report_error( ctx, "Expected `('" ); 1356 return FALSE; 1357 } 1358 cur2++; 1359 eat_opt_white( &cur2 ); 1360 if (!parse_int( &cur2, &arrayid )) { 1361 report_error( ctx, "Expected `,'" ); 1362 return FALSE; 1363 } 1364 eat_opt_white( &cur2 ); 1365 if (*cur2 != ')') { 1366 report_error( ctx, "Expected `)'" ); 1367 return FALSE; 1368 } 1369 cur2++; 1370 decl.Declaration.Array = 1; 1371 decl.Array.ArrayID = arrayid; 1372 ctx->cur = cur = cur2; 1373 } 1374 } 1375 1376 if (*cur == ',' && !is_vs_input) { 1377 uint i, j; 1378 1379 cur++; 1380 eat_opt_white( &cur ); 1381 if (file == TGSI_FILE_IMAGE) { 1382 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1383 if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1384 decl.Image.Resource = i; 1385 break; 1386 } 1387 } 1388 if (i == TGSI_TEXTURE_COUNT) { 1389 report_error(ctx, "Expected texture target"); 1390 return FALSE; 1391 } 1392 1393 cur2 = cur; 1394 eat_opt_white(&cur2); 1395 while (*cur2 == ',') { 1396 cur2++; 1397 eat_opt_white(&cur2); 1398 if (str_match_nocase_whole(&cur2, "RAW")) { 1399 decl.Image.Raw = 1; 1400 1401 } else if (str_match_nocase_whole(&cur2, "WR")) { 1402 decl.Image.Writable = 1; 1403 1404 } else { 1405 int format = str_match_format(&cur2); 1406 if (format < 0) 1407 break; 1408 1409 decl.Image.Format = format; 1410 } 1411 cur = cur2; 1412 eat_opt_white(&cur2); 1413 } 1414 1415 ctx->cur = cur; 1416 1417 } else if (file == TGSI_FILE_SAMPLER_VIEW) { 1418 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1419 if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1420 decl.SamplerView.Resource = i; 1421 break; 1422 } 1423 } 1424 if (i == TGSI_TEXTURE_COUNT) { 1425 report_error(ctx, "Expected texture target"); 1426 return FALSE; 1427 } 1428 eat_opt_white( &cur ); 1429 if (*cur != ',') { 1430 report_error( ctx, "Expected `,'" ); 1431 return FALSE; 1432 } 1433 ++cur; 1434 eat_opt_white( &cur ); 1435 for (j = 0; j < 4; ++j) { 1436 for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { 1437 if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { 1438 switch (j) { 1439 case 0: 1440 decl.SamplerView.ReturnTypeX = i; 1441 break; 1442 case 1: 1443 decl.SamplerView.ReturnTypeY = i; 1444 break; 1445 case 2: 1446 decl.SamplerView.ReturnTypeZ = i; 1447 break; 1448 case 3: 1449 decl.SamplerView.ReturnTypeW = i; 1450 break; 1451 default: 1452 assert(0); 1453 } 1454 break; 1455 } 1456 } 1457 if (i == TGSI_RETURN_TYPE_COUNT) { 1458 if (j == 0 || j > 2) { 1459 report_error(ctx, "Expected type name"); 1460 return FALSE; 1461 } 1462 break; 1463 } else { 1464 cur2 = cur; 1465 eat_opt_white( &cur2 ); 1466 if (*cur2 == ',') { 1467 cur2++; 1468 eat_opt_white( &cur2 ); 1469 cur = cur2; 1470 continue; 1471 } else 1472 break; 1473 } 1474 } 1475 if (j < 4) { 1476 decl.SamplerView.ReturnTypeY = 1477 decl.SamplerView.ReturnTypeZ = 1478 decl.SamplerView.ReturnTypeW = 1479 decl.SamplerView.ReturnTypeX; 1480 } 1481 ctx->cur = cur; 1482 } else if (file == TGSI_FILE_BUFFER) { 1483 if (str_match_nocase_whole(&cur, "ATOMIC")) { 1484 decl.Declaration.Atomic = 1; 1485 ctx->cur = cur; 1486 } 1487 } else if (file == TGSI_FILE_MEMORY) { 1488 if (str_match_nocase_whole(&cur, "GLOBAL")) { 1489 /* Note this is a no-op global is the default */ 1490 decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL; 1491 ctx->cur = cur; 1492 } else if (str_match_nocase_whole(&cur, "SHARED")) { 1493 decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED; 1494 ctx->cur = cur; 1495 } else if (str_match_nocase_whole(&cur, "PRIVATE")) { 1496 decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE; 1497 ctx->cur = cur; 1498 } else if (str_match_nocase_whole(&cur, "INPUT")) { 1499 decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT; 1500 ctx->cur = cur; 1501 } 1502 } else { 1503 if (str_match_nocase_whole(&cur, "LOCAL")) { 1504 decl.Declaration.Local = 1; 1505 ctx->cur = cur; 1506 } 1507 1508 cur = ctx->cur; 1509 eat_opt_white( &cur ); 1510 if (*cur == ',') { 1511 cur++; 1512 eat_opt_white( &cur ); 1513 1514 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { 1515 if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { 1516 uint index; 1517 1518 cur2 = cur; 1519 eat_opt_white( &cur2 ); 1520 if (*cur2 == '[') { 1521 cur2++; 1522 eat_opt_white( &cur2 ); 1523 if (!parse_uint( &cur2, &index )) { 1524 report_error( ctx, "Expected literal integer" ); 1525 return FALSE; 1526 } 1527 eat_opt_white( &cur2 ); 1528 if (*cur2 != ']') { 1529 report_error( ctx, "Expected `]'" ); 1530 return FALSE; 1531 } 1532 cur2++; 1533 1534 decl.Semantic.Index = index; 1535 1536 cur = cur2; 1537 } 1538 1539 decl.Declaration.Semantic = 1; 1540 decl.Semantic.Name = i; 1541 1542 ctx->cur = cur; 1543 break; 1544 } 1545 } 1546 } 1547 } 1548 } 1549 1550 cur = ctx->cur; 1551 eat_opt_white( &cur ); 1552 if (*cur == ',' && 1553 file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) { 1554 cur++; 1555 eat_opt_white(&cur); 1556 if (str_match_nocase_whole(&cur, "STREAM")) { 1557 uint stream[4]; 1558 1559 eat_opt_white(&cur); 1560 if (*cur != '(') { 1561 report_error(ctx, "Expected '('"); 1562 return FALSE; 1563 } 1564 cur++; 1565 1566 for (int i = 0; i < 4; ++i) { 1567 eat_opt_white(&cur); 1568 if (!parse_uint(&cur, &stream[i])) { 1569 report_error(ctx, "Expected literal integer"); 1570 return FALSE; 1571 } 1572 1573 eat_opt_white(&cur); 1574 if (i < 3) { 1575 if (*cur != ',') { 1576 report_error(ctx, "Expected ','"); 1577 return FALSE; 1578 } 1579 cur++; 1580 } 1581 } 1582 1583 if (*cur != ')') { 1584 report_error(ctx, "Expected ')'"); 1585 return FALSE; 1586 } 1587 cur++; 1588 1589 decl.Semantic.StreamX = stream[0]; 1590 decl.Semantic.StreamY = stream[1]; 1591 decl.Semantic.StreamZ = stream[2]; 1592 decl.Semantic.StreamW = stream[3]; 1593 1594 ctx->cur = cur; 1595 } 1596 } 1597 1598 cur = ctx->cur; 1599 eat_opt_white( &cur ); 1600 if (*cur == ',' && !is_vs_input) { 1601 uint i; 1602 1603 cur++; 1604 eat_opt_white( &cur ); 1605 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { 1606 if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { 1607 decl.Declaration.Interpolate = 1; 1608 decl.Interp.Interpolate = i; 1609 1610 ctx->cur = cur; 1611 break; 1612 } 1613 } 1614 if (i == TGSI_INTERPOLATE_COUNT) { 1615 report_error( ctx, "Expected semantic or interpolate attribute" ); 1616 return FALSE; 1617 } 1618 } 1619 1620 cur = ctx->cur; 1621 eat_opt_white( &cur ); 1622 if (*cur == ',' && !is_vs_input) { 1623 uint i; 1624 1625 cur++; 1626 eat_opt_white( &cur ); 1627 for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { 1628 if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { 1629 decl.Interp.Location = i; 1630 1631 ctx->cur = cur; 1632 break; 1633 } 1634 } 1635 } 1636 1637 advance = tgsi_build_full_declaration( 1638 &decl, 1639 ctx->tokens_cur, 1640 ctx->header, 1641 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1642 1643 if (advance == 0) 1644 return FALSE; 1645 ctx->tokens_cur += advance; 1646 1647 return TRUE; 1648 } 1649 1650 static boolean parse_immediate( struct translate_ctx *ctx ) 1651 { 1652 struct tgsi_full_immediate imm; 1653 uint advance; 1654 int type; 1655 1656 if (*ctx->cur == '[') { 1657 uint uindex; 1658 1659 ++ctx->cur; 1660 1661 eat_opt_white( &ctx->cur ); 1662 if (!parse_uint( &ctx->cur, &uindex )) { 1663 report_error( ctx, "Expected literal unsigned integer" ); 1664 return FALSE; 1665 } 1666 1667 if (uindex != ctx->num_immediates) { 1668 report_error( ctx, "Immediates must be sorted" ); 1669 return FALSE; 1670 } 1671 1672 eat_opt_white( &ctx->cur ); 1673 if (*ctx->cur != ']') { 1674 report_error( ctx, "Expected `]'" ); 1675 return FALSE; 1676 } 1677 1678 ctx->cur++; 1679 } 1680 1681 if (!eat_white( &ctx->cur )) { 1682 report_error( ctx, "Syntax error" ); 1683 return FALSE; 1684 } 1685 for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) { 1686 if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type])) 1687 break; 1688 } 1689 if (type == ARRAY_SIZE(tgsi_immediate_type_names)) { 1690 report_error( ctx, "Expected immediate type" ); 1691 return FALSE; 1692 } 1693 1694 imm = tgsi_default_full_immediate(); 1695 imm.Immediate.NrTokens += 4; 1696 imm.Immediate.DataType = type; 1697 parse_immediate_data(ctx, type, imm.u); 1698 1699 advance = tgsi_build_full_immediate( 1700 &imm, 1701 ctx->tokens_cur, 1702 ctx->header, 1703 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1704 if (advance == 0) 1705 return FALSE; 1706 ctx->tokens_cur += advance; 1707 1708 ctx->num_immediates++; 1709 1710 return TRUE; 1711 } 1712 1713 static boolean 1714 parse_primitive( const char **pcur, uint *primitive ) 1715 { 1716 uint i; 1717 1718 for (i = 0; i < PIPE_PRIM_MAX; i++) { 1719 const char *cur = *pcur; 1720 1721 if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) { 1722 *primitive = i; 1723 *pcur = cur; 1724 return TRUE; 1725 } 1726 } 1727 return FALSE; 1728 } 1729 1730 static boolean 1731 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) 1732 { 1733 uint i; 1734 1735 for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) { 1736 const char *cur = *pcur; 1737 1738 if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) { 1739 *fs_coord_origin = i; 1740 *pcur = cur; 1741 return TRUE; 1742 } 1743 } 1744 return FALSE; 1745 } 1746 1747 static boolean 1748 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) 1749 { 1750 uint i; 1751 1752 for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) { 1753 const char *cur = *pcur; 1754 1755 if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) { 1756 *fs_coord_pixel_center = i; 1757 *pcur = cur; 1758 return TRUE; 1759 } 1760 } 1761 return FALSE; 1762 } 1763 1764 static boolean 1765 parse_property_next_shader( const char **pcur, uint *next_shader ) 1766 { 1767 uint i; 1768 1769 for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) { 1770 const char *cur = *pcur; 1771 1772 if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) { 1773 *next_shader = i; 1774 *pcur = cur; 1775 return TRUE; 1776 } 1777 } 1778 return FALSE; 1779 } 1780 1781 static boolean parse_property( struct translate_ctx *ctx ) 1782 { 1783 struct tgsi_full_property prop; 1784 uint property_name; 1785 uint values[8]; 1786 uint advance; 1787 char id[64]; 1788 1789 if (!eat_white( &ctx->cur )) { 1790 report_error( ctx, "Syntax error" ); 1791 return FALSE; 1792 } 1793 if (!parse_identifier( &ctx->cur, id, sizeof(id) )) { 1794 report_error( ctx, "Syntax error" ); 1795 return FALSE; 1796 } 1797 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; 1798 ++property_name) { 1799 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) { 1800 break; 1801 } 1802 } 1803 if (property_name >= TGSI_PROPERTY_COUNT) { 1804 debug_printf( "\nError: Unknown property : '%s'", id ); 1805 return FALSE; 1806 } 1807 1808 eat_opt_white( &ctx->cur ); 1809 switch(property_name) { 1810 case TGSI_PROPERTY_GS_INPUT_PRIM: 1811 case TGSI_PROPERTY_GS_OUTPUT_PRIM: 1812 if (!parse_primitive(&ctx->cur, &values[0] )) { 1813 report_error( ctx, "Unknown primitive name as property!" ); 1814 return FALSE; 1815 } 1816 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && 1817 ctx->processor == PIPE_SHADER_GEOMETRY) { 1818 ctx->implied_array_size = u_vertices_per_prim(values[0]); 1819 } 1820 break; 1821 case TGSI_PROPERTY_FS_COORD_ORIGIN: 1822 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { 1823 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); 1824 return FALSE; 1825 } 1826 break; 1827 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: 1828 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { 1829 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); 1830 return FALSE; 1831 } 1832 break; 1833 case TGSI_PROPERTY_NEXT_SHADER: 1834 if (!parse_property_next_shader(&ctx->cur, &values[0] )) { 1835 report_error( ctx, "Unknown next shader property value." ); 1836 return FALSE; 1837 } 1838 break; 1839 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: 1840 default: 1841 if (!parse_uint(&ctx->cur, &values[0] )) { 1842 report_error( ctx, "Expected unsigned integer as property!" ); 1843 return FALSE; 1844 } 1845 } 1846 1847 prop = tgsi_default_full_property(); 1848 prop.Property.PropertyName = property_name; 1849 prop.Property.NrTokens += 1; 1850 prop.u[0].Data = values[0]; 1851 1852 advance = tgsi_build_full_property( 1853 &prop, 1854 ctx->tokens_cur, 1855 ctx->header, 1856 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1857 if (advance == 0) 1858 return FALSE; 1859 ctx->tokens_cur += advance; 1860 1861 return TRUE; 1862 } 1863 1864 1865 static boolean translate( struct translate_ctx *ctx ) 1866 { 1867 eat_opt_white( &ctx->cur ); 1868 if (!parse_header( ctx )) 1869 return FALSE; 1870 1871 if (ctx->processor == PIPE_SHADER_TESS_CTRL || 1872 ctx->processor == PIPE_SHADER_TESS_EVAL) 1873 ctx->implied_array_size = 32; 1874 1875 while (*ctx->cur != '\0') { 1876 uint label_val = 0; 1877 if (!eat_white( &ctx->cur )) { 1878 report_error( ctx, "Syntax error" ); 1879 return FALSE; 1880 } 1881 1882 if (*ctx->cur == '\0') 1883 break; 1884 if (parse_label( ctx, &label_val )) { 1885 if (!parse_instruction( ctx, TRUE )) 1886 return FALSE; 1887 } 1888 else if (str_match_nocase_whole( &ctx->cur, "DCL" )) { 1889 if (!parse_declaration( ctx )) 1890 return FALSE; 1891 } 1892 else if (str_match_nocase_whole( &ctx->cur, "IMM" )) { 1893 if (!parse_immediate( ctx )) 1894 return FALSE; 1895 } 1896 else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) { 1897 if (!parse_property( ctx )) 1898 return FALSE; 1899 } 1900 else if (!parse_instruction( ctx, FALSE )) { 1901 return FALSE; 1902 } 1903 } 1904 1905 return TRUE; 1906 } 1907 1908 boolean 1909 tgsi_text_translate( 1910 const char *text, 1911 struct tgsi_token *tokens, 1912 uint num_tokens ) 1913 { 1914 struct translate_ctx ctx = {0}; 1915 1916 ctx.text = text; 1917 ctx.cur = text; 1918 ctx.tokens = tokens; 1919 ctx.tokens_cur = tokens; 1920 ctx.tokens_end = tokens + num_tokens; 1921 1922 if (!translate( &ctx )) 1923 return FALSE; 1924 1925 return tgsi_sanity_check( tokens ); 1926 } 1927