aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/Makefile.am1
-rw-r--r--mesalib/src/glsl/SConscript2
-rw-r--r--mesalib/src/glsl/ast.h11
-rw-r--r--mesalib/src/glsl/ast_function.cpp6
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp114
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll3
-rw-r--r--mesalib/src/glsl/glsl_parser.yy69
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp5
-rw-r--r--mesalib/src/glsl/glsl_types.cpp22
-rw-r--r--mesalib/src/glsl/glsl_types.h3
-rw-r--r--mesalib/src/glsl/ir.cpp65
-rw-r--r--mesalib/src/glsl/ir.h230
-rw-r--r--mesalib/src/glsl/ir_function.cpp199
-rw-r--r--mesalib/src/glsl/ir_validate.cpp2
-rw-r--r--mesalib/src/glsl/loop_analysis.cpp6
15 files changed, 488 insertions, 250 deletions
diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am
index fd0e837d1..00261fd0d 100644
--- a/mesalib/src/glsl/Makefile.am
+++ b/mesalib/src/glsl/Makefile.am
@@ -114,6 +114,7 @@ libglcpp_la_SOURCES = \
glcpp_glcpp_SOURCES = \
glcpp/glcpp.c \
+ tests/common.c \
$(top_srcdir)/src/mesa/program/prog_hash_table.c
glcpp_glcpp_LDADD = \
libglcpp.la \
diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript
index fe9d50732..dc354775a 100644
--- a/mesalib/src/glsl/SConscript
+++ b/mesalib/src/glsl/SConscript
@@ -106,6 +106,6 @@ env.Alias('glsl_compiler', glsl_compiler)
glcpp = env.Program(
target = 'glcpp/glcpp',
- source = ['glcpp/glcpp.c'] + mesa_objs,
+ source = ['glcpp/glcpp.c', 'tests/common.c'] + mesa_objs,
)
env.Alias('glcpp', glcpp)
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h
index a59ebcb9f..fc80e780e 100644
--- a/mesalib/src/glsl/ast.h
+++ b/mesalib/src/glsl/ast.h
@@ -428,6 +428,7 @@ struct ast_type_qualifier {
union {
struct {
unsigned invariant:1;
+ unsigned precise:1;
unsigned constant:1;
unsigned attribute:1;
unsigned varying:1;
@@ -749,13 +750,11 @@ public:
exec_list declarations;
/**
- * Special flag for vertex shader "invariant" declarations.
- *
- * Vertex shaders can contain "invariant" variable redeclarations that do
- * not include a type. For example, "invariant gl_Position;". This flag
- * is used to note these cases when no type is specified.
+ * Flags for redeclarations. In these cases, no type is specified, to
+ * `type` is allowed to be NULL. In all other cases, this would be an error.
*/
- int invariant;
+ int invariant; /** < `invariant` redeclaration */
+ int precise; /** < `precise` redeclaration */
};
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 4b8447067..8e91a1e67 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -701,7 +701,7 @@ process_vec_mat_constructor(exec_list *instructions,
glsl_type::get_instance(GLSL_TYPE_FLOAT,
ir->type->vector_elements,
ir->type->matrix_columns);
- if (result->type->can_implicitly_convert_to(desired_type)) {
+ if (result->type->can_implicitly_convert_to(desired_type, state)) {
/* Even though convert_component() implements the constructor
* conversion rules (not the implicit conversion rules), its safe
* to use it here because we already checked that the implicit
@@ -830,7 +830,7 @@ process_array_constructor(exec_list *instructions,
glsl_type::get_instance(GLSL_TYPE_FLOAT,
ir->type->vector_elements,
ir->type->matrix_columns);
- if (result->type->can_implicitly_convert_to(desired_type)) {
+ if (result->type->can_implicitly_convert_to(desired_type, state)) {
/* Even though convert_component() implements the constructor
* conversion rules (not the implicit conversion rules), its safe
* to use it here because we already checked that the implicit
@@ -1560,7 +1560,7 @@ ast_function_expression::hir(exec_list *instructions,
foreach_list (n, &this->expressions) {
ast_node *ast = exec_node_data(ast_node, n, link);
- ir_rvalue *result = ast->hir(instructions, state)->as_rvalue();
+ ir_rvalue *result = ast->hir(instructions, state);
/* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
*
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index f230a70a3..d1c77f1ec 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -164,6 +164,31 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
}
+static ir_expression_operation
+get_conversion_operation(const glsl_type *to, const glsl_type *from,
+ struct _mesa_glsl_parse_state *state)
+{
+ switch (to->base_type) {
+ case GLSL_TYPE_FLOAT:
+ switch (from->base_type) {
+ case GLSL_TYPE_INT: return ir_unop_i2f;
+ case GLSL_TYPE_UINT: return ir_unop_u2f;
+ default: return (ir_expression_operation)0;
+ }
+
+ case GLSL_TYPE_UINT:
+ if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable)
+ return (ir_expression_operation)0;
+ switch (from->base_type) {
+ case GLSL_TYPE_INT: return ir_unop_i2u;
+ default: return (ir_expression_operation)0;
+ }
+
+ default: return (ir_expression_operation)0;
+ }
+}
+
+
/**
* If a conversion is available, convert one operand to a different type
*
@@ -185,9 +210,7 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
if (to->base_type == from->type->base_type)
return true;
- /* This conversion was added in GLSL 1.20. If the compilation mode is
- * GLSL 1.10, the conversion is skipped.
- */
+ /* Prior to GLSL 1.20, there are no implicit conversions */
if (!state->is_version(120, 0))
return false;
@@ -195,36 +218,25 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
*
* "There are no implicit array or structure conversions. For
* example, an array of int cannot be implicitly converted to an
- * array of float. There are no implicit conversions between
- * signed and unsigned integers."
- */
- /* FINISHME: The above comment is partially a lie. There is int/uint
- * FINISHME: conversion for immediate constants.
+ * array of float.
*/
- if (!to->is_float() || !from->type->is_numeric())
+ if (!to->is_numeric() || !from->type->is_numeric())
return false;
- /* Convert to a floating point type with the same number of components
- * as the original type - i.e. int to float, not int to vec4.
+ /* We don't actually want the specific type `to`, we want a type
+ * with the same base type as `to`, but the same vector width as
+ * `from`.
*/
- to = glsl_type::get_instance(GLSL_TYPE_FLOAT, from->type->vector_elements,
- from->type->matrix_columns);
+ to = glsl_type::get_instance(to->base_type, from->type->vector_elements,
+ from->type->matrix_columns);
- switch (from->type->base_type) {
- case GLSL_TYPE_INT:
- from = new(ctx) ir_expression(ir_unop_i2f, to, from, NULL);
- break;
- case GLSL_TYPE_UINT:
- from = new(ctx) ir_expression(ir_unop_u2f, to, from, NULL);
- break;
- case GLSL_TYPE_BOOL:
- from = new(ctx) ir_expression(ir_unop_b2f, to, from, NULL);
- break;
- default:
- assert(0);
+ ir_expression_operation op = get_conversion_operation(to, from->type, state);
+ if (op) {
+ from = new(ctx) ir_expression(op, to, from, NULL);
+ return true;
+ } else {
+ return false;
}
-
- return true;
}
@@ -2393,6 +2405,17 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
}
}
+ if (qual->flags.q.precise) {
+ if (var->data.used) {
+ _mesa_glsl_error(loc, state,
+ "variable `%s' may not be redeclared "
+ "`precise' after being used",
+ var->name);
+ } else {
+ var->data.precise = 1;
+ }
+ }
+
if (qual->flags.q.constant || qual->flags.q.attribute
|| qual->flags.q.uniform
|| (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT)))
@@ -3163,8 +3186,45 @@ ast_declarator_list::hir(exec_list *instructions,
return NULL;
}
+ if (this->precise) {
+ assert(this->type == NULL);
+
+ foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+ assert(decl->array_specifier == NULL);
+ assert(decl->initializer == NULL);
+
+ ir_variable *const earlier =
+ state->symbols->get_variable(decl->identifier);
+ if (earlier == NULL) {
+ _mesa_glsl_error(& loc, state,
+ "undeclared variable `%s' cannot be marked "
+ "precise", decl->identifier);
+ } else if (state->current_function != NULL &&
+ !state->symbols->name_declared_this_scope(decl->identifier)) {
+ /* Note: we have to check if we're in a function, since
+ * builtins are treated as having come from another scope.
+ */
+ _mesa_glsl_error(& loc, state,
+ "variable `%s' from an outer scope may not be "
+ "redeclared `precise' in this scope",
+ earlier->name);
+ } else if (earlier->data.used) {
+ _mesa_glsl_error(& loc, state,
+ "variable `%s' may not be redeclared "
+ "`precise' after being used",
+ earlier->name);
+ } else {
+ earlier->data.precise = true;
+ }
+ }
+
+ /* Precise redeclarations do not have r-values either. */
+ return NULL;
+ }
+
assert(this->type != NULL);
assert(!this->invariant);
+ assert(!this->precise);
/* The type specifier may contain a structure definition. Process that
* before any of the variable declarations.
diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll
index 760235127..6c3f9b692 100644
--- a/mesalib/src/glsl/glsl_lexer.ll
+++ b/mesalib/src/glsl/glsl_lexer.ll
@@ -338,6 +338,9 @@ samplerExternalOES {
return IDENTIFIER;
}
+ /* keywords available with ARB_gpu_shader5 */
+precise KEYWORD_WITH_ALT(400, 0, 400, 0, yyextra->ARB_gpu_shader5_enable, PRECISE);
+
/* keywords available with ARB_shader_image_load_store */
image1D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE1D);
image2D KEYWORD_WITH_ALT(130, 300, 420, 0, yyextra->ARB_shader_image_load_store_enable, IMAGE2D);
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index b71b240de..b69802ddb 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -129,7 +129,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK
%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4
-%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING
+%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING SAMPLE
%token NOPERSPECTIVE FLAT SMOOTH
%token MAT2X2 MAT2X3 MAT2X4
%token MAT3X2 MAT3X3 MAT3X4
@@ -167,7 +167,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
%token SUB_ASSIGN
-%token INVARIANT
+%token INVARIANT PRECISE
%token LOWP MEDIUMP HIGHP SUPERP PRECISION
%token VERSION_TOK EXTENSION LINE COLON EOL INTERFACE OUTPUT
@@ -184,7 +184,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4
%token SAMPLER3DRECT
%token SIZEOF CAST NAMESPACE USING
-%token RESOURCE PATCH SAMPLE
+%token RESOURCE PATCH
%token SUBROUTINE
%token ERROR_TOK
@@ -932,14 +932,22 @@ parameter_qualifier:
$$ = $2;
$$.flags.q.constant = 1;
}
+ | PRECISE parameter_qualifier
+ {
+ if ($2.flags.q.precise)
+ _mesa_glsl_error(&@1, state, "duplicate precise qualifier");
+
+ $$ = $2;
+ $$.flags.q.precise = 1;
+ }
| parameter_direction_qualifier parameter_qualifier
{
if (($1.flags.q.in || $1.flags.q.out) && ($2.flags.q.in || $2.flags.q.out))
_mesa_glsl_error(&@1, state, "duplicate in/out/inout qualifier");
if (!state->ARB_shading_language_420pack_enable && $2.flags.q.constant)
- _mesa_glsl_error(&@1, state, "const must be specified before "
- "in/out/inout");
+ _mesa_glsl_error(&@1, state, "in/out/inout must come after const "
+ "or precise");
$$ = $1;
$$.merge_qualifier(&@1, state, $2);
@@ -1072,7 +1080,7 @@ single_declaration:
$$->set_location_range(@1, @2);
$$->declarations.push_tail(&decl->link);
}
- | INVARIANT variable_identifier // Vertex only.
+ | INVARIANT variable_identifier
{
void *ctx = state;
ast_declaration *decl = new(ctx) ast_declaration($2, NULL, NULL);
@@ -1084,6 +1092,18 @@ single_declaration:
$$->declarations.push_tail(&decl->link);
}
+ | PRECISE variable_identifier
+ {
+ void *ctx = state;
+ ast_declaration *decl = new(ctx) ast_declaration($2, NULL, NULL);
+ decl->set_location(@2);
+
+ $$ = new(ctx) ast_declarator_list(NULL);
+ $$->set_location_range(@1, @2);
+ $$->precise = true;
+
+ $$->declarations.push_tail(&decl->link);
+ }
;
fully_specified_type:
@@ -1499,6 +1519,11 @@ type_qualifier:
memset(& $$, 0, sizeof($$));
$$.flags.q.invariant = 1;
}
+ | PRECISE
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.precise = 1;
+ }
| auxiliary_storage_qualifier
| storage_qualifier
| interpolation_qualifier
@@ -1519,8 +1544,16 @@ type_qualifier:
* Each qualifier's rule ensures that the accumulated qualifiers on the right
* side don't contain any that must appear on the left hand side.
* For example, when processing a storage qualifier, we check that there are
- * no auxiliary, interpolation, layout, or invariant qualifiers to the right.
+ * no auxiliary, interpolation, layout, invariant, or precise qualifiers to the right.
*/
+ | PRECISE type_qualifier
+ {
+ if ($2.flags.q.precise)
+ _mesa_glsl_error(&@1, state, "duplicate \"precise\" qualifier");
+
+ $$ = $2;
+ $$.flags.q.precise = 1;
+ }
| INVARIANT type_qualifier
{
if ($2.flags.q.invariant)
@@ -1531,6 +1564,10 @@ type_qualifier:
"\"invariant\" cannot be used with layout(...)");
}
+ if (!state->ARB_shading_language_420pack_enable && $2.flags.q.precise)
+ _mesa_glsl_error(&@1, state,
+ "\"invariant\" must come after \"precise\"");
+
$$ = $2;
$$.flags.q.invariant = 1;
}
@@ -1554,9 +1591,10 @@ type_qualifier:
"with layout(...)");
}
- if (!state->ARB_shading_language_420pack_enable && $2.flags.q.invariant) {
+ if (!state->ARB_shading_language_420pack_enable &&
+ ($2.flags.q.precise || $2.flags.q.invariant)) {
_mesa_glsl_error(&@1, state, "interpolation qualifiers must come "
- "after \"invariant\"");
+ "after \"precise\" or \"invariant\"");
}
$$ = $1;
@@ -1577,6 +1615,10 @@ type_qualifier:
_mesa_glsl_error(&@1, state, "layout(...) cannot be used with "
"the \"invariant\" qualifier");
+ if ($2.flags.q.precise)
+ _mesa_glsl_error(&@1, state, "layout(...) cannot be used with "
+ "the \"precise\" qualifier");
+
if ($2.has_interpolation()) {
_mesa_glsl_error(&@1, state, "layout(...) cannot be used with "
"interpolation qualifiers");
@@ -1593,7 +1635,8 @@ type_qualifier:
}
if (!state->ARB_shading_language_420pack_enable &&
- ($2.flags.q.invariant || $2.has_interpolation() || $2.has_layout())) {
+ ($2.flags.q.precise || $2.flags.q.invariant ||
+ $2.has_interpolation() || $2.has_layout())) {
_mesa_glsl_error(&@1, state, "auxiliary storage qualifiers must come "
"just before storage qualifiers");
}
@@ -1610,10 +1653,10 @@ type_qualifier:
_mesa_glsl_error(&@1, state, "duplicate storage qualifier");
if (!state->ARB_shading_language_420pack_enable &&
- ($2.flags.q.invariant || $2.has_interpolation() || $2.has_layout() ||
- $2.has_auxiliary_storage())) {
+ ($2.flags.q.precise || $2.flags.q.invariant || $2.has_interpolation() ||
+ $2.has_layout() || $2.has_auxiliary_storage())) {
_mesa_glsl_error(&@1, state, "storage qualifiers must come after "
- "invariant, interpolation, layout and auxiliary "
+ "precise, invariant, interpolation, layout and auxiliary "
"storage qualifiers");
}
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index d3339e779..f3c5bd049 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -1098,8 +1098,10 @@ ast_declarator_list::print(void) const
if (type)
type->print();
- else
+ else if (invariant)
printf("invariant ");
+ else
+ printf("precise ");
foreach_list_const (ptr, & this->declarations) {
if (ptr != this->declarations.get_head())
@@ -1117,6 +1119,7 @@ ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
{
this->type = type;
this->invariant = false;
+ this->precise = false;
}
void
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index 849a79af4..e77146cdf 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -678,7 +678,8 @@ glsl_type::component_slots() const
}
bool
-glsl_type::can_implicitly_convert_to(const glsl_type *desired) const
+glsl_type::can_implicitly_convert_to(const glsl_type *desired,
+ _mesa_glsl_parse_state *state) const
{
if (this == desired)
return true;
@@ -687,10 +688,23 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired) const
if (this->matrix_columns > 1 || desired->matrix_columns > 1)
return false;
+ /* Vector size must match. */
+ if (this->vector_elements != desired->vector_elements)
+ return false;
+
/* int and uint can be converted to float. */
- return desired->is_float()
- && this->is_integer()
- && this->vector_elements == desired->vector_elements;
+ if (desired->is_float() && this->is_integer())
+ return true;
+
+ /* With GLSL 4.0 / ARB_gpu_shader5, int can be converted to uint.
+ * Note that state may be NULL here, when resolving function calls in the
+ * linker. By this time, all the state-dependent checks have already
+ * happened though, so allow anything that's allowed in any shader version. */
+ if ((!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) &&
+ desired->base_type == GLSL_TYPE_UINT && this->base_type == GLSL_TYPE_INT)
+ return true;
+
+ return false;
}
unsigned
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index dca5492ac..35a4e6acc 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -314,7 +314,8 @@ struct glsl_type {
* integers.
* \endverbatim
*/
- bool can_implicitly_convert_to(const glsl_type *desired) const;
+ bool can_implicitly_convert_to(const glsl_type *desired,
+ _mesa_glsl_parse_state *state) const;
/**
* Query whether or not a type is a scalar (non-vector and non-matrix).
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index dec49bd64..2f4a0bec8 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -26,7 +26,8 @@
#include "ir_visitor.h"
#include "glsl_types.h"
-ir_rvalue::ir_rvalue()
+ir_rvalue::ir_rvalue(enum ir_node_type t)
+ : ir_instruction(t)
{
this->type = glsl_type::error_type;
}
@@ -153,8 +154,8 @@ ir_assignment::whole_variable_written()
ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
ir_rvalue *condition, unsigned write_mask)
+ : ir_instruction(ir_type_assignment)
{
- this->ir_type = ir_type_assignment;
this->condition = condition;
this->rhs = rhs;
this->lhs = lhs;
@@ -173,8 +174,8 @@ ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs,
ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
ir_rvalue *condition)
+ : ir_instruction(ir_type_assignment)
{
- this->ir_type = ir_type_assignment;
this->condition = condition;
this->rhs = rhs;
@@ -198,8 +199,8 @@ ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
ir_expression::ir_expression(int op, const struct glsl_type *type,
ir_rvalue *op0, ir_rvalue *op1,
ir_rvalue *op2, ir_rvalue *op3)
+ : ir_rvalue(ir_type_expression)
{
- this->ir_type = ir_type_expression;
this->type = type;
this->operation = ir_expression_operation(op);
this->operands[0] = op0;
@@ -215,9 +216,8 @@ ir_expression::ir_expression(int op, const struct glsl_type *type,
}
ir_expression::ir_expression(int op, ir_rvalue *op0)
+ : ir_rvalue(ir_type_expression)
{
- this->ir_type = ir_type_expression;
-
this->operation = ir_expression_operation(op);
this->operands[0] = op0;
this->operands[1] = NULL;
@@ -324,9 +324,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
}
ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
+ : ir_rvalue(ir_type_expression)
{
- this->ir_type = ir_type_expression;
-
this->operation = ir_expression_operation(op);
this->operands[0] = op0;
this->operands[1] = op1;
@@ -420,9 +419,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1,
ir_rvalue *op2)
+ : ir_rvalue(ir_type_expression)
{
- this->ir_type = ir_type_expression;
-
this->operation = ir_expression_operation(op);
this->operands[0] = op0;
this->operands[1] = op1;
@@ -610,25 +608,25 @@ ir_expression::get_operator(const char *str)
}
ir_constant::ir_constant()
+ : ir_rvalue(ir_type_constant)
{
- this->ir_type = ir_type_constant;
}
ir_constant::ir_constant(const struct glsl_type *type,
const ir_constant_data *data)
+ : ir_rvalue(ir_type_constant)
{
assert((type->base_type >= GLSL_TYPE_UINT)
&& (type->base_type <= GLSL_TYPE_BOOL));
- this->ir_type = ir_type_constant;
this->type = type;
memcpy(& this->value, data, sizeof(this->value));
}
ir_constant::ir_constant(float f, unsigned vector_elements)
+ : ir_rvalue(ir_type_constant)
{
assert(vector_elements <= 4);
- this->ir_type = ir_type_constant;
this->type = glsl_type::get_instance(GLSL_TYPE_FLOAT, vector_elements, 1);
for (unsigned i = 0; i < vector_elements; i++) {
this->value.f[i] = f;
@@ -639,9 +637,9 @@ ir_constant::ir_constant(float f, unsigned vector_elements)
}
ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
+ : ir_rvalue(ir_type_constant)
{
assert(vector_elements <= 4);
- this->ir_type = ir_type_constant;
this->type = glsl_type::get_instance(GLSL_TYPE_UINT, vector_elements, 1);
for (unsigned i = 0; i < vector_elements; i++) {
this->value.u[i] = u;
@@ -652,9 +650,9 @@ ir_constant::ir_constant(unsigned int u, unsigned vector_elements)
}
ir_constant::ir_constant(int integer, unsigned vector_elements)
+ : ir_rvalue(ir_type_constant)
{
assert(vector_elements <= 4);
- this->ir_type = ir_type_constant;
this->type = glsl_type::get_instance(GLSL_TYPE_INT, vector_elements, 1);
for (unsigned i = 0; i < vector_elements; i++) {
this->value.i[i] = integer;
@@ -665,9 +663,9 @@ ir_constant::ir_constant(int integer, unsigned vector_elements)
}
ir_constant::ir_constant(bool b, unsigned vector_elements)
+ : ir_rvalue(ir_type_constant)
{
assert(vector_elements <= 4);
- this->ir_type = ir_type_constant;
this->type = glsl_type::get_instance(GLSL_TYPE_BOOL, vector_elements, 1);
for (unsigned i = 0; i < vector_elements; i++) {
this->value.b[i] = b;
@@ -678,8 +676,8 @@ ir_constant::ir_constant(bool b, unsigned vector_elements)
}
ir_constant::ir_constant(const ir_constant *c, unsigned i)
+ : ir_rvalue(ir_type_constant)
{
- this->ir_type = ir_type_constant;
this->type = c->type->get_base_type();
switch (this->type->base_type) {
@@ -692,8 +690,8 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i)
}
ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list)
+ : ir_rvalue(ir_type_constant)
{
- this->ir_type = ir_type_constant;
this->type = type;
assert(type->is_scalar() || type->is_vector() || type->is_matrix()
@@ -1233,16 +1231,16 @@ ir_constant::is_uint16_constant() const
}
ir_loop::ir_loop()
+ : ir_instruction(ir_type_loop)
{
- this->ir_type = ir_type_loop;
}
ir_dereference_variable::ir_dereference_variable(ir_variable *var)
+ : ir_dereference(ir_type_dereference_variable)
{
assert(var != NULL);
- this->ir_type = ir_type_dereference_variable;
this->var = var;
this->type = var->type;
}
@@ -1250,8 +1248,8 @@ ir_dereference_variable::ir_dereference_variable(ir_variable *var)
ir_dereference_array::ir_dereference_array(ir_rvalue *value,
ir_rvalue *array_index)
+ : ir_dereference(ir_type_dereference_array)
{
- this->ir_type = ir_type_dereference_array;
this->array_index = array_index;
this->set_array(value);
}
@@ -1259,10 +1257,10 @@ ir_dereference_array::ir_dereference_array(ir_rvalue *value,
ir_dereference_array::ir_dereference_array(ir_variable *var,
ir_rvalue *array_index)
+ : ir_dereference(ir_type_dereference_array)
{
void *ctx = ralloc_parent(var);
- this->ir_type = ir_type_dereference_array;
this->array_index = array_index;
this->set_array(new(ctx) ir_dereference_variable(var));
}
@@ -1289,10 +1287,10 @@ ir_dereference_array::set_array(ir_rvalue *value)
ir_dereference_record::ir_dereference_record(ir_rvalue *value,
const char *field)
+ : ir_dereference(ir_type_dereference_record)
{
assert(value != NULL);
- this->ir_type = ir_type_dereference_record;
this->record = value;
this->field = ralloc_strdup(this, field);
this->type = this->record->type->field_type(field);
@@ -1301,10 +1299,10 @@ ir_dereference_record::ir_dereference_record(ir_rvalue *value,
ir_dereference_record::ir_dereference_record(ir_variable *var,
const char *field)
+ : ir_dereference(ir_type_dereference_record)
{
void *ctx = ralloc_parent(var);
- this->ir_type = ir_type_dereference_record;
this->record = new(ctx) ir_dereference_variable(var);
this->field = ralloc_strdup(this, field);
this->type = this->record->type->field_type(field);
@@ -1421,24 +1419,22 @@ ir_swizzle::init_mask(const unsigned *comp, unsigned count)
ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
unsigned w, unsigned count)
- : val(val)
+ : ir_rvalue(ir_type_swizzle), val(val)
{
const unsigned components[4] = { x, y, z, w };
- this->ir_type = ir_type_swizzle;
this->init_mask(components, count);
}
ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp,
unsigned count)
- : val(val)
+ : ir_rvalue(ir_type_swizzle), val(val)
{
- this->ir_type = ir_type_swizzle;
this->init_mask(comp, count);
}
ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask)
+ : ir_rvalue(ir_type_swizzle)
{
- this->ir_type = ir_type_swizzle;
this->val = val;
this->mask = mask;
this->type = glsl_type::get_instance(val->type->base_type,
@@ -1537,9 +1533,8 @@ ir_swizzle::variable_referenced() const
ir_variable::ir_variable(const struct glsl_type *type, const char *name,
ir_variable_mode mode)
- : max_ifc_array_access(NULL)
+ : ir_instruction(ir_type_variable), max_ifc_array_access(NULL)
{
- this->ir_type = ir_type_variable;
this->type = type;
this->name = ralloc_strdup(this, name);
this->data.explicit_location = false;
@@ -1613,10 +1608,10 @@ ir_variable::determine_interpolation_mode(bool flat_shade)
ir_function_signature::ir_function_signature(const glsl_type *return_type,
builtin_available_predicate b)
- : return_type(return_type), is_defined(false), is_intrinsic(false),
+ : ir_instruction(ir_type_function_signature),
+ return_type(return_type), is_defined(false), is_intrinsic(false),
builtin_avail(b), _function(NULL)
{
- this->ir_type = ir_type_function_signature;
this->origin = NULL;
}
@@ -1699,8 +1694,8 @@ ir_function_signature::replace_parameters(exec_list *new_params)
ir_function::ir_function(const char *name)
+ : ir_instruction(ir_type_function)
{
- this->ir_type = ir_type_function;
this->name = ralloc_strdup(this, name);
}
@@ -1720,7 +1715,7 @@ ir_function::has_user_signature()
ir_rvalue *
ir_rvalue::error_value(void *mem_ctx)
{
- ir_rvalue *v = new(mem_ctx) ir_rvalue;
+ ir_rvalue *v = new(mem_ctx) ir_rvalue(ir_type_unset);
v->type = glsl_type::error_type;
return v;
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 80609829e..b4e52d3d0 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -59,31 +59,27 @@
* 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
};
@@ -121,24 +117,58 @@ public:
* 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
/*@}*/
/**
@@ -152,9 +182,15 @@ public:
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.");
}
};
@@ -177,11 +213,6 @@ public:
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
@@ -281,7 +312,7 @@ public:
static ir_rvalue *error_value(void *mem_ctx);
protected:
- ir_rvalue();
+ ir_rvalue(enum ir_node_type t);
};
@@ -382,11 +413,6 @@ public:
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);
@@ -535,6 +561,7 @@ public:
unsigned centroid:1;
unsigned sample:1;
unsigned invariant:1;
+ unsigned precise:1;
/**
* Has this variable been used for reading or writing?
@@ -917,11 +944,6 @@ public:
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);
@@ -984,18 +1006,12 @@ inline const char *ir_function_signature::function_name() const
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);
@@ -1027,11 +1043,6 @@ public:
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;
};
@@ -1062,11 +1073,6 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual ir_assignment * as_assignment()
- {
- return this;
- }
-
/**
* Get a whole variable written by an assignment
*
@@ -1430,11 +1436,6 @@ public:
*/
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;
@@ -1514,9 +1515,8 @@ public:
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();
@@ -1526,11 +1526,6 @@ public:
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);
@@ -1579,39 +1574,26 @@ public:
/*@{*/
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;
@@ -1644,8 +1626,8 @@ public:
};
ir_loop_jump(jump_mode mode)
+ : ir_jump(ir_type_loop_jump)
{
- this->ir_type = ir_type_loop_jump;
this->mode = mode;
}
@@ -1678,14 +1660,14 @@ public:
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;
}
@@ -1698,11 +1680,6 @@ public:
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
- virtual ir_discard *as_discard()
- {
- return this;
- }
-
ir_rvalue *condition;
};
/*@}*/
@@ -1752,10 +1729,10 @@ enum ir_texture_opcode {
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));
}
@@ -1768,11 +1745,6 @@ public:
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);
@@ -1864,11 +1836,6 @@ public:
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.
*/
@@ -1910,17 +1877,18 @@ class ir_dereference : public ir_rvalue {
public:
virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
- virtual ir_dereference *as_dereference()
- {
- return this;
- }
-
bool is_lvalue() const;
/**
* Get the variable that is ultimately referenced by an r-value
*/
virtual ir_variable *variable_referenced() const = 0;
+
+protected:
+ ir_dereference(enum ir_node_type t)
+ : ir_rvalue(t)
+ {
+ }
};
@@ -1933,11 +1901,6 @@ public:
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);
/**
@@ -1984,11 +1947,6 @@ public:
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);
/**
@@ -2025,11 +1983,6 @@ public:
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
*/
@@ -2095,11 +2048,6 @@ public:
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);
@@ -2207,8 +2155,8 @@ private:
class ir_emit_vertex : public ir_instruction {
public:
ir_emit_vertex()
+ : ir_instruction(ir_type_emit_vertex)
{
- ir_type = ir_type_emit_vertex;
}
virtual void accept(ir_visitor *v)
@@ -2231,8 +2179,8 @@ public:
class ir_end_primitive : public ir_instruction {
public:
ir_end_primitive()
+ : ir_instruction(ir_type_end_primitive)
{
- ir_type = ir_type_end_primitive;
}
virtual void accept(ir_visitor *v)
diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp
index 40cf5894a..deec1dfe8 100644
--- a/mesalib/src/glsl/ir_function.cpp
+++ b/mesalib/src/glsl/ir_function.cpp
@@ -23,6 +23,7 @@
#include "glsl_types.h"
#include "ir.h"
+#include "glsl_parser_extras.h"
typedef enum {
PARAMETER_LIST_NO_MATCH,
@@ -38,7 +39,8 @@ typedef enum {
* \see matching_signature()
*/
static parameter_list_match_t
-parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
+parameter_lists_match(_mesa_glsl_parse_state *state,
+ const exec_list *list_a, const exec_list *list_b)
{
const exec_node *node_a = list_a->head;
const exec_node *node_b = list_b->head;
@@ -79,12 +81,12 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
case ir_var_const_in:
case ir_var_function_in:
- if (!actual->type->can_implicitly_convert_to(param->type))
+ if (!actual->type->can_implicitly_convert_to(param->type, state))
return PARAMETER_LIST_NO_MATCH;
break;
case ir_var_function_out:
- if (!param->type->can_implicitly_convert_to(actual->type))
+ if (!param->type->can_implicitly_convert_to(actual->type, state))
return PARAMETER_LIST_NO_MATCH;
break;
@@ -115,6 +117,168 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
}
+/* Classes of parameter match, sorted (mostly) best matches first.
+ * See is_better_parameter_match() below for the exceptions.
+ * */
+typedef enum {
+ PARAMETER_EXACT_MATCH,
+ PARAMETER_FLOAT_TO_DOUBLE,
+ PARAMETER_INT_TO_FLOAT,
+ PARAMETER_INT_TO_DOUBLE,
+ PARAMETER_OTHER_CONVERSION,
+} parameter_match_t;
+
+
+static parameter_match_t
+get_parameter_match_type(const ir_variable *param,
+ const ir_rvalue *actual)
+{
+ const glsl_type *from_type;
+ const glsl_type *to_type;
+
+ if (param->data.mode == ir_var_function_out) {
+ from_type = param->type;
+ to_type = actual->type;
+ } else {
+ from_type = actual->type;
+ to_type = param->type;
+ }
+
+ if (from_type == to_type)
+ return PARAMETER_EXACT_MATCH;
+
+ /* XXX: When ARB_gpu_shader_fp64 support is added, check for float->double,
+ * and int/uint->double conversions
+ */
+
+ if (to_type->base_type == GLSL_TYPE_FLOAT)
+ return PARAMETER_INT_TO_FLOAT;
+
+ /* int -> uint and any other oddball conversions */
+ return PARAMETER_OTHER_CONVERSION;
+}
+
+
+static bool
+is_better_parameter_match(parameter_match_t a_match,
+ parameter_match_t b_match)
+{
+ /* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
+ *
+ * 1. An exact match is better than a match involving any implicit
+ * conversion.
+ *
+ * 2. A match involving an implicit conversion from float to double
+ * is better than match involving any other implicit conversion.
+ *
+ * [XXX: Not in GLSL 4.0: Only in ARB_gpu_shader5:
+ * 3. A match involving an implicit conversion from either int or uint
+ * to float is better than a match involving an implicit conversion
+ * from either int or uint to double.]
+ *
+ * If none of the rules above apply to a particular pair of conversions,
+ * neither conversion is considered better than the other.
+ *
+ * --
+ *
+ * Notably, the int->uint conversion is *not* considered to be better
+ * or worse than int/uint->float or int/uint->double.
+ */
+
+ if (a_match >= PARAMETER_INT_TO_FLOAT && b_match == PARAMETER_OTHER_CONVERSION)
+ return false;
+
+ return a_match < b_match;
+}
+
+
+static bool
+is_best_inexact_overload(const exec_list *actual_parameters,
+ ir_function_signature **matches,
+ int num_matches,
+ ir_function_signature *sig)
+{
+ /* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
+ *
+ * "A function definition A is considered a better
+ * match than function definition B if:
+ *
+ * * for at least one function argument, the conversion for that argument
+ * in A is better than the corresponding conversion in B; and
+ *
+ * * there is no function argument for which the conversion in B is better
+ * than the corresponding conversion in A.
+ *
+ * If a single function definition is considered a better match than every
+ * other matching function definition, it will be used. Otherwise, a
+ * semantic error occurs and the shader will fail to compile."
+ */
+ for (ir_function_signature **other = matches;
+ other < matches + num_matches; other++) {
+ if (*other == sig)
+ continue;
+
+ const exec_node *node_a = sig->parameters.head;
+ const exec_node *node_b = (*other)->parameters.head;
+ const exec_node *node_p = actual_parameters->head;
+
+ bool better_for_some_parameter = false;
+
+ for (/* empty */
+ ; !node_a->is_tail_sentinel()
+ ; node_a = node_a->next,
+ node_b = node_b->next,
+ node_p = node_p->next) {
+ parameter_match_t a_match = get_parameter_match_type(
+ (const ir_variable *)node_a,
+ (const ir_rvalue *)node_p);
+ parameter_match_t b_match = get_parameter_match_type(
+ (const ir_variable *)node_b,
+ (const ir_rvalue *)node_p);
+
+ if (is_better_parameter_match(a_match, b_match))
+ better_for_some_parameter = true;
+
+ if (is_better_parameter_match(b_match, a_match))
+ return false; /* B is better for this parameter */
+ }
+
+ if (!better_for_some_parameter)
+ return false; /* A must be better than B for some parameter */
+
+ }
+
+ return true;
+}
+
+
+static ir_function_signature *
+choose_best_inexact_overload(_mesa_glsl_parse_state *state,
+ const exec_list *actual_parameters,
+ ir_function_signature **matches,
+ int num_matches)
+{
+ if (num_matches == 0)
+ return NULL;
+
+ if (num_matches == 1)
+ return *matches;
+
+ /* Without GLSL 4.0 / ARB_gpu_shader5, there is no overload resolution
+ * among multiple inexact matches. Note that state may be NULL here if
+ * called from the linker; in that case we assume everything supported in
+ * any GLSL version is available. */
+ if (!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) {
+ for (ir_function_signature **sig = matches; sig < matches + num_matches; sig++) {
+ if (is_best_inexact_overload(actual_parameters, matches, num_matches, *sig))
+ return *sig;
+ }
+ }
+
+ return NULL; /* no best candidate */
+}
+
+
ir_function_signature *
ir_function::matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_parameters)
@@ -126,10 +290,11 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
ir_function_signature *
ir_function::matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_parameters,
- bool *is_exact)
+ bool *is_exact)
{
+ ir_function_signature **inexact_matches = NULL;
ir_function_signature *match = NULL;
- bool multiple_inexact_matches = false;
+ int num_inexact_matches = 0;
/* From page 42 (page 49 of the PDF) of the GLSL 1.20 spec:
*
@@ -148,16 +313,19 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
if (sig->is_builtin() && !sig->is_builtin_available(state))
continue;
- switch (parameter_lists_match(& sig->parameters, actual_parameters)) {
+ switch (parameter_lists_match(state, & sig->parameters, actual_parameters)) {
case PARAMETER_LIST_EXACT_MATCH:
- *is_exact = true;
- return sig;
+ *is_exact = true;
+ free(inexact_matches);
+ return sig;
case PARAMETER_LIST_INEXACT_MATCH:
- if (match == NULL)
- match = sig;
- else
- multiple_inexact_matches = true;
- continue;
+ inexact_matches = (ir_function_signature **)
+ realloc(inexact_matches,
+ sizeof(*inexact_matches) *
+ (num_inexact_matches + 1));
+ assert(inexact_matches);
+ inexact_matches[num_inexact_matches++] = sig;
+ continue;
case PARAMETER_LIST_NO_MATCH:
continue;
default:
@@ -175,9 +343,10 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
*/
*is_exact = false;
- if (multiple_inexact_matches)
- return NULL;
+ match = choose_best_inexact_overload(state, actual_parameters,
+ inexact_matches, num_inexact_matches);
+ free(inexact_matches);
return match;
}
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index 71defc815..17a74ea55 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -795,7 +795,7 @@ check_node_type(ir_instruction *ir, void *data)
{
(void) data;
- if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
+ if (ir->ir_type >= ir_type_max) {
printf("Instruction node with unset type\n");
ir->print(); printf("\n");
}
diff --git a/mesalib/src/glsl/loop_analysis.cpp b/mesalib/src/glsl/loop_analysis.cpp
index d6a9ac775..78ac30044 100644
--- a/mesalib/src/glsl/loop_analysis.cpp
+++ b/mesalib/src/glsl/loop_analysis.cpp
@@ -589,8 +589,10 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash)
loop_variable *lv =
(loop_variable *) hash_table_find(var_hash, inc_var);
- if (!lv->is_loop_constant())
- inc = NULL;
+ if (lv == NULL || !lv->is_loop_constant()) {
+ assert(lv != NULL);
+ inc = NULL;
+ }
} else
inc = NULL;
}