asmshader.l 20.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * Direct3D shader assembler
 *
 * Copyright 2008 Stefan Dösinger
 * Copyright 2009 Matteo Bruni
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

%{
#include "wine/debug.h"

25
#include "d3dcompiler_private.h"
26 27 28 29 30 31 32
#include "asmshader.tab.h"

WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
%}

%option noyywrap
%option prefix="asmshader_"
33
%option noinput nounput never-interactive
34

35 36 37 38 39 40 41
/* Swizzles and writemasks consist of a dot and up to 4 x, y, z or w characters,
 * or up to 4 a, r, g, b characters. There are different rules for swizzles and
 * writemasks wrt repetition, those are handled in the grammar.
 */
DOT                     \.
COMPONENT               [xyzw]|[rgba]

42 43 44
/* Registers */
REG_TEMP                r[0-9]+
/* for relative addressing in the form o[x], v[x] and c[x] */
45 46
REG_OUTPUT              o[0-9]*
REG_INPUT               v[0-9]*
47
REG_CONSTFLOAT          c[0-9]*
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
REG_CONSTINT            i[0-9]+
REG_CONSTBOOL           b[0-9]+
REG_TEXTURE             t[0-9]+
REG_TEXCRDOUT           oT[0-9]+
REG_SAMPLER             s[0-9]+
REG_OPOS                oPos
REG_OFOG                oFog
REG_OPTS                oPts
REG_VERTEXCOLOR         oD[01]
REG_FRAGCOLOR           oC[0-9]+
REG_FRAGDEPTH           oDepth
REG_VPOS                vPos
REG_VFACE               vFace
REG_ADDRESS             a0
REG_LOOP                aL
REG_PREDICATE           p0
/* Not really a register, but it is considered as such */
REG_LABEL               l[0-9]+
66

67
DCL_POSITION            _position[0-9]*
68 69 70 71 72 73 74 75 76 77 78 79 80
DCL_BLENDWEIGHT         _blendweight[0-9]*
DCL_BLENDINDICES        _blendindices[0-9]*
DCL_NORMAL              _normal[0-9]*
DCL_PSIZE               _psize[0-9]*
DCL_TEXCOORD            _texcoord[0-9]*
DCL_TANGENT             _tangent[0-9]*
DCL_BINORMAL            _binormal[0-9]*
DCL_TESSFACTOR          _tessfactor[0-9]*
DCL_POSITIONT           _positiont[0-9]*
DCL_COLOR               _color[0-9]*
DCL_FOG                 _fog[0-9]*
DCL_DEPTH               _depth[0-9]*
DCL_SAMPLE              _sample[0-9]*
81

82 83 84 85 86
DCL_SAMPLER1D           _1d
DCL_SAMPLER2D           _2d
DCL_SAMPLERCUBE         _cube
DCL_SAMPLERVOLUME       _volume

87 88 89 90 91 92 93 94 95 96 97 98
PREPROCESSORDIRECTIVE   #[^\n]*\n

/* Comments */
DOUBLESLASHCOMMENT      "//"[^\n]*
SEMICOLONCOMMENT        ";"[^\n]*

/* Whitespaces are spaces, tabs and newlines */
WHITESPACE              [ \t]+
NEWLINE                 (\n)|(\r\n)

COMMA                   ","

99
IMMVAL                  (([0-9]+\.?)|([0-9]*\.[0-9]+))(f)?
100 101 102 103 104 105

ANY                     (.)

%%

    /* Common instructions(vertex and pixel shaders) */
