From ca701b7d69c97e667973449e22a8fb6d4c44790b Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Wed, 19 Sep 2012 19:46:15 +0200 Subject: [PATCH] d3dcompiler: Parse casts. --- dlls/d3dcompiler_43/d3dcompiler_private.h | 3 + dlls/d3dcompiler_43/hlsl.y | 29 ++++++++++ dlls/d3dcompiler_43/utils.c | 68 +++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index b3a9586f69c..22207c93f6c 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 e8f33af8c33..5670586efb8 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 8aaa6751433..e0cac23f67c 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) {