Home | History | Annotate | Download | only in tgsi
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
      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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 #include "util/u_debug.h"
     29 #include "pipe/p_shader_tokens.h"
     30 #include "tgsi_parse.h"
     31 #include "util/u_memory.h"
     32 
     33 unsigned
     34 tgsi_parse_init(
     35    struct tgsi_parse_context *ctx,
     36    const struct tgsi_token *tokens )
     37 {
     38    ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0];
     39    if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
     40       ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1];
     41    }
     42    else {
     43       return TGSI_PARSE_ERROR;
     44    }
     45 
     46    ctx->Tokens = tokens;
     47    ctx->Position = ctx->FullHeader.Header.HeaderSize;
     48 
     49    return TGSI_PARSE_OK;
     50 }
     51 
     52 void
     53 tgsi_parse_free(
     54    struct tgsi_parse_context *ctx )
     55 {
     56 }
     57 
     58 boolean
     59 tgsi_parse_end_of_tokens(
     60    struct tgsi_parse_context *ctx )
     61 {
     62    return ctx->Position >=
     63       ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
     64 }
     65 
     66 
     67 /**
     68  * This function is used to avoid and work-around type punning/aliasing
     69  * warnings.  The warnings seem harmless on x86 but on PPC they cause
     70  * real failures.
     71  */
     72 static INLINE void
     73 copy_token(void *dst, const void *src)
     74 {
     75    memcpy(dst, src, 4);
     76 }
     77 
     78 
     79 /**
     80  * Get next 4-byte token, return it at address specified by 'token'
     81  */
     82 static void
     83 next_token(
     84    struct tgsi_parse_context *ctx,
     85    void *token )
     86 {
     87    assert( !tgsi_parse_end_of_tokens( ctx ) );
     88    copy_token(token, &ctx->Tokens[ctx->Position]);
     89    ctx->Position++;
     90 }
     91 
     92 
     93 void
     94 tgsi_parse_token(
     95    struct tgsi_parse_context *ctx )
     96 {
     97    struct tgsi_token token;
     98    unsigned i;
     99 
    100    next_token( ctx, &token );
    101 
    102    switch( token.Type ) {
    103    case TGSI_TOKEN_TYPE_DECLARATION:
    104    {
    105       struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
    106 
    107       memset(decl, 0, sizeof *decl);
    108       copy_token(&decl->Declaration, &token);
    109 
    110       next_token( ctx, &decl->Range );
    111 
    112       if (decl->Declaration.Dimension) {
    113          next_token(ctx, &decl->Dim);
    114       }
    115 
    116       if( decl->Declaration.Interpolate ) {
    117          next_token( ctx, &decl->Interp );
    118       }
    119 
    120       if( decl->Declaration.Semantic ) {
    121          next_token( ctx, &decl->Semantic );
    122       }
    123 
    124       if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) {
    125          unsigned i, j;
    126          decl->ImmediateData.u = (union tgsi_immediate_data*)
    127                                  &ctx->Tokens[ctx->Position];
    128          for (i = 0; i <= decl->Range.Last; ++i) {
    129             for (j = 0; j < 4; ++j) {
    130                ctx->Position++;
    131             }
    132          }
    133       }
    134 
    135       if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
    136          next_token(ctx, &decl->Resource);
    137       }
    138 
    139       if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
    140          next_token(ctx, &decl->SamplerView);
    141       }
    142 
    143       break;
    144    }
    145 
    146    case TGSI_TOKEN_TYPE_IMMEDIATE:
    147    {
    148       struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
    149       uint imm_count;
    150 
    151       memset(imm, 0, sizeof *imm);
    152       copy_token(&imm->Immediate, &token);
    153 
    154       imm_count = imm->Immediate.NrTokens - 1;
    155 
    156       switch (imm->Immediate.DataType) {
    157       case TGSI_IMM_FLOAT32:
    158          for (i = 0; i < imm_count; i++) {
    159             next_token(ctx, &imm->u[i].Float);
    160          }
    161          break;
    162 
    163       case TGSI_IMM_UINT32:
    164          for (i = 0; i < imm_count; i++) {
    165             next_token(ctx, &imm->u[i].Uint);
    166          }
    167          break;
    168 
    169       case TGSI_IMM_INT32:
    170          for (i = 0; i < imm_count; i++) {
    171             next_token(ctx, &imm->u[i].Int);
    172          }
    173          break;
    174 
    175       default:
    176          assert( 0 );
    177       }
    178 
    179       break;
    180    }
    181 
    182    case TGSI_TOKEN_TYPE_INSTRUCTION:
    183    {
    184       struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
    185 
    186       memset(inst, 0, sizeof *inst);
    187       copy_token(&inst->Instruction, &token);
    188 
    189       if (inst->Instruction.Predicate) {
    190          next_token(ctx, &inst->Predicate);
    191       }
    192 
    193       if (inst->Instruction.Label) {
    194          next_token( ctx, &inst->Label);
    195       }
    196 
    197       if (inst->Instruction.Texture) {
    198          next_token( ctx, &inst->Texture);
    199          for( i = 0; i < inst->Texture.NumOffsets; i++ ) {
    200             next_token( ctx, &inst->TexOffsets[i] );
    201          }
    202       }
    203 
    204       assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
    205 
    206       for(  i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
    207 
    208          next_token( ctx, &inst->Dst[i].Register );
    209 
    210          if( inst->Dst[i].Register.Indirect ) {
    211             next_token( ctx, &inst->Dst[i].Indirect );
    212 
    213             /*
    214              * No support for indirect or multi-dimensional addressing.
    215              */
    216             assert( !inst->Dst[i].Indirect.Dimension );
    217             assert( !inst->Dst[i].Indirect.Indirect );
    218          }
    219          if( inst->Dst[i].Register.Dimension ) {
    220             next_token( ctx, &inst->Dst[i].Dimension );
    221 
    222             /*
    223              * No support for multi-dimensional addressing.
    224              */
    225             assert( !inst->Dst[i].Dimension.Dimension );
    226 
    227             if( inst->Dst[i].Dimension.Indirect ) {
    228                next_token( ctx, &inst->Dst[i].DimIndirect );
    229 
    230                /*
    231                 * No support for indirect or multi-dimensional addressing.
    232                 */
    233                assert( !inst->Dst[i].Indirect.Indirect );
    234                assert( !inst->Dst[i].Indirect.Dimension );
    235             }
    236          }
    237       }
    238 
    239       assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
    240 
    241       for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
    242 
    243          next_token( ctx, &inst->Src[i].Register );
    244 
    245          if( inst->Src[i].Register.Indirect ) {
    246             next_token( ctx, &inst->Src[i].Indirect );
    247 
    248             /*
    249              * No support for indirect or multi-dimensional addressing.
    250              */
    251             assert( !inst->Src[i].Indirect.Indirect );
    252             assert( !inst->Src[i].Indirect.Dimension );
    253          }
    254 
    255          if( inst->Src[i].Register.Dimension ) {
    256             next_token( ctx, &inst->Src[i].Dimension );
    257 
    258             /*
    259              * No support for multi-dimensional addressing.
    260              */
    261             assert( !inst->Src[i].Dimension.Dimension );
    262 
    263             if( inst->Src[i].Dimension.Indirect ) {
    264                next_token( ctx, &inst->Src[i].DimIndirect );
    265 
    266                /*
    267                * No support for indirect or multi-dimensional addressing.
    268                */
    269                assert( !inst->Src[i].Indirect.Indirect );
    270                assert( !inst->Src[i].Indirect.Dimension );
    271             }
    272          }
    273       }
    274 
    275       break;
    276    }
    277 
    278    case TGSI_TOKEN_TYPE_PROPERTY:
    279    {
    280       struct tgsi_full_property *prop = &ctx->FullToken.FullProperty;
    281       uint prop_count;
    282 
    283       memset(prop, 0, sizeof *prop);
    284       copy_token(&prop->Property, &token);
    285 
    286       prop_count = prop->Property.NrTokens - 1;
    287       for (i = 0; i < prop_count; i++) {
    288          next_token(ctx, &prop->u[i]);
    289       }
    290 
    291       break;
    292    }
    293 
    294    default:
    295       assert( 0 );
    296    }
    297 }
    298 
    299 
    300 
    301 
    302 /**
    303  * Make a new copy of a token array.
    304  */
    305 struct tgsi_token *
    306 tgsi_dup_tokens(const struct tgsi_token *tokens)
    307 {
    308    unsigned n = tgsi_num_tokens(tokens);
    309    unsigned bytes = n * sizeof(struct tgsi_token);
    310    struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
    311    if (new_tokens)
    312       memcpy(new_tokens, tokens, bytes);
    313    return new_tokens;
    314 }
    315 
    316 
    317 /**
    318  * Allocate memory for num_tokens tokens.
    319  */
    320 struct tgsi_token *
    321 tgsi_alloc_tokens(unsigned num_tokens)
    322 {
    323    unsigned bytes = num_tokens * sizeof(struct tgsi_token);
    324    return (struct tgsi_token *) MALLOC(bytes);
    325 }
    326 
    327 
    328 void
    329 tgsi_dump_tokens(const struct tgsi_token *tokens)
    330 {
    331    const unsigned *dwords = (const unsigned *)tokens;
    332    int nr = tgsi_num_tokens(tokens);
    333    int i;
    334 
    335    assert(sizeof(*tokens) == sizeof(unsigned));
    336 
    337    debug_printf("const unsigned tokens[%d] = {\n", nr);
    338    for (i = 0; i < nr; i++)
    339       debug_printf("0x%08x,\n", dwords[i]);
    340    debug_printf("};\n");
    341 }
    342