aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-08-11 21:14:48 +0200
committermarha <marha@users.sourceforge.net>2014-08-11 21:14:48 +0200
commitfdbedba4d50e1b28b0249c83ba11c029f096e400 (patch)
treea80ccb6275fd99644c79c67856e9c1bf1b323d62 /mesalib/src/glsl
parentb33b8d8ae86876b50df96881b96074b3fe177cce (diff)
downloadvcxsrv-fdbedba4d50e1b28b0249c83ba11c029f096e400.tar.gz
vcxsrv-fdbedba4d50e1b28b0249c83ba11c029f096e400.tar.bz2
vcxsrv-fdbedba4d50e1b28b0249c83ba11c029f096e400.zip
fontconfig libX11 libxcb libxcb/xcb-proto mesa xserver xkeyboard-config git update 11 Aug 2014
xserver commit 3714f5401690b288045090c4bcd9cb01c6e4860e libxcb commit 966fba6ba4838949d0727dfa45eeb9392d1f85d9 libxcb/xcb-proto commit 4b384d2a015c50d0e93dcacda4b8260a3fd37640 xkeyboard-config commit 651a00ab656a1754b9183a383970a735209bbb50 libX11 commit 368a6401c6a3275d3497fec38a3dcbc38cd9df60 libXdmcp commit fe8eab93e9bcdbe8bb8052434bb5e676e3a0ee8f libXext commit efdcbb7634501e1117d422636a0a75d7ea84b16b libfontenc commit 0037a42107b952c9d903719615747e760e4e7247 libXinerama commit edd95182b26eb5d576d4878c559e0f17dddaa909 libXau commit 1e4635be11154dd8262f37b379511bd627defa2a xkbcomp commit d4e02a09258063c6d024c3ccd42d6b22212e6e18 pixman commit 6d2cf40166d81bfc63108504c8022dc4fec37ff5 xextproto commit 66afec3f49e8eb0d4c2e9af7088fc3116d4bafd7 randrproto commit a4a6694c059d74247c16527eef4a0ec9f56bbef6 glproto commit f84853d97d5749308992412a215fa518b6536eb3 mkfontscale commit 47908fd7a0d061fdcd21e3498da4e223ca9136d9 xwininfo commit 017b3736489985999d8dcf4d9e473e1fd6dd3647 libXft commit 214f9b5306d833e2787c75fe41dfdc9228fcb738 libXmu commit 22d9c590901e121936f50dee97dc60c4f7defb63 libxtrans commit a57a7f62242e1ea972b81414741729bf3dbae0a4 fontconfig commit 841753a93f0e5698663b7931b8456e7b96259f54 mesa commit f24be7340162c6a831b392d46d6637e9656e7a8a
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/.gitignore4
-rw-r--r--mesalib/src/glsl/Makefile.am18
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/SConscript5
-rw-r--r--mesalib/src/glsl/ast_function.cpp15
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp92
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp3
-rw-r--r--mesalib/src/glsl/builtin_types.cpp81
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp2
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-lex.l449
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y426
-rw-r--r--mesalib/src/glsl/glcpp/glcpp.c6
-rw-r--r--mesalib/src/glsl/glcpp/glcpp.h6
-rw-r--r--mesalib/src/glsl/glcpp/pp.c96
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll5
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp28
-rw-r--r--mesalib/src/glsl/glsl_types.cpp45
-rw-r--r--mesalib/src/glsl/glsl_types.h41
-rw-r--r--mesalib/src/glsl/ir.h11
-rw-r--r--mesalib/src/glsl/ir_function.cpp10
-rw-r--r--mesalib/src/glsl/ir_reader.cpp3
-rw-r--r--mesalib/src/glsl/ir_variable_refcount.cpp2
-rw-r--r--mesalib/src/glsl/link_functions.cpp2
-rw-r--r--mesalib/src/glsl/link_uniform_block_active_visitor.cpp39
-rw-r--r--mesalib/src/glsl/link_uniform_block_active_visitor.h3
-rw-r--r--mesalib/src/glsl/link_uniform_blocks.cpp20
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp90
-rw-r--r--mesalib/src/glsl/link_varyings.cpp6
-rw-r--r--mesalib/src/glsl/linker.cpp3
-rw-r--r--mesalib/src/glsl/linker.h12
-rw-r--r--mesalib/src/glsl/list.h2
-rw-r--r--mesalib/src/glsl/loop_controls.cpp17
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp2
-rw-r--r--mesalib/src/glsl/lower_ubo_reference.cpp150
-rw-r--r--mesalib/src/glsl/opt_dead_code.cpp31
-rw-r--r--mesalib/src/glsl/ralloc.c492
-rw-r--r--mesalib/src/glsl/ralloc.h444
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.cpp2
38 files changed, 1279 insertions, 1385 deletions
diff --git a/mesalib/src/glsl/.gitignore b/mesalib/src/glsl/.gitignore
index 43720f60b..dda423f83 100644
--- a/mesalib/src/glsl/.gitignore
+++ b/mesalib/src/glsl/.gitignore
@@ -4,3 +4,7 @@ glsl_parser.cpp
glsl_parser.h
glsl_parser.output
glsl_test
+subtest-cr/
+subtest-lf/
+subtest-cr-lf/
+subtest-lf-cr/
diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am
index 00261fd0d..0ccc81d75 100644
--- a/mesalib/src/glsl/Makefile.am
+++ b/mesalib/src/glsl/Makefile.am
@@ -21,6 +21,7 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/src \
-I$(top_srcdir)/src/mapi \
-I$(top_srcdir)/src/mesa/ \
-I$(top_srcdir)/src/glsl/glcpp \
@@ -32,9 +33,9 @@ AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS)
include Makefile.sources
TESTS = glcpp/tests/glcpp-test \
+ glcpp/tests/glcpp-test-cr-lf \
tests/general-ir-test \
tests/optimization-test \
- tests/ralloc-test \
tests/sampler-types-test \
tests/uniform-initializer-test
@@ -47,14 +48,12 @@ check_PROGRAMS = \
glcpp/glcpp \
glsl_test \
tests/general-ir-test \
- tests/ralloc-test \
tests/sampler-types-test \
tests/uniform-initializer-test
noinst_PROGRAMS = glsl_compiler
tests_general_ir_test_SOURCES = \
- $(top_srcdir)/src/mesa/main/hash_table.c \
$(top_srcdir)/src/mesa/main/imports.c \
$(top_srcdir)/src/mesa/program/prog_hash_table.c\
$(top_srcdir)/src/mesa/program/symbol_table.c \
@@ -72,7 +71,6 @@ tests_general_ir_test_LDADD = \
$(PTHREAD_LIBS)
tests_uniform_initializer_test_SOURCES = \
- $(top_srcdir)/src/mesa/main/hash_table.c \
$(top_srcdir)/src/mesa/main/imports.c \
$(top_srcdir)/src/mesa/program/prog_hash_table.c\
$(top_srcdir)/src/mesa/program/symbol_table.c \
@@ -87,14 +85,6 @@ tests_uniform_initializer_test_LDADD = \
$(top_builddir)/src/glsl/libglsl.la \
$(PTHREAD_LIBS)
-tests_ralloc_test_SOURCES = \
- tests/ralloc_test.cpp \
- $(top_builddir)/src/glsl/ralloc.c
-tests_ralloc_test_CFLAGS = $(PTHREAD_CFLAGS)
-tests_ralloc_test_LDADD = \
- $(top_builddir)/src/gtest/libgtest.la \
- $(PTHREAD_LIBS)
-
tests_sampler_types_test_SOURCES = \
$(top_srcdir)/src/mesa/program/prog_hash_table.c\
$(top_srcdir)/src/mesa/program/symbol_table.c \
@@ -107,6 +97,8 @@ tests_sampler_types_test_LDADD = \
$(top_builddir)/src/glsl/libglsl.la \
$(PTHREAD_LIBS)
+libglcpp_la_LIBADD = \
+ $(top_builddir)/src/util/libmesautil.la
libglcpp_la_SOURCES = \
glcpp/glcpp-lex.c \
glcpp/glcpp-parse.c \
@@ -127,7 +119,6 @@ libglsl_la_SOURCES = \
$(LIBGLSL_FILES)
glsl_compiler_SOURCES = \
- $(top_srcdir)/src/mesa/main/hash_table.c \
$(top_srcdir)/src/mesa/main/imports.c \
$(top_srcdir)/src/mesa/program/prog_hash_table.c \
$(top_srcdir)/src/mesa/program/symbol_table.c \
@@ -138,7 +129,6 @@ glsl_compiler_LDADD = \
$(PTHREAD_LIBS)
glsl_test_SOURCES = \
- $(top_srcdir)/src/mesa/main/hash_table.c \
$(top_srcdir)/src/mesa/main/imports.c \
$(top_srcdir)/src/mesa/program/prog_hash_table.c \
$(top_srcdir)/src/mesa/program/symbol_table.c \
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index b54eae72d..2131ddafb 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -6,7 +6,6 @@ GLSL_BUILDDIR = $(top_builddir)/src/glsl
# libglcpp
LIBGLCPP_FILES = \
- $(GLSL_SRCDIR)/ralloc.c \
$(GLSL_SRCDIR)/glcpp/pp.c
LIBGLCPP_GENERATED_FILES = \
diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript
index dc354775a..847e96246 100644
--- a/mesalib/src/glsl/SConscript
+++ b/mesalib/src/glsl/SConscript
@@ -8,12 +8,15 @@ env = env.Clone()
env.Prepend(CPPPATH = [
'#include',
+ '#src',
'#src/mapi',
'#src/mesa',
'#src/glsl',
'#src/glsl/glcpp',
])
+env.Prepend(LIBS = [mesautil])
+
# Make glcpp-parse.h and glsl_parser.h reachable from the include path.
env.Append(CPPPATH = [Dir('.').abspath, Dir('glcpp').abspath])
@@ -55,7 +58,6 @@ if env['msvc']:
# Copy these files to avoid generation object files into src/mesa/program
env.Prepend(CPPPATH = ['#src/mesa/main'])
-env.Command('hash_table.c', '#src/mesa/main/hash_table.c', Copy('$TARGET', '$SOURCE'))
env.Command('imports.c', '#src/mesa/main/imports.c', Copy('$TARGET', '$SOURCE'))
# Copy these files to avoid generation object files into src/mesa/program
env.Prepend(CPPPATH = ['#src/mesa/program'])
@@ -65,7 +67,6 @@ env.Command('symbol_table.c', '#src/mesa/program/symbol_table.c', Copy('$TARGET'
compiler_objs = env.StaticObject(source_lists['GLSL_COMPILER_CXX_FILES'])
mesa_objs = env.StaticObject([
- 'hash_table.c',
'imports.c',
'prog_hash_table.c',
'symbol_table.c',
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 4981fe174..39c7beeb2 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -450,20 +450,21 @@ match_function_by_name(const char *name,
goto done; /* no match */
if (f != NULL) {
+ /* In desktop GL, the presence of a user-defined signature hides any
+ * built-in signatures, so we must ignore them. In contrast, in ES2
+ * user-defined signatures add new overloads, so we must consider them.
+ */
+ bool allow_builtins = state->es_shader || !f->has_user_signature();
+
/* Look for a match in the local shader. If exact, we're done. */
bool is_exact = false;
sig = local_sig = f->matching_signature(state, actual_parameters,
- &is_exact);
+ allow_builtins, &is_exact);
if (is_exact)
goto done;
- if (!state->es_shader && f->has_user_signature()) {
- /* In desktop GL, the presence of a user-defined signature hides any
- * built-in signatures, so we must ignore them. In contrast, in ES2
- * user-defined signatures add new overloads, so we must proceed.
- */
+ if (!allow_builtins)
goto done;
- }
}
/* Local shader has no exact candidates; check the built-ins. */
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index a15ee9c05..30b02d016 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -4110,12 +4110,27 @@ ast_function::hir(exec_list *instructions,
name);
}
+ /* Create an ir_function if one doesn't already exist. */
+ f = state->symbols->get_function(name);
+ if (f == NULL) {
+ f = new(ctx) ir_function(name);
+ if (!state->symbols->add_function(f)) {
+ /* This function name shadows a non-function use of the same name. */
+ YYLTYPE loc = this->get_location();
+
+ _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
+ "non-function", name);
+ return NULL;
+ }
+
+ emit_function(state, f);
+ }
+
/* Verify that this function's signature either doesn't match a previously
* seen signature for a function with the same name, or, if a match is found,
* that the previously seen signature does not have an associated definition.
*/
- f = state->symbols->get_function(name);
- if (f != NULL && (state->es_shader || f->has_user_signature())) {
+ if (state->es_shader || f->has_user_signature()) {
sig = f->exact_matching_signature(state, &hir_parameters);
if (sig != NULL) {
const char *badvar = sig->qualifiers_match(&hir_parameters);
@@ -4146,18 +4161,6 @@ ast_function::hir(exec_list *instructions,
}
}
}
- } else {
- f = new(ctx) ir_function(name);
- if (!state->symbols->add_function(f)) {
- /* This function name shadows a non-function use of the same name. */
- YYLTYPE loc = this->get_location();
-
- _mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
- "non-function", name);
- return NULL;
- }
-
- emit_function(state, f);
}
/* Verify the return type of main() */
@@ -4597,12 +4600,6 @@ ast_case_statement_list::hir(exec_list *instructions,
*/
if (!default_case.is_empty()) {
- /* Default case was the last one, no checks required. */
- if (after_default.is_empty()) {
- instructions->append_list(&default_case);
- return NULL;
- }
-
ir_rvalue *const true_val = new (state) ir_constant(true);
ir_dereference_variable *deref_run_default_var =
new(state) ir_dereference_variable(state->switch_state.run_default);
@@ -4614,6 +4611,12 @@ ast_case_statement_list::hir(exec_list *instructions,
new(state) ir_assignment(deref_run_default_var, true_val);
instructions->push_tail(init_var);
+ /* Default case was the last one, no checks required. */
+ if (after_default.is_empty()) {
+ instructions->append_list(&default_case);
+ return NULL;
+ }
+
foreach_in_list(ir_instruction, ir, &after_default) {
ir_assignment *assign = ir->as_assignment();
@@ -5072,7 +5075,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
YYLTYPE &loc,
glsl_struct_field **fields_ret,
bool is_interface,
- bool block_row_major,
+ enum glsl_matrix_layout matrix_layout,
bool allow_reserved_names,
ir_variable_mode var_mode)
{
@@ -5203,13 +5206,29 @@ ast_process_structure_or_interface_block(exec_list *instructions,
"in uniform blocks or structures.");
}
- if (field_type->is_matrix() ||
- (field_type->is_array() && field_type->fields.array->is_matrix())) {
- fields[i].row_major = block_row_major;
+ /* Propogate row- / column-major information down the fields of the
+ * structure or interface block. Structures need this data because
+ * the structure may contain a structure that contains ... a matrix
+ * that need the proper layout.
+ */
+ if (field_type->without_array()->is_matrix()
+ || field_type->without_array()->is_record()) {
+ /* If no layout is specified for the field, inherit the layout
+ * from the block.
+ */
+ fields[i].matrix_layout = matrix_layout;
+
if (qual->flags.q.row_major)
- fields[i].row_major = true;
+ fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR;
else if (qual->flags.q.column_major)
- fields[i].row_major = false;
+ fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+
+ /* If we're processing an interface block, the matrix layout must
+ * be decided by this point.
+ */
+ assert(!is_interface
+ || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR
+ || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR);
}
i++;
@@ -5264,7 +5283,7 @@ ast_struct_specifier::hir(exec_list *instructions,
loc,
&fields,
false,
- false,
+ GLSL_MATRIX_LAYOUT_INHERITED,
false /* allow_reserved_names */,
ir_var_auto);
@@ -5364,8 +5383,13 @@ ast_interface_block::hir(exec_list *instructions,
assert(!"interface block layout qualifier not found!");
}
+ enum glsl_matrix_layout matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED;
+ if (this->layout.flags.q.row_major)
+ matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR;
+ else if (this->layout.flags.q.column_major)
+ matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+
bool redeclaring_per_vertex = strcmp(this->block_name, "gl_PerVertex") == 0;
- bool block_row_major = this->layout.flags.q.row_major;
exec_list declared_variables;
glsl_struct_field *fields;
@@ -5381,7 +5405,7 @@ ast_interface_block::hir(exec_list *instructions,
loc,
&fields,
true,
- block_row_major,
+ matrix_layout,
redeclaring_per_vertex,
var_mode);
@@ -5589,6 +5613,9 @@ ast_interface_block::hir(exec_list *instructions,
var_mode);
}
+ var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
+ ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+
if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
handle_geometry_shader_input_decl(state, loc, var);
@@ -5629,6 +5656,13 @@ ast_interface_block::hir(exec_list *instructions,
var->data.sample = fields[i].sample;
var->init_interface_type(block_type);
+ if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) {
+ var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
+ ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+ } else {
+ var->data.matrix_layout = fields[i].matrix_layout;
+ }
+
if (fields[i].stream != -1 &&
((unsigned)fields[i].stream) != this->layout.stream) {
_mesa_glsl_error(&loc, state,
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index e01742c4d..185fe98b3 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -706,7 +706,8 @@ builtin_builder::find(_mesa_glsl_parse_state *state,
if (f == NULL)
return NULL;
- ir_function_signature *sig = f->matching_signature(state, actual_parameters);
+ ir_function_signature *sig =
+ f->matching_signature(state, actual_parameters, true);
if (sig == NULL)
return NULL;
diff --git a/mesalib/src/glsl/builtin_types.cpp b/mesalib/src/glsl/builtin_types.cpp
index 0a0fa8cd3..10fac0f81 100644
--- a/mesalib/src/glsl/builtin_types.cpp
+++ b/mesalib/src/glsl/builtin_types.cpp
@@ -36,6 +36,7 @@
#include "glsl_types.h"
#include "glsl_parser_extras.h"
+#include "util/macros.h"
/**
* Declarations of type flyweights (glsl_type::_foo_type) and
@@ -48,69 +49,69 @@
#define STRUCT_TYPE(NAME) \
const glsl_type glsl_type::_struct_##NAME##_type = \
- glsl_type(NAME##_fields, Elements(NAME##_fields), #NAME); \
+ glsl_type(NAME##_fields, ARRAY_SIZE(NAME##_fields), #NAME); \
const glsl_type *const glsl_type::struct_##NAME##_type = \
&glsl_type::_struct_##NAME##_type;
static const struct glsl_struct_field gl_DepthRangeParameters_fields[] = {
- { glsl_type::float_type, "near", false, -1 },
- { glsl_type::float_type, "far", false, -1 },
- { glsl_type::float_type, "diff", false, -1 },
+ { glsl_type::float_type, "near", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "far", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "diff", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_PointParameters_fields[] = {
- { glsl_type::float_type, "size", false, -1 },
- { glsl_type::float_type, "sizeMin", false, -1 },
- { glsl_type::float_type, "sizeMax", false, -1 },
- { glsl_type::float_type, "fadeThresholdSize", false, -1 },
- { glsl_type::float_type, "distanceConstantAttenuation", false, -1 },
- { glsl_type::float_type, "distanceLinearAttenuation", false, -1 },
- { glsl_type::float_type, "distanceQuadraticAttenuation", false, -1 },
+ { glsl_type::float_type, "size", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "sizeMin", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "sizeMax", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "fadeThresholdSize", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "distanceConstantAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "distanceLinearAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "distanceQuadraticAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_MaterialParameters_fields[] = {
- { glsl_type::vec4_type, "emission", false, -1 },
- { glsl_type::vec4_type, "ambient", false, -1 },
- { glsl_type::vec4_type, "diffuse", false, -1 },
- { glsl_type::vec4_type, "specular", false, -1 },
- { glsl_type::float_type, "shininess", false, -1 },
+ { glsl_type::vec4_type, "emission", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "diffuse", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "specular", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "shininess", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_LightSourceParameters_fields[] = {
- { glsl_type::vec4_type, "ambient", false, -1 },
- { glsl_type::vec4_type, "diffuse", false, -1 },
- { glsl_type::vec4_type, "specular", false, -1 },
- { glsl_type::vec4_type, "position", false, -1 },
- { glsl_type::vec4_type, "halfVector", false, -1 },
- { glsl_type::vec3_type, "spotDirection", false, -1 },
- { glsl_type::float_type, "spotExponent", false, -1 },
- { glsl_type::float_type, "spotCutoff", false, -1 },
- { glsl_type::float_type, "spotCosCutoff", false, -1 },
- { glsl_type::float_type, "constantAttenuation", false, -1 },
- { glsl_type::float_type, "linearAttenuation", false, -1 },
- { glsl_type::float_type, "quadraticAttenuation", false, -1 },
+ { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "diffuse", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "specular", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "position", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "halfVector", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec3_type, "spotDirection", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "spotExponent", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "spotCutoff", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "spotCosCutoff", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "constantAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "linearAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "quadraticAttenuation", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_LightModelParameters_fields[] = {
- { glsl_type::vec4_type, "ambient", false, -1 },
+ { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_LightModelProducts_fields[] = {
- { glsl_type::vec4_type, "sceneColor", false, -1 },
+ { glsl_type::vec4_type, "sceneColor", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_LightProducts_fields[] = {
- { glsl_type::vec4_type, "ambient", false, -1 },
- { glsl_type::vec4_type, "diffuse", false, -1 },
- { glsl_type::vec4_type, "specular", false, -1 },
+ { glsl_type::vec4_type, "ambient", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "diffuse", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::vec4_type, "specular", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
static const struct glsl_struct_field gl_FogParameters_fields[] = {
- { glsl_type::vec4_type, "color", false, -1 },
- { glsl_type::float_type, "density", false, -1 },
- { glsl_type::float_type, "start", false, -1 },
- { glsl_type::float_type, "end", false, -1 },
- { glsl_type::float_type, "scale", false, -1 },
+ { glsl_type::vec4_type, "color", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "density", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "start", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "end", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
+ { glsl_type::float_type, "scale", -1, 0, 0, 0, GLSL_MATRIX_LAYOUT_INHERITED, 0 },
};
#include "builtin_type_macros.h"
@@ -265,7 +266,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
{
struct glsl_symbol_table *symbols = state->symbols;
- for (unsigned i = 0; i < Elements(builtin_type_versions); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(builtin_type_versions); i++) {
const struct builtin_type_versions *const t = &builtin_type_versions[i];
if (state->is_version(t->min_gl, t->min_es)) {
add_type(symbols, t->type);
@@ -276,7 +277,7 @@ _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
* they're still present. We've removed them in 1.40+ (OpenGL 3.1+).
*/
if (!state->es_shader && state->language_version < 140) {
- for (unsigned i = 0; i < Elements(deprecated_types); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(deprecated_types); i++) {
add_type(symbols, deprecated_types[i]);
}
}
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 4c5b9c070..5b6f4ae62 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -317,7 +317,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type,
assert(this->num_fields < ARRAY_SIZE(this->fields));
this->fields[this->num_fields].type = type;
this->fields[this->num_fields].name = name;
- this->fields[this->num_fields].row_major = false;
+ this->fields[this->num_fields].matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED;
this->fields[this->num_fields].location = slot;
this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE;
this->fields[this->num_fields].centroid = 0;
diff --git a/mesalib/src/glsl/glcpp/glcpp-lex.l b/mesalib/src/glsl/glcpp/glcpp-lex.l
index a1a8e76af..98d500ec0 100644
--- a/mesalib/src/glsl/glcpp/glcpp-lex.l
+++ b/mesalib/src/glsl/glcpp/glcpp-lex.l
@@ -52,14 +52,107 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
yylloc->last_column = yycolumn + 1; \
parser->has_new_line_number = 0; \
parser->has_new_source_number = 0; \
- } while(0);
+ } while(0);
#define YY_USER_INIT \
do { \
yylineno = 1; \
- yycolumn = 1; \
+ yycolumn = 0; \
yylloc->source = 0; \
} while(0)
+
+/* It's ugly to have macros that have return statements inside of
+ * them, but flex-based lexer generation is all built around the
+ * return statement.
+ *
+ * To mitigate the ugliness, we defer as much of the logic as possible
+ * to an actual function, not a macro (see
+ * glcpplex_update_state_per_token) and we make the word RETURN
+ * prominent in all of the macros which may return.
+ *
+ * The most-commonly-used macro is RETURN_TOKEN which will perform all
+ * necessary state updates based on the provided token,, then
+ * conditionally return the token. It will not return a token if the
+ * parser is currently skipping tokens, (such as within #if
+ * 0...#else).
+ *
+ * The RETURN_TOKEN_NEVER_SKIP macro is a lower-level variant that
+ * makes the token returning unconditional. This is needed for things
+ * like #if and the tokens of its condition, (since these must be
+ * evaluated by the parser even when otherwise skipping).
+ *
+ * Finally, RETURN_STRING_TOKEN is a simple convenience wrapper on top
+ * of RETURN_TOKEN that performs a string copy of yytext before the
+ * return.
+ */
+#define RETURN_TOKEN_NEVER_SKIP(token) \
+ do { \
+ if (glcpp_lex_update_state_per_token (parser, token)) \
+ return token; \
+ } while (0)
+
+#define RETURN_TOKEN(token) \
+ do { \
+ if (! parser->skipping) { \
+ RETURN_TOKEN_NEVER_SKIP(token); \
+ } \
+ } while(0)
+
+#define RETURN_STRING_TOKEN(token) \
+ do { \
+ if (! parser->skipping) { \
+ yylval->str = ralloc_strdup (yyextra, yytext); \
+ RETURN_TOKEN_NEVER_SKIP (token); \
+ } \
+ } while(0)
+
+
+/* Update all state necessary for each token being returned.
+ *
+ * Here we'll be tracking newlines and spaces so that the lexer can
+ * alter its behavior as necessary, (for example, '#' has special
+ * significance if it is the first non-whitespace, non-comment token
+ * in a line, but does not otherwise).
+ *
+ * NOTE: If this function returns FALSE, then no token should be
+ * returned at all. This is used to suprress duplicate SPACE tokens.
+ */
+static int
+glcpp_lex_update_state_per_token (glcpp_parser_t *parser, int token)
+{
+ /* After the first non-space token in a line, we won't
+ * allow any '#' to introduce a directive. */
+ if (token == NEWLINE) {
+ parser->first_non_space_token_this_line = 1;
+ } else if (token != SPACE) {
+ parser->first_non_space_token_this_line = 0;
+ }
+
+ /* Track newlines just to know whether a newline needs
+ * to be inserted if end-of-file comes early. */
+ if (token == NEWLINE) {
+ parser->last_token_was_newline = 1;
+ } else {
+ parser->last_token_was_newline = 0;
+ }
+
+ /* Track spaces to avoid emitting multiple SPACE
+ * tokens in a row. */
+ if (token == SPACE) {
+ if (! parser->last_token_was_space) {
+ parser->last_token_was_space = 1;
+ return 1;
+ } else {
+ parser->last_token_was_space = 1;
+ return 0;
+ }
+ } else {
+ parser->last_token_was_space = 0;
+ return 1;
+ }
+}
+
+
%}
%option bison-bridge bison-locations reentrant noyywrap
@@ -67,14 +160,19 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
%option prefix="glcpp_"
%option stack
%option never-interactive
+%option warn nodefault
+
+ /* Note: When adding any start conditions to this list, you must also
+ * update the "Internal compiler error" catch-all rule near the end of
+ * this file. */
-%x DONE COMMENT UNREACHABLE SKIP DEFINE NEWLINE_CATCHUP
+%x COMMENT DEFINE DONE HASH NEWLINE_CATCHUP UNREACHABLE
SPACE [[:space:]]
NONSPACE [^[:space:]]
-NEWLINE [\n]
HSPACE [ \t]
-HASH ^{HSPACE}*#{HSPACE}*
+HASH #
+NEWLINE (\r\n|\n\r|\r|\n)
IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
PP_NUMBER [.]?[0-9]([._a-zA-Z0-9]|[eEpP][-+])*
PUNCTUATION [][(){}.&*~!/%<>^|;,=+-]
@@ -111,270 +209,357 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
parser->commented_newlines--;
if (parser->commented_newlines == 0)
BEGIN INITIAL;
- return NEWLINE;
+ RETURN_TOKEN_NEVER_SKIP (NEWLINE);
}
- /* The handling of the SKIP vs INITIAL start states requires
- * some special handling. Typically, a lexer would change
- * start states with statements like "BEGIN SKIP" within the
- * lexer rules. We can't get away with that here, since we
- * need the parser to actually evaluate expressions for
- * directives like "#if".
+ /* Set up the parser->skipping bit here before doing any lexing.
+ *
+ * This bit controls whether tokens are skipped, (as implemented by
+ * RETURN_TOKEN), such as between "#if 0" and "#endif".
*
- * So, here, in code that will be executed on every call to
- * the lexer,and before any rules, we examine the skip_stack
- * as set by the parser to know whether to change from INITIAL
- * to SKIP or from SKIP back to INITIAL.
+ * The parser maintains a skip_stack indicating whether we should be
+ * skipping, (and nested levels of #if/#ifdef/#ifndef/#endif) will
+ * push and pop items from the stack.
*
- * Three cases cause us to switch out of the SKIP state and
- * back to the INITIAL state:
+ * Here are the rules for determining whether we are skipping:
*
- * 1. The top of the skip_stack is of type SKIP_NO_SKIP
- * This means we're still evaluating some #if
- * hierarchy, but we're on a branch of it where
- * content should not be skipped (such as "#if 1" or
- * "#else" or so).
+ * 1. If the skip stack is NULL, we are outside of all #if blocks
+ * and we are not skipping.
*
- * 2. The skip_stack is NULL meaning that we've reached
- * the last #endif.
+ * 2. If the skip stack is non-NULL, the type of the top node in
+ * the stack determines whether to skip. A type of
+ * SKIP_NO_SKIP is used for blocks wheere we are emitting
+ * tokens, (such as between #if 1 and #endif, or after the
+ * #else of an #if 0, etc.).
*
- * 3. The lexing_directive bit is set. This indicates that we are
- * lexing a pre-processor directive, (such as #if, #elif, or
- * #else). For the #if and #elif directives we always need to
- * parse the conditions, (even if otherwise within an #if
- * 0). And for #else, we want to be able to generate an error
- * if any garbage follows #else.
+ * 3. The lexing_directive bit overrides the skip stack. This bit
+ * is set when we are actively lexing the expression for a
+ * pre-processor condition, (such as #if, #elif, or #else). In
+ * this case, even if otherwise skipping, we need to emit the
+ * tokens for this condition so that the parser can evaluate
+ * the expression. (For, #else, there's no expression, but we
+ * emit tokens so the parser can generate a nice error message
+ * if there are any tokens here).
*/
- if (YY_START == INITIAL || YY_START == SKIP) {
- if (parser->lexing_directive ||
- parser->skip_stack == NULL ||
- parser->skip_stack->type == SKIP_NO_SKIP)
- {
- BEGIN INITIAL;
- } else {
- BEGIN SKIP;
- }
+ if (parser->skip_stack &&
+ parser->skip_stack->type != SKIP_NO_SKIP &&
+ ! parser->lexing_directive)
+ {
+ parser->skipping = 1;
+ } else {
+ parser->skipping = 0;
}
/* Single-line comments */
-"//"[^\n]* {
+<INITIAL,DEFINE,HASH>"//"[^\r\n]* {
}
/* Multi-line comments */
-"/*" { yy_push_state(COMMENT, yyscanner); }
-<COMMENT>[^*\n]*
-<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; }
-<COMMENT>"*"+[^*/\n]*
-<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; parser->commented_newlines++; }
+<INITIAL,DEFINE,HASH>"/*" { yy_push_state(COMMENT, yyscanner); }
+<COMMENT>[^*\r\n]*
+<COMMENT>[^*\r\n]*{NEWLINE} { yylineno++; yycolumn = 0; parser->commented_newlines++; }
+<COMMENT>"*"+[^*/\r\n]*
+<COMMENT>"*"+[^*/\r\n]*{NEWLINE} { yylineno++; yycolumn = 0; parser->commented_newlines++; }
<COMMENT>"*"+"/" {
yy_pop_state(yyscanner);
- if (yyextra->space_tokens)
- return SPACE;
+ /* In the <HASH> start condition, we don't want any SPACE token. */
+ if (yyextra->space_tokens && YY_START != HASH)
+ RETURN_TOKEN (SPACE);
+}
+
+{HASH} {
+
+ /* If the '#' is the first non-whitespace, non-comment token on this
+ * line, then it introduces a directive, switch to the <HASH> start
+ * condition.
+ *
+ * Otherwise, this is just punctuation, so return the HASH_TOKEN
+ * token. */
+ if (parser->first_non_space_token_this_line) {
+ BEGIN HASH;
+ }
+
+ RETURN_TOKEN_NEVER_SKIP (HASH_TOKEN);
}
-{HASH}version{HSPACE}+ {
- yylval->str = ralloc_strdup (yyextra, yytext);
+<HASH>version{HSPACE}+ {
+ BEGIN INITIAL;
yyextra->space_tokens = 0;
- return HASH_VERSION;
+ RETURN_STRING_TOKEN (VERSION_TOKEN);
+}
+
+ /* Swallow empty #pragma directives, (to avoid confusing the
+ * downstream compiler). */
+<HASH>pragma{HSPACE}*/{NEWLINE} {
+ BEGIN INITIAL;
}
/* glcpp doesn't handle #extension, #version, or #pragma directives.
* Simply pass them through to the main compiler's lexer/parser. */
-{HASH}(extension|pragma)[^\n]* {
- if (parser->commented_newlines)
- BEGIN NEWLINE_CATCHUP;
- yylval->str = ralloc_strdup (yyextra, yytext);
- yylineno++;
- yycolumn = 0;
- return OTHER;
+<HASH>(extension|pragma)[^\r\n]* {
+ BEGIN INITIAL;
+ RETURN_STRING_TOKEN (PRAGMA);
}
-{HASH}line{HSPACE}+ {
- return HASH_LINE;
+<HASH>line{HSPACE}+ {
+ BEGIN INITIAL;
+ RETURN_TOKEN (LINE);
}
-<SKIP,INITIAL>{
-{HASH}ifdef {
+<HASH>{NEWLINE} {
+ BEGIN INITIAL;
+ RETURN_TOKEN_NEVER_SKIP (NEWLINE);
+}
+
+ /* For the pre-processor directives, we return these tokens
+ * even when we are otherwise skipping. */
+<HASH>ifdef {
+ BEGIN INITIAL;
yyextra->lexing_directive = 1;
yyextra->space_tokens = 0;
- return HASH_IFDEF;
+ RETURN_TOKEN_NEVER_SKIP (IFDEF);
}
-{HASH}ifndef {
+<HASH>ifndef {
+ BEGIN INITIAL;
yyextra->lexing_directive = 1;
yyextra->space_tokens = 0;
- return HASH_IFNDEF;
+ RETURN_TOKEN_NEVER_SKIP (IFNDEF);
}
-{HASH}if/[^_a-zA-Z0-9] {
+<HASH>if/[^_a-zA-Z0-9] {
+ BEGIN INITIAL;
yyextra->lexing_directive = 1;
yyextra->space_tokens = 0;
- return HASH_IF;
+ RETURN_TOKEN_NEVER_SKIP (IF);
}
-{HASH}elif/[^_a-zA-Z0-9] {
+<HASH>elif/[^_a-zA-Z0-9] {
+ BEGIN INITIAL;
yyextra->lexing_directive = 1;
yyextra->space_tokens = 0;
- return HASH_ELIF;
+ RETURN_TOKEN_NEVER_SKIP (ELIF);
}
-{HASH}else {
+<HASH>else {
+ BEGIN INITIAL;
yyextra->space_tokens = 0;
- return HASH_ELSE;
+ RETURN_TOKEN_NEVER_SKIP (ELSE);
}
-{HASH}endif {
+<HASH>endif {
+ BEGIN INITIAL;
yyextra->space_tokens = 0;
- return HASH_ENDIF;
-}
+ RETURN_TOKEN_NEVER_SKIP (ENDIF);
}
-<SKIP>[^\n] {
- if (parser->commented_newlines)
- BEGIN NEWLINE_CATCHUP;
+<HASH>error[^\r\n]* {
+ BEGIN INITIAL;
+ RETURN_STRING_TOKEN (ERROR_TOKEN);
}
-{HASH}error.* {
- char *p;
- for (p = yytext; !isalpha(p[0]); p++); /* skip " # " */
- p += 5; /* skip "error" */
- glcpp_error(yylloc, yyextra, "#error%s", p);
+ /* After we see a "#define" we enter the <DEFINE> start state
+ * for the lexer. Within <DEFINE> we are looking for the first
+ * identifier and specifically checking whether the identifier
+ * is followed by a '(' or not, (to lex either a
+ * FUNC_IDENTIFIER or an OBJ_IDENITIFIER token).
+ *
+ * While in the <DEFINE> state we also need to explicitly
+ * handle a few other things that may appear before the
+ * identifier:
+ *
+ * * Comments, (handled above with the main support for
+ * comments).
+ *
+ * * Whitespace (simply ignored)
+ *
+ * * Anything else, (not an identifier, not a comment,
+ * and not whitespace). This will generate an error.
+ */
+<HASH>define{HSPACE}* {
+ if (! parser->skipping) {
+ BEGIN DEFINE;
+ yyextra->space_tokens = 0;
+ RETURN_TOKEN (DEFINE_TOKEN);
+ }
}
-{HASH}define{HSPACE}+ {
+<HASH>undef {
+ BEGIN INITIAL;
yyextra->space_tokens = 0;
- yy_push_state(DEFINE, yyscanner);
- return HASH_DEFINE;
+ RETURN_TOKEN (UNDEF);
}
+<HASH>{HSPACE}+ {
+ /* Nothing to do here. Importantly, don't leave the <HASH>
+ * start condition, since it's legal to have space between the
+ * '#' and the directive.. */
+}
+
+ /* This will catch any non-directive garbage after a HASH */
+<HASH>{NONSPACE} {
+ BEGIN INITIAL;
+ RETURN_TOKEN (GARBAGE);
+}
+
+ /* An identifier immediately followed by '(' */
<DEFINE>{IDENTIFIER}/"(" {
- yy_pop_state(yyscanner);
- yylval->str = ralloc_strdup (yyextra, yytext);
- return FUNC_IDENTIFIER;
+ BEGIN INITIAL;
+ RETURN_STRING_TOKEN (FUNC_IDENTIFIER);
}
+ /* An identifier not immediately followed by '(' */
<DEFINE>{IDENTIFIER} {
- yy_pop_state(yyscanner);
- yylval->str = ralloc_strdup (yyextra, yytext);
- return OBJ_IDENTIFIER;
+ BEGIN INITIAL;
+ RETURN_STRING_TOKEN (OBJ_IDENTIFIER);
}
-{HASH}undef {
- yyextra->space_tokens = 0;
- return HASH_UNDEF;
+ /* Whitespace */
+<DEFINE>{HSPACE}+ {
+ /* Just ignore it. Nothing to do here. */
}
-{HASH} {
- yyextra->space_tokens = 0;
- return HASH;
+ /* '/' not followed by '*', so not a comment. This is an error. */
+<DEFINE>[/][^*]{NONSPACE}* {
+ BEGIN INITIAL;
+ glcpp_error(yylloc, yyextra, "#define followed by a non-identifier: %s", yytext);
+ RETURN_STRING_TOKEN (INTEGER_STRING);
+}
+
+ /* A character that can't start an identifier, comment, or
+ * space. This is an error. */
+<DEFINE>[^_a-zA-Z/[:space:]]{NONSPACE}* {
+ BEGIN INITIAL;
+ glcpp_error(yylloc, yyextra, "#define followed by a non-identifier: %s", yytext);
+ RETURN_STRING_TOKEN (INTEGER_STRING);
}
{DECIMAL_INTEGER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return INTEGER_STRING;
+ RETURN_STRING_TOKEN (INTEGER_STRING);
}
{OCTAL_INTEGER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return INTEGER_STRING;
+ RETURN_STRING_TOKEN (INTEGER_STRING);
}
{HEXADECIMAL_INTEGER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return INTEGER_STRING;
+ RETURN_STRING_TOKEN (INTEGER_STRING);
}
"<<" {
- return LEFT_SHIFT;
+ RETURN_TOKEN (LEFT_SHIFT);
}
">>" {
- return RIGHT_SHIFT;
+ RETURN_TOKEN (RIGHT_SHIFT);
}
"<=" {
- return LESS_OR_EQUAL;
+ RETURN_TOKEN (LESS_OR_EQUAL);
}
">=" {
- return GREATER_OR_EQUAL;
+ RETURN_TOKEN (GREATER_OR_EQUAL);
}
"==" {
- return EQUAL;
+ RETURN_TOKEN (EQUAL);
}
"!=" {
- return NOT_EQUAL;
+ RETURN_TOKEN (NOT_EQUAL);
}
"&&" {
- return AND;
+ RETURN_TOKEN (AND);
}
"||" {
- return OR;
+ RETURN_TOKEN (OR);
+}
+
+"++" {
+ RETURN_TOKEN (PLUS_PLUS);
+}
+
+"--" {
+ RETURN_TOKEN (MINUS_MINUS);
}
"##" {
- if (parser->is_gles)
- glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES");
- return PASTE;
+ if (! parser->skipping) {
+ if (parser->is_gles)
+ glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES");
+ RETURN_TOKEN (PASTE);
+ }
}
"defined" {
- return DEFINED;
+ RETURN_TOKEN (DEFINED);
}
{IDENTIFIER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return IDENTIFIER;
+ RETURN_STRING_TOKEN (IDENTIFIER);
}
{PP_NUMBER} {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return OTHER;
+ RETURN_STRING_TOKEN (OTHER);
}
{PUNCTUATION} {
- return yytext[0];
+ RETURN_TOKEN (yytext[0]);
}
{OTHER}+ {
- yylval->str = ralloc_strdup (yyextra, yytext);
- return OTHER;
+ RETURN_STRING_TOKEN (OTHER);
}
{HSPACE} {
if (yyextra->space_tokens) {
- return SPACE;
+ RETURN_TOKEN (SPACE);
}
}
-<SKIP,INITIAL>\n {
+ /* We preserve all newlines, even between #if 0..#endif, so no
+ skipping.. */
+<*>{NEWLINE} {
if (parser->commented_newlines) {
BEGIN NEWLINE_CATCHUP;
+ } else {
+ BEGIN INITIAL;
}
+ yyextra->space_tokens = 1;
yyextra->lexing_directive = 0;
yylineno++;
yycolumn = 0;
- return NEWLINE;
+ RETURN_TOKEN_NEVER_SKIP (NEWLINE);
}
- /* Handle missing newline at EOF. */
-<INITIAL><<EOF>> {
+<INITIAL,COMMENT,DEFINE,HASH><<EOF>> {
+ if (YY_START == COMMENT)
+ glcpp_error(yylloc, yyextra, "Unterminated comment");
BEGIN DONE; /* Don't keep matching this rule forever. */
yyextra->lexing_directive = 0;
- return NEWLINE;
+ if (! parser->last_token_was_newline)
+ RETURN_TOKEN (NEWLINE);
}
+ /* This is a catch-all to avoid the annoying default flex action which
+ * matches any character and prints it. If any input ever matches this
+ * rule, then we have made a mistake above and need to fix one or more
+ * of the preceding patterns to match that input. */
+
+<*>. {
+ glcpp_error(yylloc, yyextra, "Internal compiler error: Unexpected character: %s", yytext);
+
/* We don't actually use the UNREACHABLE start condition. We
- only have this action here so that we can pretend to call some
+ only have this block here so that we can pretend to call some
generated functions, (to avoid "defined but not used"
warnings. */
-<UNREACHABLE>. {
- unput('.');
- yy_top_state(yyextra);
+ if (YY_START == UNREACHABLE) {
+ unput('.');
+ yy_top_state(yyextra);
+ }
}
%%
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index 084078eb0..a61697394 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -57,6 +57,9 @@ _string_list_append_item (string_list_t *list, const char *str);
static int
_string_list_contains (string_list_t *list, const char *member, int *index);
+static const char *
+_string_list_has_duplicate (string_list_t *list);
+
static int
_string_list_length (string_list_t *list);
@@ -105,18 +108,25 @@ _parser_active_list_pop (glcpp_parser_t *parser);
static int
_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier);
+typedef enum {
+ EXPANSION_MODE_IGNORE_DEFINED,
+ EXPANSION_MODE_EVALUATE_DEFINED
+} expansion_mode_t;
+
/* Expand list, and begin lexing from the result (after first
* prefixing a token of type 'head_token_type').
*/
static void
_glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
int head_token_type,
- token_list_t *list);
+ token_list_t *list,
+ expansion_mode_t mode);
/* Perform macro expansion in-place on the given list. */
static void
_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
- token_list_t *list);
+ token_list_t *list,
+ expansion_mode_t mode);
static void
_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
@@ -164,14 +174,18 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
%lex-param {glcpp_parser_t *parser}
%expect 0
-%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE
+
+ /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to
+ * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols,
+ * (such as the <HASH> and <DEFINE> start conditions in the lexer). */
+%token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS
%token PASTE
%type <ival> INTEGER operator SPACE integer_constant
%type <expression_value> expression
-%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER
+%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA
%type <string_list> identifier_list
-%type <token> preprocessing_token conditional_token
-%type <token_list> pp_tokens replacement_list text_line conditional_tokens
+%type <token> preprocessing_token
+%type <token_list> pp_tokens replacement_list text_line
%left OR
%left AND
%left '|'
@@ -184,6 +198,8 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
%left '*' '/' '%'
%right UNARY
+%debug
+
%%
input:
@@ -192,27 +208,14 @@ input:
;
line:
- control_line {
- ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
- }
-| HASH_LINE {
- glcpp_parser_resolve_implicit_version(parser);
- } pp_tokens NEWLINE {
-
- if (parser->skip_stack == NULL ||
- parser->skip_stack->type == SKIP_NO_SKIP)
- {
- _glcpp_parser_expand_and_lex_from (parser,
- LINE_EXPANDED, $3);
- }
- }
+ control_line
+| SPACE control_line
| text_line {
_glcpp_parser_print_expanded_token_list (parser, $1);
ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
ralloc_free ($1);
}
| expanded_line
-| HASH non_directive
;
expanded_line:
@@ -259,29 +262,48 @@ define:
;
control_line:
- HASH_DEFINE {
+ control_line_success {
+ ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "\n");
+ }
+| control_line_error
+| HASH_TOKEN LINE {
+ glcpp_parser_resolve_implicit_version(parser);
+ } pp_tokens NEWLINE {
+
+ if (parser->skip_stack == NULL ||
+ parser->skip_stack->type == SKIP_NO_SKIP)
+ {
+ _glcpp_parser_expand_and_lex_from (parser,
+ LINE_EXPANDED, $4,
+ EXPANSION_MODE_IGNORE_DEFINED);
+ }
+ }
+;
+
+control_line_success:
+ HASH_TOKEN DEFINE_TOKEN {
glcpp_parser_resolve_implicit_version(parser);
} define
-| HASH_UNDEF {
+| HASH_TOKEN UNDEF {
glcpp_parser_resolve_implicit_version(parser);
} IDENTIFIER NEWLINE {
macro_t *macro;
- if (strcmp("__LINE__", $3) == 0
- || strcmp("__FILE__", $3) == 0
- || strcmp("__VERSION__", $3) == 0)
+ if (strcmp("__LINE__", $4) == 0
+ || strcmp("__FILE__", $4) == 0
+ || strcmp("__VERSION__", $4) == 0)
glcpp_error(& @1, parser, "Built-in (pre-defined)"
" macro names can not be undefined.");
- macro = hash_table_find (parser->defines, $3);
+ macro = hash_table_find (parser->defines, $4);
if (macro) {
- hash_table_remove (parser->defines, $3);
+ hash_table_remove (parser->defines, $4);
ralloc_free (macro);
}
- ralloc_free ($3);
+ ralloc_free ($4);
}
-| HASH_IF {
+| HASH_TOKEN IF {
glcpp_parser_resolve_implicit_version(parser);
- } conditional_tokens NEWLINE {
+ } pp_tokens NEWLINE {
/* Be careful to only evaluate the 'if' expression if
* we are not skipping. When we are skipping, we
* simply push a new 0-valued 'if' onto the skip
@@ -293,7 +315,8 @@ control_line:
parser->skip_stack->type == SKIP_NO_SKIP)
{
_glcpp_parser_expand_and_lex_from (parser,
- IF_EXPANDED, $3);
+ IF_EXPANDED, $4,
+ EXPANSION_MODE_EVALUATE_DEFINED);
}
else
{
@@ -301,7 +324,7 @@ control_line:
parser->skip_stack->type = SKIP_TO_ENDIF;
}
}
-| HASH_IF NEWLINE {
+| HASH_TOKEN IF NEWLINE {
/* #if without an expression is only an error if we
* are not skipping */
if (parser->skip_stack == NULL ||
@@ -311,21 +334,21 @@ control_line:
}
_glcpp_parser_skip_stack_push_if (parser, & @1, 0);
}
-| HASH_IFDEF {
+| HASH_TOKEN IFDEF {
glcpp_parser_resolve_implicit_version(parser);
} IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $3);
- ralloc_free ($3);
+ macro_t *macro = hash_table_find (parser->defines, $4);
+ ralloc_free ($4);
_glcpp_parser_skip_stack_push_if (parser, & @1, macro != NULL);
}
-| HASH_IFNDEF {
+| HASH_TOKEN IFNDEF {
glcpp_parser_resolve_implicit_version(parser);
} IDENTIFIER junk NEWLINE {
- macro_t *macro = hash_table_find (parser->defines, $3);
- ralloc_free ($3);
- _glcpp_parser_skip_stack_push_if (parser, & @2, macro == NULL);
+ macro_t *macro = hash_table_find (parser->defines, $4);
+ ralloc_free ($4);
+ _glcpp_parser_skip_stack_push_if (parser, & @3, macro == NULL);
}
-| HASH_ELIF conditional_tokens NEWLINE {
+| HASH_TOKEN ELIF pp_tokens NEWLINE {
/* Be careful to only evaluate the 'elif' expression
* if we are not skipping. When we are skipping, we
* simply change to a 0-valued 'elif' on the skip
@@ -337,7 +360,8 @@ control_line:
parser->skip_stack->type == SKIP_TO_ELSE)
{
_glcpp_parser_expand_and_lex_from (parser,
- ELIF_EXPANDED, $2);
+ ELIF_EXPANDED, $3,
+ EXPANSION_MODE_EVALUATE_DEFINED);
}
else if (parser->skip_stack &&
parser->skip_stack->has_else)
@@ -350,7 +374,7 @@ control_line:
"elif", 0);
}
}
-| HASH_ELIF NEWLINE {
+| HASH_TOKEN ELIF NEWLINE {
/* #elif without an expression is an error unless we
* are skipping. */
if (parser->skip_stack &&
@@ -370,7 +394,7 @@ control_line:
glcpp_warning(& @1, parser, "ignoring illegal #elif without expression");
}
}
-| HASH_ELSE { parser->lexing_directive = 1; } NEWLINE {
+| HASH_TOKEN ELSE { parser->lexing_directive = 1; } NEWLINE {
if (parser->skip_stack &&
parser->skip_stack->has_else)
{
@@ -383,24 +407,39 @@ control_line:
parser->skip_stack->has_else = true;
}
}
-| HASH_ENDIF {
+| HASH_TOKEN ENDIF {
_glcpp_parser_skip_stack_pop (parser, & @1);
} NEWLINE
-| HASH_VERSION integer_constant NEWLINE {
+| HASH_TOKEN VERSION_TOKEN integer_constant NEWLINE {
if (parser->version_resolved) {
glcpp_error(& @1, parser, "#version must appear on the first line");
}
- _glcpp_parser_handle_version_declaration(parser, $2, NULL, true);
+ _glcpp_parser_handle_version_declaration(parser, $3, NULL, true);
}
-| HASH_VERSION integer_constant IDENTIFIER NEWLINE {
+| HASH_TOKEN VERSION_TOKEN integer_constant IDENTIFIER NEWLINE {
if (parser->version_resolved) {
glcpp_error(& @1, parser, "#version must appear on the first line");
}
- _glcpp_parser_handle_version_declaration(parser, $2, $3, true);
+ _glcpp_parser_handle_version_declaration(parser, $3, $4, true);
}
-| HASH NEWLINE {
+| HASH_TOKEN NEWLINE {
glcpp_parser_resolve_implicit_version(parser);
}
+| HASH_TOKEN PRAGMA NEWLINE {
+ ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#%s", $2);
+ }
+;
+
+control_line_error:
+ HASH_TOKEN ERROR_TOKEN NEWLINE {
+ glcpp_error(& @1, parser, "#%s", $2);
+ }
+| HASH_TOKEN DEFINE_TOKEN NEWLINE {
+ glcpp_error (& @1, parser, "#define without macro name");
+ }
+| HASH_TOKEN GARBAGE pp_tokens NEWLINE {
+ glcpp_error (& @1, parser, "Illegal non-directive after #");
+ }
;
integer_constant:
@@ -612,12 +651,6 @@ text_line:
| pp_tokens NEWLINE
;
-non_directive:
- pp_tokens NEWLINE {
- yyerror (& @1, parser, "Invalid tokens after #");
- }
-;
-
replacement_list:
/* empty */ { $$ = NULL; }
| pp_tokens
@@ -630,31 +663,6 @@ junk:
}
;
-conditional_token:
- /* Handle "defined" operator */
- DEFINED IDENTIFIER {
- int v = hash_table_find (parser->defines, $2) ? 1 : 0;
- $$ = _token_create_ival (parser, INTEGER, v);
- }
-| DEFINED '(' IDENTIFIER ')' {
- int v = hash_table_find (parser->defines, $3) ? 1 : 0;
- $$ = _token_create_ival (parser, INTEGER, v);
- }
-| preprocessing_token
-;
-
-conditional_tokens:
- /* Exactly the same as pp_tokens, but using conditional_token */
- conditional_token {
- $$ = _token_list_create (parser);
- _token_list_append ($$, $1);
- }
-| conditional_tokens conditional_token {
- $$ = $1;
- _token_list_append ($$, $2);
- }
-;
-
pp_tokens:
preprocessing_token {
parser->space_tokens = 1;
@@ -680,6 +688,10 @@ preprocessing_token:
$$ = _token_create_ival (parser, $1, $1);
$$->location = yylloc;
}
+| DEFINED {
+ $$ = _token_create_ival (parser, DEFINED, DEFINED);
+ $$->location = yylloc;
+ }
| OTHER {
$$ = _token_create_str (parser, OTHER, $1);
$$->location = yylloc;
@@ -722,6 +734,8 @@ operator:
| ',' { $$ = ','; }
| '=' { $$ = '='; }
| PASTE { $$ = PASTE; }
+| PLUS_PLUS { $$ = PLUS_PLUS; }
+| MINUS_MINUS { $$ = MINUS_MINUS; }
;
%%
@@ -777,6 +791,25 @@ _string_list_contains (string_list_t *list, const char *member, int *index)
return 0;
}
+/* Return duplicate string in list (if any), NULL otherwise. */
+const char *
+_string_list_has_duplicate (string_list_t *list)
+{
+ string_node_t *node, *dup;
+
+ if (list == NULL)
+ return NULL;
+
+ for (node = list->head; node; node = node->next) {
+ for (dup = node->next; dup; dup = dup->next) {
+ if (strcmp (node->str, dup->str) == 0)
+ return node->str;
+ }
+ }
+
+ return NULL;
+}
+
int
_string_list_length (string_list_t *list)
{
@@ -1123,14 +1156,21 @@ _token_print (char **out, size_t *len, token_t *token)
case PASTE:
ralloc_asprintf_rewrite_tail (out, len, "##");
break;
- case COMMA_FINAL:
- ralloc_asprintf_rewrite_tail (out, len, ",");
+ case PLUS_PLUS:
+ ralloc_asprintf_rewrite_tail (out, len, "++");
+ break;
+ case MINUS_MINUS:
+ ralloc_asprintf_rewrite_tail (out, len, "--");
+ break;
+ case DEFINED:
+ ralloc_asprintf_rewrite_tail (out, len, "defined");
break;
case PLACEHOLDER:
/* Nothing to print. */
break;
default:
assert(!"Error: Don't know how to print token.");
+
break;
}
}
@@ -1308,12 +1348,16 @@ glcpp_parser_create (const struct gl_extensions *extensions, gl_api api)
parser->active = NULL;
parser->lexing_directive = 0;
parser->space_tokens = 1;
+ parser->last_token_was_newline = 0;
+ parser->last_token_was_space = 0;
+ parser->first_non_space_token_this_line = 1;
parser->newline_as_space = 0;
parser->in_control_line = 0;
parser->paren_count = 0;
parser->commented_newlines = 0;
parser->skip_stack = NULL;
+ parser->skipping = 0;
parser->lex_from_list = NULL;
parser->lex_from_node = NULL;
@@ -1459,15 +1503,143 @@ _token_list_create_with_one_integer (void *ctx, int ival)
return _token_list_create_with_one_ival (ctx, INTEGER, ival);
}
+/* Evaluate a DEFINED token node (based on subsequent tokens in the list).
+ *
+ * Note: This function must only be called when "node" is a DEFINED token,
+ * (and will abort with an assertion failure otherwise).
+ *
+ * If "node" is followed, (ignoring any SPACE tokens), by an IDENTIFIER token
+ * (optionally preceded and followed by '(' and ')' tokens) then the following
+ * occurs:
+ *
+ * If the identifier is a defined macro, this function returns 1.
+ *
+ * If the identifier is not a defined macro, this function returns 0.
+ *
+ * In either case, *last will be updated to the last node in the list
+ * consumed by the evaluation, (either the token of the identifier or the
+ * token of the closing parenthesis).
+ *
+ * In all other cases, (such as "node is the final node of the list", or
+ * "missing closing parenthesis", etc.), this function generates a
+ * preprocessor error, returns -1 and *last will not be set.
+ */
+static int
+_glcpp_parser_evaluate_defined (glcpp_parser_t *parser,
+ token_node_t *node,
+ token_node_t **last)
+{
+ token_node_t *argument, *defined = node;
+
+ assert (node->token->type == DEFINED);
+
+ node = node->next;
+
+ /* Ignore whitespace after DEFINED token. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL)
+ goto FAIL;
+
+ if (node->token->type == IDENTIFIER || node->token->type == OTHER) {
+ argument = node;
+ } else if (node->token->type == '(') {
+ node = node->next;
+
+ /* Ignore whitespace after '(' token. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || (node->token->type != IDENTIFIER &&
+ node->token->type != OTHER))
+ {
+ goto FAIL;
+ }
+
+ argument = node;
+
+ node = node->next;
+
+ /* Ignore whitespace after identifier, before ')' token. */
+ while (node && node->token->type == SPACE)
+ node = node->next;
+
+ if (node == NULL || node->token->type != ')')
+ goto FAIL;
+ } else {
+ goto FAIL;
+ }
+
+ *last = node;
+
+ return hash_table_find (parser->defines,
+ argument->token->value.str) ? 1 : 0;
+
+FAIL:
+ glcpp_error (&defined->token->location, parser,
+ "\"defined\" not followed by an identifier");
+ return -1;
+}
+
+/* Evaluate all DEFINED nodes in a given list, modifying the list in place.
+ */
+static void
+_glcpp_parser_evaluate_defined_in_list (glcpp_parser_t *parser,
+ token_list_t *list)
+{
+ token_node_t *node, *node_prev, *replacement, *last = NULL;
+ int value;
+
+ if (list == NULL)
+ return;
+
+ node_prev = NULL;
+ node = list->head;
+
+ while (node) {
+
+ if (node->token->type != DEFINED)
+ goto NEXT;
+
+ value = _glcpp_parser_evaluate_defined (parser, node, &last);
+ if (value == -1)
+ goto NEXT;
+
+ replacement = ralloc (list, token_node_t);
+ replacement->token = _token_create_ival (list, INTEGER, value);
+
+ /* Splice replacement node into list, replacing from "node"
+ * through "last". */
+ if (node_prev)
+ node_prev->next = replacement;
+ else
+ list->head = replacement;
+ replacement->next = last->next;
+ if (last == list->tail)
+ list->tail = replacement;
+
+ node = replacement;
+
+ NEXT:
+ node_prev = node;
+ node = node->next;
+ }
+}
+
/* Perform macro expansion on 'list', placing the resulting tokens
* into a new list which is initialized with a first token of type
* 'head_token_type'. Then begin lexing from the resulting list,
* (return to the current lexing source when this list is exhausted).
+ *
+ * See the documentation of _glcpp_parser_expand_token_list for a description
+ * of the "mode" parameter.
*/
static void
_glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
int head_token_type,
- token_list_t *list)
+ token_list_t *list,
+ expansion_mode_t mode)
{
token_list_t *expanded;
token_t *token;
@@ -1475,7 +1647,7 @@ _glcpp_parser_expand_and_lex_from (glcpp_parser_t *parser,
expanded = _token_list_create (parser);
token = _token_create_ival (parser, head_token_type, head_token_type);
_token_list_append (expanded, token);
- _glcpp_parser_expand_token_list (parser, list);
+ _glcpp_parser_expand_token_list (parser, list, mode);
_token_list_append_list (expanded, list);
glcpp_parser_lex_from (parser, expanded);
}
@@ -1538,12 +1710,15 @@ _glcpp_parser_apply_pastes (glcpp_parser_t *parser, token_list_t *list)
* *last to the last node in the list that was consumed by the
* expansion. Specifically, *last will be set as follows: as the
* token of the closing right parenthesis.
+ *
+ * See the documentation of _glcpp_parser_expand_token_list for a description
+ * of the "mode" parameter.
*/
static token_list_t *
_glcpp_parser_expand_function (glcpp_parser_t *parser,
token_node_t *node,
- token_node_t **last)
-
+ token_node_t **last,
+ expansion_mode_t mode)
{
macro_t *macro;
const char *identifier;
@@ -1612,7 +1787,8 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser,
expanded_argument = _token_list_copy (parser,
argument);
_glcpp_parser_expand_token_list (parser,
- expanded_argument);
+ expanded_argument,
+ mode);
_token_list_append_list (substituted,
expanded_argument);
} else {
@@ -1652,11 +1828,15 @@ _glcpp_parser_expand_function (glcpp_parser_t *parser,
*
* As the token of the closing right parenthesis in the case of
* function-like macro expansion.
+ *
+ * See the documentation of _glcpp_parser_expand_token_list for a description
+ * of the "mode" parameter.
*/
static token_list_t *
_glcpp_parser_expand_node (glcpp_parser_t *parser,
token_node_t *node,
- token_node_t **last)
+ token_node_t **last,
+ expansion_mode_t mode)
{
token_t *token = node->token;
const char *identifier;
@@ -1664,14 +1844,6 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
/* We only expand identifiers */
if (token->type != IDENTIFIER) {
- /* We change any COMMA into a COMMA_FINAL to prevent
- * it being mistaken for an argument separator
- * later. */
- if (token->type == ',') {
- token->type = COMMA_FINAL;
- token->value.ival = COMMA_FINAL;
- }
-
return NULL;
}
@@ -1723,7 +1895,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
return replacement;
}
- return _glcpp_parser_expand_function (parser, node, last);
+ return _glcpp_parser_expand_function (parser, node, last, mode);
}
/* Push a new identifier onto the parser's active list.
@@ -1782,11 +1954,28 @@ _parser_active_list_contains (glcpp_parser_t *parser, const char *identifier)
/* Walk over the token list replacing nodes with their expansion.
* Whenever nodes are expanded the walking will walk over the new
* nodes, continuing to expand as necessary. The results are placed in
- * 'list' itself;
+ * 'list' itself.
+ *
+ * The "mode" argument controls the handling of any DEFINED tokens that
+ * result from expansion as follows:
+ *
+ * EXPANSION_MODE_IGNORE_DEFINED: Any resulting DEFINED tokens will be
+ * left in the final list, unevaluated. This is the correct mode
+ * for expanding any list in any context other than a
+ * preprocessor conditional, (#if or #elif).
+ *
+ * EXPANSION_MODE_EVALUATE_DEFINED: Any resulting DEFINED tokens will be
+ * evaluated to 0 or 1 tokens depending on whether the following
+ * token is the name of a defined macro. If the DEFINED token is
+ * not followed by an (optionally parenthesized) identifier, then
+ * an error will be generated. This the correct mode for
+ * expanding any list in the context of a preprocessor
+ * conditional, (#if or #elif).
*/
static void
_glcpp_parser_expand_token_list (glcpp_parser_t *parser,
- token_list_t *list)
+ token_list_t *list,
+ expansion_mode_t mode)
{
token_node_t *node_prev;
token_node_t *node, *last = NULL;
@@ -1801,15 +1990,23 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser,
node_prev = NULL;
node = list->head;
+ if (mode == EXPANSION_MODE_EVALUATE_DEFINED)
+ _glcpp_parser_evaluate_defined_in_list (parser, list);
+
while (node) {
while (parser->active && parser->active->marker == node)
_parser_active_list_pop (parser);
- expansion = _glcpp_parser_expand_node (parser, node, &last);
+ expansion = _glcpp_parser_expand_node (parser, node, &last, mode);
if (expansion) {
token_node_t *n;
+ if (mode == EXPANSION_MODE_EVALUATE_DEFINED) {
+ _glcpp_parser_evaluate_defined_in_list (parser,
+ expansion);
+ }
+
for (n = node; n != last->next; n = n->next)
while (parser->active &&
parser->active->marker == n)
@@ -1862,7 +2059,7 @@ _glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser,
if (list == NULL)
return;
- _glcpp_parser_expand_token_list (parser, list);
+ _glcpp_parser_expand_token_list (parser, list, EXPANSION_MODE_IGNORE_DEFINED);
_token_list_trim_trailing_space (list);
@@ -1923,6 +2120,10 @@ _define_object_macro (glcpp_parser_t *parser,
{
macro_t *macro, *previous;
+ /* We define pre-defined macros before we've started parsing the
+ * actual file. So if there's no location defined yet, that's what
+ * were doing and we don't want to generate an error for using the
+ * reserved names. */
if (loc != NULL)
_check_for_reserved_macro_name(parser, loc, identifier);
@@ -1955,9 +2156,16 @@ _define_function_macro (glcpp_parser_t *parser,
token_list_t *replacements)
{
macro_t *macro, *previous;
+ const char *dup;
_check_for_reserved_macro_name(parser, loc, identifier);
+ /* Check for any duplicate parameter names. */
+ if ((dup = _string_list_has_duplicate (parameters)) != NULL) {
+ glcpp_error (loc, parser, "Duplicate macro parameter \"%s\"",
+ dup);
+ }
+
macro = ralloc (parser, macro_t);
ralloc_steal (macro, parameters);
ralloc_steal (macro, replacements);
@@ -2020,11 +2228,11 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
if (ret == NEWLINE)
parser->in_control_line = 0;
}
- else if (ret == HASH_DEFINE ||
- ret == HASH_UNDEF || ret == HASH_IF ||
- ret == HASH_IFDEF || ret == HASH_IFNDEF ||
- ret == HASH_ELIF || ret == HASH_ELSE ||
- ret == HASH_ENDIF || ret == HASH)
+ else if (ret == DEFINE_TOKEN ||
+ ret == UNDEF || ret == IF ||
+ ret == IFDEF || ret == IFNDEF ||
+ ret == ELIF || ret == ELSE ||
+ ret == ENDIF || ret == HASH_TOKEN)
{
parser->in_control_line = 1;
}
@@ -2117,7 +2325,7 @@ _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc,
const char *type, int condition)
{
if (parser->skip_stack == NULL) {
- glcpp_error (loc, parser, "%s without #if\n", type);
+ glcpp_error (loc, parser, "#%s without #if\n", type);
return;
}
@@ -2170,6 +2378,8 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (extensions != NULL) {
if (extensions->OES_EGL_image_external)
add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
+ if (extensions->OES_standard_derivatives)
+ add_builtin_define(parser, "GL_OES_standard_derivatives", 1);
}
} else {
add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
diff --git a/mesalib/src/glsl/glcpp/glcpp.c b/mesalib/src/glsl/glcpp/glcpp.c
index 07b1500b6..ca188015c 100644
--- a/mesalib/src/glsl/glcpp/glcpp.c
+++ b/mesalib/src/glsl/glcpp/glcpp.c
@@ -124,6 +124,7 @@ enum {
const static struct option
long_options[] = {
{"disable-line-continuations", no_argument, 0, DISABLE_LINE_CONTINUATIONS_OPT },
+ {"debug", no_argument, 0, 'd'},
{0, 0, 0, 0 }
};
@@ -140,11 +141,14 @@ main (int argc, char *argv[])
init_fake_gl_context (&gl_ctx);
- while ((c = getopt_long(argc, argv, "", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "d", long_options, NULL)) != -1) {
switch (c) {
case DISABLE_LINE_CONTINUATIONS_OPT:
gl_ctx.Const.DisableGLSLLineContinuations = true;
break;
+ case 'd':
+ glcpp_parser_debug = 1;
+ break;
default:
usage ();
exit (1);
diff --git a/mesalib/src/glsl/glcpp/glcpp.h b/mesalib/src/glsl/glcpp/glcpp.h
index 64b487202..70aa14b6e 100644
--- a/mesalib/src/glsl/glcpp/glcpp.h
+++ b/mesalib/src/glsl/glcpp/glcpp.h
@@ -29,7 +29,7 @@
#include "main/mtypes.h"
-#include "../ralloc.h"
+#include "util/ralloc.h"
#include "program/hash_table.h"
@@ -177,11 +177,15 @@ struct glcpp_parser {
active_list_t *active;
int lexing_directive;
int space_tokens;
+ int last_token_was_newline;
+ int last_token_was_space;
+ int first_non_space_token_this_line;
int newline_as_space;
int in_control_line;
int paren_count;
int commented_newlines;
skip_node_t *skip_stack;
+ int skipping;
token_list_t *lex_from_list;
token_node_t *lex_from_node;
char *output;
diff --git a/mesalib/src/glsl/glcpp/pp.c b/mesalib/src/glsl/glcpp/pp.c
index 4a623f81e..a54bcbe16 100644
--- a/mesalib/src/glsl/glcpp/pp.c
+++ b/mesalib/src/glsl/glcpp/pp.c
@@ -70,6 +70,42 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
&parser->info_log_length, "\n");
}
+/* Given str, (that's expected to start with a newline terminator of some
+ * sort), return a pointer to the first character in str after the newline.
+ *
+ * A newline terminator can be any of the following sequences:
+ *
+ * "\r\n"
+ * "\n\r"
+ * "\n"
+ * "\r"
+ *
+ * And the longest such sequence will be skipped.
+ */
+static const char *
+skip_newline (const char *str)
+{
+ const char *ret = str;
+
+ if (ret == NULL)
+ return ret;
+
+ if (*ret == '\0')
+ return ret;
+
+ if (*ret == '\r') {
+ ret++;
+ if (*ret && *ret == '\n')
+ ret++;
+ } else if (*ret == '\n') {
+ ret++;
+ if (*ret && *ret == '\r')
+ ret++;
+ }
+
+ return ret;
+}
+
/* Remove any line continuation characters in the shader, (whether in
* preprocessing directives or in GLSL code).
*/
@@ -78,10 +114,49 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
{
char *clean = ralloc_strdup(ctx, "");
const char *backslash, *newline, *search_start;
+ const char *cr, *lf;
+ char newline_separator[3];
int collapsed_newlines = 0;
search_start = shader;
+ /* Determine what flavor of newlines this shader is using. GLSL
+ * provides for 4 different possible ways to separate lines, (using
+ * one or two characters):
+ *
+ * "\n" (line-feed, like Linux, Unix, and new Mac OS)
+ * "\r" (carriage-return, like old Mac files)
+ * "\r\n" (carriage-return + line-feed, like DOS files)
+ * "\n\r" (line-feed + carriage-return, like nothing, really)
+ *
+ * This code explicitly supports a shader that uses a mixture of
+ * newline terminators and will properly handle line continuation
+ * backslashes followed by any of the above.
+ *
+ * But, since we must also insert additional newlines in the output
+ * (for any collapsed lines) we attempt to maintain consistency by
+ * examining the first encountered newline terminator, and using the
+ * same terminator for any newlines we insert.
+ */
+ cr = strchr(search_start, '\r');
+ lf = strchr(search_start, '\n');
+
+ newline_separator[0] = '\n';
+ newline_separator[1] = '\0';
+ newline_separator[2] = '\0';
+
+ if (cr == NULL) {
+ /* Nothing to do. */
+ } else if (lf == NULL) {
+ newline_separator[0] = '\r';
+ } else if (lf == cr + 1) {
+ newline_separator[0] = '\r';
+ newline_separator[1] = '\n';
+ } else if (cr == lf + 1) {
+ newline_separator[0] = '\n';
+ newline_separator[1] = '\r';
+ }
+
while (true) {
backslash = strchr(search_start, '\\');
@@ -91,17 +166,24 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
* line numbers.
*/
if (collapsed_newlines) {
- newline = strchr(search_start, '\n');
+ cr = strchr (search_start, '\r');
+ lf = strchr (search_start, '\n');
+ if (cr && lf)
+ newline = cr < lf ? cr : lf;
+ else if (cr)
+ newline = cr;
+ else
+ newline = lf;
if (newline &&
(backslash == NULL || newline < backslash))
{
ralloc_strncat(&clean, shader,
newline - shader + 1);
while (collapsed_newlines) {
- ralloc_strcat(&clean, "\n");
+ ralloc_strcat(&clean, newline_separator);
collapsed_newlines--;
}
- shader = newline + 1;
+ shader = skip_newline (newline);
search_start = shader;
}
}
@@ -116,15 +198,11 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
* advance the shader pointer to the character after the
* newline.
*/
- if (backslash[1] == '\n' ||
- (backslash[1] == '\r' && backslash[2] == '\n'))
+ if (backslash[1] == '\r' || backslash[1] == '\n')
{
collapsed_newlines++;
ralloc_strncat(&clean, shader, backslash - shader);
- if (backslash[1] == '\n')
- shader = backslash + 2;
- else
- shader = backslash + 3;
+ shader = skip_newline (backslash + 1);
search_start = shader;
}
}
diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll
index db7b1d179..b7c4aad3a 100644
--- a/mesalib/src/glsl/glsl_lexer.ll
+++ b/mesalib/src/glsl/glsl_lexer.ll
@@ -152,7 +152,11 @@ literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state,
%option never-interactive
%option prefix="_mesa_glsl_lexer_"
%option extra-type="struct _mesa_glsl_parse_state *"
+%option warn nodefault
+ /* Note: When adding any start conditions to this list, you must also
+ * update the "Internal compiler error" catch-all rule near the end of
+ * this file. */
%x PP PRAGMA
DEC_INT [1-9][0-9]*
@@ -236,6 +240,7 @@ HASH ^{SPC}#{SPC}
return INTCONSTANT;
}
<PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
+<PP>. { return yytext[0]; }
\n { yylineno++; yycolumn = 0; }
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 890123ad1..2d94d3554 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -31,7 +31,7 @@ extern "C" {
#include "main/shaderobj.h"
}
-#include "ralloc.h"
+#include "util/ralloc.h"
#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.h"
@@ -1487,7 +1487,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
if (shader->InfoLog)
ralloc_free(shader->InfoLog);
- shader->symbols = state->symbols;
+ shader->symbols = new(shader->ir) glsl_symbol_table;
shader->CompileStatus = !state->error;
shader->InfoLog = state->info_log;
shader->Version = state->language_version;
@@ -1500,6 +1500,30 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
/* Retain any live IR, but trash the rest. */
reparent_ir(shader->ir, shader->ir);
+ /* Destroy the symbol table. Create a new symbol table that contains only
+ * the variables and functions that still exist in the IR. The symbol
+ * table will be used later during linking.
+ *
+ * There must NOT be any freed objects still referenced by the symbol
+ * table. That could cause the linker to dereference freed memory.
+ *
+ * We don't have to worry about types or interface-types here because those
+ * are fly-weights that are looked up by glsl_type.
+ */
+ foreach_in_list (ir_instruction, ir, shader->ir) {
+ switch (ir->ir_type) {
+ case ir_type_function:
+ shader->symbols->add_function((ir_function *) ir);
+ break;
+ case ir_type_variable:
+ shader->symbols->add_variable((ir_variable *) ir);
+ break;
+ default:
+ break;
+ }
+ }
+
+ delete state->symbols;
ralloc_free(state);
}
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index f9cd258fe..66e9b1330 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -108,7 +108,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].interpolation = fields[i].interpolation;
this->fields.structure[i].centroid = fields[i].centroid;
this->fields.structure[i].sample = fields[i].sample;
- this->fields.structure[i].row_major = fields[i].row_major;
+ this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
}
}
@@ -136,7 +136,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].interpolation = fields[i].interpolation;
this->fields.structure[i].centroid = fields[i].centroid;
this->fields.structure[i].sample = fields[i].sample;
- this->fields.structure[i].row_major = fields[i].row_major;
+ this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
}
}
@@ -496,8 +496,8 @@ glsl_type::record_compare(const glsl_type *b) const
if (strcmp(this->fields.structure[i].name,
b->fields.structure[i].name) != 0)
return false;
- if (this->fields.structure[i].row_major
- != b->fields.structure[i].row_major)
+ if (this->fields.structure[i].matrix_layout
+ != b->fields.structure[i].matrix_layout)
return false;
if (this->fields.structure[i].location
!= b->fields.structure[i].location)
@@ -826,9 +826,18 @@ glsl_type::std140_base_alignment(bool row_major) const
if (this->is_record()) {
unsigned base_alignment = 16;
for (unsigned i = 0; i < this->length; i++) {
+ bool field_row_major = row_major;
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(this->fields.structure[i].matrix_layout);
+ if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
+ field_row_major = true;
+ } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
+ field_row_major = false;
+ }
+
const struct glsl_type *field_type = this->fields.structure[i].type;
base_alignment = MAX2(base_alignment,
- field_type->std140_base_alignment(row_major));
+ field_type->std140_base_alignment(field_row_major));
}
return base_alignment;
}
@@ -872,8 +881,7 @@ glsl_type::std140_size(bool row_major) const
* and <R> rows, the matrix is stored identically to a row of <S>*<R>
* row vectors with <C> components each, according to rule (4).
*/
- if (this->is_matrix() || (this->is_array() &&
- this->fields.array->is_matrix())) {
+ if (this->without_array()->is_matrix()) {
const struct glsl_type *element_type;
const struct glsl_type *vec_type;
unsigned int array_len;
@@ -935,14 +943,29 @@ glsl_type::std140_size(bool row_major) const
*/
if (this->is_record()) {
unsigned size = 0;
+ unsigned max_align = 0;
+
for (unsigned i = 0; i < this->length; i++) {
+ bool field_row_major = row_major;
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(this->fields.structure[i].matrix_layout);
+ if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
+ field_row_major = true;
+ } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
+ field_row_major = false;
+ }
+
const struct glsl_type *field_type = this->fields.structure[i].type;
- unsigned align = field_type->std140_base_alignment(row_major);
+ unsigned align = field_type->std140_base_alignment(field_row_major);
size = glsl_align(size, align);
- size += field_type->std140_size(row_major);
+ size += field_type->std140_size(field_row_major);
+
+ max_align = MAX2(align, max_align);
+
+ if (field_type->is_record() && (i + 1 < this->length))
+ size = glsl_align(size, 16);
}
- size = glsl_align(size,
- this->fields.structure[0].type->std140_base_alignment(row_major));
+ size = glsl_align(size, max_align);
return size;
}
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index 0b63d4850..d545533dc 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -79,9 +79,30 @@ enum glsl_interface_packing {
GLSL_INTERFACE_PACKING_PACKED
};
+enum glsl_matrix_layout {
+ /**
+ * The layout of the matrix is inherited from the object containing the
+ * matrix (the top level structure or the uniform block).
+ */
+ GLSL_MATRIX_LAYOUT_INHERITED,
+
+ /**
+ * Explicit column-major layout
+ *
+ * If a uniform block doesn't have an explicit layout set, it will default
+ * to this layout.
+ */
+ GLSL_MATRIX_LAYOUT_COLUMN_MAJOR,
+
+ /**
+ * Row-major layout
+ */
+ GLSL_MATRIX_LAYOUT_ROW_MAJOR
+};
+
#ifdef __cplusplus
#include "GL/gl.h"
-#include "ralloc.h"
+#include "util/ralloc.h"
struct glsl_type {
GLenum gl_type;
@@ -465,6 +486,18 @@ struct glsl_type {
}
/**
+ * Get the type stripped of any arrays
+ *
+ * \return
+ * Pointer to the type of elements of the first non-array type for array
+ * types, or pointer to itself for non-array types.
+ */
+ const glsl_type *without_array() const
+ {
+ return this->is_array() ? this->fields.array : this;
+ }
+
+ /**
* Return the amount of atomic counter storage required for a type.
*/
unsigned atomic_size() const
@@ -643,7 +676,6 @@ private:
struct glsl_struct_field {
const struct glsl_type *type;
const char *name;
- bool row_major;
/**
* For interface blocks, gl_varying_slot corresponding to the input/output
@@ -673,6 +705,11 @@ struct glsl_struct_field {
unsigned sample:1;
/**
+ * Layout of the matrix. Uses glsl_matrix_layout values.
+ */
+ unsigned matrix_layout:2;
+
+ /**
* For interface blocks, it has a value if this variable uses multiple vertex
* streams (as in ir_variable::stream). -1 otherwise.
*/
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index ea19924ab..31c354556 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -29,7 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include "ralloc.h"
+#include "util/ralloc.h"
#include "glsl_types.h"
#include "list.h"
#include "ir_visitor.h"
@@ -660,6 +660,11 @@ public:
unsigned location_frac:2;
/**
+ * Layout of the matrix. Uses glsl_matrix_layout values.
+ */
+ unsigned matrix_layout:2;
+
+ /**
* Non-zero if this variable was created by lowering a named interface
* block which was not an array.
*
@@ -974,6 +979,7 @@ public:
*/
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_param,
+ bool allow_builtins,
bool *match_is_exact);
/**
@@ -981,7 +987,8 @@ public:
* conversions into account.
*/
ir_function_signature *matching_signature(_mesa_glsl_parse_state *state,
- const exec_list *actual_param);
+ const exec_list *actual_param,
+ bool allow_builtins);
/**
* Find a signature that exactly matches a set of actual parameters without
diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp
index 7d6c2f451..98bec45ce 100644
--- a/mesalib/src/glsl/ir_function.cpp
+++ b/mesalib/src/glsl/ir_function.cpp
@@ -281,15 +281,18 @@ choose_best_inexact_overload(_mesa_glsl_parse_state *state,
ir_function_signature *
ir_function::matching_signature(_mesa_glsl_parse_state *state,
- const exec_list *actual_parameters)
+ const exec_list *actual_parameters,
+ bool allow_builtins)
{
bool is_exact;
- return matching_signature(state, actual_parameters, &is_exact);
+ return matching_signature(state, actual_parameters, allow_builtins,
+ &is_exact);
}
ir_function_signature *
ir_function::matching_signature(_mesa_glsl_parse_state *state,
const exec_list *actual_parameters,
+ bool allow_builtins,
bool *is_exact)
{
ir_function_signature **inexact_matches = NULL;
@@ -308,7 +311,8 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
*/
foreach_in_list(ir_function_signature, sig, &this->signatures) {
/* Skip over any built-ins that aren't available in this shader. */
- if (sig->is_builtin() && !sig->is_builtin_available(state))
+ if (sig->is_builtin() && (!allow_builtins ||
+ !sig->is_builtin_available(state)))
continue;
switch (parameter_lists_match(state, & sig->parameters, actual_parameters)) {
diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp
index e3566e1d6..ae00e7934 100644
--- a/mesalib/src/glsl/ir_reader.cpp
+++ b/mesalib/src/glsl/ir_reader.cpp
@@ -677,7 +677,8 @@ ir_reader::read_call(s_expression *expr)
return NULL;
}
- ir_function_signature *callee = f->matching_signature(state, &parameters);
+ ir_function_signature *callee =
+ f->matching_signature(state, &parameters, true);
if (callee == NULL) {
ir_read_error(expr, "couldn't find matching signature for function "
"%s", name->value());
diff --git a/mesalib/src/glsl/ir_variable_refcount.cpp b/mesalib/src/glsl/ir_variable_refcount.cpp
index 923eb1a82..f67fe6784 100644
--- a/mesalib/src/glsl/ir_variable_refcount.cpp
+++ b/mesalib/src/glsl/ir_variable_refcount.cpp
@@ -33,7 +33,7 @@
#include "ir_visitor.h"
#include "ir_variable_refcount.h"
#include "glsl_types.h"
-#include "main/hash_table.h"
+#include "util/hash_table.h"
ir_variable_refcount_visitor::ir_variable_refcount_visitor()
{
diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp
index 2ce9609b5..f86aec689 100644
--- a/mesalib/src/glsl/link_functions.cpp
+++ b/mesalib/src/glsl/link_functions.cpp
@@ -307,7 +307,7 @@ find_matching_signature(const char *name, const exec_list *actual_parameters,
continue;
ir_function_signature *sig =
- f->matching_signature(NULL, actual_parameters);
+ f->matching_signature(NULL, actual_parameters, use_builtin);
if ((sig == NULL) ||
(!sig->is_defined && !sig->is_intrinsic))
diff --git a/mesalib/src/glsl/link_uniform_block_active_visitor.cpp b/mesalib/src/glsl/link_uniform_block_active_visitor.cpp
index 854309f9b..9da6a4bba 100644
--- a/mesalib/src/glsl/link_uniform_block_active_visitor.cpp
+++ b/mesalib/src/glsl/link_uniform_block_active_visitor.cpp
@@ -73,6 +73,45 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
}
ir_visitor_status
+link_uniform_block_active_visitor::visit(ir_variable *var)
+{
+ if (!var->is_in_uniform_block())
+ return visit_continue;
+
+ const glsl_type *const block_type = var->is_interface_instance()
+ ? var->type : var->get_interface_type();
+
+ /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec says:
+ *
+ * "All members of a named uniform block declared with a shared or
+ * std140 layout qualifier are considered active, even if they are not
+ * referenced in any shader in the program. The uniform block itself is
+ * also considered active, even if no member of the block is
+ * referenced."
+ */
+ if (block_type->interface_packing == GLSL_INTERFACE_PACKING_PACKED)
+ return visit_continue;
+
+ /* Process the block. Bail if there was an error.
+ */
+ link_uniform_block_active *const b =
+ process_block(this->mem_ctx, this->ht, var);
+ if (b == NULL) {
+ linker_error(this->prog,
+ "uniform block `%s' has mismatching definitions",
+ var->get_interface_type()->name);
+ this->success = false;
+ return visit_stop;
+ }
+
+ assert(b->num_array_elements == 0);
+ assert(b->array_elements == NULL);
+ assert(b->type != NULL);
+
+ return visit_continue;
+}
+
+ir_visitor_status
link_uniform_block_active_visitor::visit_enter(ir_dereference_array *ir)
{
ir_dereference_variable *const d = ir->array->as_dereference_variable();
diff --git a/mesalib/src/glsl/link_uniform_block_active_visitor.h b/mesalib/src/glsl/link_uniform_block_active_visitor.h
index 524cd6b91..e5ea50155 100644
--- a/mesalib/src/glsl/link_uniform_block_active_visitor.h
+++ b/mesalib/src/glsl/link_uniform_block_active_visitor.h
@@ -26,7 +26,7 @@
#define LINK_UNIFORM_BLOCK_ACTIVE_VISITOR_H
#include "ir.h"
-#include "main/hash_table.h"
+#include "util/hash_table.h"
struct link_uniform_block_active {
const glsl_type *type;
@@ -51,6 +51,7 @@ public:
virtual ir_visitor_status visit_enter(ir_dereference_array *);
virtual ir_visitor_status visit(ir_dereference_variable *);
+ virtual ir_visitor_status visit(ir_variable *);
bool success;
diff --git a/mesalib/src/glsl/link_uniform_blocks.cpp b/mesalib/src/glsl/link_uniform_blocks.cpp
index fef3626bf..536fcd458 100644
--- a/mesalib/src/glsl/link_uniform_blocks.cpp
+++ b/mesalib/src/glsl/link_uniform_blocks.cpp
@@ -26,7 +26,7 @@
#include "linker.h"
#include "ir_uniform.h"
#include "link_uniform_block_active_visitor.h"
-#include "main/hash_table.h"
+#include "util/hash_table.h"
#include "program.h"
namespace {
@@ -68,7 +68,8 @@ private:
}
virtual void visit_field(const glsl_type *type, const char *name,
- bool row_major, const glsl_type *record_type)
+ bool row_major, const glsl_type *record_type,
+ bool last_field)
{
assert(this->index < this->num_variables);
@@ -76,7 +77,7 @@ private:
v->Name = ralloc_strdup(mem_ctx, name);
v->Type = type;
- v->RowMajor = row_major;
+ v->RowMajor = type->without_array()->is_matrix() && row_major;
if (this->is_array_instance) {
v->IndexName = ralloc_strdup(mem_ctx, name);
@@ -103,7 +104,20 @@ private:
this->offset = glsl_align(this->offset, alignment);
v->Offset = this->offset;
+
+ /* If this is the last field of a structure, apply rule #9. The
+ * GL_ARB_uniform_buffer_object spec says:
+ *
+ * "The structure may have padding at the end; the base offset of
+ * the member following the sub-structure is rounded up to the next
+ * multiple of the base alignment of the structure."
+ *
+ * last_field won't be set if this is the last field of a UBO that is
+ * not a named instance.
+ */
this->offset += size;
+ if (last_field)
+ this->offset = glsl_align(this->offset, 16);
/* From the GL_ARB_uniform_buffer_object spec:
*
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index 6c731976b..3251097bc 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -59,13 +59,11 @@ values_for_type(const glsl_type *type)
void
program_resource_visitor::process(const glsl_type *type, const char *name)
{
- assert(type->is_record()
- || (type->is_array() && type->fields.array->is_record())
- || type->is_interface()
- || (type->is_array() && type->fields.array->is_interface()));
+ assert(type->without_array()->is_record()
+ || type->without_array()->is_interface());
char *name_copy = ralloc_strdup(NULL, name);
- recursion(type, &name_copy, strlen(name), false, NULL);
+ recursion(type, &name_copy, strlen(name), false, NULL, false);
ralloc_free(name_copy);
}
@@ -73,6 +71,8 @@ void
program_resource_visitor::process(ir_variable *var)
{
const glsl_type *t = var->type;
+ const bool row_major =
+ var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
/* false is always passed for the row_major parameter to the other
* processing functions because no information is available to do
@@ -110,7 +110,7 @@ program_resource_visitor::process(ir_variable *var)
* lowering is only applied to non-uniform interface blocks, so we
* can safely pass false for row_major.
*/
- recursion(var->type, &name, new_length, false, NULL);
+ recursion(var->type, &name, new_length, row_major, NULL, false);
}
ralloc_free(name);
} else if (var->data.from_named_ifc_block_nonarray) {
@@ -134,29 +134,30 @@ program_resource_visitor::process(ir_variable *var)
* is only applied to non-uniform interface blocks, so we can safely
* pass false for row_major.
*/
- recursion(var->type, &name, strlen(name), false, NULL);
+ recursion(var->type, &name, strlen(name), row_major, NULL, false);
ralloc_free(name);
- } else if (t->is_record() || (t->is_array() && t->fields.array->is_record())) {
+ } else if (t->without_array()->is_record()) {
char *name = ralloc_strdup(NULL, var->name);
- recursion(var->type, &name, strlen(name), false, NULL);
+ recursion(var->type, &name, strlen(name), row_major, NULL, false);
ralloc_free(name);
} else if (t->is_interface()) {
char *name = ralloc_strdup(NULL, var->type->name);
- recursion(var->type, &name, strlen(name), false, NULL);
+ recursion(var->type, &name, strlen(name), row_major, NULL, false);
ralloc_free(name);
} else if (t->is_array() && t->fields.array->is_interface()) {
char *name = ralloc_strdup(NULL, var->type->fields.array->name);
- recursion(var->type, &name, strlen(name), false, NULL);
+ recursion(var->type, &name, strlen(name), row_major, NULL, false);
ralloc_free(name);
} else {
- this->visit_field(t, var->name, false, NULL);
+ this->visit_field(t, var->name, row_major, NULL, false);
}
}
void
program_resource_visitor::recursion(const glsl_type *t, char **name,
size_t name_length, bool row_major,
- const glsl_type *record_type)
+ const glsl_type *record_type,
+ bool last_field)
{
/* Records need to have each field processed individually.
*
@@ -182,8 +183,25 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field);
}
+ /* The layout of structures at the top level of the block is set
+ * during parsing. For matrices contained in multiple levels of
+ * structures in the block, the inner structures have no layout.
+ * These cases must potentially inherit the layout from the outer
+ * levels.
+ */
+ bool field_row_major = row_major;
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(t->fields.structure[i].matrix_layout);
+ if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
+ field_row_major = true;
+ } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
+ field_row_major = false;
+ }
+
recursion(t->fields.structure[i].type, name, new_length,
- t->fields.structure[i].row_major, record_type);
+ field_row_major,
+ record_type,
+ (i + 1) == t->length);
/* Only the first leaf-field of the record gets called with the
* record type pointer.
@@ -202,7 +220,8 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
ralloc_asprintf_rewrite_tail(name, &new_length, "[%u]", i);
recursion(t->fields.array, name, new_length, row_major,
- record_type);
+ record_type,
+ (i + 1) == t->length);
/* Only the first leaf-field of the record gets called with the
* record type pointer.
@@ -210,14 +229,15 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
record_type = NULL;
}
} else {
- this->visit_field(t, *name, row_major, record_type);
+ this->visit_field(t, *name, row_major, record_type, last_field);
}
}
void
program_resource_visitor::visit_field(const glsl_type *type, const char *name,
bool row_major,
- const glsl_type *)
+ const glsl_type *,
+ bool /* last_field */)
{
visit_field(type, name, row_major);
}
@@ -299,10 +319,8 @@ private:
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major)
{
- assert(!type->is_record());
- assert(!(type->is_array() && type->fields.array->is_record()));
- assert(!type->is_interface());
- assert(!(type->is_array() && type->fields.array->is_interface()));
+ assert(!type->without_array()->is_record());
+ assert(!type->without_array()->is_interface());
(void) row_major;
@@ -427,7 +445,6 @@ public:
*/
if (var->is_interface_instance()) {
ubo_byte_offset = 0;
- ubo_row_major = false;
} else {
const struct gl_uniform_block *const block =
&prog->UniformBlocks[ubo_block_index];
@@ -437,7 +454,6 @@ public:
const struct gl_uniform_buffer_variable *const ubo_var =
&block->Uniforms[var->data.location];
- ubo_row_major = ubo_var->RowMajor;
ubo_byte_offset = ubo_var->Offset;
}
@@ -452,7 +468,6 @@ public:
int ubo_block_index;
int ubo_byte_offset;
- bool ubo_row_major;
gl_shader_stage shader_type;
private:
@@ -512,14 +527,11 @@ private:
}
virtual void visit_field(const glsl_type *type, const char *name,
- bool row_major, const glsl_type *record_type)
+ bool row_major, const glsl_type *record_type,
+ bool last_field)
{
- assert(!type->is_record());
- assert(!(type->is_array() && type->fields.array->is_record()));
- assert(!type->is_interface());
- assert(!(type->is_array() && type->fields.array->is_interface()));
-
- (void) row_major;
+ assert(!type->without_array()->is_record());
+ assert(!type->without_array()->is_interface());
unsigned id;
bool found = this->map->get(id, name);
@@ -577,23 +589,25 @@ private:
this->uniforms[id].block_index = this->ubo_block_index;
const unsigned alignment = record_type
- ? record_type->std140_base_alignment(ubo_row_major)
- : type->std140_base_alignment(ubo_row_major);
+ ? record_type->std140_base_alignment(row_major)
+ : type->std140_base_alignment(row_major);
this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment);
this->uniforms[id].offset = this->ubo_byte_offset;
- this->ubo_byte_offset += type->std140_size(ubo_row_major);
+ this->ubo_byte_offset += type->std140_size(row_major);
+
+ if (last_field)
+ this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, 16);
if (type->is_array()) {
this->uniforms[id].array_stride =
- glsl_align(type->fields.array->std140_size(ubo_row_major), 16);
+ glsl_align(type->fields.array->std140_size(row_major), 16);
} else {
this->uniforms[id].array_stride = 0;
}
- if (type->is_matrix() ||
- (type->is_array() && type->fields.array->is_matrix())) {
+ if (type->without_array()->is_matrix()) {
this->uniforms[id].matrix_stride = 16;
- this->uniforms[id].row_major = ubo_row_major;
+ this->uniforms[id].row_major = row_major;
} else {
this->uniforms[id].matrix_stride = 0;
this->uniforms[id].row_major = false;
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index a3fc2ae34..1438a4b16 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -1068,10 +1068,8 @@ private:
virtual void visit_field(const glsl_type *type, const char *name,
bool row_major)
{
- assert(!type->is_record());
- assert(!(type->is_array() && type->fields.array->is_record()));
- assert(!type->is_interface());
- assert(!(type->is_array() && type->fields.array->is_interface()));
+ assert(!type->without_array()->is_record());
+ assert(!type->without_array()->is_interface());
(void) row_major;
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index d588bc63e..0096fb023 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -1129,7 +1129,8 @@ get_main_function_signature(gl_shader *sh)
* We don't have to check for multiple definitions of main (in multiple
* shaders) because that would have already been caught above.
*/
- ir_function_signature *sig = f->matching_signature(NULL, &void_parameters);
+ ir_function_signature *sig =
+ f->matching_signature(NULL, &void_parameters, false);
if ((sig != NULL) && sig->is_defined) {
return sig;
}
diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h
index 130915db4..8851da6c8 100644
--- a/mesalib/src/glsl/linker.h
+++ b/mesalib/src/glsl/linker.h
@@ -138,11 +138,15 @@ protected:
* \param name Fully qualified name of the field.
* \param row_major For a matrix type, is it stored row-major.
* \param record_type Type of the record containing the field.
+ * \param last_field Set if \c name is the last field of the structure
+ * containing it. This will always be false for items
+ * not contained in a structure or interface block.
*
* The default implementation just calls the other \c visit_field method.
*/
virtual void visit_field(const glsl_type *type, const char *name,
- bool row_major, const glsl_type *record_type);
+ bool row_major, const glsl_type *record_type,
+ bool last_field);
/**
* Method invoked for each leaf of the variable
@@ -168,9 +172,13 @@ private:
/**
* \param name_length Length of the current name \b not including the
* terminating \c NUL character.
+ * \param last_field Set if \c name is the last field of the structure
+ * containing it. This will always be false for items
+ * not contained in a structure or interface block.
*/
void recursion(const glsl_type *t, char **name, size_t name_length,
- bool row_major, const glsl_type *record_type);
+ bool row_major, const glsl_type *record_type,
+ bool last_field);
};
void
diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h
index 3ee6cdaa9..b6c32bccc 100644
--- a/mesalib/src/glsl/list.h
+++ b/mesalib/src/glsl/list.h
@@ -69,7 +69,7 @@
#endif
#include <assert.h>
-#include "ralloc.h"
+#include "util/ralloc.h"
struct exec_node {
struct exec_node *next;
diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp
index 36b49eb46..1c1d34fef 100644
--- a/mesalib/src/glsl/loop_controls.cpp
+++ b/mesalib/src/glsl/loop_controls.cpp
@@ -123,9 +123,20 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
bool valid_loop = false;
for (unsigned i = 0; i < Elements(bias); i++) {
- iter = (increment->type->is_integer())
- ? new(mem_ctx) ir_constant(iter_value + bias[i])
- : new(mem_ctx) ir_constant(float(iter_value + bias[i]));
+ /* Increment may be of type int, uint or float. */
+ switch (increment->type->base_type) {
+ case GLSL_TYPE_INT:
+ iter = new(mem_ctx) ir_constant(iter_value + bias[i]);
+ break;
+ case GLSL_TYPE_UINT:
+ iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i]));
+ break;
+ case GLSL_TYPE_FLOAT:
+ iter = new(mem_ctx) ir_constant(float(iter_value + bias[i]));
+ break;
+ default:
+ unreachable(!"Unsupported type for loop iterator.");
+ }
ir_expression *const mul =
new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index c72b80a32..780148315 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/src/glsl/lower_packed_varyings.cpp
@@ -655,7 +655,7 @@ lower_packed_varyings(void *mem_ctx, unsigned locations_used,
ir_function *main_func = shader->symbols->get_function("main");
exec_list void_parameters;
ir_function_signature *main_func_sig
- = main_func->matching_signature(NULL, &void_parameters);
+ = main_func->matching_signature(NULL, &void_parameters, false);
exec_list new_instructions;
lower_packed_varyings_visitor visitor(mem_ctx, locations_used, mode,
gs_input_vertices, &new_instructions);
diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp
index 67b752d3d..3cdfc04ac 100644
--- a/mesalib/src/glsl/lower_ubo_reference.cpp
+++ b/mesalib/src/glsl/lower_ubo_reference.cpp
@@ -40,6 +40,96 @@
using namespace ir_builder;
+/**
+ * Determine if a thing being dereferenced is row-major
+ *
+ * There is some trickery here.
+ *
+ * If the thing being dereferenced is a member of uniform block \b without an
+ * instance name, then the name of the \c ir_variable is the field name of an
+ * interface type. If this field is row-major, then the thing referenced is
+ * row-major.
+ *
+ * If the thing being dereferenced is a member of uniform block \b with an
+ * instance name, then the last dereference in the tree will be an
+ * \c ir_dereference_record. If that record field is row-major, then the
+ * thing referenced is row-major.
+ */
+static bool
+is_dereferenced_thing_row_major(const ir_dereference *deref)
+{
+ bool matrix = false;
+ const ir_rvalue *ir = deref;
+
+ while (true) {
+ matrix = matrix || ir->type->without_array()->is_matrix();
+
+ switch (ir->ir_type) {
+ case ir_type_dereference_array: {
+ const ir_dereference_array *const array_deref =
+ (const ir_dereference_array *) ir;
+
+ ir = array_deref->array;
+ break;
+ }
+
+ case ir_type_dereference_record: {
+ const ir_dereference_record *const record_deref =
+ (const ir_dereference_record *) ir;
+
+ ir = record_deref->record;
+
+ const int idx = ir->type->field_index(record_deref->field);
+ assert(idx >= 0);
+
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(ir->type->fields.structure[idx].matrix_layout);
+
+ switch (matrix_layout) {
+ case GLSL_MATRIX_LAYOUT_INHERITED:
+ break;
+ case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
+ return false;
+ case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
+ return matrix || deref->type->without_array()->is_record();
+ }
+
+ break;
+ }
+
+ case ir_type_dereference_variable: {
+ const ir_dereference_variable *const var_deref =
+ (const ir_dereference_variable *) ir;
+
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(var_deref->var->data.matrix_layout);
+
+ switch (matrix_layout) {
+ case GLSL_MATRIX_LAYOUT_INHERITED:
+ assert(!matrix);
+ return false;
+ case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
+ return false;
+ case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
+ return matrix || deref->type->is_record();
+ }
+
+ unreachable("invalid matrix layout");
+ break;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+ /* The tree must have ended with a dereference that wasn't an
+ * ir_dereference_variable. That is invalid, and it should be impossible.
+ */
+ unreachable("invalid dereference tree");
+ return false;
+}
+
namespace {
class lower_ubo_reference_visitor : public ir_rvalue_enter_visitor {
public:
@@ -50,7 +140,7 @@ public:
void handle_rvalue(ir_rvalue **rvalue);
void emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset,
- unsigned int deref_offset);
+ unsigned int deref_offset, bool row_major);
ir_expression *ubo_load(const struct glsl_type *type,
ir_rvalue *offset);
@@ -174,7 +264,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
ir_rvalue *offset = new(mem_ctx) ir_constant(0u);
unsigned const_offset = 0;
- bool row_major = ubo_var->RowMajor;
+ bool row_major = is_dereferenced_thing_row_major(deref);
/* Calculate the offset to the start of the region of the UBO
* dereferenced by *rvalue. This may be a variable offset if an
@@ -219,7 +309,8 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
if (array_index->type->base_type == GLSL_TYPE_INT)
array_index = i2u(array_index);
- ir_constant *const_index = array_index->as_constant();
+ ir_constant *const_index =
+ array_index->constant_expression_value(NULL);
if (const_index) {
const_offset += array_stride * const_index->value.u[0];
} else {
@@ -236,20 +327,27 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
const glsl_type *struct_type = deref_record->record->type;
unsigned intra_struct_offset = 0;
- unsigned max_field_align = 16;
for (unsigned int i = 0; i < struct_type->length; i++) {
const glsl_type *type = struct_type->fields.structure[i].type;
- unsigned field_align = type->std140_base_alignment(row_major);
- max_field_align = MAX2(field_align, max_field_align);
+
+ ir_dereference_record *field_deref =
+ new(mem_ctx) ir_dereference_record(deref_record->record,
+ struct_type->fields.structure[i].name);
+ const bool field_row_major =
+ is_dereferenced_thing_row_major(field_deref);
+
+ ralloc_free(field_deref);
+
+ unsigned field_align = type->std140_base_alignment(field_row_major);
+
intra_struct_offset = glsl_align(intra_struct_offset, field_align);
if (strcmp(struct_type->fields.structure[i].name,
deref_record->field) == 0)
break;
- intra_struct_offset += type->std140_size(row_major);
+ intra_struct_offset += type->std140_size(field_row_major);
}
- const_offset = glsl_align(const_offset, max_field_align);
const_offset += intra_struct_offset;
deref = deref_record->record->as_dereference();
@@ -278,7 +376,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
base_ir->insert_before(assign(load_offset, offset));
deref = new(mem_ctx) ir_dereference_variable(load_var);
- emit_ubo_loads(deref, load_offset, const_offset);
+ emit_ubo_loads(deref, load_offset, const_offset, row_major);
*rvalue = deref;
progress = true;
@@ -308,7 +406,8 @@ lower_ubo_reference_visitor::ubo_load(const glsl_type *type,
void
lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
ir_variable *base_offset,
- unsigned int deref_offset)
+ unsigned int deref_offset,
+ bool row_major)
{
if (deref->type->is_record()) {
unsigned int field_offset = 0;
@@ -322,18 +421,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
field_offset =
glsl_align(field_offset,
- field->type->std140_base_alignment(ubo_var->RowMajor));
+ field->type->std140_base_alignment(row_major));
- emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset);
+ emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset,
+ row_major);
- field_offset += field->type->std140_size(ubo_var->RowMajor);
+ field_offset += field->type->std140_size(row_major);
}
return;
}
if (deref->type->is_array()) {
unsigned array_stride =
- glsl_align(deref->type->fields.array->std140_size(ubo_var->RowMajor),
+ glsl_align(deref->type->fields.array->std140_size(row_major),
16);
for (unsigned i = 0; i < deref->type->length; i++) {
@@ -342,7 +442,8 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
element);
emit_ubo_loads(element_deref, base_offset,
- deref_offset + i * array_stride);
+ deref_offset + i * array_stride,
+ row_major);
}
return;
}
@@ -354,10 +455,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
col);
- /* std140 always rounds the stride of arrays (and matrices)
- * to a vec4, so matrices are always 16 between columns/rows.
- */
- emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16);
+ if (row_major) {
+ /* For a row-major matrix, the next column starts at the next
+ * element.
+ */
+ emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4,
+ row_major);
+ } else {
+ /* std140 always rounds the stride of arrays (and matrices) to a
+ * vec4, so matrices are always 16 between columns/rows.
+ */
+ emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16,
+ row_major);
+ }
}
return;
}
@@ -365,7 +475,7 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
assert(deref->type->is_scalar() ||
deref->type->is_vector());
- if (!ubo_var->RowMajor) {
+ if (!row_major) {
ir_rvalue *offset = add(base_offset,
new(mem_ctx) ir_constant(deref_offset));
base_ir->insert_before(assign(deref->clone(mem_ctx, NULL),
diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp
index da90bfb40..f45bf5dfd 100644
--- a/mesalib/src/glsl/opt_dead_code.cpp
+++ b/mesalib/src/glsl/opt_dead_code.cpp
@@ -31,7 +31,7 @@
#include "ir_visitor.h"
#include "ir_variable_refcount.h"
#include "glsl_types.h"
-#include "main/hash_table.h"
+#include "util/hash_table.h"
static bool debug = false;
@@ -99,10 +99,31 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
* stage. Also, once uniform locations have been assigned, the
* declaration cannot be deleted.
*/
- if (entry->var->data.mode == ir_var_uniform &&
- (uniform_locations_assigned ||
- entry->var->constant_value))
- continue;
+ if (entry->var->data.mode == ir_var_uniform) {
+ if (uniform_locations_assigned || entry->var->constant_value)
+ continue;
+
+ /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec
+ * says:
+ *
+ * "All members of a named uniform block declared with a
+ * shared or std140 layout qualifier are considered active,
+ * even if they are not referenced in any shader in the
+ * program. The uniform block itself is also considered
+ * active, even if no member of the block is referenced."
+ *
+ * If the variable is in a uniform block with one of those
+ * layouts, do not eliminate it.
+ */
+ if (entry->var->is_in_uniform_block()) {
+ const glsl_type *const block_type =
+ entry->var->is_interface_instance()
+ ? entry->var->type : entry->var->get_interface_type();
+
+ if (block_type->interface_packing != GLSL_INTERFACE_PACKING_PACKED)
+ continue;
+ }
+ }
entry->var->remove();
progress = true;
diff --git a/mesalib/src/glsl/ralloc.c b/mesalib/src/glsl/ralloc.c
deleted file mode 100644
index 36bc61fd0..000000000
--- a/mesalib/src/glsl/ralloc.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-/* Android defines SIZE_MAX in limits.h, instead of the standard stdint.h */
-#ifdef ANDROID
-#include <limits.h>
-#endif
-
-/* Some versions of MinGW are missing _vscprintf's declaration, although they
- * still provide the symbol in the import library. */
-#ifdef __MINGW32__
-_CRTIMP int _vscprintf(const char *format, va_list argptr);
-#endif
-
-#include "ralloc.h"
-
-#ifndef va_copy
-#ifdef __va_copy
-#define va_copy(dest, src) __va_copy((dest), (src))
-#else
-#define va_copy(dest, src) (dest) = (src)
-#endif
-#endif
-
-#define CANARY 0x5A1106
-
-struct ralloc_header
-{
-#ifdef DEBUG
- /* A canary value used to determine whether a pointer is ralloc'd. */
- unsigned canary;
-#endif
-
- struct ralloc_header *parent;
-
- /* The first child (head of a linked list) */
- struct ralloc_header *child;
-
- /* Linked list of siblings */
- struct ralloc_header *prev;
- struct ralloc_header *next;
-
- void (*destructor)(void *);
-};
-
-typedef struct ralloc_header ralloc_header;
-
-static void unlink_block(ralloc_header *info);
-static void unsafe_free(ralloc_header *info);
-
-static ralloc_header *
-get_header(const void *ptr)
-{
- ralloc_header *info = (ralloc_header *) (((char *) ptr) -
- sizeof(ralloc_header));
-#ifdef DEBUG
- assert(info->canary == CANARY);
-#endif
- return info;
-}
-
-#define PTR_FROM_HEADER(info) (((char *) info) + sizeof(ralloc_header))
-
-static void
-add_child(ralloc_header *parent, ralloc_header *info)
-{
- if (parent != NULL) {
- info->parent = parent;
- info->next = parent->child;
- parent->child = info;
-
- if (info->next != NULL)
- info->next->prev = info;
- }
-}
-
-void *
-ralloc_context(const void *ctx)
-{
- return ralloc_size(ctx, 0);
-}
-
-void *
-ralloc_size(const void *ctx, size_t size)
-{
- void *block = calloc(1, size + sizeof(ralloc_header));
- ralloc_header *info;
- ralloc_header *parent;
-
- if (unlikely(block == NULL))
- return NULL;
- info = (ralloc_header *) block;
- parent = ctx != NULL ? get_header(ctx) : NULL;
-
- add_child(parent, info);
-
-#ifdef DEBUG
- info->canary = CANARY;
-#endif
-
- return PTR_FROM_HEADER(info);
-}
-
-void *
-rzalloc_size(const void *ctx, size_t size)
-{
- void *ptr = ralloc_size(ctx, size);
- if (likely(ptr != NULL))
- memset(ptr, 0, size);
- return ptr;
-}
-
-/* helper function - assumes ptr != NULL */
-static void *
-resize(void *ptr, size_t size)
-{
- ralloc_header *child, *old, *info;
-
- old = get_header(ptr);
- info = realloc(old, size + sizeof(ralloc_header));
-
- if (info == NULL)
- return NULL;
-
- /* Update parent and sibling's links to the reallocated node. */
- if (info != old && info->parent != NULL) {
- if (info->parent->child == old)
- info->parent->child = info;
-
- if (info->prev != NULL)
- info->prev->next = info;
-
- if (info->next != NULL)
- info->next->prev = info;
- }
-
- /* Update child->parent links for all children */
- for (child = info->child; child != NULL; child = child->next)
- child->parent = info;
-
- return PTR_FROM_HEADER(info);
-}
-
-void *
-reralloc_size(const void *ctx, void *ptr, size_t size)
-{
- if (unlikely(ptr == NULL))
- return ralloc_size(ctx, size);
-
- assert(ralloc_parent(ptr) == ctx);
- return resize(ptr, size);
-}
-
-void *
-ralloc_array_size(const void *ctx, size_t size, unsigned count)
-{
- if (count > SIZE_MAX/size)
- return NULL;
-
- return ralloc_size(ctx, size * count);
-}
-
-void *
-rzalloc_array_size(const void *ctx, size_t size, unsigned count)
-{
- if (count > SIZE_MAX/size)
- return NULL;
-
- return rzalloc_size(ctx, size * count);
-}
-
-void *
-reralloc_array_size(const void *ctx, void *ptr, size_t size, unsigned count)
-{
- if (count > SIZE_MAX/size)
- return NULL;
-
- return reralloc_size(ctx, ptr, size * count);
-}
-
-void
-ralloc_free(void *ptr)
-{
- ralloc_header *info;
-
- if (ptr == NULL)
- return;
-
- info = get_header(ptr);
- unlink_block(info);
- unsafe_free(info);
-}
-
-static void
-unlink_block(ralloc_header *info)
-{
- /* Unlink from parent & siblings */
- if (info->parent != NULL) {
- if (info->parent->child == info)
- info->parent->child = info->next;
-
- if (info->prev != NULL)
- info->prev->next = info->next;
-
- if (info->next != NULL)
- info->next->prev = info->prev;
- }
- info->parent = NULL;
- info->prev = NULL;
- info->next = NULL;
-}
-
-static void
-unsafe_free(ralloc_header *info)
-{
- /* Recursively free any children...don't waste time unlinking them. */
- ralloc_header *temp;
- while (info->child != NULL) {
- temp = info->child;
- info->child = temp->next;
- unsafe_free(temp);
- }
-
- /* Free the block itself. Call the destructor first, if any. */
- if (info->destructor != NULL)
- info->destructor(PTR_FROM_HEADER(info));
-
- free(info);
-}
-
-void
-ralloc_steal(const void *new_ctx, void *ptr)
-{
- ralloc_header *info, *parent;
-
- if (unlikely(ptr == NULL))
- return;
-
- info = get_header(ptr);
- parent = get_header(new_ctx);
-
- unlink_block(info);
-
- add_child(parent, info);
-}
-
-void *
-ralloc_parent(const void *ptr)
-{
- ralloc_header *info;
-
- if (unlikely(ptr == NULL))
- return NULL;
-
- info = get_header(ptr);
- return info->parent ? PTR_FROM_HEADER(info->parent) : NULL;
-}
-
-static void *autofree_context = NULL;
-
-static void
-autofree(void)
-{
- ralloc_free(autofree_context);
-}
-
-void *
-ralloc_autofree_context(void)
-{
- if (unlikely(autofree_context == NULL)) {
- autofree_context = ralloc_context(NULL);
- atexit(autofree);
- }
- return autofree_context;
-}
-
-void
-ralloc_set_destructor(const void *ptr, void(*destructor)(void *))
-{
- ralloc_header *info = get_header(ptr);
- info->destructor = destructor;
-}
-
-char *
-ralloc_strdup(const void *ctx, const char *str)
-{
- size_t n;
- char *ptr;
-
- if (unlikely(str == NULL))
- return NULL;
-
- n = strlen(str);
- ptr = ralloc_array(ctx, char, n + 1);
- memcpy(ptr, str, n);
- ptr[n] = '\0';
- return ptr;
-}
-
-char *
-ralloc_strndup(const void *ctx, const char *str, size_t max)
-{
- size_t n;
- char *ptr;
-
- if (unlikely(str == NULL))
- return NULL;
-
- n = strlen(str);
- if (n > max)
- n = max;
-
- ptr = ralloc_array(ctx, char, n + 1);
- memcpy(ptr, str, n);
- ptr[n] = '\0';
- return ptr;
-}
-
-/* helper routine for strcat/strncat - n is the exact amount to copy */
-static bool
-cat(char **dest, const char *str, size_t n)
-{
- char *both;
- size_t existing_length;
- assert(dest != NULL && *dest != NULL);
-
- existing_length = strlen(*dest);
- both = resize(*dest, existing_length + n + 1);
- if (unlikely(both == NULL))
- return false;
-
- memcpy(both + existing_length, str, n);
- both[existing_length + n] = '\0';
-
- *dest = both;
- return true;
-}
-
-
-bool
-ralloc_strcat(char **dest, const char *str)
-{
- return cat(dest, str, strlen(str));
-}
-
-bool
-ralloc_strncat(char **dest, const char *str, size_t n)
-{
- /* Clamp n to the string length */
- size_t str_length = strlen(str);
- if (str_length < n)
- n = str_length;
-
- return cat(dest, str, n);
-}
-
-char *
-ralloc_asprintf(const void *ctx, const char *fmt, ...)
-{
- char *ptr;
- va_list args;
- va_start(args, fmt);
- ptr = ralloc_vasprintf(ctx, fmt, args);
- va_end(args);
- return ptr;
-}
-
-/* Return the length of the string that would be generated by a printf-style
- * format and argument list, not including the \0 byte.
- */
-static size_t
-printf_length(const char *fmt, va_list untouched_args)
-{
- int size;
- char junk;
-
- /* Make a copy of the va_list so the original caller can still use it */
- va_list args;
- va_copy(args, untouched_args);
-
-#ifdef _WIN32
- /* We need to use _vcsprintf to calculate the size as vsnprintf returns -1
- * if the number of characters to write is greater than count.
- */
- size = _vscprintf(fmt, args);
- (void)junk;
-#else
- size = vsnprintf(&junk, 1, fmt, args);
-#endif
- assert(size >= 0);
-
- va_end(args);
-
- return size;
-}
-
-char *
-ralloc_vasprintf(const void *ctx, const char *fmt, va_list args)
-{
- size_t size = printf_length(fmt, args) + 1;
-
- char *ptr = ralloc_size(ctx, size);
- if (ptr != NULL)
- vsnprintf(ptr, size, fmt, args);
-
- return ptr;
-}
-
-bool
-ralloc_asprintf_append(char **str, const char *fmt, ...)
-{
- bool success;
- va_list args;
- va_start(args, fmt);
- success = ralloc_vasprintf_append(str, fmt, args);
- va_end(args);
- return success;
-}
-
-bool
-ralloc_vasprintf_append(char **str, const char *fmt, va_list args)
-{
- size_t existing_length;
- assert(str != NULL);
- existing_length = *str ? strlen(*str) : 0;
- return ralloc_vasprintf_rewrite_tail(str, &existing_length, fmt, args);
-}
-
-bool
-ralloc_asprintf_rewrite_tail(char **str, size_t *start, const char *fmt, ...)
-{
- bool success;
- va_list args;
- va_start(args, fmt);
- success = ralloc_vasprintf_rewrite_tail(str, start, fmt, args);
- va_end(args);
- return success;
-}
-
-bool
-ralloc_vasprintf_rewrite_tail(char **str, size_t *start, const char *fmt,
- va_list args)
-{
- size_t new_length;
- char *ptr;
-
- assert(str != NULL);
-
- if (unlikely(*str == NULL)) {
- // Assuming a NULL context is probably bad, but it's expected behavior.
- *str = ralloc_vasprintf(NULL, fmt, args);
- return true;
- }
-
- new_length = printf_length(fmt, args);
-
- ptr = resize(*str, *start + new_length + 1);
- if (unlikely(ptr == NULL))
- return false;
-
- vsnprintf(ptr + *start, new_length + 1, fmt, args);
- *str = ptr;
- *start += new_length;
- return true;
-}
diff --git a/mesalib/src/glsl/ralloc.h b/mesalib/src/glsl/ralloc.h
deleted file mode 100644
index 1fe53573f..000000000
--- a/mesalib/src/glsl/ralloc.h
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file ralloc.h
- *
- * ralloc: a recursive memory allocator
- *
- * The ralloc memory allocator creates a hierarchy of allocated
- * objects. Every allocation is in reference to some parent, and
- * every allocated object can in turn be used as the parent of a
- * subsequent allocation. This allows for extremely convenient
- * discarding of an entire tree/sub-tree of allocations by calling
- * ralloc_free on any particular object to free it and all of its
- * children.
- *
- * The conceptual working of ralloc was directly inspired by Andrew
- * Tridgell's talloc, but ralloc is an independent implementation
- * released under the MIT license and tuned for Mesa.
- *
- * talloc is more sophisticated than ralloc in that it includes reference
- * counting and useful debugging features. However, it is released under
- * a non-permissive open source license.
- */
-
-#ifndef RALLOC_H
-#define RALLOC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stddef.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include "main/compiler.h"
-
-/**
- * \def ralloc(ctx, type)
- * Allocate a new object chained off of the given context.
- *
- * This is equivalent to:
- * \code
- * ((type *) ralloc_size(ctx, sizeof(type))
- * \endcode
- */
-#define ralloc(ctx, type) ((type *) ralloc_size(ctx, sizeof(type)))
-
-/**
- * \def rzalloc(ctx, type)
- * Allocate a new object out of the given context and initialize it to zero.
- *
- * This is equivalent to:
- * \code
- * ((type *) rzalloc_size(ctx, sizeof(type))
- * \endcode
- */
-#define rzalloc(ctx, type) ((type *) rzalloc_size(ctx, sizeof(type)))
-
-/**
- * Allocate a new ralloc context.
- *
- * While any ralloc'd pointer can be used as a context, sometimes it is useful
- * to simply allocate a context with no associated memory.
- *
- * It is equivalent to:
- * \code
- * ((type *) ralloc_size(ctx, 0)
- * \endcode
- */
-void *ralloc_context(const void *ctx);
-
-/**
- * Allocate memory chained off of the given context.
- *
- * This is the core allocation routine which is used by all others. It
- * simply allocates storage for \p size bytes and returns the pointer,
- * similar to \c malloc.
- */
-void *ralloc_size(const void *ctx, size_t size);
-
-/**
- * Allocate zero-initialized memory chained off of the given context.
- *
- * This is similar to \c calloc with a size of 1.
- */
-void *rzalloc_size(const void *ctx, size_t size);
-
-/**
- * Resize a piece of ralloc-managed memory, preserving data.
- *
- * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the
- * memory. Instead, it resizes it to a 0-byte ralloc context, just like
- * calling ralloc_size(ctx, 0). This is different from talloc.
- *
- * \param ctx The context to use for new allocation. If \p ptr != NULL,
- * it must be the same as ralloc_parent(\p ptr).
- * \param ptr Pointer to the memory to be resized. May be NULL.
- * \param size The amount of memory to allocate, in bytes.
- */
-void *reralloc_size(const void *ctx, void *ptr, size_t size);
-
-/// \defgroup array Array Allocators @{
-
-/**
- * \def ralloc_array(ctx, type, count)
- * Allocate an array of objects chained off the given context.
- *
- * Similar to \c calloc, but does not initialize the memory to zero.
- *
- * More than a convenience function, this also checks for integer overflow when
- * multiplying \c sizeof(type) and \p count. This is necessary for security.
- *
- * This is equivalent to:
- * \code
- * ((type *) ralloc_array_size(ctx, sizeof(type), count)
- * \endcode
- */
-#define ralloc_array(ctx, type, count) \
- ((type *) ralloc_array_size(ctx, sizeof(type), count))
-
-/**
- * \def rzalloc_array(ctx, type, count)
- * Allocate a zero-initialized array chained off the given context.
- *
- * Similar to \c calloc.
- *
- * More than a convenience function, this also checks for integer overflow when
- * multiplying \c sizeof(type) and \p count. This is necessary for security.
- *
- * This is equivalent to:
- * \code
- * ((type *) rzalloc_array_size(ctx, sizeof(type), count)
- * \endcode
- */
-#define rzalloc_array(ctx, type, count) \
- ((type *) rzalloc_array_size(ctx, sizeof(type), count))
-
-/**
- * \def reralloc(ctx, ptr, type, count)
- * Resize a ralloc-managed array, preserving data.
- *
- * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the
- * memory. Instead, it resizes it to a 0-byte ralloc context, just like
- * calling ralloc_size(ctx, 0). This is different from talloc.
- *
- * More than a convenience function, this also checks for integer overflow when
- * multiplying \c sizeof(type) and \p count. This is necessary for security.
- *
- * \param ctx The context to use for new allocation. If \p ptr != NULL,
- * it must be the same as ralloc_parent(\p ptr).
- * \param ptr Pointer to the array to be resized. May be NULL.
- * \param type The element type.
- * \param count The number of elements to allocate.
- */
-#define reralloc(ctx, ptr, type, count) \
- ((type *) reralloc_array_size(ctx, ptr, sizeof(type), count))
-
-/**
- * Allocate memory for an array chained off the given context.
- *
- * Similar to \c calloc, but does not initialize the memory to zero.
- *
- * More than a convenience function, this also checks for integer overflow when
- * multiplying \p size and \p count. This is necessary for security.
- */
-void *ralloc_array_size(const void *ctx, size_t size, unsigned count);
-
-/**
- * Allocate a zero-initialized array chained off the given context.
- *
- * Similar to \c calloc.
- *
- * More than a convenience function, this also checks for integer overflow when
- * multiplying \p size and \p count. This is necessary for security.
- */
-void *rzalloc_array_size(const void *ctx, size_t size, unsigned count);
-
-/**
- * Resize a ralloc-managed array, preserving data.
- *
- * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the
- * memory. Instead, it resizes it to a 0-byte ralloc context, just like
- * calling ralloc_size(ctx, 0). This is different from talloc.
- *
- * More than a convenience function, this also checks for integer overflow when
- * multiplying \c sizeof(type) and \p count. This is necessary for security.
- *
- * \param ctx The context to use for new allocation. If \p ptr != NULL,
- * it must be the same as ralloc_parent(\p ptr).
- * \param ptr Pointer to the array to be resized. May be NULL.
- * \param size The size of an individual element.
- * \param count The number of elements to allocate.
- *
- * \return True unless allocation failed.
- */
-void *reralloc_array_size(const void *ctx, void *ptr, size_t size,
- unsigned count);
-/// @}
-
-/**
- * Free a piece of ralloc-managed memory.
- *
- * This will also free the memory of any children allocated this context.
- */
-void ralloc_free(void *ptr);
-
-/**
- * "Steal" memory from one context, changing it to another.
- *
- * This changes \p ptr's context to \p new_ctx. This is quite useful if
- * memory is allocated out of a temporary context.
- */
-void ralloc_steal(const void *new_ctx, void *ptr);
-
-/**
- * Return the given pointer's ralloc context.
- */
-void *ralloc_parent(const void *ptr);
-
-/**
- * Return a context whose memory will be automatically freed at program exit.
- *
- * The first call to this function creates a context and registers a handler
- * to free it using \c atexit. This may cause trouble if used in a library
- * loaded with \c dlopen.
- */
-void *ralloc_autofree_context(void);
-
-/**
- * Set a callback to occur just before an object is freed.
- */
-void ralloc_set_destructor(const void *ptr, void(*destructor)(void *));
-
-/// \defgroup array String Functions @{
-/**
- * Duplicate a string, allocating the memory from the given context.
- */
-char *ralloc_strdup(const void *ctx, const char *str);
-
-/**
- * Duplicate a string, allocating the memory from the given context.
- *
- * Like \c strndup, at most \p n characters are copied. If \p str is longer
- * than \p n characters, \p n are copied, and a termining \c '\0' byte is added.
- */
-char *ralloc_strndup(const void *ctx, const char *str, size_t n);
-
-/**
- * Concatenate two strings, allocating the necessary space.
- *
- * This appends \p str to \p *dest, similar to \c strcat, using ralloc_resize
- * to expand \p *dest to the appropriate size. \p dest will be updated to the
- * new pointer unless allocation fails.
- *
- * The result will always be null-terminated.
- *
- * \return True unless allocation failed.
- */
-bool ralloc_strcat(char **dest, const char *str);
-
-/**
- * Concatenate two strings, allocating the necessary space.
- *
- * This appends at most \p n bytes of \p str to \p *dest, using ralloc_resize
- * to expand \p *dest to the appropriate size. \p dest will be updated to the
- * new pointer unless allocation fails.
- *
- * The result will always be null-terminated; \p str does not need to be null
- * terminated if it is longer than \p n.
- *
- * \return True unless allocation failed.
- */
-bool ralloc_strncat(char **dest, const char *str, size_t n);
-
-/**
- * Print to a string.
- *
- * This is analogous to \c sprintf, but allocates enough space (using \p ctx
- * as the context) for the resulting string.
- *
- * \return The newly allocated string.
- */
-char *ralloc_asprintf (const void *ctx, const char *fmt, ...) PRINTFLIKE(2, 3);
-
-/**
- * Print to a string, given a va_list.
- *
- * This is analogous to \c vsprintf, but allocates enough space (using \p ctx
- * as the context) for the resulting string.
- *
- * \return The newly allocated string.
- */
-char *ralloc_vasprintf(const void *ctx, const char *fmt, va_list args);
-
-/**
- * Rewrite the tail of an existing string, starting at a given index.
- *
- * Overwrites the contents of *str starting at \p start with newly formatted
- * text, including a new null-terminator. Allocates more memory as necessary.
- *
- * This can be used to append formatted text when the length of the existing
- * string is already known, saving a strlen() call.
- *
- * \sa ralloc_asprintf_append
- *
- * \param str The string to be updated.
- * \param start The index to start appending new data at.
- * \param fmt A printf-style formatting string
- *
- * \p str will be updated to the new pointer unless allocation fails.
- * \p start will be increased by the length of the newly formatted text.
- *
- * \return True unless allocation failed.
- */
-bool ralloc_asprintf_rewrite_tail(char **str, size_t *start,
- const char *fmt, ...)
- PRINTFLIKE(3, 4);
-
-/**
- * Rewrite the tail of an existing string, starting at a given index.
- *
- * Overwrites the contents of *str starting at \p start with newly formatted
- * text, including a new null-terminator. Allocates more memory as necessary.
- *
- * This can be used to append formatted text when the length of the existing
- * string is already known, saving a strlen() call.
- *
- * \sa ralloc_vasprintf_append
- *
- * \param str The string to be updated.
- * \param start The index to start appending new data at.
- * \param fmt A printf-style formatting string
- * \param args A va_list containing the data to be formatted
- *
- * \p str will be updated to the new pointer unless allocation fails.
- * \p start will be increased by the length of the newly formatted text.
- *
- * \return True unless allocation failed.
- */
-bool ralloc_vasprintf_rewrite_tail(char **str, size_t *start, const char *fmt,
- va_list args);
-
-/**
- * Append formatted text to the supplied string.
- *
- * This is equivalent to
- * \code
- * ralloc_asprintf_rewrite_tail(str, strlen(*str), fmt, ...)
- * \endcode
- *
- * \sa ralloc_asprintf
- * \sa ralloc_asprintf_rewrite_tail
- * \sa ralloc_strcat
- *
- * \p str will be updated to the new pointer unless allocation fails.
- *
- * \return True unless allocation failed.
- */
-bool ralloc_asprintf_append (char **str, const char *fmt, ...)
- PRINTFLIKE(2, 3);
-
-/**
- * Append formatted text to the supplied string, given a va_list.
- *
- * This is equivalent to
- * \code
- * ralloc_vasprintf_rewrite_tail(str, strlen(*str), fmt, args)
- * \endcode
- *
- * \sa ralloc_vasprintf
- * \sa ralloc_vasprintf_rewrite_tail
- * \sa ralloc_strcat
- *
- * \p str will be updated to the new pointer unless allocation fails.
- *
- * \return True unless allocation failed.
- */
-bool ralloc_vasprintf_append(char **str, const char *fmt, va_list args);
-/// @}
-
-#ifdef __cplusplus
-} /* end of extern "C" */
-#endif
-
-/**
- * Declare C++ new and delete operators which use ralloc.
- *
- * Placing this macro in the body of a class makes it possible to do:
- *
- * TYPE *var = new(mem_ctx) TYPE(...);
- * delete var;
- *
- * which is more idiomatic in C++ than calling ralloc.
- */
-#define DECLARE_RALLOC_CXX_OPERATORS(TYPE) \
-private: \
- static void _ralloc_destructor(void *p) \
- { \
- reinterpret_cast<TYPE *>(p)->~TYPE(); \
- } \
-public: \
- static void* operator new(size_t size, void *mem_ctx) \
- { \
- void *p = ralloc_size(mem_ctx, size); \
- assert(p != NULL); \
- if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \
- ralloc_set_destructor(p, _ralloc_destructor); \
- return p; \
- } \
- \
- static void operator delete(void *p) \
- { \
- /* The object's destructor is guaranteed to have already been \
- * called by the delete operator at this point -- Make sure it's \
- * not called again. \
- */ \
- if (!HAS_TRIVIAL_DESTRUCTOR(TYPE)) \
- ralloc_set_destructor(p, NULL); \
- ralloc_free(p); \
- }
-
-
-#endif
diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp
index 809732c7e..abdd83a44 100644
--- a/mesalib/src/glsl/standalone_scaffolding.cpp
+++ b/mesalib/src/glsl/standalone_scaffolding.cpp
@@ -31,7 +31,7 @@
#include <assert.h>
#include <string.h>
-#include "ralloc.h"
+#include "util/ralloc.h"
void
_mesa_warning(struct gl_context *ctx, const char *fmt, ...)