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 static boolean str_match_no_case( const char **pcur, const char *str )
86 const char *cur = *pcur;
88 while (*str != '\0' && *str == uprcase( *cur )) {
99 /* Eat zero or more whitespaces.
101 static void eat_opt_white( const char **pcur )
103 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
107 /* Eat one or more whitespaces.
108 * Return TRUE if at least one whitespace eaten.
110 static boolean eat_white( const char **pcur )
112 const char *cur = *pcur;
114 eat_opt_white( pcur );
118 /* Parse unsigned integer.
119 * No checks for overflow.
121 static boolean parse_uint( const char **pcur, uint *val )
123 const char *cur = *pcur;
125 if (is_digit( cur )) {
127 while (is_digit( cur ))
128 *val = *val * 10 + *cur++ - '0';
135 static boolean parse_identifier( const char **pcur, char *ret )
137 const char *cur = *pcur;
139 if (is_alpha_underscore( cur )) {
141 while (is_alpha_underscore( cur ) || is_digit( cur ))
150 /* Parse floating point.
152 static boolean parse_float( const char **pcur, float *val )
154 const char *cur = *pcur;
155 boolean integral_part = FALSE;
156 boolean fractional_part = FALSE;
158 *val = (float) atof( cur );
160 if (*cur == '-' || *cur == '+')
162 if (is_digit( cur )) {
164 integral_part = TRUE;
165 while (is_digit( cur ))
170 if (is_digit( cur )) {
172 fractional_part = TRUE;
173 while (is_digit( cur ))
177 if (!integral_part && !fractional_part)
179 if (uprcase( *cur ) == 'E') {
181 if (*cur == '-' || *cur == '+')
183 if (is_digit( cur )) {
185 while (is_digit( cur ))
199 struct tgsi_token *tokens;
200 struct tgsi_token *tokens_cur;
201 struct tgsi_token *tokens_end;
202 struct tgsi_header *header;
203 unsigned processor : 4;
204 int implied_array_size : 5;
207 static void report_error( struct translate_ctx *ctx, const char *msg )
211 const char *itr = ctx->text;
213 while (itr != ctx->cur) {
222 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
225 /* Parse shader header.
226 * Return TRUE for one of the following headers.
231 static boolean parse_header( struct translate_ctx *ctx )
235 if (str_match_no_case( &ctx->cur, "FRAG" ))
236 processor = TGSI_PROCESSOR_FRAGMENT;
237 else if (str_match_no_case( &ctx->cur, "VERT" ))
238 processor = TGSI_PROCESSOR_VERTEX;
239 else if (str_match_no_case( &ctx->cur, "GEOM" ))
240 processor = TGSI_PROCESSOR_GEOMETRY;
242 report_error( ctx, "Unknown header" );
246 if (ctx->tokens_cur >= ctx->tokens_end)
248 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
249 *ctx->header = tgsi_build_header();
251 if (ctx->tokens_cur >= ctx->tokens_end)
253 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
254 ctx->processor = processor;
259 static boolean parse_label( struct translate_ctx *ctx, uint *val )
261 const char *cur = ctx->cur;
263 if (parse_uint( &cur, val )) {
264 eat_opt_white( &cur );
275 parse_file( const char **pcur, uint *file )
279 for (i = 0; i < TGSI_FILE_COUNT; i++) {
280 const char *cur = *pcur;
282 if (str_match_no_case( &cur, tgsi_file_names[i] )) {
283 if (!is_digit_alpha_underscore( cur )) {
295 struct translate_ctx *ctx,
301 eat_opt_white( &cur );
304 *writemask = TGSI_WRITEMASK_NONE;
305 eat_opt_white( &cur );
306 if (uprcase( *cur ) == 'X') {
308 *writemask |= TGSI_WRITEMASK_X;
310 if (uprcase( *cur ) == 'Y') {
312 *writemask |= TGSI_WRITEMASK_Y;
314 if (uprcase( *cur ) == 'Z') {
316 *writemask |= TGSI_WRITEMASK_Z;
318 if (uprcase( *cur ) == 'W') {
320 *writemask |= TGSI_WRITEMASK_W;
323 if (*writemask == TGSI_WRITEMASK_NONE) {
324 report_error( ctx, "Writemask expected" );
331 *writemask = TGSI_WRITEMASK_XYZW;
337 /* <register_file_bracket> ::= <file> `['
340 parse_register_file_bracket(
341 struct translate_ctx *ctx,
344 if (!parse_file( &ctx->cur, file )) {
345 report_error( ctx, "Unknown register file" );
348 eat_opt_white( &ctx->cur );
349 if (*ctx->cur != '[') {
350 report_error( ctx, "Expected `['" );
357 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
360 parse_register_file_bracket_index(
361 struct translate_ctx *ctx,
367 if (!parse_register_file_bracket( ctx, file ))
369 eat_opt_white( &ctx->cur );
370 if (!parse_uint( &ctx->cur, &uindex )) {
371 report_error( ctx, "Expected literal unsigned integer" );
374 *index = (int) uindex;
378 /* Parse simple 1d register operand.
379 * <register_dst> ::= <register_file_bracket_index> `]'
382 parse_register_1d(struct translate_ctx *ctx,
386 if (!parse_register_file_bracket_index( ctx, file, index ))
388 eat_opt_white( &ctx->cur );
389 if (*ctx->cur != ']') {
390 report_error( ctx, "Expected `]'" );
397 struct parsed_bracket {
407 parse_register_bracket(
408 struct translate_ctx *ctx,
409 struct parsed_bracket *brackets)
414 memset(brackets, 0, sizeof(struct parsed_bracket));
416 eat_opt_white( &ctx->cur );
419 if (parse_file( &cur, &brackets->ind_file )) {
420 if (!parse_register_1d( ctx, &brackets->ind_file,
421 &brackets->ind_index ))
423 eat_opt_white( &ctx->cur );
425 if (*ctx->cur == '.') {
427 eat_opt_white(&ctx->cur);
429 switch (uprcase(*ctx->cur)) {
431 brackets->ind_comp = TGSI_SWIZZLE_X;
434 brackets->ind_comp = TGSI_SWIZZLE_Y;
437 brackets->ind_comp = TGSI_SWIZZLE_Z;
440 brackets->ind_comp = TGSI_SWIZZLE_W;
443 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
447 eat_opt_white(&ctx->cur);
450 if (*ctx->cur == '+' || *ctx->cur == '-') {
453 negate = *ctx->cur == '-';
455 eat_opt_white( &ctx->cur );
456 if (!parse_uint( &ctx->cur, &uindex )) {
457 report_error( ctx, "Expected literal unsigned integer" );
461 brackets->index = -(int) uindex;
463 brackets->index = (int) uindex;
470 if (!parse_uint( &ctx->cur, &uindex )) {
471 report_error( ctx, "Expected literal unsigned integer" );
474 brackets->index = (int) uindex;
475 brackets->ind_file = TGSI_FILE_NULL;
476 brackets->ind_index = 0;
478 eat_opt_white( &ctx->cur );
479 if (*ctx->cur != ']') {
480 report_error( ctx, "Expected `]'" );
488 parse_opt_register_src_bracket(
489 struct translate_ctx *ctx,
490 struct parsed_bracket *brackets,
491 int *parsed_brackets)
493 const char *cur = ctx->cur;
495 *parsed_brackets = 0;
497 eat_opt_white( &cur );
502 if (!parse_register_bracket(ctx, brackets))
505 *parsed_brackets = 1;
512 /* Parse source register operand.
513 * <register_src> ::= <register_file_bracket_index> `]' |
514 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
515 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
516 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
520 struct translate_ctx *ctx,
522 struct parsed_bracket *brackets)
524 brackets->ind_comp = TGSI_SWIZZLE_X;
525 if (!parse_register_file_bracket( ctx, file ))
527 if (!parse_register_bracket( ctx, brackets ))
533 struct parsed_dcl_bracket {
539 parse_register_dcl_bracket(
540 struct translate_ctx *ctx,
541 struct parsed_dcl_bracket *bracket)
544 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
546 eat_opt_white( &ctx->cur );
548 if (!parse_uint( &ctx->cur, &uindex )) {
549 /* it can be an empty bracket [] which means its range
550 * is from 0 to some implied size */
551 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
553 bracket->last = ctx->implied_array_size - 1;
556 report_error( ctx, "Expected literal unsigned integer" );
559 bracket->first = uindex;
561 eat_opt_white( &ctx->cur );
563 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
567 eat_opt_white( &ctx->cur );
568 if (!parse_uint( &ctx->cur, &uindex )) {
569 report_error( ctx, "Expected literal integer" );
572 bracket->last = (int) uindex;
573 eat_opt_white( &ctx->cur );
576 bracket->last = bracket->first;
580 if (*ctx->cur != ']') {
581 report_error( ctx, "Expected `]' or `..'" );
588 /* Parse register declaration.
589 * <register_dcl> ::= <register_file_bracket_index> `]' |
590 * <register_file_bracket_index> `..' <index> `]'
594 struct translate_ctx *ctx,
596 struct parsed_dcl_bracket *brackets,
603 if (!parse_register_file_bracket( ctx, file ))
605 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
611 eat_opt_white( &cur );
616 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
618 /* for geometry shader we don't really care about
619 * the first brackets it's always the size of the
620 * input primitive. so we want to declare just
621 * the index relevant to the semantics which is in
622 * the second bracket */
623 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
624 brackets[0] = brackets[1];
635 /* Parse destination register operand.*/
638 struct translate_ctx *ctx,
640 struct parsed_bracket *brackets)
642 brackets->ind_comp = TGSI_SWIZZLE_X;
643 if (!parse_register_file_bracket( ctx, file ))
645 if (!parse_register_bracket( ctx, brackets ))
653 struct translate_ctx *ctx,
654 struct tgsi_full_dst_register *dst )
659 struct parsed_bracket bracket[2];
660 int parsed_opt_brackets;
662 if (!parse_register_dst( ctx, &file, &bracket[0] ))
664 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
668 eat_opt_white( &cur );
670 if (!parse_opt_writemask( ctx, &writemask ))
673 dst->Register.File = file;
674 if (parsed_opt_brackets) {
675 dst->Register.Dimension = 1;
676 dst->Dimension.Indirect = 0;
677 dst->Dimension.Dimension = 0;
678 dst->Dimension.Index = bracket[0].index;
679 bracket[0] = bracket[1];
681 dst->Register.Index = bracket[0].index;
682 dst->Register.WriteMask = writemask;
683 if (bracket[0].ind_file != TGSI_FILE_NULL) {
684 dst->Register.Indirect = 1;
685 dst->Indirect.File = bracket[0].ind_file;
686 dst->Indirect.Index = bracket[0].ind_index;
687 dst->Indirect.SwizzleX = bracket[0].ind_comp;
688 dst->Indirect.SwizzleY = bracket[0].ind_comp;
689 dst->Indirect.SwizzleZ = bracket[0].ind_comp;
690 dst->Indirect.SwizzleW = bracket[0].ind_comp;
696 parse_optional_swizzle(
697 struct translate_ctx *ctx,
699 boolean *parsed_swizzle )
701 const char *cur = ctx->cur;
703 *parsed_swizzle = FALSE;
705 eat_opt_white( &cur );
710 eat_opt_white( &cur );
711 for (i = 0; i < 4; i++) {
712 if (uprcase( *cur ) == 'X')
713 swizzle[i] = TGSI_SWIZZLE_X;
714 else if (uprcase( *cur ) == 'Y')
715 swizzle[i] = TGSI_SWIZZLE_Y;
716 else if (uprcase( *cur ) == 'Z')
717 swizzle[i] = TGSI_SWIZZLE_Z;
718 else if (uprcase( *cur ) == 'W')
719 swizzle[i] = TGSI_SWIZZLE_W;
721 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
726 *parsed_swizzle = TRUE;
734 struct translate_ctx *ctx,
735 struct tgsi_full_src_register *src )
739 boolean parsed_swizzle;
740 struct parsed_bracket bracket[2];
741 int parsed_opt_brackets;
743 if (*ctx->cur == '-') {
745 eat_opt_white( &ctx->cur );
746 src->Register.Negate = 1;
749 if (*ctx->cur == '|') {
751 eat_opt_white( &ctx->cur );
752 src->Register.Absolute = 1;
755 if (!parse_register_src(ctx, &file, &bracket[0]))
757 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
760 src->Register.File = file;
761 if (parsed_opt_brackets) {
762 src->Register.Dimension = 1;
763 src->Dimension.Indirect = 0;
764 src->Dimension.Dimension = 0;
765 src->Dimension.Index = bracket[0].index;
766 bracket[0] = bracket[1];
768 src->Register.Index = bracket[0].index;
769 if (bracket[0].ind_file != TGSI_FILE_NULL) {
770 src->Register.Indirect = 1;
771 src->Indirect.File = bracket[0].ind_file;
772 src->Indirect.Index = bracket[0].ind_index;
773 src->Indirect.SwizzleX = bracket[0].ind_comp;
774 src->Indirect.SwizzleY = bracket[0].ind_comp;
775 src->Indirect.SwizzleZ = bracket[0].ind_comp;
776 src->Indirect.SwizzleW = bracket[0].ind_comp;
779 /* Parse optional swizzle.
781 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
782 if (parsed_swizzle) {
783 src->Register.SwizzleX = swizzle[0];
784 src->Register.SwizzleY = swizzle[1];
785 src->Register.SwizzleZ = swizzle[2];
786 src->Register.SwizzleW = swizzle[3];
790 if (src->Register.Absolute) {
791 eat_opt_white( &ctx->cur );
792 if (*ctx->cur != '|') {
793 report_error( ctx, "Expected `|'" );
804 match_inst_mnemonic(const char **pcur,
805 const struct tgsi_opcode_info *info)
807 if (str_match_no_case(pcur, info->mnemonic)) {
815 struct translate_ctx *ctx,
819 uint saturate = TGSI_SAT_NONE;
820 const struct tgsi_opcode_info *info;
821 struct tgsi_full_instruction inst;
824 inst = tgsi_default_full_instruction();
828 eat_opt_white( &ctx->cur );
829 if (*ctx->cur == '(') {
833 boolean parsed_swizzle;
835 inst.Instruction.Predicate = 1;
838 if (*ctx->cur == '!') {
840 inst.Predicate.Negate = 1;
843 if (!parse_register_1d( ctx, &file, &index ))
846 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
847 if (parsed_swizzle) {
848 inst.Predicate.SwizzleX = swizzle[0];
849 inst.Predicate.SwizzleY = swizzle[1];
850 inst.Predicate.SwizzleZ = swizzle[2];
851 inst.Predicate.SwizzleW = swizzle[3];
855 if (*ctx->cur != ')') {
856 report_error( ctx, "Expected `)'" );
863 /* Parse instruction name.
865 eat_opt_white( &ctx->cur );
866 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
867 const char *cur = ctx->cur;
869 info = tgsi_get_opcode_info( i );
870 if (match_inst_mnemonic(&cur, info)) {
871 if (str_match_no_case( &cur, "_SATNV" ))
872 saturate = TGSI_SAT_MINUS_PLUS_ONE;
873 else if (str_match_no_case( &cur, "_SAT" ))
874 saturate = TGSI_SAT_ZERO_ONE;
876 if (info->num_dst + info->num_src + info->is_tex == 0) {
877 if (!is_digit_alpha_underscore( cur )) {
882 else if (*cur == '\0' || eat_white( &cur )) {
888 if (i == TGSI_OPCODE_LAST) {
890 report_error( ctx, "Unknown opcode" );
892 report_error( ctx, "Expected `DCL', `IMM' or a label" );
896 inst.Instruction.Opcode = i;
897 inst.Instruction.Saturate = saturate;
898 inst.Instruction.NumDstRegs = info->num_dst;
899 inst.Instruction.NumSrcRegs = info->num_src;
901 /* Parse instruction operands.
903 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
905 eat_opt_white( &ctx->cur );
906 if (*ctx->cur != ',') {
907 report_error( ctx, "Expected `,'" );
911 eat_opt_white( &ctx->cur );
914 if (i < info->num_dst) {
915 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
918 else if (i < info->num_dst + info->num_src) {
919 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
925 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
926 if (str_match_no_case( &ctx->cur, tgsi_texture_names[j] )) {
927 if (!is_digit_alpha_underscore( ctx->cur )) {
928 inst.Instruction.Texture = 1;
929 inst.Texture.Texture = j;
934 if (j == TGSI_TEXTURE_COUNT) {
935 report_error( ctx, "Expected texture target" );
941 if (info->is_branch) {
944 eat_opt_white( &ctx->cur );
945 if (*ctx->cur != ':') {
946 report_error( ctx, "Expected `:'" );
950 eat_opt_white( &ctx->cur );
951 if (!parse_uint( &ctx->cur, &target )) {
952 report_error( ctx, "Expected a label" );
955 inst.Instruction.Label = 1;
956 inst.Label.Label = target;
959 advance = tgsi_build_full_instruction(
963 (uint) (ctx->tokens_end - ctx->tokens_cur) );
966 ctx->tokens_cur += advance;
971 /* parses a 4-touple of the form {x, y, z, w}
972 * where x, y, z, w are numbers */
973 static boolean parse_immediate_data(struct translate_ctx *ctx,
978 eat_opt_white( &ctx->cur );
979 if (*ctx->cur != '{') {
980 report_error( ctx, "Expected `{'" );
984 for (i = 0; i < 4; i++) {
985 eat_opt_white( &ctx->cur );
987 if (*ctx->cur != ',') {
988 report_error( ctx, "Expected `,'" );
992 eat_opt_white( &ctx->cur );
994 if (!parse_float( &ctx->cur, &values[i] )) {
995 report_error( ctx, "Expected literal floating point" );
999 eat_opt_white( &ctx->cur );
1000 if (*ctx->cur != '}') {
1001 report_error( ctx, "Expected `}'" );
1009 static boolean parse_declaration( struct translate_ctx *ctx )
1011 struct tgsi_full_declaration decl;
1013 struct parsed_dcl_bracket brackets[2];
1018 boolean is_vs_input;
1019 boolean is_imm_array;
1021 if (!eat_white( &ctx->cur )) {
1022 report_error( ctx, "Syntax error" );
1025 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1027 if (!parse_opt_writemask( ctx, &writemask ))
1030 decl = tgsi_default_full_declaration();
1031 decl.Declaration.File = file;
1032 decl.Declaration.UsageMask = writemask;
1034 if (num_brackets == 1) {
1035 decl.Range.First = brackets[0].first;
1036 decl.Range.Last = brackets[0].last;
1038 decl.Range.First = brackets[1].first;
1039 decl.Range.Last = brackets[1].last;
1041 decl.Declaration.Dimension = 1;
1042 decl.Dim.Index2D = brackets[0].first;
1045 is_vs_input = (file == TGSI_FILE_INPUT &&
1046 ctx->processor == TGSI_PROCESSOR_VERTEX);
1047 is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
1050 eat_opt_white( &cur );
1051 if (*cur == ',' && !is_vs_input) {
1055 eat_opt_white( &cur );
1056 if (file == TGSI_FILE_RESOURCE) {
1057 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1058 if (str_match_no_case(&cur, tgsi_texture_names[i])) {
1059 if (!is_digit_alpha_underscore(cur)) {
1060 decl.Resource.Resource = i;
1065 if (i == TGSI_TEXTURE_COUNT) {
1066 report_error(ctx, "Expected texture target");
1069 eat_opt_white( &cur );
1071 report_error( ctx, "Expected `,'" );
1075 eat_opt_white( &cur );
1076 for (j = 0; j < 4; ++j) {
1077 for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1078 if (str_match_no_case(&cur, tgsi_type_names[i])) {
1079 if (!is_digit_alpha_underscore(cur)) {
1082 decl.Resource.ReturnTypeX = i;
1085 decl.Resource.ReturnTypeY = i;
1088 decl.Resource.ReturnTypeZ = i;
1091 decl.Resource.ReturnTypeW = i;
1100 if (i == PIPE_TYPE_COUNT) {
1101 if (j == 0 || j > 2) {
1102 report_error(ctx, "Expected type name");
1107 const char *cur2 = cur;
1108 eat_opt_white( &cur2 );
1111 eat_opt_white( &cur2 );
1119 decl.Resource.ReturnTypeY =
1120 decl.Resource.ReturnTypeZ =
1121 decl.Resource.ReturnTypeW =
1122 decl.Resource.ReturnTypeX;
1126 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1127 if (str_match_no_case( &cur, tgsi_semantic_names[i] )) {
1128 const char *cur2 = cur;
1131 if (is_digit_alpha_underscore( cur ))
1133 eat_opt_white( &cur2 );
1136 eat_opt_white( &cur2 );
1137 if (!parse_uint( &cur2, &index )) {
1138 report_error( ctx, "Expected literal integer" );
1141 eat_opt_white( &cur2 );
1143 report_error( ctx, "Expected `]'" );
1148 decl.Semantic.Index = index;
1153 decl.Declaration.Semantic = 1;
1154 decl.Semantic.Name = i;
1161 } else if (is_imm_array) {
1164 /* we have our immediate data */
1166 report_error( ctx, "Immediate array without data" );
1172 decl.ImmediateData.u =
1173 MALLOC(sizeof(union tgsi_immediate_data) * 4 *
1174 (decl.Range.Last + 1));
1175 vals_itr = (float*)decl.ImmediateData.u;
1176 for (i = 0; i <= decl.Range.Last; ++i) {
1177 if (!parse_immediate_data(ctx, vals_itr)) {
1178 FREE(decl.ImmediateData.u);
1182 eat_opt_white( &ctx->cur );
1183 if (*ctx->cur != ',') {
1184 if (i != decl.Range.Last) {
1185 report_error( ctx, "Not enough data in immediate array!" );
1186 FREE(decl.ImmediateData.u);
1192 eat_opt_white( &ctx->cur );
1193 if (*ctx->cur != '}') {
1194 FREE(decl.ImmediateData.u);
1195 report_error( ctx, "Immediate array data missing closing '}'" );
1202 eat_opt_white( &cur );
1203 if (*cur == ',' && !is_vs_input) {
1207 eat_opt_white( &cur );
1208 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1209 if (str_match_no_case( &cur, tgsi_interpolate_names[i] )) {
1210 if (is_digit_alpha_underscore( cur ))
1212 decl.Declaration.Interpolate = i;
1218 if (i == TGSI_INTERPOLATE_COUNT) {
1219 report_error( ctx, "Expected semantic or interpolate attribute" );
1224 advance = tgsi_build_full_declaration(
1228 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1231 FREE(decl.ImmediateData.u);
1235 ctx->tokens_cur += advance;
1240 static boolean parse_immediate( struct translate_ctx *ctx )
1242 struct tgsi_full_immediate imm;
1246 if (!eat_white( &ctx->cur )) {
1247 report_error( ctx, "Syntax error" );
1250 if (!str_match_no_case( &ctx->cur, "FLT32" ) ||
1251 is_digit_alpha_underscore( ctx->cur )) {
1252 report_error( ctx, "Expected `FLT32'" );
1256 parse_immediate_data(ctx, values);
1258 imm = tgsi_default_full_immediate();
1259 imm.Immediate.NrTokens += 4;
1260 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1261 imm.u[0].Float = values[0];
1262 imm.u[1].Float = values[1];
1263 imm.u[2].Float = values[2];
1264 imm.u[3].Float = values[3];
1266 advance = tgsi_build_full_immediate(
1270 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1273 ctx->tokens_cur += advance;
1279 parse_primitive( const char **pcur, uint *primitive )
1283 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1284 const char *cur = *pcur;
1286 if (str_match_no_case( &cur, tgsi_primitive_names[i])) {
1296 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1300 for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1301 const char *cur = *pcur;
1303 if (str_match_no_case( &cur, tgsi_fs_coord_origin_names[i])) {
1304 *fs_coord_origin = i;
1313 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1317 for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1318 const char *cur = *pcur;
1320 if (str_match_no_case( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1321 *fs_coord_pixel_center = i;
1330 static boolean parse_property( struct translate_ctx *ctx )
1332 struct tgsi_full_property prop;
1338 if (!eat_white( &ctx->cur )) {
1339 report_error( ctx, "Syntax error" );
1342 if (!parse_identifier( &ctx->cur, id )) {
1343 report_error( ctx, "Syntax error" );
1346 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1348 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1352 if (property_name >= TGSI_PROPERTY_COUNT) {
1353 debug_printf( "\nError: Unknown property : '%s'", id );
1357 eat_opt_white( &ctx->cur );
1358 switch(property_name) {
1359 case TGSI_PROPERTY_GS_INPUT_PRIM:
1360 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1361 if (!parse_primitive(&ctx->cur, &values[0] )) {
1362 report_error( ctx, "Unknown primitive name as property!" );
1365 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1366 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1367 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1370 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1371 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1372 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1376 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1377 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1378 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1382 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1384 if (!parse_uint(&ctx->cur, &values[0] )) {
1385 report_error( ctx, "Expected unsigned integer as property!" );
1390 prop = tgsi_default_full_property();
1391 prop.Property.PropertyName = property_name;
1392 prop.Property.NrTokens += 1;
1393 prop.u[0].Data = values[0];
1395 advance = tgsi_build_full_property(
1399 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1402 ctx->tokens_cur += advance;
1408 static boolean translate( struct translate_ctx *ctx )
1410 eat_opt_white( &ctx->cur );
1411 if (!parse_header( ctx ))
1414 while (*ctx->cur != '\0') {
1416 if (!eat_white( &ctx->cur )) {
1417 report_error( ctx, "Syntax error" );
1421 if (*ctx->cur == '\0')
1423 if (parse_label( ctx, &label_val )) {
1424 if (!parse_instruction( ctx, TRUE ))
1427 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1428 if (!parse_declaration( ctx ))
1431 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1432 if (!parse_immediate( ctx ))
1435 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
1436 if (!parse_property( ctx ))
1439 else if (!parse_instruction( ctx, FALSE )) {
1448 tgsi_text_translate(
1450 struct tgsi_token *tokens,
1453 struct translate_ctx ctx;
1457 ctx.tokens = tokens;
1458 ctx.tokens_cur = tokens;
1459 ctx.tokens_end = tokens + num_tokens;
1461 if (!translate( &ctx ))
1464 return tgsi_sanity_check( tokens );