From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 168 ++++++++++++++++++++++++++------------- 1 file changed, 114 insertions(+), 54 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 194d21f4..9ae36cc0 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1141,54 +1141,130 @@ static struct list *make_list(struct hlsl_ctx *ctx, struct hlsl_ir_node *node) return list; }
-static unsigned int evaluate_static_expression(struct hlsl_ir_node *node) +struct static_expr_value { - if (node->data_type->class != HLSL_CLASS_SCALAR) - return 0; + enum hlsl_base_type type; + union hlsl_constant_value v; +}; + +static int static_expr_value_as_int(const struct static_expr_value *value) +{ + switch (value->type) + { + case HLSL_TYPE_DOUBLE: + return value->v.d; + case HLSL_TYPE_FLOAT: + return value->v.f; + case HLSL_TYPE_INT: + return value->v.i; + case HLSL_TYPE_UINT: + return value->v.u; + default: + vkd3d_unreachable(); + } +} + +static unsigned int static_expr_value_as_uint(const struct static_expr_value *value) +{ + switch (value->type) + { + case HLSL_TYPE_DOUBLE: + return value->v.d; + case HLSL_TYPE_FLOAT: + return value->v.f; + case HLSL_TYPE_INT: + return value->v.i; + case HLSL_TYPE_UINT: + return value->v.u; + default: + vkd3d_unreachable(); + } +} + +static void static_expr_get_value(enum hlsl_ir_expr_op op, const struct static_expr_value *operands, + struct static_expr_value *ret) +{ + switch (op) + { + case HLSL_OP2_ADD: + switch (ret->type) + { + case HLSL_TYPE_INT: + ret->v.i = static_expr_value_as_int(&operands[0]) + static_expr_value_as_int(&operands[1]); + break; + default: + FIXME("Unsupported 'add' for type %u.\n", ret->type); + } + break; + case HLSL_OP2_MUL: + switch (ret->type) + { + case HLSL_TYPE_INT: + ret->v.i = static_expr_value_as_int(&operands[0]) * static_expr_value_as_int(&operands[1]); + break; + default: + FIXME("Unsupported 'mul' for type %u.\n", ret->type); + } + break; + default: + FIXME("Unsupported expression op %u.\n", op); + } +} + +static enum hlsl_base_type expr_common_base_type(enum hlsl_base_type t1, enum hlsl_base_type t2) +{ + if (t1 > HLSL_TYPE_LAST_SCALAR || t2 > HLSL_TYPE_LAST_SCALAR) { + FIXME("Unexpected base type.\n"); + return HLSL_TYPE_FLOAT; + } + if (t1 == t2) + return t1 == HLSL_TYPE_BOOL ? HLSL_TYPE_INT : t1; + if (t1 == HLSL_TYPE_DOUBLE || t2 == HLSL_TYPE_DOUBLE) + return HLSL_TYPE_DOUBLE; + if (t1 == HLSL_TYPE_FLOAT || t2 == HLSL_TYPE_FLOAT + || t1 == HLSL_TYPE_HALF || t2 == HLSL_TYPE_HALF) + return HLSL_TYPE_FLOAT; + if (t1 == HLSL_TYPE_UINT || t2 == HLSL_TYPE_UINT) + return HLSL_TYPE_UINT; + return HLSL_TYPE_INT; +} + +static struct static_expr_value evaluate_static_expression(const struct hlsl_ir_node *node) +{ + struct static_expr_value operands[HLSL_MAX_OPERANDS] = { 0 }, ret = { 0 };
switch (node->type) { case HLSL_IR_CONSTANT: { struct hlsl_ir_constant *constant = hlsl_ir_constant(node); - const union hlsl_constant_value *value = &constant->value[0]; - - switch (constant->node.data_type->base_type) + ret.type = constant->node.data_type->base_type; + ret.v = constant->value[0]; + break; + } + case HLSL_IR_EXPR: + { + struct hlsl_ir_expr *expr = hlsl_ir_expr(node); + switch (expr->op) { - case HLSL_TYPE_UINT: - return value->u; - case HLSL_TYPE_INT: - return value->i; - case HLSL_TYPE_FLOAT: - case HLSL_TYPE_HALF: - return value->f; - case HLSL_TYPE_DOUBLE: - return value->d; - case HLSL_TYPE_BOOL: - return !!value->u; + case HLSL_OP2_ADD: + case HLSL_OP2_MUL: + operands[0] = evaluate_static_expression(expr->operands[0].node); + operands[1] = evaluate_static_expression(expr->operands[1].node); + ret.type = expr_common_base_type(operands[0].type, operands[1].type); + static_expr_get_value(expr->op, operands, &ret); + break; default: - vkd3d_unreachable(); + FIXME("Unhandled op %u.\n", expr->op); + return ret; } + break; } - - case HLSL_IR_EXPR: - case HLSL_IR_INDEX: - case HLSL_IR_LOAD: - case HLSL_IR_RESOURCE_LOAD: - case HLSL_IR_SWIZZLE: + default: FIXME("Unhandled type %s.\n", hlsl_node_type_to_string(node->type)); - return 0; - - case HLSL_IR_CALL: - case HLSL_IR_IF: - case HLSL_IR_JUMP: - case HLSL_IR_LOOP: - case HLSL_IR_RESOURCE_STORE: - case HLSL_IR_STORE: - vkd3d_unreachable(); }
- vkd3d_unreachable(); + return ret; }
static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) @@ -1225,24 +1301,6 @@ static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t return false; }
-static enum hlsl_base_type expr_common_base_type(enum hlsl_base_type t1, enum hlsl_base_type t2) -{ - if (t1 > HLSL_TYPE_LAST_SCALAR || t2 > HLSL_TYPE_LAST_SCALAR) { - FIXME("Unexpected base type.\n"); - return HLSL_TYPE_FLOAT; - } - if (t1 == t2) - return t1 == HLSL_TYPE_BOOL ? HLSL_TYPE_INT : t1; - if (t1 == HLSL_TYPE_DOUBLE || t2 == HLSL_TYPE_DOUBLE) - return HLSL_TYPE_DOUBLE; - if (t1 == HLSL_TYPE_FLOAT || t2 == HLSL_TYPE_FLOAT - || t1 == HLSL_TYPE_HALF || t2 == HLSL_TYPE_HALF) - return HLSL_TYPE_FLOAT; - if (t1 == HLSL_TYPE_UINT || t2 == HLSL_TYPE_UINT) - return HLSL_TYPE_UINT; - return HLSL_TYPE_INT; -} - static bool expr_common_shape(struct hlsl_ctx *ctx, struct hlsl_type *t1, struct hlsl_type *t2, const struct vkd3d_shader_location *loc, enum hlsl_type_class *type, unsigned int *dimx, unsigned int *dimy) { @@ -4917,7 +4975,8 @@ type_no_void: } | texture_ms_type '<' type ',' shift_expr '>' { - unsigned int sample_count = evaluate_static_expression(node_from_list($5)); + struct static_expr_value value = evaluate_static_expression(node_from_list($5)); + unsigned int sample_count = static_expr_value_as_uint(&value); destroy_instr_list($5);
$$ = hlsl_new_texture_type(ctx, $1, $3, sample_count); @@ -5111,7 +5170,8 @@ arrays: } | '[' expr ']' arrays { - unsigned int size = evaluate_static_expression(node_from_list($2)); + struct static_expr_value value = evaluate_static_expression(node_from_list($2)); + unsigned int size = static_expr_value_as_uint(&value); uint32_t *new_array;
destroy_instr_list($2);