c900a285bc7b1d3abf5aaa632f1e6ec3cb3958c3
[mesa.git] / ir.cpp
1 /*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include <string.h>
24 #include "main/imports.h"
25 #include "main/simple_list.h"
26 #include "ir.h"
27 #include "glsl_types.h"
28
29 ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs,
30 ir_rvalue *condition)
31 : ir_rvalue()
32 {
33 this->lhs = lhs;
34 this->rhs = rhs;
35 this->condition = condition;
36 }
37
38
39 ir_expression::ir_expression(int op, const struct glsl_type *type,
40 ir_rvalue *op0, ir_rvalue *op1)
41 : ir_rvalue()
42 {
43 this->type = type;
44 this->operation = ir_expression_operation(op);
45 this->operands[0] = op0;
46 this->operands[1] = op1;
47 }
48
49 unsigned int
50 ir_expression::get_num_operands(void)
51 {
52 /* Update ir_print_visitor.cpp when updating this list. */
53 const int num_operands[] = {
54 1, /* ir_unop_bit_not */
55 1, /* ir_unop_logic_not */
56 1, /* ir_unop_neg */
57 1, /* ir_unop_abs */
58 1, /* ir_unop_rcp */
59 1, /* ir_unop_rsq */
60 1, /* ir_unop_sqrt */
61 1, /* ir_unop_exp */
62 1, /* ir_unop_log */
63 1, /* ir_unop_exp2 */
64 1, /* ir_unop_log2 */
65 1, /* ir_unop_f2i */
66 1, /* ir_unop_i2f */
67 1, /* ir_unop_f2b */
68 1, /* ir_unop_b2f */
69 1, /* ir_unop_i2b */
70 1, /* ir_unop_b2i */
71 1, /* ir_unop_u2f */
72
73 1, /* ir_unop_trunc */
74 1, /* ir_unop_ceil */
75 1, /* ir_unop_floor */
76
77 2, /* ir_binop_add */
78 2, /* ir_binop_sub */
79 2, /* ir_binop_mul */
80 2, /* ir_binop_div */
81 2, /* ir_binop_mod */
82
83 2, /* ir_binop_less */
84 2, /* ir_binop_greater */
85 2, /* ir_binop_lequal */
86 2, /* ir_binop_gequal */
87 2, /* ir_binop_equal */
88 2, /* ir_binop_nequal */
89
90 2, /* ir_binop_lshift */
91 2, /* ir_binop_rshift */
92 2, /* ir_binop_bit_and */
93 2, /* ir_binop_bit_xor */
94 2, /* ir_binop_bit_or */
95
96 2, /* ir_binop_logic_and */
97 2, /* ir_binop_logic_xor */
98 2, /* ir_binop_logic_or */
99
100 2, /* ir_binop_dot */
101 2, /* ir_binop_min */
102 2, /* ir_binop_max */
103
104 2, /* ir_binop_pow */
105 };
106
107 assert(sizeof(num_operands) / sizeof(num_operands[0]) == ir_binop_pow + 1);
108
109 return num_operands[this->operation];
110 }
111
112 ir_label::ir_label(const char *label)
113 : ir_instruction(), label(label)
114 {
115 /* empty */
116 }
117
118
119 ir_constant::ir_constant(const struct glsl_type *type, const void *data)
120 : ir_rvalue()
121 {
122 unsigned size = 0;
123
124 this->type = type;
125 switch (type->base_type) {
126 case GLSL_TYPE_UINT: size = sizeof(this->value.u[0]); break;
127 case GLSL_TYPE_INT: size = sizeof(this->value.i[0]); break;
128 case GLSL_TYPE_FLOAT: size = sizeof(this->value.f[0]); break;
129 case GLSL_TYPE_BOOL: size = sizeof(this->value.b[0]); break;
130 default:
131 /* FINISHME: What to do? Exceptions are not the answer.
132 */
133 break;
134 }
135
136 memcpy(& this->value, data, size * type->components());
137 }
138
139 ir_constant::ir_constant(float f)
140 : ir_rvalue()
141 {
142 this->type = glsl_type::float_type;
143 this->value.f[0] = f;
144 }
145
146 ir_constant::ir_constant(unsigned int u)
147 : ir_rvalue()
148 {
149 this->type = glsl_type::uint_type;
150 this->value.u[0] = u;
151 }
152
153 ir_constant::ir_constant(int i)
154 : ir_rvalue()
155 {
156 this->type = glsl_type::int_type;
157 this->value.i[0] = i;
158 }
159
160 ir_constant::ir_constant(bool b)
161 : ir_rvalue()
162 {
163 this->type = glsl_type::bool_type;
164 this->value.b[0] = b;
165 }
166
167
168 ir_dereference::ir_dereference(ir_instruction *var)
169 : ir_rvalue()
170 {
171 this->mode = ir_reference_variable;
172 this->var = var;
173 this->type = (var != NULL) ? var->type : glsl_type::error_type;
174 }
175
176
177 ir_dereference::ir_dereference(ir_instruction *var,
178 ir_rvalue *array_index)
179 : ir_rvalue(), mode(ir_reference_array),
180 var(var)
181 {
182 type = glsl_type::error_type;
183
184 if (var != NULL) {
185 const glsl_type *const vt = var->type;
186
187 if (vt->is_array()) {
188 type = vt->element_type();
189 } else if (vt->is_matrix() || vt->is_vector()) {
190 type = vt->get_base_type();
191 }
192 }
193
194 this->selector.array_index = array_index;
195 }
196
197 bool
198 ir_dereference::is_lvalue()
199 {
200 if (var == NULL)
201 return false;
202
203 if (mode == ir_reference_variable) {
204 ir_variable *const as_var = var->as_variable();
205 if (as_var == NULL)
206 return false;
207
208 if (as_var->type->is_array() && !as_var->array_lvalue)
209 return false;
210
211 return !as_var->read_only;
212 } else if (mode == ir_reference_array) {
213 /* FINISHME: Walk up the dereference chain and figure out if
214 * FINISHME: the variable is read-only.
215 */
216 }
217
218 return true;
219 }
220
221 ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z,
222 unsigned w, unsigned count)
223 : val(val)
224 {
225 assert((count >= 1) && (count <= 4));
226
227 const unsigned dup_mask = 0
228 | ((count > 1) ? ((1U << y) & ((1U << x) )) : 0)
229 | ((count > 2) ? ((1U << z) & ((1U << x) | (1U << y) )) : 0)
230 | ((count > 3) ? ((1U << w) & ((1U << x) | (1U << y) | (1U << z))) : 0);
231
232 assert(x <= 3);
233 assert(y <= 3);
234 assert(z <= 3);
235 assert(w <= 3);
236
237 mask.x = x;
238 mask.y = y;
239 mask.z = z;
240 mask.w = w;
241 mask.num_components = count;
242 mask.has_duplicates = dup_mask != 0;
243
244 /* Based on the number of elements in the swizzle and the base type
245 * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
246 * generate the type of the resulting value.
247 */
248 type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1);
249 }
250
251 #define X 1
252 #define R 5
253 #define S 9
254 #define I 13
255
256 ir_swizzle *
257 ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
258 {
259 /* For each possible swizzle character, this table encodes the value in
260 * \c idx_map that represents the 0th element of the vector. For invalid
261 * swizzle characters (e.g., 'k'), a special value is used that will allow
262 * detection of errors.
263 */
264 static const unsigned char base_idx[26] = {
265 /* a b c d e f g h i j k l m */
266 R, R, I, I, I, I, R, I, I, I, I, I, I,
267 /* n o p q r s t u v w x y z */
268 I, I, S, S, R, S, S, I, I, X, X, X, X
269 };
270
271 /* Each valid swizzle character has an entry in the previous table. This
272 * table encodes the base index encoded in the previous table plus the actual
273 * index of the swizzle character. When processing swizzles, the first
274 * character in the string is indexed in the previous table. Each character
275 * in the string is indexed in this table, and the value found there has the
276 * value form the first table subtracted. The result must be on the range
277 * [0,3].
278 *
279 * For example, the string "wzyx" will get X from the first table. Each of
280 * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
281 * subtraction, the swizzle values are { 3, 2, 1, 0 }.
282 *
283 * The string "wzrg" will get X from the first table. Each of the characters
284 * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
285 * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
286 * [0,3], the error is detected.
287 */
288 static const unsigned char idx_map[26] = {
289 /* a b c d e f g h i j k l m */
290 R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0,
291 /* n o p q r s t u v w x y z */
292 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2
293 };
294
295 int swiz_idx[4] = { 0, 0, 0, 0 };
296 unsigned i;
297
298
299 /* Validate the first character in the swizzle string and look up the base
300 * index value as described above.
301 */
302 if ((str[0] < 'a') || (str[0] > 'z'))
303 return NULL;
304
305 const unsigned base = base_idx[str[0] - 'a'];
306
307
308 for (i = 0; (i < 4) && (str[i] != '\0'); i++) {
309 /* Validate the next character, and, as described above, convert it to a
310 * swizzle index.
311 */
312 if ((str[i] < 'a') || (str[i] > 'z'))
313 return NULL;
314
315 swiz_idx[i] = idx_map[str[i] - 'a'] - base;
316 if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length))
317 return NULL;
318 }
319
320 if (str[i] != '\0')
321 return NULL;
322
323 return new ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2],
324 swiz_idx[3], i);
325 }
326
327 #undef X
328 #undef R
329 #undef S
330 #undef I
331
332
333 ir_variable::ir_variable(const struct glsl_type *type, const char *name)
334 : max_array_access(0), read_only(false), centroid(false), invariant(false),
335 mode(ir_var_auto), interpolation(ir_var_smooth)
336 {
337 this->type = type;
338 this->name = name;
339
340 if (type && type->base_type == GLSL_TYPE_SAMPLER)
341 this->read_only = true;
342 }
343
344
345 ir_function_signature::ir_function_signature(const glsl_type *return_type)
346 : ir_instruction(), return_type(return_type), definition(NULL)
347 {
348 /* empty */
349 }
350
351
352 ir_function::ir_function(const char *name)
353 : ir_instruction(), name(name)
354 {
355 /* empty */
356 }
357
358
359 ir_call *
360 ir_call::get_error_instruction()
361 {
362 ir_call *call = new ir_call;
363
364 call->type = glsl_type::error_type;
365 return call;
366 }