msvcrt: Added _sscanf_l implementation.
[wine] / dlls / d3dx9_36 / asmshader.y
1 /*
2  * Direct3D shader assembler
3  *
4  * Copyright 2008 Stefan Dösinger
5  * Copyright 2009 Matteo Bruni
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 %{
23 #include "config.h"
24 #include "wine/port.h"
25 #include "wine/debug.h"
26
27 #include "d3dx9_36_private.h"
28
29 #include <stdio.h>
30
31 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
32
33 struct asm_parser asm_ctx;
34
35 /* Needed lexer functions declarations */
36 void asmshader_error(const char *s);
37 int asmshader_lex(void);
38
39 void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
40     reg->rel_reg = NULL;
41 }
42
43 %}
44
45 %union {
46     unsigned int        regnum;
47     struct shader_reg   reg;
48     struct {
49         DWORD           swizzle;
50         DWORD           writemask;
51     } swizzle_wmask;
52     DWORD               writemask;
53     DWORD               swizzle;
54     struct {
55         DWORD           mod;
56         DWORD           shift;
57     } modshift;
58     struct rel_reg      rel_reg;
59     struct src_regs     sregs;
60 }
61
62 /* Common instructions between vertex and pixel shaders */
63 %token INSTR_MOV
64
65 /* Registers */
66 %token <regnum> REG_TEMP
67 %token <regnum> REG_CONSTFLOAT
68
69 /* Version tokens */
70 %token VER_VS10
71 %token VER_VS11
72 %token VER_VS20
73 %token VER_VS2X
74 %token VER_VS30
75
76 %token VER_PS10
77 %token VER_PS11
78 %token VER_PS12
79 %token VER_PS13
80 %token VER_PS14
81 %token VER_PS20
82 %token VER_PS2X
83 %token VER_PS30
84
85
86 %type <reg> dreg_name
87 %type <reg> dreg
88 %type <reg> sreg_name
89 %type <reg> sreg
90 %type <swizzle> swizzle
91 %type <modshift> omods
92 %type <rel_reg> rel_reg
93 %type <sregs> sregs
94
95 %%
96
97 shader:               version_marker instructions
98                         {
99                             asm_ctx.funcs->end(&asm_ctx);
100                         }
101
102 version_marker:       VER_VS10
103                         {
104                             TRACE("Vertex shader 1.0\n");
105                             set_parse_status(&asm_ctx, PARSE_ERR);
106                             YYABORT;
107                         }
108                     | VER_VS11
109                         {
110                             TRACE("Vertex shader 1.1\n");
111                             set_parse_status(&asm_ctx, PARSE_ERR);
112                             YYABORT;
113                         }
114                     | VER_VS20
115                         {
116                             TRACE("Vertex shader 2.0\n");
117                             set_parse_status(&asm_ctx, PARSE_ERR);
118                             YYABORT;
119                         }
120                     | VER_VS2X
121                         {
122                             TRACE("Vertex shader 2.x\n");
123                             set_parse_status(&asm_ctx, PARSE_ERR);
124                             YYABORT;
125                         }
126                     | VER_VS30
127                         {
128                             TRACE("Vertex shader 3.0\n");
129                             create_vs30_parser(&asm_ctx);
130                         }
131                     | VER_PS10
132                         {
133                             TRACE("Pixel  shader 1.0\n");
134                             set_parse_status(&asm_ctx, PARSE_ERR);
135                             YYABORT;
136                         }
137                     | VER_PS11
138                         {
139                             TRACE("Pixel  shader 1.1\n");
140                             set_parse_status(&asm_ctx, PARSE_ERR);
141                             YYABORT;
142                         }
143                     | VER_PS12
144                         {
145                             TRACE("Pixel  shader 1.2\n");
146                             set_parse_status(&asm_ctx, PARSE_ERR);
147                             YYABORT;
148                         }
149                     | VER_PS13
150                         {
151                             TRACE("Pixel  shader 1.3\n");
152                             set_parse_status(&asm_ctx, PARSE_ERR);
153                             YYABORT;
154                         }
155                     | VER_PS14
156                         {
157                             TRACE("Pixel  shader 1.4\n");
158                             set_parse_status(&asm_ctx, PARSE_ERR);
159                             YYABORT;
160                         }
161                     | VER_PS20
162                         {
163                             TRACE("Pixel  shader 2.0\n");
164                             set_parse_status(&asm_ctx, PARSE_ERR);
165                             YYABORT;
166                         }
167                     | VER_PS2X
168                         {
169                             TRACE("Pixel  shader 2.x\n");
170                             set_parse_status(&asm_ctx, PARSE_ERR);
171                             YYABORT;
172                         }
173                     | VER_PS30
174                         {
175                             TRACE("Pixel  shader 3.0\n");
176                             set_parse_status(&asm_ctx, PARSE_ERR);
177                             YYABORT;
178                         }
179
180 instructions:         /* empty */
181                     | instructions complexinstr
182                             {
183                                 /* Nothing to do */
184                             }
185
186 complexinstr:         instruction
187                             {
188
189                             }
190
191 instruction:          INSTR_MOV omods dreg ',' sregs
192                             {
193                                 TRACE("MOV\n");
194                                 asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_MOV, $2.mod, $2.shift, 0, &$3, &$5, 1);
195                             }
196
197 dreg:                 dreg_name rel_reg
198                             {
199                                 $$.regnum = $1.regnum;
200                                 $$.type = $1.type;
201                                 $$.writemask = BWRITERSP_WRITEMASK_ALL;
202                                 $$.srcmod = BWRITERSPSM_NONE;
203                                 set_rel_reg(&$$, &$2);
204                             }
205
206 dreg_name:            REG_TEMP
207                         {
208                             $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
209                         }
210
211 swizzle:              /* empty */
212                         {
213                             $$ = BWRITERVS_NOSWIZZLE;
214                             TRACE("Default swizzle: %08x\n", $$);
215                         }
216
217 omods:                 /* Empty */
218                         {
219                             $$.mod = 0;
220                             $$.shift = 0;
221                         }
222
223 sregs:                sreg
224                         {
225                             $$.reg[0] = $1;
226                             $$.count = 1;
227                         }
228                     | sregs ',' sreg
229                         {
230                             if($$.count == MAX_SRC_REGS){
231                                 asmparser_message(&asm_ctx, "Line %u: Too many source registers in this instruction\n",
232                                                   asm_ctx.line_no);
233                                 set_parse_status(&asm_ctx, PARSE_ERR);
234                             }
235                             else
236                                 $$.reg[$$.count++] = $3;
237                         }
238
239 sreg:                   sreg_name rel_reg swizzle
240                         {
241                             $$.type = $1.type;
242                             $$.regnum = $1.regnum;
243                             $$.swizzle = $3;
244                             $$.srcmod = BWRITERSPSM_NONE;
245                             set_rel_reg(&$$, &$2);
246                         }
247
248 rel_reg:               /* empty */
249                         {
250                             $$.has_rel_reg = FALSE;
251                             $$.additional_offset = 0;
252                         }
253
254 sreg_name:            REG_TEMP
255                         {
256                             $$.regnum = $1; $$.type = BWRITERSPR_TEMP;
257                         }
258                     | REG_CONSTFLOAT
259                         {
260                             $$.regnum = $1; $$.type = BWRITERSPR_CONST;
261                         }
262
263 %%
264
265 void asmshader_error (char const *s) {
266     asmparser_message(&asm_ctx, "Line %u: Error \"%s\" from bison\n", asm_ctx.line_no, s);
267     set_parse_status(&asm_ctx, PARSE_ERR);
268 }
269
270 /* Error reporting function */
271 void asmparser_message(struct asm_parser *ctx, const char *fmt, ...) {
272     va_list args;
273     char* newbuffer;
274     int rc, newsize;
275
276     if(ctx->messagecapacity == 0) {
277         ctx->messages = asm_alloc(MESSAGEBUFFER_INITIAL_SIZE);
278         if(ctx->messages == NULL) {
279             ERR("Error allocating memory for parser messages\n");
280             return;
281         }
282         ctx->messagecapacity = MESSAGEBUFFER_INITIAL_SIZE;
283     }
284
285     while(1) {
286         va_start(args, fmt);
287         rc = vsnprintf(ctx->messages + ctx->messagesize,
288                        ctx->messagecapacity - ctx->messagesize, fmt, args);
289         va_end(args);
290
291         if (rc < 0 ||                                           /* C89 */
292             rc >= ctx->messagecapacity - ctx->messagesize) {    /* C99 */
293             /* Resize the buffer */
294             newsize = ctx->messagecapacity * 2;
295             newbuffer = asm_realloc(ctx->messages, newsize);
296             if(newbuffer == NULL){
297                 ERR("Error reallocating memory for parser messages\n");
298                 return;
299             }
300             ctx->messages = newbuffer;
301             ctx->messagecapacity = newsize;
302         } else {
303             ctx->messagesize += rc;
304             return;
305         }
306     }
307 }
308
309 /* New status is the worst between current status and parameter value */
310 void set_parse_status(struct asm_parser *ctx, enum parse_status status) {
311     if(status == PARSE_ERR) ctx->status = PARSE_ERR;
312     else if(status == PARSE_WARN && ctx->status == PARSE_SUCCESS) ctx->status = PARSE_WARN;
313 }
314
315 struct bwriter_shader *parse_asm_shader(char **messages) {
316     struct bwriter_shader *ret = NULL;
317
318     asm_ctx.shader = NULL;
319     asm_ctx.status = PARSE_SUCCESS;
320     asm_ctx.messagesize = asm_ctx.messagecapacity = 0;
321     asm_ctx.line_no = 1;
322
323     asmshader_parse();
324
325     if(asm_ctx.status != PARSE_ERR) ret = asm_ctx.shader;
326     else if(asm_ctx.shader) SlDeleteShader(asm_ctx.shader);
327
328     if(messages) {
329         if(asm_ctx.messagesize) {
330             /* Shrink the buffer to the used size */
331             *messages = asm_realloc(asm_ctx.messages, asm_ctx.messagesize + 1);
332             if(!*messages) {
333                 ERR("Out of memory, no messages reported\n");
334                 asm_free(asm_ctx.messages);
335             }
336         } else {
337             *messages = NULL;
338         }
339     } else {
340         if(asm_ctx.messagecapacity) asm_free(asm_ctx.messages);
341     }
342
343     return ret;
344 }