|
|
|
@ -1,775 +0,0 @@
|
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2016 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <inttypes.h> /* for PRIx64 macro */
|
|
|
|
|
#include "ir.h"
|
|
|
|
|
#include "ir_hierarchical_visitor.h"
|
|
|
|
|
#include "ir_builder_print_visitor.h"
|
|
|
|
|
#include "compiler/glsl_types.h"
|
|
|
|
|
#include "glsl_parser_extras.h"
|
|
|
|
|
#include "main/macros.h"
|
|
|
|
|
#include "util/hash_table.h"
|
|
|
|
|
#include "util/u_string.h"
|
|
|
|
|
|
|
|
|
|
class ir_builder_print_visitor : public ir_hierarchical_visitor {
|
|
|
|
|
public:
|
|
|
|
|
ir_builder_print_visitor(FILE *f);
|
|
|
|
|
virtual ~ir_builder_print_visitor();
|
|
|
|
|
|
|
|
|
|
void indent(void);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit(class ir_variable *);
|
|
|
|
|
virtual ir_visitor_status visit(class ir_dereference_variable *);
|
|
|
|
|
virtual ir_visitor_status visit(class ir_constant *);
|
|
|
|
|
virtual ir_visitor_status visit(class ir_loop_jump *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_enter(class ir_if *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_enter(class ir_loop *);
|
|
|
|
|
virtual ir_visitor_status visit_leave(class ir_loop *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_enter(class ir_function_signature *);
|
|
|
|
|
virtual ir_visitor_status visit_leave(class ir_function_signature *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_enter(class ir_expression *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_enter(class ir_assignment *);
|
|
|
|
|
virtual ir_visitor_status visit_leave(class ir_assignment *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_leave(class ir_call *);
|
|
|
|
|
virtual ir_visitor_status visit_leave(class ir_swizzle *);
|
|
|
|
|
virtual ir_visitor_status visit_leave(class ir_return *);
|
|
|
|
|
|
|
|
|
|
virtual ir_visitor_status visit_enter(ir_texture *ir);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void print_with_indent(const char *fmt, ...);
|
|
|
|
|
void print_without_indent(const char *fmt, ...);
|
|
|
|
|
|
|
|
|
|
void print_without_declaration(const ir_rvalue *ir);
|
|
|
|
|
void print_without_declaration(const ir_constant *ir);
|
|
|
|
|
void print_without_declaration(const ir_dereference_variable *ir);
|
|
|
|
|
void print_without_declaration(const ir_swizzle *ir);
|
|
|
|
|
void print_without_declaration(const ir_expression *ir);
|
|
|
|
|
|
|
|
|
|
unsigned next_ir_index;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mapping from ir_instruction * -> index used in the generated C code
|
|
|
|
|
* variable name.
|
|
|
|
|
*/
|
|
|
|
|
hash_table *index_map;
|
|
|
|
|
|
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
|
|
int indentation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* An operand is "simple" if it can be compactly printed on one line.
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
is_simple_operand(const ir_rvalue *ir, unsigned depth = 1)
|
|
|
|
|
{
|
|
|
|
|
if (depth == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (ir->ir_type) {
|
|
|
|
|
case ir_type_dereference_variable:
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case ir_type_constant: {
|
|
|
|
|
if (ir->type == &glsl_type_builtin_uint ||
|
|
|
|
|
ir->type == &glsl_type_builtin_int ||
|
|
|
|
|
ir->type == &glsl_type_builtin_float ||
|
|
|
|
|
ir->type == &glsl_type_builtin_bool)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
const ir_constant *const c = (ir_constant *) ir;
|
|
|
|
|
ir_constant_data all_zero;
|
|
|
|
|
memset(&all_zero, 0, sizeof(all_zero));
|
|
|
|
|
|
|
|
|
|
return memcmp(&c->value, &all_zero, sizeof(all_zero)) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ir_type_swizzle: {
|
|
|
|
|
const ir_swizzle *swiz = (ir_swizzle *) ir;
|
|
|
|
|
return swiz->mask.num_components == 1 &&
|
|
|
|
|
is_simple_operand(swiz->val, depth);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ir_type_expression: {
|
|
|
|
|
const ir_expression *expr = (ir_expression *) ir;
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < expr->num_operands; i++) {
|
|
|
|
|
if (!is_simple_operand(expr->operands[i], depth - 1))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_mesa_print_builder_for_ir(FILE *f, exec_list *instructions)
|
|
|
|
|
{
|
|
|
|
|
ir_builder_print_visitor v(f);
|
|
|
|
|
v.run(instructions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_builder_print_visitor::ir_builder_print_visitor(FILE *f)
|
|
|
|
|
: next_ir_index(1), f(f), indentation(0)
|
|
|
|
|
{
|
|
|
|
|
index_map = _mesa_pointer_hash_table_create(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_builder_print_visitor::~ir_builder_print_visitor()
|
|
|
|
|
{
|
|
|
|
|
_mesa_hash_table_destroy(index_map, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ir_builder_print_visitor::indent(void)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < indentation; i++)
|
|
|
|
|
fprintf(f, " ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_with_indent(const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
indent();
|
|
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
vfprintf(f, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_without_indent(const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
vfprintf(f, fmt, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_without_declaration(const ir_rvalue *ir)
|
|
|
|
|
{
|
|
|
|
|
switch (ir->ir_type) {
|
|
|
|
|
case ir_type_dereference_variable:
|
|
|
|
|
print_without_declaration((ir_dereference_variable *) ir);
|
|
|
|
|
break;
|
|
|
|
|
case ir_type_constant:
|
|
|
|
|
print_without_declaration((ir_constant *) ir);
|
|
|
|
|
break;
|
|
|
|
|
case ir_type_swizzle:
|
|
|
|
|
print_without_declaration((ir_swizzle *) ir);
|
|
|
|
|
break;
|
|
|
|
|
case ir_type_expression:
|
|
|
|
|
print_without_declaration((ir_expression *) ir);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid IR type.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit(ir_variable *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
_mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
|
|
|
|
|
|
|
|
|
|
const char *mode_str;
|
|
|
|
|
switch (ir->data.mode) {
|
|
|
|
|
case ir_var_auto: mode_str = "ir_var_auto"; break;
|
|
|
|
|
case ir_var_uniform: mode_str = "ir_var_uniform"; break;
|
|
|
|
|
case ir_var_shader_storage: mode_str = "ir_var_shader_storage"; break;
|
|
|
|
|
case ir_var_shader_shared: mode_str = "ir_var_shader_shared"; break;
|
|
|
|
|
case ir_var_shader_in: mode_str = "ir_var_shader_in"; break;
|
|
|
|
|
case ir_var_shader_out: mode_str = "ir_var_shader_out"; break;
|
|
|
|
|
case ir_var_function_in: mode_str = "ir_var_function_in"; break;
|
|
|
|
|
case ir_var_function_out: mode_str = "ir_var_function_out"; break;
|
|
|
|
|
case ir_var_function_inout: mode_str = "ir_var_function_inout"; break;
|
|
|
|
|
case ir_var_const_in: mode_str = "ir_var_const_in"; break;
|
|
|
|
|
case ir_var_system_value: mode_str = "ir_var_system_value"; break;
|
|
|
|
|
case ir_var_temporary: mode_str = "ir_var_temporary"; break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid variable mode");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ir->data.mode == ir_var_temporary) {
|
|
|
|
|
print_with_indent("ir_variable *const r%04X = body.make_temp(glsl_type_builtin_%s, \"%s\");\n",
|
|
|
|
|
my_index,
|
|
|
|
|
glsl_get_type_name(ir->type),
|
|
|
|
|
ir->name);
|
|
|
|
|
} else {
|
|
|
|
|
print_with_indent("ir_variable *const r%04X = new(mem_ctx) ir_variable(glsl_type_builtin_%s, \"%s\", %s);\n",
|
|
|
|
|
my_index,
|
|
|
|
|
glsl_get_type_name(ir->type),
|
|
|
|
|
ir->name,
|
|
|
|
|
mode_str);
|
|
|
|
|
|
|
|
|
|
switch (ir->data.mode) {
|
|
|
|
|
case ir_var_function_in:
|
|
|
|
|
case ir_var_function_out:
|
|
|
|
|
case ir_var_function_inout:
|
|
|
|
|
case ir_var_const_in:
|
|
|
|
|
print_with_indent("sig_parameters.push_tail(r%04X);\n", my_index);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
print_with_indent("body.emit(r%04X);\n", my_index);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_without_declaration(const ir_dereference_variable *ir)
|
|
|
|
|
{
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->var);
|
|
|
|
|
|
|
|
|
|
print_without_indent("r%04X", (unsigned)(uintptr_t) he->data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit(ir_dereference_variable *ir)
|
|
|
|
|
{
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->var);
|
|
|
|
|
|
|
|
|
|
if (he != NULL)
|
|
|
|
|
_mesa_hash_table_insert(index_map, ir, he->data);
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_enter(ir_function_signature *ir)
|
|
|
|
|
{
|
|
|
|
|
if (!ir->is_defined)
|
|
|
|
|
return visit_continue_with_parent;
|
|
|
|
|
|
|
|
|
|
print_with_indent("ir_function_signature *\n"
|
|
|
|
|
"%s(void *mem_ctx, builtin_available_predicate avail)\n"
|
|
|
|
|
"{\n",
|
|
|
|
|
ir->function_name());
|
|
|
|
|
indentation++;
|
|
|
|
|
print_with_indent("ir_function_signature *const sig =\n");
|
|
|
|
|
print_with_indent(" new(mem_ctx) ir_function_signature(glsl_type_builtin_%s, avail);\n",
|
|
|
|
|
glsl_get_type_name(ir->return_type));
|
|
|
|
|
|
|
|
|
|
print_with_indent("ir_factory body(&sig->body, mem_ctx);\n");
|
|
|
|
|
print_with_indent("sig->is_defined = true;\n\n");
|
|
|
|
|
|
|
|
|
|
if (!ir->parameters.is_empty())
|
|
|
|
|
print_with_indent("exec_list sig_parameters;\n\n");
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_leave(ir_function_signature *ir)
|
|
|
|
|
{
|
|
|
|
|
if (!ir->parameters.is_empty())
|
|
|
|
|
print_with_indent("sig->replace_parameters(&sig_parameters);\n");
|
|
|
|
|
|
|
|
|
|
print_with_indent("return sig;\n");
|
|
|
|
|
indentation--;
|
|
|
|
|
print_with_indent("}\n");
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_without_declaration(const ir_constant *ir)
|
|
|
|
|
{
|
|
|
|
|
if (glsl_type_is_scalar(ir->type)) {
|
|
|
|
|
switch (ir->type->base_type) {
|
|
|
|
|
case GLSL_TYPE_UINT:
|
|
|
|
|
print_without_indent("body.constant(%uu)", ir->value.u[0]);
|
|
|
|
|
return;
|
|
|
|
|
case GLSL_TYPE_INT:
|
|
|
|
|
print_without_indent("body.constant(int(%d))", ir->value.i[0]);
|
|
|
|
|
return;
|
|
|
|
|
case GLSL_TYPE_FLOAT:
|
|
|
|
|
print_without_indent("body.constant(%ff)", ir->value.f[0]);
|
|
|
|
|
return;
|
|
|
|
|
case GLSL_TYPE_BOOL:
|
|
|
|
|
print_without_indent("body.constant(%s)",
|
|
|
|
|
ir->value.i[0] != 0 ? "true" : "false");
|
|
|
|
|
return;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_constant_data all_zero;
|
|
|
|
|
memset(&all_zero, 0, sizeof(all_zero));
|
|
|
|
|
|
|
|
|
|
if (memcmp(&ir->value, &all_zero, sizeof(all_zero)) == 0) {
|
|
|
|
|
print_without_indent("ir_constant::zero(mem_ctx, glsl_type_builtin_%s)",
|
|
|
|
|
glsl_get_type_name(ir->type));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit(ir_constant *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
_mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
|
|
|
|
|
|
|
|
|
|
if (ir->type == &glsl_type_builtin_uint ||
|
|
|
|
|
ir->type == &glsl_type_builtin_int ||
|
|
|
|
|
ir->type == &glsl_type_builtin_float ||
|
|
|
|
|
ir->type == &glsl_type_builtin_bool) {
|
|
|
|
|
print_with_indent("ir_constant *const r%04X = ", my_index);
|
|
|
|
|
print_without_declaration(ir);
|
|
|
|
|
print_without_indent(";\n");
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_constant_data all_zero;
|
|
|
|
|
memset(&all_zero, 0, sizeof(all_zero));
|
|
|
|
|
|
|
|
|
|
if (memcmp(&ir->value, &all_zero, sizeof(all_zero)) == 0) {
|
|
|
|
|
print_with_indent("ir_constant *const r%04X = ", my_index);
|
|
|
|
|
print_without_declaration(ir);
|
|
|
|
|
print_without_indent(";\n");
|
|
|
|
|
} else {
|
|
|
|
|
print_with_indent("ir_constant_data r%04X_data;\n", my_index);
|
|
|
|
|
print_with_indent("memset(&r%04X_data, 0, sizeof(ir_constant_data));\n",
|
|
|
|
|
my_index);
|
|
|
|
|
for (unsigned i = 0; i < 16; i++) {
|
|
|
|
|
switch (ir->type->base_type) {
|
|
|
|
|
case GLSL_TYPE_UINT:
|
|
|
|
|
if (ir->value.u[i] != 0)
|
|
|
|
|
print_with_indent("r%04X_data.u[%u] = %u;\n",
|
|
|
|
|
my_index, i, ir->value.u[i]);
|
|
|
|
|
break;
|
|
|
|
|
case GLSL_TYPE_INT:
|
|
|
|
|
if (ir->value.i[i] != 0)
|
|
|
|
|
print_with_indent("r%04X_data.i[%u] = %i;\n",
|
|
|
|
|
my_index, i, ir->value.i[i]);
|
|
|
|
|
break;
|
|
|
|
|
case GLSL_TYPE_FLOAT:
|
|
|
|
|
if (ir->value.u[i] != 0)
|
|
|
|
|
print_with_indent("r%04X_data.u[%u] = 0x%08x; /* %f */\n",
|
|
|
|
|
my_index,
|
|
|
|
|
i,
|
|
|
|
|
ir->value.u[i],
|
|
|
|
|
ir->value.f[i]);
|
|
|
|
|
break;
|
|
|
|
|
case GLSL_TYPE_DOUBLE: {
|
|
|
|
|
uint64_t v;
|
|
|
|
|
|
|
|
|
|
STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
|
|
|
|
|
|
|
|
|
|
memcpy(&v, &ir->value.d[i], sizeof(v));
|
|
|
|
|
if (v != 0)
|
|
|
|
|
print_with_indent("r%04X_data.u64[%u] = 0x%016" PRIx64 "; /* %g */\n",
|
|
|
|
|
my_index, i, v, ir->value.d[i]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case GLSL_TYPE_UINT64:
|
|
|
|
|
if (ir->value.u64[i] != 0)
|
|
|
|
|
print_with_indent("r%04X_data.u64[%u] = %" PRIu64 ";\n",
|
|
|
|
|
my_index,
|
|
|
|
|
i,
|
|
|
|
|
ir->value.u64[i]);
|
|
|
|
|
break;
|
|
|
|
|
case GLSL_TYPE_INT64:
|
|
|
|
|
if (ir->value.i64[i] != 0)
|
|
|
|
|
print_with_indent("r%04X_data.i64[%u] = %" PRId64 ";\n",
|
|
|
|
|
my_index,
|
|
|
|
|
i,
|
|
|
|
|
ir->value.i64[i]);
|
|
|
|
|
break;
|
|
|
|
|
case GLSL_TYPE_BOOL:
|
|
|
|
|
if (ir->value.u[i] != 0)
|
|
|
|
|
print_with_indent("r%04X_data.u[%u] = 1;\n", my_index, i);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid constant type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_with_indent("ir_constant *const r%04X = new(mem_ctx) ir_constant(glsl_type_builtin_%s, &r%04X_data);\n",
|
|
|
|
|
my_index,
|
|
|
|
|
glsl_get_type_name(ir->type),
|
|
|
|
|
my_index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_without_declaration(const ir_swizzle *ir)
|
|
|
|
|
{
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->val);
|
|
|
|
|
|
|
|
|
|
if (ir->mask.num_components == 1) {
|
|
|
|
|
static const char swiz[4] = { 'x', 'y', 'z', 'w' };
|
|
|
|
|
|
|
|
|
|
if (is_simple_operand(ir->val)) {
|
|
|
|
|
print_without_indent("swizzle_%c(", swiz[ir->mask.x]);
|
|
|
|
|
print_without_declaration(ir->val);
|
|
|
|
|
print_without_indent(")");
|
|
|
|
|
} else {
|
|
|
|
|
assert(he);
|
|
|
|
|
print_without_indent("swizzle_%c(r%04X)",
|
|
|
|
|
swiz[ir->mask.x],
|
|
|
|
|
(unsigned)(uintptr_t) he->data);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
static const char swiz[4] = { 'X', 'Y', 'Z', 'W' };
|
|
|
|
|
|
|
|
|
|
assert(he);
|
|
|
|
|
print_without_indent("swizzle(r%04X, MAKE_SWIZZLE4(SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c, SWIZZLE_%c), %u)",
|
|
|
|
|
(unsigned)(uintptr_t) he->data,
|
|
|
|
|
swiz[ir->mask.x],
|
|
|
|
|
swiz[ir->mask.y],
|
|
|
|
|
swiz[ir->mask.z],
|
|
|
|
|
swiz[ir->mask.w],
|
|
|
|
|
ir->mask.num_components);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_leave(ir_swizzle *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
_mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
|
|
|
|
|
|
|
|
|
|
print_with_indent("ir_swizzle *const r%04X = ", my_index);
|
|
|
|
|
print_without_declaration(ir);
|
|
|
|
|
print_without_indent(";\n");
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_enter(ir_assignment *ir)
|
|
|
|
|
{
|
|
|
|
|
ir_expression *const rhs_expr = ir->rhs->as_expression();
|
|
|
|
|
|
|
|
|
|
if (!is_simple_operand(ir->rhs) && rhs_expr == NULL)
|
|
|
|
|
return visit_continue;
|
|
|
|
|
|
|
|
|
|
if (rhs_expr != NULL) {
|
|
|
|
|
const unsigned num_op = rhs_expr->num_operands;
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_op; i++) {
|
|
|
|
|
if (is_simple_operand(rhs_expr->operands[i]))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
rhs_expr->operands[i]->accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status s;
|
|
|
|
|
|
|
|
|
|
this->in_assignee = true;
|
|
|
|
|
s = ir->lhs->accept(this);
|
|
|
|
|
this->in_assignee = false;
|
|
|
|
|
if (s != visit_continue)
|
|
|
|
|
return (s == visit_continue_with_parent) ? visit_continue : s;
|
|
|
|
|
|
|
|
|
|
const struct hash_entry *const he_lhs =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->lhs);
|
|
|
|
|
|
|
|
|
|
print_with_indent("body.emit(assign(r%04X, ",
|
|
|
|
|
(unsigned)(uintptr_t) he_lhs->data);
|
|
|
|
|
print_without_declaration(ir->rhs);
|
|
|
|
|
print_without_indent(", 0x%02x));\n\n", ir->write_mask);
|
|
|
|
|
|
|
|
|
|
return visit_continue_with_parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_leave(ir_assignment *ir)
|
|
|
|
|
{
|
|
|
|
|
const struct hash_entry *const he_lhs =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->lhs);
|
|
|
|
|
|
|
|
|
|
const struct hash_entry *const he_rhs =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->rhs);
|
|
|
|
|
|
|
|
|
|
assert(ir->lhs && ir->rhs);
|
|
|
|
|
|
|
|
|
|
print_with_indent("body.emit(assign(r%04X, r%04X, 0x%02x));\n\n",
|
|
|
|
|
(unsigned)(uintptr_t) he_lhs->data,
|
|
|
|
|
(unsigned)(uintptr_t) he_rhs->data,
|
|
|
|
|
ir->write_mask);
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ir_builder_print_visitor::print_without_declaration(const ir_expression *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned num_op = ir->num_operands;
|
|
|
|
|
|
|
|
|
|
static const char *const arity[] = {
|
|
|
|
|
"", "unop", "binop", "triop", "quadop"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
switch (ir->operation) {
|
|
|
|
|
case ir_unop_neg:
|
|
|
|
|
case ir_binop_add:
|
|
|
|
|
case ir_binop_sub:
|
|
|
|
|
case ir_binop_mul:
|
|
|
|
|
case ir_binop_imul_high:
|
|
|
|
|
case ir_binop_less:
|
|
|
|
|
case ir_binop_gequal:
|
|
|
|
|
case ir_binop_equal:
|
|
|
|
|
case ir_binop_nequal:
|
|
|
|
|
case ir_binop_lshift:
|
|
|
|
|
case ir_binop_rshift:
|
|
|
|
|
case ir_binop_bit_and:
|
|
|
|
|
case ir_binop_bit_xor:
|
|
|
|
|
case ir_binop_bit_or:
|
|
|
|
|
case ir_binop_logic_and:
|
|
|
|
|
case ir_binop_logic_xor:
|
|
|
|
|
case ir_binop_logic_or:
|
|
|
|
|
print_without_indent("%s(",
|
|
|
|
|
ir_expression_operation_enum_strings[ir->operation]);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
print_without_indent("expr(ir_%s_%s, ",
|
|
|
|
|
arity[num_op],
|
|
|
|
|
ir_expression_operation_enum_strings[ir->operation]);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_op; i++) {
|
|
|
|
|
if (is_simple_operand(ir->operands[i]))
|
|
|
|
|
print_without_declaration(ir->operands[i]);
|
|
|
|
|
else {
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->operands[i]);
|
|
|
|
|
|
|
|
|
|
print_without_indent("r%04X", (unsigned)(uintptr_t) he->data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i < num_op - 1)
|
|
|
|
|
print_without_indent(", ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_without_indent(")");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_enter(ir_expression *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned num_op = ir->num_operands;
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_op; i++) {
|
|
|
|
|
if (is_simple_operand(ir->operands[i]))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
ir->operands[i]->accept(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
_mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
|
|
|
|
|
|
|
|
|
|
print_with_indent("ir_expression *const r%04X = ", my_index);
|
|
|
|
|
print_without_declaration(ir);
|
|
|
|
|
print_without_indent(";\n");
|
|
|
|
|
|
|
|
|
|
return visit_continue_with_parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_enter(ir_if *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
print_with_indent("/* IF CONDITION */\n");
|
|
|
|
|
|
|
|
|
|
ir_visitor_status s = ir->condition->accept(this);
|
|
|
|
|
if (s != visit_continue)
|
|
|
|
|
return (s == visit_continue_with_parent) ? visit_continue : s;
|
|
|
|
|
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->condition);
|
|
|
|
|
|
|
|
|
|
print_with_indent("ir_if *f%04X = new(mem_ctx) ir_if(operand(r%04X).val);\n",
|
|
|
|
|
my_index,
|
|
|
|
|
(unsigned)(uintptr_t) he->data);
|
|
|
|
|
print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n",
|
|
|
|
|
my_index);
|
|
|
|
|
|
|
|
|
|
indentation++;
|
|
|
|
|
print_with_indent("/* THEN INSTRUCTIONS */\n");
|
|
|
|
|
print_with_indent("body.instructions = &f%04X->then_instructions;\n\n",
|
|
|
|
|
my_index);
|
|
|
|
|
|
|
|
|
|
if (s != visit_continue_with_parent) {
|
|
|
|
|
s = visit_list_elements(this, &ir->then_instructions);
|
|
|
|
|
if (s == visit_stop)
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_without_indent("\n");
|
|
|
|
|
|
|
|
|
|
if (!ir->else_instructions.is_empty()) {
|
|
|
|
|
print_with_indent("/* ELSE INSTRUCTIONS */\n");
|
|
|
|
|
print_with_indent("body.instructions = &f%04X->else_instructions;\n\n",
|
|
|
|
|
my_index);
|
|
|
|
|
|
|
|
|
|
if (s != visit_continue_with_parent) {
|
|
|
|
|
s = visit_list_elements(this, &ir->else_instructions);
|
|
|
|
|
if (s == visit_stop)
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_without_indent("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
indentation--;
|
|
|
|
|
|
|
|
|
|
print_with_indent("body.instructions = f%04X_parent_instructions;\n",
|
|
|
|
|
my_index);
|
|
|
|
|
print_with_indent("body.emit(f%04X);\n\n",
|
|
|
|
|
my_index);
|
|
|
|
|
print_with_indent("/* END IF */\n\n");
|
|
|
|
|
|
|
|
|
|
return visit_continue_with_parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_leave(ir_return *ir)
|
|
|
|
|
{
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->value);
|
|
|
|
|
|
|
|
|
|
print_with_indent("body.emit(ret(r%04X));\n\n",
|
|
|
|
|
(unsigned)(uintptr_t) he->data);
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_enter(ir_texture *ir)
|
|
|
|
|
{
|
|
|
|
|
print_with_indent("\nUnsupported IR is encountered: texture functions are not supported. Exiting.\n");
|
|
|
|
|
|
|
|
|
|
return visit_stop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_leave(ir_call *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
print_without_indent("\n");
|
|
|
|
|
print_with_indent("/* CALL %s */\n", ir->callee_name());
|
|
|
|
|
print_with_indent("exec_list r%04X_parameters;\n", my_index);
|
|
|
|
|
|
|
|
|
|
foreach_in_list(ir_dereference_variable, param, &ir->actual_parameters) {
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, param);
|
|
|
|
|
|
|
|
|
|
print_with_indent("r%04X_parameters.push_tail(operand(r%04X).val);\n",
|
|
|
|
|
my_index,
|
|
|
|
|
(unsigned)(uintptr_t) he->data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char return_deref_string[32];
|
|
|
|
|
if (ir->return_deref) {
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir->return_deref);
|
|
|
|
|
|
|
|
|
|
snprintf(return_deref_string, sizeof(return_deref_string),
|
|
|
|
|
"operand(r%04X).val", (unsigned)(uintptr_t) he->data);
|
|
|
|
|
} else {
|
|
|
|
|
strcpy(return_deref_string, "NULL");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print_with_indent("body.emit(new(mem_ctx) ir_call(shader->symbols->get_function(\"%s\"),\n",
|
|
|
|
|
ir->callee_name());
|
|
|
|
|
print_with_indent(" %s, &r%04X_parameters);\n\n",
|
|
|
|
|
return_deref_string,
|
|
|
|
|
my_index);
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_enter(ir_loop *ir)
|
|
|
|
|
{
|
|
|
|
|
const unsigned my_index = next_ir_index++;
|
|
|
|
|
|
|
|
|
|
_mesa_hash_table_insert(index_map, ir, (void *)(uintptr_t) my_index);
|
|
|
|
|
|
|
|
|
|
print_with_indent("/* LOOP BEGIN */\n");
|
|
|
|
|
print_with_indent("ir_loop *f%04X = new(mem_ctx) ir_loop();\n", my_index);
|
|
|
|
|
print_with_indent("exec_list *const f%04X_parent_instructions = body.instructions;\n\n",
|
|
|
|
|
my_index);
|
|
|
|
|
|
|
|
|
|
indentation++;
|
|
|
|
|
|
|
|
|
|
print_with_indent("body.instructions = &f%04X->body_instructions;\n\n",
|
|
|
|
|
my_index);
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit_leave(ir_loop *ir)
|
|
|
|
|
{
|
|
|
|
|
const struct hash_entry *const he =
|
|
|
|
|
_mesa_hash_table_search(index_map, ir);
|
|
|
|
|
|
|
|
|
|
indentation--;
|
|
|
|
|
|
|
|
|
|
print_with_indent("/* LOOP END */\n\n");
|
|
|
|
|
print_with_indent("body.instructions = f%04X_parent_instructions;\n",
|
|
|
|
|
(unsigned)(uintptr_t) he->data);
|
|
|
|
|
print_with_indent("body.emit(f%04X);\n\n",
|
|
|
|
|
(unsigned)(uintptr_t) he->data);
|
|
|
|
|
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ir_visitor_status
|
|
|
|
|
ir_builder_print_visitor::visit(ir_loop_jump *ir)
|
|
|
|
|
{
|
|
|
|
|
print_with_indent("body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_%s));\n\n",
|
|
|
|
|
ir->is_break() ? "break" : "continue");
|
|
|
|
|
return visit_continue;
|
|
|
|
|
}
|