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