From 8975933aff3fa47eeabe5ecdb72c5715fdf62daf Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 29 Aug 2024 12:48:23 -0500
Subject: [PATCH 1/8] vkd3d-shader/hlsl: Store a pointer to the block's "value"
 instruction in the block.

---
 libs/vkd3d-shader/hlsl.h | 6 ++++++
 libs/vkd3d-shader/hlsl.y | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index c03b1f9eca..260b0da17f 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -361,6 +361,9 @@ struct hlsl_block
 {
     /* List containing instruction nodes; linked by the hlsl_ir_node.entry fields. */
     struct list instrs;
+    /* Instruction representing the "value" of this block, if applicable.
+     * This may point to an instruction outside of this block! */
+    struct hlsl_ir_node *value;
 };
 
 /* A reference to an instruction node (struct hlsl_ir_node), usable as a field in other structs.
@@ -1212,16 +1215,19 @@ static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(co
 static inline void hlsl_block_init(struct hlsl_block *block)
 {
     list_init(&block->instrs);
+    block->value = NULL;
 }
 
 static inline void hlsl_block_add_instr(struct hlsl_block *block, struct hlsl_ir_node *instr)
 {
     list_add_tail(&block->instrs, &instr->entry);
+    block->value = (instr->data_type ? instr : NULL);
 }
 
 static inline void hlsl_block_add_block(struct hlsl_block *block, struct hlsl_block *add)
 {
     list_move_tail(&block->instrs, &add->instrs);
+    block->value = add->value;
 }
 
 static inline void hlsl_src_from_node(struct hlsl_src *src, struct hlsl_ir_node *node)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 0a080666b4..842032ac32 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -147,7 +147,7 @@ static void yyerror(YYLTYPE *loc, void *scanner, struct hlsl_ctx *ctx, const cha
 
 static struct hlsl_ir_node *node_from_block(struct hlsl_block *block)
 {
-    return LIST_ENTRY(list_tail(&block->instrs), struct hlsl_ir_node, entry);
+    return block->value;
 }
 
 static struct hlsl_block *make_empty_block(struct hlsl_ctx *ctx)
@@ -639,14 +639,14 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx
         return ret;
     hlsl_block_add_block(&expr, block);
 
-    if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc))
+    if (!(node = add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc)))
     {
         hlsl_block_cleanup(&expr);
         return ret;
     }
 
     /* Wrap the node into a src to allow the reference to survive the multiple const passes. */
-    hlsl_src_from_node(&src, node_from_block(&expr));
+    hlsl_src_from_node(&src, node);
     hlsl_run_const_passes(ctx, &expr);
     node = src.node;
     hlsl_src_remove(&src);
-- 
GitLab


From eb7f5f7f685902bf718a1bfdd3ccc14b65ff5793 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 29 Aug 2024 12:48:23 -0500
Subject: [PATCH 2/8] vkd3d-shader/hlsl: Return bool from add_assignment().

---
 libs/vkd3d-shader/hlsl.y | 50 +++++++++++++++++++---------------------
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 842032ac32..d6f794ec2e 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -2059,7 +2059,7 @@ static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, un
     return true;
 }
 
-static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs,
+static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs,
         enum parse_assign_op assign_op, struct hlsl_ir_node *rhs)
 {
     struct hlsl_type *lhs_type = lhs->data_type;
@@ -2070,7 +2070,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
     if (assign_op == ASSIGN_OP_SUB)
     {
         if (!(rhs = add_unary_arithmetic_expr(ctx, block, HLSL_OP1_NEG, rhs, &rhs->loc)))
-            return NULL;
+            return false;
         assign_op = ASSIGN_OP_ADD;
     }
     if (assign_op != ASSIGN_OP_ASSIGN)
@@ -2079,7 +2079,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
 
         VKD3D_ASSERT(op);
         if (!(rhs = add_binary_expr(ctx, block, op, lhs, rhs, &rhs->loc)))
-            return NULL;
+            return false;
     }
 
     if (hlsl_is_numeric_type(lhs_type))
