X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Ftgsi%2Ftgsi_text.c;h=9779f212cb13cf693e6e74485de18c10539cec43;hb=b4802d6ea13bf547b6e5f9fd0e4059965bf2794a;hp=0b468a9184e0eb8251d36187bce799dc31109dfd;hpb=8f3bdeaad610d7d5a5c6e73e1e9c721219595754;p=mesa.git diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index 0b468a9184e..9779f212cb1 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2008 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -35,7 +35,9 @@ #include "tgsi_info.h" #include "tgsi_parse.h" #include "tgsi_sanity.h" +#include "tgsi_strings.h" #include "tgsi_util.h" +#include "tgsi_dump.h" static boolean is_alpha_underscore( const char *cur ) { @@ -58,7 +60,7 @@ static boolean is_digit_alpha_underscore( const char *cur ) static char uprcase( char c ) { if (c >= 'a' && c <= 'z') - return c += 'A' - 'a'; + return c + 'A' - 'a'; return c; } @@ -79,6 +81,11 @@ streq_nocase_uprcase(const char *str1, return *str1 == 0 && *str2 == 0; } +/* Return TRUE if both strings match. + * The second string is terminated by zero. + * The pointer to the first string is moved at end of the read word + * on success. + */ static boolean str_match_no_case( const char **pcur, const char *str ) { const char *cur = *pcur; @@ -94,6 +101,60 @@ static boolean str_match_no_case( const char **pcur, const char *str ) return FALSE; } +/* Return TRUE if both strings match. + * The first string is be terminated by a non-digit non-letter non-underscore + * character, the second string is terminated by zero. + * The pointer to the first string is moved at end of the read word + * on success. + */ +static boolean str_match_nocase_whole( const char **pcur, const char *str ) +{ + const char *cur = *pcur; + + if (str_match_no_case(&cur, str) && + !is_digit_alpha_underscore(cur)) { + *pcur = cur; + return TRUE; + } + return FALSE; +} + +/* Return the array index that matches starting at *pcur, where the string at + * *pcur is terminated by a non-digit non-letter non-underscore. + * Returns -1 if no match is found. + * + * On success, the pointer to the first string is moved to the end of the read + * word. + */ +static int str_match_name_from_array(const char **pcur, + const char * const *array, + unsigned array_size) +{ + for (unsigned j = 0; j < array_size; ++j) { + if (str_match_nocase_whole(pcur, array[j])) + return j; + } + return -1; +} + +/* Return the format corresponding to the name at *pcur. + * Returns -1 if there is no format name. + * + * On success, the pointer to the string is moved to the end of the read format + * name. + */ +static int str_match_format(const char **pcur) +{ + for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) { + const struct util_format_description *desc = + util_format_description(i); + if (desc && str_match_nocase_whole(pcur, desc->name)) { + return i; + } + } + return -1; +} + /* Eat zero or more whitespaces. */ static void eat_opt_white( const char **pcur ) @@ -130,14 +191,35 @@ static boolean parse_uint( const char **pcur, uint *val ) return FALSE; } -static boolean parse_identifier( const char **pcur, char *ret ) +static boolean parse_int( const char **pcur, int *val ) +{ + const char *cur = *pcur; + int sign = (*cur == '-' ? -1 : 1); + + if (*cur == '+' || *cur == '-') + cur++; + + if (parse_uint(&cur, (uint *)val)) { + *val *= sign; + *pcur = cur; + return TRUE; + } + + return FALSE; +} + +static boolean parse_identifier( const char **pcur, char *ret, size_t len ) { const char *cur = *pcur; - int i = 0; + size_t i = 0; if (is_alpha_underscore( cur )) { ret[i++] = *cur++; - while (is_alpha_underscore( cur )) + while (is_alpha_underscore( cur ) || is_digit( cur )) { + if (i == len - 1) + return FALSE; ret[i++] = *cur++; + } + ret[i++] = '\0'; *pcur = cur; return TRUE; } @@ -152,8 +234,15 @@ static boolean parse_float( const char **pcur, float *val ) boolean integral_part = FALSE; boolean fractional_part = FALSE; - *val = (float) atof( cur ); + if (*cur == '0' && *(cur + 1) == 'x') { + union fi fi; + fi.ui = strtoul(cur, NULL, 16); + *val = fi.f; + cur += 10; + goto out; + } + *val = (float) atof( cur ); if (*cur == '-' || *cur == '+') cur++; if (is_digit( cur )) { @@ -185,10 +274,66 @@ static boolean parse_float( const char **pcur, float *val ) else return FALSE; } + +out: *pcur = cur; return TRUE; } +static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1) +{ + const char *cur = *pcur; + union { + double dval; + uint32_t uval[2]; + } v; + + v.dval = strtod(cur, (char**)pcur); + if (*pcur == cur) + return FALSE; + + *val0 = v.uval[0]; + *val1 = v.uval[1]; + + return TRUE; +} + +static boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1) +{ + const char *cur = *pcur; + union { + int64_t i64val; + uint32_t uval[2]; + } v; + + v.i64val = strtoll(cur, (char**)pcur, 0); + if (*pcur == cur) + return FALSE; + + *val0 = v.uval[0]; + *val1 = v.uval[1]; + + return TRUE; +} + +static boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1) +{ + const char *cur = *pcur; + union { + uint64_t u64val; + uint32_t uval[2]; + } v; + + v.u64val = strtoull(cur, (char**)pcur, 0); + if (*pcur == cur) + return FALSE; + + *val0 = v.uval[0]; + *val1 = v.uval[1]; + + return TRUE; +} + struct translate_ctx { const char *text; @@ -198,7 +343,8 @@ struct translate_ctx struct tgsi_token *tokens_end; struct tgsi_header *header; unsigned processor : 4; - int implied_array_size : 5; + unsigned implied_array_size : 6; + unsigned num_immediates; }; static void report_error( struct translate_ctx *ctx, const char *msg ) @@ -229,12 +375,18 @@ static boolean parse_header( struct translate_ctx *ctx ) { uint processor; - if (str_match_no_case( &ctx->cur, "FRAG" )) - processor = TGSI_PROCESSOR_FRAGMENT; - else if (str_match_no_case( &ctx->cur, "VERT" )) - processor = TGSI_PROCESSOR_VERTEX; - else if (str_match_no_case( &ctx->cur, "GEOM" )) - processor = TGSI_PROCESSOR_GEOMETRY; + if (str_match_nocase_whole( &ctx->cur, "FRAG" )) + processor = PIPE_SHADER_FRAGMENT; + else if (str_match_nocase_whole( &ctx->cur, "VERT" )) + processor = PIPE_SHADER_VERTEX; + else if (str_match_nocase_whole( &ctx->cur, "GEOM" )) + processor = PIPE_SHADER_GEOMETRY; + else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" )) + processor = PIPE_SHADER_TESS_CTRL; + else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" )) + processor = PIPE_SHADER_TESS_EVAL; + else if (str_match_nocase_whole( &ctx->cur, "COMP" )) + processor = PIPE_SHADER_COMPUTE; else { report_error( ctx, "Unknown header" ); return FALSE; @@ -268,21 +420,6 @@ static boolean parse_label( struct translate_ctx *ctx, uint *val ) return FALSE; } -static const char *file_names[TGSI_FILE_COUNT] = -{ - "NULL", - "CONST", - "IN", - "OUT", - "TEMP", - "SAMP", - "ADDR", - "IMM", - "LOOP", - "PRED", - "SV" -}; - static boolean parse_file( const char **pcur, uint *file ) { @@ -291,12 +428,10 @@ parse_file( const char **pcur, uint *file ) for (i = 0; i < TGSI_FILE_COUNT; i++) { const char *cur = *pcur; - if (str_match_no_case( &cur, file_names[i] )) { - if (!is_digit_alpha_underscore( cur )) { - *pcur = cur; - *file = i; - return TRUE; - } + if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) { + *pcur = cur; + *file = i; + return TRUE; } } return FALSE; @@ -345,36 +480,93 @@ parse_opt_writemask( return TRUE; } + +/* ::= `[' + */ +static boolean +parse_register_file_bracket( + struct translate_ctx *ctx, + uint *file ) +{ + if (!parse_file( &ctx->cur, file )) { + report_error( ctx, "Unknown register file" ); + return FALSE; + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '[') { + report_error( ctx, "Expected `['" ); + return FALSE; + } + ctx->cur++; + return TRUE; +} + +/* ::= + */ +static boolean +parse_register_file_bracket_index( + struct translate_ctx *ctx, + uint *file, + int *index ) +{ + uint uindex; + + if (!parse_register_file_bracket( ctx, file )) + return FALSE; + eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &uindex )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + *index = (int) uindex; + return TRUE; +} + +/* Parse simple 1d register operand. + * ::= `]' + */ static boolean -parse_register_dst( struct translate_ctx *ctx, - uint *file, - int *index ); +parse_register_1d(struct translate_ctx *ctx, + uint *file, + int *index ) +{ + if (!parse_register_file_bracket_index( ctx, file, index )) + return FALSE; + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + ctx->cur++; + return TRUE; +} -struct parsed_src_bracket { +struct parsed_bracket { int index; uint ind_file; int ind_index; uint ind_comp; + uint ind_array; }; static boolean -parse_register_src_bracket( +parse_register_bracket( struct translate_ctx *ctx, - struct parsed_src_bracket *brackets) + struct parsed_bracket *brackets) { const char *cur; uint uindex; - memset(brackets, 0, sizeof(struct parsed_src_bracket)); + memset(brackets, 0, sizeof(struct parsed_bracket)); eat_opt_white( &ctx->cur ); cur = ctx->cur; if (parse_file( &cur, &brackets->ind_file )) { - if (!parse_register_dst( ctx, &brackets->ind_file, - &brackets->ind_index )) + if (!parse_register_1d( ctx, &brackets->ind_file, + &brackets->ind_index )) return FALSE; eat_opt_white( &ctx->cur ); @@ -403,24 +595,10 @@ parse_register_src_bracket( eat_opt_white(&ctx->cur); } - if (*ctx->cur == '+' || *ctx->cur == '-') { - boolean negate; - - negate = *ctx->cur == '-'; - ctx->cur++; - eat_opt_white( &ctx->cur ); - if (!parse_uint( &ctx->cur, &uindex )) { - report_error( ctx, "Expected literal unsigned integer" ); - return FALSE; - } - if (negate) - brackets->index = -(int) uindex; - else - brackets->index = (int) uindex; - } - else { + if (*ctx->cur == '+' || *ctx->cur == '-') + parse_int( &ctx->cur, &brackets->index ); + else brackets->index = 0; - } } else { if (!parse_uint( &ctx->cur, &uindex )) { @@ -437,13 +615,27 @@ parse_register_src_bracket( return FALSE; } ctx->cur++; + if (*ctx->cur == '(') { + ctx->cur++; + eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &brackets->ind_array )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ')') { + report_error( ctx, "Expected `)'" ); + return FALSE; + } + ctx->cur++; + } return TRUE; } static boolean parse_opt_register_src_bracket( struct translate_ctx *ctx, - struct parsed_src_bracket *brackets, + struct parsed_bracket *brackets, int *parsed_brackets) { const char *cur = ctx->cur; @@ -455,7 +647,7 @@ parse_opt_register_src_bracket( ++cur; ctx->cur = cur; - if (!parse_register_src_bracket(ctx, brackets)) + if (!parse_register_bracket(ctx, brackets)) return FALSE; *parsed_brackets = 1; @@ -464,46 +656,6 @@ parse_opt_register_src_bracket( return TRUE; } -/* ::= `[' - */ -static boolean -parse_register_file_bracket( - struct translate_ctx *ctx, - uint *file ) -{ - if (!parse_file( &ctx->cur, file )) { - report_error( ctx, "Unknown register file" ); - return FALSE; - } - eat_opt_white( &ctx->cur ); - if (*ctx->cur != '[') { - report_error( ctx, "Expected `['" ); - return FALSE; - } - ctx->cur++; - return TRUE; -} - -/* ::= - */ -static boolean -parse_register_file_bracket_index( - struct translate_ctx *ctx, - uint *file, - int *index ) -{ - uint uindex; - - if (!parse_register_file_bracket( ctx, file )) - return FALSE; - eat_opt_white( &ctx->cur ); - if (!parse_uint( &ctx->cur, &uindex )) { - report_error( ctx, "Expected literal unsigned integer" ); - return FALSE; - } - *index = (int) uindex; - return TRUE; -} /* Parse source register operand. * ::= `]' | @@ -515,13 +667,12 @@ static boolean parse_register_src( struct translate_ctx *ctx, uint *file, - struct parsed_src_bracket *brackets) + struct parsed_bracket *brackets) { - brackets->ind_comp = TGSI_SWIZZLE_X; if (!parse_register_file_bracket( ctx, file )) return FALSE; - if (!parse_register_src_bracket( ctx, brackets )) + if (!parse_register_bracket( ctx, brackets )) return FALSE; return TRUE; @@ -608,6 +759,9 @@ parse_register_dcl( eat_opt_white( &cur ); if (cur[0] == '[') { + bool is_in = *file == TGSI_FILE_INPUT; + bool is_out = *file == TGSI_FILE_OUTPUT; + ++cur; ctx->cur = cur; if (!parse_register_dcl_bracket( ctx, &brackets[1] )) @@ -617,7 +771,11 @@ parse_register_dcl( * input primitive. so we want to declare just * the index relevant to the semantics which is in * the second bracket */ - if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) { + + /* tessellation has similar constraints to geometry shader */ + if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) || + (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) || + (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) { brackets[0] = brackets[1]; *num_brackets = 1; } else { @@ -629,23 +787,19 @@ parse_register_dcl( } -/* Parse destination register operand. - * ::= `]' - */ +/* Parse destination register operand.*/ static boolean parse_register_dst( struct translate_ctx *ctx, uint *file, - int *index ) + struct parsed_bracket *brackets) { - if (!parse_register_file_bracket_index( ctx, file, index )) - return FALSE; - eat_opt_white( &ctx->cur ); - if (*ctx->cur != ']') { - report_error( ctx, "Expected `]'" ); + brackets->ind_comp = TGSI_SWIZZLE_X; + if (!parse_register_file_bracket( ctx, file )) return FALSE; - } - ctx->cur++; + if (!parse_register_bracket( ctx, brackets )) + return FALSE; + return TRUE; } @@ -655,11 +809,14 @@ parse_dst_operand( struct tgsi_full_dst_register *dst ) { uint file; - int index; uint writemask; const char *cur; + struct parsed_bracket bracket[2]; + int parsed_opt_brackets; - if (!parse_register_dst( ctx, &file, &index )) + if (!parse_register_dst( ctx, &file, &bracket[0] )) + return FALSE; + if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) return FALSE; cur = ctx->cur; @@ -669,16 +826,39 @@ parse_dst_operand( return FALSE; dst->Register.File = file; - dst->Register.Index = index; + if (parsed_opt_brackets) { + dst->Register.Dimension = 1; + dst->Dimension.Indirect = 0; + dst->Dimension.Dimension = 0; + dst->Dimension.Index = bracket[0].index; + + if (bracket[0].ind_file != TGSI_FILE_NULL) { + dst->Dimension.Indirect = 1; + dst->DimIndirect.File = bracket[0].ind_file; + dst->DimIndirect.Index = bracket[0].ind_index; + dst->DimIndirect.Swizzle = bracket[0].ind_comp; + dst->DimIndirect.ArrayID = bracket[0].ind_array; + } + bracket[0] = bracket[1]; + } + dst->Register.Index = bracket[0].index; dst->Register.WriteMask = writemask; + if (bracket[0].ind_file != TGSI_FILE_NULL) { + dst->Register.Indirect = 1; + dst->Indirect.File = bracket[0].ind_file; + dst->Indirect.Index = bracket[0].ind_index; + dst->Indirect.Swizzle = bracket[0].ind_comp; + dst->Indirect.ArrayID = bracket[0].ind_array; + } return TRUE; } static boolean parse_optional_swizzle( struct translate_ctx *ctx, - uint swizzle[4], - boolean *parsed_swizzle ) + uint *swizzle, + boolean *parsed_swizzle, + int components) { const char *cur = ctx->cur; @@ -686,11 +866,11 @@ parse_optional_swizzle( eat_opt_white( &cur ); if (*cur == '.') { - uint i; + int i; cur++; eat_opt_white( &cur ); - for (i = 0; i < 4; i++) { + for (i = 0; i < components; i++) { if (uprcase( *cur ) == 'X') swizzle[i] = TGSI_SWIZZLE_X; else if (uprcase( *cur ) == 'Y') @@ -700,7 +880,7 @@ parse_optional_swizzle( else if (uprcase( *cur ) == 'W') swizzle[i] = TGSI_SWIZZLE_W; else { - report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" ); + report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" ); return FALSE; } cur++; @@ -719,7 +899,7 @@ parse_src_operand( uint file; uint swizzle[4]; boolean parsed_swizzle; - struct parsed_src_bracket bracket[2]; + struct parsed_bracket bracket[2]; int parsed_opt_brackets; if (*ctx->cur == '-') { @@ -745,6 +925,13 @@ parse_src_operand( src->Dimension.Indirect = 0; src->Dimension.Dimension = 0; src->Dimension.Index = bracket[0].index; + if (bracket[0].ind_file != TGSI_FILE_NULL) { + src->Dimension.Indirect = 1; + src->DimIndirect.File = bracket[0].ind_file; + src->DimIndirect.Index = bracket[0].ind_index; + src->DimIndirect.Swizzle = bracket[0].ind_comp; + src->DimIndirect.ArrayID = bracket[0].ind_array; + } bracket[0] = bracket[1]; } src->Register.Index = bracket[0].index; @@ -752,15 +939,13 @@ parse_src_operand( src->Register.Indirect = 1; src->Indirect.File = bracket[0].ind_file; src->Indirect.Index = bracket[0].ind_index; - src->Indirect.SwizzleX = bracket[0].ind_comp; - src->Indirect.SwizzleY = bracket[0].ind_comp; - src->Indirect.SwizzleZ = bracket[0].ind_comp; - src->Indirect.SwizzleW = bracket[0].ind_comp; + src->Indirect.Swizzle = bracket[0].ind_comp; + src->Indirect.ArrayID = bracket[0].ind_array; } /* Parse optional swizzle. */ - if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) { + if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { if (parsed_swizzle) { src->Register.SwizzleX = swizzle[0]; src->Register.SwizzleY = swizzle[1]; @@ -782,26 +967,68 @@ parse_src_operand( return TRUE; } -static const char *texture_names[TGSI_TEXTURE_COUNT] = +static boolean +parse_texoffset_operand( + struct translate_ctx *ctx, + struct tgsi_texture_offset *src ) { - "UNKNOWN", - "1D", - "2D", - "3D", - "CUBE", - "RECT", - "SHADOW1D", - "SHADOW2D", - "SHADOWRECT" -}; + uint file; + uint swizzle[3]; + boolean parsed_swizzle; + struct parsed_bracket bracket; + + if (!parse_register_src(ctx, &file, &bracket)) + return FALSE; + + src->File = file; + src->Index = bracket.index; + + /* Parse optional swizzle. + */ + if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) { + if (parsed_swizzle) { + src->SwizzleX = swizzle[0]; + src->SwizzleY = swizzle[1]; + src->SwizzleZ = swizzle[2]; + } + } + + return TRUE; +} static boolean -match_inst_mnemonic(const char **pcur, - const struct tgsi_opcode_info *info) +match_inst(const char **pcur, + unsigned *saturate, + unsigned *precise, + const struct tgsi_opcode_info *info) { - if (str_match_no_case(pcur, info->mnemonic)) { + const char *cur = *pcur; + const char *mnemonic = tgsi_get_opcode_name(info->opcode); + + /* simple case: the whole string matches the instruction name */ + if (str_match_nocase_whole(&cur, mnemonic)) { + *pcur = cur; + *saturate = 0; + *precise = 0; return TRUE; } + + if (str_match_no_case(&cur, mnemonic)) { + /* the instruction has a suffix, figure it out */ + if (str_match_no_case(&cur, "_SAT")) { + *pcur = cur; + *saturate = 1; + } + + if (str_match_no_case(&cur, "_PRECISE")) { + *pcur = cur; + *precise = 1; + } + + if (!is_digit_alpha_underscore(cur)) + return TRUE; + } + return FALSE; } @@ -810,30 +1037,27 @@ parse_instruction( struct translate_ctx *ctx, boolean has_label ) { - uint i; - uint saturate = TGSI_SAT_NONE; + int i; + uint saturate = 0; + uint precise = 0; const struct tgsi_opcode_info *info; struct tgsi_full_instruction inst; + const char *cur; uint advance; + inst = tgsi_default_full_instruction(); + /* Parse instruction name. */ eat_opt_white( &ctx->cur ); for (i = 0; i < TGSI_OPCODE_LAST; i++) { - const char *cur = ctx->cur; + cur = ctx->cur; info = tgsi_get_opcode_info( i ); - if (match_inst_mnemonic(&cur, info)) { - if (str_match_no_case( &cur, "_SATNV" )) - saturate = TGSI_SAT_MINUS_PLUS_ONE; - else if (str_match_no_case( &cur, "_SAT" )) - saturate = TGSI_SAT_ZERO_ONE; - + if (match_inst(&cur, &saturate, &precise, info)) { if (info->num_dst + info->num_src + info->is_tex == 0) { - if (!is_digit_alpha_underscore( cur )) { - ctx->cur = cur; - break; - } + ctx->cur = cur; + break; } else if (*cur == '\0' || eat_white( &cur )) { ctx->cur = cur; @@ -849,12 +1073,31 @@ parse_instruction( return FALSE; } - inst = tgsi_default_full_instruction(); inst.Instruction.Opcode = i; inst.Instruction.Saturate = saturate; + inst.Instruction.Precise = precise; inst.Instruction.NumDstRegs = info->num_dst; inst.Instruction.NumSrcRegs = info->num_src; + if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { + /* + * These are not considered tex opcodes here (no additional + * target argument) however we're required to set the Texture + * bit so we can set the number of tex offsets. + */ + inst.Instruction.Texture = 1; + inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; + } + + if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || + i == TGSI_OPCODE_RESQ) { + inst.Instruction.Memory = 1; + inst.Memory.Qualifier = 0; + } + + assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); + assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); + /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { @@ -880,12 +1123,10 @@ parse_instruction( uint j; for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { - if (str_match_no_case( &ctx->cur, texture_names[j] )) { - if (!is_digit_alpha_underscore( ctx->cur )) { - inst.Instruction.Texture = 1; - inst.Texture.Texture = j; - break; - } + if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { + inst.Instruction.Texture = 1; + inst.Texture.Texture = j; + break; } } if (j == TGSI_TEXTURE_COUNT) { @@ -895,22 +1136,68 @@ parse_instruction( } } - if (info->is_branch) { - uint target; + cur = ctx->cur; + eat_opt_white( &cur ); + for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) { + cur++; + eat_opt_white( &cur ); + ctx->cur = cur; + if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) + return FALSE; + cur = ctx->cur; + eat_opt_white( &cur ); + } + inst.Texture.NumOffsets = i; - eat_opt_white( &ctx->cur ); - if (*ctx->cur != ':') { - report_error( ctx, "Expected `:'" ); - return FALSE; + cur = ctx->cur; + eat_opt_white(&cur); + + for (; inst.Instruction.Memory && *cur == ','; + ctx->cur = cur, eat_opt_white(&cur)) { + int j; + + cur++; + eat_opt_white(&cur); + + j = str_match_name_from_array(&cur, tgsi_memory_names, + ARRAY_SIZE(tgsi_memory_names)); + if (j >= 0) { + inst.Memory.Qualifier |= 1U << j; + continue; } - ctx->cur++; - eat_opt_white( &ctx->cur ); - if (!parse_uint( &ctx->cur, &target )) { + + j = str_match_name_from_array(&cur, tgsi_texture_names, + ARRAY_SIZE(tgsi_texture_names)); + if (j >= 0) { + inst.Memory.Texture = j; + continue; + } + + j = str_match_format(&cur); + if (j >= 0) { + inst.Memory.Format = j; + continue; + } + + ctx->cur = cur; + report_error(ctx, "Expected memory qualifier, texture target, or format\n"); + return FALSE; + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (info->is_branch && *cur == ':') { + uint target; + + cur++; + eat_opt_white( &cur ); + if (!parse_uint( &cur, &target )) { report_error( ctx, "Expected a label" ); return FALSE; } inst.Instruction.Label = 1; inst.Label.Label = target; + ctx->cur = cur; } advance = tgsi_build_full_instruction( @@ -925,27 +1212,73 @@ parse_instruction( return TRUE; } -static const char *semantic_names[TGSI_SEMANTIC_COUNT] = +/* parses a 4-touple of the form {x, y, z, w} + * where x, y, z, w are numbers */ +static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type, + union tgsi_immediate_data *values) { - "POSITION", - "COLOR", - "BCOLOR", - "FOG", - "PSIZE", - "GENERIC", - "NORMAL", - "FACE", - "EDGEFLAG", - "PRIM_ID", - "INSTANCEID" -}; + unsigned i; + int ret; -static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] = -{ - "CONSTANT", - "LINEAR", - "PERSPECTIVE" -}; + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '{') { + report_error( ctx, "Expected `{'" ); + return FALSE; + } + ctx->cur++; + for (i = 0; i < 4; i++) { + eat_opt_white( &ctx->cur ); + if (i > 0) { + if (*ctx->cur != ',') { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + ctx->cur++; + eat_opt_white( &ctx->cur ); + } + + switch (type) { + case TGSI_IMM_FLOAT64: + ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint); + i++; + break; + case TGSI_IMM_INT64: + ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); + i++; + break; + case TGSI_IMM_UINT64: + ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint); + i++; + break; + case TGSI_IMM_FLOAT32: + ret = parse_float(&ctx->cur, &values[i].Float); + break; + case TGSI_IMM_UINT32: + ret = parse_uint(&ctx->cur, &values[i].Uint); + break; + case TGSI_IMM_INT32: + ret = parse_int(&ctx->cur, &values[i].Int); + break; + default: + assert(0); + ret = FALSE; + break; + } + + if (!ret) { + report_error( ctx, "Expected immediate constant" ); + return FALSE; + } + } + eat_opt_white( &ctx->cur ); + if (*ctx->cur != '}') { + report_error( ctx, "Expected `}'" ); + return FALSE; + } + ctx->cur++; + + return TRUE; +} static boolean parse_declaration( struct translate_ctx *ctx ) { @@ -954,11 +1287,9 @@ static boolean parse_declaration( struct translate_ctx *ctx ) struct parsed_dcl_bracket brackets[2]; int num_brackets; uint writemask; - const char *cur; + const char *cur, *cur2; uint advance; - - assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT); - assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT); + boolean is_vs_input; if (!eat_white( &ctx->cur )) { report_error( ctx, "Syntax error" ); @@ -984,42 +1315,272 @@ static boolean parse_declaration( struct translate_ctx *ctx ) decl.Dim.Index2D = brackets[0].first; } + is_vs_input = (file == TGSI_FILE_INPUT && + ctx->processor == PIPE_SHADER_VERTEX); + cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',') { - uint i; + cur2 = cur; + cur2++; + eat_opt_white( &cur2 ); + if (str_match_nocase_whole( &cur2, "ARRAY" )) { + int arrayid; + if (*cur2 != '(') { + report_error( ctx, "Expected `('" ); + return FALSE; + } + cur2++; + eat_opt_white( &cur2 ); + if (!parse_int( &cur2, &arrayid )) { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + eat_opt_white( &cur2 ); + if (*cur2 != ')') { + report_error( ctx, "Expected `)'" ); + return FALSE; + } + cur2++; + decl.Declaration.Array = 1; + decl.Array.ArrayID = arrayid; + ctx->cur = cur = cur2; + } + } + + if (*cur == ',' && !is_vs_input) { + uint i, j; cur++; eat_opt_white( &cur ); - for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { - if (str_match_no_case( &cur, semantic_names[i] )) { - const char *cur2 = cur; - uint index; - - if (is_digit_alpha_underscore( cur )) - continue; - eat_opt_white( &cur2 ); - if (*cur2 == '[') { - cur2++; - eat_opt_white( &cur2 ); - if (!parse_uint( &cur2, &index )) { - report_error( ctx, "Expected literal integer" ); + if (file == TGSI_FILE_IMAGE) { + for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { + if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { + decl.Image.Resource = i; + break; + } + } + if (i == TGSI_TEXTURE_COUNT) { + report_error(ctx, "Expected texture target"); + return FALSE; + } + + cur2 = cur; + eat_opt_white(&cur2); + while (*cur2 == ',') { + cur2++; + eat_opt_white(&cur2); + if (str_match_nocase_whole(&cur2, "RAW")) { + decl.Image.Raw = 1; + + } else if (str_match_nocase_whole(&cur2, "WR")) { + decl.Image.Writable = 1; + + } else { + int format = str_match_format(&cur2); + if (format < 0) + break; + + decl.Image.Format = format; + } + cur = cur2; + eat_opt_white(&cur2); + } + + ctx->cur = cur; + + } else if (file == TGSI_FILE_SAMPLER_VIEW) { + for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { + if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { + decl.SamplerView.Resource = i; + break; + } + } + if (i == TGSI_TEXTURE_COUNT) { + report_error(ctx, "Expected texture target"); + return FALSE; + } + eat_opt_white( &cur ); + if (*cur != ',') { + report_error( ctx, "Expected `,'" ); + return FALSE; + } + ++cur; + eat_opt_white( &cur ); + for (j = 0; j < 4; ++j) { + for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { + if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { + switch (j) { + case 0: + decl.SamplerView.ReturnTypeX = i; + break; + case 1: + decl.SamplerView.ReturnTypeY = i; + break; + case 2: + decl.SamplerView.ReturnTypeZ = i; + break; + case 3: + decl.SamplerView.ReturnTypeW = i; + break; + default: + assert(0); + } + break; + } + } + if (i == TGSI_RETURN_TYPE_COUNT) { + if (j == 0 || j > 2) { + report_error(ctx, "Expected type name"); return FALSE; } + break; + } else { + cur2 = cur; eat_opt_white( &cur2 ); - if (*cur2 != ']') { - report_error( ctx, "Expected `]'" ); - return FALSE; + if (*cur2 == ',') { + cur2++; + eat_opt_white( &cur2 ); + cur = cur2; + continue; + } else + break; + } + } + if (j < 4) { + decl.SamplerView.ReturnTypeY = + decl.SamplerView.ReturnTypeZ = + decl.SamplerView.ReturnTypeW = + decl.SamplerView.ReturnTypeX; + } + ctx->cur = cur; + } else if (file == TGSI_FILE_BUFFER) { + if (str_match_nocase_whole(&cur, "ATOMIC")) { + decl.Declaration.Atomic = 1; + ctx->cur = cur; + } + } else if (file == TGSI_FILE_MEMORY) { + if (str_match_nocase_whole(&cur, "GLOBAL")) { + /* Note this is a no-op global is the default */ + decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL; + ctx->cur = cur; + } else if (str_match_nocase_whole(&cur, "SHARED")) { + decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED; + ctx->cur = cur; + } else if (str_match_nocase_whole(&cur, "PRIVATE")) { + decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE; + ctx->cur = cur; + } else if (str_match_nocase_whole(&cur, "INPUT")) { + decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT; + ctx->cur = cur; + } + } else { + if (str_match_nocase_whole(&cur, "LOCAL")) { + decl.Declaration.Local = 1; + ctx->cur = cur; + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',') { + cur++; + eat_opt_white( &cur ); + + for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { + if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { + uint index; + + cur2 = cur; + eat_opt_white( &cur2 ); + if (*cur2 == '[') { + cur2++; + eat_opt_white( &cur2 ); + if (!parse_uint( &cur2, &index )) { + report_error( ctx, "Expected literal integer" ); + return FALSE; + } + eat_opt_white( &cur2 ); + if (*cur2 != ']') { + report_error( ctx, "Expected `]'" ); + return FALSE; + } + cur2++; + + decl.Semantic.Index = index; + + cur = cur2; + } + + decl.Declaration.Semantic = 1; + decl.Semantic.Name = i; + + ctx->cur = cur; + break; } - cur2++; + } + } + } + } - decl.Semantic.Index = index; + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',' && + file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) { + cur++; + eat_opt_white(&cur); + if (str_match_nocase_whole(&cur, "STREAM")) { + uint stream[4]; + + eat_opt_white(&cur); + if (*cur != '(') { + report_error(ctx, "Expected '('"); + return FALSE; + } + cur++; + + for (int i = 0; i < 4; ++i) { + eat_opt_white(&cur); + if (!parse_uint(&cur, &stream[i])) { + report_error(ctx, "Expected literal integer"); + return FALSE; + } - cur = cur2; + eat_opt_white(&cur); + if (i < 3) { + if (*cur != ',') { + report_error(ctx, "Expected ','"); + return FALSE; + } + cur++; } + } + + if (*cur != ')') { + report_error(ctx, "Expected ')'"); + return FALSE; + } + cur++; - decl.Declaration.Semantic = 1; - decl.Semantic.Name = i; + decl.Semantic.StreamX = stream[0]; + decl.Semantic.StreamY = stream[1]; + decl.Semantic.StreamZ = stream[2]; + decl.Semantic.StreamW = stream[3]; + + ctx->cur = cur; + } + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',' && !is_vs_input) { + uint i; + + cur++; + eat_opt_white( &cur ); + for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { + if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { + decl.Declaration.Interpolate = 1; + decl.Interp.Interpolate = i; ctx->cur = cur; break; @@ -1029,23 +1590,31 @@ static boolean parse_declaration( struct translate_ctx *ctx ) cur = ctx->cur; eat_opt_white( &cur ); - if (*cur == ',') { + if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); - for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { - if (str_match_no_case( &cur, interpolate_names[i] )) { - if (is_digit_alpha_underscore( cur )) - continue; - decl.Declaration.Interpolate = i; + for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { + if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { + decl.Interp.Location = i; ctx->cur = cur; break; } } - if (i == TGSI_INTERPOLATE_COUNT) { - report_error( ctx, "Expected semantic or interpolate attribute" ); + } + + cur = ctx->cur; + eat_opt_white( &cur ); + if (*cur == ',' && !is_vs_input) { + cur++; + eat_opt_white( &cur ); + if (str_match_nocase_whole( &cur, tgsi_invariant_name )) { + decl.Declaration.Invariant = 1; + ctx->cur = cur; + } else { + report_error( ctx, "Expected semantic, interpolate attribute, or invariant "); return FALSE; } } @@ -1055,6 +1624,7 @@ static boolean parse_declaration( struct translate_ctx *ctx ) ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); + if (advance == 0) return FALSE; ctx->tokens_cur += advance; @@ -1065,53 +1635,51 @@ static boolean parse_declaration( struct translate_ctx *ctx ) static boolean parse_immediate( struct translate_ctx *ctx ) { struct tgsi_full_immediate imm; - uint i; - float values[4]; uint advance; + uint type; + + if (*ctx->cur == '[') { + uint uindex; + + ++ctx->cur; - if (!eat_white( &ctx->cur )) { - report_error( ctx, "Syntax error" ); - return FALSE; - } - if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) { - report_error( ctx, "Expected `FLT32'" ); - return FALSE; - } - eat_opt_white( &ctx->cur ); - if (*ctx->cur != '{') { - report_error( ctx, "Expected `{'" ); - return FALSE; - } - ctx->cur++; - for (i = 0; i < 4; i++) { eat_opt_white( &ctx->cur ); - if (i > 0) { - if (*ctx->cur != ',') { - report_error( ctx, "Expected `,'" ); - return FALSE; - } - ctx->cur++; - eat_opt_white( &ctx->cur ); + if (!parse_uint( &ctx->cur, &uindex )) { + report_error( ctx, "Expected literal unsigned integer" ); + return FALSE; } - if (!parse_float( &ctx->cur, &values[i] )) { - report_error( ctx, "Expected literal floating point" ); + + if (uindex != ctx->num_immediates) { + report_error( ctx, "Immediates must be sorted" ); + return FALSE; + } + + eat_opt_white( &ctx->cur ); + if (*ctx->cur != ']') { + report_error( ctx, "Expected `]'" ); return FALSE; } + + ctx->cur++; } - eat_opt_white( &ctx->cur ); - if (*ctx->cur != '}') { - report_error( ctx, "Expected `}'" ); + + if (!eat_white( &ctx->cur )) { + report_error( ctx, "Syntax error" ); + return FALSE; + } + for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) { + if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type])) + break; + } + if (type == ARRAY_SIZE(tgsi_immediate_type_names)) { + report_error( ctx, "Expected immediate type" ); return FALSE; } - ctx->cur++; imm = tgsi_default_full_immediate(); imm.Immediate.NrTokens += 4; - imm.Immediate.DataType = TGSI_IMM_FLOAT32; - imm.u[0].Float = values[0]; - imm.u[1].Float = values[1]; - imm.u[2].Float = values[2]; - imm.u[3].Float = values[3]; + imm.Immediate.DataType = type; + parse_immediate_data(ctx, type, imm.u); advance = tgsi_build_full_immediate( &imm, @@ -1122,45 +1690,11 @@ static boolean parse_immediate( struct translate_ctx *ctx ) return FALSE; ctx->tokens_cur += advance; + ctx->num_immediates++; + return TRUE; } -static const char *property_names[] = -{ - "GS_INPUT_PRIMITIVE", - "GS_OUTPUT_PRIMITIVE", - "GS_MAX_OUTPUT_VERTICES", - "FS_COORD_ORIGIN", - "FS_COORD_PIXEL_CENTER" -}; - -static const char *primitive_names[] = -{ - "POINTS", - "LINES", - "LINE_LOOP", - "LINE_STRIP", - "TRIANGLES", - "TRIANGLE_STRIP", - "TRIANGLE_FAN", - "QUADS", - "QUAD_STRIP", - "POLYGON" -}; - -static const char *fs_coord_origin_names[] = -{ - "UPPER_LEFT", - "LOWER_LEFT" -}; - -static const char *fs_coord_pixel_center_names[] = -{ - "HALF_INTEGER", - "INTEGER" -}; - - static boolean parse_primitive( const char **pcur, uint *primitive ) { @@ -1169,7 +1703,7 @@ parse_primitive( const char **pcur, uint *primitive ) for (i = 0; i < PIPE_PRIM_MAX; i++) { const char *cur = *pcur; - if (str_match_no_case( &cur, primitive_names[i])) { + if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) { *primitive = i; *pcur = cur; return TRUE; @@ -1183,10 +1717,10 @@ parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin ) { uint i; - for (i = 0; i < sizeof(fs_coord_origin_names) / sizeof(fs_coord_origin_names[0]); i++) { + for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) { const char *cur = *pcur; - if (str_match_no_case( &cur, fs_coord_origin_names[i])) { + if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) { *fs_coord_origin = i; *pcur = cur; return TRUE; @@ -1200,10 +1734,10 @@ parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) { uint i; - for (i = 0; i < sizeof(fs_coord_pixel_center_names) / sizeof(fs_coord_pixel_center_names[0]); i++) { + for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) { const char *cur = *pcur; - if (str_match_no_case( &cur, fs_coord_pixel_center_names[i])) { + if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) { *fs_coord_pixel_center = i; *pcur = cur; return TRUE; @@ -1212,6 +1746,22 @@ parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center ) return FALSE; } +static boolean +parse_property_next_shader( const char **pcur, uint *next_shader ) +{ + uint i; + + for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) { + const char *cur = *pcur; + + if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) { + *next_shader = i; + *pcur = cur; + return TRUE; + } + } + return FALSE; +} static boolean parse_property( struct translate_ctx *ctx ) { @@ -1225,13 +1775,13 @@ static boolean parse_property( struct translate_ctx *ctx ) report_error( ctx, "Syntax error" ); return FALSE; } - if (!parse_identifier( &ctx->cur, id )) { + if (!parse_identifier( &ctx->cur, id, sizeof(id) )) { report_error( ctx, "Syntax error" ); return FALSE; } for (property_name = 0; property_name < TGSI_PROPERTY_COUNT; ++property_name) { - if (streq_nocase_uprcase(property_names[property_name], id)) { + if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) { break; } } @@ -1249,7 +1799,7 @@ static boolean parse_property( struct translate_ctx *ctx ) return FALSE; } if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM && - ctx->processor == TGSI_PROCESSOR_GEOMETRY) { + ctx->processor == PIPE_SHADER_GEOMETRY) { ctx->implied_array_size = u_vertices_per_prim(values[0]); } break; @@ -1265,6 +1815,13 @@ static boolean parse_property( struct translate_ctx *ctx ) return FALSE; } break; + case TGSI_PROPERTY_NEXT_SHADER: + if (!parse_property_next_shader(&ctx->cur, &values[0] )) { + report_error( ctx, "Unknown next shader property value." ); + return FALSE; + } + break; + case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: default: if (!parse_uint(&ctx->cur, &values[0] )) { report_error( ctx, "Expected unsigned integer as property!" ); @@ -1296,6 +1853,10 @@ static boolean translate( struct translate_ctx *ctx ) if (!parse_header( ctx )) return FALSE; + if (ctx->processor == PIPE_SHADER_TESS_CTRL || + ctx->processor == PIPE_SHADER_TESS_EVAL) + ctx->implied_array_size = 32; + while (*ctx->cur != '\0') { uint label_val = 0; if (!eat_white( &ctx->cur )) { @@ -1309,15 +1870,15 @@ static boolean translate( struct translate_ctx *ctx ) if (!parse_instruction( ctx, TRUE )) return FALSE; } - else if (str_match_no_case( &ctx->cur, "DCL" )) { + else if (str_match_nocase_whole( &ctx->cur, "DCL" )) { if (!parse_declaration( ctx )) return FALSE; } - else if (str_match_no_case( &ctx->cur, "IMM" )) { + else if (str_match_nocase_whole( &ctx->cur, "IMM" )) { if (!parse_immediate( ctx )) return FALSE; } - else if (str_match_no_case( &ctx->cur, "PROPERTY" )) { + else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) { if (!parse_property( ctx )) return FALSE; } @@ -1335,7 +1896,7 @@ tgsi_text_translate( struct tgsi_token *tokens, uint num_tokens ) { - struct translate_ctx ctx; + struct translate_ctx ctx = {0}; ctx.text = text; ctx.cur = text;