4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2012 Matteo Bruni for CodeWeavers
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.
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.
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
23 #include "wine/debug.h"
27 #include "d3dcompiler_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL
(hlsl_parser
);
33 struct hlsl_parse_ctx hlsl_ctx
;
35 void hlsl_message
(const char *fmt
, ...
)
40 compilation_message
(&hlsl_ctx.messages
, fmt
, args
);
44 static void hlsl_error
(const char *s
)
46 hlsl_message
("Line %u: %s\n", hlsl_ctx.line_no
, s
);
47 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
50 static void debug_dump_decl
(struct hlsl_type
*type
, DWORD modifiers
, const char *declname
, unsigned int line_no
)
52 TRACE
("Line %u: ", line_no
);
54 TRACE
("%s ", debug_modifiers
(modifiers
));
55 TRACE
("%s %s;\n", debug_hlsl_type
(type
), declname
);
58 static BOOL declare_variable
(struct hlsl_ir_var
*decl
, BOOL local
)
62 TRACE
("Declaring variable %s.\n", decl
->name
);
63 if
(decl
->node.data_type
->type
== HLSL_CLASS_MATRIX
)
65 if
(!(decl
->modifiers
& (HLSL_MODIFIER_ROW_MAJOR | HLSL_MODIFIER_COLUMN_MAJOR
)))
67 decl
->modifiers |
= hlsl_ctx.matrix_majority
== HLSL_ROW_MAJOR
68 ? HLSL_MODIFIER_ROW_MAJOR
: HLSL_MODIFIER_COLUMN_MAJOR
;
73 DWORD invalid
= decl
->modifiers
& (HLSL_STORAGE_EXTERN | HLSL_STORAGE_SHARED
74 | HLSL_STORAGE_GROUPSHARED | HLSL_STORAGE_UNIFORM
);
77 hlsl_message
("Line %u: modifier '%s' invalid for local variables.\n",
78 hlsl_ctx.line_no
, debug_modifiers
(invalid
));
79 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
82 ret
= add_declaration
(hlsl_ctx.cur_scope
, decl
, local
);
85 struct hlsl_ir_var
*old
= get_variable
(hlsl_ctx.cur_scope
, decl
->name
);
87 hlsl_message
("Line %u: \"%s\" already declared.\n", hlsl_ctx.line_no
, decl
->name
);
88 hlsl_message
("Line %u: \"%s\" was previously declared here.\n", old
->node.line
, decl
->name
);
89 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
95 static DWORD add_modifier
(DWORD modifiers
, DWORD mod
)
99 hlsl_message
("Line %u: modifier '%s' already specified.\n",
100 hlsl_ctx.line_no
, debug_modifiers
(mod
));
101 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
104 if
(mod
& (HLSL_MODIFIER_ROW_MAJOR | HLSL_MODIFIER_COLUMN_MAJOR
)
105 && modifiers
& (HLSL_MODIFIER_ROW_MAJOR | HLSL_MODIFIER_COLUMN_MAJOR
))
107 hlsl_message
("Line %u: more than one matrix majority keyword.\n",
109 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
112 return modifiers | mod
;
115 static unsigned int components_count_expr_list
(struct list
*list
)
117 struct hlsl_ir_node
*node
;
118 unsigned int count
= 0;
120 LIST_FOR_EACH_ENTRY
(node
, list
, struct hlsl_ir_node
, entry
)
122 count
+= components_count_type
(node
->data_type
);
133 struct hlsl_type
*type
;
139 struct hlsl_ir_var
*var
;
140 struct hlsl_ir_node
*instr
;
142 struct hlsl_ir_function_decl
*function
;
143 struct parse_parameter parameter
;
144 struct parse_variable_def
*variable_def
;
151 %token KW_COLUMN_MAJOR
155 %token KW_DEPTHSTENCILSTATE
156 %token KW_DEPTHSTENCILVIEW
164 %token KW_GEOMETRYSHADER
165 %token KW_GROUPSHARED
172 %token KW_NOINTERPOLATION
175 %token KW_PIXELSHADER
177 %token KW_RASTERIZERSTATE
178 %token KW_RENDERTARGETVIEW
186 %token KW_SAMPLERCUBE
187 %token KW_SAMPLER_STATE
188 %token KW_SAMPLERCOMPARISONSTATE
191 %token KW_STATEBLOCK_STATE
198 %token KW_TECHNIQUE10
201 %token KW_TEXTURE1DARRAY
203 %token KW_TEXTURE2DARRAY
204 %token KW_TEXTURE2DMS
205 %token KW_TEXTURE2DMSARRAY
207 %token KW_TEXTURE3DARRAY
208 %token KW_TEXTURECUBE
213 %token KW_VERTEXSHADER
224 %token OP_LEFTSHIFTASSIGN
226 %token OP_RIGHTSHIFTASSIGN
244 %token
<intval
> PRE_LINE
246 %token
<name
> VAR_IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
247 %type
<name
> any_identifier var_identifier
249 %token
<floatval
> C_FLOAT
250 %token
<intval
> C_INTEGER
251 %type
<boolval
> boolean
252 %type
<type
> base_type
254 %type
<list
> complex_initializer
255 %type
<list
> initializer_expr_list
256 %type
<instr
> initializer_expr
257 %type
<modifiers
> var_modifiers
258 %type
<list
> parameters
259 %type
<list
> param_list
263 %type
<list
> statement
264 %type
<list
> statement_list
265 %type
<list
> compound_statement
266 %type
<function
> func_declaration
267 %type
<function
> func_prototype
268 %type
<parameter
> parameter
269 %type
<name
> semantic
270 %type
<variable_def
> variable_def
271 %type
<list
> variables_def
272 %type
<instr
> primary_expr
273 %type
<instr
> postfix_expr
274 %type
<instr
> unary_expr
275 %type
<instr
> mul_expr
276 %type
<instr
> add_expr
277 %type
<instr
> shift_expr
278 %type
<instr
> relational_expr
279 %type
<instr
> equality_expr
280 %type
<instr
> bitand_expr
281 %type
<instr
> bitxor_expr
282 %type
<instr
> bitor_expr
283 %type
<instr
> logicand_expr
284 %type
<instr
> logicor_expr
285 %type
<instr
> conditional_expr
286 %type
<instr
> assignment_expr
287 %type
<list
> expr_statement
288 %type
<modifiers
> input_mod
291 hlsl_prog: /* empty */
294 | hlsl_prog func_declaration
296 FIXME
("Check that the function doesn't conflict with an already declared one.\n");
297 list_add_tail
(&hlsl_ctx.functions
, &$2->node.entry
);
299 | hlsl_prog declaration_statement
301 TRACE
("Declaration statement parsed.\n");
303 | hlsl_prog preproc_directive
307 preproc_directive: PRE_LINE STRING
309 TRACE
("Updating line information to file %s, line %u\n", debugstr_a
($2), $1);
310 hlsl_ctx.line_no
= $1 - 1;
311 d3dcompiler_free
(hlsl_ctx.source_file
);
312 hlsl_ctx.source_file
= $2;
315 any_identifier: VAR_IDENTIFIER
319 func_declaration: func_prototype compound_statement
321 TRACE
("Function %s parsed.\n", $1->name
);
324 pop_scope
(&hlsl_ctx
);
328 TRACE
("Function prototype for %s.\n", $1->name
);
330 pop_scope
(&hlsl_ctx
);
333 func_prototype: var_modifiers type var_identifier
'(' parameters
')' semantic
335 $$
= new_func_decl
($3, $2, $5);
338 ERR
("Out of memory.\n");
344 compound_statement: '{' '}'
346 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
349 |
'{' scope_start statement_list
'}'
351 pop_scope
(&hlsl_ctx
);
355 scope_start: /* Empty */
357 push_scope
(&hlsl_ctx
);
360 var_identifier: VAR_IDENTIFIER
363 semantic: /* Empty */
372 parameters: scope_start
374 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
377 | scope_start param_list
382 param_list: parameter
384 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
386 if
(!add_func_parameter
($$
, &$1, hlsl_ctx.line_no
))
388 ERR
("Error adding function parameter %s.\n", $1.name
);
389 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
393 | param_list
',' parameter
396 if
(!add_func_parameter
($$
, &$3, hlsl_ctx.line_no
))
398 hlsl_message
("Line %u: duplicate parameter %s.\n",
399 hlsl_ctx.line_no
, $3.name
);
400 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
405 parameter: input_mod var_modifiers type any_identifier semantic
414 input_mod: /* Empty */
416 $$
= HLSL_MODIFIER_IN
;
420 $$
= HLSL_MODIFIER_IN
;
424 $$
= HLSL_MODIFIER_OUT
;
428 $$
= HLSL_MODIFIER_IN | HLSL_MODIFIER_OUT
;
435 | KW_VECTOR
'<' base_type
',' C_INTEGER
'>'
437 if
($3->type
!= HLSL_CLASS_SCALAR
)
439 hlsl_message
("Line %u: vectors of non-scalar types are not allowed.\n",
441 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
444 if
($5 < 1 ||
$5 > 4)
446 hlsl_message
("Line %u: vector size must be between 1 and 4.\n",
448 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
452 $$
= new_hlsl_type
(NULL
, HLSL_CLASS_VECTOR
, $3->base_type
, $5, 1);
454 | KW_MATRIX
'<' base_type
',' C_INTEGER
',' C_INTEGER
'>'
456 if
($3->type
!= HLSL_CLASS_SCALAR
)
458 hlsl_message
("Line %u: matrices of non-scalar types are not allowed.\n",
460 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
463 if
($5 < 1 ||
$5 > 4 ||
$7 < 1 ||
$7 > 4)
465 hlsl_message
("Line %u: matrix dimensions must be between 1 and 4.\n",
467 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
471 $$
= new_hlsl_type
(NULL
, HLSL_CLASS_MATRIX
, $3->base_type
, $5, $7);
476 $$
= new_hlsl_type
("void", HLSL_CLASS_SCALAR
, HLSL_TYPE_VOID
, 1, 1);
480 $$
= new_hlsl_type
("sampler", HLSL_CLASS_OBJECT
, HLSL_TYPE_SAMPLER
, 1, 1);
481 $$
->sampler_dim
= HLSL_SAMPLER_DIM_GENERIC
;
485 $$
= new_hlsl_type
("sampler1D", HLSL_CLASS_OBJECT
, HLSL_TYPE_SAMPLER
, 1, 1);
486 $$
->sampler_dim
= HLSL_SAMPLER_DIM_1D
;
490 $$
= new_hlsl_type
("sampler2D", HLSL_CLASS_OBJECT
, HLSL_TYPE_SAMPLER
, 1, 1);
491 $$
->sampler_dim
= HLSL_SAMPLER_DIM_2D
;
495 $$
= new_hlsl_type
("sampler3D", HLSL_CLASS_OBJECT
, HLSL_TYPE_SAMPLER
, 1, 1);
496 $$
->sampler_dim
= HLSL_SAMPLER_DIM_3D
;
500 $$
= new_hlsl_type
("samplerCUBE", HLSL_CLASS_OBJECT
, HLSL_TYPE_SAMPLER
, 1, 1);
501 $$
->sampler_dim
= HLSL_SAMPLER_DIM_CUBE
;
505 struct hlsl_type
*type
;
507 TRACE
("Type %s.\n", $1);
508 type
= get_type
(hlsl_ctx.cur_scope
, $1, TRUE
);
510 d3dcompiler_free
($1);
512 | KW_STRUCT TYPE_IDENTIFIER
514 struct hlsl_type
*type
;
516 TRACE
("Struct type %s.\n", $2);
517 type
= get_type
(hlsl_ctx.cur_scope
, $2, TRUE
);
518 if
(type
->type
!= HLSL_CLASS_STRUCT
)
520 hlsl_message
("Line %u: redefining %s as a structure.\n",
521 hlsl_ctx.line_no
, $2);
522 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
528 d3dcompiler_free
($2);
531 declaration_statement: declaration
535 declaration: var_modifiers type variables_def
';'
537 struct parse_variable_def
*v
, *v_next
;
538 struct hlsl_ir_var
*var
;
539 BOOL ret
, local
= TRUE
;
541 LIST_FOR_EACH_ENTRY_SAFE
(v
, v_next
, $3, struct parse_variable_def
, entry
)
543 debug_dump_decl
($2, $1, v
->name
, hlsl_ctx.line_no
);
544 var
= d3dcompiler_alloc
(sizeof
(*var
));
545 var
->node.type
= HLSL_IR_VAR
;
547 var
->node.data_type
= new_array_type
($2, v
->array_size
);
549 var
->node.data_type
= $2;
552 var
->semantic
= v
->semantic
;
553 var
->node.line
= hlsl_ctx.line_no
;
556 FIXME
("Variable with an initializer.\n");
557 free_instr_list
(v
->initializer
);
560 if
(hlsl_ctx.cur_scope
== hlsl_ctx.globals
)
562 var
->modifiers |
= HLSL_STORAGE_UNIFORM
;
566 ret
= declare_variable
(var
, local
);
568 free_declaration
(var
);
570 TRACE
("Declared variable %s.\n", var
->name
);
573 d3dcompiler_free
($3);
576 variables_def: variable_def
578 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
580 list_add_head
($$
, &$1->entry
);
582 | variables_def
',' variable_def
585 list_add_tail
($$
, &$3->entry
);
588 /* FIXME: Local variables can't have semantics. */
589 variable_def: any_identifier array semantic
591 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
596 | any_identifier array semantic
'=' complex_initializer
598 TRACE
("Declaration with initializer.\n");
599 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
603 $$
->initializer
= $5;
617 var_modifiers: /* Empty */
621 | KW_EXTERN var_modifiers
623 $$
= add_modifier
($2, HLSL_STORAGE_EXTERN
);
625 | KW_NOINTERPOLATION var_modifiers
627 $$
= add_modifier
($2, HLSL_STORAGE_NOINTERPOLATION
);
629 | KW_PRECISE var_modifiers
631 $$
= add_modifier
($2, HLSL_MODIFIER_PRECISE
);
633 | KW_SHARED var_modifiers
635 $$
= add_modifier
($2, HLSL_STORAGE_SHARED
);
637 | KW_GROUPSHARED var_modifiers
639 $$
= add_modifier
($2, HLSL_STORAGE_GROUPSHARED
);
641 | KW_STATIC var_modifiers
643 $$
= add_modifier
($2, HLSL_STORAGE_STATIC
);
645 | KW_UNIFORM var_modifiers
647 $$
= add_modifier
($2, HLSL_STORAGE_UNIFORM
);
649 | KW_VOLATILE var_modifiers
651 $$
= add_modifier
($2, HLSL_STORAGE_VOLATILE
);
653 | KW_CONST var_modifiers
655 $$
= add_modifier
($2, HLSL_MODIFIER_CONST
);
657 | KW_ROW_MAJOR var_modifiers
659 $$
= add_modifier
($2, HLSL_MODIFIER_ROW_MAJOR
);
661 | KW_COLUMN_MAJOR var_modifiers
663 $$
= add_modifier
($2, HLSL_MODIFIER_COLUMN_MAJOR
);
666 complex_initializer: initializer_expr
668 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
670 list_add_head
($$
, &$1->entry
);
672 |
'{' initializer_expr_list
'}'
677 initializer_expr: assignment_expr
682 initializer_expr_list: initializer_expr
684 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
686 list_add_head
($$
, &$1->entry
);
688 | initializer_expr_list
',' initializer_expr
691 list_add_tail
($$
, &$3->entry
);
703 statement_list: statement
707 | statement_list statement
710 list_move_tail
($$
, $2);
711 d3dcompiler_free
($2);
714 statement: declaration_statement
716 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
730 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
735 $$
= d3dcompiler_alloc
(sizeof
(*$$
));
738 list_add_head
($$
, &$1->entry
);
741 primary_expr: C_FLOAT
743 struct hlsl_ir_constant
*c
= d3dcompiler_alloc
(sizeof
(*c
));
746 ERR
("Out of memory.\n");
749 c
->node.type
= HLSL_IR_CONSTANT
;
750 c
->node.data_type
= new_hlsl_type
("float", HLSL_CLASS_SCALAR
, HLSL_TYPE_FLOAT
, 1, 1);
751 c
->v.value.f
[0] = $1;
756 struct hlsl_ir_constant
*c
= d3dcompiler_alloc
(sizeof
(*c
));
759 ERR
("Out of memory.\n");
762 c
->node.type
= HLSL_IR_CONSTANT
;
763 c
->node.data_type
= new_hlsl_type
("int", HLSL_CLASS_SCALAR
, HLSL_TYPE_INT
, 1, 1);
764 c
->v.value.i
[0] = $1;
769 struct hlsl_ir_constant
*c
= d3dcompiler_alloc
(sizeof
(*c
));
772 ERR
("Out of memory.\n");
775 c
->node.type
= HLSL_IR_CONSTANT
;
776 c
->node.data_type
= new_hlsl_type
("bool", HLSL_CLASS_SCALAR
, HLSL_TYPE_BOOL
, 1, 1);
777 c
->v.value.b
[0] = $1;
782 struct hlsl_ir_deref
*deref
= new_var_deref
($1);
783 $$
= deref ?
&deref
->node
: NULL
;
790 variable: VAR_IDENTIFIER
792 struct hlsl_ir_var
*var
;
793 var
= get_variable
(hlsl_ctx.cur_scope
, $1);
796 hlsl_message
("Line %d: variable '%s' not declared\n",
797 hlsl_ctx.line_no
, $1);
798 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
804 postfix_expr: primary_expr
808 /* "var_modifiers" doesn't make sense in this case, but it's needed
809 in the grammar to avoid shift/reduce conflicts. */
810 | var_modifiers type
'(' initializer_expr_list
')'
812 struct hlsl_ir_constructor
*constructor
;
814 TRACE
("%s constructor.\n", debug_hlsl_type
($2));
817 hlsl_message
("Line %u: unexpected modifier in a constructor.\n",
819 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
822 if
($2->type
> HLSL_CLASS_LAST_NUMERIC
)
824 hlsl_message
("Line %u: constructors are allowed only for numeric data types.\n",
826 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
829 if
($2->dimx
* $2->dimy
!= components_count_expr_list
($4))
831 hlsl_message
("Line %u: wrong number of components in constructor.\n",
833 set_parse_status
(&hlsl_ctx.status
, PARSE_ERR
);
837 constructor
= d3dcompiler_alloc
(sizeof
(*constructor
));
838 constructor
->node.type
= HLSL_IR_CONSTRUCTOR
;
839 constructor
->node.data_type
= $2;
840 constructor
->arguments
= $4;
842 $$
= &constructor
->node
;
845 unary_expr: postfix_expr
865 relational_expr: shift_expr
870 equality_expr: relational_expr
875 bitand_expr: equality_expr
880 bitxor_expr: bitand_expr
885 bitor_expr: bitxor_expr
890 logicand_expr: bitor_expr
895 logicor_expr: logicand_expr
900 conditional_expr: logicor_expr
905 assignment_expr: conditional_expr
910 expr: assignment_expr
914 | expr
',' assignment_expr
916 FIXME
("Comma expression\n");
921 struct bwriter_shader
*parse_hlsl
(enum shader_type type
, DWORD version
, const char *entrypoint
, char **messages
)
923 struct hlsl_ir_function_decl
*function
;
924 struct hlsl_scope
*scope
, *next_scope
;
925 struct hlsl_type
*hlsl_type
, *next_type
;
926 struct hlsl_ir_var
*var
, *next_var
;
928 hlsl_ctx.line_no
= 1;
929 hlsl_ctx.source_file
= d3dcompiler_strdup
("");
930 hlsl_ctx.cur_scope
= NULL
;
931 hlsl_ctx.matrix_majority
= HLSL_COLUMN_MAJOR
;
932 list_init
(&hlsl_ctx.scopes
);
933 list_init
(&hlsl_ctx.types
);
934 list_init
(&hlsl_ctx.functions
);
936 push_scope
(&hlsl_ctx
);
937 hlsl_ctx.globals
= hlsl_ctx.cur_scope
;
941 if
(TRACE_ON
(hlsl_parser
))
943 struct hlsl_ir_function_decl
*func
;
946 LIST_FOR_EACH_ENTRY
(func
, &hlsl_ctx.functions
, struct hlsl_ir_function_decl
, node.entry
)
949 debug_dump_ir_function
(func
);
953 d3dcompiler_free
(hlsl_ctx.source_file
);
954 TRACE
("Freeing functions IR.\n");
955 LIST_FOR_EACH_ENTRY
(function
, &hlsl_ctx.functions
, struct hlsl_ir_function_decl
, node.entry
)
956 free_function
(function
);
958 TRACE
("Freeing variables.\n");
959 LIST_FOR_EACH_ENTRY_SAFE
(scope
, next_scope
, &hlsl_ctx.scopes
, struct hlsl_scope
, entry
)
961 LIST_FOR_EACH_ENTRY_SAFE
(var
, next_var
, &scope
->vars
, struct hlsl_ir_var
, scope_entry
)
963 free_declaration
(var
);
965 d3dcompiler_free
(scope
);
968 TRACE
("Freeing types.\n");
969 LIST_FOR_EACH_ENTRY_SAFE
(hlsl_type
, next_type
, &hlsl_ctx.types
, struct hlsl_type
, entry
)
971 free_hlsl_type
(hlsl_type
);