glsl: Never put ir_var_temporary variables in the symbol table
[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 assert(v->data.mode != ir_var_temporary);
128
129 if (this->separate_function_namespace) {
130 /* In 1.10, functions and variables have separate namespaces. */
131 symbol_table_entry *existing = get_entry(v->name);
132 if (name_declared_this_scope(v->name)) {
133 /* If there's already an existing function (not a constructor!) in
134 * the current scope, just update the existing entry to include 'v'.
135 */
136 if (existing->v == NULL && existing->t == NULL) {
137 existing->v = v;
138 return true;
139 }
140 } else {
141 /* If not declared at this scope, add a new entry. But if an existing
142 * entry includes a function, propagate that to this block - otherwise
143 * the new variable declaration would shadow the function.
144 */
145 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
146 if (existing != NULL)
147 entry->f = existing->f;
148 int added = _mesa_symbol_table_add_symbol(table, -1, v->name, entry);
149 assert(added == 0);
150 (void)added;
151 return true;
152 }
153 return false;
154 }
155
156 /* 1.20+ rules: */
157 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(v);
158 return _mesa_symbol_table_add_symbol(table, -1, v->name, entry) == 0;
159 }
160
161 bool glsl_symbol_table::add_type(const char *name, const glsl_type *t)
162 {
163 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(t);
164 return _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
165 }
166
167 bool glsl_symbol_table::add_interface(const char *name, const glsl_type *i,
168 enum ir_variable_mode mode)
169 {
170 assert(i->is_interface());
171 symbol_table_entry *entry = get_entry(name);
172 if (entry == NULL) {
173 symbol_table_entry *entry =
174 new(mem_ctx) symbol_table_entry(i, mode);
175 bool add_interface_symbol_result =
176 _mesa_symbol_table_add_symbol(table, -1, name, entry) == 0;
177 assert(add_interface_symbol_result);
178 return add_interface_symbol_result;
179 } else {
180 return entry->add_interface(i, mode);
181 }
182 }
183
184 bool glsl_symbol_table::add_function(ir_function *f)
185 {
186 if (this->separate_function_namespace && name_declared_this_scope(f->name)) {
187 /* In 1.10, functions and variables have separate namespaces. */
188 symbol_table_entry *existing = get_entry(f->name);
189 if ((existing->f == NULL) && (existing->t == NULL)) {
190 existing->f = f;
191 return true;
192 }
193 }
194 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
195 return _mesa_symbol_table_add_symbol(table, -1, f->name, entry) == 0;
196 }
197
198 void glsl_symbol_table::add_global_function(ir_function *f)
199 {
200 symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
201 int added = _mesa_symbol_table_add_global_symbol(table, -1, f->name, entry);
202 assert(added == 0);
203 (void)added;
204 }
205
206 ir_variable *glsl_symbol_table::get_variable(const char *name)
207 {
208 symbol_table_entry *entry = get_entry(name);
209 return entry != NULL ? entry->v : NULL;
210 }
211
212 const glsl_type *glsl_symbol_table::get_type(const char *name)
213 {
214 symbol_table_entry *entry = get_entry(name);
215 return entry != NULL ? entry->t : NULL;
216 }
217
218 const glsl_type *glsl_symbol_table::get_interface(const char *name,
219 enum ir_variable_mode mode)
220 {
221 symbol_table_entry *entry = get_entry(name);
222 return entry != NULL ? entry->get_interface(mode) : NULL;
223 }
224
225 ir_function *glsl_symbol_table::get_function(const char *name)
226 {
227 symbol_table_entry *entry = get_entry(name);
228 return entry != NULL ? entry->f : NULL;
229 }
230
231 symbol_table_entry *glsl_symbol_table::get_entry(const char *name)
232 {
233 return (symbol_table_entry *)
234 _mesa_symbol_table_find_symbol(table, -1, name);
235 }
236
237 void
238 glsl_symbol_table::disable_variable(const char *name)
239 {
240 /* Ideally we would remove the variable's entry from the symbol table, but
241 * that would be difficult. Fortunately, since this is only used for
242 * built-in variables, it won't be possible for the shader to re-introduce
243 * the variable later, so all we really need to do is to make sure that
244 * further attempts to access it using get_variable() will return NULL.
245 */
246 symbol_table_entry *entry = get_entry(name);
247 if (entry != NULL) {
248 entry->v = NULL;
249 }
250 }