#include <stdio.h>
#include <stdlib.h>
-#include "ralloc.h"
+#include "util/ralloc.h"
#include "glsl_types.h"
#include "list.h"
#include "ir_visitor.h"
* types, this allows writing very straightforward, readable code.
*/
enum ir_node_type {
- /**
- * Zero is unused so that the IR validator can detect cases where
- * \c ir_instruction::ir_type has not been initialized.
- */
- ir_type_unset,
- ir_type_variable,
- ir_type_assignment,
- ir_type_call,
- ir_type_constant,
ir_type_dereference_array,
ir_type_dereference_record,
ir_type_dereference_variable,
- ir_type_discard,
+ ir_type_constant,
ir_type_expression,
+ ir_type_swizzle,
+ ir_type_texture,
+ ir_type_variable,
+ ir_type_assignment,
+ ir_type_call,
ir_type_function,
ir_type_function_signature,
ir_type_if,
ir_type_loop,
ir_type_loop_jump,
ir_type_return,
- ir_type_swizzle,
- ir_type_texture,
+ ir_type_discard,
ir_type_emit_vertex,
ir_type_end_primitive,
- ir_type_max /**< maximum ir_type enum number, for validation */
+ ir_type_max, /**< maximum ir_type enum number, for validation */
+ ir_type_unset = ir_type_max
};
/** ir_print_visitor helper for debugging. */
void print(void) const;
+ void fprint(FILE *f) const;
virtual void accept(ir_visitor *) = 0;
virtual ir_visitor_status accept(ir_hierarchical_visitor *) = 0;
* Additional downcast functions will be added as needed.
*/
/*@{*/
- virtual class ir_variable * as_variable() { return NULL; }
- virtual class ir_function * as_function() { return NULL; }
- virtual class ir_dereference * as_dereference() { return NULL; }
- virtual class ir_dereference_array * as_dereference_array() { return NULL; }
- virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
- virtual class ir_dereference_record *as_dereference_record() { return NULL; }
- virtual class ir_expression * as_expression() { return NULL; }
- virtual class ir_rvalue * as_rvalue() { return NULL; }
- virtual class ir_loop * as_loop() { return NULL; }
- virtual class ir_assignment * as_assignment() { return NULL; }
- virtual class ir_call * as_call() { return NULL; }
- virtual class ir_return * as_return() { return NULL; }
- virtual class ir_if * as_if() { return NULL; }
- virtual class ir_swizzle * as_swizzle() { return NULL; }
- virtual class ir_texture * as_texture() { return NULL; }
- virtual class ir_constant * as_constant() { return NULL; }
- virtual class ir_discard * as_discard() { return NULL; }
- virtual class ir_jump * as_jump() { return NULL; }
+ class ir_rvalue *as_rvalue()
+ {
+ if (ir_type == ir_type_dereference_array ||
+ ir_type == ir_type_dereference_record ||
+ ir_type == ir_type_dereference_variable ||
+ ir_type == ir_type_constant ||
+ ir_type == ir_type_expression ||
+ ir_type == ir_type_swizzle ||
+ ir_type == ir_type_texture)
+ return (class ir_rvalue *) this;
+ return NULL;
+ }
+
+ class ir_dereference *as_dereference()
+ {
+ if (ir_type == ir_type_dereference_array ||
+ ir_type == ir_type_dereference_record ||
+ ir_type == ir_type_dereference_variable)
+ return (class ir_dereference *) this;
+ return NULL;
+ }
+
+ class ir_jump *as_jump()
+ {
+ if (ir_type == ir_type_loop_jump ||
+ ir_type == ir_type_return ||
+ ir_type == ir_type_discard)
+ return (class ir_jump *) this;
+ return NULL;
+ }
+
+ #define AS_CHILD(TYPE) \
+ class ir_##TYPE * as_##TYPE() \
+ { \
+ return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \
+ }
+ AS_CHILD(variable)
+ AS_CHILD(function)
+ AS_CHILD(dereference_array)
+ AS_CHILD(dereference_variable)
+ AS_CHILD(dereference_record)
+ AS_CHILD(expression)
+ AS_CHILD(loop)
+ AS_CHILD(assignment)
+ AS_CHILD(call)
+ AS_CHILD(return)
+ AS_CHILD(if)
+ AS_CHILD(swizzle)
+ AS_CHILD(texture)
+ AS_CHILD(constant)
+ AS_CHILD(discard)
+ #undef AS_CHILD
/*@}*/
/**
virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
protected:
+ ir_instruction(enum ir_node_type t)
+ : ir_type(t)
+ {
+ }
+
+private:
ir_instruction()
{
- ir_type = ir_type_unset;
+ assert(!"Should not get here.");
}
};
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_rvalue * as_rvalue()
- {
- return this;
- }
-
ir_rvalue *as_rvalue_to_saturate();
virtual bool is_lvalue() const
*/
virtual bool is_basis() const;
+ /**
+ * Determine if an r-value is an unsigned integer constant which can be
+ * stored in 16 bits.
+ *
+ * \sa ir_constant::is_uint16_constant.
+ */
+ virtual bool is_uint16_constant() const { return false; }
/**
* Return a generic value of error_type.
static ir_rvalue *error_value(void *mem_ctx);
protected:
- ir_rvalue();
+ ir_rvalue(enum ir_node_type t);
};
virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
- virtual ir_variable *as_variable()
- {
- return this;
- }
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
void reinit_interface_type(const struct glsl_type *type)
{
if (this->max_ifc_array_access != NULL) {
-#ifndef _NDEBUG
+#ifndef NDEBUG
/* Redeclaring gl_PerVertex is only allowed if none of the built-ins
* it defines have been accessed yet; so it's safe to throw away the
* old max_ifc_array_access pointer, since all of its values are
unsigned centroid:1;
unsigned sample:1;
unsigned invariant:1;
+ unsigned precise:1;
/**
* Has this variable been used for reading or writing?
*/
unsigned location_frac:2;
+ /**
+ * Layout of the matrix. Uses glsl_matrix_layout values.
+ */
+ unsigned matrix_layout:2;
+
/**
* Non-zero if this variable was created by lowering a named interface
* block which was not an array.
*/
unsigned from_named_ifc_block_array:1;
+ /**
+ * Non-zero if the variable must be a shader input. This is useful for
+ * constraints on function parameters.
+ */
+ unsigned must_be_shader_input:1;
+
/**
* \brief Layout qualifier for gl_FragDepth.
*
*/
int location;
+ /**
+ * Vertex stream output identifier.
+ */
+ unsigned stream;
+
/**
* output index for dual source blending.
*/
unsigned offset;
} atomic;
+ /**
+ * ARB_shader_image_load_store qualifiers.
+ */
+ struct {
+ bool read_only; /**< "readonly" qualifier. */
+ bool write_only; /**< "writeonly" qualifier. */
+ bool coherent;
+ bool _volatile;
+ bool restrict_flag;
+
+ /** Image internal format if specified explicitly, otherwise GL_NONE. */
+ GLenum format;
+ } image;
+
/**
* Highest element accessed with a constant expression array index
*
virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
- virtual ir_function *as_function()
- {
- return this;
- }
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
*/
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_param,
+ bool allow_builtins,
bool *match_is_exact);
/**
* conversions into account.
*/
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
- const exec_list *actual_param);
+ const exec_list *actual_param,
+ bool allow_builtins);
/**
* Find a signature that exactly matches a set of actual parameters without
class ir_if : public ir_instruction {
public:
ir_if(ir_rvalue *condition)
- : condition(condition)
+ : ir_instruction(ir_type_if), condition(condition)
{
- ir_type = ir_type_if;
}
virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
- virtual ir_if *as_if()
- {
- return this;
- }
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual ir_loop *as_loop()
- {
- return this;
- }
-
/** List of ir_instruction that make up the body of the loop. */
exec_list body_instructions;
};
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual ir_assignment * as_assignment()
- {
- return this;
- }
-
/**
* Get a whole variable written by an assignment
*
ir_unop_noise,
+ /**
+ * Interpolate fs input at centroid
+ *
+ * operand0 is the fs input.
+ */
+ ir_unop_interpolate_at_centroid,
+
/**
* A sentinel marking the last of the unary operations.
*/
- ir_last_unop = ir_unop_noise,
+ ir_last_unop = ir_unop_interpolate_at_centroid,
ir_binop_add,
ir_binop_sub,
*/
ir_binop_vector_extract,
+ /**
+ * Interpolate fs input at offset
+ *
+ * operand0 is the fs input
+ * operand1 is the offset from the pixel center
+ */
+ ir_binop_interpolate_at_offset,
+
+ /**
+ * Interpolate fs input at sample position
+ *
+ * operand0 is the fs input
+ * operand1 is the sample ID
+ */
+ ir_binop_interpolate_at_sample,
+
/**
* A sentinel marking the last of the binary operations.
*/
- ir_last_binop = ir_binop_vector_extract,
+ ir_last_binop = ir_binop_interpolate_at_sample,
/**
* \name Fused floating-point multiply-add, part of ARB_gpu_shader5.
*/
ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2);
- virtual ir_expression *as_expression()
- {
- return this;
- }
-
virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
? this->type->vector_elements : get_num_operands(operation);
}
+ /**
+ * Return whether the expression operates on vectors horizontally.
+ */
+ bool is_horizontal() const
+ {
+ return operation == ir_binop_all_equal ||
+ operation == ir_binop_any_nequal ||
+ operation == ir_unop_any ||
+ operation == ir_binop_dot ||
+ operation == ir_quadop_vector;
+ }
+
/**
* Return a string representing this expression's operator.
*/
ir_call(ir_function_signature *callee,
ir_dereference_variable *return_deref,
exec_list *actual_parameters)
- : return_deref(return_deref), callee(callee)
+ : ir_instruction(ir_type_call), return_deref(return_deref), callee(callee)
{
- ir_type = ir_type_call;
assert(callee->return_type != NULL);
actual_parameters->move_nodes_to(& this->actual_parameters);
this->use_builtin = callee->is_builtin();
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_call *as_call()
- {
- return this;
- }
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
/*@{*/
class ir_jump : public ir_instruction {
protected:
- ir_jump()
+ ir_jump(enum ir_node_type t)
+ : ir_instruction(t)
{
- ir_type = ir_type_unset;
- }
-
-public:
- virtual ir_jump *as_jump()
- {
- return this;
}
};
class ir_return : public ir_jump {
public:
ir_return()
- : value(NULL)
+ : ir_jump(ir_type_return), value(NULL)
{
- this->ir_type = ir_type_return;
}
ir_return(ir_rvalue *value)
- : value(value)
+ : ir_jump(ir_type_return), value(value)
{
- this->ir_type = ir_type_return;
}
virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
- virtual ir_return *as_return()
- {
- return this;
- }
-
ir_rvalue *get_value() const
{
return value;
};
ir_loop_jump(jump_mode mode)
+ : ir_jump(ir_type_loop_jump)
{
- this->ir_type = ir_type_loop_jump;
this->mode = mode;
}
class ir_discard : public ir_jump {
public:
ir_discard()
+ : ir_jump(ir_type_discard)
{
- this->ir_type = ir_type_discard;
this->condition = NULL;
}
ir_discard(ir_rvalue *cond)
+ : ir_jump(ir_type_discard)
{
- this->ir_type = ir_type_discard;
this->condition = cond;
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual ir_discard *as_discard()
- {
- return this;
- }
-
ir_rvalue *condition;
};
/*@}*/
class ir_texture : public ir_rvalue {
public:
ir_texture(enum ir_texture_opcode op)
- : op(op), sampler(NULL), coordinate(NULL), projector(NULL),
+ : ir_rvalue(ir_type_texture),
+ op(op), sampler(NULL), coordinate(NULL), projector(NULL),
shadow_comparitor(NULL), offset(NULL)
{
- this->ir_type = ir_type_texture;
memset(&lod_info, 0, sizeof(lod_info));
}
v->visit(this);
}
- virtual ir_texture *as_texture()
- {
- return this;
- }
-
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_swizzle *as_swizzle()
- {
- return this;
- }
-
/**
* Construct an ir_swizzle from the textual representation. Can fail.
*/
public:
virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
- virtual ir_dereference *as_dereference()
- {
- return this;
- }
-
bool is_lvalue() const;
/**
*/
virtual ir_variable *variable_referenced() const = 0;
- /**
- * Get the constant that is ultimately referenced by an r-value,
- * in a constant expression evaluation context.
- *
- * The offset is used when the reference is to a specific column of
- * a matrix.
- */
- virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const = 0;
+protected:
+ ir_dereference(enum ir_node_type t)
+ : ir_rvalue(t)
+ {
+ }
};
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_dereference_variable *as_dereference_variable()
- {
- return this;
- }
-
virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
/**
return this->var;
}
- /**
- * Get the constant that is ultimately referenced by an r-value,
- * in a constant expression evaluation context.
- *
- * The offset is used when the reference is to a specific column of
- * a matrix.
- */
- virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
-
virtual ir_variable *whole_variable_referenced()
{
/* ir_dereference_variable objects always dereference the entire
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_dereference_array *as_dereference_array()
- {
- return this;
- }
-
virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
/**
return this->array->variable_referenced();
}
- /**
- * Get the constant that is ultimately referenced by an r-value,
- * in a constant expression evaluation context.
- *
- * The offset is used when the reference is to a specific column of
- * a matrix.
- */
- virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_dereference_record *as_dereference_record()
- {
- return this;
- }
-
/**
* Get the variable that is ultimately referenced by an r-value
*/
return this->record->variable_referenced();
}
- /**
- * Get the constant that is ultimately referenced by an r-value,
- * in a constant expression evaluation context.
- *
- * The offset is used when the reference is to a specific column of
- * a matrix.
- */
- virtual void constant_referenced(struct hash_table *variable_context, ir_constant *&store, int &offset) const;
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
- virtual ir_constant *as_constant()
- {
- return this;
- }
-
virtual void accept(ir_visitor *v)
{
v->visit(this);
virtual bool is_negative_one() const;
virtual bool is_basis() const;
+ /**
+ * Return true for constants that could be stored as 16-bit unsigned values.
+ *
+ * Note that this will return true even for signed integer ir_constants, as
+ * long as the value is non-negative and fits in 16-bits.
+ */
+ virtual bool is_uint16_constant() const;
+
/**
* Value of the constant.
*
ir_constant(void);
};
-/*@}*/
-
/**
* IR instruction to emit a vertex in a geometry shader.
*/
class ir_emit_vertex : public ir_instruction {
public:
- ir_emit_vertex()
+ ir_emit_vertex(ir_rvalue *stream)
+ : ir_instruction(ir_type_emit_vertex),
+ stream(stream)
{
- ir_type = ir_type_emit_vertex;
+ assert(stream);
}
virtual void accept(ir_visitor *v)
v->visit(this);
}
- virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const
+ virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *ht) const
{
- return new(mem_ctx) ir_emit_vertex();
+ return new(mem_ctx) ir_emit_vertex(this->stream->clone(mem_ctx, ht));
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ int stream_id() const
+ {
+ return stream->as_constant()->value.i[0];
+ }
+
+ ir_rvalue *stream;
};
/**
*/
class ir_end_primitive : public ir_instruction {
public:
- ir_end_primitive()
+ ir_end_primitive(ir_rvalue *stream)
+ : ir_instruction(ir_type_end_primitive),
+ stream(stream)
{
- ir_type = ir_type_end_primitive;
+ assert(stream);
}
virtual void accept(ir_visitor *v)
v->visit(this);
}
- virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const
+ virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *ht) const
{
- return new(mem_ctx) ir_end_primitive();
+ return new(mem_ctx) ir_end_primitive(this->stream->clone(mem_ctx, ht));
}
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+
+ int stream_id() const
+ {
+ return stream->as_constant()->value.i[0];
+ }
+
+ ir_rvalue *stream;
};
+/*@}*/
+
/**
* Apply a visitor to each IR node in a list
*/
const char *
mode_string(const ir_variable *var);
+/**
+ * Built-in / reserved GL variables names start with "gl_"
+ */
+static inline bool
+is_gl_identifier(const char *s)
+{
+ return s && s[0] == 'g' && s[1] == 'l' && s[2] == '_';
+}
+
extern "C" {
#endif /* __cplusplus */
-extern void _mesa_print_ir(struct exec_list *instructions,
+extern void _mesa_print_ir(FILE *f, struct exec_list *instructions,
struct _mesa_glsl_parse_state *state);
+extern void
+fprint_ir(FILE *f, const void *instruction);
+
#ifdef __cplusplus
} /* extern "C" */
#endif