Merge commit mesa-public/master into vulkan
[mesa.git] / src / compiler / glsl / glsl_symbol_table.cpp
1 /* -*- c++ -*- */
2 /*
3 * Copyright © 2010 Intel Corporation
4 *
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:
11 *
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
14 * Software.
15 *
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.
23 */
24
25 #include "glsl_symbol_table.h"
26 #include "ast.h"
27
28 class symbol_table_entry {
29 public:
30 DECLARE_RALLOC_CXX_OPERATORS(symbol_table_entry);
31
32 bool add_interface(const glsl_type *i, enum ir_variable_mode mode)
33 {
34 const glsl_type **dest;
35
36 switch (mode) {
37 case ir_var_uniform:
38 dest = &ibu;
39 break;
40 case ir_var_shader_storage:
41 dest = &iss;
42 break;
43 case ir_var_shader_in:
44 dest = &ibi;
45 break;
46 case ir_var_shader_out:
47 dest = &ibo;
48 break;
49 default:
50 assert(!"Unsupported interface variable mode!");
51 return false;
52 }
53
54 if (*dest != NULL) {
55 return false;
56 } else {
57 *dest = i;
58 return true;
59 }
60 }
61
62 const glsl_type *get_interface(enum ir_variable_mode mode)
63 {
64 switch (mode) {
65 case ir_var_uniform:
66 return ibu;
67 case ir_var_shader_storage:
68 return iss;
69 case ir_var_shader_in:
70 return ibi;
71 case ir_var_shader_out:
72 return ibo;
73 default:
74 assert(!"Unsupported interface variable mode!");
75 return NULL;
76 }
77 }
78
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)
87 {
88 assert(t->is_interface());
89 add_interface(t, mode);
90 }
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) {}
93
94 ir_variable *v;
95 ir_function *f;
96 const glsl_type *t;
97 const glsl_type *ibu;
98 const glsl_type *iss;
99 const glsl_type *ibi;
100 const glsl_type *ibo;
101 const class ast_type_specifier *a;
102 };
103
104 glsl_symbol_table::glsl_symbol_table()
105 {
106 this->separate_function_namespace = false;
107 this->table = _mesa_symbol_table_ctor();
108 this->mem_ctx = ralloc_context(NULL);
109 }
110
111 glsl_symbol_table::~glsl_symbol_table()
112 {
113 _mesa_symbol_table_dtor(table);
114 ralloc_free(mem_ctx);
115 }
116
117 void glsl_symbol_table::push_scope()
118 {
119 _mesa_symbol_table_push_scope(table);
120 }
121
122 void glsl_symbol_table::pop_scope()
123 {
124 _mesa_symbol_table_pop_scope(table);
125 }
126
127 bool glsl_symbol_table::name_declared_this_scope(const char *name)
128 {
129 return _mesa_symbol_table_symbol_scope(table, -1, name) == 0;
130 }
131
132 bool glsl_symbol_table::add_variable(ir_variable *v)
133 {
134 assert(v->data.mode != ir_var_temporary);
135
136 if (this->separate_function_namespace) {
137 /* In 1.10, functions and variables have separate namespaces. */
138 symbol_table_entry *existing = get_entry(v->name);
139 if (name_declared_this_scope(v->name)) {
140 /* If there's already an existing function (not a constructor!) in
141 * the current scope, just update the existing entry to include 'v'.
142 */
143 if (existing->v == NULL && existing->t == NULL) {
144 existing->v = v;
145 return true;
146 }
147 } else {
148 /* If not declared at this scope, add a new entry. But if an existing
149 * entry includes a function, propagate that to this block - otherwise
150 * the new variable declaration would shadow the function.
151 */
152 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
153 if (existing != NULL)
154 entry->f = existing->f;
155 int added = _mesa_symbol_table_add_symbol(table, -1, v->name, entry);
156 assert(added == 0);
157 (void)added;
158 return true;
159 }
160 return false;
161 }
162
163 /* 1.20+ rules: */
164 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
165 return _mesa_symbol_table_add_symbol(table, -1, v->name, entry) == 0;
166 }
167
168 bool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
169 {
170 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(t);
171 return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
172 }
173
174 bool glsl_symbol_table::add_interface(const char *name, const glsl_type *i,
175 enum ir_variable_mode mode)
176 {
177 assert(i->is_interface());
178 symbol_table_entry *entry = get_entry(name);
179 if (entry == NULL) {
180 symbol_table_entry *entry =
181 new(mem_ctx) symbol_table_entry(i, mode);
182 bool add_interface_symbol_result =
183 _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
184 assert(add_interface_symbol_result);
185 return add_interface_symbol_result;
186 } else {
187 return entry->add_interface(i, mode);
188 }
189 }
190
191 bool glsl_symbol_table::add_function(ir_function *f)
192 {
193 if (this->separate_function_namespace && name_declared_this_scope(f->name)) {
194 /* In 1.10, functions and variables have separate namespaces. */
195 symbol_table_entry *existing = get_entry(f->name);
196 if ((existing->f == NULL) && (existing->t == NULL)) {
197 existing->f = f;
198 return true;
199 }
200 }
201 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
202 return _mesa_symbol_table_add_symbol(table, -1, f->name, entry) == 0;
203 }
204
205 bool glsl_symbol_table::add_default_precision_qualifier(const char *type_name,
206 int precision)
207 {
208 char *name = ralloc_asprintf(mem_ctx, "#default_precision_%s", type_name);
209
210 ast_type_specifier *default_specifier = new(mem_ctx) ast_type_specifier(name);
211 default_specifier->default_precision = precision;
212
213 symbol_table_entry *entry =
214 new(mem_ctx) symbol_table_entry(default_specifier);
215
216 return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
217 }
218
219 void glsl_symbol_table::add_global_function(ir_function *f)
220 {
221 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
222 int added = _mesa_symbol_table_add_global_symbol(table, -1, f->name, entry);
223 assert(added == 0);
224 (void)added;
225 }
226
227 ir_variable *glsl_symbol_table::get_variable(const char *name)
228 {
229 symbol_table_entry *entry = get_entry(name);
230 return entry != NULL ? entry->v : NULL;
231 }
232
233 const glsl_type *glsl_symbol_table::get_type(const char *name)
234 {
235 symbol_table_entry *entry = get_entry(name);
236 return entry != NULL ? entry->t : NULL;
237 }
238
239 const glsl_type *glsl_symbol_table::get_interface(const char *name,
240 enum ir_variable_mode mode)
241 {
242 symbol_table_entry *entry = get_entry(name);
243 return entry != NULL ? entry->get_interface(mode) : NULL;
244 }
245
246 ir_function *glsl_symbol_table::get_function(const char *name)
247 {
248 symbol_table_entry *entry = get_entry(name);
249 return entry != NULL ? entry->f : NULL;
250 }
251
252 int glsl_symbol_table::get_default_precision_qualifier(const char *type_name)
253 {
254 char *name = ralloc_asprintf(mem_ctx, "#default_precision_%s", type_name);
255 symbol_table_entry *entry = get_entry(name);
256 if (!entry)
257 return ast_precision_none;
258 return entry->a->default_precision;
259 }
260
261 symbol_table_entry *glsl_symbol_table::get_entry(const char *name)
262 {
263 return (symbol_table_entry *)
264 _mesa_symbol_table_find_symbol(table, -1, name);
265 }
266
267 void
268 glsl_symbol_table::disable_variable(const char *name)
269 {
270 /* Ideally we would remove the variable's entry from the symbol table, but
271 * that would be difficult. Fortunately, since this is only used for
272 * built-in variables, it won't be possible for the shader to re-introduce
273 * the variable later, so all we really need to do is to make sure that
274 * further attempts to access it using get_variable() will return NULL.
275 */
276 symbol_table_entry *entry = get_entry(name);
277 if (entry != NULL) {
278 entry->v = NULL;
279 }
280 }