106 107
add                     {return INSTR_ADD;          }
nop                     {return INSTR_NOP;          }
108
mov                     {return INSTR_MOV;          }
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
sub                     {return INSTR_SUB;          }
mad                     {return INSTR_MAD;          }
mul                     {return INSTR_MUL;          }
rcp                     {return INSTR_RCP;          }
rsq                     {return INSTR_RSQ;          }
dp3                     {return INSTR_DP3;          }
dp4                     {return INSTR_DP4;          }
min                     {return INSTR_MIN;          }
max                     {return INSTR_MAX;          }
slt                     {return INSTR_SLT;          }
sge                     {return INSTR_SGE;          }
abs                     {return INSTR_ABS;          }
exp                     {return INSTR_EXP;          }
log                     {return INSTR_LOG;          }
expp                    {return INSTR_EXPP;         }
logp                    {return INSTR_LOGP;         }
dst                     {return INSTR_DST;          }
lrp                     {return INSTR_LRP;          }
frc                     {return INSTR_FRC;          }
pow                     {return INSTR_POW;          }
crs                     {return INSTR_CRS;          }
sgn                     {return INSTR_SGN;          }
nrm                     {return INSTR_NRM;          }
sincos                  {return INSTR_SINCOS;       }
m4x4                    {return INSTR_M4x4;         }
m4x3                    {return INSTR_M4x3;         }
m3x4                    {return INSTR_M3x4;         }
m3x3                    {return INSTR_M3x3;         }
m3x2                    {return INSTR_M3x2;         }
138
dcl                     {return INSTR_DCL;          }
139
def                     {return INSTR_DEF;          }
140
defb                    {return INSTR_DEFB;         }
141
defi                    {return INSTR_DEFI;         }
142 143 144 145 146 147
rep                     {return INSTR_REP;          }
endrep                  {return INSTR_ENDREP;       }
if                      {return INSTR_IF;           }
else                    {return INSTR_ELSE;         }
endif                   {return INSTR_ENDIF;        }
break                   {return INSTR_BREAK;        }
148
breakp                  {return INSTR_BREAKP;       }
149 150 151 152 153 154
call                    {return INSTR_CALL;         }
callnz                  {return INSTR_CALLNZ;       }
loop                    {return INSTR_LOOP;         }
ret                     {return INSTR_RET;          }
endloop                 {return INSTR_ENDLOOP;      }
label                   {return INSTR_LABEL;        }
155
setp                    {return INSTR_SETP;         }
156 157 158 159 160 161
texldl                  {return INSTR_TEXLDL;       }

    /* Vertex shader only instructions  */
lit                     {return INSTR_LIT;          }
mova                    {return INSTR_MOVA;         }

162
    /* Pixel shader only instructions   */
163
cnd                     {return INSTR_CND;          }
164 165
cmp                     {return INSTR_CMP;          }
dp2add                  {return INSTR_DP2ADD;       }
166
texcoord                {return INSTR_TEXCOORD;     }
167
texcrd                  {return INSTR_TEXCRD;       }
168
texkill                 {return INSTR_TEXKILL;      }
169
tex                     {return INSTR_TEX;          }
170
texld                   {return INSTR_TEXLD;        }
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
texbem                  {return INSTR_TEXBEM;       }
texbeml                 {return INSTR_TEXBEML;      }
texreg2ar               {return INSTR_TEXREG2AR;    }
texreg2gb               {return INSTR_TEXREG2GB;    }
texreg2rgb              {return INSTR_TEXREG2RGB;   }
texm3x2pad              {return INSTR_TEXM3x2PAD;   }
texm3x2tex              {return INSTR_TEXM3x2TEX;   }
texm3x3pad              {return INSTR_TEXM3x3PAD;   }
texm3x3spec             {return INSTR_TEXM3x3SPEC;  }
texm3x3vspec            {return INSTR_TEXM3x3VSPEC; }
texm3x3tex              {return INSTR_TEXM3x3TEX;   }
texdp3tex               {return INSTR_TEXDP3TEX;    }
texm3x2depth            {return INSTR_TEXM3x2DEPTH; }
texdp3                  {return INSTR_TEXDP3;       }
texm3x3                 {return INSTR_TEXM3x3;      }
186 187
texdepth                {return INSTR_TEXDEPTH;     }
bem                     {return INSTR_BEM;          }
188 189 190 191 192
dsx                     {return INSTR_DSX;          }
dsy                     {return INSTR_DSY;          }
texldp                  {return INSTR_TEXLDP;       }
texldb                  {return INSTR_TEXLDB;       }
texldd                  {return INSTR_TEXLDD;       }
193
phase                   {return INSTR_PHASE;        }
194 195 196 197 198

{REG_TEMP}              {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_TEMP;
                        }
199 200 201 202 203 204 205 206
{REG_OUTPUT}            {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_OUTPUT;
                        }
{REG_INPUT}             {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_INPUT;
                        }
