Home | History | Annotate | Download | only in tgsi
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 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 "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_IMAGE) {
    125          next_token(ctx, &decl->Image);
    126       }
    127 
    128       if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
    129          next_token(ctx, &decl->SamplerView);
    130       }
    131 
    132       if (decl->Declaration.Array) {
    133          next_token(ctx, &decl->Array);
    134       }
    135 
    136       break;
    137    }
    138 
    139    case TGSI_TOKEN_TYPE_IMMEDIATE:
    140    {
    141       struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
    142       uint imm_count;
    143 
    144       memset(imm, 0, sizeof *imm);
    145       copy_token(&imm->Immediate, &token);
    146 
    147       imm_count = imm->Immediate.NrTokens - 1;
    148 
    149       switch (imm->Immediate.DataType) {
    150       case TGSI_IMM_FLOAT32:
    151       case TGSI_IMM_FLOAT64:
    152          for (i = 0; i < imm_count; i++) {
    153             next_token(ctx, &imm->u[i].Float);
    154          }
    155          break;
    156 
    157       case TGSI_IMM_UINT32:
    158       case TGSI_IMM_UINT64:
    159          for (i = 0; i < imm_count; i++) {
    160             next_token(ctx, &imm->u[i].Uint);
    161          }
    162          break;
    163 
    164       case TGSI_IMM_INT32:
    165       case TGSI_IMM_INT64:
    166          for (i = 0; i < imm_count; i++) {
    167             next_token(ctx, &imm->u[i].Int);
    168          }
    169          break;
    170 
    171       default:
    172          assert( 0 );
    173       }
    174 
    175       break;
    176    }
    177 
    178    case TGSI_TOKEN_TYPE_INSTRUCTION:
    179    {
    180       struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
    181 
    182       memset(inst, 0, sizeof *inst);
    183       copy_token(&inst->Instruction, &token);
    184 
    185       if (inst->Instruction.Predicate) {
    186          next_token(ctx, &inst->Predicate);
    187       }
    188 
    189       if (inst->Instruction.Label) {
    190          next_token( ctx, &inst->Label);
    191       }
    192 
    193       if (inst->Instruction.Texture) {
    194          next_token( ctx, &inst->Texture);
    195          for (i = 0; i < inst->Texture.NumOffsets; i++) {
    196             next_token( ctx, &inst->TexOffsets[i] );
    197          }
    198       }
    199 
    200       if (inst->Instruction.Memory) {
    201          next_token(ctx, &inst->Memory);
    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          if (inst->Dst[i].Register.Dimension) {
    214             next_token( ctx, &inst->Dst[i].Dimension );
    215 
    216             /*
    217              * No support for multi-dimensional addressing.
    218              */
    219             assert( !inst->Dst[i].Dimension.Dimension );
    220 
    221             if (inst->Dst[i].Dimension.Indirect)
    222                next_token( ctx, &inst->Dst[i].DimIndirect );
    223          }
    224       }
    225 
    226       assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
    227 
    228       for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
    229 
    230          next_token( ctx, &inst->Src[i].Register );
    231 
    232          if (inst->Src[i].Register.Indirect)
    233             next_token( ctx, &inst->Src[i].Indirect );
    234 
    235          if (inst->Src[i].Register.Dimension) {
    236             next_token( ctx, &inst->Src[i].Dimension );
    237 
    238             /*
    239              * No support for multi-dimensional addressing.
    240              */
    241             assert( !inst->Src[i].Dimension.Dimension );
    242 
    243             if (inst->Src[i].Dimension.Indirect)
    244                next_token( ctx, &inst->Src[i].DimIndirect );
    245          }
    246       }
    247 
    248       break;
    249    }
    250 
    251    case TGSI_TOKEN_TYPE_PROPERTY:
    252    {
    253       struct tgsi_full_property *prop = &ctx->FullToken.FullProperty;
    254       uint prop_count;
    255 
    256       memset(prop, 0, sizeof *prop);
    257       copy_token(&prop->Property, &token);
    258 
    259       prop_count = prop->Property.NrTokens - 1;
    260       for (i = 0; i < prop_count; i++) {
    261          next_token(ctx, &prop->u[i]);
    262       }
    263 
    264       break;
    265    }
    266 
    267    default:
    268       assert( 0 );
    269    }
    270 }
    271 
    272 
    273 
    274 
    275 /**
    276  * Make a new copy of a token array.
    277  */
    278 struct tgsi_token *
    279 tgsi_dup_tokens(const struct tgsi_token *tokens)
    280 {
    281    unsigned n = tgsi_num_tokens(tokens);
    282    unsigned bytes = n * sizeof(struct tgsi_token);
    283    struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
    284    if (new_tokens)
    285       memcpy(new_tokens, tokens, bytes);
    286    return new_tokens;
    287 }
    288 
    289 
    290 /**
    291  * Allocate memory for num_tokens tokens.
    292  */
    293 struct tgsi_token *
    294 tgsi_alloc_tokens(unsigned num_tokens)
    295 {
    296    unsigned bytes = num_tokens * sizeof(struct tgsi_token);
    297    return (struct tgsi_token *) MALLOC(bytes);
    298 }
    299 
    300 
    301 /**
    302  * Free tokens allocated by tgsi_alloc_tokens() or tgsi_dup_tokens()
    303  */
    304 void
    305 tgsi_free_tokens(const struct tgsi_token *tokens)
    306 {
    307    FREE((void *) tokens);
    308 }
    309 
    310 
    311 void
    312 tgsi_dump_tokens(const struct tgsi_token *tokens)
    313 {
    314    const unsigned *dwords = (const unsigned *)tokens;
    315    int nr = tgsi_num_tokens(tokens);
    316    int i;
    317 
    318    STATIC_ASSERT(sizeof(*tokens) == sizeof(unsigned));
    319 
    320    debug_printf("const unsigned tokens[%d] = {\n", nr);
    321    for (i = 0; i < nr; i++)
    322       debug_printf("0x%08x,\n", dwords[i]);
    323    debug_printf("};\n");
    324 }
    325 
    326 unsigned
    327 tgsi_get_processor_type(const struct tgsi_token *tokens)
    328 {
    329    struct tgsi_parse_context parse;
    330 
    331    if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
    332       debug_printf("tgsi_parse_init() failed in %s:%i!\n", __func__, __LINE__);
    333       return ~0;
    334    }
    335    return parse.FullHeader.Processor.Processor;
    336 }
    337