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_util.h"
39 #include "tgsi_dump.h"
41 static boolean is_alpha_underscore( const char *cur )
44 (*cur >= 'a' && *cur <= 'z') ||
45 (*cur >= 'A' && *cur <= 'Z') ||
49 static boolean is_digit( const char *cur )
51 return *cur >= '0' && *cur <= '9';
54 static boolean is_digit_alpha_underscore( const char *cur )
56 return is_digit( cur ) || is_alpha_underscore( cur );
59 static char uprcase( char c )
61 if (c >= 'a' && c <= 'z')
67 * Ignore case of str1 and assume str1 is already uppercase.
68 * Return TRUE iff str1 and str2 are equal.
71 streq_nocase_uprcase(const char *str1,
74 while (*str1 && *str2) {
75 if (*str1 != uprcase(*str2))
80 return *str1 == 0 && *str2 == 0;
83 static boolean str_match_no_case( const char **pcur, const char *str )
85 const char *cur = *pcur;
87 while (*str != '\0' && *str == uprcase( *cur )) {
98 /* Eat zero or more whitespaces.
100 static void eat_opt_white( const char **pcur )
102 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
106 /* Eat one or more whitespaces.
107 * Return TRUE if at least one whitespace eaten.
109 static boolean eat_white( const char **pcur )
111 const char *cur = *pcur;
113 eat_opt_white( pcur );
117 /* Parse unsigned integer.
118 * No checks for overflow.
120 static boolean parse_uint( const char **pcur, uint *val )
122 const char *cur = *pcur;
124 if (is_digit( cur )) {
126 while (is_digit( cur ))
127 *val = *val * 10 + *cur++ - '0';
134 static boolean parse_identifier( const char **pcur, char *ret )
136 const char *cur = *pcur;
138 if (is_alpha_underscore( cur )) {
140 while (is_alpha_underscore( cur ) || is_digit( cur ))
149 /* Parse floating point.
151 static boolean parse_float( const char **pcur, float *val )
153 const char *cur = *pcur;
154 boolean integral_part = FALSE;
155 boolean fractional_part = FALSE;
157 *val = (float) atof( cur );
159 if (*cur == '-' || *cur == '+')
161 if (is_digit( cur )) {
163 integral_part = TRUE;
164 while (is_digit( cur ))
169 if (is_digit( cur )) {
171 fractional_part = TRUE;
172 while (is_digit( cur ))
176 if (!integral_part && !fractional_part)
178 if (uprcase( *cur ) == 'E') {
180 if (*cur == '-' || *cur == '+')
182 if (is_digit( cur )) {
184 while (is_digit( cur ))
198 struct tgsi_token *tokens;
199 struct tgsi_token *tokens_cur;
200 struct tgsi_token *tokens_end;
201 struct tgsi_header *header;
202 unsigned processor : 4;
203 int implied_array_size : 5;
206 static void report_error( struct translate_ctx *ctx, const char *msg )
210 const char *itr = ctx->text;
212 while (itr != ctx->cur) {
221 debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
224 /* Parse shader header.
225 * Return TRUE for one of the following headers.
230 static boolean parse_header( struct translate_ctx *ctx )
234 if (str_match_no_case( &ctx->cur, "FRAG" ))
235 processor = TGSI_PROCESSOR_FRAGMENT;
236 else if (str_match_no_case( &ctx->cur, "VERT" ))
237 processor = TGSI_PROCESSOR_VERTEX;
238 else if (str_match_no_case( &ctx->cur, "GEOM" ))
239 processor = TGSI_PROCESSOR_GEOMETRY;
241 report_error( ctx, "Unknown header" );
245 if (ctx->tokens_cur >= ctx->tokens_end)
247 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
248 *ctx->header = tgsi_build_header();
250 if (ctx->tokens_cur >= ctx->tokens_end)
252 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
253 ctx->processor = processor;
258 static boolean parse_label( struct translate_ctx *ctx, uint *val )
260 const char *cur = ctx->cur;
262 if (parse_uint( &cur, val )) {
263 eat_opt_white( &cur );
273 static const char *file_names[TGSI_FILE_COUNT] =
291 parse_file( const char **pcur, uint *file )
295 for (i = 0; i < TGSI_FILE_COUNT; i++) {
296 const char *cur = *pcur;
298 if (str_match_no_case( &cur, file_names[i] )) {
299 if (!is_digit_alpha_underscore( cur )) {
311 struct translate_ctx *ctx,
317 eat_opt_white( &cur );
320 *writemask = TGSI_WRITEMASK_NONE;
321 eat_opt_white( &cur );
322 if (uprcase( *cur ) == 'X') {
324 *writemask |= TGSI_WRITEMASK_X;
326 if (uprcase( *cur ) == 'Y') {
328 *writemask |= TGSI_WRITEMASK_Y;
330 if (uprcase( *cur ) == 'Z') {
332 *writemask |= TGSI_WRITEMASK_Z;
334 if (uprcase( *cur ) == 'W') {
336 *writemask |= TGSI_WRITEMASK_W;
339 if (*writemask == TGSI_WRITEMASK_NONE) {
340 report_error( ctx, "Writemask expected" );
347 *writemask = TGSI_WRITEMASK_XYZW;
353 /* <register_file_bracket> ::= <file> `['
356 parse_register_file_bracket(
357 struct translate_ctx *ctx,
360 if (!parse_file( &ctx->cur, file )) {
361 report_error( ctx, "Unknown register file" );
364 eat_opt_white( &ctx->cur );
365 if (*ctx->cur != '[') {
366 report_error( ctx, "Expected `['" );
373 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
376 parse_register_file_bracket_index(
377 struct translate_ctx *ctx,
383 if (!parse_register_file_bracket( ctx, file ))
385 eat_opt_white( &ctx->cur );
386 if (!parse_uint( &ctx->cur, &uindex )) {
387 report_error( ctx, "Expected literal unsigned integer" );
390 *index = (int) uindex;
394 /* Parse simple 1d register operand.
395 * <register_dst> ::= <register_file_bracket_index> `]'
398 parse_register_1d(struct translate_ctx *ctx,
402 if (!parse_register_file_bracket_index( ctx, file, index ))
404 eat_opt_white( &ctx->cur );
405 if (*ctx->cur != ']') {
406 report_error( ctx, "Expected `]'" );
413 struct parsed_bracket {
423 parse_register_bracket(
424 struct translate_ctx *ctx,
425 struct parsed_bracket *brackets)
430 memset(brackets, 0, sizeof(struct parsed_bracket));
432 eat_opt_white( &ctx->cur );
435 if (parse_file( &cur, &brackets->ind_file )) {
436 if (!parse_register_1d( ctx, &brackets->ind_file,
437 &brackets->ind_index ))
439 eat_opt_white( &ctx->cur );
441 if (*ctx->cur == '.') {
443 eat_opt_white(&ctx->cur);
445 switch (uprcase(*ctx->cur)) {
447 brackets->ind_comp = TGSI_SWIZZLE_X;
450 brackets->ind_comp = TGSI_SWIZZLE_Y;
453 brackets->ind_comp = TGSI_SWIZZLE_Z;
456 brackets->ind_comp = TGSI_SWIZZLE_W;
459 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
463 eat_opt_white(&ctx->cur);
466 if (*ctx->cur == '+' || *ctx->cur == '-') {
469 negate = *ctx->cur == '-';
471 eat_opt_white( &ctx->cur );
472 if (!parse_uint( &ctx->cur, &uindex )) {
473 report_error( ctx, "Expected literal unsigned integer" );
477 brackets->index = -(int) uindex;
479 brackets->index = (int) uindex;
486 if (!parse_uint( &ctx->cur, &uindex )) {
487 report_error( ctx, "Expected literal unsigned integer" );
490 brackets->index = (int) uindex;
491 brackets->ind_file = TGSI_FILE_NULL;
492 brackets->ind_index = 0;
494 eat_opt_white( &ctx->cur );
495 if (*ctx->cur != ']') {
496 report_error( ctx, "Expected `]'" );
504 parse_opt_register_src_bracket(
505 struct translate_ctx *ctx,
506 struct parsed_bracket *brackets,
507 int *parsed_brackets)
509 const char *cur = ctx->cur;
511 *parsed_brackets = 0;
513 eat_opt_white( &cur );
518 if (!parse_register_bracket(ctx, brackets))
521 *parsed_brackets = 1;
528 /* Parse source register operand.
529 * <register_src> ::= <register_file_bracket_index> `]' |
530 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
531 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
532 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
536 struct translate_ctx *ctx,
538 struct parsed_bracket *brackets)
540 brackets->ind_comp = TGSI_SWIZZLE_X;
541 if (!parse_register_file_bracket( ctx, file ))
543 if (!parse_register_bracket( ctx, brackets ))
549 struct parsed_dcl_bracket {
555 parse_register_dcl_bracket(
556 struct translate_ctx *ctx,
557 struct parsed_dcl_bracket *bracket)
560 memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
562 eat_opt_white( &ctx->cur );
564 if (!parse_uint( &ctx->cur, &uindex )) {
565 /* it can be an empty bracket [] which means its range
566 * is from 0 to some implied size */
567 if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
569 bracket->last = ctx->implied_array_size - 1;
572 report_error( ctx, "Expected literal unsigned integer" );
575 bracket->first = uindex;
577 eat_opt_white( &ctx->cur );
579 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
583 eat_opt_white( &ctx->cur );
584 if (!parse_uint( &ctx->cur, &uindex )) {
585 report_error( ctx, "Expected literal integer" );
588 bracket->last = (int) uindex;
589 eat_opt_white( &ctx->cur );
592 bracket->last = bracket->first;
596 if (*ctx->cur != ']') {
597 report_error( ctx, "Expected `]' or `..'" );
604 /* Parse register declaration.
605 * <register_dcl> ::= <register_file_bracket_index> `]' |
606 * <register_file_bracket_index> `..' <index> `]'
610 struct translate_ctx *ctx,
612 struct parsed_dcl_bracket *brackets,
619 if (!parse_register_file_bracket( ctx, file ))
621 if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
627 eat_opt_white( &cur );
632 if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
634 /* for geometry shader we don't really care about
635 * the first brackets it's always the size of the
636 * input primitive. so we want to declare just
637 * the index relevant to the semantics which is in
638 * the second bracket */
639 if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
640 brackets[0] = brackets[1];
651 /* Parse destination register operand.*/
654 struct translate_ctx *ctx,
656 struct parsed_bracket *brackets)
658 brackets->ind_comp = TGSI_SWIZZLE_X;
659 if (!parse_register_file_bracket( ctx, file ))
661 if (!parse_register_bracket( ctx, brackets ))
669 struct translate_ctx *ctx,
670 struct tgsi_full_dst_register *dst )
675 struct parsed_bracket bracket[2];
676 int parsed_opt_brackets;
678 if (!parse_register_dst( ctx, &file, &bracket[0] ))
680 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
684 eat_opt_white( &cur );
686 if (!parse_opt_writemask( ctx, &writemask ))
689 dst->Register.File = file;
690 if (parsed_opt_brackets) {
691 dst->Register.Dimension = 1;
692 dst->Dimension.Indirect = 0;
693 dst->Dimension.Dimension = 0;
694 dst->Dimension.Index = bracket[0].index;
695 bracket[0] = bracket[1];
697 dst->Register.Index = bracket[0].index;
698 dst->Register.WriteMask = writemask;
699 if (bracket[0].ind_file != TGSI_FILE_NULL) {
700 dst->Register.Indirect = 1;
701 dst->Indirect.File = bracket[0].ind_file;
702 dst->Indirect.Index = bracket[0].ind_index;
703 dst->Indirect.SwizzleX = bracket[0].ind_comp;
704 dst->Indirect.SwizzleY = bracket[0].ind_comp;
705 dst->Indirect.SwizzleZ = bracket[0].ind_comp;
706 dst->Indirect.SwizzleW = bracket[0].ind_comp;
712 parse_optional_swizzle(
713 struct translate_ctx *ctx,
715 boolean *parsed_swizzle )
717 const char *cur = ctx->cur;
719 *parsed_swizzle = FALSE;
721 eat_opt_white( &cur );
726 eat_opt_white( &cur );
727 for (i = 0; i < 4; i++) {
728 if (uprcase( *cur ) == 'X')
729 swizzle[i] = TGSI_SWIZZLE_X;
730 else if (uprcase( *cur ) == 'Y')
731 swizzle[i] = TGSI_SWIZZLE_Y;
732 else if (uprcase( *cur ) == 'Z')
733 swizzle[i] = TGSI_SWIZZLE_Z;
734 else if (uprcase( *cur ) == 'W')
735 swizzle[i] = TGSI_SWIZZLE_W;
737 report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
742 *parsed_swizzle = TRUE;
750 struct translate_ctx *ctx,
751 struct tgsi_full_src_register *src )
755 boolean parsed_swizzle;
756 struct parsed_bracket bracket[2];
757 int parsed_opt_brackets;
759 if (*ctx->cur == '-') {
761 eat_opt_white( &ctx->cur );
762 src->Register.Negate = 1;
765 if (*ctx->cur == '|') {
767 eat_opt_white( &ctx->cur );
768 src->Register.Absolute = 1;
771 if (!parse_register_src(ctx, &file, &bracket[0]))
773 if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
776 src->Register.File = file;
777 if (parsed_opt_brackets) {
778 src->Register.Dimension = 1;
779 src->Dimension.Indirect = 0;
780 src->Dimension.Dimension = 0;
781 src->Dimension.Index = bracket[0].index;
782 bracket[0] = bracket[1];
784 src->Register.Index = bracket[0].index;
785 if (bracket[0].ind_file != TGSI_FILE_NULL) {
786 src->Register.Indirect = 1;
787 src->Indirect.File = bracket[0].ind_file;
788 src->Indirect.Index = bracket[0].ind_index;
789 src->Indirect.SwizzleX = bracket[0].ind_comp;
790 src->Indirect.SwizzleY = bracket[0].ind_comp;
791 src->Indirect.SwizzleZ = bracket[0].ind_comp;
792 src->Indirect.SwizzleW = bracket[0].ind_comp;
795 /* Parse optional swizzle.
797 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
798 if (parsed_swizzle) {
799 src->Register.SwizzleX = swizzle[0];
800 src->Register.SwizzleY = swizzle[1];
801 src->Register.SwizzleZ = swizzle[2];
802 src->Register.SwizzleW = swizzle[3];
806 if (src->Register.Absolute) {
807 eat_opt_white( &ctx->cur );
808 if (*ctx->cur != '|') {
809 report_error( ctx, "Expected `|'" );
819 static const char *texture_names[TGSI_TEXTURE_COUNT] =
832 static const char *type_names[] =
842 match_inst_mnemonic(const char **pcur,
843 const struct tgsi_opcode_info *info)
845 if (str_match_no_case(pcur, info->mnemonic)) {
853 struct translate_ctx *ctx,
857 uint saturate = TGSI_SAT_NONE;
858 const struct tgsi_opcode_info *info;
859 struct tgsi_full_instruction inst;
862 inst = tgsi_default_full_instruction();
866 eat_opt_white( &ctx->cur );
867 if (*ctx->cur == '(') {
871 boolean parsed_swizzle;
873 inst.Instruction.Predicate = 1;
876 if (*ctx->cur == '!') {
878 inst.Predicate.Negate = 1;
881 if (!parse_register_1d( ctx, &file, &index ))
884 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
885 if (parsed_swizzle) {
886 inst.Predicate.SwizzleX = swizzle[0];
887 inst.Predicate.SwizzleY = swizzle[1];
888 inst.Predicate.SwizzleZ = swizzle[2];
889 inst.Predicate.SwizzleW = swizzle[3];
893 if (*ctx->cur != ')') {
894 report_error( ctx, "Expected `)'" );
901 /* Parse instruction name.
903 eat_opt_white( &ctx->cur );
904 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
905 const char *cur = ctx->cur;
907 info = tgsi_get_opcode_info( i );
908 if (match_inst_mnemonic(&cur, info)) {
909 if (str_match_no_case( &cur, "_SATNV" ))
910 saturate = TGSI_SAT_MINUS_PLUS_ONE;
911 else if (str_match_no_case( &cur, "_SAT" ))
912 saturate = TGSI_SAT_ZERO_ONE;
914 if (info->num_dst + info->num_src + info->is_tex == 0) {
915 if (!is_digit_alpha_underscore( cur )) {
920 else if (*cur == '\0' || eat_white( &cur )) {
926 if (i == TGSI_OPCODE_LAST) {
928 report_error( ctx, "Unknown opcode" );
930 report_error( ctx, "Expected `DCL', `IMM' or a label" );
934 inst.Instruction.Opcode = i;
935 inst.Instruction.Saturate = saturate;
936 inst.Instruction.NumDstRegs = info->num_dst;
937 inst.Instruction.NumSrcRegs = info->num_src;
939 /* Parse instruction operands.
941 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
943 eat_opt_white( &ctx->cur );
944 if (*ctx->cur != ',') {
945 report_error( ctx, "Expected `,'" );
949 eat_opt_white( &ctx->cur );
952 if (i < info->num_dst) {
953 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
956 else if (i < info->num_dst + info->num_src) {
957 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
963 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
964 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
965 if (!is_digit_alpha_underscore( ctx->cur )) {
966 inst.Instruction.Texture = 1;
967 inst.Texture.Texture = j;
972 if (j == TGSI_TEXTURE_COUNT) {
973 report_error( ctx, "Expected texture target" );
979 if (info->is_branch) {
982 eat_opt_white( &ctx->cur );
983 if (*ctx->cur != ':') {
984 report_error( ctx, "Expected `:'" );
988 eat_opt_white( &ctx->cur );
989 if (!parse_uint( &ctx->cur, &target )) {
990 report_error( ctx, "Expected a label" );
993 inst.Instruction.Label = 1;
994 inst.Label.Label = target;
997 advance = tgsi_build_full_instruction(
1001 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1004 ctx->tokens_cur += advance;
1009 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
1025 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
1033 /* parses a 4-touple of the form {x, y, z, w}
1034 * where x, y, z, w are numbers */
1035 static boolean parse_immediate_data(struct translate_ctx *ctx,
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 );
1056 if (!parse_float( &ctx->cur, &values[i] )) {
1057 report_error( ctx, "Expected literal floating point" );
1061 eat_opt_white( &ctx->cur );
1062 if (*ctx->cur != '}') {
1063 report_error( ctx, "Expected `}'" );
1071 static boolean parse_declaration( struct translate_ctx *ctx )
1073 struct tgsi_full_declaration decl;
1075 struct parsed_dcl_bracket brackets[2];
1080 boolean is_vs_input;
1081 boolean is_imm_array;
1083 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
1084 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
1086 if (!eat_white( &ctx->cur )) {
1087 report_error( ctx, "Syntax error" );
1090 if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1092 if (!parse_opt_writemask( ctx, &writemask ))
1095 decl = tgsi_default_full_declaration();
1096 decl.Declaration.File = file;
1097 decl.Declaration.UsageMask = writemask;
1099 if (num_brackets == 1) {
1100 decl.Range.First = brackets[0].first;
1101 decl.Range.Last = brackets[0].last;
1103 decl.Range.First = brackets[1].first;
1104 decl.Range.Last = brackets[1].last;
1106 decl.Declaration.Dimension = 1;
1107 decl.Dim.Index2D = brackets[0].first;
1110 is_vs_input = (file == TGSI_FILE_INPUT &&
1111 ctx->processor == TGSI_PROCESSOR_VERTEX);
1112 is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);
1115 eat_opt_white( &cur );
1116 if (*cur == ',' && !is_vs_input) {
1120 eat_opt_white( &cur );
1121 if (file == TGSI_FILE_RESOURCE) {
1122 for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1123 if (str_match_no_case(&cur, texture_names[i])) {
1124 if (!is_digit_alpha_underscore(cur)) {
1125 decl.Resource.Resource = i;
1130 if (i == TGSI_TEXTURE_COUNT) {
1131 report_error(ctx, "Expected texture target");
1134 eat_opt_white( &cur );
1136 report_error( ctx, "Expected `,'" );
1140 eat_opt_white( &cur );
1141 for (j = 0; j < 4; ++j) {
1142 for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1143 if (str_match_no_case(&cur, type_names[i])) {
1144 if (!is_digit_alpha_underscore(cur)) {
1147 decl.Resource.ReturnTypeX = i;
1150 decl.Resource.ReturnTypeY = i;
1153 decl.Resource.ReturnTypeZ = i;
1156 decl.Resource.ReturnTypeW = i;
1165 if (i == PIPE_TYPE_COUNT) {
1166 if (j == 0 || j > 2) {
1167 report_error(ctx, "Expected type name");
1172 const char *cur2 = cur;
1173 eat_opt_white( &cur2 );
1176 eat_opt_white( &cur2 );
1184 decl.Resource.ReturnTypeY =
1185 decl.Resource.ReturnTypeZ =
1186 decl.Resource.ReturnTypeW =
1187 decl.Resource.ReturnTypeX;
1191 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1192 if (str_match_no_case( &cur, semantic_names[i] )) {
1193 const char *cur2 = cur;
1196 if (is_digit_alpha_underscore( cur ))
1198 eat_opt_white( &cur2 );
1201 eat_opt_white( &cur2 );
1202 if (!parse_uint( &cur2, &index )) {
1203 report_error( ctx, "Expected literal integer" );
1206 eat_opt_white( &cur2 );
1208 report_error( ctx, "Expected `]'" );
1213 decl.Semantic.Index = index;
1218 decl.Declaration.Semantic = 1;
1219 decl.Semantic.Name = i;
1226 } else if (is_imm_array) {
1229 /* we have our immediate data */
1231 report_error( ctx, "Immediate array without data" );
1237 decl.ImmediateData.u =
1238 MALLOC(sizeof(union tgsi_immediate_data) * 4 *
1239 (decl.Range.Last + 1));
1240 vals_itr = (float*)decl.ImmediateData.u;
1241 for (i = 0; i <= decl.Range.Last; ++i) {
1242 if (!parse_immediate_data(ctx, vals_itr)) {
1243 FREE(decl.ImmediateData.u);
1247 eat_opt_white( &ctx->cur );
1248 if (*ctx->cur != ',') {
1249 if (i != decl.Range.Last) {
1250 report_error( ctx, "Not enough data in immediate array!" );
1251 FREE(decl.ImmediateData.u);
1257 eat_opt_white( &ctx->cur );
1258 if (*ctx->cur != '}') {
1259 FREE(decl.ImmediateData.u);
1260 report_error( ctx, "Immediate array data missing closing '}'" );
1267 eat_opt_white( &cur );
1268 if (*cur == ',' && !is_vs_input) {
1272 eat_opt_white( &cur );
1273 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1274 if (str_match_no_case( &cur, interpolate_names[i] )) {
1275 if (is_digit_alpha_underscore( cur ))
1277 decl.Declaration.Interpolate = i;
1283 if (i == TGSI_INTERPOLATE_COUNT) {
1284 report_error( ctx, "Expected semantic or interpolate attribute" );
1289 advance = tgsi_build_full_declaration(
1293 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1296 FREE(decl.ImmediateData.u);
1300 ctx->tokens_cur += advance;
1305 static boolean parse_immediate( struct translate_ctx *ctx )
1307 struct tgsi_full_immediate imm;
1311 if (!eat_white( &ctx->cur )) {
1312 report_error( ctx, "Syntax error" );
1315 if (!str_match_no_case( &ctx->cur, "FLT32" ) ||
1316 is_digit_alpha_underscore( ctx->cur )) {
1317 report_error( ctx, "Expected `FLT32'" );
1321 parse_immediate_data(ctx, values);
1323 imm = tgsi_default_full_immediate();
1324 imm.Immediate.NrTokens += 4;
1325 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1326 imm.u[0].Float = values[0];
1327 imm.u[1].Float = values[1];
1328 imm.u[2].Float = values[2];
1329 imm.u[3].Float = values[3];
1331 advance = tgsi_build_full_immediate(
1335 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1338 ctx->tokens_cur += advance;
1344 parse_primitive( const char **pcur, uint *primitive )
1348 for (i = 0; i < PIPE_PRIM_MAX; i++) {
1349 const char *cur = *pcur;
1351 if (str_match_no_case( &cur, tgsi_primitive_names[i])) {
1361 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1365 for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1366 const char *cur = *pcur;
1368 if (str_match_no_case( &cur, tgsi_fs_coord_origin_names[i])) {
1369 *fs_coord_origin = i;
1378 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1382 for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1383 const char *cur = *pcur;
1385 if (str_match_no_case( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1386 *fs_coord_pixel_center = i;
1395 static boolean parse_property( struct translate_ctx *ctx )
1397 struct tgsi_full_property prop;
1403 if (!eat_white( &ctx->cur )) {
1404 report_error( ctx, "Syntax error" );
1407 if (!parse_identifier( &ctx->cur, id )) {
1408 report_error( ctx, "Syntax error" );
1411 for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1413 if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1417 if (property_name >= TGSI_PROPERTY_COUNT) {
1418 debug_printf( "\nError: Unknown property : '%s'", id );
1422 eat_opt_white( &ctx->cur );
1423 switch(property_name) {
1424 case TGSI_PROPERTY_GS_INPUT_PRIM:
1425 case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1426 if (!parse_primitive(&ctx->cur, &values[0] )) {
1427 report_error( ctx, "Unknown primitive name as property!" );
1430 if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1431 ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1432 ctx->implied_array_size = u_vertices_per_prim(values[0]);
1435 case TGSI_PROPERTY_FS_COORD_ORIGIN:
1436 if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1437 report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1441 case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1442 if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1443 report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1447 case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1449 if (!parse_uint(&ctx->cur, &values[0] )) {
1450 report_error( ctx, "Expected unsigned integer as property!" );
1455 prop = tgsi_default_full_property();
1456 prop.Property.PropertyName = property_name;
1457 prop.Property.NrTokens += 1;
1458 prop.u[0].Data = values[0];
1460 advance = tgsi_build_full_property(
1464 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1467 ctx->tokens_cur += advance;
1473 static boolean translate( struct translate_ctx *ctx )
1475 eat_opt_white( &ctx->cur );
1476 if (!parse_header( ctx ))
1479 while (*ctx->cur != '\0') {
1481 if (!eat_white( &ctx->cur )) {
1482 report_error( ctx, "Syntax error" );
1486 if (*ctx->cur == '\0')
1488 if (parse_label( ctx, &label_val )) {
1489 if (!parse_instruction( ctx, TRUE ))
1492 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1493 if (!parse_declaration( ctx ))
1496 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1497 if (!parse_immediate( ctx ))
1500 else if (str_match_no_case( &ctx->cur, "PROPERTY" )) {
1501 if (!parse_property( ctx ))
1504 else if (!parse_instruction( ctx, FALSE )) {
1513 tgsi_text_translate(
1515 struct tgsi_token *tokens,
1518 struct translate_ctx ctx;
1522 ctx.tokens = tokens;
1523 ctx.tokens_cur = tokens;
1524 ctx.tokens_end = tokens + num_tokens;
1526 if (!translate( &ctx ))
1529 return tgsi_sanity_check( tokens );