207 208 209 210
{REG_CONSTFLOAT}        {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_CONSTFLOAT;
                        }
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
{REG_CONSTINT}          {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_CONSTINT;
                        }
{REG_CONSTBOOL}         {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_CONSTBOOL;
                        }
{REG_TEXTURE}           {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_TEXTURE;
                        }
{REG_TEXCRDOUT}         {
                            asmshader_lval.regnum = atoi(yytext + 2);
                            return REG_TEXCRDOUT;
                        }
{REG_SAMPLER}           {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_SAMPLER;
                        }
{REG_OPOS}              {return REG_OPOS;           }
{REG_OFOG}              {return REG_OFOG;           }
{REG_OPTS}              {return REG_OPTS;           }
{REG_VERTEXCOLOR}       {
                            asmshader_lval.regnum = atoi(yytext + 2);
                            return REG_VERTEXCOLOR;
                        }
{REG_FRAGCOLOR}         {
                            asmshader_lval.regnum = atoi(yytext + 2);
                            return REG_FRAGCOLOR;
                        }
{REG_FRAGDEPTH}         {return REG_FRAGDEPTH;      }
{REG_VPOS}              {return REG_VPOS;           }
{REG_VFACE}             {return REG_VFACE;          }
{REG_ADDRESS}           {return REG_ADDRESS;        }
{REG_LOOP}              {return REG_LOOP;           }
{REG_PREDICATE}         {return REG_PREDICATE;      }

{REG_LABEL}             {
                            asmshader_lval.regnum = atoi(yytext + 1);
                            return REG_LABEL;
                        }
253 254 255 256 257 258 259

    /* Shader versions. These are important to select the correct
     * parser profile.
     */
vs\.1\.0|vs_1_0         {return VER_VS10;       }
vs\.1\.1|vs_1_1         {return VER_VS11;       }

260 261 262
vs\.2\.0|vs_2_0         {return VER_VS20;       }
vs\.2\.x|vs_2_x         {return VER_VS2X;       }
vs\.3\.0|vs_3_0         {return VER_VS30;       }
263 264 265 266 267 268 269

ps\.1\.0|ps_1_0         {return VER_PS10;       }
ps\.1\.1|ps_1_1         {return VER_PS11;       }
ps\.1\.2|ps_1_2         {return VER_PS12;       }
ps\.1\.3|ps_1_3         {return VER_PS13;       }
ps\.1\.4|ps_1_4         {return VER_PS14;       }

270 271 272
ps\.2\.0|ps_2_0         {return VER_PS20;       }
ps\.2\.x|ps_2_x         {return VER_PS2X;       }
ps\.3\.0|ps_3_0         {return VER_PS30;       }
273

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
{DOT}                   {return yytext[0];      }
{COMPONENT}             {
                            switch(yytext[0]) {
                                case 'x':
                                case 'r':
                                    asmshader_lval.component = 0;
                                    break;
                                case 'y':
                                case 'g':
                                    asmshader_lval.component = 1;
                                    break;
                                case 'z':
                                case 'b':
                                    asmshader_lval.component = 2;
                                    break;
                                case 'w':
                                case 'a':
                                    asmshader_lval.component = 3;
                                    break;
                            }
                            return COMPONENT;
                        }

297
    /* Output modifiers */
298
\_x2                    {return SHIFT_X2;           }
299 300 301 302 303
\_x4                    {return SHIFT_X4;           }
\_x8                    {return SHIFT_X8;           }
\_d2                    {return SHIFT_D2;           }
\_d4                    {return SHIFT_D4;           }
\_d8                    {return SHIFT_D8;           }
304 305 306 307
\_sat                   {return MOD_SAT;            }
\_pp                    {return MOD_PP;             }
\_centroid              {return MOD_CENTROID;       }

308 309 310 311 312 313 314 315
    /* compare params */
\_gt                    {return COMP_GT;            }
\_lt                    {return COMP_LT;            }
\_ge                    {return COMP_GE;            }
\_le                    {return COMP_LE;            }
\_eq                    {return COMP_EQ;            }
\_ne                    {return COMP_NE;            }

316 317 318 319 320
{IMMVAL}                {
                            asmshader_lval.immval.val = atof(yytext);
                            asmshader_lval.immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL));
                            return IMMVAL;
                        }
321 322 323 324 325 326 327 328
true                    {
                            asmshader_lval.immbool = TRUE;
                            return IMMBOOL;
                        }
false                   {
                            asmshader_lval.immbool = FALSE;
                            return IMMBOOL;
                        }
329

330 331 332 333 334
{COMMA}                 {return yytext[0];          }
-                       {return yytext[0];          }
\(                      {return yytext[0];          }
\)                      {return yytext[0];          }