@@ -2089,14 +2089,14 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
     }
 
     if (!(rhs = add_implicit_conversion(ctx, block, rhs, lhs_type, &rhs->loc)))
-        return NULL;
+        return false;
 
     while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_INDEX)
     {
         if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST)
         {
             hlsl_fixme(ctx, &lhs->loc, "Cast on the LHS.");
-            return NULL;
+            return false;
         }
         else if (lhs->type == HLSL_IR_SWIZZLE)
         {
@@ -2111,25 +2111,23 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
                 if (swizzle->val.node->type != HLSL_IR_LOAD && swizzle->val.node->type != HLSL_IR_INDEX)
                 {
                     hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle.");
-                    return NULL;
+                    return false;
                 }
                 if (!invert_swizzle_matrix(&s, &writemask, &width))
                 {
                     hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask for matrix.");
-                    return NULL;
+                    return false;
                 }
                 matrix_writemask = true;
             }
             else if (!invert_swizzle(&s, &writemask, &width))
             {
                 hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask.");
-                return NULL;
+                return false;
             }
 
             if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc)))
-            {
-                return NULL;
-            }
+                return false;
             hlsl_block_add_instr(block, new_swizzle);
 
             lhs = swizzle->val.node;
@@ -2138,7 +2136,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
         else
         {
             hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Invalid lvalue.");
-            return NULL;
+            return false;
         }
     }
 
@@ -2153,11 +2151,11 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
         if (!hlsl_index_is_resource_access(hlsl_ir_index(lhs)))
         {
             hlsl_fixme(ctx, &lhs->loc, "Non-direct structured resource store.");
-            return NULL;
+            return false;
         }
 
         if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, hlsl_ir_index(lhs)->val.node))
-            return NULL;
+            return false;
 
         resource_type = hlsl_deref_get_type(ctx, &resource_deref);
         VKD3D_ASSERT(resource_type->class == HLSL_CLASS_TEXTURE || resource_type->class == HLSL_CLASS_UAV);
@@ -2179,7 +2177,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
         if (!(store = hlsl_new_resource_store(ctx, &resource_deref, coords, rhs, &lhs->loc)))
         {
             hlsl_cleanup_deref(&resource_deref);
-            return NULL;
+            return false;
         }
         hlsl_block_add_instr(block, store);
         hlsl_cleanup_deref(&resource_deref);
@@ -2206,13 +2204,13 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
                 if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc)))
                 {
                     hlsl_cleanup_deref(&deref);
-                    return NULL;
+                    return false;
                 }
 
                 if (!hlsl_new_store_component(ctx, &store_block, &deref, component, load))
                 {
                     hlsl_cleanup_deref(&deref);
-                    return NULL;
+                    return false;
                 }
                 hlsl_block_add_block(block, &store_block);
             }
@@ -2237,23 +2235,23 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
                 continue;
 
             if (!(c = hlsl_new_uint_constant(ctx, i, &lhs->loc)))
-                return NULL;
+                return false;
             hlsl_block_add_instr(block, c);
 
             if (!(cell = hlsl_new_index(ctx, &row->node, c, &lhs->loc)))
-                return NULL;
+                return false;
             hlsl_block_add_instr(block, cell);
 
             if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc)))
-                return NULL;
+                return false;
 
             if (!hlsl_init_deref_from_index_chain(ctx, &deref, cell))
-                return NULL;
+                return false;
 
             if (!(store = hlsl_new_store_index(ctx, &deref, NULL, load, 0, &rhs->loc)))
             {
                 hlsl_cleanup_deref(&deref);
-                return NULL;
+                return false;
             }
             hlsl_block_add_instr(block, store);
             hlsl_cleanup_deref(&deref);
