ir_print_visitor.cpp ir_variable.cpp ir_function.cpp \
ir_basic_block.cpp \
ir_basic_block.h \
+ ir_clone.cpp \
ir_constant_expression.cpp \
ir_constant_folding.cpp \
ir_constant_variable.cpp \
if (loop != NULL) {
ir_loop_jump *const jump =
- new ir_loop_jump(loop,
- (mode == ast_break)
+ new ir_loop_jump((mode == ast_break)
? ir_loop_jump::jump_break
: ir_loop_jump::jump_continue);
instructions->push_tail(jump);
ir_if *const if_stmt = new ir_if(not_cond);
ir_jump *const break_stmt =
- new ir_loop_jump(stmt, ir_loop_jump::jump_break);
+ new ir_loop_jump(ir_loop_jump::jump_break);
if_stmt->then_instructions.push_tail(break_stmt);
stmt->body_instructions.push_tail(if_stmt);
}
}
-ir_constant *
-ir_constant::clone()
+ir_instruction *
+ir_constant::clone(struct hash_table *ht) const
{
switch (this->type->base_type) {
case GLSL_TYPE_UINT:
; node = node->next) {
ir_constant *const orig = (ir_constant *) node;
- c->components.push_tail(orig->clone());
+ c->components.push_tail(orig->clone(NULL));
}
return c;
class ir_constant *constant_expression_value();
/** ir_print_visitor helper for debugging. */
- void print(void);
+ void print(void) const;
virtual void accept(ir_visitor *) = 0;
virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
+ virtual ir_instruction *clone(struct hash_table *ht) const = 0;
/**
* \name IR instruction downcast functions
public:
ir_variable(const struct glsl_type *, const char *);
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual ir_variable *as_variable()
{
return this;
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- /**
- * Duplicate an IR variable
- *
- * \note
- * This will probably be made \c virtual and moved to the base class
- * eventually.
- */
- ir_variable *clone() const
- {
- ir_variable *var = new ir_variable(type, name);
-
- var->max_array_access = this->max_array_access;
- var->read_only = this->read_only;
- var->centroid = this->centroid;
- var->invariant = this->invariant;
- var->mode = this->mode;
- var->interpolation = this->interpolation;
-
- return var;
- }
/**
* Get the string value for the interpolation qualifier
public:
ir_function_signature(const glsl_type *return_type);
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
public:
ir_function(const char *name);
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual ir_function *as_function()
{
return this;
/* empty */
}
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual ir_if *as_if()
{
return this;
/* empty */
}
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
public:
ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
ir_expression(int op, const struct glsl_type *type,
ir_rvalue *, ir_rvalue *);
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
static unsigned int get_num_operands(ir_expression_operation);
- unsigned int get_num_operands()
+ unsigned int get_num_operands() const
{
return get_num_operands(operation);
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- ir_expression *clone();
-
ir_expression_operation operation;
ir_rvalue *operands[2];
};
actual_parameters->move_nodes_to(& this->actual_parameters);
}
+ virtual ir_instruction *clone(struct hash_table *ht) const;
+
virtual ir_call *as_call()
{
return this;
/* empty */
}
+ virtual ir_instruction *clone(struct hash_table *) const;
+
virtual ir_return *as_return()
{
return this;
jump_continue
};
- ir_loop_jump(ir_loop *loop, jump_mode mode)
- : loop(loop), mode(mode)
+ ir_loop_jump(jump_mode mode)
+ : mode(mode)
{
/* empty */
}
+ virtual ir_instruction *clone(struct hash_table *) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
}
private:
- /** Loop containing this break instruction. */
- ir_loop *loop;
-
/** Mode selector for the jump instruction. */
enum jump_mode mode;
};
/* empty */
}
+ virtual ir_instruction *clone(struct hash_table *) const;
+
virtual void accept(ir_visitor *v)
{
v->visit(this);
unsigned count);
ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask);
+ virtual ir_instruction *clone(struct hash_table *) const;
+
virtual ir_swizzle *as_swizzle()
{
return this;
}
- ir_swizzle *clone()
- {
- return new ir_swizzle(this->val, this->mask);
- }
-
/**
* Construct an ir_swizzle from the textual representation. Can fail.
*/
public:
ir_dereference_variable(ir_variable *var);
+ virtual ir_instruction *clone(struct hash_table *) const;
+
/**
* Get the variable that is ultimately referenced by an r-value
*/
ir_dereference_array(ir_variable *var, ir_rvalue *array_index);
+ virtual ir_instruction *clone(struct hash_table *) const;
+
virtual ir_dereference_array *as_dereference_array()
{
return this;
ir_dereference_record(ir_variable *var, const char *field);
+ virtual ir_instruction *clone(struct hash_table *) const;
+
/**
* Get the variable that is ultimately referenced by an r-value
*/
*/
ir_constant(const ir_constant *c, unsigned i);
+ virtual ir_instruction *clone(struct hash_table *) const;
+
virtual ir_constant *as_constant()
{
return this;
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- ir_constant *clone();
-
/**
* Get a particular component of a constant as a specific type
*
--- /dev/null
+/*
+ * Copyright © 2010 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 <string.h>
+#include "ir.h"
+#include "glsl_types.h"
+#include "hash_table.h"
+
+/**
+ * Duplicate an IR variable
+ *
+ * \note
+ * This will probably be made \c virtual and moved to the base class
+ * eventually.
+ */
+ir_instruction *
+ir_variable::clone(struct hash_table *ht) const
+{
+ ir_variable *var = new ir_variable(type, name);
+
+ var->max_array_access = this->max_array_access;
+ var->read_only = this->read_only;
+ var->centroid = this->centroid;
+ var->invariant = this->invariant;
+ var->mode = this->mode;
+ var->interpolation = this->interpolation;
+
+ if (ht) {
+ hash_table_insert(ht, (void *)const_cast<ir_variable *>(this), var);
+ }
+
+ return var;
+}
+
+ir_instruction *
+ir_swizzle::clone(struct hash_table *ht) const
+{
+ return new ir_swizzle((ir_rvalue *)this->val->clone(ht), this->mask);
+}
+
+ir_instruction *
+ir_return::clone(struct hash_table *ht) const
+{
+ ir_rvalue *new_value = NULL;
+
+ if (this->value)
+ new_value = (ir_rvalue *)this->value->clone(ht);
+
+ return new ir_return(new_value);
+}
+
+ir_instruction *
+ir_loop_jump::clone(struct hash_table *ht) const
+{
+ (void)ht;
+
+ return new ir_loop_jump(this->mode);
+}
+
+ir_instruction *
+ir_if::clone(struct hash_table *ht) const
+{
+ ir_if *new_if = new ir_if((ir_rvalue *)this->condition->clone(ht));
+
+ foreach_iter(exec_list_iterator, iter, this->then_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_if->then_instructions.push_tail(ir->clone(ht));
+ }
+
+ foreach_iter(exec_list_iterator, iter, this->else_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_if->else_instructions.push_tail(ir->clone(ht));
+ }
+
+ return new_if;
+}
+
+ir_instruction *
+ir_loop::clone(struct hash_table *ht) const
+{
+ ir_loop *new_loop = new ir_loop();
+
+ if (this->from)
+ new_loop->from = (ir_rvalue *)this->from->clone(ht);
+ if (this->to)
+ new_loop->to = (ir_rvalue *)this->to->clone(ht);
+ if (this->increment)
+ new_loop->increment = (ir_rvalue *)this->increment->clone(ht);
+ new_loop->counter = counter;
+
+ foreach_iter(exec_list_iterator, iter, this->body_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_loop->body_instructions.push_tail(ir->clone(ht));
+ }
+
+ return new_loop;
+}
+
+ir_instruction *
+ir_call::clone(struct hash_table *ht) const
+{
+ exec_list new_parameters;
+
+ foreach_iter(exec_list_iterator, iter, this->actual_parameters) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ new_parameters.push_tail(ir->clone(ht));
+ }
+
+ return new ir_call(this->callee, &new_parameters);
+}
+
+ir_instruction *
+ir_expression::clone(struct hash_table *ht) const
+{
+ ir_rvalue *op[2] = {NULL, NULL};
+ unsigned int i;
+
+ for (i = 0; i < get_num_operands(); i++) {
+ op[i] = (ir_rvalue *)this->operands[i]->clone(ht);
+ }
+
+ return new ir_expression(this->operation, this->type, op[0], op[1]);
+}
+
+ir_instruction *
+ir_dereference_variable::clone(struct hash_table *ht) const
+{
+ ir_variable *new_var;
+
+ if (ht) {
+ new_var = (ir_variable *)hash_table_find(ht, this->var);
+ if (!new_var)
+ new_var = this->var;
+ } else {
+ new_var = this->var;
+ }
+
+ return new ir_dereference_variable(new_var);
+}
+
+ir_instruction *
+ir_dereference_array::clone(struct hash_table *ht) const
+{
+ return new ir_dereference_array((ir_rvalue *)this->array->clone(ht),
+ (ir_rvalue *)this->array_index->clone(ht));
+}
+
+ir_instruction *
+ir_dereference_record::clone(struct hash_table *ht) const
+{
+ return new ir_dereference_record((ir_rvalue *)this->record->clone(ht),
+ this->field);
+}
+
+ir_instruction *
+ir_texture::clone(struct hash_table *ht) const
+{
+ ir_texture *new_tex = new ir_texture(this->op);
+
+ new_tex->sampler = (ir_dereference *)this->sampler->clone(ht);
+ new_tex->coordinate = (ir_rvalue *)this->coordinate->clone(ht);
+ if (this->projector)
+ new_tex->projector = (ir_rvalue *)this->projector->clone(ht);
+ if (this->shadow_comparitor) {
+ new_tex->shadow_comparitor =
+ (ir_rvalue *)this->shadow_comparitor->clone(ht);
+ }
+
+ for (int i = 0; i < 3; i++)
+ new_tex->offsets[i] = this->offsets[i];
+
+ switch (this->op) {
+ case ir_tex:
+ break;
+ case ir_txb:
+ new_tex->lod_info.bias = (ir_rvalue *)this->lod_info.bias->clone(ht);
+ break;
+ case ir_txl:
+ case ir_txf:
+ new_tex->lod_info.lod = (ir_rvalue *)this->lod_info.lod->clone(ht);
+ break;
+ case ir_txd:
+ new_tex->lod_info.grad.dPdx =
+ (ir_rvalue *)this->lod_info.grad.dPdx->clone(ht);
+ new_tex->lod_info.grad.dPdy =
+ (ir_rvalue *)this->lod_info.grad.dPdy->clone(ht);
+ break;
+ }
+
+ return new_tex;
+}
+
+ir_instruction *
+ir_assignment::clone(struct hash_table *ht) const
+{
+ ir_rvalue *new_condition = NULL;
+
+ if (this->condition)
+ new_condition = (ir_rvalue *)this->condition->clone(ht);
+
+ return new ir_assignment((ir_rvalue *)this->lhs->clone(ht),
+ (ir_rvalue *)this->rhs->clone(ht),
+ new_condition);
+}
+
+ir_instruction *
+ir_function::clone(struct hash_table *ht) const
+{
+ (void)ht;
+ /* FINISHME */
+ abort();
+}
+
+ir_instruction *
+ir_function_signature::clone(struct hash_table *ht) const
+{
+ (void)ht;
+ /* FINISHME */
+ abort();
+}
ir_variable *var = ir->variable_referenced();
if (var && var->constant_value)
- value = var->constant_value->clone();
+ value = (ir_constant *)var->constant_value->clone(NULL);
}
* Replaces calls to functions with the body of the function.
*/
+#include <inttypes.h>
#include "ir.h"
#include "ir_visitor.h"
#include "ir_function_inlining.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"
+#include "hash_table.h"
class ir_function_inlining_visitor : public ir_hierarchical_visitor {
public:
bool progress;
};
-class variable_remap : public exec_node {
-public:
- variable_remap(const ir_variable *old_var, ir_variable *new_var)
- : old_var(old_var), new_var(new_var)
- {
- /* empty */
- }
- const ir_variable *old_var;
- ir_variable *new_var;
-};
-
-class ir_function_cloning_visitor : public ir_visitor {
-public:
- ir_function_cloning_visitor(ir_variable *retval)
- : retval(retval)
- {
- /* empty */
- }
-
- virtual ~ir_function_cloning_visitor()
- {
- /* empty */
- }
-
- void remap_variable(const ir_variable *old_var, ir_variable *new_var) {
- variable_remap *remap = new variable_remap(old_var, new_var);
- this->remap_list.push_tail(remap);
- }
-
- ir_variable *get_remapped_variable(ir_variable *var) {
- foreach_iter(exec_list_iterator, iter, this->remap_list) {
- variable_remap *remap = (variable_remap *)iter.get();
-
- if (var == remap->old_var)
- return remap->new_var;
- }
-
- /* Not a reapped variable, so a global scoped reference, for example. */
- return var;
- }
-
- /* List of variable_remap for mapping from original function body variables
- * to inlined function body variables.
- */
- exec_list remap_list;
-
- /* Return value for the inlined function. */
- ir_variable *retval;
-
- /**
- * \name Visit methods
- *
- * As typical for the visitor pattern, there must be one \c visit method for
- * each concrete subclass of \c ir_instruction. Virtual base classes within
- * the hierarchy should not have \c visit methods.
- */
- /*@{*/
- virtual void visit(ir_variable *);
- virtual void visit(ir_loop *);
- virtual void visit(ir_loop_jump *);
- virtual void visit(ir_function_signature *);
- virtual void visit(ir_function *);
- virtual void visit(ir_expression *);
- virtual void visit(ir_texture *);
- virtual void visit(ir_swizzle *);
- virtual void visit(ir_dereference_variable *);
- virtual void visit(ir_dereference_array *);
- virtual void visit(ir_dereference_record *);
- virtual void visit(ir_assignment *);
- virtual void visit(ir_constant *);
- virtual void visit(ir_call *);
- virtual void visit(ir_return *);
- virtual void visit(ir_if *);
- /*@}*/
-
- ir_instruction *result;
-};
-
-void
-ir_function_cloning_visitor::visit(ir_variable *ir)
-{
- ir_variable *new_var = ir->clone();
-
- this->result = new_var;
- this->remap_variable(ir, new_var);
-}
-
-void
-ir_function_cloning_visitor::visit(ir_loop *ir)
-{
- /* FINISHME: Implement loop cloning. */
- assert(0);
-
- (void)ir;
- this->result = NULL;
-}
-
-void
-ir_function_cloning_visitor::visit(ir_loop_jump *ir)
-{
- /* FINISHME: Implement loop cloning. */
- assert(0);
-
- (void) ir;
- this->result = NULL;
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_function_signature *ir)
-{
- assert(0);
- (void)ir;
- this->result = NULL;
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_function *ir)
+unsigned int hash_func(const void *key)
{
- assert(0);
- (void) ir;
- this->result = NULL;
+ return (unsigned int)(uintptr_t)key;
}
-void
-ir_function_cloning_visitor::visit(ir_expression *ir)
+int hash_compare_func(const void *key1, const void *key2)
{
- unsigned int operand;
- ir_rvalue *op[2] = {NULL, NULL};
-
- for (operand = 0; operand < ir->get_num_operands(); operand++) {
- ir->operands[operand]->accept(this);
- op[operand] = this->result->as_rvalue();
- assert(op[operand]);
- }
-
- this->result = new ir_expression(ir->operation, ir->type, op[0], op[1]);
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_texture *ir)
-{
- ir_texture *tex = new ir_texture(ir->op);
-
- ir->sampler->accept(this);
- tex->set_sampler(this->result->as_dereference());
-
- ir->coordinate->accept(this);
- tex->coordinate = this->result->as_rvalue();
-
- if (ir->projector != NULL) {
- ir->projector->accept(this);
- tex->projector = this->result->as_rvalue();
- }
-
- if (ir->shadow_comparitor != NULL) {
- ir->shadow_comparitor->accept(this);
- tex->shadow_comparitor = this->result->as_rvalue();
- }
-
- for (int i = 0; i < 3; i++)
- tex->offsets[i] = ir->offsets[i];
-
- tex->lod_info = ir->lod_info;
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_swizzle *ir)
-{
- ir->val->accept(this);
-
- this->result = new ir_swizzle(this->result->as_rvalue(), ir->mask);
-}
-
-void
-ir_function_cloning_visitor::visit(ir_dereference_variable *ir)
-{
- ir_variable *var = this->get_remapped_variable(ir->variable_referenced());
- this->result = new ir_dereference_variable(var);
-}
-
-void
-ir_function_cloning_visitor::visit(ir_dereference_array *ir)
-{
- ir->array->accept(this);
-
- ir_rvalue *var = this->result->as_rvalue();
-
- ir->array_index->accept(this);
-
- ir_rvalue *index = this->result->as_rvalue();
-
- this->result = new ir_dereference_array(var, index);
-}
-
-void
-ir_function_cloning_visitor::visit(ir_dereference_record *ir)
-{
- ir->record->accept(this);
-
- ir_rvalue *var = this->result->as_rvalue();
-
- this->result = new ir_dereference_record(var, strdup(ir->field));
-}
-
-void
-ir_function_cloning_visitor::visit(ir_assignment *ir)
-{
- ir_rvalue *lhs, *rhs, *condition = NULL;
-
- ir->lhs->accept(this);
- lhs = this->result->as_rvalue();
-
- ir->rhs->accept(this);
- rhs = this->result->as_rvalue();
-
- if (ir->condition) {
- ir->condition->accept(this);
- condition = this->result->as_rvalue();
- }
-
- this->result = new ir_assignment(lhs, rhs, condition);
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_constant *ir)
-{
- this->result = ir->clone();
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_call *ir)
-{
- exec_list parameters;
-
- foreach_iter(exec_list_iterator, iter, *ir) {
- ir_rvalue *param = (ir_rvalue *)iter.get();
-
- param->accept(this);
- parameters.push_tail(this->result);
- }
-
- this->result = new ir_call(ir->get_callee(), ¶meters);
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_return *ir)
-{
- ir_rvalue *rval;
-
- assert(this->retval);
-
- rval = ir->get_value();
- rval->accept(this);
- rval = this->result->as_rvalue();
- assert(rval);
-
- result = new ir_assignment(new ir_dereference_variable(this->retval), rval,
- NULL);
-}
-
-
-void
-ir_function_cloning_visitor::visit(ir_if *ir)
-{
- /* FINISHME: Implement if cloning. */
- assert(0);
-
- (void) ir;
- result = NULL;
+ return key1 == key2 ? 0 : 1;
}
bool
int num_parameters;
int i;
ir_variable *retval = NULL;
+ struct hash_table *ht;
+
+ ht = hash_table_ctor(0, hash_func, hash_compare_func);
num_parameters = 0;
foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters)
next_ir->insert_before(retval);
}
- ir_function_cloning_visitor v = ir_function_cloning_visitor(retval);
-
/* Generate the declarations for the parameters to our inlined code,
* and set up the mapping of real function body variables to ours.
*/
ir_rvalue *param = (ir_rvalue *) param_iter.get();
/* Generate a new variable for the parameter. */
- parameters[i] = sig_param->clone();
+ parameters[i] = (ir_variable *)sig_param->clone(ht);
next_ir->insert_before(parameters[i]);
- v.remap_variable(sig_param, parameters[i]);
-
/* Move the actual param into our param variable if it's an 'in' type. */
if (parameters[i]->mode == ir_var_in ||
parameters[i]->mode == ir_var_inout) {
foreach_iter(exec_list_iterator, iter, callee->body) {
ir_instruction *ir = (ir_instruction *)iter.get();
- ir->accept(&v);
- assert(v.result);
- next_ir->insert_before(v.result);
+ next_ir->insert_before(ir->clone(ht));
}
/* Copy back the value of any 'out' parameters from the function body
delete [] parameters;
+ hash_table_dtor(ht);
+
if (retval)
return new ir_dereference_variable(retval);
else
static void print_type(const glsl_type *t);
void
-ir_instruction::print(void)
+ir_instruction::print(void) const
{
+ ir_instruction *deconsted = const_cast<ir_instruction *>(this);
+
ir_print_visitor v;
- accept(&v);
+ deconsted->accept(&v);
}
void
s_symbol *symbol = SX_AS_SYMBOL(expr);
if (symbol != NULL) {
if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL)
- return new ir_loop_jump(loop_ctx, ir_loop_jump::jump_break);
+ return new ir_loop_jump(ir_loop_jump::jump_break);
if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL)
- return new ir_loop_jump(loop_ctx, ir_loop_jump::jump_continue);
+ return new ir_loop_jump(ir_loop_jump::jump_continue);
}
s_list *list = SX_AS_LIST(expr);
* have an initializer but a later instance does, copy the
* initializer to the version stored in the symbol table.
*/
- existing->constant_value = var->constant_value->clone();
+ existing->constant_value =
+ (ir_constant *)var->constant_value->clone(NULL);
}
} else
uniforms.add_variable(var->name, var);