blob: 942f19836074e37d8f1c0855594d1a8af9401d5e [file] [log] [blame]
Ian Romanick1cf43a42010-03-30 16:56:50 -07001/*
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
24/**
25 * \file ir_constant_expression.cpp
26 * Evaluate and process constant valued expressions
27 *
28 * In GLSL, constant valued expressions are used in several places. These
29 * must be processed and evaluated very early in the compilation process.
30 *
31 * * Sizes of arrays
32 * * Initializers for uniforms
33 * * Initializers for \c const variables
34 */
35
Eric Anholt43ad37a2010-05-12 14:42:21 -070036#include <math.h>
Kenneth Graunkef9149152010-07-21 21:56:13 -070037#include "main/macros.h"
Ian Romanick1cf43a42010-03-30 16:56:50 -070038#include "ir.h"
39#include "ir_visitor.h"
Eric Anholta576f9d2010-03-31 16:25:12 -100040#include "glsl_types.h"
Ian Romanick1cf43a42010-03-30 16:56:50 -070041
Kenneth Graunkeffcec132010-07-21 20:09:21 -070042static float
43dot(ir_constant *op0, ir_constant *op1)
44{
45 assert(op0->type->is_float() && op1->type->is_float());
46
47 float result = 0;
48 for (unsigned c = 0; c < op0->type->components(); c++)
49 result += op0->value.f[c] * op1->value.f[c];
50
51 return result;
52}
53
Ian Romanick1cf43a42010-03-30 16:56:50 -070054ir_constant *
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -070055ir_expression::constant_expression_value()
Ian Romanick1cf43a42010-03-30 16:56:50 -070056{
Kenneth Graunke6bc432e2010-07-02 17:12:23 -070057 ir_constant *op[2] = { NULL, NULL };
Ian Romanick4daaab62010-06-11 16:08:47 -070058 ir_constant_data data;
Eric Anholt160d0922010-04-01 18:07:08 -100059
Kenneth Graunkec63a1db2010-07-05 22:33:35 -070060 memset(&data, 0, sizeof(data));
61
Kenneth Graunke98f32a12010-07-15 10:20:51 -070062 for (unsigned operand = 0; operand < this->get_num_operands(); operand++) {
63 op[operand] = this->operands[operand]->constant_expression_value();
Eric Anholtd98da972010-04-01 18:25:11 -100064 if (!op[operand])
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -070065 return NULL;
Eric Anholt160d0922010-04-01 18:07:08 -100066 }
Eric Anholta576f9d2010-03-31 16:25:12 -100067
Kenneth Graunke6fc983b2010-07-06 02:39:57 -070068 if (op[1] != NULL)
69 assert(op[0]->type->base_type == op[1]->type->base_type);
70
Kenneth Graunkee74dcd72010-07-06 02:48:16 -070071 bool op0_scalar = op[0]->type->is_scalar();
72 bool op1_scalar = op[1] != NULL && op[1]->type->is_scalar();
73
74 /* When iterating over a vector or matrix's components, we want to increase
75 * the loop counter. However, for scalars, we want to stay at 0.
76 */
Kenneth Graunkeacf88f22010-07-07 12:08:23 -070077 unsigned c0_inc = op0_scalar ? 0 : 1;
78 unsigned c1_inc = op1_scalar ? 0 : 1;
Eric Anholt570dc0d2010-07-07 09:07:09 -070079 unsigned components;
80 if (op1_scalar || !op[1]) {
81 components = op[0]->type->components();
82 } else {
83 components = op[1]->type->components();
84 }
Kenneth Graunkee74dcd72010-07-06 02:48:16 -070085
Kenneth Graunke9a6d40f2010-07-20 03:08:32 -070086 void *ctx = talloc_parent(this);
87
88 /* Handle array operations here, rather than below. */
89 if (op[0]->type->is_array()) {
90 assert(op[1] != NULL && op[1]->type->is_array());
91 switch (this->operation) {
92 case ir_binop_equal:
93 return new(ctx) ir_constant(op[0]->has_value(op[1]));
94 case ir_binop_nequal:
95 return new(ctx) ir_constant(!op[0]->has_value(op[1]));
96 default:
97 break;
98 }
99 return NULL;
100 }
101
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700102 switch (this->operation) {
Eric Anholt528bb852010-03-31 21:09:02 -1000103 case ir_unop_logic_not:
Ian Romanickf8b88be2010-06-11 16:23:52 -0700104 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700105 for (unsigned c = 0; c < op[0]->type->components(); c++)
Ian Romanick4daaab62010-06-11 16:08:47 -0700106 data.b[c] = !op[0]->value.b[c];
Eric Anholt528bb852010-03-31 21:09:02 -1000107 break;
Eric Anholtaf186412010-04-06 10:53:57 -0700108
109 case ir_unop_f2i:
110 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700111 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700112 data.i[c] = op[0]->value.f[c];
Eric Anholtaf186412010-04-06 10:53:57 -0700113 }
114 break;
115 case ir_unop_i2f:
Kenneth Graunke46d6b8d2010-07-20 13:01:56 -0700116 assert(op[0]->type->base_type == GLSL_TYPE_INT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700117 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunke46d6b8d2010-07-20 13:01:56 -0700118 data.f[c] = op[0]->value.i[c];
119 }
120 break;
121 case ir_unop_u2f:
122 assert(op[0]->type->base_type == GLSL_TYPE_UINT);
123 for (unsigned c = 0; c < op[0]->type->components(); c++) {
124 data.f[c] = op[0]->value.u[c];
Eric Anholtaf186412010-04-06 10:53:57 -0700125 }
126 break;
Ian Romanick7dc2b712010-06-07 15:10:14 -0700127 case ir_unop_b2f:
128 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700129 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700130 data.f[c] = op[0]->value.b[c] ? 1.0 : 0.0;
Ian Romanick7dc2b712010-06-07 15:10:14 -0700131 }
132 break;
133 case ir_unop_f2b:
134 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700135 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700136 data.b[c] = bool(op[0]->value.f[c]);
Ian Romanick7dc2b712010-06-07 15:10:14 -0700137 }
138 break;
Ian Romanick39d6dd32010-06-11 13:46:30 -0700139 case ir_unop_b2i:
140 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700141 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700142 data.u[c] = op[0]->value.b[c] ? 1 : 0;
Ian Romanick39d6dd32010-06-11 13:46:30 -0700143 }
144 break;
145 case ir_unop_i2b:
146 assert(op[0]->type->is_integer());
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700147 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700148 data.b[c] = bool(op[0]->value.u[c]);
Ian Romanick39d6dd32010-06-11 13:46:30 -0700149 }
150 break;
Eric Anholtaf186412010-04-06 10:53:57 -0700151
Eric Anholt5e9ac942010-08-23 12:21:33 -0700152 case ir_unop_any:
153 assert(op[0]->type->is_boolean());
154 data.b[0] = false;
155 for (unsigned c = 0; c < op[0]->type->components(); c++) {
156 if (op[0]->value.b[c])
157 data.b[0] = true;
158 }
159 break;
160
Kenneth Graunke323d9092010-07-08 23:21:36 -0700161 case ir_unop_trunc:
162 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700163 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunke323d9092010-07-08 23:21:36 -0700164 data.f[c] = truncf(op[0]->value.f[c]);
165 }
166 break;
167
Kenneth Graunkec1ee30a2010-07-08 23:22:36 -0700168 case ir_unop_ceil:
169 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700170 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunkec1ee30a2010-07-08 23:22:36 -0700171 data.f[c] = ceilf(op[0]->value.f[c]);
172 }
173 break;
174
Kenneth Graunke07472042010-07-08 23:23:23 -0700175 case ir_unop_floor:
176 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700177 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunke07472042010-07-08 23:23:23 -0700178 data.f[c] = floorf(op[0]->value.f[c]);
179 }
180 break;
181
Eric Anholtd925c912010-07-01 10:37:11 -0700182 case ir_unop_fract:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700183 for (unsigned c = 0; c < op[0]->type->components(); c++) {
184 switch (this->type->base_type) {
Eric Anholtd925c912010-07-01 10:37:11 -0700185 case GLSL_TYPE_UINT:
186 data.u[c] = 0;
187 break;
188 case GLSL_TYPE_INT:
189 data.i[c] = 0;
190 break;
191 case GLSL_TYPE_FLOAT:
192 data.f[c] = op[0]->value.f[c] - floor(op[0]->value.f[c]);
193 break;
194 default:
195 assert(0);
196 }
197 }
198 break;
199
Kenneth Graunke908afd12010-07-08 23:28:50 -0700200 case ir_unop_sin:
201 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700202 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunke908afd12010-07-08 23:28:50 -0700203 data.f[c] = sinf(op[0]->value.f[c]);
204 }
205 break;
206
Kenneth Graunke3fab3762010-07-08 23:29:37 -0700207 case ir_unop_cos:
208 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700209 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunke3fab3762010-07-08 23:29:37 -0700210 data.f[c] = cosf(op[0]->value.f[c]);
211 }
212 break;
213
Eric Anholt43ad37a2010-05-12 14:42:21 -0700214 case ir_unop_neg:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700215 for (unsigned c = 0; c < op[0]->type->components(); c++) {
216 switch (this->type->base_type) {
Eric Anholt43ad37a2010-05-12 14:42:21 -0700217 case GLSL_TYPE_UINT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700218 data.u[c] = -op[0]->value.u[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700219 break;
220 case GLSL_TYPE_INT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700221 data.i[c] = -op[0]->value.i[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700222 break;
223 case GLSL_TYPE_FLOAT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700224 data.f[c] = -op[0]->value.f[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700225 break;
226 default:
227 assert(0);
228 }
229 }
230 break;
231
232 case ir_unop_abs:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700233 for (unsigned c = 0; c < op[0]->type->components(); c++) {
234 switch (this->type->base_type) {
Eric Anholt43ad37a2010-05-12 14:42:21 -0700235 case GLSL_TYPE_UINT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700236 data.u[c] = op[0]->value.u[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700237 break;
238 case GLSL_TYPE_INT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700239 data.i[c] = op[0]->value.i[c];
240 if (data.i[c] < 0)
241 data.i[c] = -data.i[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700242 break;
243 case GLSL_TYPE_FLOAT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700244 data.f[c] = fabs(op[0]->value.f[c]);
Eric Anholt43ad37a2010-05-12 14:42:21 -0700245 break;
246 default:
247 assert(0);
248 }
249 }
250 break;
251
Kenneth Graunke14b7b262010-07-08 23:11:14 -0700252 case ir_unop_sign:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700253 for (unsigned c = 0; c < op[0]->type->components(); c++) {
254 switch (this->type->base_type) {
Kenneth Graunke14b7b262010-07-08 23:11:14 -0700255 case GLSL_TYPE_UINT:
256 data.u[c] = op[0]->value.i[c] > 0;
257 break;
258 case GLSL_TYPE_INT:
259 data.i[c] = (op[0]->value.i[c] > 0) - (op[0]->value.i[c] < 0);
260 break;
261 case GLSL_TYPE_FLOAT:
262 data.f[c] = float((op[0]->value.f[c] > 0)-(op[0]->value.f[c] < 0));
263 break;
264 default:
265 assert(0);
266 }
267 }
268 break;
269
Eric Anholt43ad37a2010-05-12 14:42:21 -0700270 case ir_unop_rcp:
271 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700272 for (unsigned c = 0; c < op[0]->type->components(); c++) {
273 switch (this->type->base_type) {
Eric Anholt43ad37a2010-05-12 14:42:21 -0700274 case GLSL_TYPE_UINT:
275 if (op[0]->value.u[c] != 0.0)
Ian Romanick4daaab62010-06-11 16:08:47 -0700276 data.u[c] = 1 / op[0]->value.u[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700277 break;
278 case GLSL_TYPE_INT:
279 if (op[0]->value.i[c] != 0.0)
Ian Romanick4daaab62010-06-11 16:08:47 -0700280 data.i[c] = 1 / op[0]->value.i[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700281 break;
282 case GLSL_TYPE_FLOAT:
283 if (op[0]->value.f[c] != 0.0)
Ian Romanick4daaab62010-06-11 16:08:47 -0700284 data.f[c] = 1.0 / op[0]->value.f[c];
Eric Anholt43ad37a2010-05-12 14:42:21 -0700285 break;
286 default:
287 assert(0);
288 }
289 }
290 break;
291
292 case ir_unop_rsq:
293 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700294 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700295 data.f[c] = 1.0 / sqrtf(op[0]->value.f[c]);
Eric Anholt43ad37a2010-05-12 14:42:21 -0700296 }
297 break;
298
299 case ir_unop_sqrt:
300 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700301 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700302 data.f[c] = sqrtf(op[0]->value.f[c]);
Eric Anholt43ad37a2010-05-12 14:42:21 -0700303 }
304 break;
305
306 case ir_unop_exp:
307 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700308 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700309 data.f[c] = expf(op[0]->value.f[c]);
Eric Anholt43ad37a2010-05-12 14:42:21 -0700310 }
311 break;
312
Kenneth Graunkeaca01ed2010-07-08 23:14:32 -0700313 case ir_unop_exp2:
314 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700315 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunkeaca01ed2010-07-08 23:14:32 -0700316 data.f[c] = exp2f(op[0]->value.f[c]);
317 }
318 break;
319
Eric Anholt43ad37a2010-05-12 14:42:21 -0700320 case ir_unop_log:
321 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700322 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700323 data.f[c] = logf(op[0]->value.f[c]);
Eric Anholt43ad37a2010-05-12 14:42:21 -0700324 }
325 break;
326
Kenneth Graunkecb639292010-07-08 23:18:09 -0700327 case ir_unop_log2:
328 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700329 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunkecb639292010-07-08 23:18:09 -0700330 data.f[c] = log2f(op[0]->value.f[c]);
331 }
332 break;
333
Kenneth Graunked6a32d42010-06-09 15:22:35 -0700334 case ir_unop_dFdx:
335 case ir_unop_dFdy:
336 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700337 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Ian Romanick4daaab62010-06-11 16:08:47 -0700338 data.f[c] = 0.0;
Kenneth Graunked6a32d42010-06-09 15:22:35 -0700339 }
340 break;
341
Kenneth Graunke891a0642010-07-08 23:35:09 -0700342 case ir_binop_pow:
343 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700344 for (unsigned c = 0; c < op[0]->type->components(); c++) {
Kenneth Graunke891a0642010-07-08 23:35:09 -0700345 data.f[c] = powf(op[0]->value.f[c], op[1]->value.f[c]);
346 }
347 break;
348
Kenneth Graunke3f4a0b82010-07-05 21:15:32 -0700349 case ir_binop_dot:
Kenneth Graunkeffcec132010-07-21 20:09:21 -0700350 data.f[0] = dot(op[0], op[1]);
Kenneth Graunke3f4a0b82010-07-05 21:15:32 -0700351 break;
Kenneth Graunkeffcec132010-07-21 20:09:21 -0700352
Kenneth Graunke79fed372010-07-09 11:53:56 -0700353 case ir_binop_min:
354 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
355 for (unsigned c = 0, c0 = 0, c1 = 0;
356 c < components;
357 c0 += c0_inc, c1 += c1_inc, c++) {
358
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700359 switch (op[0]->type->base_type) {
Kenneth Graunke79fed372010-07-09 11:53:56 -0700360 case GLSL_TYPE_UINT:
Kenneth Graunkef9149152010-07-21 21:56:13 -0700361 data.u[c] = MIN2(op[0]->value.u[c0], op[1]->value.u[c1]);
Kenneth Graunke79fed372010-07-09 11:53:56 -0700362 break;
363 case GLSL_TYPE_INT:
Kenneth Graunkef9149152010-07-21 21:56:13 -0700364 data.i[c] = MIN2(op[0]->value.i[c0], op[1]->value.i[c1]);
Kenneth Graunke79fed372010-07-09 11:53:56 -0700365 break;
366 case GLSL_TYPE_FLOAT:
Kenneth Graunkef9149152010-07-21 21:56:13 -0700367 data.f[c] = MIN2(op[0]->value.f[c0], op[1]->value.f[c1]);
Kenneth Graunke79fed372010-07-09 11:53:56 -0700368 break;
369 default:
370 assert(0);
371 }
372 }
373
374 break;
375 case ir_binop_max:
376 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
377 for (unsigned c = 0, c0 = 0, c1 = 0;
378 c < components;
379 c0 += c0_inc, c1 += c1_inc, c++) {
380
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700381 switch (op[0]->type->base_type) {
Kenneth Graunke79fed372010-07-09 11:53:56 -0700382 case GLSL_TYPE_UINT:
Kenneth Graunkef9149152010-07-21 21:56:13 -0700383 data.u[c] = MAX2(op[0]->value.u[c0], op[1]->value.u[c1]);
Kenneth Graunke79fed372010-07-09 11:53:56 -0700384 break;
385 case GLSL_TYPE_INT:
Kenneth Graunkef9149152010-07-21 21:56:13 -0700386 data.i[c] = MAX2(op[0]->value.i[c0], op[1]->value.i[c1]);
Kenneth Graunke79fed372010-07-09 11:53:56 -0700387 break;
388 case GLSL_TYPE_FLOAT:
Kenneth Graunkef9149152010-07-21 21:56:13 -0700389 data.f[c] = MAX2(op[0]->value.f[c0], op[1]->value.f[c1]);
Kenneth Graunke79fed372010-07-09 11:53:56 -0700390 break;
391 default:
392 assert(0);
393 }
394 }
Kenneth Graunke79fed372010-07-09 11:53:56 -0700395 break;
Eric Anholt9be7f632010-07-13 15:37:57 -0700396
397 case ir_binop_cross:
398 assert(op[0]->type == glsl_type::vec3_type);
399 assert(op[1]->type == glsl_type::vec3_type);
400 data.f[0] = (op[0]->value.f[1] * op[1]->value.f[2] -
401 op[1]->value.f[1] * op[0]->value.f[2]);
402 data.f[1] = (op[0]->value.f[2] * op[1]->value.f[0] -
403 op[1]->value.f[2] * op[0]->value.f[0]);
404 data.f[2] = (op[0]->value.f[0] * op[1]->value.f[1] -
405 op[1]->value.f[0] * op[0]->value.f[1]);
406 break;
407
Eric Anholtd251b922010-04-01 18:35:42 -1000408 case ir_binop_add:
Kenneth Graunkee74dcd72010-07-06 02:48:16 -0700409 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
410 for (unsigned c = 0, c0 = 0, c1 = 0;
411 c < components;
412 c0 += c0_inc, c1 += c1_inc, c++) {
413
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700414 switch (op[0]->type->base_type) {
Kenneth Graunkee74dcd72010-07-06 02:48:16 -0700415 case GLSL_TYPE_UINT:
416 data.u[c] = op[0]->value.u[c0] + op[1]->value.u[c1];
417 break;
418 case GLSL_TYPE_INT:
419 data.i[c] = op[0]->value.i[c0] + op[1]->value.i[c1];
420 break;
421 case GLSL_TYPE_FLOAT:
422 data.f[c] = op[0]->value.f[c0] + op[1]->value.f[c1];
423 break;
424 default:
425 assert(0);
Eric Anholtd251b922010-04-01 18:35:42 -1000426 }
Kenneth Graunkee74dcd72010-07-06 02:48:16 -0700427 }
Ian Romanickf8b88be2010-06-11 16:23:52 -0700428
Eric Anholtd251b922010-04-01 18:35:42 -1000429 break;
430 case ir_binop_sub:
Kenneth Graunke97b44f02010-07-06 02:53:29 -0700431 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
432 for (unsigned c = 0, c0 = 0, c1 = 0;
433 c < components;
434 c0 += c0_inc, c1 += c1_inc, c++) {
435
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700436 switch (op[0]->type->base_type) {
Kenneth Graunke97b44f02010-07-06 02:53:29 -0700437 case GLSL_TYPE_UINT:
438 data.u[c] = op[0]->value.u[c0] - op[1]->value.u[c1];
439 break;
440 case GLSL_TYPE_INT:
441 data.i[c] = op[0]->value.i[c0] - op[1]->value.i[c1];
442 break;
443 case GLSL_TYPE_FLOAT:
444 data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1];
445 break;
446 default:
447 assert(0);
Eric Anholtd251b922010-04-01 18:35:42 -1000448 }
Kenneth Graunke97b44f02010-07-06 02:53:29 -0700449 }
Ian Romanickf8b88be2010-06-11 16:23:52 -0700450
Eric Anholtd251b922010-04-01 18:35:42 -1000451 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000452 case ir_binop_mul:
Kenneth Graunkecf80a4d2010-07-05 23:19:56 -0700453 /* Check for equal types, or unequal types involving scalars */
Kenneth Graunke37b3f9d2010-07-06 03:01:15 -0700454 if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
455 || op0_scalar || op1_scalar) {
456 for (unsigned c = 0, c0 = 0, c1 = 0;
457 c < components;
458 c0 += c0_inc, c1 += c1_inc, c++) {
459
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700460 switch (op[0]->type->base_type) {
Eric Anholtd98da972010-04-01 18:25:11 -1000461 case GLSL_TYPE_UINT:
Kenneth Graunke37b3f9d2010-07-06 03:01:15 -0700462 data.u[c] = op[0]->value.u[c0] * op[1]->value.u[c1];
Eric Anholtd98da972010-04-01 18:25:11 -1000463 break;
464 case GLSL_TYPE_INT:
Kenneth Graunke37b3f9d2010-07-06 03:01:15 -0700465 data.i[c] = op[0]->value.i[c0] * op[1]->value.i[c1];
Eric Anholtd98da972010-04-01 18:25:11 -1000466 break;
467 case GLSL_TYPE_FLOAT:
Kenneth Graunke37b3f9d2010-07-06 03:01:15 -0700468 data.f[c] = op[0]->value.f[c0] * op[1]->value.f[c1];
Eric Anholtd98da972010-04-01 18:25:11 -1000469 break;
470 default:
471 assert(0);
472 }
Eric Anholta576f9d2010-03-31 16:25:12 -1000473 }
Kenneth Graunkecf80a4d2010-07-05 23:19:56 -0700474 } else {
475 assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
476
477 /* Multiply an N-by-M matrix with an M-by-P matrix. Since either
478 * matrix can be a GLSL vector, either N or P can be 1.
479 *
480 * For vec*mat, the vector is treated as a row vector. This
481 * means the vector is a 1-row x M-column matrix.
482 *
483 * For mat*vec, the vector is treated as a column vector. Since
484 * matrix_columns is 1 for vectors, this just works.
485 */
486 const unsigned n = op[0]->type->is_vector()
487 ? 1 : op[0]->type->vector_elements;
488 const unsigned m = op[1]->type->vector_elements;
489 const unsigned p = op[1]->type->matrix_columns;
490 for (unsigned j = 0; j < p; j++) {
491 for (unsigned i = 0; i < n; i++) {
492 for (unsigned k = 0; k < m; k++) {
493 data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
494 }
495 }
496 }
497 }
Ian Romanickf8b88be2010-06-11 16:23:52 -0700498
Eric Anholta576f9d2010-03-31 16:25:12 -1000499 break;
Eric Anholtd251b922010-04-01 18:35:42 -1000500 case ir_binop_div:
Kenneth Graunkedad35eb2010-07-06 02:56:36 -0700501 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
502 for (unsigned c = 0, c0 = 0, c1 = 0;
503 c < components;
504 c0 += c0_inc, c1 += c1_inc, c++) {
505
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700506 switch (op[0]->type->base_type) {
Kenneth Graunkedad35eb2010-07-06 02:56:36 -0700507 case GLSL_TYPE_UINT:
508 data.u[c] = op[0]->value.u[c0] / op[1]->value.u[c1];
509 break;
510 case GLSL_TYPE_INT:
511 data.i[c] = op[0]->value.i[c0] / op[1]->value.i[c1];
512 break;
513 case GLSL_TYPE_FLOAT:
514 data.f[c] = op[0]->value.f[c0] / op[1]->value.f[c1];
515 break;
516 default:
517 assert(0);
Eric Anholtd251b922010-04-01 18:35:42 -1000518 }
Kenneth Graunkedad35eb2010-07-06 02:56:36 -0700519 }
Ian Romanickf8b88be2010-06-11 16:23:52 -0700520
Eric Anholtd251b922010-04-01 18:35:42 -1000521 break;
Kenneth Graunkece5ae5f2010-07-14 11:28:40 -0700522 case ir_binop_mod:
523 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
524 for (unsigned c = 0, c0 = 0, c1 = 0;
525 c < components;
526 c0 += c0_inc, c1 += c1_inc, c++) {
527
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700528 switch (op[0]->type->base_type) {
Kenneth Graunkece5ae5f2010-07-14 11:28:40 -0700529 case GLSL_TYPE_UINT:
530 data.u[c] = op[0]->value.u[c0] % op[1]->value.u[c1];
531 break;
532 case GLSL_TYPE_INT:
533 data.i[c] = op[0]->value.i[c0] % op[1]->value.i[c1];
534 break;
535 case GLSL_TYPE_FLOAT:
536 /* We don't use fmod because it rounds toward zero; GLSL specifies
537 * the use of floor.
538 */
Kenneth Graunke3e882ec2010-07-22 17:44:34 -0700539 data.f[c] = op[0]->value.f[c0] - op[1]->value.f[c1]
Kenneth Graunkece5ae5f2010-07-14 11:28:40 -0700540 * floorf(op[0]->value.f[c0] / op[1]->value.f[c1]);
541 break;
542 default:
543 assert(0);
544 }
545 }
546
547 break;
548
Eric Anholta576f9d2010-03-31 16:25:12 -1000549 case ir_binop_logic_and:
Ian Romanickf8b88be2010-06-11 16:23:52 -0700550 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700551 for (unsigned c = 0; c < op[0]->type->components(); c++)
Ian Romanick4daaab62010-06-11 16:08:47 -0700552 data.b[c] = op[0]->value.b[c] && op[1]->value.b[c];
Eric Anholta576f9d2010-03-31 16:25:12 -1000553 break;
Eric Anholtd251b922010-04-01 18:35:42 -1000554 case ir_binop_logic_xor:
Ian Romanickf8b88be2010-06-11 16:23:52 -0700555 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700556 for (unsigned c = 0; c < op[0]->type->components(); c++)
Ian Romanick4daaab62010-06-11 16:08:47 -0700557 data.b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
Eric Anholtd251b922010-04-01 18:35:42 -1000558 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000559 case ir_binop_logic_or:
Ian Romanickf8b88be2010-06-11 16:23:52 -0700560 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700561 for (unsigned c = 0; c < op[0]->type->components(); c++)
Ian Romanick4daaab62010-06-11 16:08:47 -0700562 data.b[c] = op[0]->value.b[c] || op[1]->value.b[c];
Eric Anholta576f9d2010-03-31 16:25:12 -1000563 break;
Eric Anholt85171c22010-04-06 09:55:45 -0700564
565 case ir_binop_less:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700566 switch (op[0]->type->base_type) {
Eric Anholt85171c22010-04-06 09:55:45 -0700567 case GLSL_TYPE_UINT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700568 data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700569 break;
570 case GLSL_TYPE_INT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700571 data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700572 break;
573 case GLSL_TYPE_FLOAT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700574 data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700575 break;
576 default:
577 assert(0);
578 }
579 break;
580 case ir_binop_greater:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700581 switch (op[0]->type->base_type) {
Eric Anholt85171c22010-04-06 09:55:45 -0700582 case GLSL_TYPE_UINT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700583 data.b[0] = op[0]->value.u[0] > op[1]->value.u[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700584 break;
585 case GLSL_TYPE_INT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700586 data.b[0] = op[0]->value.i[0] > op[1]->value.i[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700587 break;
588 case GLSL_TYPE_FLOAT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700589 data.b[0] = op[0]->value.f[0] > op[1]->value.f[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700590 break;
591 default:
592 assert(0);
593 }
594 break;
595 case ir_binop_lequal:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700596 switch (op[0]->type->base_type) {
Eric Anholt85171c22010-04-06 09:55:45 -0700597 case GLSL_TYPE_UINT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700598 data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700599 break;
600 case GLSL_TYPE_INT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700601 data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700602 break;
603 case GLSL_TYPE_FLOAT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700604 data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700605 break;
606 default:
607 assert(0);
608 }
609 break;
610 case ir_binop_gequal:
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700611 switch (op[0]->type->base_type) {
Eric Anholt85171c22010-04-06 09:55:45 -0700612 case GLSL_TYPE_UINT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700613 data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700614 break;
615 case GLSL_TYPE_INT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700616 data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700617 break;
618 case GLSL_TYPE_FLOAT:
Ian Romanick4daaab62010-06-11 16:08:47 -0700619 data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
Eric Anholt85171c22010-04-06 09:55:45 -0700620 break;
621 default:
622 assert(0);
623 }
624 break;
625
Eric Anholtec1949e2010-04-06 10:02:27 -0700626 case ir_binop_equal:
Kenneth Graunke3163f872010-07-20 03:01:54 -0700627 data.b[0] = op[0]->has_value(op[1]);
Eric Anholtec1949e2010-04-06 10:02:27 -0700628 break;
629 case ir_binop_nequal:
Kenneth Graunke3163f872010-07-20 03:01:54 -0700630 data.b[0] = !op[0]->has_value(op[1]);
Eric Anholtec1949e2010-04-06 10:02:27 -0700631 break;
632
Eric Anholta576f9d2010-03-31 16:25:12 -1000633 default:
Ian Romanickf8b88be2010-06-11 16:23:52 -0700634 /* FINISHME: Should handle all expression types. */
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700635 return NULL;
Eric Anholta576f9d2010-03-31 16:25:12 -1000636 }
Eric Anholtd98da972010-04-01 18:25:11 -1000637
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700638 return new(ctx) ir_constant(this->type, &data);
Ian Romanick1cf43a42010-03-30 16:56:50 -0700639}
640
641
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700642ir_constant *
643ir_texture::constant_expression_value()
Kenneth Graunke26d74cd2010-05-26 17:42:03 -0700644{
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700645 /* texture lookups aren't constant expressions */
646 return NULL;
Kenneth Graunke26d74cd2010-05-26 17:42:03 -0700647}
648
649
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700650ir_constant *
651ir_swizzle::constant_expression_value()
Ian Romanick1cf43a42010-03-30 16:56:50 -0700652{
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700653 ir_constant *v = this->val->constant_expression_value();
Ian Romanickc2ba6192010-06-11 12:30:28 -0700654
Ian Romanickc2ba6192010-06-11 12:30:28 -0700655 if (v != NULL) {
Ian Romanick0bb70a32010-06-11 15:49:49 -0700656 ir_constant_data data;
Ian Romanickc2ba6192010-06-11 12:30:28 -0700657
658 const unsigned swiz_idx[4] = {
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700659 this->mask.x, this->mask.y, this->mask.z, this->mask.w
Ian Romanickc2ba6192010-06-11 12:30:28 -0700660 };
661
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700662 for (unsigned i = 0; i < this->mask.num_components; i++) {
Ian Romanickc2ba6192010-06-11 12:30:28 -0700663 switch (v->type->base_type) {
664 case GLSL_TYPE_UINT:
665 case GLSL_TYPE_INT: data.u[i] = v->value.u[swiz_idx[i]]; break;
666 case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break;
667 case GLSL_TYPE_BOOL: data.b[i] = v->value.b[swiz_idx[i]]; break;
668 default: assert(!"Should not get here."); break;
669 }
670 }
671
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700672 void *ctx = talloc_parent(this);
673 return new(ctx) ir_constant(this->type, &data);
Ian Romanickc2ba6192010-06-11 12:30:28 -0700674 }
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700675 return NULL;
Ian Romanick1cf43a42010-03-30 16:56:50 -0700676}
677
678
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700679ir_constant *
680ir_dereference_variable::constant_expression_value()
Ian Romanick1cf43a42010-03-30 16:56:50 -0700681{
Eric Anholt54f583a2010-07-27 12:10:50 -0700682 /* This may occur during compile and var->type is glsl_type::error_type */
683 if (!var)
684 return NULL;
685
Eric Anholt5704ed22010-08-02 15:31:28 -0700686 /* The constant_value of a uniform variable is its initializer,
687 * not the lifetime constant value of the uniform.
688 */
689 if (var->mode == ir_var_uniform)
690 return NULL;
691
Eric Anholt8273bd42010-08-04 12:34:56 -0700692 if (!var->constant_value)
693 return NULL;
694
695 return var->constant_value->clone(talloc_parent(var), NULL);
Ian Romanickc7b10462010-05-19 13:20:12 +0200696}
697
698
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700699ir_constant *
700ir_dereference_array::constant_expression_value()
Ian Romanickc7b10462010-05-19 13:20:12 +0200701{
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700702 ir_constant *array = this->array->constant_expression_value();
703 ir_constant *idx = this->array_index->constant_expression_value();
Ian Romanick9b92af92010-06-11 12:20:12 -0700704
Ian Romanick9b92af92010-06-11 12:20:12 -0700705 if ((array != NULL) && (idx != NULL)) {
Eric Anholt952d0f82010-08-04 12:57:58 -0700706 void *ctx = talloc_parent(this);
Ian Romanick9b92af92010-06-11 12:20:12 -0700707 if (array->type->is_matrix()) {
708 /* Array access of a matrix results in a vector.
709 */
710 const unsigned column = idx->value.u[0];
711
712 const glsl_type *const column_type = array->type->column_type();
713
714 /* Offset in the constant matrix to the first element of the column
715 * to be extracted.
716 */
717 const unsigned mat_idx = column * column_type->vector_elements;
718
Ian Romanick0bb70a32010-06-11 15:49:49 -0700719 ir_constant_data data;
Ian Romanick9b92af92010-06-11 12:20:12 -0700720
721 switch (column_type->base_type) {
722 case GLSL_TYPE_UINT:
723 case GLSL_TYPE_INT:
724 for (unsigned i = 0; i < column_type->vector_elements; i++)
725 data.u[i] = array->value.u[mat_idx + i];
726
727 break;
728
729 case GLSL_TYPE_FLOAT:
730 for (unsigned i = 0; i < column_type->vector_elements; i++)
731 data.f[i] = array->value.f[mat_idx + i];
732
733 break;
734
735 default:
736 assert(!"Should not get here.");
737 break;
738 }
739
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700740 return new(ctx) ir_constant(column_type, &data);
Ian Romanick9b92af92010-06-11 12:20:12 -0700741 } else if (array->type->is_vector()) {
742 const unsigned component = idx->value.u[0];
743
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700744 return new(ctx) ir_constant(array, component);
Ian Romanick9b92af92010-06-11 12:20:12 -0700745 } else {
Kenneth Graunkea096fa72010-07-20 01:31:29 -0700746 const unsigned index = idx->value.u[0];
Eric Anholt8273bd42010-08-04 12:34:56 -0700747 return array->get_array_element(index)->clone(ctx, NULL);
Ian Romanick9b92af92010-06-11 12:20:12 -0700748 }
749 }
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700750 return NULL;
Ian Romanickc7b10462010-05-19 13:20:12 +0200751}
752
753
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700754ir_constant *
755ir_dereference_record::constant_expression_value()
Ian Romanickc7b10462010-05-19 13:20:12 +0200756{
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700757 ir_constant *v = this->record->constant_expression_value();
Ian Romanick253dede2010-06-09 17:30:19 -0700758
Kenneth Graunke98f32a12010-07-15 10:20:51 -0700759 return (v != NULL) ? v->get_record_field(this->field) : NULL;
Ian Romanick1cf43a42010-03-30 16:56:50 -0700760}
761
762
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700763ir_constant *
764ir_assignment::constant_expression_value()
Ian Romanick1cf43a42010-03-30 16:56:50 -0700765{
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700766 /* FINISHME: Handle CEs involving assignment (return RHS) */
767 return NULL;
Ian Romanick1cf43a42010-03-30 16:56:50 -0700768}
769
770
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700771ir_constant *
772ir_constant::constant_expression_value()
Ian Romanick1cf43a42010-03-30 16:56:50 -0700773{
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700774 return this;
Ian Romanick1cf43a42010-03-30 16:56:50 -0700775}
776
777
Kenneth Graunkefb2ffd22010-07-15 10:09:09 -0700778ir_constant *
779ir_call::constant_expression_value()
Ian Romanick1cf43a42010-03-30 16:56:50 -0700780{
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700781 if (this->type == glsl_type::error_type)
782 return NULL;
Ian Romanick1cf43a42010-03-30 16:56:50 -0700783
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700784 /* From the GLSL 1.20 spec, page 23:
785 * "Function calls to user-defined functions (non-built-in functions)
786 * cannot be used to form constant expressions."
787 */
788 if (!this->callee->is_built_in)
789 return NULL;
790
791 unsigned num_parameters = 0;
792
793 /* Check if all parameters are constant */
794 ir_constant *op[3];
795 foreach_list(n, &this->actual_parameters) {
796 ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value();
797 if (constant == NULL)
798 return NULL;
799
800 op[num_parameters] = constant;
801
802 assert(num_parameters < 3);
803 num_parameters++;
804 }
805
806 /* Individual cases below can either:
807 * - Assign "expr" a new ir_expression to evaluate (for basic opcodes)
808 * - Fill "data" with appopriate constant data
809 * - Return an ir_constant directly.
810 */
811 void *mem_ctx = talloc_parent(this);
812 ir_expression *expr = NULL;
813
814 ir_constant_data data;
815 memset(&data, 0, sizeof(data));
816
817 const char *callee = this->callee_name();
818 if (strcmp(callee, "abs") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700819 expr = new(mem_ctx) ir_expression(ir_unop_abs, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700820 } else if (strcmp(callee, "all") == 0) {
Kenneth Graunkeaca7e952010-07-21 17:34:32 -0700821 assert(op[0]->type->is_boolean());
822 for (unsigned c = 0; c < op[0]->type->components(); c++) {
823 if (!op[0]->value.b[c])
824 return new(mem_ctx) ir_constant(false);
825 }
826 return new(mem_ctx) ir_constant(true);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700827 } else if (strcmp(callee, "any") == 0) {
Kenneth Graunked6792a72010-07-21 17:35:52 -0700828 assert(op[0]->type->is_boolean());
829 for (unsigned c = 0; c < op[0]->type->components(); c++) {
830 if (op[0]->value.b[c])
831 return new(mem_ctx) ir_constant(true);
832 }
833 return new(mem_ctx) ir_constant(false);
Kenneth Graunkef6ea9df2010-07-21 17:39:47 -0700834 } else if (strcmp(callee, "acos") == 0) {
835 assert(op[0]->type->is_float());
836 for (unsigned c = 0; c < op[0]->type->components(); c++)
837 data.f[c] = acosf(op[0]->value.f[c]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700838 } else if (strcmp(callee, "asin") == 0) {
Kenneth Graunke3b6c29b2010-07-21 17:38:38 -0700839 assert(op[0]->type->is_float());
840 for (unsigned c = 0; c < op[0]->type->components(); c++)
841 data.f[c] = asinf(op[0]->value.f[c]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700842 } else if (strcmp(callee, "atan") == 0) {
Kenneth Graunke13f87582010-07-21 17:42:23 -0700843 assert(op[0]->type->is_float());
844 if (num_parameters == 2) {
845 assert(op[1]->type->is_float());
846 for (unsigned c = 0; c < op[0]->type->components(); c++)
847 data.f[c] = atan2f(op[0]->value.f[c], op[1]->value.f[c]);
848 } else {
849 for (unsigned c = 0; c < op[0]->type->components(); c++)
850 data.f[c] = atanf(op[0]->value.f[c]);
851 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700852 } else if (strcmp(callee, "dFdx") == 0 || strcmp(callee, "dFdy") == 0) {
Kenneth Graunke38cb1b22010-07-21 16:57:10 -0700853 return ir_constant::zero(mem_ctx, this->type);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700854 } else if (strcmp(callee, "ceil") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700855 expr = new(mem_ctx) ir_expression(ir_unop_ceil, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700856 } else if (strcmp(callee, "clamp") == 0) {
Kenneth Graunkea4ca1cf2010-07-21 22:23:17 -0700857 assert(num_parameters == 3);
858 unsigned c1_inc = op[1]->type->is_scalar() ? 0 : 1;
859 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
860 for (unsigned c = 0, c1 = 0, c2 = 0;
861 c < op[0]->type->components();
862 c1 += c1_inc, c2 += c2_inc, c++) {
863
864 switch (op[0]->type->base_type) {
865 case GLSL_TYPE_UINT:
866 data.u[c] = CLAMP(op[0]->value.u[c], op[1]->value.u[c1],
867 op[2]->value.u[c2]);
868 break;
869 case GLSL_TYPE_INT:
870 data.i[c] = CLAMP(op[0]->value.i[c], op[1]->value.i[c1],
Eric Anholtc8babd52010-08-02 17:49:01 -0700871 op[2]->value.i[c2]);
Kenneth Graunkea4ca1cf2010-07-21 22:23:17 -0700872 break;
873 case GLSL_TYPE_FLOAT:
874 data.f[c] = CLAMP(op[0]->value.f[c], op[1]->value.f[c1],
875 op[2]->value.f[c2]);
876 break;
877 default:
878 assert(!"Should not get here.");
879 }
880 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700881 } else if (strcmp(callee, "cos") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700882 expr = new(mem_ctx) ir_expression(ir_unop_cos, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700883 } else if (strcmp(callee, "cosh") == 0) {
Kenneth Graunkeba417832010-07-21 17:47:55 -0700884 assert(op[0]->type->is_float());
885 for (unsigned c = 0; c < op[0]->type->components(); c++)
886 data.f[c] = coshf(op[0]->value.f[c]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700887 } else if (strcmp(callee, "cross") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700888 expr = new(mem_ctx) ir_expression(ir_binop_cross, type, op[0], op[1]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700889 } else if (strcmp(callee, "degrees") == 0) {
Kenneth Graunke7bcaa382010-07-21 17:59:00 -0700890 assert(op[0]->type->is_float());
891 for (unsigned c = 0; c < op[0]->type->components(); c++)
892 data.f[c] = 180.0/M_PI * op[0]->value.f[c];
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700893 } else if (strcmp(callee, "distance") == 0) {
Kenneth Graunke2eaf3162010-07-21 18:01:22 -0700894 assert(op[0]->type->is_float() && op[1]->type->is_float());
895 float length_squared = 0.0;
896 for (unsigned c = 0; c < op[0]->type->components(); c++) {
897 float t = op[0]->value.f[c] - op[1]->value.f[c];
898 length_squared += t * t;
899 }
900 return new(mem_ctx) ir_constant(sqrtf(length_squared));
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700901 } else if (strcmp(callee, "dot") == 0) {
Kenneth Graunkea7650af2010-07-21 20:12:43 -0700902 return new(mem_ctx) ir_constant(dot(op[0], op[1]));
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700903 } else if (strcmp(callee, "equal") == 0) {
Kenneth Graunke0b6ef6e2010-07-21 18:04:22 -0700904 assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
905 for (unsigned c = 0; c < op[0]->type->components(); c++) {
906 switch (op[0]->type->base_type) {
907 case GLSL_TYPE_UINT:
908 data.b[c] = op[0]->value.u[c] == op[1]->value.u[c];
909 break;
910 case GLSL_TYPE_INT:
911 data.b[c] = op[0]->value.i[c] == op[1]->value.i[c];
912 break;
913 case GLSL_TYPE_FLOAT:
914 data.b[c] = op[0]->value.f[c] == op[1]->value.f[c];
915 break;
Kenneth Graunked12cb772010-08-18 12:06:25 -0700916 case GLSL_TYPE_BOOL:
917 data.b[c] = op[0]->value.b[c] == op[1]->value.b[c];
918 break;
Kenneth Graunke0b6ef6e2010-07-21 18:04:22 -0700919 default:
920 assert(!"Should not get here.");
921 }
922 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700923 } else if (strcmp(callee, "exp") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700924 expr = new(mem_ctx) ir_expression(ir_unop_exp, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700925 } else if (strcmp(callee, "exp2") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700926 expr = new(mem_ctx) ir_expression(ir_unop_exp2, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700927 } else if (strcmp(callee, "faceforward") == 0) {
Kenneth Graunke3d5c2f02010-07-21 21:46:16 -0700928 if (dot(op[2], op[1]) < 0)
929 return op[0];
930 for (unsigned c = 0; c < op[0]->type->components(); c++)
931 data.f[c] = -op[0]->value.f[c];
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700932 } else if (strcmp(callee, "floor") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700933 expr = new(mem_ctx) ir_expression(ir_unop_floor, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700934 } else if (strcmp(callee, "fract") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700935 expr = new(mem_ctx) ir_expression(ir_unop_fract, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700936 } else if (strcmp(callee, "fwidth") == 0) {
Kenneth Graunke38cb1b22010-07-21 16:57:10 -0700937 return ir_constant::zero(mem_ctx, this->type);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700938 } else if (strcmp(callee, "greaterThan") == 0) {
Kenneth Graunke7f042b92010-07-21 18:07:43 -0700939 assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
940 for (unsigned c = 0; c < op[0]->type->components(); c++) {
941 switch (op[0]->type->base_type) {
942 case GLSL_TYPE_UINT:
943 data.b[c] = op[0]->value.u[c] > op[1]->value.u[c];
944 break;
945 case GLSL_TYPE_INT:
946 data.b[c] = op[0]->value.i[c] > op[1]->value.i[c];
947 break;
948 case GLSL_TYPE_FLOAT:
949 data.b[c] = op[0]->value.f[c] > op[1]->value.f[c];
950 break;
951 default:
952 assert(!"Should not get here.");
953 }
954 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700955 } else if (strcmp(callee, "greaterThanEqual") == 0) {
Kenneth Graunke55782732010-07-21 18:08:05 -0700956 assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
957 for (unsigned c = 0; c < op[0]->type->components(); c++) {
958 switch (op[0]->type->base_type) {
959 case GLSL_TYPE_UINT:
960 data.b[c] = op[0]->value.u[c] >= op[1]->value.u[c];
961 break;
962 case GLSL_TYPE_INT:
963 data.b[c] = op[0]->value.i[c] >= op[1]->value.i[c];
964 break;
965 case GLSL_TYPE_FLOAT:
966 data.b[c] = op[0]->value.f[c] >= op[1]->value.f[c];
967 break;
968 default:
969 assert(!"Should not get here.");
970 }
971 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700972 } else if (strcmp(callee, "inversesqrt") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -0700973 expr = new(mem_ctx) ir_expression(ir_unop_rsq, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700974 } else if (strcmp(callee, "length") == 0) {
Kenneth Graunke5489ad02010-07-21 18:26:00 -0700975 return new(mem_ctx) ir_constant(sqrtf(dot(op[0], op[0])));
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700976 } else if (strcmp(callee, "lessThan") == 0) {
Kenneth Graunke6d897f02010-07-21 18:06:18 -0700977 assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
978 for (unsigned c = 0; c < op[0]->type->components(); c++) {
979 switch (op[0]->type->base_type) {
980 case GLSL_TYPE_UINT:
981 data.b[c] = op[0]->value.u[c] < op[1]->value.u[c];
982 break;
983 case GLSL_TYPE_INT:
984 data.b[c] = op[0]->value.i[c] < op[1]->value.i[c];
985 break;
986 case GLSL_TYPE_FLOAT:
987 data.b[c] = op[0]->value.f[c] < op[1]->value.f[c];
988 break;
989 default:
990 assert(!"Should not get here.");
991 }
992 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -0700993 } else if (strcmp(callee, "lessThanEqual") == 0) {
Kenneth Graunke319f4942010-07-21 18:07:09 -0700994 assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
995 for (unsigned c = 0; c < op[0]->type->components(); c++) {
996 switch (op[0]->type->base_type) {
997 case GLSL_TYPE_UINT:
998 data.b[c] = op[0]->value.u[c] <= op[1]->value.u[c];
999 break;
1000 case GLSL_TYPE_INT:
1001 data.b[c] = op[0]->value.i[c] <= op[1]->value.i[c];
1002 break;
1003 case GLSL_TYPE_FLOAT:
1004 data.b[c] = op[0]->value.f[c] <= op[1]->value.f[c];
1005 break;
1006 default:
1007 assert(!"Should not get here.");
1008 }
1009 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001010 } else if (strcmp(callee, "log") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001011 expr = new(mem_ctx) ir_expression(ir_unop_log, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001012 } else if (strcmp(callee, "log2") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001013 expr = new(mem_ctx) ir_expression(ir_unop_log2, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001014 } else if (strcmp(callee, "matrixCompMult") == 0) {
Kenneth Graunke8fe5f302010-07-21 20:03:55 -07001015 assert(op[0]->type->is_float() && op[1]->type->is_float());
1016 for (unsigned c = 0; c < op[0]->type->components(); c++)
1017 data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001018 } else if (strcmp(callee, "max") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001019 expr = new(mem_ctx) ir_expression(ir_binop_max, type, op[0], op[1]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001020 } else if (strcmp(callee, "min") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001021 expr = new(mem_ctx) ir_expression(ir_binop_min, type, op[0], op[1]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001022 } else if (strcmp(callee, "mix") == 0) {
Kenneth Graunke5d255e22010-07-23 12:36:50 -07001023 assert(op[0]->type->is_float() && op[1]->type->is_float());
1024 if (op[2]->type->is_float()) {
1025 unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
1026 unsigned components = op[0]->type->components();
1027 for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
1028 data.f[c] = op[0]->value.f[c] * (1 - op[2]->value.f[c2]) +
1029 op[1]->value.f[c] * op[2]->value.f[c2];
1030 }
1031 } else {
1032 assert(op[2]->type->is_boolean());
1033 for (unsigned c = 0; c < op[0]->type->components(); c++)
1034 data.f[c] = op[op[2]->value.b[c] ? 1 : 0]->value.f[c];
1035 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001036 } else if (strcmp(callee, "mod") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001037 expr = new(mem_ctx) ir_expression(ir_binop_mod, type, op[0], op[1]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001038 } else if (strcmp(callee, "normalize") == 0) {
Kenneth Graunke53f306d2010-07-21 20:19:32 -07001039 assert(op[0]->type->is_float());
1040 float length = sqrtf(dot(op[0], op[0]));
1041
1042 if (length == 0)
1043 return ir_constant::zero(mem_ctx, this->type);
1044
1045 for (unsigned c = 0; c < op[0]->type->components(); c++)
1046 data.f[c] = op[0]->value.f[c] / length;
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001047 } else if (strcmp(callee, "not") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001048 expr = new(mem_ctx) ir_expression(ir_unop_logic_not, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001049 } else if (strcmp(callee, "notEqual") == 0) {
Kenneth Graunke48a69ba2010-07-21 18:05:36 -07001050 assert(op[0]->type->is_vector() && op[1] && op[1]->type->is_vector());
1051 for (unsigned c = 0; c < op[0]->type->components(); c++) {
1052 switch (op[0]->type->base_type) {
1053 case GLSL_TYPE_UINT:
1054 data.b[c] = op[0]->value.u[c] != op[1]->value.u[c];
1055 break;
1056 case GLSL_TYPE_INT:
1057 data.b[c] = op[0]->value.i[c] != op[1]->value.i[c];
1058 break;
1059 case GLSL_TYPE_FLOAT:
1060 data.b[c] = op[0]->value.f[c] != op[1]->value.f[c];
1061 break;
Kenneth Graunked12cb772010-08-18 12:06:25 -07001062 case GLSL_TYPE_BOOL:
1063 data.b[c] = op[0]->value.b[c] != op[1]->value.b[c];
1064 break;
Kenneth Graunke48a69ba2010-07-21 18:05:36 -07001065 default:
1066 assert(!"Should not get here.");
1067 }
1068 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001069 } else if (strcmp(callee, "outerProduct") == 0) {
Kenneth Graunke7ddee6a2010-07-23 13:24:09 -07001070 assert(op[0]->type->is_vector() && op[1]->type->is_vector());
1071 const unsigned m = op[0]->type->vector_elements;
1072 const unsigned n = op[1]->type->vector_elements;
1073 for (unsigned j = 0; j < n; j++) {
1074 for (unsigned i = 0; i < m; i++) {
1075 data.f[i+m*j] = op[0]->value.f[i] * op[1]->value.f[j];
1076 }
1077 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001078 } else if (strcmp(callee, "pow") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001079 expr = new(mem_ctx) ir_expression(ir_binop_pow, type, op[0], op[1]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001080 } else if (strcmp(callee, "radians") == 0) {
Kenneth Graunke0afe3492010-07-21 17:58:03 -07001081 assert(op[0]->type->is_float());
1082 for (unsigned c = 0; c < op[0]->type->components(); c++)
1083 data.f[c] = M_PI/180.0 * op[0]->value.f[c];
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001084 } else if (strcmp(callee, "reflect") == 0) {
Kenneth Graunked60b2b02010-07-21 20:24:29 -07001085 assert(op[0]->type->is_float());
1086 float dot_NI = dot(op[1], op[0]);
1087 for (unsigned c = 0; c < op[0]->type->components(); c++)
1088 data.f[c] = op[0]->value.f[c] - 2 * dot_NI * op[1]->value.f[c];
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001089 } else if (strcmp(callee, "refract") == 0) {
Kenneth Graunke04b36432010-07-21 20:33:42 -07001090 const float eta = op[2]->value.f[0];
1091 const float dot_NI = dot(op[1], op[0]);
1092 const float k = 1.0 - eta * eta * (1.0 - dot_NI * dot_NI);
1093 if (k < 0.0) {
1094 return ir_constant::zero(mem_ctx, this->type);
1095 } else {
1096 for (unsigned c = 0; c < type->components(); c++) {
1097 data.f[c] = eta * op[0]->value.f[c] - (eta * dot_NI + sqrtf(k))
1098 * op[1]->value.f[c];
1099 }
1100 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001101 } else if (strcmp(callee, "sign") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001102 expr = new(mem_ctx) ir_expression(ir_unop_sign, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001103 } else if (strcmp(callee, "sin") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001104 expr = new(mem_ctx) ir_expression(ir_unop_sin, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001105 } else if (strcmp(callee, "sinh") == 0) {
Kenneth Graunke5d551da2010-07-21 17:49:56 -07001106 assert(op[0]->type->is_float());
1107 for (unsigned c = 0; c < op[0]->type->components(); c++)
1108 data.f[c] = sinhf(op[0]->value.f[c]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001109 } else if (strcmp(callee, "smoothstep") == 0) {
Kenneth Graunke546f3a22010-07-21 22:37:50 -07001110 assert(num_parameters == 3);
1111 assert(op[1]->type == op[0]->type);
1112 unsigned edge_inc = op[0]->type->is_scalar() ? 0 : 1;
1113 for (unsigned c = 0, e = 0; c < type->components(); e += edge_inc, c++) {
1114 const float edge0 = op[0]->value.f[e];
1115 const float edge1 = op[1]->value.f[e];
1116 if (edge0 == edge1) {
1117 data.f[c] = 0.0; /* Avoid a crash - results are undefined anyway */
1118 } else {
1119 const float numerator = op[2]->value.f[c] - edge0;
1120 const float denominator = edge1 - edge0;
1121 const float t = CLAMP(numerator/denominator, 0, 1);
1122 data.f[c] = t * t * (3 - 2 * t);
1123 }
1124 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001125 } else if (strcmp(callee, "sqrt") == 0) {
Kenneth Graunke8b1680a2010-07-21 16:57:53 -07001126 expr = new(mem_ctx) ir_expression(ir_unop_sqrt, type, op[0], NULL);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001127 } else if (strcmp(callee, "step") == 0) {
Kenneth Graunkeff58b7c2010-07-21 21:53:40 -07001128 assert(op[0]->type->is_float() && op[1]->type->is_float());
1129 /* op[0] (edge) may be either a scalar or a vector */
1130 const unsigned c0_inc = op[0]->type->is_scalar() ? 0 : 1;
1131 for (unsigned c = 0, c0 = 0; c < type->components(); c0 += c0_inc, c++)
1132 data.f[c] = (op[1]->value.f[c] < op[0]->value.f[c0]) ? 0.0 : 1.0;
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001133 } else if (strcmp(callee, "tan") == 0) {
Kenneth Graunke9c9f8b22010-07-21 17:50:50 -07001134 assert(op[0]->type->is_float());
1135 for (unsigned c = 0; c < op[0]->type->components(); c++)
1136 data.f[c] = tanf(op[0]->value.f[c]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001137 } else if (strcmp(callee, "tanh") == 0) {
Kenneth Graunke20970f72010-07-21 17:51:23 -07001138 assert(op[0]->type->is_float());
1139 for (unsigned c = 0; c < op[0]->type->components(); c++)
1140 data.f[c] = tanhf(op[0]->value.f[c]);
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001141 } else if (strcmp(callee, "transpose") == 0) {
Kenneth Graunkeb09ae5d2010-07-22 15:34:49 -07001142 assert(op[0]->type->is_matrix());
1143 const unsigned n = op[0]->type->vector_elements;
1144 const unsigned m = op[0]->type->matrix_columns;
1145 for (unsigned j = 0; j < m; j++) {
1146 for (unsigned i = 0; i < n; i++) {
1147 data.f[m*i+j] += op[0]->value.f[i+n*j];
1148 }
1149 }
Kenneth Graunkebafd89f2010-07-21 16:55:46 -07001150 } else {
1151 /* Unsupported builtin - some are not allowed in constant expressions. */
1152 return NULL;
1153 }
1154
1155 if (expr != NULL)
1156 return expr->constant_expression_value();
1157
1158 return new(mem_ctx) ir_constant(this->type, &data);
1159}