diff options
Diffstat (limited to 'ast_function.cpp')
-rw-r--r-- | ast_function.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/ast_function.cpp b/ast_function.cpp new file mode 100644 index 00000000000..2e0cbe9e132 --- /dev/null +++ b/ast_function.cpp @@ -0,0 +1,109 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <cstdio> +#include "symbol_table.h" +#include "ast.h" +#include "glsl_types.h" +#include "ir.h" + +ir_instruction * +ast_function_expression::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + /* There are three sorts of function calls. + * + * 1. contstructors - The first subexpression is an ast_type_specifier. + * 2. methods - Only the .length() method of array types. + * 3. functions - Calls to regular old functions. + * + * There are two kinds of constructor call. Constructors for built-in + * language types, such as mat4 and vec2, are free form. The only + * requirement is that the parameters must provide enough values of the + * correct scalar type. Constructors for arrays and structures must have + * the exact number of parameters with matching types in the correct order. + * These constructors follow essentially the same type matching rules as + * functions. + * + * Method calls are actually detected when the ast_field_selection + * expression is handled. + */ + if (is_constructor()) { + return ir_call::get_error_instruction(); + } else { + const ast_expression *id = subexpressions[0]; + + ir_function *f = (ir_function *) + _mesa_symbol_table_find_symbol(state->symbols, 0, + id->primary_expression.identifier); + + if (f == NULL) { + YYLTYPE loc = id->get_location(); + + _mesa_glsl_error(& loc, state, "function `%s' undeclared", + id->primary_expression.identifier); + return ir_call::get_error_instruction(); + } + + /* Once we've determined that the function being called might exist, + * process the parameters. + */ + exec_list actual_parameters; + simple_node *const first = subexpressions[1]; + if (first != NULL) { + simple_node *ptr = first; + do { + ir_instruction *const result = + ((ast_node *) ptr)->hir(instructions, state); + ptr = ptr->next; + + actual_parameters.push_tail(result); + } while (ptr != first); + } + + /* After processing the function's actual parameters, try to find an + * overload of the function that matches. + */ + const ir_function_signature *sig = + f->matching_signature(& actual_parameters); + if (sig != NULL) { + /* FINISHME: The list of actual parameters needs to be modified to + * FINISHME: include any necessary conversions. + */ + return new ir_call(sig, & actual_parameters); + } else { + YYLTYPE loc = id->get_location(); + + /* FINISHME: Log a better error message here. G++ will show the types + * FINISHME: of the actual parameters and the set of candidate + * FINISHME: functions. A different error should also be logged when + * FINISHME: multiple functions match. + */ + _mesa_glsl_error(& loc, state, "no matching function for call to `%s'", + id->primary_expression.identifier); + return ir_call::get_error_instruction(); + } + } + + return ir_call::get_error_instruction(); +} |