示例#1
0
static nir_instr *
worklist_pop(struct exec_list *worklist)
{
   struct exec_node *node = exec_list_pop_head(worklist);
   worklist_elem *elem = exec_node_data(worklist_elem, node, node);
   return elem->instr;
}
示例#2
0
static nir_block *
get_src_block(nir_src *src)
{
   if (src->parent_instr->type == nir_instr_type_phi) {
      return exec_node_data(nir_phi_src, src, src)->pred;
   } else {
      return src->parent_instr->block;
   }
}
static unsigned
process_parameters(exec_list *instructions, exec_list *actual_parameters,
		   exec_list *parameters,
		   struct _mesa_glsl_parse_state *state)
{
   unsigned count = 0;

   foreach_list (n, parameters) {
      ast_node *const ast = exec_node_data(ast_node, n, link);
      ir_rvalue *result = ast->hir(instructions, state);

      ir_constant *const constant = result->constant_expression_value();
      if (constant != NULL)
	 result = constant;

      actual_parameters->push_tail(result);
      count++;
   }
示例#4
0
static bool
dead_cf_list(struct exec_list *list, bool *list_ends_in_jump)
{
   bool progress = false;
   *list_ends_in_jump = false;

   nir_cf_node *prev = NULL;

   foreach_list_typed(nir_cf_node, cur, node, list) {
      switch (cur->type) {
      case nir_cf_node_block: {
         nir_block *block = nir_cf_node_as_block(cur);
         if (dead_cf_block(block)) {
            /* We just deleted the if or loop after this block, so we may have
             * deleted the block before or after it -- which one is an
             * implementation detail. Therefore, to recover the place we were
             * at, we have to use the previous cf_node.
             */

            if (prev) {
               cur = nir_cf_node_next(prev);
            } else {
               cur = exec_node_data(nir_cf_node, exec_list_get_head(list),
                                    node);
            }

            block = nir_cf_node_as_block(cur);

            progress = true;
         }

         if (ends_in_jump(block)) {
            *list_ends_in_jump = true;

            if (!exec_node_is_tail_sentinel(cur->node.next)) {
               remove_after_cf_node(cur);
               return true;
            }
         }

         break;
      }

      case nir_cf_node_if: {
         nir_if *if_stmt = nir_cf_node_as_if(cur);
         bool then_ends_in_jump, else_ends_in_jump;
         progress |= dead_cf_list(&if_stmt->then_list, &then_ends_in_jump);
         progress |= dead_cf_list(&if_stmt->else_list, &else_ends_in_jump);

         if (then_ends_in_jump && else_ends_in_jump) {
            *list_ends_in_jump = true;
            nir_block *next = nir_cf_node_as_block(nir_cf_node_next(cur));
            if (!exec_list_is_empty(&next->instr_list) ||
                !exec_node_is_tail_sentinel(next->cf_node.node.next)) {
               remove_after_cf_node(cur);
               return true;
            }
         }

         break;
      }

      case nir_cf_node_loop: {
         nir_loop *loop = nir_cf_node_as_loop(cur);
         bool dummy;
         progress |= dead_cf_list(&loop->body, &dummy);

         break;
      }

      default:
         unreachable("unknown cf node type");
      }

      prev = cur;
   }

   return progress;
}
示例#5
0
ir_rvalue * _mesa_ast_field_selection_to_hir(const ast_expression *expr,
	exec_list *instructions, struct _mesa_glsl_parse_state *state)
{
	void *ctx = state;
	ir_rvalue *result = NULL;
	ir_rvalue *op;

	op = expr->subexpressions[0]->hir(instructions, state);

	/* There are two kinds of field selection.  There is the selection of a
	* specific field from a structure, and there is the selection of a
	* swizzle / mask from a vector.  Which is which is determined entirely
	* by the base type of the thing to which the field selection operator is
	* being applied.
	*/
	YYLTYPE loc = expr->get_location();
	if (op->type->is_error())
	{
		/* silently propagate the error */
	}
	else if (op->type->is_vector() || op->type->is_scalar())
	{
		ir_swizzle *swiz = ir_swizzle::create(op,
			expr->primary_expression.identifier,
			op->type->vector_elements);
		if (swiz != NULL)
		{
			result = swiz;
		}
		else
		{
			/* FINISHME: Logging of error messages should be moved into
			* FINISHME: ir_swizzle::create.  This allows the generation of more
			* FINISHME: specific error messages.
			*/
			_mesa_glsl_error(& loc, state, "Invalid swizzle / mask '%s'",
				expr->primary_expression.identifier);
		}
	}
	else if (op->type->is_matrix() && expr->primary_expression.identifier)
	{
		int src_components = op->type->components();
		int components[4] = {0};
		uint32 num_components = 0;
		ir_swizzle_mask mask = {0};
		const char* mask_str = expr->primary_expression.identifier;
		if (mask_str[0] == '_' && mask_str[1] == 'm')
		{
			do
			{
				mask_str += 2;
				int col = (*mask_str) ? (*mask_str++) - '0' : -1;
				int row = (*mask_str) ? (*mask_str++) - '0' : -1;

				if (col >= 0 && col <= op->type->matrix_columns &&
					row >= 0 && row <= op->type->vector_elements)
				{
					components[num_components++] = col * op->type->vector_elements + row;
				}
				else
				{
					components[num_components++] = -1;
				}
			} while (*mask_str != 0 && num_components < 4);
		}
		else if (mask_str[0] == '_' && mask_str[1] >= '1' && mask_str[2] <= '4')
		{
			do
			{
				mask_str += 1;
				int col = (*mask_str) ? (*mask_str++) - '1' : -1;
				int row = (*mask_str) ? (*mask_str++) - '1' : -1;

				if (col >= 0 && col <= op->type->matrix_columns &&
					row >= 0 && row <= op->type->vector_elements)
				{
					components[num_components++] = col * op->type->vector_elements + row;
				}
				else
				{
					components[num_components++] = -1;
				}
			} while (*mask_str != 0 && num_components < 4);
		}

		if (*mask_str == 0)
		{
			if (num_components > 0 && components[0] >= 0 && components[0] <= src_components)
			{
				mask.x = (unsigned)components[0];
				mask.num_components++;
			}
			if (num_components > 1 && components[1] >= 0 && components[1] <= src_components)
			{
				mask.y = (unsigned)components[1];
				mask.has_duplicates = (mask.y == mask.x);
				mask.num_components++;
			}
			if (num_components > 2 && components[2] >= 0 && components[2] <= src_components)
			{
				mask.z = (unsigned)components[2];
				mask.has_duplicates = mask.has_duplicates || (mask.z == mask.y) || (mask.z == mask.x);
				mask.num_components++;
			}
			if (num_components > 3 && components[3] >= 0 && components[3] <= src_components)
			{
				mask.w = (unsigned)components[3];
				mask.has_duplicates = mask.has_duplicates || (mask.w == mask.z) ||
					(mask.w == mask.y) || (mask.w == mask.x);
				mask.num_components++;
			}
		}

		if (mask.num_components == num_components)
		{
			result = new(ctx)ir_swizzle(op, mask);
		}

		if (result == NULL)
		{
			_mesa_glsl_error(&loc, state, "invalid matrix swizzle '%s'",
				expr->primary_expression.identifier);
		}
	}
	else if (op->type->base_type == GLSL_TYPE_STRUCT)
	{
		result = new(ctx)ir_dereference_record(op,
			expr->primary_expression.identifier);

		if (result->type->is_error())
		{
			_mesa_glsl_error(& loc, state, "Cannot access field '%s' of "
				"structure",
				expr->primary_expression.identifier);
		}
	}
	else if (expr->subexpressions[1] != NULL)
	{
		/* Handle "method calls" in GLSL 1.20+ */
		if (state->language_version < 120)
			_mesa_glsl_error(&loc, state, "Methods not supported in GLSL 1.10.");

		ast_expression *call = expr->subexpressions[1];
		check(call->oper == ast_function_call);

		const char *method;
		method = call->subexpressions[0]->primary_expression.identifier;

		if (op->type->is_array() && strcmp(method, "length") == 0)
		{
			if (!call->expressions.is_empty())
				_mesa_glsl_error(&loc, state, "length method takes no arguments.");

			if (op->type->array_size() == 0)
				_mesa_glsl_error(&loc, state, "length called on unsized array.");

			result = new(ctx)ir_constant(op->type->array_size());
		}
		else if (op->type->is_sampler() && op->as_dereference() != NULL)
		{
			return gen_texture_op(expr, op->as_dereference(), instructions, state);
		}
		else if (op->type->is_image() && op->as_dereference() != NULL)
		{
			return gen_image_op(expr, op->as_dereference(), instructions, state);
		}
		else if (op->type->is_outputstream() && strcmp(method, "Append") == 0)
		{
			check(op->variable_referenced()->type->inner_type->is_record());
			check(op->variable_referenced()->type->inner_type->name);

			const char* function_name = "OutputStream_Append";

			ir_function *func = state->symbols->get_function(function_name);
			if (!func)
			{
				// Prepare the function, add it to global symbols. It will be added to declarations at GenerateGlslMain().
				func = new(ctx)ir_function(function_name);
				state->symbols->add_global_function(func);

				//				_mesa_glsl_warning(state, "Append function generation for type '%s'", op->variable_referenced()->type->inner_type->name );
				//				{
				//					const glsl_type* output_type = op->variable_referenced()->type->inner_type;
				//					for (int i = 0; i < output_type->length; i++)
				//					{
				//						_mesa_glsl_warning(state, "   name '%s' : semantic '%s'", output_type->fields.structure[i].name, output_type->fields.structure[i].semantic );
				//					}
				//				}
			}

			exec_list comparison_parameter;
			ir_variable* var = new(ctx)ir_variable(op->variable_referenced()->type->inner_type, ralloc_asprintf(ctx, "arg0"), ir_var_in);
			comparison_parameter.push_tail(var);

			bool is_exact = false;
			ir_function_signature *sig = func->matching_signature(&comparison_parameter, &is_exact);
			if (!sig || !is_exact)
			{
				sig = new(ctx)ir_function_signature(glsl_type::void_type);
				sig->parameters.push_tail(var);
				sig->is_builtin = false;
				sig->is_defined = true;
				func->add_signature(sig);
			}

			if (call->expressions.is_empty() || (call->expressions.get_head() != call->expressions.get_tail()))
			{
				_mesa_glsl_error(&loc, state, "Append method takes one argument.");
			}
			else
			{
				exec_list actual_parameter;
				ast_node *const ast = exec_node_data(ast_node, call->expressions.get_head(), link);
				ir_rvalue *result = ast->hir(instructions, state);
				actual_parameter.push_tail(result);

				instructions->push_tail(new(ctx)ir_call(sig, NULL, &actual_parameter));
			}

			return NULL;
		}
		else if (op->type->is_outputstream() && strcmp(method, "RestartStrip") == 0)
		{
			exec_list actual_parameters;	// empty, as no parameters

			ir_function *func = state->symbols->get_function("EndPrimitive");
			check(func);

			bool is_exact = false;
			ir_function_signature *sig = func->matching_signature(&actual_parameters, &is_exact);
			check(sig && is_exact);

			instructions->push_tail(new(ctx)ir_call(sig, NULL, &actual_parameters));

			return NULL;
		}
		else
		{
			_mesa_glsl_error(&loc, state, "Unknown method: '%s'.", method);
		}
	}
	else
	{
		_mesa_glsl_error(& loc, state, "Cannot access field '%s' of "
			"non-structure / non-vector.",
			expr->primary_expression.identifier);
	}

	return result ? result : ir_rvalue::error_value(ctx);
}
示例#6
0
文件: ast_type.cpp 项目: Haifen/mesa
bool
ast_layout_expression::process_qualifier_constant(struct _mesa_glsl_parse_state *state,
                                                  const char *qual_indentifier,
                                                  unsigned *value,
                                                  bool can_be_zero,
                                                  bool must_match)
{
   int min_value = 0;
   bool first_pass = true;
   *value = 0;

   if (!can_be_zero)
      min_value = 1;

   for (exec_node *node = layout_const_expressions.get_head_raw();
        !node->is_tail_sentinel(); node = node->next) {

      exec_list dummy_instructions;
      ast_node *const_expression = exec_node_data(ast_node, node, link);

      ir_rvalue *const ir = const_expression->hir(&dummy_instructions, state);

      ir_constant *const const_int = ir->constant_expression_value();
      if (const_int == NULL || !const_int->type->is_integer()) {
         YYLTYPE loc = const_expression->get_location();
         _mesa_glsl_error(&loc, state, "%s must be an integral constant "
                          "expression", qual_indentifier);
         return false;
      }

      if (const_int->value.i[0] < min_value) {
         YYLTYPE loc = const_expression->get_location();
         _mesa_glsl_error(&loc, state, "%s layout qualifier is invalid "
                          "(%d < %d)", qual_indentifier,
                          const_int->value.i[0], min_value);
         return false;
      }

      /* From section 4.4 "Layout Qualifiers" of the GLSL 4.50 spec:
       * "When the same layout-qualifier-name occurs multiple times,
       *  in a single declaration, the last occurrence overrides the
       *  former occurrence(s)."
       */
      if (!first_pass) {
         if ((must_match || !state->has_420pack()) && *value != const_int->value.u[0]) {
            YYLTYPE loc = const_expression->get_location();
            _mesa_glsl_error(&loc, state, "%s layout qualifier does not "
                             "match previous declaration (%d vs %d)",
                             qual_indentifier, *value, const_int->value.i[0]);
            return false;
         }
      } else {
         first_pass = false;
         *value = const_int->value.u[0];
      }

      /* If the location is const (and we've verified that
       * it is) then no instructions should have been emitted
       * when we converted it to HIR. If they were emitted,
       * then either the location isn't const after all, or
       * we are emitting unnecessary instructions.
       */
      assert(dummy_instructions.is_empty());
   }

   return true;
}