@@ -2265,12 +2263,12 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
         struct hlsl_deref deref;
 
         if (!hlsl_init_deref_from_index_chain(ctx, &deref, lhs))
-            return NULL;
+            return false;
 
         if (!(store = hlsl_new_store_index(ctx, &deref, NULL, rhs, writemask, &rhs->loc)))
         {
             hlsl_cleanup_deref(&deref);
-            return NULL;
+            return false;
         }
         hlsl_block_add_instr(block, store);
         hlsl_cleanup_deref(&deref);
@@ -2280,9 +2278,9 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
      * splitting easier. Instead copy it here. Since we retrieve sources from
      * the last instruction in the list, we do need to copy. */
     if (!(copy = hlsl_new_copy(ctx, rhs)))
-        return NULL;
+        return false;
     hlsl_block_add_instr(block, copy);
-    return copy;
+    return true;
 }
 
 static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool decrement, bool post,
-- 
GitLab


From f73a23f735e099490fc27b80e7ee8515adb9534d Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 29 Aug 2024 12:48:23 -0500
Subject: [PATCH 3/8] vkd3d-shader/hlsl: Do not create a copy in
 add_assignment().

---
 libs/vkd3d-shader/hlsl.y | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index d6f794ec2e..5e622fcca7 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -2063,7 +2063,6 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc
         enum parse_assign_op assign_op, struct hlsl_ir_node *rhs)
 {
     struct hlsl_type *lhs_type = lhs->data_type;
-    struct hlsl_ir_node *copy;
     unsigned int writemask = 0, width = 0;
     bool matrix_writemask = false;
 
@@ -2274,12 +2273,7 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc
         hlsl_cleanup_deref(&deref);
     }
 
-    /* Don't use the instruction itself as a source, as this makes structure
-     * splitting easier. Instead copy it here. Since we retrieve sources from
-     * the last instruction in the list, we do need to copy. */
-    if (!(copy = hlsl_new_copy(ctx, rhs)))
-        return false;
-    hlsl_block_add_instr(block, copy);
+    block->value = rhs;
     return true;
 }
 
-- 
GitLab


From 010aa53bfa26c9c4c22138c135d76868849ecf59 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Fri, 20 Sep 2024 12:44:56 -0500
Subject: [PATCH 4/8] vkd3d-shader/hlsl: Do not handle
 HLSL_CLASS_CONSTANT_BUFFER in copy_propagation_transform_load().

---
 libs/vkd3d-shader/hlsl_codegen.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 4d44fc5ef1..6c908e0c5f 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -1655,11 +1655,11 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx,
         case HLSL_CLASS_MATRIX:
         case HLSL_CLASS_ARRAY:
         case HLSL_CLASS_STRUCT:
-        case HLSL_CLASS_CONSTANT_BUFFER:
             /* FIXME: Actually we shouldn't even get here, but we don't split
              * matrices yet. */
             return false;
 
+        case HLSL_CLASS_CONSTANT_BUFFER:
         case HLSL_CLASS_EFFECT_GROUP:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_TECHNIQUE:
-- 
GitLab


From 7daaaf63864ec1c5f5bbcf7da49524cf9d32177f Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Fri, 20 Sep 2024 13:57:53 -0500
Subject: [PATCH 5/8] vkd3d-shader/hlsl: Clarify a comment.

---
 libs/vkd3d-shader/hlsl_codegen.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 6c908e0c5f..9f77f2033a 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -1655,8 +1655,12 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx,
         case HLSL_CLASS_MATRIX:
         case HLSL_CLASS_ARRAY:
         case HLSL_CLASS_STRUCT:
-            /* FIXME: Actually we shouldn't even get here, but we don't split
-             * matrices yet. */
+            /* We can't handle complex types here.
+             * They should have been already split anyway by earlier passes,
+             * but they may not have been deleted yet. We can't rely on DCE to
+             * solve that problem for us, since we may be called on a partial
+             * block, but DCE deletes dead stores, so it needs to be able to
+             * see the whole program. */
             return false;
 
         case HLSL_CLASS_CONSTANT_BUFFER:
