X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fglsl%2Fir.cpp;h=e3134eaa1c8e68b9cd5f697a3035220bc892a3b0;hb=dbf5b772b3b5f962c3186dd0073146539ec0586b;hp=356eb0fbcfdf67745eb043f227364aafc287ec03;hpb=ce55afc4d6d3d97440856cad117d02c20fb952a9;p=mesa.git diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp index 356eb0fbcfd..e3134eaa1c8 100644 --- a/src/compiler/glsl/ir.cpp +++ b/src/compiler/glsl/ir.cpp @@ -21,9 +21,10 @@ * DEALINGS IN THE SOFTWARE. */ #include -#include "main/core.h" /* for MAX2 */ #include "ir.h" #include "compiler/glsl_types.h" +#include "glsl_parser_extras.h" + ir_rvalue::ir_rvalue(enum ir_node_type t) : ir_instruction(t) @@ -201,11 +202,16 @@ ir_expression::ir_expression(int op, const struct glsl_type *type, this->operands[1] = op1; this->operands[2] = op2; this->operands[3] = op3; + init_num_operands(); + #ifndef NDEBUG - int num_operands = get_num_operands(this->operation); - for (int i = num_operands; i < 4; i++) { + for (unsigned i = num_operands; i < 4; i++) { assert(this->operands[i] == NULL); } + + for (unsigned i = 0; i < num_operands; i++) { + assert(this->operands[i] != NULL); + } #endif } @@ -219,6 +225,9 @@ ir_expression::ir_expression(int op, ir_rvalue *op0) this->operands[3] = NULL; assert(op <= ir_last_unop); + init_num_operands(); + assert(num_operands == 1); + assert(this->operands[0]); switch (this->operation) { case ir_unop_bit_not: @@ -368,6 +377,16 @@ ir_expression::ir_expression(int op, ir_rvalue *op0) this->type = glsl_type::vec4_type; break; + case ir_unop_unpack_sampler_2x32: + case ir_unop_unpack_image_2x32: + this->type = glsl_type::uvec2_type; + break; + + case ir_unop_pack_sampler_2x32: + case ir_unop_pack_image_2x32: + this->type = op0->type; + break; + case ir_unop_frexp_sig: this->type = op0->type; break; @@ -413,6 +432,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1) this->operands[3] = NULL; assert(op > ir_last_unop); + init_num_operands(); + assert(num_operands == 2); + for (unsigned i = 0; i < num_operands; i++) { + assert(this->operands[i] != NULL); + } switch (this->operation) { case ir_binop_all_equal: @@ -462,10 +486,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1) case ir_binop_equal: case ir_binop_nequal: - case ir_binop_lequal: case ir_binop_gequal: case ir_binop_less: - case ir_binop_greater: assert(op0->type == op1->type); this->type = glsl_type::get_instance(GLSL_TYPE_BOOL, op0->type->vector_elements, 1); @@ -507,6 +529,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, this->operands[3] = NULL; assert(op > ir_last_binop && op <= ir_last_triop); + init_num_operands(); + assert(num_operands == 3); + for (unsigned i = 0; i < num_operands; i++) { + assert(this->operands[i] != NULL); + } switch (this->operation) { case ir_triop_fma: @@ -526,7 +553,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, } } -unsigned int +/** + * This is only here for ir_reader to used for testing purposes. Please use + * the precomputed num_operands field if you need the number of operands. + */ +unsigned ir_expression::get_num_operands(ir_expression_operation op) { assert(op <= ir_last_opcode); @@ -543,8 +574,7 @@ ir_expression::get_num_operands(ir_expression_operation op) if (op <= ir_last_quadop) return 4; - assert(false); - return 0; + unreachable("Could not calculate number of operands"); } #include "ir_expression_operation_strings.h" @@ -594,17 +624,17 @@ ir_expression::variable_referenced() const ir_constant::ir_constant() : ir_rvalue(ir_type_constant) { - this->array_elements = NULL; + this->const_elements = NULL; } ir_constant::ir_constant(const struct glsl_type *type, const ir_constant_data *data) : ir_rvalue(ir_type_constant) { - this->array_elements = NULL; + this->const_elements = NULL; assert((type->base_type >= GLSL_TYPE_UINT) - && (type->base_type <= GLSL_TYPE_BOOL)); + && (type->base_type <= GLSL_TYPE_IMAGE)); this->type = type; memcpy(& this->value, data, sizeof(this->value)); @@ -704,7 +734,7 @@ ir_constant::ir_constant(bool b, unsigned vector_elements) ir_constant::ir_constant(const ir_constant *c, unsigned i) : ir_rvalue(ir_type_constant) { - this->array_elements = NULL; + this->const_elements = NULL; this->type = c->type->get_base_type(); switch (this->type->base_type) { @@ -720,34 +750,25 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i) ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) : ir_rvalue(ir_type_constant) { - this->array_elements = NULL; + this->const_elements = NULL; this->type = type; assert(type->is_scalar() || type->is_vector() || type->is_matrix() || type->is_record() || type->is_array()); - if (type->is_array()) { - this->array_elements = ralloc_array(this, ir_constant *, type->length); - unsigned i = 0; - foreach_in_list(ir_constant, value, value_list) { - assert(value->as_constant() != NULL); - - this->array_elements[i++] = value; - } - return; - } - /* If the constant is a record, the types of each of the entries in * value_list must be a 1-for-1 match with the structure components. Each * entry must also be a constant. Just move the nodes from the value_list * to the list in the ir_constant. */ - /* FINISHME: Should there be some type checking and / or assertions here? */ - /* FINISHME: Should the new constant take ownership of the nodes from - * FINISHME: value_list, or should it make copies? - */ - if (type->is_record()) { - value_list->move_nodes_to(& this->components); + if (type->is_array() || type->is_record()) { + this->const_elements = ralloc_array(this, ir_constant *, type->length); + unsigned i = 0; + foreach_in_list(ir_constant, value, value_list) { + assert(value->as_constant() != NULL); + + this->const_elements[i++] = value; + } return; } @@ -891,16 +912,18 @@ ir_constant::zero(void *mem_ctx, const glsl_type *type) memset(&c->value, 0, sizeof(c->value)); if (type->is_array()) { - c->array_elements = ralloc_array(c, ir_constant *, type->length); + c->const_elements = ralloc_array(c, ir_constant *, type->length); for (unsigned i = 0; i < type->length; i++) - c->array_elements[i] = ir_constant::zero(c, type->fields.array); + c->const_elements[i] = ir_constant::zero(c, type->fields.array); } if (type->is_record()) { + c->const_elements = ralloc_array(c, ir_constant *, type->length); + for (unsigned i = 0; i < type->length; i++) { - ir_constant *comp = ir_constant::zero(mem_ctx, type->fields.structure[i].type); - c->components.push_tail(comp); + c->const_elements[i] = + ir_constant::zero(mem_ctx, type->fields.structure[i].type); } } @@ -1067,32 +1090,16 @@ ir_constant::get_array_element(unsigned i) const else if (i >= this->type->length) i = this->type->length - 1; - return array_elements[i]; + return const_elements[i]; } ir_constant * -ir_constant::get_record_field(const char *name) +ir_constant::get_record_field(int idx) { - int idx = this->type->field_index(name); + assert(this->type->is_record()); + assert(idx >= 0 && (unsigned) idx < this->type->length); - if (idx < 0) - return NULL; - - if (this->components.is_empty()) - return NULL; - - exec_node *node = this->components.get_head_raw(); - for (int i = 0; i < idx; i++) { - node = node->next; - - /* If the end of the list is encountered before the element matching the - * requested field is found, return NULL. - */ - if (node->is_tail_sentinel()) - return NULL; - } - - return (ir_constant *) node; + return const_elements[idx]; } void @@ -1138,19 +1145,11 @@ ir_constant::copy_offset(ir_constant *src, int offset) break; } - case GLSL_TYPE_STRUCT: { - assert (src->type == this->type); - this->components.make_empty(); - foreach_in_list(ir_constant, orig, &src->components) { - this->components.push_tail(orig->clone(this, NULL)); - } - break; - } - + case GLSL_TYPE_STRUCT: case GLSL_TYPE_ARRAY: { assert (src->type == this->type); for (unsigned i = 0; i < this->type->length; i++) { - this->array_elements[i] = src->array_elements[i]->clone(this, NULL); + this->const_elements[i] = src->const_elements[i]->clone(this, NULL); } break; } @@ -1210,34 +1209,14 @@ ir_constant::has_value(const ir_constant *c) const if (this->type != c->type) return false; - if (this->type->is_array()) { + if (this->type->is_array() || this->type->is_record()) { for (unsigned i = 0; i < this->type->length; i++) { - if (!this->array_elements[i]->has_value(c->array_elements[i])) + if (!this->const_elements[i]->has_value(c->const_elements[i])) return false; } return true; } - if (this->type->is_record()) { - const exec_node *a_node = this->components.get_head_raw(); - const exec_node *b_node = c->components.get_head_raw(); - - while (!a_node->is_tail_sentinel()) { - assert(!b_node->is_tail_sentinel()); - - const ir_constant *const a_field = (ir_constant *) a_node; - const ir_constant *const b_field = (ir_constant *) b_node; - - if (!a_field->has_value(b_field)) - return false; - - a_node = a_node->next; - b_node = b_node->next; - } - - return true; - } - for (unsigned i = 0; i < this->type->components(); i++) { switch (this->type->base_type) { case GLSL_TYPE_UINT: @@ -1419,8 +1398,8 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value, assert(value != NULL); this->record = value; - this->field = ralloc_strdup(this, field); this->type = this->record->type->field_type(field); + this->field_idx = this->record->type->field_index(field); } @@ -1431,12 +1410,12 @@ ir_dereference_record::ir_dereference_record(ir_variable *var, void *ctx = ralloc_parent(var); this->record = new(ctx) ir_dereference_variable(var); - this->field = ralloc_strdup(this, field); this->type = this->record->type->field_type(field); + this->field_idx = this->record->type->field_index(field); } bool -ir_dereference::is_lvalue() const +ir_dereference::is_lvalue(const struct _mesa_glsl_parse_state *state) const { ir_variable *var = this->variable_referenced(); @@ -1445,6 +1424,20 @@ ir_dereference::is_lvalue() const if ((var == NULL) || var->data.read_only) return false; + /* From section 4.1.7 of the ARB_bindless_texture spec: + * + * "Samplers can be used as l-values, so can be assigned into and used as + * "out" and "inout" function parameters." + * + * From section 4.1.X of the ARB_bindless_texture spec: + * + * "Images can be used as l-values, so can be assigned into and used as + * "out" and "inout" function parameters." + */ + if ((!state || state->has_bindless()) && + (this->type->contains_sampler() || this->type->contains_image())) + return true; + /* From section 4.1.7 of the GLSL 4.40 spec: * * "Opaque variables cannot be treated as l-values; hence cannot @@ -1564,10 +1557,8 @@ ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp, } ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask) - : ir_rvalue(ir_type_swizzle) + : ir_rvalue(ir_type_swizzle), val(val), mask(mask) { - this->val = val; - this->mask = mask; this->type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1); } @@ -1722,18 +1713,17 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->data.max_array_access = -1; this->data.offset = 0; this->data.precision = GLSL_PRECISION_NONE; - this->data.image_read_only = false; - this->data.image_write_only = false; - this->data.image_coherent = false; - this->data.image_volatile = false; - this->data.image_restrict = false; + this->data.memory_read_only = false; + this->data.memory_write_only = false; + this->data.memory_coherent = false; + this->data.memory_volatile = false; + this->data.memory_restrict = false; this->data.from_ssbo_unsized_array = false; this->data.fb_fetch_output = false; + this->data.bindless = false; + this->data.bound = false; if (type != NULL) { - if (type->is_sampler()) - this->data.read_only = true; - if (type->is_interface()) this->init_interface_type(type); else if (type->without_array()->is_interface()) @@ -1846,11 +1836,11 @@ ir_function_signature::qualifiers_match(exec_list *params) a->data.centroid != b->data.centroid || a->data.sample != b->data.sample || a->data.patch != b->data.patch || - a->data.image_read_only != b->data.image_read_only || - a->data.image_write_only != b->data.image_write_only || - a->data.image_coherent != b->data.image_coherent || - a->data.image_volatile != b->data.image_volatile || - a->data.image_restrict != b->data.image_restrict) { + a->data.memory_read_only != b->data.memory_read_only || + a->data.memory_write_only != b->data.memory_write_only || + a->data.memory_coherent != b->data.memory_coherent || + a->data.memory_volatile != b->data.memory_volatile || + a->data.memory_restrict != b->data.memory_restrict) { /* parameter a's qualifiers don't match */ return a->name; @@ -1927,15 +1917,10 @@ steal_memory(ir_instruction *ir, void *new_ctx) /* The components of aggregate constants are not visited by the normal * visitor, so steal their values by hand. */ - if (constant != NULL) { - if (constant->type->is_record()) { - foreach_in_list(ir_constant, field, &constant->components) { - steal_memory(field, ir); - } - } else if (constant->type->is_array()) { - for (unsigned int i = 0; i < constant->type->length; i++) { - steal_memory(constant->array_elements[i], ir); - } + if (constant != NULL && + (constant->type->is_array() || constant->type->is_record())) { + for (unsigned int i = 0; i < constant->type->length; i++) { + steal_memory(constant->const_elements[i], ir); } }