From 79c6ce0a0ff295e40d2e627111c2734dcf96a155 Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Wed, 19 Sep 2012 19:46:11 +0200 Subject: [PATCH] d3dcompiler: Parse "if/else" statement. --- dlls/d3dcompiler_43/d3dcompiler_private.h | 21 +++++++++ dlls/d3dcompiler_43/hlsl.y | 40 +++++++++++++++++ dlls/d3dcompiler_43/utils.c | 52 ++++++++++++++++++----- 3 files changed, 102 insertions(+), 11 deletions(-) diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index eb754481869..5171abe2d4d 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_private.h +++ b/dlls/d3dcompiler_43/d3dcompiler_private.h @@ -706,6 +706,7 @@ enum hlsl_ir_node_type HLSL_IR_DEREF, HLSL_IR_EXPR, HLSL_IR_FUNCTION_DECL, + HLSL_IR_IF, HLSL_IR_JUMP, HLSL_IR_SWIZZLE, }; @@ -755,6 +756,14 @@ struct hlsl_ir_function_decl struct list *body; }; +struct hlsl_ir_if +{ + struct hlsl_ir_node node; + struct hlsl_ir_node *condition; + struct list *then_instrs; + struct list *else_instrs; +}; + struct hlsl_ir_assignment { struct hlsl_ir_node node; @@ -939,6 +948,12 @@ struct parse_variable_def struct list *initializer; }; +struct parse_if_body +{ + struct list *then_instrs; + struct list *else_instrs; +}; + enum parse_unary_op { UNARY_OP_PLUS, @@ -1043,6 +1058,12 @@ static inline struct hlsl_ir_constructor *constructor_from_node(const struct hls return CONTAINING_RECORD(node, struct hlsl_ir_constructor, node); } +static inline struct hlsl_ir_if *if_from_node(const struct hlsl_ir_node *node) +{ + assert(node->type == HLSL_IR_IF); + return CONTAINING_RECORD(node, struct hlsl_ir_if, node); +} + BOOL add_declaration(struct hlsl_scope *scope, struct hlsl_ir_var *decl, BOOL local_var) DECLSPEC_HIDDEN; struct hlsl_ir_var *get_variable(struct hlsl_scope *scope, const char *name) DECLSPEC_HIDDEN; void free_declaration(struct hlsl_ir_var *decl) DECLSPEC_HIDDEN; diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y index 75b57412821..97a1d620b6e 100644 --- a/dlls/d3dcompiler_43/hlsl.y +++ b/dlls/d3dcompiler_43/hlsl.y @@ -358,6 +358,7 @@ static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const cha %locations %error-verbose +%expect 1 %union { @@ -373,6 +374,7 @@ static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const cha struct hlsl_ir_function_decl *function; struct parse_parameter parameter; struct parse_variable_def *variable_def; + struct parse_if_body if_body; enum parse_unary_op unary_op; enum parse_assign_op assign_op; } @@ -498,12 +500,14 @@ static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const cha %type statement_list %type compound_statement %type jump_statement +%type selection_statement %type func_declaration %type func_prototype %type parameter %type semantic %type variable_def %type variables_def +%type if_body %type primary_expr %type postfix_expr %type unary_expr @@ -994,6 +998,7 @@ statement: declaration_statement | expr_statement | compound_statement | jump_statement + | selection_statement /* FIXME: add rule for return with no value */ jump_statement: KW_RETURN expr ';' @@ -1019,6 +1024,41 @@ jump_statement: KW_RETURN expr ';' list_add_tail($$, &jump->node.entry); } +selection_statement: KW_IF '(' expr ')' if_body + { + struct hlsl_ir_if *instr = d3dcompiler_alloc(sizeof(*instr)); + if (!instr) + { + ERR("Out of memory\n"); + return -1; + } + instr->node.type = HLSL_IR_IF; + set_location(&instr->node.loc, &@1); + instr->condition = $3; + instr->then_instrs = $5.then_instrs; + instr->else_instrs = $5.else_instrs; + if ($3->data_type->dimx > 1 || $3->data_type->dimy > 1) + { + hlsl_report_message(instr->node.loc.file, instr->node.loc.line, + instr->node.loc.col, HLSL_LEVEL_ERROR, + "if condition requires a scalar"); + } + $$ = d3dcompiler_alloc(sizeof(*$$)); + list_init($$); + list_add_head($$, &instr->node.entry); + } + +if_body: statement + { + $$.then_instrs = $1; + $$.else_instrs = NULL; + } + | statement KW_ELSE statement + { + $$.then_instrs = $1; + $$.else_instrs = $3; + } + expr_statement: ';' { $$ = d3dcompiler_alloc(sizeof(*$$)); diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c index e0d351c7629..05f769c06ff 100644 --- a/dlls/d3dcompiler_43/utils.c +++ b/dlls/d3dcompiler_43/utils.c @@ -1742,6 +1742,7 @@ static const char *debug_node_type(enum hlsl_ir_node_type type) "HLSL_IR_DEREF", "HLSL_IR_EXPR", "HLSL_IR_FUNCTION_DECL", + "HLSL_IR_IF", "HLSL_IR_JUMP", "HLSL_IR_SWIZZLE", }; @@ -1753,6 +1754,17 @@ static const char *debug_node_type(enum hlsl_ir_node_type type) static void debug_dump_instr(const struct hlsl_ir_node *instr); +static void debug_dump_instr_list(const struct list *list) +{ + struct hlsl_ir_node *instr; + + LIST_FOR_EACH_ENTRY(instr, list, struct hlsl_ir_node, entry) + { + debug_dump_instr(instr); + TRACE("\n"); + } +} + static void debug_dump_ir_var(const struct hlsl_ir_var *var) { if (var->modifiers) @@ -1997,6 +2009,21 @@ static void debug_dump_ir_jump(const struct hlsl_ir_jump *jump) } } +static void debug_dump_ir_if(const struct hlsl_ir_if *if_node) +{ + TRACE("if ("); + debug_dump_instr(if_node->condition); + TRACE(")\n{\n"); + debug_dump_instr_list(if_node->then_instrs); + TRACE("}\n"); + if (if_node->else_instrs) + { + TRACE("else\n{\n"); + debug_dump_instr_list(if_node->else_instrs); + TRACE("}\n"); + } +} + static void debug_dump_instr(const struct hlsl_ir_node *instr) { switch (instr->type) @@ -2022,22 +2049,14 @@ static void debug_dump_instr(const struct hlsl_ir_node *instr) case HLSL_IR_JUMP: debug_dump_ir_jump(jump_from_node(instr)); break; + case HLSL_IR_IF: + debug_dump_ir_if(if_from_node(instr)); + break; default: TRACE("No dump function for %s\n", debug_node_type(instr->type)); } } -static void debug_dump_instr_list(const struct list *list) -{ - struct hlsl_ir_node *instr; - - LIST_FOR_EACH_ENTRY(instr, list, struct hlsl_ir_node, entry) - { - debug_dump_instr(instr); - TRACE("\n"); - } -} - void debug_dump_ir_function(const struct hlsl_ir_function_decl *func) { struct hlsl_ir_var *param; @@ -2159,6 +2178,14 @@ static void free_ir_assignment(struct hlsl_ir_assignment *assignment) d3dcompiler_free(assignment); } +static void free_ir_if(struct hlsl_ir_if *if_node) +{ + free_instr(if_node->condition); + free_instr_list(if_node->then_instrs); + free_instr_list(if_node->else_instrs); + d3dcompiler_free(if_node); +} + static void free_ir_jump(struct hlsl_ir_jump *jump) { if (jump->type == HLSL_IR_JUMP_RETURN) @@ -2191,6 +2218,9 @@ void free_instr(struct hlsl_ir_node *node) case HLSL_IR_ASSIGNMENT: free_ir_assignment(assignment_from_node(node)); break; + case HLSL_IR_IF: + free_ir_if(if_from_node(node)); + break; case HLSL_IR_JUMP: free_ir_jump(jump_from_node(node)); break;