tgsi_text.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 #include "pipe/p_debug.h"
00029 #include "tgsi_text.h"
00030 #include "tgsi_build.h"
00031 #include "tgsi_info.h"
00032 #include "tgsi_parse.h"
00033 #include "tgsi_sanity.h"
00034 #include "tgsi_util.h"
00035 
00036 static boolean is_alpha_underscore( const char *cur )
00037 {
00038    return
00039       (*cur >= 'a' && *cur <= 'z') ||
00040       (*cur >= 'A' && *cur <= 'Z') ||
00041       *cur == '_';
00042 }
00043 
00044 static boolean is_digit( const char *cur )
00045 {
00046    return *cur >= '0' && *cur <= '9';
00047 }
00048 
00049 static boolean is_digit_alpha_underscore( const char *cur )
00050 {
00051    return is_digit( cur ) || is_alpha_underscore( cur );
00052 }
00053 
00054 static boolean uprcase( char c )
00055 {
00056    if (c >= 'a' && c <= 'z')
00057       return c += 'A' - 'a';
00058    return c;
00059 }
00060 
00061 static boolean str_match_no_case( const char **pcur, const char *str )
00062 {
00063    const char *cur = *pcur;
00064 
00065    while (*str != '\0' && *str == uprcase( *cur )) {
00066       str++;
00067       cur++;
00068    }
00069    if (*str == '\0') {
00070       *pcur = cur;
00071       return TRUE;
00072    }
00073    return FALSE;
00074 }
00075 
00076 /* Eat zero or more whitespaces.
00077  */
00078 static void eat_opt_white( const char **pcur )
00079 {
00080    while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
00081       (*pcur)++;
00082 }
00083 
00084 /* Eat one or more whitespaces.
00085  * Return TRUE if at least one whitespace eaten.
00086  */
00087 static boolean eat_white( const char **pcur )
00088 {
00089    const char *cur = *pcur;
00090 
00091    eat_opt_white( pcur );
00092    return *pcur > cur;
00093 }
00094 
00095 /* Parse unsigned integer.
00096  * No checks for overflow.
00097  */
00098 static boolean parse_uint( const char **pcur, uint *val )
00099 {
00100    const char *cur = *pcur;
00101 
00102    if (is_digit( cur )) {
00103       *val = *cur++ - '0';
00104       while (is_digit( cur ))
00105          *val = *val * 10 + *cur++ - '0';
00106       *pcur = cur;
00107       return TRUE;
00108    }
00109    return FALSE;
00110 }
00111 
00112 /* Parse floating point.
00113  */
00114 static boolean parse_float( const char **pcur, float *val )
00115 {
00116    const char *cur = *pcur;
00117    boolean integral_part = FALSE;
00118    boolean fractional_part = FALSE;
00119 
00120    *val = (float) atof( cur );
00121 
00122    if (*cur == '-' || *cur == '+')
00123       cur++;
00124    if (is_digit( cur )) {
00125       cur++;
00126       integral_part = TRUE;
00127       while (is_digit( cur ))
00128          cur++;
00129    }
00130    if (*cur == '.') {
00131       cur++;
00132       if (is_digit( cur )) {
00133          cur++;
00134          fractional_part = TRUE;
00135          while (is_digit( cur ))
00136             cur++;
00137       }
00138    }
00139    if (!integral_part && !fractional_part)
00140       return FALSE;
00141    if (uprcase( *cur ) == 'E') {
00142       cur++;
00143       if (*cur == '-' || *cur == '+')
00144          cur++;
00145       if (is_digit( cur )) {
00146          cur++;
00147          while (is_digit( cur ))
00148             cur++;
00149       }
00150       else
00151          return FALSE;
00152    }
00153    *pcur = cur;
00154    return TRUE;
00155 }
00156 
00157 struct translate_ctx
00158 {
00159    const char *text;
00160    const char *cur;
00161    struct tgsi_token *tokens;
00162    struct tgsi_token *tokens_cur;
00163    struct tgsi_token *tokens_end;
00164    struct tgsi_header *header;
00165 };
00166 
00167 static void report_error( struct translate_ctx *ctx, const char *msg )
00168 {
00169    debug_printf( "\nError: %s", msg );
00170 }
00171 
00172 /* Parse shader header.
00173  * Return TRUE for one of the following headers.
00174  *    FRAG1.1
00175  *    GEOM1.1
00176  *    VERT1.1
00177  */
00178 static boolean parse_header( struct translate_ctx *ctx )
00179 {
00180    uint processor;
00181 
00182    if (str_match_no_case( &ctx->cur, "FRAG1.1" ))
00183       processor = TGSI_PROCESSOR_FRAGMENT;
00184    else if (str_match_no_case( &ctx->cur, "VERT1.1" ))
00185       processor = TGSI_PROCESSOR_VERTEX;
00186    else if (str_match_no_case( &ctx->cur, "GEOM1.1" ))
00187       processor = TGSI_PROCESSOR_GEOMETRY;
00188    else {
00189       report_error( ctx, "Unknown header" );
00190       return FALSE;
00191    }
00192 
00193    if (ctx->tokens_cur >= ctx->tokens_end)
00194       return FALSE;
00195    *(struct tgsi_version *) ctx->tokens_cur++ = tgsi_build_version();
00196 
00197    if (ctx->tokens_cur >= ctx->tokens_end)
00198       return FALSE;
00199    ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
00200    *ctx->header = tgsi_build_header();
00201 
00202    if (ctx->tokens_cur >= ctx->tokens_end)
00203       return FALSE;
00204    *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
00205 
00206    return TRUE;
00207 }
00208 
00209 static boolean parse_label( struct translate_ctx *ctx, uint *val )
00210 {
00211    const char *cur = ctx->cur;
00212 
00213    if (parse_uint( &cur, val )) {
00214       eat_opt_white( &cur );
00215       if (*cur == ':') {
00216          cur++;
00217          ctx->cur = cur;
00218          return TRUE;
00219       }
00220    }
00221    return FALSE;
00222 }
00223 
00224 static const char *file_names[TGSI_FILE_COUNT] =
00225 {
00226    "NULL",
00227    "CONST",
00228    "IN",
00229    "OUT",
00230    "TEMP",
00231    "SAMP",
00232    "ADDR",
00233    "IMM",
00234    "LOOP"
00235 };
00236 
00237 static boolean
00238 parse_file( const char **pcur, uint *file )
00239 {
00240    uint i;
00241 
00242    for (i = 0; i < TGSI_FILE_COUNT; i++) {
00243       const char *cur = *pcur;
00244 
00245       if (str_match_no_case( &cur, file_names[i] )) {
00246          if (!is_digit_alpha_underscore( cur )) {
00247             *pcur = cur;
00248             *file = i;
00249             return TRUE;
00250          }
00251       }
00252    }
00253    return FALSE;
00254 }
00255 
00256 static boolean
00257 parse_opt_writemask(
00258    struct translate_ctx *ctx,
00259    uint *writemask )
00260 {
00261    const char *cur;
00262 
00263    cur = ctx->cur;
00264    eat_opt_white( &cur );
00265    if (*cur == '.') {
00266       cur++;
00267       *writemask = TGSI_WRITEMASK_NONE;
00268       eat_opt_white( &cur );
00269       if (uprcase( *cur ) == 'X') {
00270          cur++;
00271          *writemask |= TGSI_WRITEMASK_X;
00272       }
00273       if (uprcase( *cur ) == 'Y') {
00274          cur++;
00275          *writemask |= TGSI_WRITEMASK_Y;
00276       }
00277       if (uprcase( *cur ) == 'Z') {
00278          cur++;
00279          *writemask |= TGSI_WRITEMASK_Z;
00280       }
00281       if (uprcase( *cur ) == 'W') {
00282          cur++;
00283          *writemask |= TGSI_WRITEMASK_W;
00284       }
00285 
00286       if (*writemask == TGSI_WRITEMASK_NONE) {
00287          report_error( ctx, "Writemask expected" );
00288          return FALSE;
00289       }
00290 
00291       ctx->cur = cur;
00292    }
00293    else {
00294       *writemask = TGSI_WRITEMASK_XYZW;
00295    }
00296    return TRUE;
00297 }
00298 
00299 /* <register_file_bracket> ::= <file> `['
00300  */
00301 static boolean
00302 parse_register_file_bracket(
00303    struct translate_ctx *ctx,
00304    uint *file )
00305 {
00306    if (!parse_file( &ctx->cur, file )) {
00307       report_error( ctx, "Unknown register file" );
00308       return FALSE;
00309    }
00310    eat_opt_white( &ctx->cur );
00311    if (*ctx->cur != '[') {
00312       report_error( ctx, "Expected `['" );
00313       return FALSE;
00314    }
00315    ctx->cur++;
00316    return TRUE;
00317 }
00318 
00319 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
00320  */
00321 static boolean
00322 parse_register_file_bracket_index(
00323    struct translate_ctx *ctx,
00324    uint *file,
00325    int *index )
00326 {
00327    uint uindex;
00328 
00329    if (!parse_register_file_bracket( ctx, file ))
00330       return FALSE;
00331    eat_opt_white( &ctx->cur );
00332    if (!parse_uint( &ctx->cur, &uindex )) {
00333       report_error( ctx, "Expected literal unsigned integer" );
00334       return FALSE;
00335    }
00336    *index = (int) uindex;
00337    return TRUE;
00338 }
00339 
00340 /* Parse destination register operand.
00341  *    <register_dst> ::= <register_file_bracket_index> `]'
00342  */
00343 static boolean
00344 parse_register_dst(
00345    struct translate_ctx *ctx,
00346    uint *file,
00347    int *index )
00348 {
00349    if (!parse_register_file_bracket_index( ctx, file, index ))
00350       return FALSE;
00351    eat_opt_white( &ctx->cur );
00352    if (*ctx->cur != ']') {
00353       report_error( ctx, "Expected `]'" );
00354       return FALSE;
00355    }
00356    ctx->cur++;
00357    return TRUE;
00358 }
00359 
00360 /* Parse source register operand.
00361  *    <register_src> ::= <register_file_bracket_index> `]' |
00362  *                       <register_file_bracket> <register_dst> `]' |
00363  *                       <register_file_bracket> <register_dst> `+' <uint> `]' |
00364  *                       <register_file_bracket> <register_dst> `-' <uint> `]'
00365  */
00366 static boolean
00367 parse_register_src(
00368    struct translate_ctx *ctx,
00369    uint *file,
00370    int *index,
00371    uint *ind_file,
00372    int *ind_index )
00373 {
00374    const char *cur;
00375    uint uindex;
00376 
00377    if (!parse_register_file_bracket( ctx, file ))
00378       return FALSE;
00379    eat_opt_white( &ctx->cur );
00380    cur = ctx->cur;
00381    if (parse_file( &cur, ind_file )) {
00382       if (!parse_register_dst( ctx, ind_file, ind_index ))
00383          return FALSE;
00384       eat_opt_white( &ctx->cur );
00385       if (*ctx->cur == '+' || *ctx->cur == '-') {
00386          boolean negate;
00387 
00388          negate = *ctx->cur == '-';
00389          ctx->cur++;
00390          eat_opt_white( &ctx->cur );
00391          if (!parse_uint( &ctx->cur, &uindex )) {
00392             report_error( ctx, "Expected literal unsigned integer" );
00393             return FALSE;
00394          }
00395          if (negate)
00396             *index = -(int) uindex;
00397          else
00398             *index = (int) uindex;
00399       }
00400       else {
00401          *index = 0;
00402       }
00403    }
00404    else {
00405       if (!parse_uint( &ctx->cur, &uindex )) {
00406          report_error( ctx, "Expected literal unsigned integer" );
00407          return FALSE;
00408       }
00409       *index = (int) uindex;
00410       *ind_file = TGSI_FILE_NULL;
00411       *ind_index = 0;
00412    }
00413    eat_opt_white( &ctx->cur );
00414    if (*ctx->cur != ']') {
00415       report_error( ctx, "Expected `]'" );
00416       return FALSE;
00417    }
00418    ctx->cur++;
00419    return TRUE;
00420 }
00421 
00422 /* Parse register declaration.
00423  *    <register_dcl> ::= <register_file_bracket_index> `]' |
00424  *                       <register_file_bracket_index> `..' <index> `]'
00425  */
00426 static boolean
00427 parse_register_dcl(
00428    struct translate_ctx *ctx,
00429    uint *file,
00430    int *first,
00431    int *last )
00432 {
00433    if (!parse_register_file_bracket_index( ctx, file, first ))
00434       return FALSE;
00435    eat_opt_white( &ctx->cur );
00436    if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
00437       uint uindex;
00438 
00439       ctx->cur += 2;
00440       eat_opt_white( &ctx->cur );
00441       if (!parse_uint( &ctx->cur, &uindex )) {
00442          report_error( ctx, "Expected literal integer" );
00443          return FALSE;
00444       }
00445       *last = (int) uindex;
00446       eat_opt_white( &ctx->cur );
00447    }
00448    else {
00449       *last = *first;
00450    }
00451    if (*ctx->cur != ']') {
00452       report_error( ctx, "Expected `]' or `..'" );
00453       return FALSE;
00454    }
00455    ctx->cur++;
00456    return TRUE;
00457 }
00458 
00459 static const char *modulate_names[TGSI_MODULATE_COUNT] =
00460 {
00461    "_1X",
00462    "_2X",
00463    "_4X",
00464    "_8X",
00465    "_D2",
00466    "_D4",
00467    "_D8"
00468 };
00469 
00470 static boolean
00471 parse_dst_operand(
00472    struct translate_ctx *ctx,
00473    struct tgsi_full_dst_register *dst )
00474 {
00475    uint file;
00476    int index;
00477    uint writemask;
00478    const char *cur;
00479 
00480    if (!parse_register_dst( ctx, &file, &index ))
00481       return FALSE;
00482 
00483    cur = ctx->cur;
00484    eat_opt_white( &cur );
00485    if (*cur == '_') {
00486       uint i;
00487 
00488       for (i = 0; i < TGSI_MODULATE_COUNT; i++) {
00489          if (str_match_no_case( &cur, modulate_names[i] )) {
00490             if (!is_digit_alpha_underscore( cur )) {
00491                dst->DstRegisterExtModulate.Modulate = i;
00492                ctx->cur = cur;
00493                break;
00494             }
00495          }
00496       }
00497    }
00498 
00499    if (!parse_opt_writemask( ctx, &writemask ))
00500       return FALSE;
00501 
00502    dst->DstRegister.File = file;
00503    dst->DstRegister.Index = index;
00504    dst->DstRegister.WriteMask = writemask;
00505    return TRUE;
00506 }
00507 
00508 static boolean
00509 parse_optional_swizzle(
00510    struct translate_ctx *ctx,
00511    uint swizzle[4],
00512    boolean *parsed_swizzle,
00513    boolean *parsed_extswizzle )
00514 {
00515    const char *cur = ctx->cur;
00516 
00517    *parsed_swizzle = FALSE;
00518    *parsed_extswizzle = FALSE;
00519 
00520    eat_opt_white( &cur );
00521    if (*cur == '.') {
00522       uint i;
00523 
00524       cur++;
00525       eat_opt_white( &cur );
00526       for (i = 0; i < 4; i++) {
00527          if (uprcase( *cur ) == 'X')
00528             swizzle[i] = TGSI_SWIZZLE_X;
00529          else if (uprcase( *cur ) == 'Y')
00530             swizzle[i] = TGSI_SWIZZLE_Y;
00531          else if (uprcase( *cur ) == 'Z')
00532             swizzle[i] = TGSI_SWIZZLE_Z;
00533          else if (uprcase( *cur ) == 'W')
00534             swizzle[i] = TGSI_SWIZZLE_W;
00535          else {
00536             if (*cur == '0')
00537                swizzle[i] = TGSI_EXTSWIZZLE_ZERO;
00538             else if (*cur == '1')
00539                swizzle[i] = TGSI_EXTSWIZZLE_ONE;
00540             else {
00541                report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
00542                return FALSE;
00543             }
00544             *parsed_extswizzle = TRUE;
00545          }
00546          cur++;
00547       }
00548       *parsed_swizzle = TRUE;
00549       ctx->cur = cur;
00550    }
00551    return TRUE;
00552 }
00553 
00554 static boolean
00555 parse_src_operand(
00556    struct translate_ctx *ctx,
00557    struct tgsi_full_src_register *src )
00558 {
00559    const char *cur;
00560    float value;
00561    uint file;
00562    int index;
00563    uint ind_file;
00564    int ind_index;
00565    uint swizzle[4];
00566    boolean parsed_swizzle;
00567    boolean parsed_extswizzle;
00568 
00569    if (*ctx->cur == '-') {
00570       cur = ctx->cur;
00571       cur++;
00572       eat_opt_white( &cur );
00573       if (*cur == '(') {
00574          cur++;
00575          src->SrcRegisterExtMod.Negate = 1;
00576          eat_opt_white( &cur );
00577          ctx->cur = cur;
00578       }
00579    }
00580 
00581    if (*ctx->cur == '|') {
00582       ctx->cur++;
00583       eat_opt_white( &ctx->cur );
00584       src->SrcRegisterExtMod.Absolute = 1;
00585    }
00586 
00587    if (*ctx->cur == '-') {
00588       ctx->cur++;
00589       eat_opt_white( &ctx->cur );
00590       src->SrcRegister.Negate = 1;
00591    }
00592 
00593    cur = ctx->cur;
00594    if (parse_float( &cur, &value )) {
00595       if (value == 2.0f) {
00596          eat_opt_white( &cur );
00597          if (*cur != '*') {
00598             report_error( ctx, "Expected `*'" );
00599             return FALSE;
00600          }
00601          cur++;
00602          if (*cur != '(') {
00603             report_error( ctx, "Expected `('" );
00604             return FALSE;
00605          }
00606          cur++;
00607          src->SrcRegisterExtMod.Scale2X = 1;
00608          eat_opt_white( &cur );
00609          ctx->cur = cur;
00610       }
00611    }
00612 
00613    if (*ctx->cur == '(') {
00614       ctx->cur++;
00615       eat_opt_white( &ctx->cur );
00616       src->SrcRegisterExtMod.Bias = 1;
00617    }
00618 
00619    cur = ctx->cur;
00620    if (parse_float( &cur, &value )) {
00621       if (value == 1.0f) {
00622          eat_opt_white( &cur );
00623          if (*cur != '-') {
00624             report_error( ctx, "Expected `-'" );
00625             return FALSE;
00626          }
00627          cur++;
00628          if (*cur != '(') {
00629             report_error( ctx, "Expected `('" );
00630             return FALSE;
00631          }
00632          cur++;
00633          src->SrcRegisterExtMod.Complement = 1;
00634          eat_opt_white( &cur );
00635          ctx->cur = cur;
00636       }
00637    }
00638 
00639    if (!parse_register_src( ctx, &file, &index, &ind_file, &ind_index ))
00640       return FALSE;
00641    src->SrcRegister.File = file;
00642    src->SrcRegister.Index = index;
00643    if (ind_file != TGSI_FILE_NULL) {
00644       src->SrcRegister.Indirect = 1;
00645       src->SrcRegisterInd.File = ind_file;
00646       src->SrcRegisterInd.Index = ind_index;
00647    }
00648 
00649    /* Parse optional swizzle.
00650     */
00651    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, &parsed_extswizzle )) {
00652       if (parsed_extswizzle) {
00653          assert( parsed_swizzle );
00654 
00655          src->SrcRegisterExtSwz.ExtSwizzleX = swizzle[0];
00656          src->SrcRegisterExtSwz.ExtSwizzleY = swizzle[1];
00657          src->SrcRegisterExtSwz.ExtSwizzleZ = swizzle[2];
00658          src->SrcRegisterExtSwz.ExtSwizzleW = swizzle[3];
00659       }
00660       else if (parsed_swizzle) {
00661          src->SrcRegister.SwizzleX = swizzle[0];
00662          src->SrcRegister.SwizzleY = swizzle[1];
00663          src->SrcRegister.SwizzleZ = swizzle[2];
00664          src->SrcRegister.SwizzleW = swizzle[3];
00665       }
00666    }
00667 
00668    if (src->SrcRegisterExtMod.Complement) {
00669       eat_opt_white( &ctx->cur );
00670       if (*ctx->cur != ')') {
00671          report_error( ctx, "Expected `)'" );
00672          return FALSE;
00673       }
00674       ctx->cur++;
00675    }
00676 
00677    if (src->SrcRegisterExtMod.Bias) {
00678       eat_opt_white( &ctx->cur );
00679       if (*ctx->cur != ')') {
00680          report_error( ctx, "Expected `)'" );
00681          return FALSE;
00682       }
00683       ctx->cur++;
00684       eat_opt_white( &ctx->cur );
00685       if (*ctx->cur != '-') {
00686          report_error( ctx, "Expected `-'" );
00687          return FALSE;
00688       }
00689       ctx->cur++;
00690       eat_opt_white( &ctx->cur );
00691       if (!parse_float( &ctx->cur, &value )) {
00692          report_error( ctx, "Expected literal floating point" );
00693          return FALSE;
00694       }
00695       if (value != 0.5f) {
00696          report_error( ctx, "Expected 0.5" );
00697          return FALSE;
00698       }
00699    }
00700 
00701    if (src->SrcRegisterExtMod.Scale2X) {
00702       eat_opt_white( &ctx->cur );
00703       if (*ctx->cur != ')') {
00704          report_error( ctx, "Expected `)'" );
00705          return FALSE;
00706       }
00707       ctx->cur++;
00708    }
00709 
00710    if (src->SrcRegisterExtMod.Absolute) {
00711       eat_opt_white( &ctx->cur );
00712       if (*ctx->cur != '|') {
00713          report_error( ctx, "Expected `|'" );
00714          return FALSE;
00715       }
00716       ctx->cur++;
00717    }
00718 
00719    if (src->SrcRegisterExtMod.Negate) {
00720       eat_opt_white( &ctx->cur );
00721       if (*ctx->cur != ')') {
00722          report_error( ctx, "Expected `)'" );
00723          return FALSE;
00724       }
00725       ctx->cur++;
00726    }
00727 
00728    return TRUE;
00729 }
00730 
00731 static const char *texture_names[TGSI_TEXTURE_COUNT] =
00732 {
00733    "UNKNOWN",
00734    "1D",
00735    "2D",
00736    "3D",
00737    "CUBE",
00738    "RECT",
00739    "SHADOW1D",
00740    "SHADOW2D",
00741    "SHADOWRECT"
00742 };
00743 
00744 static boolean
00745 parse_instruction(
00746    struct translate_ctx *ctx,
00747    boolean has_label )
00748 {
00749    uint i;
00750    uint saturate = TGSI_SAT_NONE;
00751    const struct tgsi_opcode_info *info;
00752    struct tgsi_full_instruction inst;
00753    uint advance;
00754 
00755    /* Parse instruction name.
00756     */
00757    eat_opt_white( &ctx->cur );
00758    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
00759       const char *cur = ctx->cur;
00760 
00761       info = tgsi_get_opcode_info( i );
00762       if (str_match_no_case( &cur, info->mnemonic )) {
00763          if (str_match_no_case( &cur, "_SATNV" ))
00764             saturate = TGSI_SAT_MINUS_PLUS_ONE;
00765          else if (str_match_no_case( &cur, "_SAT" ))
00766             saturate = TGSI_SAT_ZERO_ONE;
00767 
00768          if (info->num_dst + info->num_src + info->is_tex == 0) {
00769             if (!is_digit_alpha_underscore( cur )) {
00770                ctx->cur = cur;
00771                break;
00772             }
00773          }
00774          else if (*cur == '\0' || eat_white( &cur )) {
00775             ctx->cur = cur;
00776             break;
00777          }
00778       }
00779    }
00780    if (i == TGSI_OPCODE_LAST) {
00781       if (has_label)
00782          report_error( ctx, "Unknown opcode" );
00783       else
00784          report_error( ctx, "Expected `DCL', `IMM' or a label" );
00785       return FALSE;
00786    }
00787 
00788    inst = tgsi_default_full_instruction();
00789    inst.Instruction.Opcode = i;
00790    inst.Instruction.Saturate = saturate;
00791    inst.Instruction.NumDstRegs = info->num_dst;
00792    inst.Instruction.NumSrcRegs = info->num_src;
00793 
00794    /* Parse instruction operands.
00795     */
00796    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
00797       if (i > 0) {
00798          eat_opt_white( &ctx->cur );
00799          if (*ctx->cur != ',') {
00800             report_error( ctx, "Expected `,'" );
00801             return FALSE;
00802          }
00803          ctx->cur++;
00804          eat_opt_white( &ctx->cur );
00805       }
00806 
00807       if (i < info->num_dst) {
00808          if (!parse_dst_operand( ctx, &inst.FullDstRegisters[i] ))
00809             return FALSE;
00810       }
00811       else if (i < info->num_dst + info->num_src) {
00812          if (!parse_src_operand( ctx, &inst.FullSrcRegisters[i - info->num_dst] ))
00813             return FALSE;
00814       }
00815       else {
00816          uint j;
00817 
00818          for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
00819             if (str_match_no_case( &ctx->cur, texture_names[j] )) {
00820                if (!is_digit_alpha_underscore( ctx->cur )) {
00821                   inst.InstructionExtTexture.Texture = j;
00822                   break;
00823                }
00824             }
00825          }
00826          if (j == TGSI_TEXTURE_COUNT) {
00827             report_error( ctx, "Expected texture target" );
00828             return FALSE;
00829          }
00830       }
00831    }
00832 
00833    if (info->is_branch) {
00834       uint target;
00835 
00836       eat_opt_white( &ctx->cur );
00837       if (*ctx->cur != ':') {
00838          report_error( ctx, "Expected `:'" );
00839          return FALSE;
00840       }
00841       ctx->cur++;
00842       eat_opt_white( &ctx->cur );
00843       if (!parse_uint( &ctx->cur, &target )) {
00844          report_error( ctx, "Expected a label" );
00845          return FALSE;
00846       }
00847       inst.InstructionExtLabel.Label = target;
00848    }
00849 
00850    advance = tgsi_build_full_instruction(
00851       &inst,
00852       ctx->tokens_cur,
00853       ctx->header,
00854       (uint) (ctx->tokens_end - ctx->tokens_cur) );
00855    if (advance == 0)
00856       return FALSE;
00857    ctx->tokens_cur += advance;
00858 
00859    return TRUE;
00860 }
00861 
00862 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
00863 {
00864    "POSITION",
00865    "COLOR",
00866    "BCOLOR",
00867    "FOG",
00868    "PSIZE",
00869    "GENERIC",
00870    "NORMAL"
00871 };
00872 
00873 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
00874 {
00875    "CONSTANT",
00876    "LINEAR",
00877    "PERSPECTIVE"
00878 };
00879 
00880 static boolean parse_declaration( struct translate_ctx *ctx )
00881 {
00882    struct tgsi_full_declaration decl;
00883    uint file;
00884    int first;
00885    int last;
00886    uint writemask;
00887    const char *cur;
00888    uint advance;
00889 
00890    if (!eat_white( &ctx->cur )) {
00891       report_error( ctx, "Syntax error" );
00892       return FALSE;
00893    }
00894    if (!parse_register_dcl( ctx, &file, &first, &last ))
00895       return FALSE;
00896    if (!parse_opt_writemask( ctx, &writemask ))
00897       return FALSE;
00898 
00899    decl = tgsi_default_full_declaration();
00900    decl.Declaration.File = file;
00901    decl.Declaration.UsageMask = writemask;
00902    decl.DeclarationRange.First = first;
00903    decl.DeclarationRange.Last = last;
00904 
00905    cur = ctx->cur;
00906    eat_opt_white( &cur );
00907    if (*cur == ',') {
00908       uint i;
00909 
00910       cur++;
00911       eat_opt_white( &cur );
00912       for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
00913          if (str_match_no_case( &cur, semantic_names[i] )) {
00914             const char *cur2 = cur;
00915             uint index;
00916 
00917             if (is_digit_alpha_underscore( cur ))
00918                continue;
00919             eat_opt_white( &cur2 );
00920             if (*cur2 == '[') {
00921                cur2++;
00922                eat_opt_white( &cur2 );
00923                if (!parse_uint( &cur2, &index )) {
00924                   report_error( ctx, "Expected literal integer" );
00925                   return FALSE;
00926                }
00927                eat_opt_white( &cur2 );
00928                if (*cur2 != ']') {
00929                   report_error( ctx, "Expected `]'" );
00930                   return FALSE;
00931                }
00932                cur2++;
00933 
00934                decl.Semantic.SemanticIndex = index;
00935 
00936                cur = cur2;
00937             }
00938 
00939             decl.Declaration.Semantic = 1;
00940             decl.Semantic.SemanticName = i;
00941 
00942             ctx->cur = cur;
00943             break;
00944          }
00945       }
00946    }
00947 
00948    cur = ctx->cur;
00949    eat_opt_white( &cur );
00950    if (*cur == ',') {
00951       uint i;
00952 
00953       cur++;
00954       eat_opt_white( &cur );
00955       for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
00956          if (str_match_no_case( &cur, interpolate_names[i] )) {
00957             if (is_digit_alpha_underscore( cur ))
00958                continue;
00959             decl.Declaration.Interpolate = i;
00960 
00961             ctx->cur = cur;
00962             break;
00963          }
00964       }
00965       if (i == TGSI_INTERPOLATE_COUNT) {
00966          report_error( ctx, "Expected semantic or interpolate attribute" );
00967          return FALSE;
00968       }
00969    }
00970 
00971    advance = tgsi_build_full_declaration(
00972       &decl,
00973       ctx->tokens_cur,
00974       ctx->header,
00975       (uint) (ctx->tokens_end - ctx->tokens_cur) );
00976    if (advance == 0)
00977       return FALSE;
00978    ctx->tokens_cur += advance;
00979 
00980    return TRUE;
00981 }
00982 
00983 static boolean parse_immediate( struct translate_ctx *ctx )
00984 {
00985    struct tgsi_full_immediate imm;
00986    uint i;
00987    float values[4];
00988    uint advance;
00989 
00990    if (!eat_white( &ctx->cur )) {
00991       report_error( ctx, "Syntax error" );
00992       return FALSE;
00993    }
00994    if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
00995       report_error( ctx, "Expected `FLT32'" );
00996       return FALSE;
00997    }
00998    eat_opt_white( &ctx->cur );
00999    if (*ctx->cur != '{') {
01000       report_error( ctx, "Expected `{'" );
01001       return FALSE;
01002    }
01003    ctx->cur++;
01004    for (i = 0; i < 4; i++) {
01005       eat_opt_white( &ctx->cur );
01006       if (i > 0) {
01007          if (*ctx->cur != ',') {
01008             report_error( ctx, "Expected `,'" );
01009             return FALSE;
01010          }
01011          ctx->cur++;
01012          eat_opt_white( &ctx->cur );
01013       }
01014       if (!parse_float( &ctx->cur, &values[i] )) {
01015          report_error( ctx, "Expected literal floating point" );
01016          return FALSE;
01017       }
01018    }
01019    eat_opt_white( &ctx->cur );
01020    if (*ctx->cur != '}') {
01021       report_error( ctx, "Expected `}'" );
01022       return FALSE;
01023    }
01024    ctx->cur++;
01025 
01026    imm = tgsi_default_full_immediate();
01027    imm.Immediate.Size += 4;
01028    imm.Immediate.DataType = TGSI_IMM_FLOAT32;
01029    imm.u.Pointer = values;
01030 
01031    advance = tgsi_build_full_immediate(
01032       &imm,
01033       ctx->tokens_cur,
01034       ctx->header,
01035       (uint) (ctx->tokens_end - ctx->tokens_cur) );
01036    if (advance == 0)
01037       return FALSE;
01038    ctx->tokens_cur += advance;
01039 
01040    return TRUE;
01041 }
01042 
01043 static boolean translate( struct translate_ctx *ctx )
01044 {
01045    eat_opt_white( &ctx->cur );
01046    if (!parse_header( ctx ))
01047       return FALSE;
01048 
01049    while (*ctx->cur != '\0') {
01050       uint label_val = 0;
01051 
01052       if (!eat_white( &ctx->cur )) {
01053          report_error( ctx, "Syntax error" );
01054          return FALSE;
01055       }
01056 
01057       if (*ctx->cur == '\0')
01058          break;
01059 
01060       if (parse_label( ctx, &label_val )) {
01061          if (!parse_instruction( ctx, TRUE ))
01062             return FALSE;
01063       }
01064       else if (str_match_no_case( &ctx->cur, "DCL" )) {
01065          if (!parse_declaration( ctx ))
01066             return FALSE;
01067       }
01068       else if (str_match_no_case( &ctx->cur, "IMM" )) {
01069          if (!parse_immediate( ctx ))
01070             return FALSE;
01071       }
01072       else if (!parse_instruction( ctx, FALSE )) {
01073          return FALSE;
01074       }
01075    }
01076 
01077    return TRUE;
01078 }
01079 
01080 boolean
01081 tgsi_text_translate(
01082    const char *text,
01083    struct tgsi_token *tokens,
01084    uint num_tokens )
01085 {
01086    struct translate_ctx ctx;
01087 
01088    ctx.text = text;
01089    ctx.cur = text;
01090    ctx.tokens = tokens;
01091    ctx.tokens_cur = tokens;
01092    ctx.tokens_end = tokens + num_tokens;
01093 
01094    if (!translate( &ctx ))
01095       return FALSE;
01096 
01097    return tgsi_sanity_check( tokens );
01098 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4