tgsi_parse.c revision 2083a276eb270b748d1c2668eb9faa5aadc8e700
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
33unsigned
34tgsi_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
52void
53tgsi_parse_free(
54   struct tgsi_parse_context *ctx )
55{
56}
57
58boolean
59tgsi_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 */
72static INLINE void
73copy_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 */
82static void
83next_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
93void
94tgsi_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.Semantic ) {
117         next_token( ctx, &decl->Semantic );
118      }
119
120      if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) {
121         unsigned i, j;
122         decl->ImmediateData.u = (union tgsi_immediate_data*)
123                                 &ctx->Tokens[ctx->Position];
124         for (i = 0; i <= decl->Range.Last; ++i) {
125            for (j = 0; j < 4; ++j) {
126               ctx->Position++;
127            }
128         }
129      }
130
131      if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
132         next_token(ctx, &decl->Resource);
133      }
134
135      break;
136   }
137
138   case TGSI_TOKEN_TYPE_IMMEDIATE:
139   {
140      struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
141      uint imm_count;
142
143      memset(imm, 0, sizeof *imm);
144      copy_token(&imm->Immediate, &token);
145
146      imm_count = imm->Immediate.NrTokens - 1;
147
148      switch (imm->Immediate.DataType) {
149      case TGSI_IMM_FLOAT32:
150         for (i = 0; i < imm_count; i++) {
151            next_token(ctx, &imm->u[i].Float);
152         }
153         break;
154
155      case TGSI_IMM_UINT32:
156         for (i = 0; i < imm_count; i++) {
157            next_token(ctx, &imm->u[i].Uint);
158         }
159         break;
160
161      case TGSI_IMM_INT32:
162         for (i = 0; i < imm_count; i++) {
163            next_token(ctx, &imm->u[i].Int);
164         }
165         break;
166
167      default:
168         assert( 0 );
169      }
170
171      break;
172   }
173
174   case TGSI_TOKEN_TYPE_INSTRUCTION:
175   {
176      struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
177
178      memset(inst, 0, sizeof *inst);
179      copy_token(&inst->Instruction, &token);
180
181      if (inst->Instruction.Predicate) {
182         next_token(ctx, &inst->Predicate);
183      }
184
185      if (inst->Instruction.Label) {
186         next_token( ctx, &inst->Label);
187      }
188
189      if (inst->Instruction.Texture) {
190         next_token( ctx, &inst->Texture);
191         for( i = 0; i < inst->Texture.NumOffsets; i++ ) {
192            next_token( ctx, &inst->TexOffsets[i] );
193         }
194      }
195
196      assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
197
198      for(  i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
199
200         next_token( ctx, &inst->Dst[i].Register );
201
202         if( inst->Dst[i].Register.Indirect ) {
203            next_token( ctx, &inst->Dst[i].Indirect );
204
205            /*
206             * No support for indirect or multi-dimensional addressing.
207             */
208            assert( !inst->Dst[i].Indirect.Dimension );
209            assert( !inst->Dst[i].Indirect.Indirect );
210         }
211         if( inst->Dst[i].Register.Dimension ) {
212            next_token( ctx, &inst->Dst[i].Dimension );
213
214            /*
215             * No support for multi-dimensional addressing.
216             */
217            assert( !inst->Dst[i].Dimension.Dimension );
218
219            if( inst->Dst[i].Dimension.Indirect ) {
220               next_token( ctx, &inst->Dst[i].DimIndirect );
221
222               /*
223                * No support for indirect or multi-dimensional addressing.
224                */
225               assert( !inst->Dst[i].Indirect.Indirect );
226               assert( !inst->Dst[i].Indirect.Dimension );
227            }
228         }
229      }
230
231      assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
232
233      for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
234
235         next_token( ctx, &inst->Src[i].Register );
236
237         if( inst->Src[i].Register.Indirect ) {
238            next_token( ctx, &inst->Src[i].Indirect );
239
240            /*
241             * No support for indirect or multi-dimensional addressing.
242             */
243            assert( !inst->Src[i].Indirect.Indirect );
244            assert( !inst->Src[i].Indirect.Dimension );
245         }
246
247         if( inst->Src[i].Register.Dimension ) {
248            next_token( ctx, &inst->Src[i].Dimension );
249
250            /*
251             * No support for multi-dimensional addressing.
252             */
253            assert( !inst->Src[i].Dimension.Dimension );
254
255            if( inst->Src[i].Dimension.Indirect ) {
256               next_token( ctx, &inst->Src[i].DimIndirect );
257
258               /*
259               * No support for indirect or multi-dimensional addressing.
260               */
261               assert( !inst->Src[i].Indirect.Indirect );
262               assert( !inst->Src[i].Indirect.Dimension );
263            }
264         }
265      }
266
267      break;
268   }
269
270   case TGSI_TOKEN_TYPE_PROPERTY:
271   {
272      struct tgsi_full_property *prop = &ctx->FullToken.FullProperty;
273      uint prop_count;
274
275      memset(prop, 0, sizeof *prop);
276      copy_token(&prop->Property, &token);
277
278      prop_count = prop->Property.NrTokens - 1;
279      for (i = 0; i < prop_count; i++) {
280         next_token(ctx, &prop->u[i]);
281      }
282
283      break;
284   }
285
286   default:
287      assert( 0 );
288   }
289}
290
291
292
293
294/**
295 * Make a new copy of a token array.
296 */
297struct tgsi_token *
298tgsi_dup_tokens(const struct tgsi_token *tokens)
299{
300   unsigned n = tgsi_num_tokens(tokens);
301   unsigned bytes = n * sizeof(struct tgsi_token);
302   struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
303   if (new_tokens)
304      memcpy(new_tokens, tokens, bytes);
305   return new_tokens;
306}
307
308
309/**
310 * Allocate memory for num_tokens tokens.
311 */
312struct tgsi_token *
313tgsi_alloc_tokens(unsigned num_tokens)
314{
315   unsigned bytes = num_tokens * sizeof(struct tgsi_token);
316   return (struct tgsi_token *) MALLOC(bytes);
317}
318
319
320void
321tgsi_dump_tokens(const struct tgsi_token *tokens)
322{
323   const unsigned *dwords = (const unsigned *)tokens;
324   int nr = tgsi_num_tokens(tokens);
325   int i;
326
327   assert(sizeof(*tokens) == sizeof(unsigned));
328
329   debug_printf("const unsigned tokens[%d] = {\n", nr);
330   for (i = 0; i < nr; i++)
331      debug_printf("0x%08x,\n", dwords[i]);
332   debug_printf("};\n");
333}
334