tgsi_text.c revision e6133564bf2e65fc86f626a45d7977bdeaff8579
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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 "tgsi_text.h" 31#include "tgsi_build.h" 32#include "tgsi_info.h" 33#include "tgsi_parse.h" 34#include "tgsi_sanity.h" 35#include "tgsi_util.h" 36 37static boolean is_alpha_underscore( const char *cur ) 38{ 39 return 40 (*cur >= 'a' && *cur <= 'z') || 41 (*cur >= 'A' && *cur <= 'Z') || 42 *cur == '_'; 43} 44 45static boolean is_digit( const char *cur ) 46{ 47 return *cur >= '0' && *cur <= '9'; 48} 49 50static boolean is_digit_alpha_underscore( const char *cur ) 51{ 52 return is_digit( cur ) || is_alpha_underscore( cur ); 53} 54 55static boolean uprcase( char c ) 56{ 57 if (c >= 'a' && c <= 'z') 58 return c += 'A' - 'a'; 59 return c; 60} 61 62static boolean str_match_no_case( const char **pcur, const char *str ) 63{ 64 const char *cur = *pcur; 65 66 while (*str != '\0' && *str == uprcase( *cur )) { 67 str++; 68 cur++; 69 } 70 if (*str == '\0') { 71 *pcur = cur; 72 return TRUE; 73 } 74 return FALSE; 75} 76 77/* Eat zero or more whitespaces. 78 */ 79static void eat_opt_white( const char **pcur ) 80{ 81 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n') 82 (*pcur)++; 83} 84 85/* Eat one or more whitespaces. 86 * Return TRUE if at least one whitespace eaten. 87 */ 88static boolean eat_white( const char **pcur ) 89{ 90 const char *cur = *pcur; 91 92 eat_opt_white( pcur ); 93 return *pcur > cur; 94} 95 96/* Parse unsigned integer. 97 * No checks for overflow. 98 */ 99static boolean parse_uint( const char **pcur, uint *val ) 100{ 101 const char *cur = *pcur; 102 103 if (is_digit( cur )) { 104 *val = *cur++ - '0'; 105 while (is_digit( cur )) 106 *val = *val * 10 + *cur++ - '0'; 107 *pcur = cur; 108 return TRUE; 109 } 110 return FALSE; 111} 112 113/* Parse floating point. 114 */ 115static boolean parse_float( const char **pcur, float *val ) 116{ 117 const char *cur = *pcur; 118 boolean integral_part = FALSE; 119 boolean fractional_part = FALSE; 120 121 *val = (float) atof( cur ); 122 123 if (*cur == '-' || *cur == '+') 124 cur++; 125 if (is_digit( cur )) { 126 cur++; 127 integral_part = TRUE; 128 while (is_digit( cur )) 129 cur++; 130 } 131 if (*cur == '.') { 132 cur++; 133 if (is_digit( cur )) { 134 cur++; 135 fractional_part = TRUE; 136 while (is_digit( cur )) 137 cur++; 138 } 139 } 140 if (!integral_part && !fractional_part) 141 return FALSE; 142 if (uprcase( *cur ) == 'E') { 143 cur++; 144 if (*cur == '-' || *cur == '+') 145 cur++; 146 if (is_digit( cur )) { 147 cur++; 148 while (is_digit( cur )) 149 cur++; 150 } 151 else 152 return FALSE; 153 } 154 *pcur = cur; 155 return TRUE; 156} 157 158struct translate_ctx 159{ 160 const char *text; 161 const char *cur; 162 struct tgsi_token *tokens; 163 struct tgsi_token *tokens_cur; 164 struct tgsi_token *tokens_end; 165 struct tgsi_header *header; 166}; 167 168static void report_error( struct translate_ctx *ctx, const char *msg ) 169{ 170 debug_printf( "\nError: %s", msg ); 171} 172 173/* Parse shader header. 174 * Return TRUE for one of the following headers. 175 * FRAG 176 * GEOM 177 * VERT 178 */ 179static boolean parse_header( struct translate_ctx *ctx ) 180{ 181 uint processor; 182 183 if (str_match_no_case( &ctx->cur, "FRAG" )) 184 processor = TGSI_PROCESSOR_FRAGMENT; 185 else if (str_match_no_case( &ctx->cur, "VERT" )) 186 processor = TGSI_PROCESSOR_VERTEX; 187 else if (str_match_no_case( &ctx->cur, "GEOM" )) 188 processor = TGSI_PROCESSOR_GEOMETRY; 189 else { 190 report_error( ctx, "Unknown header" ); 191 return FALSE; 192 } 193 194 if (ctx->tokens_cur >= ctx->tokens_end) 195 return FALSE; 196 ctx->header = (struct tgsi_header *) ctx->tokens_cur++; 197 *ctx->header = tgsi_build_header(); 198 199 if (ctx->tokens_cur >= ctx->tokens_end) 200 return FALSE; 201 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header ); 202 203 return TRUE; 204} 205 206static boolean parse_label( struct translate_ctx *ctx, uint *val ) 207{ 208 const char *cur = ctx->cur; 209 210 if (parse_uint( &cur, val )) { 211 eat_opt_white( &cur ); 212 if (*cur == ':') { 213 cur++; 214 ctx->cur = cur; 215 return TRUE; 216 } 217 } 218 return FALSE; 219} 220 221static const char *file_names[TGSI_FILE_COUNT] = 222{ 223 "NULL", 224 "CONST", 225 "IN", 226 "OUT", 227 "TEMP", 228 "SAMP", 229 "ADDR", 230 "IMM", 231 "LOOP", 232 "PRED" 233}; 234 235static boolean 236parse_file( const char **pcur, uint *file ) 237{ 238 uint i; 239 240 for (i = 0; i < TGSI_FILE_COUNT; i++) { 241 const char *cur = *pcur; 242 243 if (str_match_no_case( &cur, file_names[i] )) { 244 if (!is_digit_alpha_underscore( cur )) { 245 *pcur = cur; 246 *file = i; 247 return TRUE; 248 } 249 } 250 } 251 return FALSE; 252} 253 254static boolean 255parse_opt_writemask( 256 struct translate_ctx *ctx, 257 uint *writemask ) 258{ 259 const char *cur; 260 261 cur = ctx->cur; 262 eat_opt_white( &cur ); 263 if (*cur == '.') { 264 cur++; 265 *writemask = TGSI_WRITEMASK_NONE; 266 eat_opt_white( &cur ); 267 if (uprcase( *cur ) == 'X') { 268 cur++; 269 *writemask |= TGSI_WRITEMASK_X; 270 } 271 if (uprcase( *cur ) == 'Y') { 272 cur++; 273 *writemask |= TGSI_WRITEMASK_Y; 274 } 275 if (uprcase( *cur ) == 'Z') { 276 cur++; 277 *writemask |= TGSI_WRITEMASK_Z; 278 } 279 if (uprcase( *cur ) == 'W') { 280 cur++; 281 *writemask |= TGSI_WRITEMASK_W; 282 } 283 284 if (*writemask == TGSI_WRITEMASK_NONE) { 285 report_error( ctx, "Writemask expected" ); 286 return FALSE; 287 } 288 289 ctx->cur = cur; 290 } 291 else { 292 *writemask = TGSI_WRITEMASK_XYZW; 293 } 294 return TRUE; 295} 296 297/* <register_file_bracket> ::= <file> `[' 298 */ 299static boolean 300parse_register_file_bracket( 301 struct translate_ctx *ctx, 302 uint *file ) 303{ 304 if (!parse_file( &ctx->cur, file )) { 305 report_error( ctx, "Unknown register file" ); 306 return FALSE; 307 } 308 eat_opt_white( &ctx->cur ); 309 if (*ctx->cur != '[') { 310 report_error( ctx, "Expected `['" ); 311 return FALSE; 312 } 313 ctx->cur++; 314 return TRUE; 315} 316 317/* <register_file_bracket_index> ::= <register_file_bracket> <uint> 318 */ 319static boolean 320parse_register_file_bracket_index( 321 struct translate_ctx *ctx, 322 uint *file, 323 int *index ) 324{ 325 uint uindex; 326 327 if (!parse_register_file_bracket( ctx, file )) 328 return FALSE; 329 eat_opt_white( &ctx->cur ); 330 if (!parse_uint( &ctx->cur, &uindex )) { 331 report_error( ctx, "Expected literal unsigned integer" ); 332 return FALSE; 333 } 334 *index = (int) uindex; 335 return TRUE; 336} 337 338/* Parse destination register operand. 339 * <register_dst> ::= <register_file_bracket_index> `]' 340 */ 341static boolean 342parse_register_dst( 343 struct translate_ctx *ctx, 344 uint *file, 345 int *index ) 346{ 347 if (!parse_register_file_bracket_index( ctx, file, index )) 348 return FALSE; 349 eat_opt_white( &ctx->cur ); 350 if (*ctx->cur != ']') { 351 report_error( ctx, "Expected `]'" ); 352 return FALSE; 353 } 354 ctx->cur++; 355 return TRUE; 356} 357 358/* Parse source register operand. 359 * <register_src> ::= <register_file_bracket_index> `]' | 360 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' | 361 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' | 362 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]' 363 */ 364static boolean 365parse_register_src( 366 struct translate_ctx *ctx, 367 uint *file, 368 int *index, 369 uint *ind_file, 370 int *ind_index, 371 uint *ind_comp) 372{ 373 const char *cur; 374 uint uindex; 375 376 *ind_comp = TGSI_SWIZZLE_X; 377 if (!parse_register_file_bracket( ctx, file )) 378 return FALSE; 379 eat_opt_white( &ctx->cur ); 380 cur = ctx->cur; 381 if (parse_file( &cur, ind_file )) { 382 if (!parse_register_dst( ctx, ind_file, ind_index )) 383 return FALSE; 384 eat_opt_white( &ctx->cur ); 385 386 if (*ctx->cur == '.') { 387 ctx->cur++; 388 eat_opt_white(&ctx->cur); 389 390 switch (uprcase(*ctx->cur)) { 391 case 'X': 392 *ind_comp = TGSI_SWIZZLE_X; 393 break; 394 case 'Y': 395 *ind_comp = TGSI_SWIZZLE_Y; 396 break; 397 case 'Z': 398 *ind_comp = TGSI_SWIZZLE_Z; 399 break; 400 case 'W': 401 *ind_comp = TGSI_SWIZZLE_W; 402 break; 403 default: 404 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'"); 405 return FALSE; 406 } 407 ctx->cur++; 408 eat_opt_white(&ctx->cur); 409 } 410 411 if (*ctx->cur == '+' || *ctx->cur == '-') { 412 boolean negate; 413 414 negate = *ctx->cur == '-'; 415 ctx->cur++; 416 eat_opt_white( &ctx->cur ); 417 if (!parse_uint( &ctx->cur, &uindex )) { 418 report_error( ctx, "Expected literal unsigned integer" ); 419 return FALSE; 420 } 421 if (negate) 422 *index = -(int) uindex; 423 else 424 *index = (int) uindex; 425 } 426 else { 427 *index = 0; 428 } 429 } 430 else { 431 if (!parse_uint( &ctx->cur, &uindex )) { 432 report_error( ctx, "Expected literal unsigned integer" ); 433 return FALSE; 434 } 435 *index = (int) uindex; 436 *ind_file = TGSI_FILE_NULL; 437 *ind_index = 0; 438 } 439 eat_opt_white( &ctx->cur ); 440 if (*ctx->cur != ']') { 441 report_error( ctx, "Expected `]'" ); 442 return FALSE; 443 } 444 ctx->cur++; 445 return TRUE; 446} 447 448/* Parse register declaration. 449 * <register_dcl> ::= <register_file_bracket_index> `]' | 450 * <register_file_bracket_index> `..' <index> `]' 451 */ 452static boolean 453parse_register_dcl( 454 struct translate_ctx *ctx, 455 uint *file, 456 int *first, 457 int *last ) 458{ 459 if (!parse_register_file_bracket_index( ctx, file, first )) 460 return FALSE; 461 eat_opt_white( &ctx->cur ); 462 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') { 463 uint uindex; 464 465 ctx->cur += 2; 466 eat_opt_white( &ctx->cur ); 467 if (!parse_uint( &ctx->cur, &uindex )) { 468 report_error( ctx, "Expected literal integer" ); 469 return FALSE; 470 } 471 *last = (int) uindex; 472 eat_opt_white( &ctx->cur ); 473 } 474 else { 475 *last = *first; 476 } 477 if (*ctx->cur != ']') { 478 report_error( ctx, "Expected `]' or `..'" ); 479 return FALSE; 480 } 481 ctx->cur++; 482 return TRUE; 483} 484 485 486static boolean 487parse_dst_operand( 488 struct translate_ctx *ctx, 489 struct tgsi_full_dst_register *dst ) 490{ 491 uint file; 492 int index; 493 uint writemask; 494 const char *cur; 495 496 if (!parse_register_dst( ctx, &file, &index )) 497 return FALSE; 498 499 cur = ctx->cur; 500 eat_opt_white( &cur ); 501 502 if (!parse_opt_writemask( ctx, &writemask )) 503 return FALSE; 504 505 dst->Register.File = file; 506 dst->Register.Index = index; 507 dst->Register.WriteMask = writemask; 508 return TRUE; 509} 510 511static boolean 512parse_optional_swizzle( 513 struct translate_ctx *ctx, 514 uint swizzle[4], 515 boolean *parsed_swizzle ) 516{ 517 const char *cur = ctx->cur; 518 519 *parsed_swizzle = FALSE; 520 521 eat_opt_white( &cur ); 522 if (*cur == '.') { 523 uint i; 524 525 cur++; 526 eat_opt_white( &cur ); 527 for (i = 0; i < 4; i++) { 528 if (uprcase( *cur ) == 'X') 529 swizzle[i] = TGSI_SWIZZLE_X; 530 else if (uprcase( *cur ) == 'Y') 531 swizzle[i] = TGSI_SWIZZLE_Y; 532 else if (uprcase( *cur ) == 'Z') 533 swizzle[i] = TGSI_SWIZZLE_Z; 534 else if (uprcase( *cur ) == 'W') 535 swizzle[i] = TGSI_SWIZZLE_W; 536 else { 537 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" ); 538 return FALSE; 539 } 540 cur++; 541 } 542 *parsed_swizzle = TRUE; 543 ctx->cur = cur; 544 } 545 return TRUE; 546} 547 548static boolean 549parse_src_operand( 550 struct translate_ctx *ctx, 551 struct tgsi_full_src_register *src ) 552{ 553 uint file; 554 int index; 555 uint ind_file; 556 int ind_index; 557 uint ind_comp; 558 uint swizzle[4]; 559 boolean parsed_swizzle; 560 561 if (*ctx->cur == '-') { 562 ctx->cur++; 563 eat_opt_white( &ctx->cur ); 564 src->Register.Negate = 1; 565 } 566 567 if (*ctx->cur == '|') { 568 ctx->cur++; 569 eat_opt_white( &ctx->cur ); 570 src->Register.Absolute = 1; 571 } 572 573 if (!parse_register_src(ctx, &file, &index, &ind_file, &ind_index, &ind_comp)) 574 return FALSE; 575 src->Register.File = file; 576 src->Register.Index = index; 577 if (ind_file != TGSI_FILE_NULL) { 578 src->Register.Indirect = 1; 579 src->Indirect.File = ind_file; 580 src->Indirect.Index = ind_index; 581 src->Indirect.SwizzleX = ind_comp; 582 src->Indirect.SwizzleY = ind_comp; 583 src->Indirect.SwizzleZ = ind_comp; 584 src->Indirect.SwizzleW = ind_comp; 585 } 586 587 /* Parse optional swizzle. 588 */ 589 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) { 590 if (parsed_swizzle) { 591 src->Register.SwizzleX = swizzle[0]; 592 src->Register.SwizzleY = swizzle[1]; 593 src->Register.SwizzleZ = swizzle[2]; 594 src->Register.SwizzleW = swizzle[3]; 595 } 596 } 597 598 if (src->Register.Absolute) { 599 eat_opt_white( &ctx->cur ); 600 if (*ctx->cur != '|') { 601 report_error( ctx, "Expected `|'" ); 602 return FALSE; 603 } 604 ctx->cur++; 605 } 606 607 608 return TRUE; 609} 610 611static const char *texture_names[TGSI_TEXTURE_COUNT] = 612{ 613 "UNKNOWN", 614 "1D", 615 "2D", 616 "3D", 617 "CUBE", 618 "RECT", 619 "SHADOW1D", 620 "SHADOW2D", 621 "SHADOWRECT" 622}; 623 624static boolean 625match_inst_mnemonic(const char **pcur, 626 const struct tgsi_opcode_info *info) 627{ 628 if (str_match_no_case(pcur, info->mnemonic)) { 629 return TRUE; 630 } 631 return FALSE; 632} 633 634static boolean 635parse_instruction( 636 struct translate_ctx *ctx, 637 boolean has_label ) 638{ 639 uint i; 640 uint saturate = TGSI_SAT_NONE; 641 const struct tgsi_opcode_info *info; 642 struct tgsi_full_instruction inst; 643 uint advance; 644 645 /* Parse instruction name. 646 */ 647 eat_opt_white( &ctx->cur ); 648 for (i = 0; i < TGSI_OPCODE_LAST; i++) { 649 const char *cur = ctx->cur; 650 651 info = tgsi_get_opcode_info( i ); 652 if (match_inst_mnemonic(&cur, info)) { 653 if (str_match_no_case( &cur, "_SATNV" )) 654 saturate = TGSI_SAT_MINUS_PLUS_ONE; 655 else if (str_match_no_case( &cur, "_SAT" )) 656 saturate = TGSI_SAT_ZERO_ONE; 657 658 if (info->num_dst + info->num_src + info->is_tex == 0) { 659 if (!is_digit_alpha_underscore( cur )) { 660 ctx->cur = cur; 661 break; 662 } 663 } 664 else if (*cur == '\0' || eat_white( &cur )) { 665 ctx->cur = cur; 666 break; 667 } 668 } 669 } 670 if (i == TGSI_OPCODE_LAST) { 671 if (has_label) 672 report_error( ctx, "Unknown opcode" ); 673 else 674 report_error( ctx, "Expected `DCL', `IMM' or a label" ); 675 return FALSE; 676 } 677 678 inst = tgsi_default_full_instruction(); 679 inst.Instruction.Opcode = i; 680 inst.Instruction.Saturate = saturate; 681 inst.Instruction.NumDstRegs = info->num_dst; 682 inst.Instruction.NumSrcRegs = info->num_src; 683 684 /* Parse instruction operands. 685 */ 686 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { 687 if (i > 0) { 688 eat_opt_white( &ctx->cur ); 689 if (*ctx->cur != ',') { 690 report_error( ctx, "Expected `,'" ); 691 return FALSE; 692 } 693 ctx->cur++; 694 eat_opt_white( &ctx->cur ); 695 } 696 697 if (i < info->num_dst) { 698 if (!parse_dst_operand( ctx, &inst.Dst[i] )) 699 return FALSE; 700 } 701 else if (i < info->num_dst + info->num_src) { 702 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) 703 return FALSE; 704 } 705 else { 706 uint j; 707 708 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { 709 if (str_match_no_case( &ctx->cur, texture_names[j] )) { 710 if (!is_digit_alpha_underscore( ctx->cur )) { 711 inst.Instruction.Texture = 1; 712 inst.Texture.Texture = j; 713 break; 714 } 715 } 716 } 717 if (j == TGSI_TEXTURE_COUNT) { 718 report_error( ctx, "Expected texture target" ); 719 return FALSE; 720 } 721 } 722 } 723 724 if (info->is_branch) { 725 uint target; 726 727 eat_opt_white( &ctx->cur ); 728 if (*ctx->cur != ':') { 729 report_error( ctx, "Expected `:'" ); 730 return FALSE; 731 } 732 ctx->cur++; 733 eat_opt_white( &ctx->cur ); 734 if (!parse_uint( &ctx->cur, &target )) { 735 report_error( ctx, "Expected a label" ); 736 return FALSE; 737 } 738 inst.Instruction.Label = 1; 739 inst.Label.Label = target; 740 } 741 742 advance = tgsi_build_full_instruction( 743 &inst, 744 ctx->tokens_cur, 745 ctx->header, 746 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 747 if (advance == 0) 748 return FALSE; 749 ctx->tokens_cur += advance; 750 751 return TRUE; 752} 753 754static const char *semantic_names[TGSI_SEMANTIC_COUNT] = 755{ 756 "POSITION", 757 "COLOR", 758 "BCOLOR", 759 "FOG", 760 "PSIZE", 761 "GENERIC", 762 "NORMAL", 763 "FACE" 764}; 765 766static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] = 767{ 768 "CONSTANT", 769 "LINEAR", 770 "PERSPECTIVE" 771}; 772 773static boolean parse_declaration( struct translate_ctx *ctx ) 774{ 775 struct tgsi_full_declaration decl; 776 uint file; 777 int first; 778 int last; 779 uint writemask; 780 const char *cur; 781 uint advance; 782 783 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT); 784 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT); 785 786 if (!eat_white( &ctx->cur )) { 787 report_error( ctx, "Syntax error" ); 788 return FALSE; 789 } 790 if (!parse_register_dcl( ctx, &file, &first, &last )) 791 return FALSE; 792 if (!parse_opt_writemask( ctx, &writemask )) 793 return FALSE; 794 795 decl = tgsi_default_full_declaration(); 796 decl.Declaration.File = file; 797 decl.Declaration.UsageMask = writemask; 798 decl.Range.First = first; 799 decl.Range.Last = last; 800 801 cur = ctx->cur; 802 eat_opt_white( &cur ); 803 if (*cur == ',') { 804 uint i; 805 806 cur++; 807 eat_opt_white( &cur ); 808 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { 809 if (str_match_no_case( &cur, semantic_names[i] )) { 810 const char *cur2 = cur; 811 uint index; 812 813 if (is_digit_alpha_underscore( cur )) 814 continue; 815 eat_opt_white( &cur2 ); 816 if (*cur2 == '[') { 817 cur2++; 818 eat_opt_white( &cur2 ); 819 if (!parse_uint( &cur2, &index )) { 820 report_error( ctx, "Expected literal integer" ); 821 return FALSE; 822 } 823 eat_opt_white( &cur2 ); 824 if (*cur2 != ']') { 825 report_error( ctx, "Expected `]'" ); 826 return FALSE; 827 } 828 cur2++; 829 830 decl.Semantic.Index = index; 831 832 cur = cur2; 833 } 834 835 decl.Declaration.Semantic = 1; 836 decl.Semantic.Name = i; 837 838 ctx->cur = cur; 839 break; 840 } 841 } 842 } 843 844 cur = ctx->cur; 845 eat_opt_white( &cur ); 846 if (*cur == ',') { 847 uint i; 848 849 cur++; 850 eat_opt_white( &cur ); 851 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { 852 if (str_match_no_case( &cur, interpolate_names[i] )) { 853 if (is_digit_alpha_underscore( cur )) 854 continue; 855 decl.Declaration.Interpolate = i; 856 857 ctx->cur = cur; 858 break; 859 } 860 } 861 if (i == TGSI_INTERPOLATE_COUNT) { 862 report_error( ctx, "Expected semantic or interpolate attribute" ); 863 return FALSE; 864 } 865 } 866 867 advance = tgsi_build_full_declaration( 868 &decl, 869 ctx->tokens_cur, 870 ctx->header, 871 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 872 if (advance == 0) 873 return FALSE; 874 ctx->tokens_cur += advance; 875 876 return TRUE; 877} 878 879static boolean parse_immediate( struct translate_ctx *ctx ) 880{ 881 struct tgsi_full_immediate imm; 882 uint i; 883 float values[4]; 884 uint advance; 885 886 if (!eat_white( &ctx->cur )) { 887 report_error( ctx, "Syntax error" ); 888 return FALSE; 889 } 890 if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) { 891 report_error( ctx, "Expected `FLT32'" ); 892 return FALSE; 893 } 894 eat_opt_white( &ctx->cur ); 895 if (*ctx->cur != '{') { 896 report_error( ctx, "Expected `{'" ); 897 return FALSE; 898 } 899 ctx->cur++; 900 for (i = 0; i < 4; i++) { 901 eat_opt_white( &ctx->cur ); 902 if (i > 0) { 903 if (*ctx->cur != ',') { 904 report_error( ctx, "Expected `,'" ); 905 return FALSE; 906 } 907 ctx->cur++; 908 eat_opt_white( &ctx->cur ); 909 } 910 if (!parse_float( &ctx->cur, &values[i] )) { 911 report_error( ctx, "Expected literal floating point" ); 912 return FALSE; 913 } 914 } 915 eat_opt_white( &ctx->cur ); 916 if (*ctx->cur != '}') { 917 report_error( ctx, "Expected `}'" ); 918 return FALSE; 919 } 920 ctx->cur++; 921 922 imm = tgsi_default_full_immediate(); 923 imm.Immediate.NrTokens += 4; 924 imm.Immediate.DataType = TGSI_IMM_FLOAT32; 925 imm.u[0].Float = values[0]; 926 imm.u[1].Float = values[1]; 927 imm.u[2].Float = values[2]; 928 imm.u[3].Float = values[3]; 929 930 advance = tgsi_build_full_immediate( 931 &imm, 932 ctx->tokens_cur, 933 ctx->header, 934 (uint) (ctx->tokens_end - ctx->tokens_cur) ); 935 if (advance == 0) 936 return FALSE; 937 ctx->tokens_cur += advance; 938 939 return TRUE; 940} 941 942static boolean translate( struct translate_ctx *ctx ) 943{ 944 eat_opt_white( &ctx->cur ); 945 if (!parse_header( ctx )) 946 return FALSE; 947 948 while (*ctx->cur != '\0') { 949 uint label_val = 0; 950 951 if (!eat_white( &ctx->cur )) { 952 report_error( ctx, "Syntax error" ); 953 return FALSE; 954 } 955 956 if (*ctx->cur == '\0') 957 break; 958 959 if (parse_label( ctx, &label_val )) { 960 if (!parse_instruction( ctx, TRUE )) 961 return FALSE; 962 } 963 else if (str_match_no_case( &ctx->cur, "DCL" )) { 964 if (!parse_declaration( ctx )) 965 return FALSE; 966 } 967 else if (str_match_no_case( &ctx->cur, "IMM" )) { 968 if (!parse_immediate( ctx )) 969 return FALSE; 970 } 971 else if (!parse_instruction( ctx, FALSE )) { 972 return FALSE; 973 } 974 } 975 976 return TRUE; 977} 978 979boolean 980tgsi_text_translate( 981 const char *text, 982 struct tgsi_token *tokens, 983 uint num_tokens ) 984{ 985 struct translate_ctx ctx; 986 987 ctx.text = text; 988 ctx.cur = text; 989 ctx.tokens = tokens; 990 ctx.tokens_cur = tokens; 991 ctx.tokens_end = tokens + num_tokens; 992 993 if (!translate( &ctx )) 994 return FALSE; 995 996 return tgsi_sanity_check( tokens ); 997} 998