3 * Copyright © 2010 Intel Corporation
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 #include "glsl_symbol_table.h"
28 class symbol_table_entry
{
30 DECLARE_LINEAR_ALLOC_CXX_OPERATORS(symbol_table_entry
);
32 bool add_interface(const glsl_type
*i
, enum ir_variable_mode mode
)
34 const glsl_type
**dest
;
40 case ir_var_shader_storage
:
43 case ir_var_shader_in
:
46 case ir_var_shader_out
:
50 assert(!"Unsupported interface variable mode!");
62 const glsl_type
*get_interface(enum ir_variable_mode mode
)
67 case ir_var_shader_storage
:
69 case ir_var_shader_in
:
71 case ir_var_shader_out
:
74 assert(!"Unsupported interface variable mode!");
79 symbol_table_entry(ir_variable
*v
) :
80 v(v
), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) {}
81 symbol_table_entry(ir_function
*f
) :
82 v(0), f(f
), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0) {}
83 symbol_table_entry(const glsl_type
*t
) :
84 v(0), f(0), t(t
), ibu(0), iss(0), ibi(0), ibo(0), a(0) {}
85 symbol_table_entry(const glsl_type
*t
, enum ir_variable_mode mode
) :
86 v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(0)
88 assert(t
->is_interface());
89 add_interface(t
, mode
);
91 symbol_table_entry(const class ast_type_specifier
*a
):
92 v(0), f(0), t(0), ibu(0), iss(0), ibi(0), ibo(0), a(a
) {}
100 const glsl_type
*ibo
;
101 const class ast_type_specifier
*a
;
104 glsl_symbol_table::glsl_symbol_table()
106 this->separate_function_namespace
= false;
107 this->table
= _mesa_symbol_table_ctor();
108 this->mem_ctx
= ralloc_context(NULL
);
109 this->linalloc
= linear_alloc_parent(this->mem_ctx
, 0);
112 glsl_symbol_table::~glsl_symbol_table()
114 _mesa_symbol_table_dtor(table
);
115 ralloc_free(mem_ctx
);
118 void glsl_symbol_table::push_scope()
120 _mesa_symbol_table_push_scope(table
);
123 void glsl_symbol_table::pop_scope()
125 _mesa_symbol_table_pop_scope(table
);
128 bool glsl_symbol_table::name_declared_this_scope(const char *name
)
130 return _mesa_symbol_table_symbol_scope(table
, name
) == 0;
133 bool glsl_symbol_table::add_variable(ir_variable
*v
)
135 assert(v
->data
.mode
!= ir_var_temporary
);
137 if (this->separate_function_namespace
) {
138 /* In 1.10, functions and variables have separate namespaces. */
139 symbol_table_entry
*existing
= get_entry(v
->name
);
140 if (name_declared_this_scope(v
->name
)) {
141 /* If there's already an existing function (not a constructor!) in
142 * the current scope, just update the existing entry to include 'v'.
144 if (existing
->v
== NULL
&& existing
->t
== NULL
) {
149 /* If not declared at this scope, add a new entry. But if an existing
150 * entry includes a function, propagate that to this block - otherwise
151 * the new variable declaration would shadow the function.
153 symbol_table_entry
*entry
= new(linalloc
) symbol_table_entry(v
);
154 if (existing
!= NULL
)
155 entry
->f
= existing
->f
;
156 int added
= _mesa_symbol_table_add_symbol(table
, v
->name
, entry
);
165 symbol_table_entry
*entry
= new(linalloc
) symbol_table_entry(v
);
166 return _mesa_symbol_table_add_symbol(table
, v
->name
, entry
) == 0;
169 bool glsl_symbol_table::add_type(const char *name
, const glsl_type
*t
)
171 symbol_table_entry
*entry
= new(linalloc
) symbol_table_entry(t
);
172 return _mesa_symbol_table_add_symbol(table
, name
, entry
) == 0;
175 bool glsl_symbol_table::add_interface(const char *name
, const glsl_type
*i
,
176 enum ir_variable_mode mode
)
178 assert(i
->is_interface());
179 symbol_table_entry
*entry
= get_entry(name
);
181 symbol_table_entry
*entry
=
182 new(linalloc
) symbol_table_entry(i
, mode
);
183 bool add_interface_symbol_result
=
184 _mesa_symbol_table_add_symbol(table
, name
, entry
) == 0;
185 assert(add_interface_symbol_result
);
186 return add_interface_symbol_result
;
188 return entry
->add_interface(i
, mode
);
192 bool glsl_symbol_table::add_function(ir_function
*f
)
194 if (this->separate_function_namespace
&& name_declared_this_scope(f
->name
)) {
195 /* In 1.10, functions and variables have separate namespaces. */
196 symbol_table_entry
*existing
= get_entry(f
->name
);
197 if ((existing
->f
== NULL
) && (existing
->t
== NULL
)) {
202 symbol_table_entry
*entry
= new(linalloc
) symbol_table_entry(f
);
203 return _mesa_symbol_table_add_symbol(table
, f
->name
, entry
) == 0;
206 bool glsl_symbol_table::add_default_precision_qualifier(const char *type_name
,
209 char *name
= ralloc_asprintf(mem_ctx
, "#default_precision_%s", type_name
);
211 ast_type_specifier
*default_specifier
= new(linalloc
) ast_type_specifier(name
);
212 default_specifier
->default_precision
= precision
;
214 symbol_table_entry
*entry
=
215 new(linalloc
) symbol_table_entry(default_specifier
);
217 if (!get_entry(name
))
218 return _mesa_symbol_table_add_symbol(table
, name
, entry
) == 0;
220 return _mesa_symbol_table_replace_symbol(table
, name
, entry
) == 0;
223 void glsl_symbol_table::add_global_function(ir_function
*f
)
225 symbol_table_entry
*entry
= new(linalloc
) symbol_table_entry(f
);
226 int added
= _mesa_symbol_table_add_global_symbol(table
, f
->name
, entry
);
231 ir_variable
*glsl_symbol_table::get_variable(const char *name
)
233 symbol_table_entry
*entry
= get_entry(name
);
234 return entry
!= NULL
? entry
->v
: NULL
;
237 const glsl_type
*glsl_symbol_table::get_type(const char *name
)
239 symbol_table_entry
*entry
= get_entry(name
);
240 return entry
!= NULL
? entry
->t
: NULL
;
243 const glsl_type
*glsl_symbol_table::get_interface(const char *name
,
244 enum ir_variable_mode mode
)
246 symbol_table_entry
*entry
= get_entry(name
);
247 return entry
!= NULL
? entry
->get_interface(mode
) : NULL
;
250 ir_function
*glsl_symbol_table::get_function(const char *name
)
252 symbol_table_entry
*entry
= get_entry(name
);
253 return entry
!= NULL
? entry
->f
: NULL
;
256 int glsl_symbol_table::get_default_precision_qualifier(const char *type_name
)
258 char *name
= ralloc_asprintf(mem_ctx
, "#default_precision_%s", type_name
);
259 symbol_table_entry
*entry
= get_entry(name
);
261 return ast_precision_none
;
262 return entry
->a
->default_precision
;
265 symbol_table_entry
*glsl_symbol_table::get_entry(const char *name
)
267 return (symbol_table_entry
*)
268 _mesa_symbol_table_find_symbol(table
, name
);
272 glsl_symbol_table::disable_variable(const char *name
)
274 /* Ideally we would remove the variable's entry from the symbol table, but
275 * that would be difficult. Fortunately, since this is only used for
276 * built-in variables, it won't be possible for the shader to re-introduce
277 * the variable later, so all we really need to do is to make sure that
278 * further attempts to access it using get_variable() will return NULL.
280 symbol_table_entry
*entry
= get_entry(name
);
287 glsl_symbol_table::replace_variable(const char *name
,
290 symbol_table_entry
*entry
= get_entry(name
);