-- 
GitLab


From c43e5c8eb554c868cf4f56df14bc0d3ce02951d3 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 29 Aug 2024 12:48:23 -0500
Subject: [PATCH 6/8] vkd3d-shader/hlsl: Introduce the "error" type.

Currently, if an expression successfully parses according to the bison grammar,
but for one reason or another cannot generate a meaningful IR instruction, we
abort parsing with YYABORT. This includes, for example, an undefined variable or
function, invalid swizzle or field reference, or a constructor with a complex or
non-numeric data type.

Aborting parsing is unfortunate, however, because it means that any further
errors in the program cannot be caught by the programmer, increasing the number
of times they will need to fix errors and recompile.

The idea of this patch is that any such expression will instead generate an IR
node whose data type is of HLSL_CLASS_ERROR. Any further expression which would
consume an "error" typed instruction will instead immediately return an
expression of type "error" (probably the same one) instead of aborting or doing
any other type-checking.

Currently these "error" instructions should not pass the parsing stage, since
hlsl_compile_shader() will immediately notice that compilation has failed and
skip any optimization, lowering, or bytecode-writing.

A further direction to take this is to pre-allocate one "error" expression
immediately when creating the HLSL parser, and return that expression when we
fail to allocate an hlsl_ir_node of any type. This means we do not need to
handle allocation errors when constructing nodes, saving us quite a lot of error
handling (which is not only tedious but currently often broken, if nothing else
by virtue of neglecting cleanup of local variables).
---
 libs/vkd3d-shader/d3dbc.c        |  2 ++
 libs/vkd3d-shader/fx.c           |  2 ++
 libs/vkd3d-shader/hlsl.c         | 11 +++++++++++
 libs/vkd3d-shader/hlsl.h         |  2 ++
 libs/vkd3d-shader/hlsl_codegen.c |  1 +
 libs/vkd3d-shader/tpf.c          |  1 +
 6 files changed, 19 insertions(+)

diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c
index 693d86d346..c903d354db 100644
--- a/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d-shader/d3dbc.c
@@ -1522,6 +1522,7 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type)
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_RASTERIZER_STATE:
         case HLSL_CLASS_RENDER_TARGET_VIEW:
@@ -1627,6 +1628,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type)
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_RASTERIZER_STATE:
         case HLSL_CLASS_RENDER_TARGET_VIEW:
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c
index 1314bc09e7..7d4a9d2e2f 100644
--- a/libs/vkd3d-shader/fx.c
+++ b/libs/vkd3d-shader/fx.c
@@ -665,6 +665,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
 
         case HLSL_CLASS_ARRAY:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_TECHNIQUE:
         case HLSL_CLASS_CONSTANT_BUFFER:
@@ -1117,6 +1118,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type
             return false;
 
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_TECHNIQUE:
         case HLSL_CLASS_CONSTANT_BUFFER:
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 1bdca895c9..070168acff 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -276,6 +276,7 @@ bool hlsl_type_is_shader(const struct hlsl_type *type)
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_RASTERIZER_STATE:
         case HLSL_CLASS_RENDER_TARGET_VIEW:
@@ -418,6 +419,7 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_PIXEL_SHADER:
         case HLSL_CLASS_RASTERIZER_STATE:
@@ -494,6 +496,7 @@ static bool type_is_single_component(const struct hlsl_type *type)
     {
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PIXEL_SHADER:
         case HLSL_CLASS_SCALAR:
         case HLSL_CLASS_SAMPLER:
@@ -670,6 +673,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty
                 break;
 
             case HLSL_CLASS_EFFECT_GROUP:
+            case HLSL_CLASS_ERROR:
             case HLSL_CLASS_PASS:
             case HLSL_CLASS_TECHNIQUE:
             case HLSL_CLASS_VOID:
@@ -1061,6 +1065,7 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type)
 
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PIXEL_SHADER:
         case HLSL_CLASS_RASTERIZER_STATE:
         case HLSL_CLASS_RENDER_TARGET_VIEW:
