Home | History | Annotate | Download | only in tgsi
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 #include "util/u_debug.h"
     29 #include "util/u_memory.h"
     30 #include "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"
     41 
     42 static boolean is_alpha_underscore( const char *cur )
     43 {
     44    return
     45       (*cur >= 'a' && *cur <= 'z') ||
     46       (*cur >= 'A' && *cur <= 'Z') ||
     47       *cur == '_';
     48 }
     49 
     50 static boolean is_digit( const char *cur )
     51 {
     52    return *cur >= '0' && *cur <= '9';
     53 }
     54 
     55 static boolean is_digit_alpha_underscore( const char *cur )
     56 {
     57    return is_digit( cur ) || is_alpha_underscore( cur );
     58 }
     59 
     60 static char uprcase( char c )
     61 {
     62    if (c >= 'a' && c <= 'z')
     63       return c + 'A' - 'a';
     64    return c;
     65 }
     66 
     67 /*
     68  * Ignore case of str1 and assume str1 is already uppercase.
     69  * Return TRUE iff str1 and str2 are equal.
     70  */
     71 static int
     72 streq_nocase_uprcase(const char *str1,
     73                      const char *str2)
     74 {
     75    while (*str1 && *str2) {
     76       if (*str1 != uprcase(*str2))
     77          return FALSE;
     78       str1++;
     79       str2++;
     80    }
     81    return *str1 == 0 && *str2 == 0;
     82 }
     83 
     84 /* Return TRUE if both strings match.
     85  * The second string is terminated by zero.
     86  * The pointer to the first string is moved at end of the read word
     87  * on success.
     88  */
     89 static boolean str_match_no_case( const char **pcur, const char *str )
     90 {
     91    const char *cur = *pcur;
     92 
     93    while (*str != '\0' && *str == uprcase( *cur )) {
     94       str++;
     95       cur++;
     96    }
     97    if (*str == '\0') {
     98       *pcur = cur;
     99       return TRUE;
    100    }
    101    return FALSE;
    102 }
    103 
    104 /* Return TRUE if both strings match.
    105  * The first string is be terminated by a non-digit non-letter non-underscore
    106  * character, the second string is terminated by zero.
    107  * The pointer to the first string is moved at end of the read word
    108  * on success.
    109  */
    110 static boolean str_match_nocase_whole( const char **pcur, const char *str )
    111 {
    112    const char *cur = *pcur;
    113 
    114    if (str_match_no_case(&cur, str) &&
    115        !is_digit_alpha_underscore(cur)) {
    116       *pcur = cur;
    117       return TRUE;
    118    }
    119    return FALSE;
    120 }
    121 
    122 /* Return the array index that matches starting at *pcur, where the string at
    123  * *pcur is terminated by a non-digit non-letter non-underscore.
    124  * Returns -1 if no match is found.
    125  *
    126  * On success, the pointer to the first string is moved to the end of the read
    127  * word.
    128  */
    129 static int str_match_name_from_array(const char **pcur,
    130                                      const char * const *array,
    131                                      unsigned array_size)
    132 {
    133    for (unsigned j = 0; j < array_size; ++j) {
    134       if (str_match_nocase_whole(pcur, array[j]))
    135          return j;
    136    }
    137    return -1;
    138 }
    139 
    140 /* Return the format corresponding to the name at *pcur.
    141  * Returns -1 if there is no format name.
    142  *
    143  * On success, the pointer to the string is moved to the end of the read format
    144  * name.
    145  */
    146 static int str_match_format(const char **pcur)
    147 {
    148    for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {
    149       const struct util_format_description *desc =
    150          util_format_description(i);
    151       if (desc && str_match_nocase_whole(pcur, desc->name)) {
    152          return i;
    153       }
    154    }
    155    return -1;
    156 }
    157 
    158 /* Eat zero or more whitespaces.
    159  */
    160 static void eat_opt_white( const char **pcur )
    161 {
    162    while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
    163       (*pcur)++;
    164 }
    165 
    166 /* Eat one or more whitespaces.
    167  * Return TRUE if at least one whitespace eaten.
    168  */
    169 static boolean eat_white( const char **pcur )
    170 {
    171    const char *cur = *pcur;
    172 
    173    eat_opt_white( pcur );
    174    return *pcur > cur;
    175 }
    176 
    177 /* Parse unsigned integer.
    178  * No checks for overflow.
    179  */
    180 static boolean parse_uint( const char **pcur, uint *val )
    181 {
    182    const char *cur = *pcur;
    183 
    184    if (is_digit( cur )) {
    185       *val = *cur++ - '0';
    186       while (is_digit( cur ))
    187          *val = *val * 10 + *cur++ - '0';
    188       *pcur = cur;
    189       return TRUE;
    190    }
    191    return FALSE;
    192 }
    193 
    194 static boolean parse_int( const char **pcur, int *val )
    195 {
    196    const char *cur = *pcur;
    197    int sign = (*cur == '-' ? -1 : 1);
    198 
    199    if (*cur == '+' || *cur == '-')
    200       cur++;
    201 
    202    if (parse_uint(&cur, (uint *)val)) {
    203       *val *= sign;
    204       *pcur = cur;
    205       return TRUE;
    206    }
    207 
    208    return FALSE;
    209 }
    210 
    211 static boolean parse_identifier( const char **pcur, char *ret, size_t len )
    212 {
    213    const char *cur = *pcur;
    214    int i = 0;
    215    if (is_alpha_underscore( cur )) {
    216       ret[i++] = *cur++;
    217       while (is_alpha_underscore( cur ) || is_digit( cur )) {
    218          if (i == len - 1)
    219             return FALSE;
    220          ret[i++] = *cur++;
    221       }
    222       ret[i++] = '\0';
    223       *pcur = cur;
    224       return TRUE;
    225    }
    226    return FALSE;
    227 }
    228 
    229 /* Parse floating point.
    230  */
    231 static boolean parse_float( const char **pcur, float *val )
    232 {
    233    const char *cur = *pcur;
    234    boolean integral_part = FALSE;
    235    boolean fractional_part = FALSE;
    236 
    237    if (*cur == '0' && *(cur + 1) == 'x') {
    238       union fi fi;
    239       fi.ui = strtoul(cur, NULL, 16);
    240       *val = fi.f;
    241       cur += 10;
    242       goto out;
    243    }
    244 
    245    *val = (float) atof( cur );
    246    if (*cur == '-' || *cur == '+')
    247       cur++;
    248    if (is_digit( cur )) {
    249       cur++;
    250       integral_part = TRUE;
    251       while (is_digit( cur ))
    252          cur++;
    253    }
    254    if (*cur == '.') {
    255       cur++;
    256       if (is_digit( cur )) {
    257          cur++;
    258          fractional_part = TRUE;
    259          while (is_digit( cur ))
    260             cur++;
    261       }
    262    }
    263    if (!integral_part && !fractional_part)
    264       return FALSE;
    265    if (uprcase( *cur ) == 'E') {
    266       cur++;
    267       if (*cur == '-' || *cur == '+')
    268          cur++;
    269       if (is_digit( cur )) {
    270          cur++;
    271          while (is_digit( cur ))
    272             cur++;
    273       }
    274       else
    275          return FALSE;
    276    }
    277 
    278 out:
    279    *pcur = cur;
    280    return TRUE;
    281 }
    282 
    283 static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
    284 {
    285    const char *cur = *pcur;
    286    union {
    287       double dval;
    288       uint32_t uval[2];
    289    } v;
    290 
    291    v.dval = strtod(cur, (char**)pcur);
    292    if (*pcur == cur)
    293       return FALSE;
    294 
    295    *val0 = v.uval[0];
    296    *val1 = v.uval[1];
    297 
    298    return TRUE;
    299 }
    300 
    301 static boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1)
    302 {
    303    const char *cur = *pcur;
    304    union {
    305       int64_t i64val;
    306       uint32_t uval[2];
    307    } v;
    308 
    309    v.i64val = strtoll(cur, (char**)pcur, 0);
    310    if (*pcur == cur)
    311       return FALSE;
    312 
    313    *val0 = v.uval[0];
    314    *val1 = v.uval[1];
    315 
    316    return TRUE;
    317 }
    318 
    319 static boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1)
    320 {
    321    const char *cur = *pcur;
    322    union {
    323       uint64_t u64val;
    324       uint32_t uval[2];
    325    } v;
    326 
    327    v.u64val = strtoull(cur, (char**)pcur, 0);
    328    if (*pcur == cur)
    329       return FALSE;
    330 
    331    *val0 = v.uval[0];
    332    *val1 = v.uval[1];
    333 
    334    return TRUE;
    335 }
    336 
    337 struct translate_ctx
    338 {
    339    const char *text;
    340    const char *cur;
    341    struct tgsi_token *tokens;
    342    struct tgsi_token *tokens_cur;
    343    struct tgsi_token *tokens_end;
    344    struct tgsi_header *header;
    345    unsigned processor : 4;
    346    unsigned implied_array_size : 6;
    347    unsigned num_immediates;
    348 };
    349 
    350 static void report_error( struct translate_ctx *ctx, const char *msg )
    351 {
    352    int line = 1;
    353    int column = 1;
    354    const char *itr = ctx->text;
    355 
    356    while (itr != ctx->cur) {
    357       if (*itr == '\n') {
    358          column = 1;
    359          ++line;
    360       }
    361       ++column;
    362       ++itr;
    363    }
    364 
    365    debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
    366 }
    367 
    368 /* Parse shader header.
    369  * Return TRUE for one of the following headers.
    370  *    FRAG
    371  *    GEOM
    372  *    VERT
    373  */
    374 static boolean parse_header( struct translate_ctx *ctx )
    375 {
    376    uint processor;
    377 
    378    if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
    379       processor = PIPE_SHADER_FRAGMENT;
    380    else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
    381       processor = PIPE_SHADER_VERTEX;
    382    else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
    383       processor = PIPE_SHADER_GEOMETRY;
    384    else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" ))
    385       processor = PIPE_SHADER_TESS_CTRL;
    386    else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" ))
    387       processor = PIPE_SHADER_TESS_EVAL;
    388    else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
    389       processor = PIPE_SHADER_COMPUTE;
    390    else {
    391       report_error( ctx, "Unknown header" );
    392       return FALSE;
    393    }
    394 
    395    if (ctx->tokens_cur >= ctx->tokens_end)
    396       return FALSE;
    397    ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
    398    *ctx->header = tgsi_build_header();
    399 
    400    if (ctx->tokens_cur >= ctx->tokens_end)
    401       return FALSE;
    402    *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
    403    ctx->processor = processor;
    404 
    405    return TRUE;
    406 }
    407 
    408 static boolean parse_label( struct translate_ctx *ctx, uint *val )
    409 {
    410    const char *cur = ctx->cur;
    411 
    412    if (parse_uint( &cur, val )) {
    413       eat_opt_white( &cur );
    414       if (*cur == ':') {
    415          cur++;
    416          ctx->cur = cur;
    417          return TRUE;
    418       }
    419    }
    420    return FALSE;
    421 }
    422 
    423 static boolean
    424 parse_file( const char **pcur, uint *file )
    425 {
    426    uint i;
    427 
    428    for (i = 0; i < TGSI_FILE_COUNT; i++) {
    429       const char *cur = *pcur;
    430 
    431       if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
    432          *pcur = cur;
    433          *file = i;
    434          return TRUE;
    435       }
    436    }
    437    return FALSE;
    438 }
    439 
    440 static boolean
    441 parse_opt_writemask(
    442    struct translate_ctx *ctx,
    443    uint *writemask )
    444 {
    445    const char *cur;
    446 
    447    cur = ctx->cur;
    448    eat_opt_white( &cur );
    449    if (*cur == '.') {
    450       cur++;
    451       *writemask = TGSI_WRITEMASK_NONE;
    452       eat_opt_white( &cur );
    453       if (uprcase( *cur ) == 'X') {
    454          cur++;
    455          *writemask |= TGSI_WRITEMASK_X;
    456       }
    457       if (uprcase( *cur ) == 'Y') {
    458          cur++;
    459          *writemask |= TGSI_WRITEMASK_Y;
    460       }
    461       if (uprcase( *cur ) == 'Z') {
    462          cur++;
    463          *writemask |= TGSI_WRITEMASK_Z;
    464       }
    465       if (uprcase( *cur ) == 'W') {
    466          cur++;
    467          *writemask |= TGSI_WRITEMASK_W;
    468       }
    469 
    470       if (*writemask == TGSI_WRITEMASK_NONE) {
    471          report_error( ctx, "Writemask expected" );
    472          return FALSE;
    473       }
    474 
    475       ctx->cur = cur;
    476    }
    477    else {
    478       *writemask = TGSI_WRITEMASK_XYZW;
    479    }
    480    return TRUE;
    481 }
    482 
    483 
    484 /* <register_file_bracket> ::= <file> `['
    485  */
    486 static boolean
    487 parse_register_file_bracket(
    488    struct translate_ctx *ctx,
    489    uint *file )
    490 {
    491    if (!parse_file( &ctx->cur, file )) {
    492       report_error( ctx, "Unknown register file" );
    493       return FALSE;
    494    }
    495    eat_opt_white( &ctx->cur );
    496    if (*ctx->cur != '[') {
    497       report_error( ctx, "Expected `['" );
    498       return FALSE;
    499    }
    500    ctx->cur++;
    501    return TRUE;
    502 }
    503 
    504 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
    505  */
    506 static boolean
    507 parse_register_file_bracket_index(
    508    struct translate_ctx *ctx,
    509    uint *file,
    510    int *index )
    511 {
    512    uint uindex;
    513 
    514    if (!parse_register_file_bracket( ctx, file ))
    515       return FALSE;
    516    eat_opt_white( &ctx->cur );
    517    if (!parse_uint( &ctx->cur, &uindex )) {
    518       report_error( ctx, "Expected literal unsigned integer" );
    519       return FALSE;
    520    }
    521    *index = (int) uindex;
    522    return TRUE;
    523 }
    524 
    525 /* Parse simple 1d register operand.
    526  *    <register_dst> ::= <register_file_bracket_index> `]'
    527  */
    528 static boolean
    529 parse_register_1d(struct translate_ctx *ctx,
    530                   uint *file,
    531                   int *index )
    532 {
    533    if (!parse_register_file_bracket_index( ctx, file, index ))
    534       return FALSE;
    535    eat_opt_white( &ctx->cur );
    536    if (*ctx->cur != ']') {
    537       report_error( ctx, "Expected `]'" );
    538       return FALSE;
    539    }
    540    ctx->cur++;
    541    return TRUE;
    542 }
    543 
    544 struct parsed_bracket {
    545    int index;
    546 
    547    uint ind_file;
    548    int ind_index;
    549    uint ind_comp;
    550    uint ind_array;
    551 };
    552 
    553 
    554 static boolean
    555 parse_register_bracket(
    556    struct translate_ctx *ctx,
    557    struct parsed_bracket *brackets)
    558 {
    559    const char *cur;
    560    uint uindex;
    561 
    562    memset(brackets, 0, sizeof(struct parsed_bracket));
    563 
    564    eat_opt_white( &ctx->cur );
    565 
    566    cur = ctx->cur;
    567    if (parse_file( &cur, &brackets->ind_file )) {
    568       if (!parse_register_1d( ctx, &brackets->ind_file,
    569                               &brackets->ind_index ))
    570          return FALSE;
    571       eat_opt_white( &ctx->cur );
    572 
    573       if (*ctx->cur == '.') {
    574          ctx->cur++;
    575          eat_opt_white(&ctx->cur);
    576 
    577          switch (uprcase(*ctx->cur)) {
    578          case 'X':
    579             brackets->ind_comp = TGSI_SWIZZLE_X;
    580             break;
    581          case 'Y':
    582             brackets->ind_comp = TGSI_SWIZZLE_Y;
    583             break;
    584          case 'Z':
    585             brackets->ind_comp = TGSI_SWIZZLE_Z;
    586             break;
    587          case 'W':
    588             brackets->ind_comp = TGSI_SWIZZLE_W;
    589             break;
    590          default:
    591             report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
    592             return FALSE;
    593          }
    594          ctx->cur++;
    595          eat_opt_white(&ctx->cur);
    596       }
    597 
    598       if (*ctx->cur == '+' || *ctx->cur == '-')
    599          parse_int( &ctx->cur, &brackets->index );
    600       else
    601          brackets->index = 0;
    602    }
    603    else {
    604       if (!parse_uint( &ctx->cur, &uindex )) {
    605          report_error( ctx, "Expected literal unsigned integer" );
    606          return FALSE;
    607       }
    608       brackets->index = (int) uindex;
    609       brackets->ind_file = TGSI_FILE_NULL;
    610       brackets->ind_index = 0;
    611    }
    612    eat_opt_white( &ctx->cur );
    613    if (*ctx->cur != ']') {
    614       report_error( ctx, "Expected `]'" );
    615       return FALSE;
    616    }
    617    ctx->cur++;
    618    if (*ctx->cur == '(') {
    619       ctx->cur++;
    620       eat_opt_white( &ctx->cur );
    621       if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
    622          report_error( ctx, "Expected literal unsigned integer" );
    623          return FALSE;
    624       }
    625       eat_opt_white( &ctx->cur );
    626       if (*ctx->cur != ')') {
    627          report_error( ctx, "Expected `)'" );
    628          return FALSE;
    629       }
    630       ctx->cur++;
    631    }
    632    return TRUE;
    633 }
    634 
    635 static boolean
    636 parse_opt_register_src_bracket(
    637    struct translate_ctx *ctx,
    638    struct parsed_bracket *brackets,
    639    int *parsed_brackets)
    640 {
    641    const char *cur = ctx->cur;
    642 
    643    *parsed_brackets = 0;
    644 
    645    eat_opt_white( &cur );
    646    if (cur[0] == '[') {
    647       ++cur;
    648       ctx->cur = cur;
    649 
    650       if (!parse_register_bracket(ctx, brackets))
    651          return FALSE;
    652 
    653       *parsed_brackets = 1;
    654    }
    655 
    656    return TRUE;
    657 }
    658 
    659 
    660 /* Parse source register operand.
    661  *    <register_src> ::= <register_file_bracket_index> `]' |
    662  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
    663  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
    664  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
    665  */
    666 static boolean
    667 parse_register_src(
    668    struct translate_ctx *ctx,
    669    uint *file,
    670    struct parsed_bracket *brackets)
    671 {
    672    brackets->ind_comp = TGSI_SWIZZLE_X;
    673    if (!parse_register_file_bracket( ctx, file ))
    674       return FALSE;
    675    if (!parse_register_bracket( ctx, brackets ))
    676        return FALSE;
    677 
    678    return TRUE;
    679 }
    680 
    681 struct parsed_dcl_bracket {
    682    uint first;
    683    uint last;
    684 };
    685 
    686 static boolean
    687 parse_register_dcl_bracket(
    688    struct translate_ctx *ctx,
    689    struct parsed_dcl_bracket *bracket)
    690 {
    691    uint uindex;
    692    memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
    693 
    694    eat_opt_white( &ctx->cur );
    695 
    696    if (!parse_uint( &ctx->cur, &uindex )) {
    697       /* it can be an empty bracket [] which means its range
    698        * is from 0 to some implied size */
    699       if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
    700          bracket->first = 0;
    701          bracket->last = ctx->implied_array_size - 1;
    702          goto cleanup;
    703       }
    704       report_error( ctx, "Expected literal unsigned integer" );
    705       return FALSE;
    706    }
    707    bracket->first = uindex;
    708 
    709    eat_opt_white( &ctx->cur );
    710 
    711    if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
    712       uint uindex;
    713 
    714       ctx->cur += 2;
    715       eat_opt_white( &ctx->cur );
    716       if (!parse_uint( &ctx->cur, &uindex )) {
    717          report_error( ctx, "Expected literal integer" );
    718          return FALSE;
    719       }
    720       bracket->last = (int) uindex;
    721       eat_opt_white( &ctx->cur );
    722    }
    723    else {
    724       bracket->last = bracket->first;
    725    }
    726 
    727 cleanup:
    728    if (*ctx->cur != ']') {
    729       report_error( ctx, "Expected `]' or `..'" );
    730       return FALSE;
    731    }
    732    ctx->cur++;
    733    return TRUE;
    734 }
    735 
    736 /* Parse register declaration.
    737  *    <register_dcl> ::= <register_file_bracket_index> `]' |
    738  *                       <register_file_bracket_index> `..' <index> `]'
    739  */
    740 static boolean
    741 parse_register_dcl(
    742    struct translate_ctx *ctx,
    743    uint *file,
    744    struct parsed_dcl_bracket *brackets,
    745    int *num_brackets)
    746 {
    747    const char *cur;
    748 
    749    *num_brackets = 0;
    750 
    751    if (!parse_register_file_bracket( ctx, file ))
    752       return FALSE;
    753    if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
    754       return FALSE;
    755 
    756    *num_brackets = 1;
    757 
    758    cur = ctx->cur;
    759    eat_opt_white( &cur );
    760 
    761    if (cur[0] == '[') {
    762       bool is_in = *file == TGSI_FILE_INPUT;
    763       bool is_out = *file == TGSI_FILE_OUTPUT;
    764 
    765       ++cur;
    766       ctx->cur = cur;
    767       if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
    768          return FALSE;
    769       /* for geometry shader we don't really care about
    770        * the first brackets it's always the size of the
    771        * input primitive. so we want to declare just
    772        * the index relevant to the semantics which is in
    773        * the second bracket */
    774 
    775       /* tessellation has similar constraints to geometry shader */
    776       if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) ||
    777           (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) ||
    778           (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) {
    779          brackets[0] = brackets[1];
    780          *num_brackets = 1;
    781       } else {
    782          *num_brackets = 2;
    783       }
    784    }
    785 
    786    return TRUE;
    787 }
    788 
    789 
    790 /* Parse destination register operand.*/
    791 static boolean
    792 parse_register_dst(
    793    struct translate_ctx *ctx,
    794    uint *file,
    795    struct parsed_bracket *brackets)
    796 {
    797    brackets->ind_comp = TGSI_SWIZZLE_X;
    798    if (!parse_register_file_bracket( ctx, file ))
    799       return FALSE;
    800    if (!parse_register_bracket( ctx, brackets ))
    801        return FALSE;
    802 
    803    return TRUE;
    804 }
    805 
    806 static boolean
    807 parse_dst_operand(
    808    struct translate_ctx *ctx,
    809    struct tgsi_full_dst_register *dst )
    810 {
    811    uint file;
    812    uint writemask;
    813    const char *cur;
    814    struct parsed_bracket bracket[2];
    815    int parsed_opt_brackets;
    816 
    817    if (!parse_register_dst( ctx, &file, &bracket[0] ))
    818       return FALSE;
    819    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
    820       return FALSE;
    821 
    822    cur = ctx->cur;
    823    eat_opt_white( &cur );
    824 
    825    if (!parse_opt_writemask( ctx, &writemask ))
    826       return FALSE;
    827 
    828    dst->Register.File = file;
    829    if (parsed_opt_brackets) {
    830       dst->Register.Dimension = 1;
    831       dst->Dimension.Indirect = 0;
    832       dst->Dimension.Dimension = 0;
    833       dst->Dimension.Index = bracket[0].index;
    834 
    835       if (bracket[0].ind_file != TGSI_FILE_NULL) {
    836          dst->Dimension.Indirect = 1;
    837          dst->DimIndirect.File = bracket[0].ind_file;
    838          dst->DimIndirect.Index = bracket[0].ind_index;
    839          dst->DimIndirect.Swizzle = bracket[0].ind_comp;
    840          dst->DimIndirect.ArrayID = bracket[0].ind_array;
    841       }
    842       bracket[0] = bracket[1];
    843    }
    844    dst->Register.Index = bracket[0].index;
    845    dst->Register.WriteMask = writemask;
    846    if (bracket[0].ind_file != TGSI_FILE_NULL) {
    847       dst->Register.Indirect = 1;
    848       dst->Indirect.File = bracket[0].ind_file;
    849       dst->Indirect.Index = bracket[0].ind_index;
    850       dst->Indirect.Swizzle = bracket[0].ind_comp;
    851       dst->Indirect.ArrayID = bracket[0].ind_array;
    852    }
    853    return TRUE;
    854 }
    855 
    856 static boolean
    857 parse_optional_swizzle(
    858    struct translate_ctx *ctx,
    859    uint *swizzle,
    860    boolean *parsed_swizzle,
    861    int components)
    862 {
    863    const char *cur = ctx->cur;
    864 
    865    *parsed_swizzle = FALSE;
    866 
    867    eat_opt_white( &cur );
    868    if (*cur == '.') {
    869       uint i;
    870 
    871       cur++;
    872       eat_opt_white( &cur );
    873       for (i = 0; i < components; i++) {
    874          if (uprcase( *cur ) == 'X')
    875             swizzle[i] = TGSI_SWIZZLE_X;
    876          else if (uprcase( *cur ) == 'Y')
    877             swizzle[i] = TGSI_SWIZZLE_Y;
    878          else if (uprcase( *cur ) == 'Z')
    879             swizzle[i] = TGSI_SWIZZLE_Z;
    880          else if (uprcase( *cur ) == 'W')
    881             swizzle[i] = TGSI_SWIZZLE_W;
    882          else {
    883 	    report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
    884 	    return FALSE;
    885          }
    886          cur++;
    887       }
    888       *parsed_swizzle = TRUE;
    889       ctx->cur = cur;
    890    }
    891    return TRUE;
    892 }
    893 
    894 static boolean
    895 parse_src_operand(
    896    struct translate_ctx *ctx,
    897    struct tgsi_full_src_register *src )
    898 {
    899    uint file;
    900    uint swizzle[4];
    901    boolean parsed_swizzle;
    902    struct parsed_bracket bracket[2];
    903    int parsed_opt_brackets;
    904 
    905    if (*ctx->cur == '-') {
    906       ctx->cur++;
    907       eat_opt_white( &ctx->cur );
    908       src->Register.Negate = 1;
    909    }
    910 
    911    if (*ctx->cur == '|') {
    912       ctx->cur++;
    913       eat_opt_white( &ctx->cur );
    914       src->Register.Absolute = 1;
    915    }
    916 
    917    if (!parse_register_src(ctx, &file, &bracket[0]))
    918       return FALSE;
    919    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
    920       return FALSE;
    921 
    922    src->Register.File = file;
    923    if (parsed_opt_brackets) {
    924       src->Register.Dimension = 1;
    925       src->Dimension.Indirect = 0;
    926       src->Dimension.Dimension = 0;
    927       src->Dimension.Index = bracket[0].index;
    928       if (bracket[0].ind_file != TGSI_FILE_NULL) {
    929          src->Dimension.Indirect = 1;
    930          src->DimIndirect.File = bracket[0].ind_file;
    931          src->DimIndirect.Index = bracket[0].ind_index;
    932          src->DimIndirect.Swizzle = bracket[0].ind_comp;
    933          src->DimIndirect.ArrayID = bracket[0].ind_array;
    934       }
    935       bracket[0] = bracket[1];
    936    }
    937    src->Register.Index = bracket[0].index;
    938    if (bracket[0].ind_file != TGSI_FILE_NULL) {
    939       src->Register.Indirect = 1;
    940       src->Indirect.File = bracket[0].ind_file;
    941       src->Indirect.Index = bracket[0].ind_index;
    942       src->Indirect.Swizzle = bracket[0].ind_comp;
    943       src->Indirect.ArrayID = bracket[0].ind_array;
    944    }
    945 
    946    /* Parse optional swizzle.
    947     */
    948    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
    949       if (parsed_swizzle) {
    950          src->Register.SwizzleX = swizzle[0];
    951          src->Register.SwizzleY = swizzle[1];
    952          src->Register.SwizzleZ = swizzle[2];
    953          src->Register.SwizzleW = swizzle[3];
    954       }
    955    }
    956 
    957    if (src->Register.Absolute) {
    958       eat_opt_white( &ctx->cur );
    959       if (*ctx->cur != '|') {
    960          report_error( ctx, "Expected `|'" );
    961          return FALSE;
    962       }
    963       ctx->cur++;
    964    }
    965 
    966 
    967    return TRUE;
    968 }
    969 
    970 static boolean
    971 parse_texoffset_operand(
    972    struct translate_ctx *ctx,
    973    struct tgsi_texture_offset *src )
    974 {
    975    uint file;
    976    uint swizzle[3];
    977    boolean parsed_swizzle;
    978    struct parsed_bracket bracket;
    979 
    980    if (!parse_register_src(ctx, &file, &bracket))
    981       return FALSE;
    982 
    983    src->File = file;
    984    src->Index = bracket.index;
    985 
    986    /* Parse optional swizzle.
    987     */
    988    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {
    989       if (parsed_swizzle) {
    990          src->SwizzleX = swizzle[0];
    991          src->SwizzleY = swizzle[1];
    992          src->SwizzleZ = swizzle[2];
    993       }
    994    }
    995 
    996    return TRUE;
    997 }
    998 
    999 static boolean
   1000 match_inst(const char **pcur,
   1001            unsigned *saturate,
   1002            const struct tgsi_opcode_info *info)
   1003 {
   1004    const char *cur = *pcur;
   1005 
   1006    /* simple case: the whole string matches the instruction name */
   1007    if (str_match_nocase_whole(&cur, info->mnemonic)) {
   1008       *pcur = cur;
   1009       *saturate = 0;
   1010       return TRUE;
   1011    }
   1012 
   1013    if (str_match_no_case(&cur, info->mnemonic)) {
   1014       /* the instruction has a suffix, figure it out */
   1015       if (str_match_nocase_whole(&cur, "_SAT")) {
   1016          *pcur = cur;
   1017          *saturate = 1;
   1018          return TRUE;
   1019       }
   1020    }
   1021 
   1022    return FALSE;
   1023 }
   1024 
   1025 static boolean
   1026 parse_instruction(
   1027    struct translate_ctx *ctx,
   1028    boolean has_label )
   1029 {
   1030    uint i;
   1031    uint saturate = 0;
   1032    const struct tgsi_opcode_info *info;
   1033    struct tgsi_full_instruction inst;
   1034    const char *cur;
   1035    uint advance;
   1036 
   1037    inst = tgsi_default_full_instruction();
   1038 
   1039    /* Parse predicate.
   1040     */
   1041    eat_opt_white( &ctx->cur );
   1042    if (*ctx->cur == '(') {
   1043       uint file;
   1044       int index;
   1045       uint swizzle[4];
   1046       boolean parsed_swizzle;
   1047 
   1048       inst.Instruction.Predicate = 1;
   1049 
   1050       ctx->cur++;
   1051       if (*ctx->cur == '!') {
   1052          ctx->cur++;
   1053          inst.Predicate.Negate = 1;
   1054       }
   1055 
   1056       if (!parse_register_1d( ctx, &file, &index ))
   1057          return FALSE;
   1058 
   1059       if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
   1060          if (parsed_swizzle) {
   1061             inst.Predicate.SwizzleX = swizzle[0];
   1062             inst.Predicate.SwizzleY = swizzle[1];
   1063             inst.Predicate.SwizzleZ = swizzle[2];
   1064             inst.Predicate.SwizzleW = swizzle[3];
   1065          }
   1066       }
   1067 
   1068       if (*ctx->cur != ')') {
   1069          report_error( ctx, "Expected `)'" );
   1070          return FALSE;
   1071       }
   1072 
   1073       ctx->cur++;
   1074    }
   1075 
   1076    /* Parse instruction name.
   1077     */
   1078    eat_opt_white( &ctx->cur );
   1079    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
   1080       cur = ctx->cur;
   1081 
   1082       info = tgsi_get_opcode_info( i );
   1083       if (match_inst(&cur, &saturate, info)) {
   1084          if (info->num_dst + info->num_src + info->is_tex == 0) {
   1085             ctx->cur = cur;
   1086             break;
   1087          }
   1088          else if (*cur == '\0' || eat_white( &cur )) {
   1089             ctx->cur = cur;
   1090             break;
   1091          }
   1092       }
   1093    }
   1094    if (i == TGSI_OPCODE_LAST) {
   1095       if (has_label)
   1096          report_error( ctx, "Unknown opcode" );
   1097       else
   1098          report_error( ctx, "Expected `DCL', `IMM' or a label" );
   1099       return FALSE;
   1100    }
   1101 
   1102    inst.Instruction.Opcode = i;
   1103    inst.Instruction.Saturate = saturate;
   1104    inst.Instruction.NumDstRegs = info->num_dst;
   1105    inst.Instruction.NumSrcRegs = info->num_src;
   1106 
   1107    if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
   1108       /*
   1109        * These are not considered tex opcodes here (no additional
   1110        * target argument) however we're required to set the Texture
   1111        * bit so we can set the number of tex offsets.
   1112        */
   1113       inst.Instruction.Texture = 1;
   1114       inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
   1115    }
   1116 
   1117    if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
   1118        i == TGSI_OPCODE_RESQ) {
   1119       inst.Instruction.Memory = 1;
   1120       inst.Memory.Qualifier = 0;
   1121    }
   1122 
   1123    assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS);
   1124    assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS);
   1125 
   1126    /* Parse instruction operands.
   1127     */
   1128    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
   1129       if (i > 0) {
   1130          eat_opt_white( &ctx->cur );
   1131          if (*ctx->cur != ',') {
   1132             report_error( ctx, "Expected `,'" );
   1133             return FALSE;
   1134          }
   1135          ctx->cur++;
   1136          eat_opt_white( &ctx->cur );
   1137       }
   1138 
   1139       if (i < info->num_dst) {
   1140          if (!parse_dst_operand( ctx, &inst.Dst[i] ))
   1141             return FALSE;
   1142       }
   1143       else if (i < info->num_dst + info->num_src) {
   1144          if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
   1145             return FALSE;
   1146       }
   1147       else {
   1148          uint j;
   1149 
   1150          for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
   1151             if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
   1152                inst.Instruction.Texture = 1;
   1153                inst.Texture.Texture = j;
   1154                break;
   1155             }
   1156          }
   1157          if (j == TGSI_TEXTURE_COUNT) {
   1158             report_error( ctx, "Expected texture target" );
   1159             return FALSE;
   1160          }
   1161       }
   1162    }
   1163 
   1164    cur = ctx->cur;
   1165    eat_opt_white( &cur );
   1166    for (i = 0; inst.Instruction.Texture && *cur == ','; i++) {
   1167          cur++;
   1168          eat_opt_white( &cur );
   1169          ctx->cur = cur;
   1170          if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
   1171             return FALSE;
   1172          cur = ctx->cur;
   1173          eat_opt_white( &cur );
   1174    }
   1175    inst.Texture.NumOffsets = i;
   1176 
   1177    cur = ctx->cur;
   1178    eat_opt_white(&cur);
   1179 
   1180    for (; inst.Instruction.Memory && *cur == ',';
   1181         ctx->cur = cur, eat_opt_white(&cur)) {
   1182       int j;
   1183 
   1184       cur++;
   1185       eat_opt_white(&cur);
   1186 
   1187       j = str_match_name_from_array(&cur, tgsi_memory_names,
   1188                                     ARRAY_SIZE(tgsi_memory_names));
   1189       if (j >= 0) {
   1190          inst.Memory.Qualifier |= 1U << j;
   1191          continue;
   1192       }
   1193 
   1194       j = str_match_name_from_array(&cur, tgsi_texture_names,
   1195                                     ARRAY_SIZE(tgsi_texture_names));
   1196       if (j >= 0) {
   1197          inst.Memory.Texture = j;
   1198          continue;
   1199       }
   1200 
   1201       j = str_match_format(&cur);
   1202       if (j >= 0) {
   1203          inst.Memory.Format = j;
   1204          continue;
   1205       }
   1206 
   1207       ctx->cur = cur;
   1208       report_error(ctx, "Expected memory qualifier, texture target, or format\n");
   1209       return FALSE;
   1210    }
   1211 
   1212    cur = ctx->cur;
   1213    eat_opt_white( &cur );
   1214    if (info->is_branch && *cur == ':') {
   1215       uint target;
   1216 
   1217       cur++;
   1218       eat_opt_white( &cur );
   1219       if (!parse_uint( &cur, &target )) {
   1220          report_error( ctx, "Expected a label" );
   1221          return FALSE;
   1222       }
   1223       inst.Instruction.Label = 1;
   1224       inst.Label.Label = target;
   1225       ctx->cur = cur;
   1226    }
   1227 
   1228    advance = tgsi_build_full_instruction(
   1229       &inst,
   1230       ctx->tokens_cur,
   1231       ctx->header,
   1232       (uint) (ctx->tokens_end - ctx->tokens_cur) );
   1233    if (advance == 0)
   1234       return FALSE;
   1235    ctx->tokens_cur += advance;
   1236 
   1237    return TRUE;
   1238 }
   1239 
   1240 /* parses a 4-touple of the form {x, y, z, w}
   1241  * where x, y, z, w are numbers */
   1242 static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
   1243                                     union tgsi_immediate_data *values)
   1244 {
   1245    unsigned i;
   1246    int ret;
   1247 
   1248    eat_opt_white( &ctx->cur );
   1249    if (*ctx->cur != '{') {
   1250       report_error( ctx, "Expected `{'" );
   1251       return FALSE;
   1252    }
   1253    ctx->cur++;
   1254    for (i = 0; i < 4; i++) {
   1255       eat_opt_white( &ctx->cur );
   1256       if (i > 0) {
   1257          if (*ctx->cur != ',') {
   1258             report_error( ctx, "Expected `,'" );
   1259             return FALSE;
   1260          }
   1261          ctx->cur++;
   1262          eat_opt_white( &ctx->cur );
   1263       }
   1264 
   1265       switch (type) {
   1266       case TGSI_IMM_FLOAT64:
   1267          ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
   1268          i++;
   1269          break;
   1270       case TGSI_IMM_INT64:
   1271          ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
   1272          i++;
   1273          break;
   1274       case TGSI_IMM_UINT64:
   1275          ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
   1276          i++;
   1277          break;
   1278       case TGSI_IMM_FLOAT32:
   1279          ret = parse_float(&ctx->cur, &values[i].Float);
   1280          break;
   1281       case TGSI_IMM_UINT32:
   1282          ret = parse_uint(&ctx->cur, &values[i].Uint);
   1283          break;
   1284       case TGSI_IMM_INT32:
   1285          ret = parse_int(&ctx->cur, &values[i].Int);
   1286          break;
   1287       default:
   1288          assert(0);
   1289          ret = FALSE;
   1290          break;
   1291       }
   1292 
   1293       if (!ret) {
   1294          report_error( ctx, "Expected immediate constant" );
   1295          return FALSE;
   1296       }
   1297    }
   1298    eat_opt_white( &ctx->cur );
   1299    if (*ctx->cur != '}') {
   1300       report_error( ctx, "Expected `}'" );
   1301       return FALSE;
   1302    }
   1303    ctx->cur++;
   1304 
   1305    return TRUE;
   1306 }
   1307 
   1308 static boolean parse_declaration( struct translate_ctx *ctx )
   1309 {
   1310    struct tgsi_full_declaration decl;
   1311    uint file;
   1312    struct parsed_dcl_bracket brackets[2];
   1313    int num_brackets;
   1314    uint writemask;
   1315    const char *cur, *cur2;
   1316    uint advance;
   1317    boolean is_vs_input;
   1318 
   1319    if (!eat_white( &ctx->cur )) {
   1320       report_error( ctx, "Syntax error" );
   1321       return FALSE;
   1322    }
   1323    if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
   1324       return FALSE;
   1325    if (!parse_opt_writemask( ctx, &writemask ))
   1326       return FALSE;
   1327 
   1328    decl = tgsi_default_full_declaration();
   1329    decl.Declaration.File = file;
   1330    decl.Declaration.UsageMask = writemask;
   1331 
   1332    if (num_brackets == 1) {
   1333       decl.Range.First = brackets[0].first;
   1334       decl.Range.Last = brackets[0].last;
   1335    } else {
   1336       decl.Range.First = brackets[1].first;
   1337       decl.Range.Last = brackets[1].last;
   1338 
   1339       decl.Declaration.Dimension = 1;
   1340       decl.Dim.Index2D = brackets[0].first;
   1341    }
   1342 
   1343    is_vs_input = (file == TGSI_FILE_INPUT &&
   1344                   ctx->processor == PIPE_SHADER_VERTEX);
   1345 
   1346    cur = ctx->cur;
   1347    eat_opt_white( &cur );
   1348    if (*cur == ',') {
   1349       cur2 = cur;
   1350       cur2++;
   1351       eat_opt_white( &cur2 );
   1352       if (str_match_nocase_whole( &cur2, "ARRAY" )) {
   1353          int arrayid;
   1354          if (*cur2 != '(') {
   1355             report_error( ctx, "Expected `('" );
   1356             return FALSE;
   1357          }
   1358          cur2++;
   1359          eat_opt_white( &cur2 );
   1360          if (!parse_int( &cur2, &arrayid )) {
   1361             report_error( ctx, "Expected `,'" );
   1362             return FALSE;
   1363          }
   1364          eat_opt_white( &cur2 );
   1365          if (*cur2 != ')') {
   1366             report_error( ctx, "Expected `)'" );
   1367             return FALSE;
   1368          }
   1369          cur2++;
   1370          decl.Declaration.Array = 1;
   1371          decl.Array.ArrayID = arrayid;
   1372          ctx->cur = cur = cur2;
   1373       }
   1374    }
   1375 
   1376    if (*cur == ',' && !is_vs_input) {
   1377       uint i, j;
   1378 
   1379       cur++;
   1380       eat_opt_white( &cur );
   1381       if (file == TGSI_FILE_IMAGE) {
   1382          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
   1383             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
   1384                decl.Image.Resource = i;
   1385                break;
   1386             }
   1387          }
   1388          if (i == TGSI_TEXTURE_COUNT) {
   1389             report_error(ctx, "Expected texture target");
   1390             return FALSE;
   1391          }
   1392 
   1393          cur2 = cur;
   1394          eat_opt_white(&cur2);
   1395          while (*cur2 == ',') {
   1396             cur2++;
   1397             eat_opt_white(&cur2);
   1398             if (str_match_nocase_whole(&cur2, "RAW")) {
   1399                decl.Image.Raw = 1;
   1400 
   1401             } else if (str_match_nocase_whole(&cur2, "WR")) {
   1402                decl.Image.Writable = 1;
   1403 
   1404             } else {
   1405                int format = str_match_format(&cur2);
   1406                if (format < 0)
   1407                   break;
   1408 
   1409                decl.Image.Format = format;
   1410             }
   1411             cur = cur2;
   1412             eat_opt_white(&cur2);
   1413          }
   1414 
   1415          ctx->cur = cur;
   1416 
   1417       } else if (file == TGSI_FILE_SAMPLER_VIEW) {
   1418          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
   1419             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
   1420                decl.SamplerView.Resource = i;
   1421                break;
   1422             }
   1423          }
   1424          if (i == TGSI_TEXTURE_COUNT) {
   1425             report_error(ctx, "Expected texture target");
   1426             return FALSE;
   1427          }
   1428          eat_opt_white( &cur );
   1429          if (*cur != ',') {
   1430             report_error( ctx, "Expected `,'" );
   1431             return FALSE;
   1432          }
   1433          ++cur;
   1434          eat_opt_white( &cur );
   1435          for (j = 0; j < 4; ++j) {
   1436             for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {
   1437                if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {
   1438                   switch (j) {
   1439                   case 0:
   1440                      decl.SamplerView.ReturnTypeX = i;
   1441                      break;
   1442                   case 1:
   1443                      decl.SamplerView.ReturnTypeY = i;
   1444                      break;
   1445                   case 2:
   1446                      decl.SamplerView.ReturnTypeZ = i;
   1447                      break;
   1448                   case 3:
   1449                      decl.SamplerView.ReturnTypeW = i;
   1450                      break;
   1451                   default:
   1452                      assert(0);
   1453                   }
   1454                   break;
   1455                }
   1456             }
   1457             if (i == TGSI_RETURN_TYPE_COUNT) {
   1458                if (j == 0 || j >  2) {
   1459                   report_error(ctx, "Expected type name");
   1460                   return FALSE;
   1461                }
   1462                break;
   1463             } else {
   1464                cur2 = cur;
   1465                eat_opt_white( &cur2 );
   1466                if (*cur2 == ',') {
   1467                   cur2++;
   1468                   eat_opt_white( &cur2 );
   1469                   cur = cur2;
   1470                   continue;
   1471                } else
   1472                   break;
   1473             }
   1474          }
   1475          if (j < 4) {
   1476             decl.SamplerView.ReturnTypeY =
   1477                decl.SamplerView.ReturnTypeZ =
   1478                decl.SamplerView.ReturnTypeW =
   1479                decl.SamplerView.ReturnTypeX;
   1480          }
   1481          ctx->cur = cur;
   1482       } else if (file == TGSI_FILE_BUFFER) {
   1483          if (str_match_nocase_whole(&cur, "ATOMIC")) {
   1484             decl.Declaration.Atomic = 1;
   1485             ctx->cur = cur;
   1486          }
   1487       } else if (file == TGSI_FILE_MEMORY) {
   1488          if (str_match_nocase_whole(&cur, "GLOBAL")) {
   1489             /* Note this is a no-op global is the default */
   1490             decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL;
   1491             ctx->cur = cur;
   1492          } else if (str_match_nocase_whole(&cur, "SHARED")) {
   1493             decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED;
   1494             ctx->cur = cur;
   1495          } else if (str_match_nocase_whole(&cur, "PRIVATE")) {
   1496             decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE;
   1497             ctx->cur = cur;
   1498          } else if (str_match_nocase_whole(&cur, "INPUT")) {
   1499             decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT;
   1500             ctx->cur = cur;
   1501          }
   1502       } else {
   1503          if (str_match_nocase_whole(&cur, "LOCAL")) {
   1504             decl.Declaration.Local = 1;
   1505             ctx->cur = cur;
   1506          }
   1507 
   1508          cur = ctx->cur;
   1509          eat_opt_white( &cur );
   1510          if (*cur == ',') {
   1511             cur++;
   1512             eat_opt_white( &cur );
   1513 
   1514             for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
   1515                if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
   1516                   uint index;
   1517 
   1518                   cur2 = cur;
   1519                   eat_opt_white( &cur2 );
   1520                   if (*cur2 == '[') {
   1521                      cur2++;
   1522                      eat_opt_white( &cur2 );
   1523                      if (!parse_uint( &cur2, &index )) {
   1524                         report_error( ctx, "Expected literal integer" );
   1525                         return FALSE;
   1526                      }
   1527                      eat_opt_white( &cur2 );
   1528                      if (*cur2 != ']') {
   1529                         report_error( ctx, "Expected `]'" );
   1530                         return FALSE;
   1531                      }
   1532                      cur2++;
   1533 
   1534                      decl.Semantic.Index = index;
   1535 
   1536                      cur = cur2;
   1537                   }
   1538 
   1539                   decl.Declaration.Semantic = 1;
   1540                   decl.Semantic.Name = i;
   1541 
   1542                   ctx->cur = cur;
   1543                   break;
   1544                }
   1545             }
   1546          }
   1547       }
   1548    }
   1549 
   1550    cur = ctx->cur;
   1551    eat_opt_white( &cur );
   1552    if (*cur == ',' &&
   1553        file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) {
   1554       cur++;
   1555       eat_opt_white(&cur);
   1556       if (str_match_nocase_whole(&cur, "STREAM")) {
   1557          uint stream[4];
   1558 
   1559          eat_opt_white(&cur);
   1560          if (*cur != '(') {
   1561             report_error(ctx, "Expected '('");
   1562             return FALSE;
   1563          }
   1564          cur++;
   1565 
   1566          for (int i = 0; i < 4; ++i) {
   1567             eat_opt_white(&cur);
   1568             if (!parse_uint(&cur, &stream[i])) {
   1569                report_error(ctx, "Expected literal integer");
   1570                return FALSE;
   1571             }
   1572 
   1573             eat_opt_white(&cur);
   1574             if (i < 3) {
   1575                if (*cur != ',') {
   1576                   report_error(ctx, "Expected ','");
   1577                   return FALSE;
   1578                }
   1579                cur++;
   1580             }
   1581          }
   1582 
   1583          if (*cur != ')') {
   1584             report_error(ctx, "Expected ')'");
   1585             return FALSE;
   1586          }
   1587          cur++;
   1588 
   1589          decl.Semantic.StreamX = stream[0];
   1590          decl.Semantic.StreamY = stream[1];
   1591          decl.Semantic.StreamZ = stream[2];
   1592          decl.Semantic.StreamW = stream[3];
   1593 
   1594          ctx->cur = cur;
   1595       }
   1596    }
   1597 
   1598    cur = ctx->cur;
   1599    eat_opt_white( &cur );
   1600    if (*cur == ',' && !is_vs_input) {
   1601       uint i;
   1602 
   1603       cur++;
   1604       eat_opt_white( &cur );
   1605       for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
   1606          if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
   1607             decl.Declaration.Interpolate = 1;
   1608             decl.Interp.Interpolate = i;
   1609 
   1610             ctx->cur = cur;
   1611             break;
   1612          }
   1613       }
   1614       if (i == TGSI_INTERPOLATE_COUNT) {
   1615          report_error( ctx, "Expected semantic or interpolate attribute" );
   1616          return FALSE;
   1617       }
   1618    }
   1619 
   1620    cur = ctx->cur;
   1621    eat_opt_white( &cur );
   1622    if (*cur == ',' && !is_vs_input) {
   1623       uint i;
   1624 
   1625       cur++;
   1626       eat_opt_white( &cur );
   1627       for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {
   1628          if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {
   1629             decl.Interp.Location = i;
   1630 
   1631             ctx->cur = cur;
   1632             break;
   1633          }
   1634       }
   1635    }
   1636 
   1637    advance = tgsi_build_full_declaration(
   1638       &decl,
   1639       ctx->tokens_cur,
   1640       ctx->header,
   1641       (uint) (ctx->tokens_end - ctx->tokens_cur) );
   1642 
   1643    if (advance == 0)
   1644       return FALSE;
   1645    ctx->tokens_cur += advance;
   1646 
   1647    return TRUE;
   1648 }
   1649 
   1650 static boolean parse_immediate( struct translate_ctx *ctx )
   1651 {
   1652    struct tgsi_full_immediate imm;
   1653    uint advance;
   1654    int type;
   1655 
   1656    if (*ctx->cur == '[') {
   1657       uint uindex;
   1658 
   1659       ++ctx->cur;
   1660 
   1661       eat_opt_white( &ctx->cur );
   1662       if (!parse_uint( &ctx->cur, &uindex )) {
   1663          report_error( ctx, "Expected literal unsigned integer" );
   1664          return FALSE;
   1665       }
   1666 
   1667       if (uindex != ctx->num_immediates) {
   1668          report_error( ctx, "Immediates must be sorted" );
   1669          return FALSE;
   1670       }
   1671 
   1672       eat_opt_white( &ctx->cur );
   1673       if (*ctx->cur != ']') {
   1674          report_error( ctx, "Expected `]'" );
   1675          return FALSE;
   1676       }
   1677 
   1678       ctx->cur++;
   1679    }
   1680 
   1681    if (!eat_white( &ctx->cur )) {
   1682       report_error( ctx, "Syntax error" );
   1683       return FALSE;
   1684    }
   1685    for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) {
   1686       if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
   1687          break;
   1688    }
   1689    if (type == ARRAY_SIZE(tgsi_immediate_type_names)) {
   1690       report_error( ctx, "Expected immediate type" );
   1691       return FALSE;
   1692    }
   1693 
   1694    imm = tgsi_default_full_immediate();
   1695    imm.Immediate.NrTokens += 4;
   1696    imm.Immediate.DataType = type;
   1697    parse_immediate_data(ctx, type, imm.u);
   1698 
   1699    advance = tgsi_build_full_immediate(
   1700       &imm,
   1701       ctx->tokens_cur,
   1702       ctx->header,
   1703       (uint) (ctx->tokens_end - ctx->tokens_cur) );
   1704    if (advance == 0)
   1705       return FALSE;
   1706    ctx->tokens_cur += advance;
   1707 
   1708    ctx->num_immediates++;
   1709 
   1710    return TRUE;
   1711 }
   1712 
   1713 static boolean
   1714 parse_primitive( const char **pcur, uint *primitive )
   1715 {
   1716    uint i;
   1717 
   1718    for (i = 0; i < PIPE_PRIM_MAX; i++) {
   1719       const char *cur = *pcur;
   1720 
   1721       if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
   1722          *primitive = i;
   1723          *pcur = cur;
   1724          return TRUE;
   1725       }
   1726    }
   1727    return FALSE;
   1728 }
   1729 
   1730 static boolean
   1731 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
   1732 {
   1733    uint i;
   1734 
   1735    for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) {
   1736       const char *cur = *pcur;
   1737 
   1738       if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
   1739          *fs_coord_origin = i;
   1740          *pcur = cur;
   1741          return TRUE;
   1742       }
   1743    }
   1744    return FALSE;
   1745 }
   1746 
   1747 static boolean
   1748 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
   1749 {
   1750    uint i;
   1751 
   1752    for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) {
   1753       const char *cur = *pcur;
   1754 
   1755       if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
   1756          *fs_coord_pixel_center = i;
   1757          *pcur = cur;
   1758          return TRUE;
   1759       }
   1760    }
   1761    return FALSE;
   1762 }
   1763 
   1764 static boolean
   1765 parse_property_next_shader( const char **pcur, uint *next_shader )
   1766 {
   1767    uint i;
   1768 
   1769    for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) {
   1770       const char *cur = *pcur;
   1771 
   1772       if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) {
   1773          *next_shader = i;
   1774          *pcur = cur;
   1775          return TRUE;
   1776       }
   1777    }
   1778    return FALSE;
   1779 }
   1780 
   1781 static boolean parse_property( struct translate_ctx *ctx )
   1782 {
   1783    struct tgsi_full_property prop;
   1784    uint property_name;
   1785    uint values[8];
   1786    uint advance;
   1787    char id[64];
   1788 
   1789    if (!eat_white( &ctx->cur )) {
   1790       report_error( ctx, "Syntax error" );
   1791       return FALSE;
   1792    }
   1793    if (!parse_identifier( &ctx->cur, id, sizeof(id) )) {
   1794       report_error( ctx, "Syntax error" );
   1795       return FALSE;
   1796    }
   1797    for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
   1798         ++property_name) {
   1799       if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
   1800          break;
   1801       }
   1802    }
   1803    if (property_name >= TGSI_PROPERTY_COUNT) {
   1804       debug_printf( "\nError: Unknown property : '%s'", id );
   1805       return FALSE;
   1806    }
   1807 
   1808    eat_opt_white( &ctx->cur );
   1809    switch(property_name) {
   1810    case TGSI_PROPERTY_GS_INPUT_PRIM:
   1811    case TGSI_PROPERTY_GS_OUTPUT_PRIM:
   1812       if (!parse_primitive(&ctx->cur, &values[0] )) {
   1813          report_error( ctx, "Unknown primitive name as property!" );
   1814          return FALSE;
   1815       }
   1816       if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
   1817           ctx->processor == PIPE_SHADER_GEOMETRY) {
   1818          ctx->implied_array_size = u_vertices_per_prim(values[0]);
   1819       }
   1820       break;
   1821    case TGSI_PROPERTY_FS_COORD_ORIGIN:
   1822       if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
   1823          report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
   1824          return FALSE;
   1825       }
   1826       break;
   1827    case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
   1828       if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
   1829          report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
   1830          return FALSE;
   1831       }
   1832       break;
   1833    case TGSI_PROPERTY_NEXT_SHADER:
   1834       if (!parse_property_next_shader(&ctx->cur, &values[0] )) {
   1835          report_error( ctx, "Unknown next shader property value." );
   1836          return FALSE;
   1837       }
   1838       break;
   1839    case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
   1840    default:
   1841       if (!parse_uint(&ctx->cur, &values[0] )) {
   1842          report_error( ctx, "Expected unsigned integer as property!" );
   1843          return FALSE;
   1844       }
   1845    }
   1846 
   1847    prop = tgsi_default_full_property();
   1848    prop.Property.PropertyName = property_name;
   1849    prop.Property.NrTokens += 1;
   1850    prop.u[0].Data = values[0];
   1851 
   1852    advance = tgsi_build_full_property(
   1853       &prop,
   1854       ctx->tokens_cur,
   1855       ctx->header,
   1856       (uint) (ctx->tokens_end - ctx->tokens_cur) );
   1857    if (advance == 0)
   1858       return FALSE;
   1859    ctx->tokens_cur += advance;
   1860 
   1861    return TRUE;
   1862 }
   1863 
   1864 
   1865 static boolean translate( struct translate_ctx *ctx )
   1866 {
   1867    eat_opt_white( &ctx->cur );
   1868    if (!parse_header( ctx ))
   1869       return FALSE;
   1870 
   1871    if (ctx->processor == PIPE_SHADER_TESS_CTRL ||
   1872        ctx->processor == PIPE_SHADER_TESS_EVAL)
   1873        ctx->implied_array_size = 32;
   1874 
   1875    while (*ctx->cur != '\0') {
   1876       uint label_val = 0;
   1877       if (!eat_white( &ctx->cur )) {
   1878          report_error( ctx, "Syntax error" );
   1879          return FALSE;
   1880       }
   1881 
   1882       if (*ctx->cur == '\0')
   1883          break;
   1884       if (parse_label( ctx, &label_val )) {
   1885          if (!parse_instruction( ctx, TRUE ))
   1886             return FALSE;
   1887       }
   1888       else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
   1889          if (!parse_declaration( ctx ))
   1890             return FALSE;
   1891       }
   1892       else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
   1893          if (!parse_immediate( ctx ))
   1894             return FALSE;
   1895       }
   1896       else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
   1897          if (!parse_property( ctx ))
   1898             return FALSE;
   1899       }
   1900       else if (!parse_instruction( ctx, FALSE )) {
   1901          return FALSE;
   1902       }
   1903    }
   1904 
   1905    return TRUE;
   1906 }
   1907 
   1908 boolean
   1909 tgsi_text_translate(
   1910    const char *text,
   1911    struct tgsi_token *tokens,
   1912    uint num_tokens )
   1913 {
   1914    struct translate_ctx ctx = {0};
   1915 
   1916    ctx.text = text;
   1917    ctx.cur = text;
   1918    ctx.tokens = tokens;
   1919    ctx.tokens_cur = tokens;
   1920    ctx.tokens_end = tokens + num_tokens;
   1921 
   1922    if (!translate( &ctx ))
   1923       return FALSE;
   1924 
   1925    return tgsi_sanity_check( tokens );
   1926 }
   1927