1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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"
42 static boolean is_alpha_underscore( const char *cur )
45 (*cur >= 'a' && *cur <= 'z') ||
46 (*cur >= 'A' && *cur <= 'Z') ||
50 static boolean is_digit( const char *cur )
52 return *cur >= '0' && *cur <= '9';
55 static boolean is_digit_alpha_underscore( const char *cur )
57 return is_digit( cur ) || is_alpha_underscore( cur );
60 static char uprcase( char c )
62 if (c >= 'a' && c <= 'z')
68 * Ignore case of str1 and assume str1 is already uppercase.
69 * Return TRUE iff str1 and str2 are equal.
72 streq_nocase_uprcase(const char *str1,
75 while (*str1 && *str2) {
76 if (*str1 != uprcase(*str2))
81 return *str1 == 0 && *str2 == 0;
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
89 static boolean str_match_no_case( const char **pcur, const char *str )
91 const char *cur = *pcur;
93 while (*str != '\0' && *str == uprcase( *cur )) {
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
110 static boolean str_match_nocase_whole( const char **pcur, const char *str )
112 const char *cur = *pcur;
114 if (str_match_no_case(&cur, str) &&
115 !is_digit_alpha_underscore(cur)) {
122 /* Eat zero or more whitespaces.
124 static void eat_opt_white( const char **pcur )
126 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
130 /* Eat one or more whitespaces.
131 * Return TRUE if at least one whitespace eaten.
133 static boolean eat_white( const char **pcur )
135 const char *cur = *pcur;
137 eat_opt_white( pcur );
141 /* Parse unsigned integer.
142 * No checks for overflow.
144 static boolean parse_uint( const char **pcur, uint *val )
146 const char *cur = *pcur;
148 if (is_digit( cur )) {
150 while (is_digit( cur ))
151 *val = *val * 10 + *cur++ - '0';
158 static boolean parse_int( const char **pcur, int *val )
160 const char *cur = *pcur;
161 int sign = (*cur == '-' ? -1 : 1);
163 if (*cur == '+' || *cur == '-')
166 if (parse_uint(&cur, (uint *)val)) {
175 static boolean parse_identifier( const char **pcur, char *ret )
177 const char *cur = *pcur;
179 if (is_alpha_underscore( cur )) {
181 while (is_alpha_underscore( cur ) || is_digit( cur ))
190 /* Parse floating point.
192 static boolean parse_float( const char **pcur, float *val )
194 const char *cur = *pcur;
195 boolean integral_part = FALSE;
196 boolean fractional_part = FALSE;
198 *val = (float) atof( cur );
200 if (*cur == '-' || *cur == '+')
202 if (is_digit( cur )) {
204 integral_part = TRUE;
205 while (is_digit( cur ))
210 if (is_digit( cur )) {
212 fractional_part = TRUE;
213 while (is_digit( cur ))
217 if (!integral_part && !fractional_part)
219 if (uprcase( *cur ) == 'E') {
221 if (*cur == '-' || *cur == '+')
223 if (is_digit( cur )) {
225 while (is_digit( cur ))
239 struct tgsi_token *tokens;
240 struct tgsi_token *tokens_cur;
241 struct tgsi_token *tokens_end;
242 struct tgsi_header *header;
243 unsigned processor : 4;
244 int implied_array_size : 5;
245 unsigned num_immediates;
248 static void report_error( struct translate_ctx *ctx, const char *msg )
252 const char *itr = ctx->text;
254 while (itr != ctx->cur) {
263 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
266 /* Parse shader header.
267 * Return TRUE for one of the following headers.
272 static boolean parse_header( struct translate_ctx *ctx )
276 if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
277 processor = TGSI_PROCESSOR_FRAGMENT;
278 else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
279 processor = TGSI_PROCESSOR_VERTEX;
280 else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
281 processor = TGSI_PROCESSOR_GEOMETRY;
282 else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
283 processor = TGSI_PROCESSOR_COMPUTE;
285 report_error( ctx, "Unknown header" );
289 if (ctx->tokens_cur >= ctx->tokens_end)
291 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
292 *ctx->header = tgsi_build_header();
294 if (ctx->tokens_cur >= ctx->tokens_end)
296 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
297 ctx->processor = processor;
302 static boolean parse_label( struct translate_ctx *ctx, uint *val )
304 const char *cur = ctx->cur;
306 if (parse_uint( &cur, val )) {
307 eat_opt_white( &cur );
318 parse_file( const char **pcur, uint *file )
322 for (i = 0; i < TGSI_FILE_COUNT; i++) {
323 const char *cur = *pcur;
325 if (str_match_nocase_whole( &cur, tgsi_file_names[i] )) {
336 struct translate_ctx *ctx,
342 eat_opt_white( &cur );
345 *writemask = TGSI_WRITEMASK_NONE;
346 eat_opt_white( &cur );
347 if (uprcase( *cur ) == 'X') {
349 *writemask |= TGSI_WRITEMASK_X;
351 if (uprcase( *cur ) == 'Y') {
353 *writemask |= TGSI_WRITEMASK_Y;
355 if (uprcase( *cur ) == 'Z') {
357 *writemask |= TGSI_WRITEMASK_Z;
359 if (uprcase( *cur ) == 'W') {
361 *writemask |= TGSI_WRITEMASK_W;
364 if (*writemask == TGSI_WRITEMASK_NONE) {
365 report_error( ctx, "Writemask expected" );
372 *writemask = TGSI_WRITEMASK_XYZW;
378 /* <register_file_bracket> ::= <file> `['
381 parse_register_file_bracket(
382 struct translate_ctx *ctx,
385 if (!parse_file( &ctx->cur, file )) {
386 report_error( ctx, "Unknown register file" );
389 eat_opt_white( &ctx->cur );
390 if (*ctx->cur != '[') {
391 report_error( ctx, "Expected `['" );
398 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
401 parse_register_file_bracket_index(
402 struct translate_ctx *ctx,
408 if (!parse_register_file_bracket( ctx, file ))
410 eat_opt_white( &ctx->cur );
411 if (!parse_uint( &ctx->cur, &uindex )) {
412 report_error( ctx, "Expected literal unsigned integer" );
415 *index = (int) uindex;
419 /* Parse simple 1d register operand.
420 * <register_dst> ::= <register_file_bracket_index> `]'
423 parse_register_1d(struct translate_ctx *ctx,
427 if (!parse_register_file_bracket_index( ctx, file, index ))
429 eat_opt_white( &ctx->cur );
430 if (*ctx->cur != ']') {
431 report_error( ctx, "Expected `]'" );
438 struct parsed_bracket {
449 parse_register_bracket(
450 struct translate_ctx *ctx,
451 struct parsed_bracket *brackets)
456 memset(brackets, 0, sizeof(struct parsed_bracket));
458 eat_opt_white( &ctx->cur );
461 if (parse_file( &cur, &brackets->ind_file )) {
462 if (!parse_register_1d( ctx, &brackets->ind_file,
463 &brackets->ind_index ))
465 eat_opt_white( &ctx->cur );
467 if (*ctx->cur == '.') {
469 eat_opt_white(&ctx->cur);
471 switch (uprcase(*ctx->cur)) {
473 brackets->ind_comp = TGSI_SWIZZLE_X;
476 brackets->ind_comp = TGSI_SWIZZLE_Y;
479 brackets->ind_comp = TGSI_SWIZZLE_Z;
482 brackets->ind_comp = TGSI_SWIZZLE_W;
485 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
489 eat_opt_white(&ctx->cur);
492 if (*ctx->cur == '+' || *ctx->cur == '-')
493 parse_int( &ctx->cur, &brackets->index );
498 if (!parse_uint( &ctx->cur, &uindex )) {
499 report_error( ctx, "Expected literal unsigned integer" );
502 brackets->index = (int) uindex;
503 brackets->ind_file = TGSI_FILE_NULL;
504 brackets->ind_index = 0;
506 eat_opt_white( &ctx->cur );
507 if (*ctx->cur != ']') {
508 report_error( ctx, "Expected `]'" );
512 if (*ctx->cur == '(') {
514 eat_opt_white( &ctx->cur );
515 if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
516 report_error( ctx, "Expected literal unsigned integer" );
519 eat_opt_white( &ctx->cur );
520 if (*ctx->cur != ')') {
521 report_error( ctx, "Expected `)'" );
530 parse_opt_register_src_bracket(
531 struct translate_ctx *ctx,
532 struct parsed_bracket *brackets,
533 int *parsed_brackets)
535 const char *cur = ctx->cur;
537 *parsed_brackets = 0;
539 eat_opt_white( &cur );
544 if (!parse_register_bracket(ctx, brackets))
547 *parsed_brackets = 1;
554 /* Parse source register operand.
555 * <register_src> ::= <register_file_bracket_index> `]' |
556 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
557 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
558 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
562 struct translate_ctx *ctx,
564 struct parsed_bracket *brackets)
566 brackets->ind_comp = TGSI_SWIZZLE_X;
567 if (!parse_register_file_bracket( ctx, file ))
569 if (!parse_register_bracket( ctx, brackets ))
575 struct parsed_dcl_bracket {
581 parse_register_dcl_bracket(
582 struct translate_ctx *ctx,
583 struct parsed_dcl_bracket *bracket)
586 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
588 eat_opt_white( &ctx->cur );
590 if (!parse_uint( &ctx->cur, &uindex )) {
591 /* it can be an empty bracket [] which means its range
592 * is from 0 to some implied size */
593 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
595 bracket->last = ctx->implied_array_size - 1;
598 report_error( ctx, "Expected literal unsigned integer" );
601 bracket->first = uindex;
603 eat_opt_white( &ctx->cur );
605 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
609 eat_opt_white( &ctx->cur );
610 if (!parse_uint( &ctx->cur, &uindex )) {
611 report_error( ctx, "Expected literal integer" );
614 bracket->last = (int) uindex;
615 eat_opt_white( &ctx->cur );
618 bracket->last = bracket->first;
622 if (*ctx->cur != ']') {
623 report_error( ctx, "Expected `]' or `..'" );
630 /* Parse register declaration.
631 * <register_dcl> ::= <register_file_bracket_index> `]' |
632 * <register_file_bracket_index> `..' <index> `]'
636 struct translate_ctx *ctx,
638 struct parsed_dcl_bracket *brackets,
645 if (!parse_register_file_bracket( ctx, file ))
647 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
653 eat_opt_white( &cur );
658 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
660 /* for geometry shader we don't really care about
661 * the first brackets it's always the size of the
662 * input primitive. so we want to declare just
663 * the index relevant to the semantics which is in
664 * the second bracket */
665 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
666 brackets[0] = brackets[1];
677 /* Parse destination register operand.*/
680 struct translate_ctx *ctx,
682 struct parsed_bracket *brackets)
684 brackets->ind_comp = TGSI_SWIZZLE_X;
685 if (!parse_register_file_bracket( ctx, file ))
687 if (!parse_register_bracket( ctx, brackets ))
695 struct translate_ctx *ctx,
696 struct tgsi_full_dst_register *dst )
701 struct parsed_bracket bracket[2];
702 int parsed_opt_brackets;
704 if (!parse_register_dst( ctx, &file, &bracket[0] ))
706 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
710 eat_opt_white( &cur );
712 if (!parse_opt_writemask( ctx, &writemask ))
715 dst->Register.File = file;
716 if (parsed_opt_brackets) {
717 dst->Register.Dimension = 1;
718 dst->Dimension.Indirect = 0;
719 dst->Dimension.Dimension = 0;
720 dst->Dimension.Index = bracket[0].index;
721 bracket[0] = bracket[1];
723 dst->Register.Index = bracket[0].index;
724 dst->Register.WriteMask = writemask;
725 if (bracket[0].ind_file != TGSI_FILE_NULL) {
726 dst->Register.Indirect = 1;
727 dst->Indirect.File = bracket[0].ind_file;
728 dst->Indirect.Index = bracket[0].ind_index;
729 dst->Indirect.Swizzle = bracket[0].ind_comp;
730 dst->Indirect.ArrayID = bracket[0].ind_array;
736 parse_optional_swizzle(
737 struct translate_ctx *ctx,
739 boolean *parsed_swizzle )
741 const char *cur = ctx->cur;
743 *parsed_swizzle = FALSE;
745 eat_opt_white( &cur );
750 eat_opt_white( &cur );
751 for (i = 0; i < 4; i++) {
752 if (uprcase( *cur ) == 'X')
753 swizzle[i] = TGSI_SWIZZLE_X;
754 else if (uprcase( *cur ) == 'Y')
755 swizzle[i] = TGSI_SWIZZLE_Y;
756 else if (uprcase( *cur ) == 'Z')
757 swizzle[i] = TGSI_SWIZZLE_Z;
758 else if (uprcase( *cur ) == 'W')
759 swizzle[i] = TGSI_SWIZZLE_W;
761 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
766 *parsed_swizzle = TRUE;
774 struct translate_ctx *ctx,
775 struct tgsi_full_src_register *src )
779 boolean parsed_swizzle;
780 struct parsed_bracket bracket[2];
781 int parsed_opt_brackets;
783 if (*ctx->cur == '-') {
785 eat_opt_white( &ctx->cur );
786 src->Register.Negate = 1;
789 if (*ctx->cur == '|') {
791 eat_opt_white( &ctx->cur );
792 src->Register.Absolute = 1;
795 if (!parse_register_src(ctx, &file, &bracket[0]))
797 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
800 src->Register.File = file;
801 if (parsed_opt_brackets) {
802 src->Register.Dimension = 1;
803 src->Dimension.Indirect = 0;
804 src->Dimension.Dimension = 0;
805 src->Dimension.Index = bracket[0].index;
806 bracket[0] = bracket[1];
808 src->Register.Index = bracket[0].index;
809 if (bracket[0].ind_file != TGSI_FILE_NULL) {
810 src->Register.Indirect = 1;
811 src->Indirect.File = bracket[0].ind_file;
812 src->Indirect.Index = bracket[0].ind_index;
813 src->Indirect.Swizzle = bracket[0].ind_comp;
814 src->Indirect.ArrayID = bracket[0].ind_array;
817 /* Parse optional swizzle.
819 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
820 if (parsed_swizzle) {
821 src->Register.SwizzleX = swizzle[0];
822 src->Register.SwizzleY = swizzle[1];
823 src->Register.SwizzleZ = swizzle[2];
824 src->Register.SwizzleW = swizzle[3];
828 if (src->Register.Absolute) {
829 eat_opt_white( &ctx->cur );
830 if (*ctx->cur != '|') {
831 report_error( ctx, "Expected `|'" );
842 match_inst(const char **pcur,
844 const struct tgsi_opcode_info *info)
846 const char *cur = *pcur;
848 /* simple case: the whole string matches the instruction name */
849 if (str_match_nocase_whole(&cur, info->mnemonic)) {
851 *saturate = TGSI_SAT_NONE;
855 if (str_match_no_case(&cur, info->mnemonic)) {
856 /* the instruction has a suffix, figure it out */
857 if (str_match_nocase_whole(&cur, "_SAT")) {
859 *saturate = TGSI_SAT_ZERO_ONE;
863 if (str_match_nocase_whole(&cur, "_SATNV")) {
865 *saturate = TGSI_SAT_MINUS_PLUS_ONE;
875 struct translate_ctx *ctx,
879 uint saturate = TGSI_SAT_NONE;
880 const struct tgsi_opcode_info *info;
881 struct tgsi_full_instruction inst;
885 inst = tgsi_default_full_instruction();
889 eat_opt_white( &ctx->cur );
890 if (*ctx->cur == '(') {
894 boolean parsed_swizzle;
896 inst.Instruction.Predicate = 1;
899 if (*ctx->cur == '!') {
901 inst.Predicate.Negate = 1;
904 if (!parse_register_1d( ctx, &file, &index ))
907 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
908 if (parsed_swizzle) {
909 inst.Predicate.SwizzleX = swizzle[0];
910 inst.Predicate.SwizzleY = swizzle[1];
911 inst.Predicate.SwizzleZ = swizzle[2];
912 inst.Predicate.SwizzleW = swizzle[3];
916 if (*ctx->cur != ')') {
917 report_error( ctx, "Expected `)'" );
924 /* Parse instruction name.
926 eat_opt_white( &ctx->cur );
927 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
930 info = tgsi_get_opcode_info( i );
931 if (match_inst(&cur, &saturate, info)) {
932 if (info->num_dst + info->num_src + info->is_tex == 0) {
936 else if (*cur == '\0' || eat_white( &cur )) {
942 if (i == TGSI_OPCODE_LAST) {
944 report_error( ctx, "Unknown opcode" );
946 report_error( ctx, "Expected `DCL', `IMM' or a label" );
950 inst.Instruction.Opcode = i;
951 inst.Instruction.Saturate = saturate;
952 inst.Instruction.NumDstRegs = info->num_dst;
953 inst.Instruction.NumSrcRegs = info->num_src;
955 if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
957 * These are not considered tex opcodes here (no additional
958 * target argument) however we're required to set the Texture
959 * bit so we can set the number of tex offsets (offsets aren't
960 * actually handled here yet in any case).
962 inst.Instruction.Texture = 1;
963 inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
966 /* Parse instruction operands.
968 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
970 eat_opt_white( &ctx->cur );
971 if (*ctx->cur != ',') {
972 report_error( ctx, "Expected `,'" );
976 eat_opt_white( &ctx->cur );
979 if (i < info->num_dst) {
980 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
983 else if (i < info->num_dst + info->num_src) {
984 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
990 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
991 if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
992 inst.Instruction.Texture = 1;
993 inst.Texture.Texture = j;
997 if (j == TGSI_TEXTURE_COUNT) {
998 report_error( ctx, "Expected texture target" );
1005 eat_opt_white( &cur );
1006 if (info->is_branch && *cur == ':') {
1010 eat_opt_white( &cur );
1011 if (!parse_uint( &cur, &target )) {
1012 report_error( ctx, "Expected a label" );
1015 inst.Instruction.Label = 1;
1016 inst.Label.Label = target;
1020 advance = tgsi_build_full_instruction(
1024 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1027 ctx->tokens_cur += advance;
1032 /* parses a 4-touple of the form {x, y, z, w}
1033 * where x, y, z, w are numbers */
1034 static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1035 union tgsi_immediate_data *values)
1040 eat_opt_white( &ctx->cur );
1041 if (*ctx->cur != '{') {
1042 report_error( ctx, "Expected `{'" );
1046 for (i = 0; i < 4; i++) {
1047 eat_opt_white( &ctx->cur );
1049 if (*ctx->cur != ',') {
1050 report_error( ctx, "Expected `,'" );
1054 eat_opt_white( &ctx->cur );
1058 case TGSI_IMM_FLOAT32:
1059 ret = parse_float(&ctx->cur, &values[i].Float);
1061 case TGSI_IMM_UINT32:
1062 ret = parse_uint(&ctx->cur, &values[i].Uint);
1064 case TGSI_IMM_INT32:
1065 ret = parse_int(&ctx->cur, &values[i].Int);
1074 report_error( ctx, "Expected immediate constant" );
1078 eat_opt_white( &ctx->cur );
1079 if (*ctx->cur != '}') {
1080 report_error( ctx, "Expected `}'" );
1088 static boolean parse_declaration( struct translate_ctx *ctx )
1090 struct tgsi_full_declaration decl;
1092 struct parsed_dcl_bracket brackets[2];
1095 const char *cur, *cur2;
1097 boolean is_vs_input;
1099 if (!eat_white( &ctx->cur )) {
1100 report_error( ctx, "Syntax error" );
1103 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1105 if (!parse_opt_writemask( ctx, &writemask ))
1108 decl = tgsi_default_full_declaration();
1109 decl.Declaration.File = file;
1110 decl.Declaration.UsageMask = writemask;
1112 if (num_brackets == 1) {
1113 decl.Range.First = brackets[0].first;
1114 decl.Range.Last = brackets[0].last;
1116 decl.Range.First = brackets[1].first;
1117 decl.Range.Last = brackets[1].last;
1119 decl.Declaration.Dimension = 1;
1120 decl.Dim.Index2D = brackets[0].first;
1123 is_vs_input = (file == TGSI_FILE_INPUT &&
1124 ctx->processor == TGSI_PROCESSOR_VERTEX);
1127 eat_opt_white( &cur );
1131 eat_opt_white( &cur2 );
1132 if (str_match_nocase_whole( &cur2, "ARRAY(" )) {
1134 eat_opt_white( &cur2 );
1135 if (!parse_int( &cur2, &arrayid )) {
1136 report_error( ctx, "Expected `,'" );
1139 eat_opt_white( &cur2 );
1141 report_error( ctx, "Expected `,'" );
1144 decl.Declaration.Array = 1;
1145 decl.Array.ArrayID = arrayid;
1150 if (*cur == ',' && !is_vs_input) {
1154 eat_opt_white( &cur );
1155 if (file == TGSI_FILE_RESOURCE) {
1156 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1157 if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1158 decl.Resource.Resource = i;
1162 if (i == TGSI_TEXTURE_COUNT) {
1163 report_error(ctx, "Expected texture target");
1168 eat_opt_white(&cur2);
1169 while (*cur2 == ',') {
1171 eat_opt_white(&cur2);
1172 if (str_match_nocase_whole(&cur2, "RAW")) {
1173 decl.Resource.Raw = 1;
1175 } else if (str_match_nocase_whole(&cur2, "WR")) {
1176 decl.Resource.Writable = 1;
1182 eat_opt_white(&cur2);
1187 } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1188 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1189 if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1190 decl.SamplerView.Resource = i;
1194 if (i == TGSI_TEXTURE_COUNT) {
1195 report_error(ctx, "Expected texture target");
1198 eat_opt_white( &cur );
1200 report_error( ctx, "Expected `,'" );
1204 eat_opt_white( &cur );
1205 for (j = 0; j < 4; ++j) {
1206 for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1207 if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
1210 decl.SamplerView.ReturnTypeX = i;
1213 decl.SamplerView.ReturnTypeY = i;
1216 decl.SamplerView.ReturnTypeZ = i;
1219 decl.SamplerView.ReturnTypeW = i;
1227 if (i == PIPE_TYPE_COUNT) {
1228 if (j == 0 || j > 2) {
1229 report_error(ctx, "Expected type name");
1235 eat_opt_white( &cur2 );
1238 eat_opt_white( &cur2 );
1246 decl.SamplerView.ReturnTypeY =
1247 decl.SamplerView.ReturnTypeZ =
1248 decl.SamplerView.ReturnTypeW =
1249 decl.SamplerView.ReturnTypeX;
1253 if (str_match_nocase_whole(&cur, "LOCAL")) {
1254 decl.Declaration.Local = 1;
1259 eat_opt_white( &cur );
1262 eat_opt_white( &cur );
1264 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1265 if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1269 eat_opt_white( &cur2 );
1272 eat_opt_white( &cur2 );
1273 if (!parse_uint( &cur2, &index )) {
1274 report_error( ctx, "Expected literal integer" );
1277 eat_opt_white( &cur2 );
1279 report_error( ctx, "Expected `]'" );
1284 decl.Semantic.Index = index;
1289 decl.Declaration.Semantic = 1;
1290 decl.Semantic.Name = i;
1301 eat_opt_white( &cur );
1302 if (*cur == ',' && !is_vs_input) {
1306 eat_opt_white( &cur );
1307 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1308 if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1309 decl.Declaration.Interpolate = 1;
1310 decl.Interp.Interpolate = i;
1316 if (i == TGSI_INTERPOLATE_COUNT) {
1317 report_error( ctx, "Expected semantic or interpolate attribute" );
1322 advance = tgsi_build_full_declaration(
1326 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1330 ctx->tokens_cur += advance;
1335 static boolean parse_immediate( struct translate_ctx *ctx )
1337 struct tgsi_full_immediate imm;
1341 if (*ctx->cur == '[') {
1346 eat_opt_white( &ctx->cur );
1347 if (!parse_uint( &ctx->cur, &uindex )) {
1348 report_error( ctx, "Expected literal unsigned integer" );
1352 if (uindex != ctx->num_immediates) {
1353 report_error( ctx, "Immediates must be sorted" );
1357 eat_opt_white( &ctx->cur );
1358 if (*ctx->cur != ']') {
1359 report_error( ctx, "Expected `]'" );
1366 if (!eat_white( &ctx->cur )) {
1367 report_error( ctx, "Syntax error" );
1370 for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
1371 if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1374 if (type == Elements(tgsi_immediate_type_names)) {
1375 report_error( ctx, "Expected immediate type" );
1379 imm = tgsi_default_full_immediate();
1380 imm.Immediate.NrTokens += 4;
1381 imm.Immediate.DataType = type;
1382 parse_immediate_data(ctx, type, imm.u);
1384 advance = tgsi_build_full_immediate(
1388 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1391 ctx->tokens_cur += advance;
1393 ctx->num_immediates++;
1399 parse_primitive( const char **pcur, uint *primitive )
1403 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1404 const char *cur = *pcur;
1406 if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1416 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1420 for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1421 const char *cur = *pcur;
1423 if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1424 *fs_coord_origin = i;
1433 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1437 for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1438 const char *cur = *pcur;
1440 if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1441 *fs_coord_pixel_center = i;
1450 static boolean parse_property( struct translate_ctx *ctx )
1452 struct tgsi_full_property prop;
1458 if (!eat_white( &ctx->cur )) {
1459 report_error( ctx, "Syntax error" );
1462 if (!parse_identifier( &ctx->cur, id )) {
1463 report_error( ctx, "Syntax error" );
1466 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1468 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1472 if (property_name >= TGSI_PROPERTY_COUNT) {
1473 debug_printf( "\nError: Unknown property : '%s'", id );
1477 eat_opt_white( &ctx->cur );
1478 switch(property_name) {
1479 case TGSI_PROPERTY_GS_INPUT_PRIM:
1480 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1481 if (!parse_primitive(&ctx->cur, &values[0] )) {
1482 report_error( ctx, "Unknown primitive name as property!" );
1485 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1486 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1487 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1490 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1491 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1492 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1496 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1497 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1498 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1502 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1504 if (!parse_uint(&ctx->cur, &values[0] )) {
1505 report_error( ctx, "Expected unsigned integer as property!" );
1510 prop = tgsi_default_full_property();
1511 prop.Property.PropertyName = property_name;
1512 prop.Property.NrTokens += 1;
1513 prop.u[0].Data = values[0];
1515 advance = tgsi_build_full_property(
1519 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1522 ctx->tokens_cur += advance;
1528 static boolean translate( struct translate_ctx *ctx )
1530 eat_opt_white( &ctx->cur );
1531 if (!parse_header( ctx ))
1534 while (*ctx->cur != '\0') {
1536 if (!eat_white( &ctx->cur )) {
1537 report_error( ctx, "Syntax error" );
1541 if (*ctx->cur == '\0')
1543 if (parse_label( ctx, &label_val )) {
1544 if (!parse_instruction( ctx, TRUE ))
1547 else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1548 if (!parse_declaration( ctx ))
1551 else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1552 if (!parse_immediate( ctx ))
1555 else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1556 if (!parse_property( ctx ))
1559 else if (!parse_instruction( ctx, FALSE )) {
1568 tgsi_text_translate(
1570 struct tgsi_token *tokens,
1573 struct translate_ctx ctx = {0};
1577 ctx.tokens = tokens;
1578 ctx.tokens_cur = tokens;
1579 ctx.tokens_end = tokens + num_tokens;
1581 if (!translate( &ctx ))
1584 return tgsi_sanity_check( tokens );