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;
121 struct hlsl_type *type;
127 struct hlsl_ir_var *var;
128 struct hlsl_ir_node *instr;
130 struct hlsl_ir_function_decl *function;
131 struct parse_parameter parameter;
132 struct parse_variable_def *variable_def;
139 %token KW_COLUMN_MAJOR
143 %token KW_DEPTHSTENCILSTATE
144 %token KW_DEPTHSTENCILVIEW
152 %token KW_GEOMETRYSHADER
153 %token KW_GROUPSHARED
160 %token KW_NOINTERPOLATION
163 %token KW_PIXELSHADER
165 %token KW_RASTERIZERSTATE
166 %token KW_RENDERTARGETVIEW
174 %token KW_SAMPLERCUBE
175 %token KW_SAMPLER_STATE
176 %token KW_SAMPLERCOMPARISONSTATE
179 %token KW_STATEBLOCK_STATE
186 %token KW_TECHNIQUE10
189 %token KW_TEXTURE1DARRAY
191 %token KW_TEXTURE2DARRAY
192 %token KW_TEXTURE2DMS
193 %token KW_TEXTURE2DMSARRAY
195 %token KW_TEXTURE3DARRAY
196 %token KW_TEXTURECUBE
201 %token KW_VERTEXSHADER
212 %token OP_LEFTSHIFTASSIGN
214 %token OP_RIGHTSHIFTASSIGN
232 %token <intval> PRE_LINE
234 %token <name> VAR_IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
235 %type <name> any_identifier var_identifier
237 %token <floatval> C_FLOAT
238 %token <intval> C_INTEGER
239 %type <boolval> boolean
240 %type <type> base_type
242 %type <list> complex_initializer
243 %type <list> initializer_expr_list
244 %type <instr> initializer_expr
245 %type <modifiers> var_modifiers
246 %type <list> parameters
247 %type <list> param_list
251 %type <list> statement
252 %type <list> statement_list
253 %type <list> compound_statement
254 %type <function> func_declaration
255 %type <function> func_prototype
256 %type <parameter> parameter
257 %type <name> semantic
258 %type <variable_def> variable_def
259 %type <list> variables_def
260 %type <instr> primary_expr
261 %type <instr> postfix_expr
262 %type <instr> unary_expr
263 %type <instr> mul_expr
264 %type <instr> add_expr
265 %type <instr> shift_expr
266 %type <instr> relational_expr
267 %type <instr> equality_expr
268 %type <instr> bitand_expr
269 %type <instr> bitxor_expr
270 %type <instr> bitor_expr
271 %type <instr> logicand_expr
272 %type <instr> logicor_expr
273 %type <instr> conditional_expr
274 %type <instr> assignment_expr
275 %type <list> expr_statement
276 %type <modifiers> input_mod
279 hlsl_prog: /* empty */
282 | hlsl_prog func_declaration
284 FIXME("Check that the function doesn't conflict with an already declared one.\n");
285 list_add_tail(&hlsl_ctx.functions, &$2->node.entry);
287 | hlsl_prog declaration_statement
289 TRACE("Declaration statement parsed.\n");
291 | hlsl_prog preproc_directive
295 preproc_directive: PRE_LINE STRING
297 TRACE("Updating line information to file %s, line %u\n", debugstr_a($2), $1);
298 hlsl_ctx.line_no = $1 - 1;
299 d3dcompiler_free(hlsl_ctx.source_file);
300 hlsl_ctx.source_file = $2;
303 any_identifier: VAR_IDENTIFIER
307 func_declaration: func_prototype compound_statement
309 TRACE("Function %s parsed.\n", $1->name);
312 pop_scope(&hlsl_ctx);
316 TRACE("Function prototype for %s.\n", $1->name);
318 pop_scope(&hlsl_ctx);
321 func_prototype: var_modifiers type var_identifier '(' parameters ')' semantic
323 $$ = new_func_decl($3, $2, $5);
326 ERR("Out of memory.\n");
332 compound_statement: '{' '}'
334 $$ = d3dcompiler_alloc(sizeof(*$$));
337 | '{' scope_start statement_list '}'
339 pop_scope(&hlsl_ctx);
343 scope_start: /* Empty */
345 push_scope(&hlsl_ctx);
348 var_identifier: VAR_IDENTIFIER
351 semantic: /* Empty */
360 parameters: scope_start
362 $$ = d3dcompiler_alloc(sizeof(*$$));
365 | scope_start param_list
370 param_list: parameter
372 $$ = d3dcompiler_alloc(sizeof(*$$));
374 if (!add_func_parameter($$, &$1, hlsl_ctx.line_no))
376 ERR("Error adding function parameter %s.\n", $1.name);
377 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
381 | param_list ',' parameter
384 if (!add_func_parameter($$, &$3, hlsl_ctx.line_no))
386 hlsl_message("Line %u: duplicate parameter %s.\n",
387 hlsl_ctx.line_no, $3.name);
388 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
393 parameter: input_mod var_modifiers type any_identifier semantic
402 input_mod: /* Empty */
404 $$ = HLSL_MODIFIER_IN;
408 $$ = HLSL_MODIFIER_IN;
412 $$ = HLSL_MODIFIER_OUT;
416 $$ = HLSL_MODIFIER_IN | HLSL_MODIFIER_OUT;
423 | KW_VECTOR '<' base_type ',' C_INTEGER '>'
425 if ($3->type != HLSL_CLASS_SCALAR)
427 hlsl_message("Line %u: vectors of non-scalar types are not allowed.\n",
429 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
432 if ($5 < 1 || $5 > 4)
434 hlsl_message("Line %u: vector size must be between 1 and 4.\n",
436 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
440 $$ = new_hlsl_type(NULL, HLSL_CLASS_VECTOR, $3->base_type, $5, 1);
442 | KW_MATRIX '<' base_type ',' C_INTEGER ',' C_INTEGER '>'
444 if ($3->type != HLSL_CLASS_SCALAR)
446 hlsl_message("Line %u: matrices of non-scalar types are not allowed.\n",
448 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
451 if ($5 < 1 || $5 > 4 || $7 < 1 || $7 > 4)
453 hlsl_message("Line %u: matrix dimensions must be between 1 and 4.\n",
455 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
459 $$ = new_hlsl_type(NULL, HLSL_CLASS_MATRIX, $3->base_type, $5, $7);
464 $$ = new_hlsl_type("void", HLSL_CLASS_SCALAR, HLSL_TYPE_VOID, 1, 1);
468 $$ = new_hlsl_type("sampler", HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
469 $$->sampler_dim = HLSL_SAMPLER_DIM_GENERIC;
473 $$ = new_hlsl_type("sampler1D", HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
474 $$->sampler_dim = HLSL_SAMPLER_DIM_1D;
478 $$ = new_hlsl_type("sampler2D", HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
479 $$->sampler_dim = HLSL_SAMPLER_DIM_2D;
483 $$ = new_hlsl_type("sampler3D", HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
484 $$->sampler_dim = HLSL_SAMPLER_DIM_3D;
488 $$ = new_hlsl_type("samplerCUBE", HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
489 $$->sampler_dim = HLSL_SAMPLER_DIM_CUBE;
493 struct hlsl_type *type;
495 TRACE("Type %s.\n", $1);
496 type = get_type(hlsl_ctx.cur_scope, $1, TRUE);
498 d3dcompiler_free($1);
500 | KW_STRUCT TYPE_IDENTIFIER
502 struct hlsl_type *type;
504 TRACE("Struct type %s.\n", $2);
505 type = get_type(hlsl_ctx.cur_scope, $2, TRUE);
506 if (type->type != HLSL_CLASS_STRUCT)
508 hlsl_message("Line %u: redefining %s as a structure.\n",
509 hlsl_ctx.line_no, $2);
510 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
516 d3dcompiler_free($2);
519 declaration_statement: declaration
523 declaration: var_modifiers type variables_def ';'
525 struct parse_variable_def *v, *v_next;
526 struct hlsl_ir_var *var;
527 BOOL ret, local = TRUE;
529 LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $3, struct parse_variable_def, entry)
531 debug_dump_decl($2, $1, v->name, hlsl_ctx.line_no);
532 var = d3dcompiler_alloc(sizeof(*var));
533 var->node.type = HLSL_IR_VAR;
535 var->node.data_type = new_array_type($2, v->array_size);
537 var->node.data_type = $2;
540 var->semantic = v->semantic;
541 var->node.line = hlsl_ctx.line_no;
544 FIXME("Variable with an initializer.\n");
545 free_instr_list(v->initializer);
548 if (hlsl_ctx.cur_scope == hlsl_ctx.globals)
550 var->modifiers |= HLSL_STORAGE_UNIFORM;
554 ret = declare_variable(var, local);
556 free_declaration(var);
558 TRACE("Declared variable %s.\n", var->name);
561 d3dcompiler_free($3);
564 variables_def: variable_def
566 $$ = d3dcompiler_alloc(sizeof(*$$));
568 list_add_head($$, &$1->entry);
570 | variables_def ',' variable_def
573 list_add_tail($$, &$3->entry);
576 /* FIXME: Local variables can't have semantics. */
577 variable_def: any_identifier array semantic
579 $$ = d3dcompiler_alloc(sizeof(*$$));
584 | any_identifier array semantic '=' complex_initializer
586 TRACE("Declaration with initializer.\n");
587 $$ = d3dcompiler_alloc(sizeof(*$$));
591 $$->initializer = $5;
605 var_modifiers: /* Empty */
609 | KW_EXTERN var_modifiers
611 $$ = add_modifier($2, HLSL_STORAGE_EXTERN);
613 | KW_NOINTERPOLATION var_modifiers
615 $$ = add_modifier($2, HLSL_STORAGE_NOINTERPOLATION);
617 | KW_PRECISE var_modifiers
619 $$ = add_modifier($2, HLSL_MODIFIER_PRECISE);
621 | KW_SHARED var_modifiers
623 $$ = add_modifier($2, HLSL_STORAGE_SHARED);
625 | KW_GROUPSHARED var_modifiers
627 $$ = add_modifier($2, HLSL_STORAGE_GROUPSHARED);
629 | KW_STATIC var_modifiers
631 $$ = add_modifier($2, HLSL_STORAGE_STATIC);
633 | KW_UNIFORM var_modifiers
635 $$ = add_modifier($2, HLSL_STORAGE_UNIFORM);
637 | KW_VOLATILE var_modifiers
639 $$ = add_modifier($2, HLSL_STORAGE_VOLATILE);
641 | KW_CONST var_modifiers
643 $$ = add_modifier($2, HLSL_MODIFIER_CONST);
645 | KW_ROW_MAJOR var_modifiers
647 $$ = add_modifier($2, HLSL_MODIFIER_ROW_MAJOR);
649 | KW_COLUMN_MAJOR var_modifiers
651 $$ = add_modifier($2, HLSL_MODIFIER_COLUMN_MAJOR);
654 complex_initializer: initializer_expr
656 $$ = d3dcompiler_alloc(sizeof(*$$));
658 list_add_head($$, &$1->entry);
660 | '{' initializer_expr_list '}'
665 initializer_expr: assignment_expr
670 initializer_expr_list: initializer_expr
672 $$ = d3dcompiler_alloc(sizeof(*$$));
674 list_add_head($$, &$1->entry);
676 | initializer_expr_list ',' initializer_expr
679 list_add_tail($$, &$3->entry);
691 statement_list: statement
695 | statement_list statement
698 list_move_tail($$, $2);
699 d3dcompiler_free($2);
702 statement: declaration_statement
704 $$ = d3dcompiler_alloc(sizeof(*$$));
718 $$ = d3dcompiler_alloc(sizeof(*$$));
723 $$ = d3dcompiler_alloc(sizeof(*$$));
726 list_add_head($$, &$1->entry);
729 primary_expr: C_FLOAT
731 struct hlsl_ir_constant *c = d3dcompiler_alloc(sizeof(*c));
734 ERR("Out of memory.\n");
737 c->node.type = HLSL_IR_CONSTANT;
738 c->node.data_type = new_hlsl_type("float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1);
739 c->v.value.f[0] = $1;
744 struct hlsl_ir_constant *c = d3dcompiler_alloc(sizeof(*c));
747 ERR("Out of memory.\n");
750 c->node.type = HLSL_IR_CONSTANT;
751 c->node.data_type = new_hlsl_type("int", HLSL_CLASS_SCALAR, HLSL_TYPE_INT, 1, 1);
752 c->v.value.i[0] = $1;
757 struct hlsl_ir_constant *c = d3dcompiler_alloc(sizeof(*c));
760 ERR("Out of memory.\n");
763 c->node.type = HLSL_IR_CONSTANT;
764 c->node.data_type = new_hlsl_type("bool", HLSL_CLASS_SCALAR, HLSL_TYPE_BOOL, 1, 1);
765 c->v.value.b[0] = $1;
770 struct hlsl_ir_deref *deref = new_var_deref($1);
771 $$ = deref ? &deref->node : NULL;
778 variable: VAR_IDENTIFIER
780 struct hlsl_ir_var *var;
781 var = get_variable(hlsl_ctx.cur_scope, $1);
784 hlsl_message("Line %d: variable '%s' not declared\n",
785 hlsl_ctx.line_no, $1);
786 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
792 postfix_expr: primary_expr
797 unary_expr: postfix_expr
817 relational_expr: shift_expr
822 equality_expr: relational_expr
827 bitand_expr: equality_expr
832 bitxor_expr: bitand_expr
837 bitor_expr: bitxor_expr
842 logicand_expr: bitor_expr
847 logicor_expr: logicand_expr
852 conditional_expr: logicor_expr
857 assignment_expr: conditional_expr
862 expr: assignment_expr
866 | expr ',' assignment_expr
868 FIXME("Comma expression\n");
873 struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD version, const char *entrypoint, char **messages)
875 struct hlsl_ir_function_decl *function;
876 struct hlsl_scope *scope, *next_scope;
877 struct hlsl_type *hlsl_type, *next_type;
878 struct hlsl_ir_var *var, *next_var;
880 hlsl_ctx.line_no = 1;
881 hlsl_ctx.source_file = d3dcompiler_strdup("");
882 hlsl_ctx.cur_scope = NULL;
883 hlsl_ctx.matrix_majority = HLSL_COLUMN_MAJOR;
884 list_init(&hlsl_ctx.scopes);
885 list_init(&hlsl_ctx.types);
886 list_init(&hlsl_ctx.functions);
888 push_scope(&hlsl_ctx);
889 hlsl_ctx.globals = hlsl_ctx.cur_scope;
893 if (TRACE_ON(hlsl_parser))
895 struct hlsl_ir_function_decl *func;
898 LIST_FOR_EACH_ENTRY(func, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
901 debug_dump_ir_function(func);
905 d3dcompiler_free(hlsl_ctx.source_file);
906 TRACE("Freeing functions IR.\n");
907 LIST_FOR_EACH_ENTRY(function, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
908 free_function(function);
910 TRACE("Freeing variables.\n");
911 LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &hlsl_ctx.scopes, struct hlsl_scope, entry)
913 LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry)
915 free_declaration(var);
917 d3dcompiler_free(scope);
920 TRACE("Freeing types.\n");
921 LIST_FOR_EACH_ENTRY_SAFE(hlsl_type, next_type, &hlsl_ctx.types, struct hlsl_type, entry)
923 free_hlsl_type(hlsl_type);