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);