+/* -*- c++ -*- */
/*
* Copyright © 2010 Intel Corporation
*
* DEALINGS IN THE SOFTWARE.
*/
+#pragma once
+#ifndef IR_H
+#define IR_H
+
#include "list.h"
+#include "ir_visitor.h"
struct ir_program {
void *bong_hits;
};
-
-enum ir_opcodes {
- ir_op_var_decl,
- ir_op_assign,
- ir_op_expression,
- ir_op_dereference,
- ir_op_jump,
- ir_op_label,
- ir_op_constant,
- ir_op_func_sig,
- ir_op_func
-};
-
/**
* Base class of all IR instructions
*/
class ir_instruction : public exec_node {
public:
- unsigned mode;
const struct glsl_type *type;
-protected:
- ir_instruction(int mode);
+ class ir_constant *constant_expression_value();
+ virtual void accept(ir_visitor *) = 0;
-private:
/**
- * Dummy constructor to catch bad constructors in derived classes.
+ * \name IR instruction downcast functions
*
- * Every derived must use the constructor that sets the instructions
- * mode. Having the \c void constructor private prevents derived classes
- * from accidentally doing the wrong thing.
+ * These functions either cast the object to a derived class or return
+ * \c NULL if the object's type does not match the specified derived class.
+ * Additional downcast functions will be added as needed.
*/
- ir_instruction(void);
+ /*@{*/
+ virtual class ir_variable * as_variable() { return NULL; }
+ virtual class ir_dereference * as_dereference() { return NULL; }
+ virtual class ir_rvalue * as_rvalue() { return NULL; }
+ /*@}*/
+
+protected:
+ ir_instruction()
+ {
+ /* empty */
+ }
+};
+
+
+class ir_rvalue : public ir_instruction {
+public:
+ virtual ir_rvalue * as_rvalue()
+ {
+ return this;
+ }
+
+ virtual bool is_lvalue()
+ {
+ return false;
+ }
+
+protected:
+ ir_rvalue() : ir_instruction() { }
};
ir_var_noperspective
};
+
class ir_variable : public ir_instruction {
public:
ir_variable(const struct glsl_type *, const char *);
+ virtual ir_variable *as_variable()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ /**
+ * 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->read_only = this->read_only;
+ var->centroid = this->centroid;
+ var->invariant = this->invariant;
+ var->mode = this->mode;
+ var->interpolation = this->interpolation;
+
+ return var;
+ }
+
const char *name;
unsigned read_only:1;
public:
ir_label(const char *label);
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
const char *label;
};
/*@{*/
class ir_function_signature : public ir_instruction {
public:
- ir_function_signature(void);
+ ir_function_signature(const glsl_type *return_type);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ /**
+ * Get the name of the function for which this is a signature
+ */
+ const char *function_name() const;
/**
* Function return type.
* Pointer to the label that begins the function definition.
*/
ir_label *definition;
+
+private:
+ /** Function of which this signature is one overload. */
+ class ir_function *function;
+
+ friend class ir_function;
};
*/
class ir_function : public ir_instruction {
public:
- ir_function(void);
+ ir_function(const char *name);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ void add_signature(ir_function_signature *sig)
+ {
+ sig->function = this;
+ signatures.push_tail(sig);
+ }
+
+ /**
+ * Get an iterator for the set of function signatures
+ */
+ exec_list_iterator iterator()
+ {
+ return signatures.iterator();
+ }
+
+ /**
+ * Find a signature that matches a set of actual parameters.
+ */
+ const ir_function_signature *matching_signature(exec_list *actual_param);
/**
* Name of the function.
*/
const char *name;
+private:
+ /**
+ * Set of overloaded functions with this name.
+ */
struct exec_list signatures;
};
+
+inline const char *ir_function_signature::function_name() const
+{
+ return function->name;
+}
/*@}*/
-class ir_expression;
-class ir_dereference;
-class ir_assignment : public ir_instruction {
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
public:
- ir_assignment(ir_instruction *lhs, ir_instruction *rhs,
- ir_expression *condition);
+ ir_if(ir_rvalue *condition)
+ : condition(condition)
+ {
+ /* empty */
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ ir_rvalue *condition;
+ exec_list then_instructions;
+ exec_list else_instructions;
+};
+
+
+class ir_assignment : public ir_rvalue {
+public:
+ ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
/**
* Left-hand side of the assignment.
*/
- ir_dereference *lhs;
+ ir_rvalue *lhs;
/**
* Value being assigned
- *
- * This should be either \c ir_op_expression or \c ir_op_deference.
*/
- ir_instruction *rhs;
+ ir_rvalue *rhs;
/**
* Optional condition for the assignment.
*/
- ir_expression *condition;
+ ir_rvalue *condition;
};
-
+/* Update ir_print_visitor.cpp when updating this list. */
enum ir_expression_operation {
ir_unop_bit_not,
ir_unop_logic_not,
ir_unop_abs,
ir_unop_rcp,
ir_unop_rsq,
+ ir_unop_sqrt,
ir_unop_exp,
ir_unop_log,
+ ir_unop_exp2,
+ ir_unop_log2,
ir_unop_f2i, /**< Float-to-integer conversion. */
ir_unop_i2f, /**< Integer-to-float conversion. */
+ ir_unop_u2f, /**< Unsigned-to-float conversion. */
/**
* \name Unary floating-point rounding operations.
ir_binop_pow
};
-class ir_expression : public ir_instruction {
+class ir_expression : public ir_rvalue {
public:
ir_expression(int op, const struct glsl_type *type,
- ir_instruction *, ir_instruction *);
+ ir_rvalue *, ir_rvalue *);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
ir_expression_operation operation;
- ir_instruction *operands[2];
+ ir_rvalue *operands[2];
};
+/**
+ * IR instruction representing a function call
+ */
+class ir_call : public ir_rvalue {
+public:
+ ir_call(const ir_function_signature *callee, exec_list *actual_parameters)
+ : ir_rvalue(), callee(callee)
+ {
+ assert(callee->return_type != NULL);
+ type = callee->return_type;
+ actual_parameters->move_nodes_to(& this->actual_parameters);
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ /**
+ * Get a generic ir_call object when an error occurs
+ */
+ static ir_call *get_error_instruction();
+
+ /**
+ * Get an iterator for the set of acutal parameters
+ */
+ exec_list_iterator iterator()
+ {
+ return actual_parameters.iterator();
+ }
+
+ /**
+ * Get the name of the function being called.
+ */
+ const char *callee_name() const
+ {
+ return callee->function_name();
+ }
+
+private:
+ ir_call()
+ : ir_rvalue(), callee(NULL)
+ {
+ /* empty */
+ }
+
+ const ir_function_signature *callee;
+ exec_list actual_parameters;
+};
+
+
+/**
+ * \name Jump-like IR instructions.
+ *
+ * These include \c break, \c continue, \c return, and \c discard.
+ */
+/*@{*/
+class ir_jump : public ir_instruction {
+protected:
+ ir_jump()
+ : ir_instruction()
+ {
+ /* empty */
+ }
+};
+
+class ir_return : public ir_jump {
+public:
+ ir_return()
+ : value(NULL)
+ {
+ /* empty */
+ }
+
+ ir_return(ir_rvalue *value)
+ : value(value)
+ {
+ /* empty */
+ }
+
+ ir_rvalue *get_value() const
+ {
+ return value;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+private:
+ ir_rvalue *value;
+};
+/*@}*/
+
+
struct ir_swizzle_mask {
unsigned x:2;
unsigned y:2;
/**
* Number of components in the swizzle.
*/
- unsigned num_components:2;
+ unsigned num_components:3;
/**
* Does the swizzle contain duplicate components?
unsigned has_duplicates:1;
};
-class ir_dereference : public ir_instruction {
+
+class ir_swizzle : public ir_rvalue {
+public:
+ ir_swizzle(ir_rvalue *, unsigned x, unsigned y, unsigned z, unsigned w,
+ unsigned count);
+ /**
+ * Construct an ir_swizzle from the textual representation. Can fail.
+ */
+ static ir_swizzle *create(ir_rvalue *, const char *, unsigned vector_length);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ bool is_lvalue()
+ {
+ return val->is_lvalue() && !mask.has_duplicates;
+ }
+
+ ir_rvalue *val;
+ ir_swizzle_mask mask;
+};
+
+
+class ir_dereference : public ir_rvalue {
public:
ir_dereference(struct ir_instruction *);
+ ir_dereference(ir_instruction *variable, ir_rvalue *array_index);
+
+ virtual ir_dereference *as_dereference()
+ {
+ return this;
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ bool is_lvalue()
+ {
+ if (var == NULL)
+ return false;
+
+ ir_variable *const as_var = var->as_variable();
+ if (as_var == NULL)
+ return false;
+
+ return !as_var->read_only;
+ }
+
enum {
ir_reference_variable,
ir_reference_array,
/**
* Object being dereferenced.
*
- * Must be either an \c ir_variable or an \c ir_deference.
+ * Must be either an \c ir_variable or an \c ir_rvalue.
*/
ir_instruction *var;
union {
- ir_expression *array_index;
+ ir_rvalue *array_index;
const char *field;
- struct ir_swizzle_mask swizzle;
} selector;
};
-class ir_constant : public ir_instruction {
+class ir_constant : public ir_rvalue {
public:
ir_constant(const struct glsl_type *type, const void *data);
+ ir_constant(bool b);
+ ir_constant(unsigned int u);
+ ir_constant(int i);
+ ir_constant(float f);
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
/**
* Value of the constant.
} value;
};
+
+extern void
+_mesa_glsl_initialize_variables(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+extern void
+_mesa_glsl_initialize_functions(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
+#endif /* IR_H */