aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-06-08 14:33:00 +0200
committermarha <marha@users.sourceforge.net>2014-06-08 14:33:00 +0200
commit2acb86c9b086bdb9a3897db0b93820652e07cb59 (patch)
tree02a43a0005c991c736f03de9a1c8ba98f0bbdf28 /mesalib/src/glsl
parent816a5430313e07083c5325f0a430126a2e10ec41 (diff)
downloadvcxsrv-2acb86c9b086bdb9a3897db0b93820652e07cb59.tar.gz
vcxsrv-2acb86c9b086bdb9a3897db0b93820652e07cb59.tar.bz2
vcxsrv-2acb86c9b086bdb9a3897db0b93820652e07cb59.zip
xwininfo libX11 mesa mkfontscale xserver git updated 8 June 2014
xserver commit e27a839bf0488d5b1cc2e2a887f2ea0e3d790790 libxcb commit d978a4f69b30b630f28d07f1003cf290284d24d8 libxcb/xcb-proto commit 389889e2f95af19e7fc7ac89e7faeb2f28652415 xkeyboard-config commit bc3ac1b0d152e929b3532a541596cf9fe286bb9e libX11 commit d81fed46144d089bdfa1d916a28dffc9ebffe1e4 libXdmcp commit fe8eab93e9bcdbe8bb8052434bb5e676e3a0ee8f libXext commit 11aad96bd689d54156064d2e81213dc827a689d1 libfontenc commit 0037a42107b952c9d903719615747e760e4e7247 libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909 libXau commit 1e4635be11154dd8262f37b379511bd627defa2a xkbcomp commit d4e02a09258063c6d024c3ccd42d6b22212e6e18 pixman commit 9cd283b2eb8279824406bfd47b020d21fc00cf82 xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7 randrproto commit a4a6694c059d74247c16527eef4a0ec9f56bbef6 glproto commit f84853d97d5749308992412a215fa518b6536eb3 mkfontscale commit 48e541dc2f2fc3f4e99d3e168c28241ff5adff4d xwininfo commit 017b3736489985999d8dcf4d9e473e1fd6dd3647 libXft commit 214f9b5306d833e2787c75fe41dfdc9228fcb738 libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63 libxtrans commit a57a7f62242e1ea972b81414741729bf3dbae0a4 fontconfig commit f44bfad235e63bb792c38e16ae1fbd281ec1453b mesa commit eb58aa9cf015e79a0fcf2e088676e6aa1d5dabce
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 6b136f518..56e7bd86f 100644
--- a/mesalib/src/glsl/ast.h
+++ b/mesalib/src/glsl/ast.h
@@ -424,6 +424,7 @@ struct ast_type_qualifier {
union {
struct {
unsigned invariant:1;
+ unsigned precise:1;
unsigned constant:1;
unsigned attribute:1;
unsigned varying:1;
@@ -745,13 +746,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 b09d6e536..eddab0518 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -128,7 +128,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
@@ -166,7 +166,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
@@ -183,7 +183,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
@@ -931,14 +931,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);
@@ -1071,7 +1079,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);
@@ -1083,6 +1091,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:
@@ -1498,6 +1518,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
@@ -1518,8 +1543,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)
@@ -1530,6 +1563,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;
}
@@ -1553,9 +1590,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;
@@ -1576,6 +1614,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");
@@ -1592,7 +1634,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");
}
@@ -1609,10 +1652,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 ba8a8394f..8fed768a2 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;
}