Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 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 | |||
24 | #include "glsl_symbol_table.h" |
||
25 | #include "ast.h" |
||
26 | #include "glsl_types.h" |
||
27 | #include "ir.h" |
||
28 | #include "main/core.h" /* for MIN2 */ |
||
29 | |||
30 | static ir_rvalue * |
||
31 | convert_component(ir_rvalue *src, const glsl_type *desired_type); |
||
32 | |||
33 | bool |
||
34 | apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, |
||
35 | struct _mesa_glsl_parse_state *state); |
||
36 | |||
37 | static unsigned |
||
38 | process_parameters(exec_list *instructions, exec_list *actual_parameters, |
||
39 | exec_list *parameters, |
||
40 | struct _mesa_glsl_parse_state *state) |
||
41 | { |
||
42 | unsigned count = 0; |
||
43 | |||
44 | foreach_list_typed(ast_node, ast, link, parameters) { |
||
45 | ir_rvalue *result = ast->hir(instructions, state); |
||
46 | |||
47 | ir_constant *const constant = result->constant_expression_value(); |
||
48 | if (constant != NULL) |
||
49 | result = constant; |
||
50 | |||
51 | actual_parameters->push_tail(result); |
||
52 | count++; |
||
53 | } |
||
54 | |||
55 | return count; |
||
56 | } |
||
57 | |||
58 | |||
59 | /** |
||
60 | * Generate a source prototype for a function signature |
||
61 | * |
||
62 | * \param return_type Return type of the function. May be \c NULL. |
||
63 | * \param name Name of the function. |
||
64 | * \param parameters List of \c ir_instruction nodes representing the |
||
65 | * parameter list for the function. This may be either a |
||
66 | * formal (\c ir_variable) or actual (\c ir_rvalue) |
||
67 | * parameter list. Only the type is used. |
||
68 | * |
||
69 | * \return |
||
70 | * A ralloced string representing the prototype of the function. |
||
71 | */ |
||
72 | char * |
||
73 | prototype_string(const glsl_type *return_type, const char *name, |
||
74 | exec_list *parameters) |
||
75 | { |
||
76 | char *str = NULL; |
||
77 | |||
78 | if (return_type != NULL) |
||
79 | str = ralloc_asprintf(NULL, "%s ", return_type->name); |
||
80 | |||
81 | ralloc_asprintf_append(&str, "%s(", name); |
||
82 | |||
83 | const char *comma = ""; |
||
84 | foreach_in_list(const ir_variable, param, parameters) { |
||
85 | ralloc_asprintf_append(&str, "%s%s", comma, param->type->name); |
||
86 | comma = ", "; |
||
87 | } |
||
88 | |||
89 | ralloc_strcat(&str, ")"); |
||
90 | return str; |
||
91 | } |
||
92 | |||
93 | static bool |
||
94 | verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state, |
||
95 | const ir_variable *formal, const ir_variable *actual) |
||
96 | { |
||
97 | /** |
||
98 | * From the ARB_shader_image_load_store specification: |
||
99 | * |
||
100 | * "The values of image variables qualified with coherent, |
||
101 | * volatile, restrict, readonly, or writeonly may not be passed |
||
102 | * to functions whose formal parameters lack such |
||
103 | * qualifiers. [...] It is legal to have additional qualifiers |
||
104 | * on a formal parameter, but not to have fewer." |
||
105 | */ |
||
106 | if (actual->data.image_coherent && !formal->data.image_coherent) { |
||
107 | _mesa_glsl_error(loc, state, |
||
108 | "function call parameter `%s' drops " |
||
109 | "`coherent' qualifier", formal->name); |
||
110 | return false; |
||
111 | } |
||
112 | |||
113 | if (actual->data.image_volatile && !formal->data.image_volatile) { |
||
114 | _mesa_glsl_error(loc, state, |
||
115 | "function call parameter `%s' drops " |
||
116 | "`volatile' qualifier", formal->name); |
||
117 | return false; |
||
118 | } |
||
119 | |||
120 | if (actual->data.image_restrict && !formal->data.image_restrict) { |
||
121 | _mesa_glsl_error(loc, state, |
||
122 | "function call parameter `%s' drops " |
||
123 | "`restrict' qualifier", formal->name); |
||
124 | return false; |
||
125 | } |
||
126 | |||
127 | if (actual->data.image_read_only && !formal->data.image_read_only) { |
||
128 | _mesa_glsl_error(loc, state, |
||
129 | "function call parameter `%s' drops " |
||
130 | "`readonly' qualifier", formal->name); |
||
131 | return false; |
||
132 | } |
||
133 | |||
134 | if (actual->data.image_write_only && !formal->data.image_write_only) { |
||
135 | _mesa_glsl_error(loc, state, |
||
136 | "function call parameter `%s' drops " |
||
137 | "`writeonly' qualifier", formal->name); |
||
138 | return false; |
||
139 | } |
||
140 | |||
141 | return true; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Verify that 'out' and 'inout' actual parameters are lvalues. Also, verify |
||
146 | * that 'const_in' formal parameters (an extension in our IR) correspond to |
||
147 | * ir_constant actual parameters. |
||
148 | */ |
||
149 | static bool |
||
150 | verify_parameter_modes(_mesa_glsl_parse_state *state, |
||
151 | ir_function_signature *sig, |
||
152 | exec_list &actual_ir_parameters, |
||
153 | exec_list &actual_ast_parameters) |
||
154 | { |
||
155 | exec_node *actual_ir_node = actual_ir_parameters.head; |
||
156 | exec_node *actual_ast_node = actual_ast_parameters.head; |
||
157 | |||
158 | foreach_in_list(const ir_variable, formal, &sig->parameters) { |
||
159 | /* The lists must be the same length. */ |
||
160 | assert(!actual_ir_node->is_tail_sentinel()); |
||
161 | assert(!actual_ast_node->is_tail_sentinel()); |
||
162 | |||
163 | const ir_rvalue *const actual = (ir_rvalue *) actual_ir_node; |
||
164 | const ast_expression *const actual_ast = |
||
165 | exec_node_data(ast_expression, actual_ast_node, link); |
||
166 | |||
167 | /* FIXME: 'loc' is incorrect (as of 2011-01-21). It is always |
||
168 | * FIXME: 0:0(0). |
||
169 | */ |
||
170 | YYLTYPE loc = actual_ast->get_location(); |
||
171 | |||
172 | /* Verify that 'const_in' parameters are ir_constants. */ |
||
173 | if (formal->data.mode == ir_var_const_in && |
||
174 | actual->ir_type != ir_type_constant) { |
||
175 | _mesa_glsl_error(&loc, state, |
||
176 | "parameter `in %s' must be a constant expression", |
||
177 | formal->name); |
||
178 | return false; |
||
179 | } |
||
180 | |||
181 | /* Verify that shader_in parameters are shader inputs */ |
||
182 | if (formal->data.must_be_shader_input) { |
||
183 | ir_variable *var = actual->variable_referenced(); |
||
184 | if (var && var->data.mode != ir_var_shader_in) { |
||
185 | _mesa_glsl_error(&loc, state, |
||
186 | "parameter `%s` must be a shader input", |
||
187 | formal->name); |
||
188 | return false; |
||
189 | } |
||
190 | |||
191 | if (actual->ir_type == ir_type_swizzle) { |
||
192 | _mesa_glsl_error(&loc, state, |
||
193 | "parameter `%s` must not be swizzled", |
||
194 | formal->name); |
||
195 | return false; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | /* Verify that 'out' and 'inout' actual parameters are lvalues. */ |
||
200 | if (formal->data.mode == ir_var_function_out |
||
201 | || formal->data.mode == ir_var_function_inout) { |
||
202 | const char *mode = NULL; |
||
203 | switch (formal->data.mode) { |
||
204 | case ir_var_function_out: mode = "out"; break; |
||
205 | case ir_var_function_inout: mode = "inout"; break; |
||
206 | default: assert(false); break; |
||
207 | } |
||
208 | |||
209 | /* This AST-based check catches errors like f(i++). The IR-based |
||
210 | * is_lvalue() is insufficient because the actual parameter at the |
||
211 | * IR-level is just a temporary value, which is an l-value. |
||
212 | */ |
||
213 | if (actual_ast->non_lvalue_description != NULL) { |
||
214 | _mesa_glsl_error(&loc, state, |
||
215 | "function parameter '%s %s' references a %s", |
||
216 | mode, formal->name, |
||
217 | actual_ast->non_lvalue_description); |
||
218 | return false; |
||
219 | } |
||
220 | |||
221 | ir_variable *var = actual->variable_referenced(); |
||
222 | if (var) |
||
223 | var->data.assigned = true; |
||
224 | |||
225 | if (var && var->data.read_only) { |
||
226 | _mesa_glsl_error(&loc, state, |
||
227 | "function parameter '%s %s' references the " |
||
228 | "read-only variable '%s'", |
||
229 | mode, formal->name, |
||
230 | actual->variable_referenced()->name); |
||
231 | return false; |
||
232 | } else if (!actual->is_lvalue()) { |
||
233 | /* Even though ir_binop_vector_extract is not an l-value, let it |
||
234 | * slop through. generate_call will handle it correctly. |
||
235 | */ |
||
236 | ir_expression *const expr = ((ir_rvalue *) actual)->as_expression(); |
||
237 | if (expr == NULL |
||
238 | || expr->operation != ir_binop_vector_extract |
||
239 | || !expr->operands[0]->is_lvalue()) { |
||
240 | _mesa_glsl_error(&loc, state, |
||
241 | "function parameter '%s %s' is not an lvalue", |
||
242 | mode, formal->name); |
||
243 | return false; |
||
244 | } |
||
245 | } |
||
246 | } |
||
247 | |||
248 | if (formal->type->is_image() && |
||
249 | actual->variable_referenced()) { |
||
250 | if (!verify_image_parameter(&loc, state, formal, |
||
251 | actual->variable_referenced())) |
||
252 | return false; |
||
253 | } |
||
254 | |||
255 | actual_ir_node = actual_ir_node->next; |
||
256 | actual_ast_node = actual_ast_node->next; |
||
257 | } |
||
258 | return true; |
||
259 | } |
||
260 | |||
261 | static void |
||
262 | fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type, |
||
263 | exec_list *before_instructions, exec_list *after_instructions, |
||
264 | bool parameter_is_inout) |
||
265 | { |
||
266 | ir_expression *const expr = actual->as_expression(); |
||
267 | |||
268 | /* If the types match exactly and the parameter is not a vector-extract, |
||
269 | * nothing needs to be done to fix the parameter. |
||
270 | */ |
||
271 | if (formal_type == actual->type |
||
272 | && (expr == NULL || expr->operation != ir_binop_vector_extract)) |
||
273 | return; |
||
274 | |||
275 | /* To convert an out parameter, we need to create a temporary variable to |
||
276 | * hold the value before conversion, and then perform the conversion after |
||
277 | * the function call returns. |
||
278 | * |
||
279 | * This has the effect of transforming code like this: |
||
280 | * |
||
281 | * void f(out int x); |
||
282 | * float value; |
||
283 | * f(value); |
||
284 | * |
||
285 | * Into IR that's equivalent to this: |
||
286 | * |
||
287 | * void f(out int x); |
||
288 | * float value; |
||
289 | * int out_parameter_conversion; |
||
290 | * f(out_parameter_conversion); |
||
291 | * value = float(out_parameter_conversion); |
||
292 | * |
||
293 | * If the parameter is an ir_expression of ir_binop_vector_extract, |
||
294 | * additional conversion is needed in the post-call re-write. |
||
295 | */ |
||
296 | ir_variable *tmp = |
||
297 | new(mem_ctx) ir_variable(formal_type, "inout_tmp", ir_var_temporary); |
||
298 | |||
299 | before_instructions->push_tail(tmp); |
||
300 | |||
301 | /* If the parameter is an inout parameter, copy the value of the actual |
||
302 | * parameter to the new temporary. Note that no type conversion is allowed |
||
303 | * here because inout parameters must match types exactly. |
||
304 | */ |
||
305 | if (parameter_is_inout) { |
||
306 | /* Inout parameters should never require conversion, since that would |
||
307 | * require an implicit conversion to exist both to and from the formal |
||
308 | * parameter type, and there are no bidirectional implicit conversions. |
||
309 | */ |
||
310 | assert (actual->type == formal_type); |
||
311 | |||
312 | ir_dereference_variable *const deref_tmp_1 = |
||
313 | new(mem_ctx) ir_dereference_variable(tmp); |
||
314 | ir_assignment *const assignment = |
||
315 | new(mem_ctx) ir_assignment(deref_tmp_1, actual); |
||
316 | before_instructions->push_tail(assignment); |
||
317 | } |
||
318 | |||
319 | /* Replace the parameter in the call with a dereference of the new |
||
320 | * temporary. |
||
321 | */ |
||
322 | ir_dereference_variable *const deref_tmp_2 = |
||
323 | new(mem_ctx) ir_dereference_variable(tmp); |
||
324 | actual->replace_with(deref_tmp_2); |
||
325 | |||
326 | |||
327 | /* Copy the temporary variable to the actual parameter with optional |
||
328 | * type conversion applied. |
||
329 | */ |
||
330 | ir_rvalue *rhs = new(mem_ctx) ir_dereference_variable(tmp); |
||
331 | if (actual->type != formal_type) |
||
332 | rhs = convert_component(rhs, actual->type); |
||
333 | |||
334 | ir_rvalue *lhs = actual; |
||
335 | if (expr != NULL && expr->operation == ir_binop_vector_extract) { |
||
336 | rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert, |
||
337 | expr->operands[0]->type, |
||
338 | expr->operands[0]->clone(mem_ctx, NULL), |
||
339 | rhs, |
||
340 | expr->operands[1]->clone(mem_ctx, NULL)); |
||
341 | lhs = expr->operands[0]->clone(mem_ctx, NULL); |
||
342 | } |
||
343 | |||
344 | ir_assignment *const assignment_2 = new(mem_ctx) ir_assignment(lhs, rhs); |
||
345 | after_instructions->push_tail(assignment_2); |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * Generate a function call. |
||
350 | * |
||
351 | * For non-void functions, this returns a dereference of the temporary variable |
||
352 | * which stores the return value for the call. For void functions, this returns |
||
353 | * NULL. |
||
354 | */ |
||
355 | static ir_rvalue * |
||
356 | generate_call(exec_list *instructions, ir_function_signature *sig, |
||
357 | exec_list *actual_parameters, |
||
358 | struct _mesa_glsl_parse_state *state) |
||
359 | { |
||
360 | void *ctx = state; |
||
361 | exec_list post_call_conversions; |
||
362 | |||
363 | /* Perform implicit conversion of arguments. For out parameters, we need |
||
364 | * to place them in a temporary variable and do the conversion after the |
||
365 | * call takes place. Since we haven't emitted the call yet, we'll place |
||
366 | * the post-call conversions in a temporary exec_list, and emit them later. |
||
367 | */ |
||
368 | foreach_two_lists(formal_node, &sig->parameters, |
||
369 | actual_node, actual_parameters) { |
||
370 | ir_rvalue *actual = (ir_rvalue *) actual_node; |
||
371 | ir_variable *formal = (ir_variable *) formal_node; |
||
372 | |||
373 | if (formal->type->is_numeric() || formal->type->is_boolean()) { |
||
374 | switch (formal->data.mode) { |
||
375 | case ir_var_const_in: |
||
376 | case ir_var_function_in: { |
||
377 | ir_rvalue *converted |
||
378 | = convert_component(actual, formal->type); |
||
379 | actual->replace_with(converted); |
||
380 | break; |
||
381 | } |
||
382 | case ir_var_function_out: |
||
383 | case ir_var_function_inout: |
||
384 | fix_parameter(ctx, actual, formal->type, |
||
385 | instructions, &post_call_conversions, |
||
386 | formal->data.mode == ir_var_function_inout); |
||
387 | break; |
||
388 | default: |
||
389 | assert (!"Illegal formal parameter mode"); |
||
390 | break; |
||
391 | } |
||
392 | } |
||
393 | } |
||
394 | |||
395 | /* If the function call is a constant expression, don't generate any |
||
396 | * instructions; just generate an ir_constant. |
||
397 | * |
||
398 | * Function calls were first allowed to be constant expressions in GLSL |
||
399 | * 1.20 and GLSL ES 3.00. |
||
400 | */ |
||
401 | if (state->is_version(120, 300)) { |
||
402 | ir_constant *value = sig->constant_expression_value(actual_parameters, NULL); |
||
403 | if (value != NULL) { |
||
404 | return value; |
||
405 | } |
||
406 | } |
||
407 | |||
408 | ir_dereference_variable *deref = NULL; |
||
409 | if (!sig->return_type->is_void()) { |
||
410 | /* Create a new temporary to hold the return value. */ |
||
411 | char *const name = ir_variable::temporaries_allocate_names |
||
412 | ? ralloc_asprintf(ctx, "%s_retval", sig->function_name()) |
||
413 | : NULL; |
||
414 | |||
415 | ir_variable *var; |
||
416 | |||
417 | var = new(ctx) ir_variable(sig->return_type, name, ir_var_temporary); |
||
418 | instructions->push_tail(var); |
||
419 | |||
420 | ralloc_free(name); |
||
421 | |||
422 | deref = new(ctx) ir_dereference_variable(var); |
||
423 | } |
||
424 | ir_call *call = new(ctx) ir_call(sig, deref, actual_parameters); |
||
425 | instructions->push_tail(call); |
||
426 | |||
427 | /* Also emit any necessary out-parameter conversions. */ |
||
428 | instructions->append_list(&post_call_conversions); |
||
429 | |||
430 | return deref ? deref->clone(ctx, NULL) : NULL; |
||
431 | } |
||
432 | |||
433 | /** |
||
434 | * Given a function name and parameter list, find the matching signature. |
||
435 | */ |
||
436 | static ir_function_signature * |
||
437 | match_function_by_name(const char *name, |
||
438 | exec_list *actual_parameters, |
||
439 | struct _mesa_glsl_parse_state *state) |
||
440 | { |
||
441 | void *ctx = state; |
||
442 | ir_function *f = state->symbols->get_function(name); |
||
443 | ir_function_signature *local_sig = NULL; |
||
444 | ir_function_signature *sig = NULL; |
||
445 | |||
446 | /* Is the function hidden by a record type constructor? */ |
||
447 | if (state->symbols->get_type(name)) |
||
448 | goto done; /* no match */ |
||
449 | |||
450 | /* Is the function hidden by a variable (impossible in 1.10)? */ |
||
451 | if (!state->symbols->separate_function_namespace |
||
452 | && state->symbols->get_variable(name)) |
||
453 | goto done; /* no match */ |
||
454 | |||
455 | if (f != NULL) { |
||
456 | /* In desktop GL, the presence of a user-defined signature hides any |
||
457 | * built-in signatures, so we must ignore them. In contrast, in ES2 |
||
458 | * user-defined signatures add new overloads, so we must consider them. |
||
459 | */ |
||
460 | bool allow_builtins = state->es_shader || !f->has_user_signature(); |
||
461 | |||
462 | /* Look for a match in the local shader. If exact, we're done. */ |
||
463 | bool is_exact = false; |
||
464 | sig = local_sig = f->matching_signature(state, actual_parameters, |
||
465 | allow_builtins, &is_exact); |
||
466 | if (is_exact) |
||
467 | goto done; |
||
468 | |||
469 | if (!allow_builtins) |
||
470 | goto done; |
||
471 | } |
||
472 | |||
473 | /* Local shader has no exact candidates; check the built-ins. */ |
||
474 | _mesa_glsl_initialize_builtin_functions(); |
||
475 | sig = _mesa_glsl_find_builtin_function(state, name, actual_parameters); |
||
476 | |||
477 | done: |
||
478 | if (sig != NULL) { |
||
479 | /* If the match is from a linked built-in shader, import the prototype. */ |
||
480 | if (sig != local_sig) { |
||
481 | if (f == NULL) { |
||
482 | f = new(ctx) ir_function(name); |
||
483 | state->symbols->add_global_function(f); |
||
484 | emit_function(state, f); |
||
485 | } |
||
486 | f->add_signature(sig->clone_prototype(f, NULL)); |
||
487 | } |
||
488 | } |
||
489 | return sig; |
||
490 | } |
||
491 | |||
492 | static void |
||
493 | print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc, |
||
494 | ir_function *f) |
||
495 | { |
||
496 | if (f == NULL) |
||
497 | return; |
||
498 | |||
499 | foreach_in_list(ir_function_signature, sig, &f->signatures) { |
||
500 | if (sig->is_builtin() && !sig->is_builtin_available(state)) |
||
501 | continue; |
||
502 | |||
503 | char *str = prototype_string(sig->return_type, f->name, &sig->parameters); |
||
504 | _mesa_glsl_error(loc, state, " %s", str); |
||
505 | ralloc_free(str); |
||
506 | } |
||
507 | } |
||
508 | |||
509 | /** |
||
510 | * Raise a "no matching function" error, listing all possible overloads the |
||
511 | * compiler considered so developers can figure out what went wrong. |
||
512 | */ |
||
513 | static void |
||
514 | no_matching_function_error(const char *name, |
||
515 | YYLTYPE *loc, |
||
516 | exec_list *actual_parameters, |
||
517 | _mesa_glsl_parse_state *state) |
||
518 | { |
||
519 | gl_shader *sh = _mesa_glsl_get_builtin_function_shader(); |
||
520 | |||
521 | if (state->symbols->get_function(name) == NULL |
||
522 | && (!state->uses_builtin_functions |
||
523 | || sh->symbols->get_function(name) == NULL)) { |
||
524 | _mesa_glsl_error(loc, state, "no function with name '%s'", name); |
||
525 | } else { |
||
526 | char *str = prototype_string(NULL, name, actual_parameters); |
||
527 | _mesa_glsl_error(loc, state, |
||
528 | "no matching function for call to `%s'; candidates are:", |
||
529 | str); |
||
530 | ralloc_free(str); |
||
531 | |||
532 | print_function_prototypes(state, loc, state->symbols->get_function(name)); |
||
533 | |||
534 | if (state->uses_builtin_functions) { |
||
535 | print_function_prototypes(state, loc, sh->symbols->get_function(name)); |
||
536 | } |
||
537 | } |
||
538 | } |
||
539 | |||
540 | /** |
||
541 | * Perform automatic type conversion of constructor parameters |
||
542 | * |
||
543 | * This implements the rules in the "Conversion and Scalar Constructors" |
||
544 | * section (GLSL 1.10 section 5.4.1), not the "Implicit Conversions" rules. |
||
545 | */ |
||
546 | static ir_rvalue * |
||
547 | convert_component(ir_rvalue *src, const glsl_type *desired_type) |
||
548 | { |
||
549 | void *ctx = ralloc_parent(src); |
||
550 | const unsigned a = desired_type->base_type; |
||
551 | const unsigned b = src->type->base_type; |
||
552 | ir_expression *result = NULL; |
||
553 | |||
554 | if (src->type->is_error()) |
||
555 | return src; |
||
556 | |||
557 | assert(a <= GLSL_TYPE_BOOL); |
||
558 | assert(b <= GLSL_TYPE_BOOL); |
||
559 | |||
560 | if (a == b) |
||
561 | return src; |
||
562 | |||
563 | switch (a) { |
||
564 | case GLSL_TYPE_UINT: |
||
565 | switch (b) { |
||
566 | case GLSL_TYPE_INT: |
||
567 | result = new(ctx) ir_expression(ir_unop_i2u, src); |
||
568 | break; |
||
569 | case GLSL_TYPE_FLOAT: |
||
570 | result = new(ctx) ir_expression(ir_unop_f2u, src); |
||
571 | break; |
||
572 | case GLSL_TYPE_BOOL: |
||
573 | result = new(ctx) ir_expression(ir_unop_i2u, |
||
574 | new(ctx) ir_expression(ir_unop_b2i, src)); |
||
575 | break; |
||
576 | case GLSL_TYPE_DOUBLE: |
||
577 | result = new(ctx) ir_expression(ir_unop_d2u, src); |
||
578 | break; |
||
579 | } |
||
580 | break; |
||
581 | case GLSL_TYPE_INT: |
||
582 | switch (b) { |
||
583 | case GLSL_TYPE_UINT: |
||
584 | result = new(ctx) ir_expression(ir_unop_u2i, src); |
||
585 | break; |
||
586 | case GLSL_TYPE_FLOAT: |
||
587 | result = new(ctx) ir_expression(ir_unop_f2i, src); |
||
588 | break; |
||
589 | case GLSL_TYPE_BOOL: |
||
590 | result = new(ctx) ir_expression(ir_unop_b2i, src); |
||
591 | break; |
||
592 | case GLSL_TYPE_DOUBLE: |
||
593 | result = new(ctx) ir_expression(ir_unop_d2i, src); |
||
594 | break; |
||
595 | } |
||
596 | break; |
||
597 | case GLSL_TYPE_FLOAT: |
||
598 | switch (b) { |
||
599 | case GLSL_TYPE_UINT: |
||
600 | result = new(ctx) ir_expression(ir_unop_u2f, desired_type, src, NULL); |
||
601 | break; |
||
602 | case GLSL_TYPE_INT: |
||
603 | result = new(ctx) ir_expression(ir_unop_i2f, desired_type, src, NULL); |
||
604 | break; |
||
605 | case GLSL_TYPE_BOOL: |
||
606 | result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL); |
||
607 | break; |
||
608 | case GLSL_TYPE_DOUBLE: |
||
609 | result = new(ctx) ir_expression(ir_unop_d2f, desired_type, src, NULL); |
||
610 | break; |
||
611 | } |
||
612 | break; |
||
613 | case GLSL_TYPE_BOOL: |
||
614 | switch (b) { |
||
615 | case GLSL_TYPE_UINT: |
||
616 | result = new(ctx) ir_expression(ir_unop_i2b, |
||
617 | new(ctx) ir_expression(ir_unop_u2i, src)); |
||
618 | break; |
||
619 | case GLSL_TYPE_INT: |
||
620 | result = new(ctx) ir_expression(ir_unop_i2b, desired_type, src, NULL); |
||
621 | break; |
||
622 | case GLSL_TYPE_FLOAT: |
||
623 | result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL); |
||
624 | break; |
||
625 | case GLSL_TYPE_DOUBLE: |
||
626 | result = new(ctx) ir_expression(ir_unop_d2b, desired_type, src, NULL); |
||
627 | break; |
||
628 | } |
||
629 | break; |
||
630 | case GLSL_TYPE_DOUBLE: |
||
631 | switch (b) { |
||
632 | case GLSL_TYPE_INT: |
||
633 | result = new(ctx) ir_expression(ir_unop_i2d, src); |
||
634 | break; |
||
635 | case GLSL_TYPE_UINT: |
||
636 | result = new(ctx) ir_expression(ir_unop_u2d, src); |
||
637 | break; |
||
638 | case GLSL_TYPE_BOOL: |
||
639 | result = new(ctx) ir_expression(ir_unop_f2d, |
||
640 | new(ctx) ir_expression(ir_unop_b2f, src)); |
||
641 | break; |
||
642 | case GLSL_TYPE_FLOAT: |
||
643 | result = new(ctx) ir_expression(ir_unop_f2d, desired_type, src, NULL); |
||
644 | break; |
||
645 | } |
||
646 | } |
||
647 | |||
648 | assert(result != NULL); |
||
649 | assert(result->type == desired_type); |
||
650 | |||
651 | /* Try constant folding; it may fold in the conversion we just added. */ |
||
652 | ir_constant *const constant = result->constant_expression_value(); |
||
653 | return (constant != NULL) ? (ir_rvalue *) constant : (ir_rvalue *) result; |
||
654 | } |
||
655 | |||
656 | /** |
||
657 | * Dereference a specific component from a scalar, vector, or matrix |
||
658 | */ |
||
659 | static ir_rvalue * |
||
660 | dereference_component(ir_rvalue *src, unsigned component) |
||
661 | { |
||
662 | void *ctx = ralloc_parent(src); |
||
663 | assert(component < src->type->components()); |
||
664 | |||
665 | /* If the source is a constant, just create a new constant instead of a |
||
666 | * dereference of the existing constant. |
||
667 | */ |
||
668 | ir_constant *constant = src->as_constant(); |
||
669 | if (constant) |
||
670 | return new(ctx) ir_constant(constant, component); |
||
671 | |||
672 | if (src->type->is_scalar()) { |
||
673 | return src; |
||
674 | } else if (src->type->is_vector()) { |
||
675 | return new(ctx) ir_swizzle(src, component, 0, 0, 0, 1); |
||
676 | } else { |
||
677 | assert(src->type->is_matrix()); |
||
678 | |||
679 | /* Dereference a row of the matrix, then call this function again to get |
||
680 | * a specific element from that row. |
||
681 | */ |
||
682 | const int c = component / src->type->column_type()->vector_elements; |
||
683 | const int r = component % src->type->column_type()->vector_elements; |
||
684 | ir_constant *const col_index = new(ctx) ir_constant(c); |
||
685 | ir_dereference *const col = new(ctx) ir_dereference_array(src, col_index); |
||
686 | |||
687 | col->type = src->type->column_type(); |
||
688 | |||
689 | return dereference_component(col, r); |
||
690 | } |
||
691 | |||
692 | assert(!"Should not get here."); |
||
693 | return NULL; |
||
694 | } |
||
695 | |||
696 | |||
697 | static ir_rvalue * |
||
698 | process_vec_mat_constructor(exec_list *instructions, |
||
699 | const glsl_type *constructor_type, |
||
700 | YYLTYPE *loc, exec_list *parameters, |
||
701 | struct _mesa_glsl_parse_state *state) |
||
702 | { |
||
703 | void *ctx = state; |
||
704 | |||
705 | /* The ARB_shading_language_420pack spec says: |
||
706 | * |
||
707 | * "If an initializer is a list of initializers enclosed in curly braces, |
||
708 | * the variable being declared must be a vector, a matrix, an array, or a |
||
709 | * structure. |
||
710 | * |
||
711 | * int i = { 1 }; // illegal, i is not an aggregate" |
||
712 | */ |
||
713 | if (constructor_type->vector_elements <= 1) { |
||
714 | _mesa_glsl_error(loc, state, "aggregates can only initialize vectors, " |
||
715 | "matrices, arrays, and structs"); |
||
716 | return ir_rvalue::error_value(ctx); |
||
717 | } |
||
718 | |||
719 | exec_list actual_parameters; |
||
720 | const unsigned parameter_count = |
||
721 | process_parameters(instructions, &actual_parameters, parameters, state); |
||
722 | |||
723 | if (parameter_count == 0 |
||
724 | || (constructor_type->is_vector() && |
||
725 | constructor_type->vector_elements != parameter_count) |
||
726 | || (constructor_type->is_matrix() && |
||
727 | constructor_type->matrix_columns != parameter_count)) { |
||
728 | _mesa_glsl_error(loc, state, "%s constructor must have %u parameters", |
||
729 | constructor_type->is_vector() ? "vector" : "matrix", |
||
730 | constructor_type->vector_elements); |
||
731 | return ir_rvalue::error_value(ctx); |
||
732 | } |
||
733 | |||
734 | bool all_parameters_are_constant = true; |
||
735 | |||
736 | /* Type cast each parameter and, if possible, fold constants. */ |
||
737 | foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) { |
||
738 | ir_rvalue *result = ir; |
||
739 | |||
740 | /* Apply implicit conversions (not the scalar constructor rules!). See |
||
741 | * the spec quote above. */ |
||
742 | if (constructor_type->base_type != result->type->base_type) { |
||
743 | const glsl_type *desired_type = |
||
744 | glsl_type::get_instance(constructor_type->base_type, |
||
745 | ir->type->vector_elements, |
||
746 | ir->type->matrix_columns); |
||
747 | if (result->type->can_implicitly_convert_to(desired_type, state)) { |
||
748 | /* Even though convert_component() implements the constructor |
||
749 | * conversion rules (not the implicit conversion rules), its safe |
||
750 | * to use it here because we already checked that the implicit |
||
751 | * conversion is legal. |
||
752 | */ |
||
753 | result = convert_component(ir, desired_type); |
||
754 | } |
||
755 | } |
||
756 | |||
757 | if (constructor_type->is_matrix()) { |
||
758 | if (result->type != constructor_type->column_type()) { |
||
759 | _mesa_glsl_error(loc, state, "type error in matrix constructor: " |
||
760 | "expected: %s, found %s", |
||
761 | constructor_type->column_type()->name, |
||
762 | result->type->name); |
||
763 | return ir_rvalue::error_value(ctx); |
||
764 | } |
||
765 | } else if (result->type != constructor_type->get_scalar_type()) { |
||
766 | _mesa_glsl_error(loc, state, "type error in vector constructor: " |
||
767 | "expected: %s, found %s", |
||
768 | constructor_type->get_scalar_type()->name, |
||
769 | result->type->name); |
||
770 | return ir_rvalue::error_value(ctx); |
||
771 | } |
||
772 | |||
773 | /* Attempt to convert the parameter to a constant valued expression. |
||
774 | * After doing so, track whether or not all the parameters to the |
||
775 | * constructor are trivially constant valued expressions. |
||
776 | */ |
||
777 | ir_rvalue *const constant = result->constant_expression_value(); |
||
778 | |||
779 | if (constant != NULL) |
||
780 | result = constant; |
||
781 | else |
||
782 | all_parameters_are_constant = false; |
||
783 | |||
784 | ir->replace_with(result); |
||
785 | } |
||
786 | |||
787 | if (all_parameters_are_constant) |
||
788 | return new(ctx) ir_constant(constructor_type, &actual_parameters); |
||
789 | |||
790 | ir_variable *var = new(ctx) ir_variable(constructor_type, "vec_mat_ctor", |
||
791 | ir_var_temporary); |
||
792 | instructions->push_tail(var); |
||
793 | |||
794 | int i = 0; |
||
795 | |||
796 | foreach_in_list(ir_rvalue, rhs, &actual_parameters) { |
||
797 | ir_instruction *assignment = NULL; |
||
798 | |||
799 | if (var->type->is_matrix()) { |
||
800 | ir_rvalue *lhs = new(ctx) ir_dereference_array(var, |
||
801 | new(ctx) ir_constant(i)); |
||
802 | assignment = new(ctx) ir_assignment(lhs, rhs, NULL); |
||
803 | } else { |
||
804 | /* use writemask rather than index for vector */ |
||
805 | assert(var->type->is_vector()); |
||
806 | assert(i < 4); |
||
807 | ir_dereference *lhs = new(ctx) ir_dereference_variable(var); |
||
808 | assignment = new(ctx) ir_assignment(lhs, rhs, NULL, (unsigned)(1 << i)); |
||
809 | } |
||
810 | |||
811 | instructions->push_tail(assignment); |
||
812 | |||
813 | i++; |
||
814 | } |
||
815 | |||
816 | return new(ctx) ir_dereference_variable(var); |
||
817 | } |
||
818 | |||
819 | |||
820 | static ir_rvalue * |
||
821 | process_array_constructor(exec_list *instructions, |
||
822 | const glsl_type *constructor_type, |
||
823 | YYLTYPE *loc, exec_list *parameters, |
||
824 | struct _mesa_glsl_parse_state *state) |
||
825 | { |
||
826 | void *ctx = state; |
||
827 | /* Array constructors come in two forms: sized and unsized. Sized array |
||
828 | * constructors look like 'vec4[2](a, b)', where 'a' and 'b' are vec4 |
||
829 | * variables. In this case the number of parameters must exactly match the |
||
830 | * specified size of the array. |
||
831 | * |
||
832 | * Unsized array constructors look like 'vec4[](a, b)', where 'a' and 'b' |
||
833 | * are vec4 variables. In this case the size of the array being constructed |
||
834 | * is determined by the number of parameters. |
||
835 | * |
||
836 | * From page 52 (page 58 of the PDF) of the GLSL 1.50 spec: |
||
837 | * |
||
838 | * "There must be exactly the same number of arguments as the size of |
||
839 | * the array being constructed. If no size is present in the |
||
840 | * constructor, then the array is explicitly sized to the number of |
||
841 | * arguments provided. The arguments are assigned in order, starting at |
||
842 | * element 0, to the elements of the constructed array. Each argument |
||
843 | * must be the same type as the element type of the array, or be a type |
||
844 | * that can be converted to the element type of the array according to |
||
845 | * Section 4.1.10 "Implicit Conversions."" |
||
846 | */ |
||
847 | exec_list actual_parameters; |
||
848 | const unsigned parameter_count = |
||
849 | process_parameters(instructions, &actual_parameters, parameters, state); |
||
850 | bool is_unsized_array = constructor_type->is_unsized_array(); |
||
851 | |||
852 | if ((parameter_count == 0) || |
||
853 | (!is_unsized_array && (constructor_type->length != parameter_count))) { |
||
854 | const unsigned min_param = is_unsized_array |
||
855 | ? 1 : constructor_type->length; |
||
856 | |||
857 | _mesa_glsl_error(loc, state, "array constructor must have %s %u " |
||
858 | "parameter%s", |
||
859 | is_unsized_array ? "at least" : "exactly", |
||
860 | min_param, (min_param <= 1) ? "" : "s"); |
||
861 | return ir_rvalue::error_value(ctx); |
||
862 | } |
||
863 | |||
864 | if (is_unsized_array) { |
||
865 | constructor_type = |
||
866 | glsl_type::get_array_instance(constructor_type->element_type(), |
||
867 | parameter_count); |
||
868 | assert(constructor_type != NULL); |
||
869 | assert(constructor_type->length == parameter_count); |
||
870 | } |
||
871 | |||
872 | bool all_parameters_are_constant = true; |
||
873 | |||
874 | /* Type cast each parameter and, if possible, fold constants. */ |
||
875 | foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) { |
||
876 | ir_rvalue *result = ir; |
||
877 | |||
878 | const glsl_base_type element_base_type = |
||
879 | constructor_type->element_type()->base_type; |
||
880 | |||
881 | /* Apply implicit conversions (not the scalar constructor rules!). See |
||
882 | * the spec quote above. */ |
||
883 | if (element_base_type != result->type->base_type) { |
||
884 | const glsl_type *desired_type = |
||
885 | glsl_type::get_instance(element_base_type, |
||
886 | ir->type->vector_elements, |
||
887 | ir->type->matrix_columns); |
||
888 | |||
889 | if (result->type->can_implicitly_convert_to(desired_type, state)) { |
||
890 | /* Even though convert_component() implements the constructor |
||
891 | * conversion rules (not the implicit conversion rules), its safe |
||
892 | * to use it here because we already checked that the implicit |
||
893 | * conversion is legal. |
||
894 | */ |
||
895 | result = convert_component(ir, desired_type); |
||
896 | } |
||
897 | } |
||
898 | |||
899 | if (result->type != constructor_type->element_type()) { |
||
900 | _mesa_glsl_error(loc, state, "type error in array constructor: " |
||
901 | "expected: %s, found %s", |
||
902 | constructor_type->element_type()->name, |
||
903 | result->type->name); |
||
904 | return ir_rvalue::error_value(ctx); |
||
905 | } |
||
906 | |||
907 | /* Attempt to convert the parameter to a constant valued expression. |
||
908 | * After doing so, track whether or not all the parameters to the |
||
909 | * constructor are trivially constant valued expressions. |
||
910 | */ |
||
911 | ir_rvalue *const constant = result->constant_expression_value(); |
||
912 | |||
913 | if (constant != NULL) |
||
914 | result = constant; |
||
915 | else |
||
916 | all_parameters_are_constant = false; |
||
917 | |||
918 | ir->replace_with(result); |
||
919 | } |
||
920 | |||
921 | if (all_parameters_are_constant) |
||
922 | return new(ctx) ir_constant(constructor_type, &actual_parameters); |
||
923 | |||
924 | ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor", |
||
925 | ir_var_temporary); |
||
926 | instructions->push_tail(var); |
||
927 | |||
928 | int i = 0; |
||
929 | foreach_in_list(ir_rvalue, rhs, &actual_parameters) { |
||
930 | ir_rvalue *lhs = new(ctx) ir_dereference_array(var, |
||
931 | new(ctx) ir_constant(i)); |
||
932 | |||
933 | ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL); |
||
934 | instructions->push_tail(assignment); |
||
935 | |||
936 | i++; |
||
937 | } |
||
938 | |||
939 | return new(ctx) ir_dereference_variable(var); |
||
940 | } |
||
941 | |||
942 | |||
943 | /** |
||
944 | * Try to convert a record constructor to a constant expression |
||
945 | */ |
||
946 | static ir_constant * |
||
947 | constant_record_constructor(const glsl_type *constructor_type, |
||
948 | exec_list *parameters, void *mem_ctx) |
||
949 | { |
||
950 | foreach_in_list(ir_instruction, node, parameters) { |
||
951 | ir_constant *constant = node->as_constant(); |
||
952 | if (constant == NULL) |
||
953 | return NULL; |
||
954 | node->replace_with(constant); |
||
955 | } |
||
956 | |||
957 | return new(mem_ctx) ir_constant(constructor_type, parameters); |
||
958 | } |
||
959 | |||
960 | |||
961 | /** |
||
962 | * Determine if a list consists of a single scalar r-value |
||
963 | */ |
||
964 | bool |
||
965 | single_scalar_parameter(exec_list *parameters) |
||
966 | { |
||
967 | const ir_rvalue *const p = (ir_rvalue *) parameters->head; |
||
968 | assert(((ir_rvalue *)p)->as_rvalue() != NULL); |
||
969 | |||
970 | return (p->type->is_scalar() && p->next->is_tail_sentinel()); |
||
971 | } |
||
972 | |||
973 | |||
974 | /** |
||
975 | * Generate inline code for a vector constructor |
||
976 | * |
||
977 | * The generated constructor code will consist of a temporary variable |
||
978 | * declaration of the same type as the constructor. A sequence of assignments |
||
979 | * from constructor parameters to the temporary will follow. |
||
980 | * |
||
981 | * \return |
||
982 | * An \c ir_dereference_variable of the temprorary generated in the constructor |
||
983 | * body. |
||
984 | */ |
||
985 | ir_rvalue * |
||
986 | emit_inline_vector_constructor(const glsl_type *type, |
||
987 | exec_list *instructions, |
||
988 | exec_list *parameters, |
||
989 | void *ctx) |
||
990 | { |
||
991 | assert(!parameters->is_empty()); |
||
992 | |||
993 | ir_variable *var = new(ctx) ir_variable(type, "vec_ctor", ir_var_temporary); |
||
994 | instructions->push_tail(var); |
||
995 | |||
996 | /* There are two kinds of vector constructors. |
||
997 | * |
||
998 | * - Construct a vector from a single scalar by replicating that scalar to |
||
999 | * all components of the vector. |
||
1000 | * |
||
1001 | * - Construct a vector from an arbirary combination of vectors and |
||
1002 | * scalars. The components of the constructor parameters are assigned |
||
1003 | * to the vector in order until the vector is full. |
||
1004 | */ |
||
1005 | const unsigned lhs_components = type->components(); |
||
1006 | if (single_scalar_parameter(parameters)) { |
||
1007 | ir_rvalue *first_param = (ir_rvalue *)parameters->head; |
||
1008 | ir_rvalue *rhs = new(ctx) ir_swizzle(first_param, 0, 0, 0, 0, |
||
1009 | lhs_components); |
||
1010 | ir_dereference_variable *lhs = new(ctx) ir_dereference_variable(var); |
||
1011 | const unsigned mask = (1U << lhs_components) - 1; |
||
1012 | |||
1013 | assert(rhs->type == lhs->type); |
||
1014 | |||
1015 | ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, mask); |
||
1016 | instructions->push_tail(inst); |
||
1017 | } else { |
||
1018 | unsigned base_component = 0; |
||
1019 | unsigned base_lhs_component = 0; |
||
1020 | ir_constant_data data; |
||
1021 | unsigned constant_mask = 0, constant_components = 0; |
||
1022 | |||
1023 | memset(&data, 0, sizeof(data)); |
||
1024 | |||
1025 | foreach_in_list(ir_rvalue, param, parameters) { |
||
1026 | unsigned rhs_components = param->type->components(); |
||
1027 | |||
1028 | /* Do not try to assign more components to the vector than it has! |
||
1029 | */ |
||
1030 | if ((rhs_components + base_lhs_component) > lhs_components) { |
||
1031 | rhs_components = lhs_components - base_lhs_component; |
||
1032 | } |
||
1033 | |||
1034 | const ir_constant *const c = param->as_constant(); |
||
1035 | if (c != NULL) { |
||
1036 | for (unsigned i = 0; i < rhs_components; i++) { |
||
1037 | switch (c->type->base_type) { |
||
1038 | case GLSL_TYPE_UINT: |
||
1039 | data.u[i + base_component] = c->get_uint_component(i); |
||
1040 | break; |
||
1041 | case GLSL_TYPE_INT: |
||
1042 | data.i[i + base_component] = c->get_int_component(i); |
||
1043 | break; |
||
1044 | case GLSL_TYPE_FLOAT: |
||
1045 | data.f[i + base_component] = c->get_float_component(i); |
||
1046 | break; |
||
1047 | case GLSL_TYPE_DOUBLE: |
||
1048 | data.d[i + base_component] = c->get_double_component(i); |
||
1049 | break; |
||
1050 | case GLSL_TYPE_BOOL: |
||
1051 | data.b[i + base_component] = c->get_bool_component(i); |
||
1052 | break; |
||
1053 | default: |
||
1054 | assert(!"Should not get here."); |
||
1055 | break; |
||
1056 | } |
||
1057 | } |
||
1058 | |||
1059 | /* Mask of fields to be written in the assignment. |
||
1060 | */ |
||
1061 | constant_mask |= ((1U << rhs_components) - 1) << base_lhs_component; |
||
1062 | constant_components += rhs_components; |
||
1063 | |||
1064 | base_component += rhs_components; |
||
1065 | } |
||
1066 | /* Advance the component index by the number of components |
||
1067 | * that were just assigned. |
||
1068 | */ |
||
1069 | base_lhs_component += rhs_components; |
||
1070 | } |
||
1071 | |||
1072 | if (constant_mask != 0) { |
||
1073 | ir_dereference *lhs = new(ctx) ir_dereference_variable(var); |
||
1074 | const glsl_type *rhs_type = glsl_type::get_instance(var->type->base_type, |
||
1075 | constant_components, |
||
1076 | 1); |
||
1077 | ir_rvalue *rhs = new(ctx) ir_constant(rhs_type, &data); |
||
1078 | |||
1079 | ir_instruction *inst = |
||
1080 | new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask); |
||
1081 | instructions->push_tail(inst); |
||
1082 | } |
||
1083 | |||
1084 | base_component = 0; |
||
1085 | foreach_in_list(ir_rvalue, param, parameters) { |
||
1086 | unsigned rhs_components = param->type->components(); |
||
1087 | |||
1088 | /* Do not try to assign more components to the vector than it has! |
||
1089 | */ |
||
1090 | if ((rhs_components + base_component) > lhs_components) { |
||
1091 | rhs_components = lhs_components - base_component; |
||
1092 | } |
||
1093 | |||
1094 | const ir_constant *const c = param->as_constant(); |
||
1095 | if (c == NULL) { |
||
1096 | /* Mask of fields to be written in the assignment. |
||
1097 | */ |
||
1098 | const unsigned write_mask = ((1U << rhs_components) - 1) |
||
1099 | << base_component; |
||
1100 | |||
1101 | ir_dereference *lhs = new(ctx) ir_dereference_variable(var); |
||
1102 | |||
1103 | /* Generate a swizzle so that LHS and RHS sizes match. |
||
1104 | */ |
||
1105 | ir_rvalue *rhs = |
||
1106 | new(ctx) ir_swizzle(param, 0, 1, 2, 3, rhs_components); |
||
1107 | |||
1108 | ir_instruction *inst = |
||
1109 | new(ctx) ir_assignment(lhs, rhs, NULL, write_mask); |
||
1110 | instructions->push_tail(inst); |
||
1111 | } |
||
1112 | |||
1113 | /* Advance the component index by the number of components that were |
||
1114 | * just assigned. |
||
1115 | */ |
||
1116 | base_component += rhs_components; |
||
1117 | } |
||
1118 | } |
||
1119 | return new(ctx) ir_dereference_variable(var); |
||
1120 | } |
||
1121 | |||
1122 | |||
1123 | /** |
||
1124 | * Generate assignment of a portion of a vector to a portion of a matrix column |
||
1125 | * |
||
1126 | * \param src_base First component of the source to be used in assignment |
||
1127 | * \param column Column of destination to be assiged |
||
1128 | * \param row_base First component of the destination column to be assigned |
||
1129 | * \param count Number of components to be assigned |
||
1130 | * |
||
1131 | * \note |
||
1132 | * \c src_base + \c count must be less than or equal to the number of components |
||
1133 | * in the source vector. |
||
1134 | */ |
||
1135 | ir_instruction * |
||
1136 | assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base, |
||
1137 | ir_rvalue *src, unsigned src_base, unsigned count, |
||
1138 | void *mem_ctx) |
||
1139 | { |
||
1140 | ir_constant *col_idx = new(mem_ctx) ir_constant(column); |
||
1141 | ir_dereference *column_ref = new(mem_ctx) ir_dereference_array(var, col_idx); |
||
1142 | |||
1143 | assert(column_ref->type->components() >= (row_base + count)); |
||
1144 | assert(src->type->components() >= (src_base + count)); |
||
1145 | |||
1146 | /* Generate a swizzle that extracts the number of components from the source |
||
1147 | * that are to be assigned to the column of the matrix. |
||
1148 | */ |
||
1149 | if (count < src->type->vector_elements) { |
||
1150 | src = new(mem_ctx) ir_swizzle(src, |
||
1151 | src_base + 0, src_base + 1, |
||
1152 | src_base + 2, src_base + 3, |
||
1153 | count); |
||
1154 | } |
||
1155 | |||
1156 | /* Mask of fields to be written in the assignment. |
||
1157 | */ |
||
1158 | const unsigned write_mask = ((1U << count) - 1) << row_base; |
||
1159 | |||
1160 | return new(mem_ctx) ir_assignment(column_ref, src, NULL, write_mask); |
||
1161 | } |
||
1162 | |||
1163 | |||
1164 | /** |
||
1165 | * Generate inline code for a matrix constructor |
||
1166 | * |
||
1167 | * The generated constructor code will consist of a temporary variable |
||
1168 | * declaration of the same type as the constructor. A sequence of assignments |
||
1169 | * from constructor parameters to the temporary will follow. |
||
1170 | * |
||
1171 | * \return |
||
1172 | * An \c ir_dereference_variable of the temprorary generated in the constructor |
||
1173 | * body. |
||
1174 | */ |
||
1175 | ir_rvalue * |
||
1176 | emit_inline_matrix_constructor(const glsl_type *type, |
||
1177 | exec_list *instructions, |
||
1178 | exec_list *parameters, |
||
1179 | void *ctx) |
||
1180 | { |
||
1181 | assert(!parameters->is_empty()); |
||
1182 | |||
1183 | ir_variable *var = new(ctx) ir_variable(type, "mat_ctor", ir_var_temporary); |
||
1184 | instructions->push_tail(var); |
||
1185 | |||
1186 | /* There are three kinds of matrix constructors. |
||
1187 | * |
||
1188 | * - Construct a matrix from a single scalar by replicating that scalar to |
||
1189 | * along the diagonal of the matrix and setting all other components to |
||
1190 | * zero. |
||
1191 | * |
||
1192 | * - Construct a matrix from an arbirary combination of vectors and |
||
1193 | * scalars. The components of the constructor parameters are assigned |
||
1194 | * to the matrix in column-major order until the matrix is full. |
||
1195 | * |
||
1196 | * - Construct a matrix from a single matrix. The source matrix is copied |
||
1197 | * to the upper left portion of the constructed matrix, and the remaining |
||
1198 | * elements take values from the identity matrix. |
||
1199 | */ |
||
1200 | ir_rvalue *const first_param = (ir_rvalue *) parameters->head; |
||
1201 | if (single_scalar_parameter(parameters)) { |
||
1202 | /* Assign the scalar to the X component of a vec4, and fill the remaining |
||
1203 | * components with zero. |
||
1204 | */ |
||
1205 | glsl_base_type param_base_type = first_param->type->base_type; |
||
1206 | assert(param_base_type == GLSL_TYPE_FLOAT || |
||
1207 | param_base_type == GLSL_TYPE_DOUBLE); |
||
1208 | ir_variable *rhs_var = |
||
1209 | new(ctx) ir_variable(glsl_type::get_instance(param_base_type, 4, 1), |
||
1210 | "mat_ctor_vec", |
||
1211 | ir_var_temporary); |
||
1212 | instructions->push_tail(rhs_var); |
||
1213 | |||
1214 | ir_constant_data zero; |
||
1215 | for (unsigned i = 0; i < 4; i++) |
||
1216 | if (param_base_type == GLSL_TYPE_FLOAT) |
||
1217 | zero.f[i] = 0.0; |
||
1218 | else |
||
1219 | zero.d[i] = 0.0; |
||
1220 | |||
1221 | ir_instruction *inst = |
||
1222 | new(ctx) ir_assignment(new(ctx) ir_dereference_variable(rhs_var), |
||
1223 | new(ctx) ir_constant(rhs_var->type, &zero), |
||
1224 | NULL); |
||
1225 | instructions->push_tail(inst); |
||
1226 | |||
1227 | ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1228 | |||
1229 | inst = new(ctx) ir_assignment(rhs_ref, first_param, NULL, 0x01); |
||
1230 | instructions->push_tail(inst); |
||
1231 | |||
1232 | /* Assign the temporary vector to each column of the destination matrix |
||
1233 | * with a swizzle that puts the X component on the diagonal of the |
||
1234 | * matrix. In some cases this may mean that the X component does not |
||
1235 | * get assigned into the column at all (i.e., when the matrix has more |
||
1236 | * columns than rows). |
||
1237 | */ |
||
1238 | static const unsigned rhs_swiz[4][4] = { |
||
1239 | { 0, 1, 1, 1 }, |
||
1240 | { 1, 0, 1, 1 }, |
||
1241 | { 1, 1, 0, 1 }, |
||
1242 | { 1, 1, 1, 0 } |
||
1243 | }; |
||
1244 | |||
1245 | const unsigned cols_to_init = MIN2(type->matrix_columns, |
||
1246 | type->vector_elements); |
||
1247 | for (unsigned i = 0; i < cols_to_init; i++) { |
||
1248 | ir_constant *const col_idx = new(ctx) ir_constant(i); |
||
1249 | ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx); |
||
1250 | |||
1251 | ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1252 | ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, rhs_swiz[i], |
||
1253 | type->vector_elements); |
||
1254 | |||
1255 | inst = new(ctx) ir_assignment(col_ref, rhs, NULL); |
||
1256 | instructions->push_tail(inst); |
||
1257 | } |
||
1258 | |||
1259 | for (unsigned i = cols_to_init; i < type->matrix_columns; i++) { |
||
1260 | ir_constant *const col_idx = new(ctx) ir_constant(i); |
||
1261 | ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var, col_idx); |
||
1262 | |||
1263 | ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1264 | ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, 1, 1, 1, 1, |
||
1265 | type->vector_elements); |
||
1266 | |||
1267 | inst = new(ctx) ir_assignment(col_ref, rhs, NULL); |
||
1268 | instructions->push_tail(inst); |
||
1269 | } |
||
1270 | } else if (first_param->type->is_matrix()) { |
||
1271 | /* From page 50 (56 of the PDF) of the GLSL 1.50 spec: |
||
1272 | * |
||
1273 | * "If a matrix is constructed from a matrix, then each component |
||
1274 | * (column i, row j) in the result that has a corresponding |
||
1275 | * component (column i, row j) in the argument will be initialized |
||
1276 | * from there. All other components will be initialized to the |
||
1277 | * identity matrix. If a matrix argument is given to a matrix |
||
1278 | * constructor, it is an error to have any other arguments." |
||
1279 | */ |
||
1280 | assert(first_param->next->is_tail_sentinel()); |
||
1281 | ir_rvalue *const src_matrix = first_param; |
||
1282 | |||
1283 | /* If the source matrix is smaller, pre-initialize the relavent parts of |
||
1284 | * the destination matrix to the identity matrix. |
||
1285 | */ |
||
1286 | if ((src_matrix->type->matrix_columns < var->type->matrix_columns) |
||
1287 | || (src_matrix->type->vector_elements < var->type->vector_elements)) { |
||
1288 | |||
1289 | /* If the source matrix has fewer rows, every column of the destination |
||
1290 | * must be initialized. Otherwise only the columns in the destination |
||
1291 | * that do not exist in the source must be initialized. |
||
1292 | */ |
||
1293 | unsigned col = |
||
1294 | (src_matrix->type->vector_elements < var->type->vector_elements) |
||
1295 | ? 0 : src_matrix->type->matrix_columns; |
||
1296 | |||
1297 | const glsl_type *const col_type = var->type->column_type(); |
||
1298 | for (/* empty */; col < var->type->matrix_columns; col++) { |
||
1299 | ir_constant_data ident; |
||
1300 | |||
1301 | ident.f[0] = 0.0; |
||
1302 | ident.f[1] = 0.0; |
||
1303 | ident.f[2] = 0.0; |
||
1304 | ident.f[3] = 0.0; |
||
1305 | |||
1306 | ident.f[col] = 1.0; |
||
1307 | |||
1308 | ir_rvalue *const rhs = new(ctx) ir_constant(col_type, &ident); |
||
1309 | |||
1310 | ir_rvalue *const lhs = |
||
1311 | new(ctx) ir_dereference_array(var, new(ctx) ir_constant(col)); |
||
1312 | |||
1313 | ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL); |
||
1314 | instructions->push_tail(inst); |
||
1315 | } |
||
1316 | } |
||
1317 | |||
1318 | /* Assign columns from the source matrix to the destination matrix. |
||
1319 | * |
||
1320 | * Since the parameter will be used in the RHS of multiple assignments, |
||
1321 | * generate a temporary and copy the paramter there. |
||
1322 | */ |
||
1323 | ir_variable *const rhs_var = |
||
1324 | new(ctx) ir_variable(first_param->type, "mat_ctor_mat", |
||
1325 | ir_var_temporary); |
||
1326 | instructions->push_tail(rhs_var); |
||
1327 | |||
1328 | ir_dereference *const rhs_var_ref = |
||
1329 | new(ctx) ir_dereference_variable(rhs_var); |
||
1330 | ir_instruction *const inst = |
||
1331 | new(ctx) ir_assignment(rhs_var_ref, first_param, NULL); |
||
1332 | instructions->push_tail(inst); |
||
1333 | |||
1334 | const unsigned last_row = MIN2(src_matrix->type->vector_elements, |
||
1335 | var->type->vector_elements); |
||
1336 | const unsigned last_col = MIN2(src_matrix->type->matrix_columns, |
||
1337 | var->type->matrix_columns); |
||
1338 | |||
1339 | unsigned swiz[4] = { 0, 0, 0, 0 }; |
||
1340 | for (unsigned i = 1; i < last_row; i++) |
||
1341 | swiz[i] = i; |
||
1342 | |||
1343 | const unsigned write_mask = (1U << last_row) - 1; |
||
1344 | |||
1345 | for (unsigned i = 0; i < last_col; i++) { |
||
1346 | ir_dereference *const lhs = |
||
1347 | new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i)); |
||
1348 | ir_rvalue *const rhs_col = |
||
1349 | new(ctx) ir_dereference_array(rhs_var, new(ctx) ir_constant(i)); |
||
1350 | |||
1351 | /* If one matrix has columns that are smaller than the columns of the |
||
1352 | * other matrix, wrap the column access of the larger with a swizzle |
||
1353 | * so that the LHS and RHS of the assignment have the same size (and |
||
1354 | * therefore have the same type). |
||
1355 | * |
||
1356 | * It would be perfectly valid to unconditionally generate the |
||
1357 | * swizzles, this this will typically result in a more compact IR tree. |
||
1358 | */ |
||
1359 | ir_rvalue *rhs; |
||
1360 | if (lhs->type->vector_elements != rhs_col->type->vector_elements) { |
||
1361 | rhs = new(ctx) ir_swizzle(rhs_col, swiz, last_row); |
||
1362 | } else { |
||
1363 | rhs = rhs_col; |
||
1364 | } |
||
1365 | |||
1366 | ir_instruction *inst = |
||
1367 | new(ctx) ir_assignment(lhs, rhs, NULL, write_mask); |
||
1368 | instructions->push_tail(inst); |
||
1369 | } |
||
1370 | } else { |
||
1371 | const unsigned cols = type->matrix_columns; |
||
1372 | const unsigned rows = type->vector_elements; |
||
1373 | unsigned remaining_slots = rows * cols; |
||
1374 | unsigned col_idx = 0; |
||
1375 | unsigned row_idx = 0; |
||
1376 | |||
1377 | foreach_in_list(ir_rvalue, rhs, parameters) { |
||
1378 | unsigned rhs_components = rhs->type->components(); |
||
1379 | unsigned rhs_base = 0; |
||
1380 | |||
1381 | if (remaining_slots == 0) |
||
1382 | break; |
||
1383 | |||
1384 | /* Since the parameter might be used in the RHS of two assignments, |
||
1385 | * generate a temporary and copy the paramter there. |
||
1386 | */ |
||
1387 | ir_variable *rhs_var = |
||
1388 | new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary); |
||
1389 | instructions->push_tail(rhs_var); |
||
1390 | |||
1391 | ir_dereference *rhs_var_ref = |
||
1392 | new(ctx) ir_dereference_variable(rhs_var); |
||
1393 | ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs, NULL); |
||
1394 | instructions->push_tail(inst); |
||
1395 | |||
1396 | do { |
||
1397 | /* Assign the current parameter to as many components of the matrix |
||
1398 | * as it will fill. |
||
1399 | * |
||
1400 | * NOTE: A single vector parameter can span two matrix columns. A |
||
1401 | * single vec4, for example, can completely fill a mat2. |
||
1402 | */ |
||
1403 | unsigned count = MIN2(rows - row_idx, |
||
1404 | rhs_components - rhs_base); |
||
1405 | |||
1406 | rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var); |
||
1407 | ir_instruction *inst = assign_to_matrix_column(var, col_idx, |
||
1408 | row_idx, |
||
1409 | rhs_var_ref, |
||
1410 | rhs_base, |
||
1411 | count, ctx); |
||
1412 | instructions->push_tail(inst); |
||
1413 | rhs_base += count; |
||
1414 | row_idx += count; |
||
1415 | remaining_slots -= count; |
||
1416 | |||
1417 | /* Sometimes, there is still data left in the parameters and |
||
1418 | * components left to be set in the destination but in other |
||
1419 | * column. |
||
1420 | */ |
||
1421 | if (row_idx >= rows) { |
||
1422 | row_idx = 0; |
||
1423 | col_idx++; |
||
1424 | } |
||
1425 | } while(remaining_slots > 0 && rhs_base < rhs_components); |
||
1426 | } |
||
1427 | } |
||
1428 | |||
1429 | return new(ctx) ir_dereference_variable(var); |
||
1430 | } |
||
1431 | |||
1432 | |||
1433 | ir_rvalue * |
||
1434 | emit_inline_record_constructor(const glsl_type *type, |
||
1435 | exec_list *instructions, |
||
1436 | exec_list *parameters, |
||
1437 | void *mem_ctx) |
||
1438 | { |
||
1439 | ir_variable *const var = |
||
1440 | new(mem_ctx) ir_variable(type, "record_ctor", ir_var_temporary); |
||
1441 | ir_dereference_variable *const d = new(mem_ctx) ir_dereference_variable(var); |
||
1442 | |||
1443 | instructions->push_tail(var); |
||
1444 | |||
1445 | exec_node *node = parameters->head; |
||
1446 | for (unsigned i = 0; i < type->length; i++) { |
||
1447 | assert(!node->is_tail_sentinel()); |
||
1448 | |||
1449 | ir_dereference *const lhs = |
||
1450 | new(mem_ctx) ir_dereference_record(d->clone(mem_ctx, NULL), |
||
1451 | type->fields.structure[i].name); |
||
1452 | |||
1453 | ir_rvalue *const rhs = ((ir_instruction *) node)->as_rvalue(); |
||
1454 | assert(rhs != NULL); |
||
1455 | |||
1456 | ir_instruction *const assign = new(mem_ctx) ir_assignment(lhs, rhs, NULL); |
||
1457 | |||
1458 | instructions->push_tail(assign); |
||
1459 | node = node->next; |
||
1460 | } |
||
1461 | |||
1462 | return d; |
||
1463 | } |
||
1464 | |||
1465 | |||
1466 | static ir_rvalue * |
||
1467 | process_record_constructor(exec_list *instructions, |
||
1468 | const glsl_type *constructor_type, |
||
1469 | YYLTYPE *loc, exec_list *parameters, |
||
1470 | struct _mesa_glsl_parse_state *state) |
||
1471 | { |
||
1472 | void *ctx = state; |
||
1473 | exec_list actual_parameters; |
||
1474 | |||
1475 | process_parameters(instructions, &actual_parameters, |
||
1476 | parameters, state); |
||
1477 | |||
1478 | exec_node *node = actual_parameters.head; |
||
1479 | for (unsigned i = 0; i < constructor_type->length; i++) { |
||
1480 | ir_rvalue *ir = (ir_rvalue *) node; |
||
1481 | |||
1482 | if (node->is_tail_sentinel()) { |
||
1483 | _mesa_glsl_error(loc, state, |
||
1484 | "insufficient parameters to constructor for `%s'", |
||
1485 | constructor_type->name); |
||
1486 | return ir_rvalue::error_value(ctx); |
||
1487 | } |
||
1488 | |||
1489 | if (apply_implicit_conversion(constructor_type->fields.structure[i].type, |
||
1490 | ir, state)) { |
||
1491 | node->replace_with(ir); |
||
1492 | } else { |
||
1493 | _mesa_glsl_error(loc, state, |
||
1494 | "parameter type mismatch in constructor for `%s.%s' " |
||
1495 | "(%s vs %s)", |
||
1496 | constructor_type->name, |
||
1497 | constructor_type->fields.structure[i].name, |
||
1498 | ir->type->name, |
||
1499 | constructor_type->fields.structure[i].type->name); |
||
1500 | return ir_rvalue::error_value(ctx);; |
||
1501 | } |
||
1502 | |||
1503 | node = node->next; |
||
1504 | } |
||
1505 | |||
1506 | if (!node->is_tail_sentinel()) { |
||
1507 | _mesa_glsl_error(loc, state, "too many parameters in constructor " |
||
1508 | "for `%s'", constructor_type->name); |
||
1509 | return ir_rvalue::error_value(ctx); |
||
1510 | } |
||
1511 | |||
1512 | ir_rvalue *const constant = |
||
1513 | constant_record_constructor(constructor_type, &actual_parameters, |
||
1514 | state); |
||
1515 | |||
1516 | return (constant != NULL) |
||
1517 | ? constant |
||
1518 | : emit_inline_record_constructor(constructor_type, instructions, |
||
1519 | &actual_parameters, state); |
||
1520 | } |
||
1521 | |||
1522 | |||
1523 | ir_rvalue * |
||
1524 | ast_function_expression::hir(exec_list *instructions, |
||
1525 | struct _mesa_glsl_parse_state *state) |
||
1526 | { |
||
1527 | void *ctx = state; |
||
1528 | /* There are three sorts of function calls. |
||
1529 | * |
||
1530 | * 1. constructors - The first subexpression is an ast_type_specifier. |
||
1531 | * 2. methods - Only the .length() method of array types. |
||
1532 | * 3. functions - Calls to regular old functions. |
||
1533 | * |
||
1534 | * Method calls are actually detected when the ast_field_selection |
||
1535 | * expression is handled. |
||
1536 | */ |
||
1537 | if (is_constructor()) { |
||
1538 | const ast_type_specifier *type = (ast_type_specifier *) subexpressions[0]; |
||
1539 | YYLTYPE loc = type->get_location(); |
||
1540 | const char *name; |
||
1541 | |||
1542 | const glsl_type *const constructor_type = type->glsl_type(& name, state); |
||
1543 | |||
1544 | /* constructor_type can be NULL if a variable with the same name as the |
||
1545 | * structure has come into scope. |
||
1546 | */ |
||
1547 | if (constructor_type == NULL) { |
||
1548 | _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name " |
||
1549 | "may be shadowed by a variable with the same name)", |
||
1550 | type->type_name); |
||
1551 | return ir_rvalue::error_value(ctx); |
||
1552 | } |
||
1553 | |||
1554 | |||
1555 | /* Constructors for opaque types are illegal. |
||
1556 | */ |
||
1557 | if (constructor_type->contains_opaque()) { |
||
1558 | _mesa_glsl_error(& loc, state, "cannot construct opaque type `%s'", |
||
1559 | constructor_type->name); |
||
1560 | return ir_rvalue::error_value(ctx); |
||
1561 | } |
||
1562 | |||
1563 | if (constructor_type->is_array()) { |
||
1564 | if (!state->check_version(120, 300, &loc, |
||
1565 | "array constructors forbidden")) { |
||
1566 | return ir_rvalue::error_value(ctx); |
||
1567 | } |
||
1568 | |||
1569 | return process_array_constructor(instructions, constructor_type, |
||
1570 | & loc, &this->expressions, state); |
||
1571 | } |
||
1572 | |||
1573 | |||
1574 | /* There are two kinds of constructor calls. Constructors for arrays and |
||
1575 | * structures must have the exact number of arguments with matching types |
||
1576 | * in the correct order. These constructors follow essentially the same |
||
1577 | * type matching rules as functions. |
||
1578 | * |
||
1579 | * Constructors for built-in language types, such as mat4 and vec2, are |
||
1580 | * free form. The only requirements are that the parameters must provide |
||
1581 | * enough values of the correct scalar type and that no arguments are |
||
1582 | * given past the last used argument. |
||
1583 | * |
||
1584 | * When using the C-style initializer syntax from GLSL 4.20, constructors |
||
1585 | * must have the exact number of arguments with matching types in the |
||
1586 | * correct order. |
||
1587 | */ |
||
1588 | if (constructor_type->is_record()) { |
||
1589 | return process_record_constructor(instructions, constructor_type, |
||
1590 | &loc, &this->expressions, |
||
1591 | state); |
||
1592 | } |
||
1593 | |||
1594 | if (!constructor_type->is_numeric() && !constructor_type->is_boolean()) |
||
1595 | return ir_rvalue::error_value(ctx); |
||
1596 | |||
1597 | /* Total number of components of the type being constructed. */ |
||
1598 | const unsigned type_components = constructor_type->components(); |
||
1599 | |||
1600 | /* Number of components from parameters that have actually been |
||
1601 | * consumed. This is used to perform several kinds of error checking. |
||
1602 | */ |
||
1603 | unsigned components_used = 0; |
||
1604 | |||
1605 | unsigned matrix_parameters = 0; |
||
1606 | unsigned nonmatrix_parameters = 0; |
||
1607 | exec_list actual_parameters; |
||
1608 | |||
1609 | foreach_list_typed(ast_node, ast, link, &this->expressions) { |
||
1610 | ir_rvalue *result = ast->hir(instructions, state); |
||
1611 | |||
1612 | /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec: |
||
1613 | * |
||
1614 | * "It is an error to provide extra arguments beyond this |
||
1615 | * last used argument." |
||
1616 | */ |
||
1617 | if (components_used >= type_components) { |
||
1618 | _mesa_glsl_error(& loc, state, "too many parameters to `%s' " |
||
1619 | "constructor", |
||
1620 | constructor_type->name); |
||
1621 | return ir_rvalue::error_value(ctx); |
||
1622 | } |
||
1623 | |||
1624 | if (!result->type->is_numeric() && !result->type->is_boolean()) { |
||
1625 | _mesa_glsl_error(& loc, state, "cannot construct `%s' from a " |
||
1626 | "non-numeric data type", |
||
1627 | constructor_type->name); |
||
1628 | return ir_rvalue::error_value(ctx); |
||
1629 | } |
||
1630 | |||
1631 | /* Count the number of matrix and nonmatrix parameters. This |
||
1632 | * is used below to enforce some of the constructor rules. |
||
1633 | */ |
||
1634 | if (result->type->is_matrix()) |
||
1635 | matrix_parameters++; |
||
1636 | else |
||
1637 | nonmatrix_parameters++; |
||
1638 | |||
1639 | actual_parameters.push_tail(result); |
||
1640 | components_used += result->type->components(); |
||
1641 | } |
||
1642 | |||
1643 | /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec: |
||
1644 | * |
||
1645 | * "It is an error to construct matrices from other matrices. This |
||
1646 | * is reserved for future use." |
||
1647 | */ |
||
1648 | if (matrix_parameters > 0 |
||
1649 | && constructor_type->is_matrix() |
||
1650 | && !state->check_version(120, 100, &loc, |
||
1651 | "cannot construct `%s' from a matrix", |
||
1652 | constructor_type->name)) { |
||
1653 | return ir_rvalue::error_value(ctx); |
||
1654 | } |
||
1655 | |||
1656 | /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec: |
||
1657 | * |
||
1658 | * "If a matrix argument is given to a matrix constructor, it is |
||
1659 | * an error to have any other arguments." |
||
1660 | */ |
||
1661 | if ((matrix_parameters > 0) |
||
1662 | && ((matrix_parameters + nonmatrix_parameters) > 1) |
||
1663 | && constructor_type->is_matrix()) { |
||
1664 | _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, " |
||
1665 | "matrix must be only parameter", |
||
1666 | constructor_type->name); |
||
1667 | return ir_rvalue::error_value(ctx); |
||
1668 | } |
||
1669 | |||
1670 | /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec: |
||
1671 | * |
||
1672 | * "In these cases, there must be enough components provided in the |
||
1673 | * arguments to provide an initializer for every component in the |
||
1674 | * constructed value." |
||
1675 | */ |
||
1676 | if (components_used < type_components && components_used != 1 |
||
1677 | && matrix_parameters == 0) { |
||
1678 | _mesa_glsl_error(& loc, state, "too few components to construct " |
||
1679 | "`%s'", |
||
1680 | constructor_type->name); |
||
1681 | return ir_rvalue::error_value(ctx); |
||
1682 | } |
||
1683 | |||
1684 | /* Later, we cast each parameter to the same base type as the |
||
1685 | * constructor. Since there are no non-floating point matrices, we |
||
1686 | * need to break them up into a series of column vectors. |
||
1687 | */ |
||
1688 | if (constructor_type->base_type != GLSL_TYPE_FLOAT) { |
||
1689 | foreach_in_list_safe(ir_rvalue, matrix, &actual_parameters) { |
||
1690 | if (!matrix->type->is_matrix()) |
||
1691 | continue; |
||
1692 | |||
1693 | /* Create a temporary containing the matrix. */ |
||
1694 | ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp", |
||
1695 | ir_var_temporary); |
||
1696 | instructions->push_tail(var); |
||
1697 | instructions->push_tail(new(ctx) ir_assignment(new(ctx) |
||
1698 | ir_dereference_variable(var), matrix, NULL)); |
||
1699 | var->constant_value = matrix->constant_expression_value(); |
||
1700 | |||
1701 | /* Replace the matrix with dereferences of its columns. */ |
||
1702 | for (int i = 0; i < matrix->type->matrix_columns; i++) { |
||
1703 | matrix->insert_before(new (ctx) ir_dereference_array(var, |
||
1704 | new(ctx) ir_constant(i))); |
||
1705 | } |
||
1706 | matrix->remove(); |
||
1707 | } |
||
1708 | } |
||
1709 | |||
1710 | bool all_parameters_are_constant = true; |
||
1711 | |||
1712 | /* Type cast each parameter and, if possible, fold constants.*/ |
||
1713 | foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) { |
||
1714 | const glsl_type *desired_type = |
||
1715 | glsl_type::get_instance(constructor_type->base_type, |
||
1716 | ir->type->vector_elements, |
||
1717 | ir->type->matrix_columns); |
||
1718 | ir_rvalue *result = convert_component(ir, desired_type); |
||
1719 | |||
1720 | /* Attempt to convert the parameter to a constant valued expression. |
||
1721 | * After doing so, track whether or not all the parameters to the |
||
1722 | * constructor are trivially constant valued expressions. |
||
1723 | */ |
||
1724 | ir_rvalue *const constant = result->constant_expression_value(); |
||
1725 | |||
1726 | if (constant != NULL) |
||
1727 | result = constant; |
||
1728 | else |
||
1729 | all_parameters_are_constant = false; |
||
1730 | |||
1731 | if (result != ir) { |
||
1732 | ir->replace_with(result); |
||
1733 | } |
||
1734 | } |
||
1735 | |||
1736 | /* If all of the parameters are trivially constant, create a |
||
1737 | * constant representing the complete collection of parameters. |
||
1738 | */ |
||
1739 | if (all_parameters_are_constant) { |
||
1740 | return new(ctx) ir_constant(constructor_type, &actual_parameters); |
||
1741 | } else if (constructor_type->is_scalar()) { |
||
1742 | return dereference_component((ir_rvalue *) actual_parameters.head, |
||
1743 | 0); |
||
1744 | } else if (constructor_type->is_vector()) { |
||
1745 | return emit_inline_vector_constructor(constructor_type, |
||
1746 | instructions, |
||
1747 | &actual_parameters, |
||
1748 | ctx); |
||
1749 | } else { |
||
1750 | assert(constructor_type->is_matrix()); |
||
1751 | return emit_inline_matrix_constructor(constructor_type, |
||
1752 | instructions, |
||
1753 | &actual_parameters, |
||
1754 | ctx); |
||
1755 | } |
||
1756 | } else { |
||
1757 | const ast_expression *id = subexpressions[0]; |
||
1758 | const char *func_name = id->primary_expression.identifier; |
||
1759 | YYLTYPE loc = get_location(); |
||
1760 | exec_list actual_parameters; |
||
1761 | |||
1762 | process_parameters(instructions, &actual_parameters, &this->expressions, |
||
1763 | state); |
||
1764 | |||
1765 | ir_function_signature *sig = |
||
1766 | match_function_by_name(func_name, &actual_parameters, state); |
||
1767 | |||
1768 | ir_rvalue *value = NULL; |
||
1769 | if (sig == NULL) { |
||
1770 | no_matching_function_error(func_name, &loc, &actual_parameters, state); |
||
1771 | value = ir_rvalue::error_value(ctx); |
||
1772 | } else if (!verify_parameter_modes(state, sig, actual_parameters, this->expressions)) { |
||
1773 | /* an error has already been emitted */ |
||
1774 | value = ir_rvalue::error_value(ctx); |
||
1775 | } else { |
||
1776 | value = generate_call(instructions, sig, &actual_parameters, state); |
||
1777 | } |
||
1778 | |||
1779 | return value; |
||
1780 | } |
||
1781 | |||
1782 | unreachable("not reached"); |
||
1783 | } |
||
1784 | |||
1785 | ir_rvalue * |
||
1786 | ast_aggregate_initializer::hir(exec_list *instructions, |
||
1787 | struct _mesa_glsl_parse_state *state) |
||
1788 | { |
||
1789 | void *ctx = state; |
||
1790 | YYLTYPE loc = this->get_location(); |
||
1791 | |||
1792 | if (!this->constructor_type) { |
||
1793 | _mesa_glsl_error(&loc, state, "type of C-style initializer unknown"); |
||
1794 | return ir_rvalue::error_value(ctx); |
||
1795 | } |
||
1796 | const glsl_type *const constructor_type = this->constructor_type; |
||
1797 | |||
1798 | if (!state->ARB_shading_language_420pack_enable) { |
||
1799 | _mesa_glsl_error(&loc, state, "C-style initialization requires the " |
||
1800 | "GL_ARB_shading_language_420pack extension"); |
||
1801 | return ir_rvalue::error_value(ctx); |
||
1802 | } |
||
1803 | |||
1804 | if (constructor_type->is_array()) { |
||
1805 | return process_array_constructor(instructions, constructor_type, &loc, |
||
1806 | &this->expressions, state); |
||
1807 | } |
||
1808 | |||
1809 | if (constructor_type->is_record()) { |
||
1810 | return process_record_constructor(instructions, constructor_type, &loc, |
||
1811 | &this->expressions, state); |
||
1812 | } |
||
1813 | |||
1814 | return process_vec_mat_constructor(instructions, constructor_type, &loc, |
||
1815 | &this->expressions, state); |
||
1816 | }>>>>>>><>>>>>>>>>><>><>>><>><>><>><>>><>=>><>>=>>=>=> |