From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 2 ++ libs/vkd3d-shader/hlsl.h | 2 ++ libs/vkd3d-shader/hlsl.y | 57 +++++++++++++++++++++++++++++++--------- 3 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 3a1e17797..4648cc77c 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1842,6 +1842,7 @@ static struct hlsl_scope *hlsl_new_scope(struct hlsl_ctx *ctx, struct hlsl_scope return NULL; list_init(&scope->vars); rb_init(&scope->types, compare_hlsl_types_rb); + hlsl_block_init(&scope->loop_iterator); scope->upper = upper; list_add_tail(&ctx->scopes, &scope->entry); return scope; @@ -3281,6 +3282,7 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry) hlsl_free_var(var); rb_destroy(&scope->types, NULL, NULL); + hlsl_block_cleanup(&scope->loop_iterator); vkd3d_free(scope); }
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index eceead8cb..f83f06d96 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -684,6 +684,8 @@ struct hlsl_scope struct hlsl_scope *upper; /* The scope was created for the loop statement. */ bool loop; + /* Block of iterator instructions of a 'for' loop. */ + struct hlsl_block loop_iterator; };
struct hlsl_profile_info diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 36face242..b24c87544 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -482,10 +482,10 @@ static bool attribute_list_has_duplicates(const struct parse_attribute_list *att return false; }
-static struct list *create_loop(struct hlsl_ctx *ctx, enum loop_type type, const struct parse_attribute_list *attributes, struct list *init, struct list *cond, - struct list *iter, struct list *body, const struct vkd3d_shader_location *loc) +static struct list *create_loop(struct hlsl_ctx *ctx, enum loop_type type, const struct parse_attribute_list *attributes, + struct list *init, struct list *cond, struct list *body, const struct vkd3d_shader_location *loc) { - struct hlsl_block body_block; + struct hlsl_block body_block, iter_block; struct hlsl_ir_node *loop; unsigned int i;
@@ -532,8 +532,9 @@ static struct list *create_loop(struct hlsl_ctx *ctx, enum loop_type type, const
list_move_tail(&body_block.instrs, body);
- if (iter) - list_move_tail(&body_block.instrs, iter); + if (!hlsl_clone_block(ctx, &iter_block, &ctx->cur_scope->loop_iterator)) + goto oom; + hlsl_block_add_block(&body_block, &iter_block);
if (type == LOOP_DO_WHILE) list_move_tail(&body_block.instrs, cond); @@ -549,7 +550,6 @@ static struct list *create_loop(struct hlsl_ctx *ctx, enum loop_type type, const oom: destroy_instr_list(init); destroy_instr_list(cond); - destroy_instr_list(iter); destroy_instr_list(body); return NULL; } @@ -4480,6 +4480,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope) %type <list> jump_statement %type <list> logicand_expr %type <list> logicor_expr +%type <list> loop_iterator %type <list> loop_statement %type <list> mul_expr %type <list> postfix_expr @@ -5810,6 +5811,27 @@ jump_statement: YYABORT; list_add_tail($$, &jump->entry); } + | KW_CONTINUE ';' + { + struct hlsl_ir_node *jump; + struct hlsl_scope *scope; + struct hlsl_block iter; + + if (!(scope = get_loop_scope(ctx->cur_scope))) + { + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Incorrect context for a 'continue' statement."); + } + + if (!($$ = make_empty_list(ctx))) + YYABORT; + + if (!hlsl_clone_block(ctx, &iter, &scope->loop_iterator)) + YYABORT; + if (!(jump = hlsl_new_jump(ctx, HLSL_IR_JUMP_CONTINUE, NULL, &@1))) + YYABORT; + list_move_tail($$, &iter.instrs); + list_add_tail($$, &jump->entry); + } | KW_RETURN expr ';' { if (!add_return(ctx, $2, node_from_list($2), &@1)) @@ -5878,25 +5900,36 @@ if_body: $$.else_block = list_to_block($3); }
+loop_iterator: + expr_optional + { + struct hlsl_scope *scope = ctx->cur_scope; + + if ($1) + { + list_move_tail(&scope->loop_iterator.instrs, $1); + } + } + loop_statement: attribute_list_optional loop_scope_start KW_WHILE '(' expr ')' statement { - $$ = create_loop(ctx, LOOP_WHILE, &$1, NULL, $5, NULL, $7, &@3); + $$ = create_loop(ctx, LOOP_WHILE, &$1, NULL, $5, $7, &@3); hlsl_pop_scope(ctx); } | attribute_list_optional loop_scope_start KW_DO statement KW_WHILE '(' expr ')' ';' { - $$ = create_loop(ctx, LOOP_DO_WHILE, &$1, NULL, $7, NULL, $4, &@3); + $$ = create_loop(ctx, LOOP_DO_WHILE, &$1, NULL, $7, $4, &@3); hlsl_pop_scope(ctx); } - | attribute_list_optional loop_scope_start KW_FOR '(' expr_statement expr_statement expr_optional ')' statement + | attribute_list_optional loop_scope_start KW_FOR '(' expr_statement expr_statement loop_iterator ')' statement { - $$ = create_loop(ctx, LOOP_FOR, &$1, $5, $6, $7, $9, &@3); + $$ = create_loop(ctx, LOOP_FOR, &$1, $5, $6, $9, &@3); hlsl_pop_scope(ctx); } - | attribute_list_optional loop_scope_start KW_FOR '(' declaration expr_statement expr_optional ')' statement + | attribute_list_optional loop_scope_start KW_FOR '(' declaration expr_statement loop_iterator ')' statement { - $$ = create_loop(ctx, LOOP_FOR, &$1, $5, $6, $7, $9, &@3); + $$ = create_loop(ctx, LOOP_FOR, &$1, $5, $6, $9, &@3); hlsl_pop_scope(ctx); }