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> declaration_statement
255 %type <list> complex_initializer
256 %type <list> initializer_expr_list
257 %type <instr> initializer_expr
258 %type <modifiers> var_modifiers
259 %type <list> parameters
260 %type <list> param_list
264 %type <list> statement
265 %type <list> statement_list
266 %type <list> compound_statement
267 %type <function> func_declaration
268 %type <function> func_prototype
269 %type <parameter> parameter
270 %type <name> semantic
271 %type <variable_def> variable_def
272 %type <list> variables_def
273 %type <instr> primary_expr
274 %type <instr> postfix_expr
275 %type <instr> unary_expr
276 %type <instr> mul_expr
277 %type <instr> add_expr
278 %type <instr> shift_expr
279 %type <instr> relational_expr
280 %type <instr> equality_expr
281 %type <instr> bitand_expr
282 %type <instr> bitxor_expr
283 %type <instr> bitor_expr
284 %type <instr> logicand_expr
285 %type <instr> logicor_expr
286 %type <instr> conditional_expr
287 %type <instr> assignment_expr
288 %type <list> expr_statement
289 %type <modifiers> input_mod
292 hlsl_prog: /* empty */
295 | hlsl_prog func_declaration
297 FIXME("Check that the function doesn't conflict with an already declared one.\n");
298 list_add_tail(&hlsl_ctx.functions, &$2->node.entry);
300 | hlsl_prog declaration_statement
302 TRACE("Declaration statement parsed.\n");
304 | hlsl_prog preproc_directive
308 preproc_directive: PRE_LINE STRING
310 TRACE("Updating line information to file %s, line %u\n", debugstr_a($2), $1);
311 hlsl_ctx.line_no = $1;
312 d3dcompiler_free(hlsl_ctx.source_file);
313 hlsl_ctx.source_file = $2;
316 any_identifier: VAR_IDENTIFIER
320 func_declaration: func_prototype compound_statement
322 TRACE("Function %s parsed.\n", $1->name);
325 pop_scope(&hlsl_ctx);
329 TRACE("Function prototype for %s.\n", $1->name);
331 pop_scope(&hlsl_ctx);
334 func_prototype: var_modifiers type var_identifier '(' parameters ')' semantic
336 $$ = new_func_decl($3, $2, $5);
339 ERR("Out of memory.\n");
345 compound_statement: '{' '}'
347 $$ = d3dcompiler_alloc(sizeof(*$$));
350 | '{' scope_start statement_list '}'
352 pop_scope(&hlsl_ctx);
356 scope_start: /* Empty */
358 push_scope(&hlsl_ctx);
361 var_identifier: VAR_IDENTIFIER
364 semantic: /* Empty */
373 parameters: scope_start
375 $$ = d3dcompiler_alloc(sizeof(*$$));
378 | scope_start param_list
383 param_list: parameter
385 $$ = d3dcompiler_alloc(sizeof(*$$));
387 if (!add_func_parameter($$, &$1, hlsl_ctx.line_no))
389 ERR("Error adding function parameter %s.\n", $1.name);
390 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
394 | param_list ',' parameter
397 if (!add_func_parameter($$, &$3, hlsl_ctx.line_no))
399 hlsl_message("Line %u: duplicate parameter %s.\n",
400 hlsl_ctx.line_no, $3.name);
401 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
406 parameter: input_mod var_modifiers type any_identifier semantic
415 input_mod: /* Empty */
417 $$ = HLSL_MODIFIER_IN;
421 $$ = HLSL_MODIFIER_IN;
425 $$ = HLSL_MODIFIER_OUT;
429 $$ = HLSL_MODIFIER_IN | HLSL_MODIFIER_OUT;
436 | KW_VECTOR '<' base_type ',' C_INTEGER '>'
438 if ($3->type != HLSL_CLASS_SCALAR)
440 hlsl_message("Line %u: vectors of non-scalar types are not allowed.\n",
442 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
445 if ($5 < 1 || $5 > 4)
447 hlsl_message("Line %u: vector size must be between 1 and 4.\n",
449 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
453 $$ = new_hlsl_type(NULL, HLSL_CLASS_VECTOR, $3->base_type, $5, 1);
455 | KW_MATRIX '<' base_type ',' C_INTEGER ',' C_INTEGER '>'
457 if ($3->type != HLSL_CLASS_SCALAR)
459 hlsl_message("Line %u: matrices of non-scalar types are not allowed.\n",
461 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
464 if ($5 < 1 || $5 > 4 || $7 < 1 || $7 > 4)
466 hlsl_message("Line %u: matrix dimensions must be between 1 and 4.\n",
468 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
472 $$ = new_hlsl_type(NULL, HLSL_CLASS_MATRIX, $3->base_type, $5, $7);
477 $$ = new_hlsl_type(d3dcompiler_strdup("void"), HLSL_CLASS_SCALAR, HLSL_TYPE_VOID, 1, 1);
481 $$ = new_hlsl_type(d3dcompiler_strdup("sampler"), HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
482 $$->sampler_dim = HLSL_SAMPLER_DIM_GENERIC;
486 $$ = new_hlsl_type(d3dcompiler_strdup("sampler1D"), HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
487 $$->sampler_dim = HLSL_SAMPLER_DIM_1D;
491 $$ = new_hlsl_type(d3dcompiler_strdup("sampler2D"), HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
492 $$->sampler_dim = HLSL_SAMPLER_DIM_2D;
496 $$ = new_hlsl_type(d3dcompiler_strdup("sampler3D"), HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
497 $$->sampler_dim = HLSL_SAMPLER_DIM_3D;
501 $$ = new_hlsl_type(d3dcompiler_strdup("samplerCUBE"), HLSL_CLASS_OBJECT, HLSL_TYPE_SAMPLER, 1, 1);
502 $$->sampler_dim = HLSL_SAMPLER_DIM_CUBE;
506 struct hlsl_type *type;
508 TRACE("Type %s.\n", $1);
509 type = get_type(hlsl_ctx.cur_scope, $1, TRUE);
511 d3dcompiler_free($1);
513 | KW_STRUCT TYPE_IDENTIFIER
515 struct hlsl_type *type;
517 TRACE("Struct type %s.\n", $2);
518 type = get_type(hlsl_ctx.cur_scope, $2, TRUE);
519 if (type->type != HLSL_CLASS_STRUCT)
521 hlsl_message("Line %u: redefining %s as a structure.\n",
522 hlsl_ctx.line_no, $2);
523 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
529 d3dcompiler_free($2);
532 declaration_statement: declaration
534 $$ = d3dcompiler_alloc(sizeof(*$$));
538 declaration: var_modifiers type variables_def ';'
540 struct parse_variable_def *v, *v_next;
541 struct hlsl_ir_var *var;
542 BOOL ret, local = TRUE;
544 LIST_FOR_EACH_ENTRY_SAFE(v, v_next, $3, struct parse_variable_def, entry)
546 debug_dump_decl($2, $1, v->name, hlsl_ctx.line_no);
547 var = d3dcompiler_alloc(sizeof(*var));
548 var->node.type = HLSL_IR_VAR;
550 var->node.data_type = new_array_type($2, v->array_size);
552 var->node.data_type = $2;
555 var->semantic = v->semantic;
556 var->node.line = hlsl_ctx.line_no;
559 FIXME("Variable with an initializer.\n");
560 free_instr_list(v->initializer);
563 if (hlsl_ctx.cur_scope == hlsl_ctx.globals)
565 var->modifiers |= HLSL_STORAGE_UNIFORM;
569 ret = declare_variable(var, local);
571 free_declaration(var);
573 TRACE("Declared variable %s.\n", var->name);
576 d3dcompiler_free($3);
579 variables_def: variable_def
581 $$ = d3dcompiler_alloc(sizeof(*$$));
583 list_add_head($$, &$1->entry);
585 | variables_def ',' variable_def
588 list_add_tail($$, &$3->entry);
591 /* FIXME: Local variables can't have semantics. */
592 variable_def: any_identifier array semantic
594 $$ = d3dcompiler_alloc(sizeof(*$$));
599 | any_identifier array semantic '=' complex_initializer
601 TRACE("Declaration with initializer.\n");
602 $$ = d3dcompiler_alloc(sizeof(*$$));
606 $$->initializer = $5;
620 var_modifiers: /* Empty */
624 | KW_EXTERN var_modifiers
626 $$ = add_modifier($2, HLSL_STORAGE_EXTERN);
628 | KW_NOINTERPOLATION var_modifiers
630 $$ = add_modifier($2, HLSL_STORAGE_NOINTERPOLATION);
632 | KW_PRECISE var_modifiers
634 $$ = add_modifier($2, HLSL_MODIFIER_PRECISE);
636 | KW_SHARED var_modifiers
638 $$ = add_modifier($2, HLSL_STORAGE_SHARED);
640 | KW_GROUPSHARED var_modifiers
642 $$ = add_modifier($2, HLSL_STORAGE_GROUPSHARED);
644 | KW_STATIC var_modifiers
646 $$ = add_modifier($2, HLSL_STORAGE_STATIC);
648 | KW_UNIFORM var_modifiers
650 $$ = add_modifier($2, HLSL_STORAGE_UNIFORM);
652 | KW_VOLATILE var_modifiers
654 $$ = add_modifier($2, HLSL_STORAGE_VOLATILE);
656 | KW_CONST var_modifiers
658 $$ = add_modifier($2, HLSL_MODIFIER_CONST);
660 | KW_ROW_MAJOR var_modifiers
662 $$ = add_modifier($2, HLSL_MODIFIER_ROW_MAJOR);
664 | KW_COLUMN_MAJOR var_modifiers
666 $$ = add_modifier($2, HLSL_MODIFIER_COLUMN_MAJOR);
669 complex_initializer: initializer_expr
671 $$ = d3dcompiler_alloc(sizeof(*$$));
673 list_add_head($$, &$1->entry);
675 | '{' initializer_expr_list '}'
680 initializer_expr: assignment_expr
685 initializer_expr_list: initializer_expr
687 $$ = d3dcompiler_alloc(sizeof(*$$));
689 list_add_head($$, &$1->entry);
691 | initializer_expr_list ',' initializer_expr
694 list_add_tail($$, &$3->entry);
706 statement_list: statement
710 | statement_list statement
713 list_move_tail($$, $2);
714 d3dcompiler_free($2);
717 statement: declaration_statement
732 $$ = d3dcompiler_alloc(sizeof(*$$));
737 $$ = d3dcompiler_alloc(sizeof(*$$));
740 list_add_head($$, &$1->entry);
743 primary_expr: C_FLOAT
745 struct hlsl_ir_constant *c = d3dcompiler_alloc(sizeof(*c));
748 ERR("Out of memory.\n");
751 c->node.type = HLSL_IR_CONSTANT;
752 c->node.data_type = new_hlsl_type("float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1);
753 c->v.value.f[0] = $1;
758 struct hlsl_ir_constant *c = d3dcompiler_alloc(sizeof(*c));
761 ERR("Out of memory.\n");
764 c->node.type = HLSL_IR_CONSTANT;
765 c->node.data_type = new_hlsl_type("int", HLSL_CLASS_SCALAR, HLSL_TYPE_INT, 1, 1);
766 c->v.value.i[0] = $1;
771 struct hlsl_ir_constant *c = d3dcompiler_alloc(sizeof(*c));
774 ERR("Out of memory.\n");
777 c->node.type = HLSL_IR_CONSTANT;
778 c->node.data_type = new_hlsl_type("bool", HLSL_CLASS_SCALAR, HLSL_TYPE_BOOL, 1, 1);
779 c->v.value.b[0] = $1;
784 struct hlsl_ir_deref *deref = new_var_deref($1);
785 $$ = deref ? &deref->node : NULL;
792 variable: VAR_IDENTIFIER
794 struct hlsl_ir_var *var;
795 var = get_variable(hlsl_ctx.cur_scope, $1);
798 hlsl_message("Line %d: variable '%s' not declared\n",
799 hlsl_ctx.line_no, $1);
800 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
806 postfix_expr: primary_expr
810 /* "var_modifiers" doesn't make sense in this case, but it's needed
811 in the grammar to avoid shift/reduce conflicts. */
812 | var_modifiers type '(' initializer_expr_list ')'
814 struct hlsl_ir_constructor *constructor;
816 TRACE("%s constructor.\n", debug_hlsl_type($2));
819 hlsl_message("Line %u: unexpected modifier in a constructor.\n",
821 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
824 if ($2->type > HLSL_CLASS_LAST_NUMERIC)
826 hlsl_message("Line %u: constructors are allowed only for numeric data types.\n",
828 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
831 if ($2->dimx * $2->dimy != components_count_expr_list($4))
833 hlsl_message("Line %u: wrong number of components in constructor.\n",
835 set_parse_status(&hlsl_ctx.status, PARSE_ERR);
839 constructor = d3dcompiler_alloc(sizeof(*constructor));
840 constructor->node.type = HLSL_IR_CONSTRUCTOR;
841 constructor->node.data_type = $2;
842 constructor->arguments = $4;
844 $$ = &constructor->node;
847 unary_expr: postfix_expr
867 relational_expr: shift_expr
872 equality_expr: relational_expr
877 bitand_expr: equality_expr
882 bitxor_expr: bitand_expr
887 bitor_expr: bitxor_expr
892 logicand_expr: bitor_expr
897 logicor_expr: logicand_expr
902 conditional_expr: logicor_expr
907 assignment_expr: conditional_expr
912 expr: assignment_expr
916 | expr ',' assignment_expr
918 FIXME("Comma expression\n");
923 struct bwriter_shader *parse_hlsl(enum shader_type type, DWORD major, DWORD minor,
924 const char *entrypoint, char **messages)
926 struct hlsl_ir_function_decl *function;
927 struct hlsl_scope *scope, *next_scope;
928 struct hlsl_type *hlsl_type, *next_type;
929 struct hlsl_ir_var *var, *next_var;
931 hlsl_ctx.status = PARSE_SUCCESS;
932 hlsl_ctx.messages.size = hlsl_ctx.messages.capacity = 0;
933 hlsl_ctx.line_no = 1;
934 hlsl_ctx.source_file = d3dcompiler_strdup("");
935 hlsl_ctx.cur_scope = NULL;
936 hlsl_ctx.matrix_majority = HLSL_COLUMN_MAJOR;
937 list_init(&hlsl_ctx.scopes);
938 list_init(&hlsl_ctx.types);
939 list_init(&hlsl_ctx.functions);
941 push_scope(&hlsl_ctx);
942 hlsl_ctx.globals = hlsl_ctx.cur_scope;
946 if (TRACE_ON(hlsl_parser))
948 struct hlsl_ir_function_decl *func;
951 LIST_FOR_EACH_ENTRY(func, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
954 debug_dump_ir_function(func);
958 TRACE("Compilation status = %d\n", hlsl_ctx.status);
961 if (hlsl_ctx.messages.size)
962 *messages = hlsl_ctx.messages.string;
968 if (hlsl_ctx.messages.capacity)
969 d3dcompiler_free(hlsl_ctx.messages.string);
972 d3dcompiler_free(hlsl_ctx.source_file);
973 TRACE("Freeing functions IR.\n");
974 LIST_FOR_EACH_ENTRY(function, &hlsl_ctx.functions, struct hlsl_ir_function_decl, node.entry)
975 free_function(function);
977 TRACE("Freeing variables.\n");
978 LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &hlsl_ctx.scopes, struct hlsl_scope, entry)
980 LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry)
982 free_declaration(var);
984 d3dcompiler_free(scope);
987 TRACE("Freeing types.\n");
988 LIST_FOR_EACH_ENTRY_SAFE(hlsl_type, next_type, &hlsl_ctx.types, struct hlsl_type, entry)
990 free_hlsl_type(hlsl_type);