[PATCH 5/5] d3dcompiler: Parse casts.

Matteo Bruni mbruni at codeweavers.com
Wed Sep 19 12:46:15 CDT 2012


---
 dlls/d3dcompiler_43/d3dcompiler_private.h |    3 +
 dlls/d3dcompiler_43/hlsl.y                |   29 ++++++++++++
 dlls/d3dcompiler_43/utils.c               |   68 +++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h
index b3a9586..22207c9 100644
--- a/dlls/d3dcompiler_43/d3dcompiler_private.h
+++ b/dlls/d3dcompiler_43/d3dcompiler_private.h
@@ -1080,8 +1080,11 @@ struct hlsl_type *clone_hlsl_type(struct hlsl_type *old) DECLSPEC_HIDDEN;
 struct hlsl_type *get_type(struct hlsl_scope *scope, const char *name, BOOL recursive) DECLSPEC_HIDDEN;
 BOOL find_function(const char *name) DECLSPEC_HIDDEN;
 unsigned int components_count_type(struct hlsl_type *type) DECLSPEC_HIDDEN;
+BOOL compatible_data_types(struct hlsl_type *s1, struct hlsl_type *s2) DECLSPEC_HIDDEN;
 struct hlsl_ir_expr *new_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node **operands,
         struct source_location *loc) DECLSPEC_HIDDEN;
+struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type,
+	struct source_location *loc) DECLSPEC_HIDDEN;
 struct hlsl_ir_expr *hlsl_mul(struct hlsl_ir_node *op1, struct hlsl_ir_node *op2,
         struct source_location *loc) DECLSPEC_HIDDEN;
 struct hlsl_ir_expr *hlsl_div(struct hlsl_ir_node *op1, struct hlsl_ir_node *op2,
diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y
index e8f33af..5670586 100644
--- a/dlls/d3dcompiler_43/hlsl.y
+++ b/dlls/d3dcompiler_43/hlsl.y
@@ -1472,6 +1472,35 @@ unary_expr:               postfix_expr
                                     $$ = &new_expr(ops[$1], operands, &loc)->node;
                                 }
                             }
+                          /* var_modifiers just to avoid shift/reduce conflicts */
+                        | '(' var_modifiers type array ')' unary_expr
+                            {
+                                struct hlsl_ir_expr *expr;
+                                struct hlsl_type *src_type = $6->data_type;
+                                struct hlsl_type *dst_type;
+                                struct source_location loc;
+
+                                set_location(&loc, &@3);
+                                if ($2)
+                                {
+                                    hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
+                                            "unexpected modifier in a cast");
+                                    return 1;
+                                }
+
+                                dst_type = $3;
+
+                                if (!compatible_data_types(src_type, dst_type))
+                                {
+                                    hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
+                                            "can't cast from %s to %s",
+                                            debug_hlsl_type(src_type), debug_hlsl_type(dst_type));
+                                    return 1;
+                                }
+
+                                expr = new_cast($6, dst_type, &loc);
+                                $$ = expr ? &expr->node : NULL;
+                            }
 
 unary_op:                 '+'
                             {
diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c
index 8aaa675..e0cac23 100644
--- a/dlls/d3dcompiler_43/utils.c
+++ b/dlls/d3dcompiler_43/utils.c
@@ -1031,6 +1031,60 @@ static BOOL convertible_data_type(struct hlsl_type *type)
     return type->type != HLSL_CLASS_OBJECT;
 }
 
+BOOL compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
+{
+   if (!convertible_data_type(t1) || !convertible_data_type(t2))
+        return FALSE;
+
+    if (t1->type <= HLSL_CLASS_LAST_NUMERIC)
+    {
+        /* Scalar vars can be cast to pretty much everything */
+        if (t1->dimx == 1 && t1->dimy == 1)
+            return TRUE;
+
+        if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR)
+            return t1->dimx >= t2->dimx;
+    }
+
+    /* The other way around is true too i.e. whatever to scalar */
+    if (t2->type <= HLSL_CLASS_LAST_NUMERIC && t2->dimx == 1 && t2->dimy == 1)
+        return TRUE;
+
+    if (t1->type == HLSL_CLASS_ARRAY)
+    {
+        if (compare_hlsl_types(t1->e.array.type, t2))
+            /* e.g. float4[3] to float4 is allowed */
+            return TRUE;
+
+        if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT)
+            return components_count_type(t1) >= components_count_type(t2);
+        else
+            return components_count_type(t1) == components_count_type(t2);
+    }
+
+    if (t1->type == HLSL_CLASS_STRUCT)
+        return components_count_type(t1) >= components_count_type(t2);
+
+    if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT)
+        return components_count_type(t1) == components_count_type(t2);
+
+    if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX)
+    {
+        if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy)
+            return TRUE;
+
+        /* Matrix-vector conversion is apparently allowed if they have the same components count */
+        if ((t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR)
+                && components_count_type(t1) == components_count_type(t2))
+            return TRUE;
+        return FALSE;
+    }
+
+    if (components_count_type(t1) >= components_count_type(t2))
+        return TRUE;
+    return FALSE;
+}
+
 static BOOL implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
 {
     if (!convertible_data_type(t1) || !convertible_data_type(t2))
@@ -1322,6 +1376,20 @@ struct hlsl_ir_expr *new_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node **ope
     return expr;
 }
 
+struct hlsl_ir_expr *new_cast(struct hlsl_ir_node *node, struct hlsl_type *type,
+        struct source_location *loc)
+{
+    struct hlsl_ir_expr *cast;
+    struct hlsl_ir_node *operands[3];
+
+    operands[0] = node;
+    operands[1] = operands[2] = NULL;
+    cast = new_expr(HLSL_IR_UNOP_CAST, operands, loc);
+    if (cast)
+        cast->node.data_type = type;
+    return cast;
+}
+
 struct hlsl_ir_expr *hlsl_mul(struct hlsl_ir_node *op1, struct hlsl_ir_node *op2,
         struct source_location *loc)
 {
-- 
1.7.8.6




More information about the wine-patches mailing list