335 336 337
    /* for relative addressing */
\[|\]|\+                {return yytext[0];          }

338 339 340 341 342
\_bias                  {return SMOD_BIAS;          }
    /* No _x2 here; it is identical to MOD_X2 */
\_bx2                   {return SMOD_SCALEBIAS;     }
\_dz                    {return SMOD_DZ;            }
\_dw                    {return SMOD_DW;            }
343 344
\_abs                   {return SMOD_ABS;           }

345 346
!                       {return SMOD_NOT;           }

347 348 349 350 351 352 353 354
{DCL_POSITION}          {
                            if(yytext[strlen("_position")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_position"));
                            }
                            return USAGE_POSITION;
                        }
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
{DCL_BLENDWEIGHT}       {
                            if(yytext[strlen("_blendweight")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_blendweight"));
                            }
                            return USAGE_BLENDWEIGHT;
                        }
{DCL_BLENDINDICES}      {
                            if(yytext[strlen("_blendindices")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_blendindices"));
                            }
                            return USAGE_BLENDINDICES;
                        }
{DCL_NORMAL}            {
                            if(yytext[strlen("_normal")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_normal"));
                            }
                            return USAGE_NORMAL;
                        }
{DCL_PSIZE}             {
                            if(yytext[strlen("_psize")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_psize"));
                            }
                            return USAGE_PSIZE;
                        }
{DCL_TEXCOORD}          {
                            if(yytext[strlen("_texcoord")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_texcoord"));
                            }
                            return USAGE_TEXCOORD;
                        }
{DCL_TANGENT}           {
                            if(yytext[strlen("_tangent")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_tangent"));
                            }
                            return USAGE_TANGENT;
                        }
{DCL_BINORMAL}          {
                            if(yytext[strlen("_binormal")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_binormal"));
                            }
                            return USAGE_BINORMAL;
                        }
{DCL_TESSFACTOR}        {
                            if(yytext[strlen("_tessfactor")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_tessfactor"));
                            }
                            return USAGE_TESSFACTOR;
                        }
{DCL_POSITIONT}         {
                            if(yytext[strlen("_positiont")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_positiont"));
                            }
                            return USAGE_POSITIONT;
                        }
{DCL_COLOR}             {
                            if(yytext[strlen("_color")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_color"));
                            }
                            return USAGE_COLOR;
                        }
{DCL_FOG}               {
                            if(yytext[strlen("_fog")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_fog"));
                            }
                            return USAGE_FOG;
                        }
{DCL_DEPTH}             {
                            if(yytext[strlen("_depth")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_depth"));
                            }
                            return USAGE_DEPTH;
                        }
{DCL_SAMPLE}            {
                            if(yytext[strlen("_sample")] == '\0') {
                                asmshader_lval.regnum = 0;
                            } else {
                                asmshader_lval.regnum = atoi(yytext + strlen("_sample"));
                            }
                            return USAGE_SAMPLE;
                        }
459

460 461 462 463 464
{DCL_SAMPLER1D}         { return SAMPTYPE_1D;       }
{DCL_SAMPLER2D}         { return SAMPTYPE_2D;       }
{DCL_SAMPLERCUBE}       { return SAMPTYPE_CUBE;     }
{DCL_SAMPLERVOLUME}     { return SAMPTYPE_VOLUME;   }

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
{PREPROCESSORDIRECTIVE} {
                            /* TODO: update current line information */
                            TRACE("line info update: %s", yytext);
                        }

    /* Skip comments */
{DOUBLESLASHCOMMENT}    {                           }
{SEMICOLONCOMMENT}      {                           }

{WHITESPACE}            { /* Do nothing */          }
{NEWLINE}               {
                            asm_ctx.line_no++;
                        }

{ANY}                   {
                            asmparser_message(&asm_ctx, "Line %u: Unexpected input %s\n", asm_ctx.line_no, yytext);
481
                            set_parse_status(&asm_ctx.status, PARSE_ERR);
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
                        }

%%

struct bwriter_shader *SlAssembleShader(const char *text, char **messages) {
    struct bwriter_shader *ret = NULL;
    YY_BUFFER_STATE buffer;
    TRACE("%p, %p\n", text, messages);

    buffer = asmshader__scan_string(text);
    asmshader__switch_to_buffer(buffer);

    ret = parse_asm_shader(messages);

    asmshader__delete_buffer(buffer);

    return ret;
}