@@ -1155,6 +1160,7 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_PIXEL_SHADER:
         case HLSL_CLASS_RASTERIZER_STATE:
@@ -2710,6 +2716,10 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru
             }
             return string;
 
+        case HLSL_CLASS_ERROR:
+            vkd3d_string_buffer_printf(string, "<error type>");
+            return string;
+
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
@@ -4146,6 +4156,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
     ctx->builtin_types.Void = hlsl_new_simple_type(ctx, "void", HLSL_CLASS_VOID);
     ctx->builtin_types.null = hlsl_new_type(ctx, "NULL", HLSL_CLASS_NULL, HLSL_TYPE_UINT, 1, 1);
     ctx->builtin_types.string = hlsl_new_simple_type(ctx, "string", HLSL_CLASS_STRING);
+    ctx->builtin_types.error = hlsl_new_simple_type(ctx, "<error type>", HLSL_CLASS_ERROR);
     hlsl_scope_add_type(ctx->globals, ctx->builtin_types.string);
     hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilView", HLSL_CLASS_DEPTH_STENCIL_VIEW));
     hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilState", HLSL_CLASS_DEPTH_STENCIL_STATE));
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 260b0da17f..f220aa469a 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -106,6 +106,7 @@ enum hlsl_type_class
     HLSL_CLASS_BLEND_STATE,
     HLSL_CLASS_VOID,
     HLSL_CLASS_NULL,
+    HLSL_CLASS_ERROR,
 };
 
 enum hlsl_base_type
@@ -1046,6 +1047,7 @@ struct hlsl_ctx
         struct hlsl_type *string;
         struct hlsl_type *Void;
         struct hlsl_type *null;
+        struct hlsl_type *error;
     } builtin_types;
 
     /* List of the instruction nodes for initializing static variables. */
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 9f77f2033a..feab6cf06c 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -1661,6 +1661,7 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx,
              * solve that problem for us, since we may be called on a partial
              * block, but DCE deletes dead stores, so it needs to be able to
              * see the whole program. */
+        case HLSL_CLASS_ERROR:
             return false;
 
         case HLSL_CLASS_CONSTANT_BUFFER:
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c
index 7b299f5e75..e09d91c586 100644
--- a/libs/vkd3d-shader/tpf.c
+++ b/libs/vkd3d-shader/tpf.c
@@ -3236,6 +3236,7 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type)
         case HLSL_CLASS_DEPTH_STENCIL_STATE:
         case HLSL_CLASS_DEPTH_STENCIL_VIEW:
         case HLSL_CLASS_EFFECT_GROUP:
+        case HLSL_CLASS_ERROR:
         case HLSL_CLASS_STRUCT:
         case HLSL_CLASS_PASS:
         case HLSL_CLASS_PIXEL_SHADER:
-- 
GitLab


From 7e3231c7496770dd3e50126ac38d9275207e90da Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 12 Sep 2024 21:42:46 -0500
Subject: [PATCH 7/8] vkd3d-shader/hlsl: Return an "error" expression when
 constructing an arithmetic expression from incompatible types.

---
 libs/vkd3d-shader/hlsl.c | 15 +++++++++++++++
 libs/vkd3d-shader/hlsl.h |  4 ++++
 libs/vkd3d-shader/hlsl.y |  6 +++++-
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 070168acff..f4401bc5d8 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -1635,6 +1635,16 @@ struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_ex
     return hlsl_new_expr(ctx, op, operands, arg1->data_type, &arg1->loc);
 }
 
