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/* 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 */ 129static 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 */ 146static 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 */ 160static 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 */ 169static 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 */ 180static 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 194static 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 211static boolean parse_identifier( const char **pcur, char *ret, size_t len ) 212{ 213 const char *cur = *pcur; 214 size_t 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 */ 231static 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 278out: 279 *pcur = cur; 280 return TRUE; 281} 282 283static 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 301static 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 319static 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 337struct 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 350static 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 */ 374static 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 408static 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 423static boolean 424parse_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 440static boolean 441parse_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 */ 486static boolean 487parse_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 */ 506static boolean 507parse_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 */ 528static boolean 529parse_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 544struct 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 554static boolean 555parse_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 635static boolean 636parse_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 */ 666static boolean 667parse_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 681struct parsed_dcl_bracket { 682 uint first; 683 uint last; 684}; 685 686static boolean 687parse_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 727cleanup: 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 */ 740static boolean 741parse_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.*/ 791static boolean 792parse_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 806static boolean 807parse_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 856static boolean 857parse_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 int 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 894static boolean 895parse_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 970static boolean 971parse_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 999static boolean 1000match_inst(const char **pcur, 1001 unsigned *saturate, 1002 unsigned *precise, 1003 const struct tgsi_opcode_info *info) 1004{ 1005 const char *cur = *pcur; 1006 const char *mnemonic = tgsi_get_opcode_name(info->opcode); 1007 1008 /* simple case: the whole string matches the instruction name */ 1009 if (str_match_nocase_whole(&cur, mnemonic)) { 1010 *pcur = cur; 1011 *saturate = 0; 1012 *precise = 0; 1013 return TRUE; 1014 } 1015 1016 if (str_match_no_case(&cur, mnemonic)) { 1017 /* the instruction has a suffix, figure it out */ 1018 if (str_match_no_case(&cur, "_SAT")) { 1019 *pcur = cur; 1020 *saturate = 1; 1021 } 1022 1023 if (str_match_no_case(&cur, "_PRECISE")) { 1024 *pcur = cur; 1025 *precise = 1; 1026 } 1027 1028 if (!is_digit_alpha_underscore(cur)) 1029 return TRUE; 1030 } 1031 1032 return FALSE; 1033} 1034 1035static boolean 1036parse_instruction( 1037 struct translate_ctx *ctx, 1038 boolean has_label ) 1039{ 1040 int i; 1041 uint saturate = 0; 1042 uint precise = 0; 1043 const struct tgsi_opcode_info *info; 1044 struct tgsi_full_instruction inst; 1045 const char *cur; 1046 uint advance; 1047 1048 inst = tgsi_default_full_instruction(); 1049 1050 /* Parse instruction name. 1051 */ 1052 eat_opt_white( &ctx->cur ); 1053 for (i = 0; i < TGSI_OPCODE_LAST; i++) { 1054 cur = ctx->cur; 1055 1056 info = tgsi_get_opcode_info( i ); 1057 if (match_inst(&cur, &saturate, &precise, info)) { 1058 if (info->num_dst + info->num_src + info->is_tex == 0) { 1059 ctx->cur = cur; 1060 break; 1061 } 1062 else if (*cur == '\0' || eat_white( &cur )) { 1063 ctx->cur = cur; 1064 break; 1065 } 1066 } 1067 } 1068 if (i == TGSI_OPCODE_LAST) { 1069 if (has_label) 1070 report_error( ctx, "Unknown opcode" ); 1071 else 1072 report_error( ctx, "Expected `DCL', `IMM' or a label" ); 1073 return FALSE; 1074 } 1075 1076 inst.Instruction.Opcode = i; 1077 inst.Instruction.Saturate = saturate; 1078 inst.Instruction.Precise = precise; 1079 inst.Instruction.NumDstRegs = info->num_dst; 1080 inst.Instruction.NumSrcRegs = info->num_src; 1081 1082 if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { 1083 /* 1084 * These are not considered tex opcodes here (no additional 1085 * target argument) however we're required to set the Texture 1086 * bit so we can set the number of tex offsets. 1087 */ 1088 inst.Instruction.Texture = 1; 1089 inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; 1090 } 1091 1092 if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || 1093 i == TGSI_OPCODE_RESQ) { 1094 inst.Instruction.Memory = 1; 1095 inst.Memory.Qualifier = 0; 1096 } 1097 1098 assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); 1099 assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); 1100 1101 /* Parse instruction operands. 1102 */ 1103 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { 1104 if (i > 0) { 1105 eat_opt_white( &ctx->cur ); 1106 if (*ctx->cur != ',') { 1107 report_error( ctx, "Expected `,'" ); 1108 return FALSE; 1109 } 1110 ctx->cur++; 1111 eat_opt_white( &ctx->cur ); 1112 } 1113 1114 if (i < info->num_dst) { 1115 if (!parse_dst_operand( ctx, &inst.Dst[i] )) 1116 return FALSE; 1117 } 1118 else if (i < info->num_dst + info->num_src) { 1119 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) 1120 return FALSE; 1121 } 1122 else { 1123 uint j; 1124 1125 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { 1126 if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { 1127 inst.Instruction.Texture = 1; 1128 inst.Texture.Texture = j; 1129 break; 1130 } 1131 } 1132 if (j == TGSI_TEXTURE_COUNT) { 1133 report_error( ctx, "Expected texture target" ); 1134 return FALSE; 1135 } 1136 } 1137 } 1138 1139 cur = ctx->cur; 1140 eat_opt_white( &cur ); 1141 for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) { 1142 cur++; 1143 eat_opt_white( &cur ); 1144 ctx->cur = cur; 1145 if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) 1146 return FALSE; 1147 cur = ctx->cur; 1148 eat_opt_white( &cur ); 1149 } 1150 inst.Texture.NumOffsets = i; 1151 1152 cur = ctx->cur; 1153 eat_opt_white(&cur); 1154 1155 for (; inst.Instruction.Memory && *cur == ','; 1156 ctx->cur = cur, eat_opt_white(&cur)) { 1157 int j; 1158 1159 cur++; 1160 eat_opt_white(&cur); 1161 1162 j = str_match_name_from_array(&cur, tgsi_memory_names, 1163 ARRAY_SIZE(tgsi_memory_names)); 1164 if (j >= 0) { 1165 inst.Memory.Qualifier |= 1U << j; 1166 continue; 1167 } 1168 1169 j = str_match_name_from_array(&cur, tgsi_texture_names, 1170 ARRAY_SIZE(tgsi_texture_names)); 1171 if (j >= 0) { 1172 inst.Memory.Texture = j; 1173 continue; 1174 } 1175 1176 j = str_match_format(&cur); 1177 if (j >= 0) { 1178 inst.Memory.Format = j; 1179 continue; 1180 } 1181 1182 ctx->cur = cur; 1183 report_error(ctx, "Expected memory qualifier, texture target, or format\n"); 1184 return FALSE; 1185 } 1186 1187 cur = ctx->cur; 1188 eat_opt_white( &cur ); 1189 if (info->is_branch && *cur == ':') { 1190 uint target; 1191 1192 cur++; 1193 eat_opt_white( &cur ); 1194 if (!parse_uint( &cur, &target )) { 1195 report_error( ctx, "Expected a label" ); 1196 return FALSE; 1197 } 1198 inst.Instruction.Label = 1; 1199 inst.Label.Label = target; 1200 ctx->cur = cur; 1201 } 1202 1203 advance = tgsi_build_full_instruction( 1204 &inst, 1205 ctx->tokens_cur, 1206 ctx->header, 1207 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1208 if (advance == 0) 1209 return FALSE; 1210 ctx->tokens_cur += advance; 1211 1212 return TRUE; 1213} 1214 1215/* parses a 4-touple of the form {x, y, z, w} 1216 * where x, y, z, w are numbers */ 1217static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type, 1218 union tgsi_immediate_data *values) 1219{ 1220 unsigned i; 1221 int ret; 1222 1223 eat_opt_white( &ctx->cur ); 1224 if (*ctx->cur != '{') { 1225 report_error( ctx, "Expected `{'" ); 1226 return FALSE; 1227 } 1228 ctx->cur++; 1229 for (i = 0; i < 4; i++) { 1230 eat_opt_white( &ctx->cur ); 1231 if (i > 0) { 1232 if (*ctx->cur != ',') { 1233 report_error( ctx, "Expected `,'" ); 1234 return FALSE; 1235 } 1236 ctx->cur++; 1237 eat_opt_white( &ctx->cur ); 1238 } 1239 1240 switch (type) { 1241 case TGSI_IMM_FLOAT64: 1242 ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1243 i++; 1244 break; 1245 case TGSI_IMM_INT64: 1246 ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1247 i++; 1248 break; 1249 case TGSI_IMM_UINT64: 1250 ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); 1251 i++; 1252 break; 1253 case TGSI_IMM_FLOAT32: 1254 ret = parse_float(&ctx->cur, &values[i].Float); 1255 break; 1256 case TGSI_IMM_UINT32: 1257 ret = parse_uint(&ctx->cur, &values[i].Uint); 1258 break; 1259 case TGSI_IMM_INT32: 1260 ret = parse_int(&ctx->cur, &values[i].Int); 1261 break; 1262 default: 1263 assert(0); 1264 ret = FALSE; 1265 break; 1266 } 1267 1268 if (!ret) { 1269 report_error( ctx, "Expected immediate constant" ); 1270 return FALSE; 1271 } 1272 } 1273 eat_opt_white( &ctx->cur ); 1274 if (*ctx->cur != '}') { 1275 report_error( ctx, "Expected `}'" ); 1276 return FALSE; 1277 } 1278 ctx->cur++; 1279 1280 return TRUE; 1281} 1282 1283static boolean parse_declaration( struct translate_ctx *ctx ) 1284{ 1285 struct tgsi_full_declaration decl; 1286 uint file; 1287 struct parsed_dcl_bracket brackets[2]; 1288 int num_brackets; 1289 uint writemask; 1290 const char *cur, *cur2; 1291 uint advance; 1292 boolean is_vs_input; 1293 1294 if (!eat_white( &ctx->cur )) { 1295 report_error( ctx, "Syntax error" ); 1296 return FALSE; 1297 } 1298 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) 1299 return FALSE; 1300 if (!parse_opt_writemask( ctx, &writemask )) 1301 return FALSE; 1302 1303 decl = tgsi_default_full_declaration(); 1304 decl.Declaration.File = file; 1305 decl.Declaration.UsageMask = writemask; 1306 1307 if (num_brackets == 1) { 1308 decl.Range.First = brackets[0].first; 1309 decl.Range.Last = brackets[0].last; 1310 } else { 1311 decl.Range.First = brackets[1].first; 1312 decl.Range.Last = brackets[1].last; 1313 1314 decl.Declaration.Dimension = 1; 1315 decl.Dim.Index2D = brackets[0].first; 1316 } 1317 1318 is_vs_input = (file == TGSI_FILE_INPUT && 1319 ctx->processor == PIPE_SHADER_VERTEX); 1320 1321 cur = ctx->cur; 1322 eat_opt_white( &cur ); 1323 if (*cur == ',') { 1324 cur2 = cur; 1325 cur2++; 1326 eat_opt_white( &cur2 ); 1327 if (str_match_nocase_whole( &cur2, "ARRAY" )) { 1328 int arrayid; 1329 if (*cur2 != '(') { 1330 report_error( ctx, "Expected `('" ); 1331 return FALSE; 1332 } 1333 cur2++; 1334 eat_opt_white( &cur2 ); 1335 if (!parse_int( &cur2, &arrayid )) { 1336 report_error( ctx, "Expected `,'" ); 1337 return FALSE; 1338 } 1339 eat_opt_white( &cur2 ); 1340 if (*cur2 != ')') { 1341 report_error( ctx, "Expected `)'" ); 1342 return FALSE; 1343 } 1344 cur2++; 1345 decl.Declaration.Array = 1; 1346 decl.Array.ArrayID = arrayid; 1347 ctx->cur = cur = cur2; 1348 } 1349 } 1350 1351 if (*cur == ',' && !is_vs_input) { 1352 uint i, j; 1353 1354 cur++; 1355 eat_opt_white( &cur ); 1356 if (file == TGSI_FILE_IMAGE) { 1357 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1358 if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1359 decl.Image.Resource = i; 1360 break; 1361 } 1362 } 1363 if (i == TGSI_TEXTURE_COUNT) { 1364 report_error(ctx, "Expected texture target"); 1365 return FALSE; 1366 } 1367 1368 cur2 = cur; 1369 eat_opt_white(&cur2); 1370 while (*cur2 == ',') { 1371 cur2++; 1372 eat_opt_white(&cur2); 1373 if (str_match_nocase_whole(&cur2, "RAW")) { 1374 decl.Image.Raw = 1; 1375 1376 } else if (str_match_nocase_whole(&cur2, "WR")) { 1377 decl.Image.Writable = 1; 1378 1379 } else { 1380 int format = str_match_format(&cur2); 1381 if (format < 0) 1382 break; 1383 1384 decl.Image.Format = format; 1385 } 1386 cur = cur2; 1387 eat_opt_white(&cur2); 1388 } 1389 1390 ctx->cur = cur; 1391 1392 } else if (file == TGSI_FILE_SAMPLER_VIEW) { 1393 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { 1394 if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { 1395 decl.SamplerView.Resource = i; 1396 break; 1397 } 1398 } 1399 if (i == TGSI_TEXTURE_COUNT) { 1400 report_error(ctx, "Expected texture target"); 1401 return FALSE; 1402 } 1403 eat_opt_white( &cur ); 1404 if (*cur != ',') { 1405 report_error( ctx, "Expected `,'" ); 1406 return FALSE; 1407 } 1408 ++cur; 1409 eat_opt_white( &cur ); 1410 for (j = 0; j < 4; ++j) { 1411 for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { 1412 if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { 1413 switch (j) { 1414 case 0: 1415 decl.SamplerView.ReturnTypeX = i; 1416 break; 1417 case 1: 1418 decl.SamplerView.ReturnTypeY = i; 1419 break; 1420 case 2: 1421 decl.SamplerView.ReturnTypeZ = i; 1422 break; 1423 case 3: 1424 decl.SamplerView.ReturnTypeW = i; 1425 break; 1426 default: 1427 assert(0); 1428 } 1429 break; 1430 } 1431 } 1432 if (i == TGSI_RETURN_TYPE_COUNT) { 1433 if (j == 0 || j > 2) { 1434 report_error(ctx, "Expected type name"); 1435 return FALSE; 1436 } 1437 break; 1438 } else { 1439 cur2 = cur; 1440 eat_opt_white( &cur2 ); 1441 if (*cur2 == ',') { 1442 cur2++; 1443 eat_opt_white( &cur2 ); 1444 cur = cur2; 1445 continue; 1446 } else 1447 break; 1448 } 1449 } 1450 if (j < 4) { 1451 decl.SamplerView.ReturnTypeY = 1452 decl.SamplerView.ReturnTypeZ = 1453 decl.SamplerView.ReturnTypeW = 1454 decl.SamplerView.ReturnTypeX; 1455 } 1456 ctx->cur = cur; 1457 } else if (file == TGSI_FILE_BUFFER) { 1458 if (str_match_nocase_whole(&cur, "ATOMIC")) { 1459 decl.Declaration.Atomic = 1; 1460 ctx->cur = cur; 1461 } 1462 } else if (file == TGSI_FILE_MEMORY) { 1463 if (str_match_nocase_whole(&cur, "GLOBAL")) { 1464 /* Note this is a no-op global is the default */ 1465 decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL; 1466 ctx->cur = cur; 1467 } else if (str_match_nocase_whole(&cur, "SHARED")) { 1468 decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED; 1469 ctx->cur = cur; 1470 } else if (str_match_nocase_whole(&cur, "PRIVATE")) { 1471 decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE; 1472 ctx->cur = cur; 1473 } else if (str_match_nocase_whole(&cur, "INPUT")) { 1474 decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT; 1475 ctx->cur = cur; 1476 } 1477 } else { 1478 if (str_match_nocase_whole(&cur, "LOCAL")) { 1479 decl.Declaration.Local = 1; 1480 ctx->cur = cur; 1481 } 1482 1483 cur = ctx->cur; 1484 eat_opt_white( &cur ); 1485 if (*cur == ',') { 1486 cur++; 1487 eat_opt_white( &cur ); 1488 1489 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { 1490 if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { 1491 uint index; 1492 1493 cur2 = cur; 1494 eat_opt_white( &cur2 ); 1495 if (*cur2 == '[') { 1496 cur2++; 1497 eat_opt_white( &cur2 ); 1498 if (!parse_uint( &cur2, &index )) { 1499 report_error( ctx, "Expected literal integer" ); 1500 return FALSE; 1501 } 1502 eat_opt_white( &cur2 ); 1503 if (*cur2 != ']') { 1504 report_error( ctx, "Expected `]'" ); 1505 return FALSE; 1506 } 1507 cur2++; 1508 1509 decl.Semantic.Index = index; 1510 1511 cur = cur2; 1512 } 1513 1514 decl.Declaration.Semantic = 1; 1515 decl.Semantic.Name = i; 1516 1517 ctx->cur = cur; 1518 break; 1519 } 1520 } 1521 } 1522 } 1523 } 1524 1525 cur = ctx->cur; 1526 eat_opt_white( &cur ); 1527 if (*cur == ',' && 1528 file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) { 1529 cur++; 1530 eat_opt_white(&cur); 1531 if (str_match_nocase_whole(&cur, "STREAM")) { 1532 uint stream[4]; 1533 1534 eat_opt_white(&cur); 1535 if (*cur != '(') { 1536 report_error(ctx, "Expected '('"); 1537 return FALSE; 1538 } 1539 cur++; 1540 1541 for (int i = 0; i < 4; ++i) { 1542 eat_opt_white(&cur); 1543 if (!parse_uint(&cur, &stream[i])) { 1544 report_error(ctx, "Expected literal integer"); 1545 return FALSE; 1546 } 1547 1548 eat_opt_white(&cur); 1549 if (i < 3) { 1550 if (*cur != ',') { 1551 report_error(ctx, "Expected ','"); 1552 return FALSE; 1553 } 1554 cur++; 1555 } 1556 } 1557 1558 if (*cur != ')') { 1559 report_error(ctx, "Expected ')'"); 1560 return FALSE; 1561 } 1562 cur++; 1563 1564 decl.Semantic.StreamX = stream[0]; 1565 decl.Semantic.StreamY = stream[1]; 1566 decl.Semantic.StreamZ = stream[2]; 1567 decl.Semantic.StreamW = stream[3]; 1568 1569 ctx->cur = cur; 1570 } 1571 } 1572 1573 cur = ctx->cur; 1574 eat_opt_white( &cur ); 1575 if (*cur == ',' && !is_vs_input) { 1576 uint i; 1577 1578 cur++; 1579 eat_opt_white( &cur ); 1580 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { 1581 if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { 1582 decl.Declaration.Interpolate = 1; 1583 decl.Interp.Interpolate = i; 1584 1585 ctx->cur = cur; 1586 break; 1587 } 1588 } 1589 } 1590 1591 cur = ctx->cur; 1592 eat_opt_white( &cur ); 1593 if (*cur == ',' && !is_vs_input) { 1594 uint i; 1595 1596 cur++; 1597 eat_opt_white( &cur ); 1598 for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { 1599 if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { 1600 decl.Interp.Location = i; 1601 1602 ctx->cur = cur; 1603 break; 1604 } 1605 } 1606 } 1607 1608 cur = ctx->cur; 1609 eat_opt_white( &cur ); 1610 if (*cur == ',' && !is_vs_input) { 1611 cur++; 1612 eat_opt_white( &cur ); 1613 if (str_match_nocase_whole( &cur, tgsi_invariant_name )) { 1614 decl.Declaration.Invariant = 1; 1615 ctx->cur = cur; 1616 } else { 1617 report_error( ctx, "Expected semantic, interpolate attribute, or invariant "); 1618 return FALSE; 1619 } 1620 } 1621 1622 advance = tgsi_build_full_declaration( 1623 &decl, 1624 ctx->tokens_cur, 1625 ctx->header, 1626 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1627 1628 if (advance == 0) 1629 return FALSE; 1630 ctx->tokens_cur += advance; 1631 1632 return TRUE; 1633} 1634 1635static boolean parse_immediate( struct translate_ctx *ctx ) 1636{ 1637 struct tgsi_full_immediate imm; 1638 uint advance; 1639 uint type; 1640 1641 if (*ctx->cur == '[') { 1642 uint uindex; 1643 1644 ++ctx->cur; 1645 1646 eat_opt_white( &ctx->cur ); 1647 if (!parse_uint( &ctx->cur, &uindex )) { 1648 report_error( ctx, "Expected literal unsigned integer" ); 1649 return FALSE; 1650 } 1651 1652 if (uindex != ctx->num_immediates) { 1653 report_error( ctx, "Immediates must be sorted" ); 1654 return FALSE; 1655 } 1656 1657 eat_opt_white( &ctx->cur ); 1658 if (*ctx->cur != ']') { 1659 report_error( ctx, "Expected `]'" ); 1660 return FALSE; 1661 } 1662 1663 ctx->cur++; 1664 } 1665 1666 if (!eat_white( &ctx->cur )) { 1667 report_error( ctx, "Syntax error" ); 1668 return FALSE; 1669 } 1670 for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) { 1671 if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type])) 1672 break; 1673 } 1674 if (type == ARRAY_SIZE(tgsi_immediate_type_names)) { 1675 report_error( ctx, "Expected immediate type" ); 1676 return FALSE; 1677 } 1678 1679 imm = tgsi_default_full_immediate(); 1680 imm.Immediate.NrTokens += 4; 1681 imm.Immediate.DataType = type; 1682 parse_immediate_data(ctx, type, imm.u); 1683 1684 advance = tgsi_build_full_immediate( 1685 &imm, 1686 ctx->tokens_cur, 1687 ctx->header, 1688 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1689 if (advance == 0) 1690 return FALSE; 1691 ctx->tokens_cur += advance; 1692 1693 ctx->num_immediates++; 1694 1695 return TRUE; 1696} 1697 1698static boolean 1699parse_primitive( const char **pcur, uint *primitive ) 1700{ 1701 uint i; 1702 1703 for (i = 0; i < PIPE_PRIM_MAX; i++) { 1704 const char *cur = *pcur; 1705 1706 if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) { 1707 *primitive = i; 1708 *pcur = cur; 1709 return TRUE; 1710 } 1711 } 1712 return FALSE; 1713} 1714 1715static boolean 1716parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) 1717{ 1718 uint i; 1719 1720 for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) { 1721 const char *cur = *pcur; 1722 1723 if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) { 1724 *fs_coord_origin = i; 1725 *pcur = cur; 1726 return TRUE; 1727 } 1728 } 1729 return FALSE; 1730} 1731 1732static boolean 1733parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) 1734{ 1735 uint i; 1736 1737 for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) { 1738 const char *cur = *pcur; 1739 1740 if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) { 1741 *fs_coord_pixel_center = i; 1742 *pcur = cur; 1743 return TRUE; 1744 } 1745 } 1746 return FALSE; 1747} 1748 1749static boolean 1750parse_property_next_shader( const char **pcur, uint *next_shader ) 1751{ 1752 uint i; 1753 1754 for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) { 1755 const char *cur = *pcur; 1756 1757 if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) { 1758 *next_shader = i; 1759 *pcur = cur; 1760 return TRUE; 1761 } 1762 } 1763 return FALSE; 1764} 1765 1766static boolean parse_property( struct translate_ctx *ctx ) 1767{ 1768 struct tgsi_full_property prop; 1769 uint property_name; 1770 uint values[8]; 1771 uint advance; 1772 char id[64]; 1773 1774 if (!eat_white( &ctx->cur )) { 1775 report_error( ctx, "Syntax error" ); 1776 return FALSE; 1777 } 1778 if (!parse_identifier( &ctx->cur, id, sizeof(id) )) { 1779 report_error( ctx, "Syntax error" ); 1780 return FALSE; 1781 } 1782 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; 1783 ++property_name) { 1784 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) { 1785 break; 1786 } 1787 } 1788 if (property_name >= TGSI_PROPERTY_COUNT) { 1789 debug_printf( "\nError: Unknown property : '%s'", id ); 1790 return FALSE; 1791 } 1792 1793 eat_opt_white( &ctx->cur ); 1794 switch(property_name) { 1795 case TGSI_PROPERTY_GS_INPUT_PRIM: 1796 case TGSI_PROPERTY_GS_OUTPUT_PRIM: 1797 if (!parse_primitive(&ctx->cur, &values[0] )) { 1798 report_error( ctx, "Unknown primitive name as property!" ); 1799 return FALSE; 1800 } 1801 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && 1802 ctx->processor == PIPE_SHADER_GEOMETRY) { 1803 ctx->implied_array_size = u_vertices_per_prim(values[0]); 1804 } 1805 break; 1806 case TGSI_PROPERTY_FS_COORD_ORIGIN: 1807 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) { 1808 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" ); 1809 return FALSE; 1810 } 1811 break; 1812 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER: 1813 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) { 1814 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" ); 1815 return FALSE; 1816 } 1817 break; 1818 case TGSI_PROPERTY_NEXT_SHADER: 1819 if (!parse_property_next_shader(&ctx->cur, &values[0] )) { 1820 report_error( ctx, "Unknown next shader property value." ); 1821 return FALSE; 1822 } 1823 break; 1824 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: 1825 default: 1826 if (!parse_uint(&ctx->cur, &values[0] )) { 1827 report_error( ctx, "Expected unsigned integer as property!" ); 1828 return FALSE; 1829 } 1830 } 1831 1832 prop = tgsi_default_full_property(); 1833 prop.Property.PropertyName = property_name; 1834 prop.Property.NrTokens += 1; 1835 prop.u[0].Data = values[0]; 1836 1837 advance = tgsi_build_full_property( 1838 &prop, 1839 ctx->tokens_cur, 1840 ctx->header, 1841 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 1842 if (advance == 0) 1843 return FALSE; 1844 ctx->tokens_cur += advance; 1845 1846 return TRUE; 1847} 1848 1849 1850static boolean translate( struct translate_ctx *ctx ) 1851{ 1852 eat_opt_white( &ctx->cur ); 1853 if (!parse_header( ctx )) 1854 return FALSE; 1855 1856 if (ctx->processor == PIPE_SHADER_TESS_CTRL || 1857 ctx->processor == PIPE_SHADER_TESS_EVAL) 1858 ctx->implied_array_size = 32; 1859 1860 while (*ctx->cur != '\0') { 1861 uint label_val = 0; 1862 if (!eat_white( &ctx->cur )) { 1863 report_error( ctx, "Syntax error" ); 1864 return FALSE; 1865 } 1866 1867 if (*ctx->cur == '\0') 1868 break; 1869 if (parse_label( ctx, &label_val )) { 1870 if (!parse_instruction( ctx, TRUE )) 1871 return FALSE; 1872 } 1873 else if (str_match_nocase_whole( &ctx->cur, "DCL" )) { 1874 if (!parse_declaration( ctx )) 1875 return FALSE; 1876 } 1877 else if (str_match_nocase_whole( &ctx->cur, "IMM" )) { 1878 if (!parse_immediate( ctx )) 1879 return FALSE; 1880 } 1881 else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) { 1882 if (!parse_property( ctx )) 1883 return FALSE; 1884 } 1885 else if (!parse_instruction( ctx, FALSE )) { 1886 return FALSE; 1887 } 1888 } 1889 1890 return TRUE; 1891} 1892 1893boolean 1894tgsi_text_translate( 1895 const char *text, 1896 struct tgsi_token *tokens, 1897 uint num_tokens ) 1898{ 1899 struct translate_ctx ctx = {0}; 1900 1901 ctx.text = text; 1902 ctx.cur = text; 1903 ctx.tokens = tokens; 1904 ctx.tokens_cur = tokens; 1905 ctx.tokens_end = tokens + num_tokens; 1906 1907 if (!translate( &ctx )) 1908 return FALSE; 1909 1910 return tgsi_sanity_check( tokens ); 1911} 1912