+static struct hlsl_ir_node *hlsl_new_error_expr(struct hlsl_ctx *ctx)
+{
+    static const struct vkd3d_shader_location loc = {.source_name = "<error>"};
+    struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0};
+
+    /* Use a dummy location; we should never report any messages related to
+     * this expression. */
+    return hlsl_new_expr(ctx, HLSL_OP0_ERROR, operands, ctx->builtin_types.error, &loc);
+}
+
 struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition,
         struct hlsl_block *then_block, struct hlsl_block *else_block, const struct vkd3d_shader_location *loc)
 {
@@ -3059,6 +3069,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
 {
     static const char *const op_names[] =
     {
+        [HLSL_OP0_ERROR]        = "error",
         [HLSL_OP0_VOID]         = "void",
         [HLSL_OP0_RASTERIZER_SAMPLE_COUNT] = "GetRenderTargetSampleCount",
 
@@ -4279,6 +4290,10 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil
         }
     }
 
+    if (!(ctx->error_instr = hlsl_new_error_expr(ctx)))
+        return false;
+    hlsl_block_add_instr(&ctx->static_initializers, ctx->error_instr);
+
     ctx->domain = VKD3D_TESSELLATOR_DOMAIN_INVALID;
     ctx->output_control_point_count = UINT_MAX;
     ctx->output_primitive = 0;
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index f220aa469a..a0f3550efd 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -661,6 +661,7 @@ struct hlsl_ir_switch
 
 enum hlsl_ir_expr_op
 {
+    HLSL_OP0_ERROR,
     HLSL_OP0_VOID,
     HLSL_OP0_RASTERIZER_SAMPLE_COUNT,
 
@@ -1050,6 +1051,9 @@ struct hlsl_ctx
         struct hlsl_type *error;
     } builtin_types;
 
+    /* Pre-allocated "error" expression. */
+    struct hlsl_ir_node *error_instr;
+
     /* List of the instruction nodes for initializing static variables. */
     struct hlsl_block static_initializers;
 
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 5e622fcca7..2799c826e5 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -1756,7 +1756,11 @@ static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, str
     struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
     struct hlsl_type *common_type;
 
-    common_type = get_common_numeric_type(ctx, arg1, arg2, loc);
+    if (!(common_type = get_common_numeric_type(ctx, arg1, arg2, loc)))
+    {
+        block->value = ctx->error_instr;
+        return block->value;
+    }
 
     if (!(args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc)))
         return NULL;
-- 
GitLab


From 43b714d896f220671f87637da3e064e05eb514f5 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
Date: Thu, 29 Aug 2024 12:48:23 -0500
Subject: [PATCH 8/8] vkd3d-shader/hlsl: Handle error expressions in unary
 expressions.

---
 libs/vkd3d-shader/hlsl.y | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 2799c826e5..87be13dd64 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -1710,12 +1710,18 @@ static struct hlsl_ir_node *add_unary_arithmetic_expr(struct hlsl_ctx *ctx, stru
 {
     struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {arg};
 
+    if (arg->data_type->class == HLSL_CLASS_ERROR)
+        return arg;
+
     return add_expr(ctx, block, op, args, arg->data_type, loc);
 }
 
 static struct hlsl_ir_node *add_unary_bitwise_expr(struct hlsl_ctx *ctx, struct hlsl_block *block,
         enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
 {
+    if (arg->data_type->class == HLSL_CLASS_ERROR)
+        return arg;
+
     check_integer_type(ctx, arg);
 
     return add_unary_arithmetic_expr(ctx, block, op, arg, loc);
@@ -1727,6 +1733,9 @@ static struct hlsl_ir_node *add_unary_logical_expr(struct hlsl_ctx *ctx, struct
     struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0};
     struct hlsl_type *bool_type;
 
+    if (arg->data_type->class == HLSL_CLASS_ERROR)
+        return arg;
+
     bool_type = hlsl_get_numeric_type(ctx, arg->data_type->class, HLSL_TYPE_BOOL,
             arg->data_type->dimx, arg->data_type->dimy);
 
-- 
GitLab