+ /* Copy the temporary variable to the actual parameter with optional
+ * type conversion applied.
+ */
+ ir_rvalue *rhs = new(mem_ctx) ir_dereference_variable(tmp);
+ if (actual->type != formal_type)
+ rhs = convert_component(rhs, actual->type);
+
+ ir_rvalue *lhs = actual;
+ if (expr != NULL && expr->operation == ir_binop_vector_extract) {
+ rhs = new(mem_ctx) ir_expression(ir_triop_vector_insert,
+ expr->operands[0]->type,
+ expr->operands[0]->clone(mem_ctx, NULL),
+ rhs,
+ expr->operands[1]->clone(mem_ctx, NULL));
+ lhs = expr->operands[0]->clone(mem_ctx, NULL);
+ }
+
+ ir_assignment *const assignment_2 = new(mem_ctx) ir_assignment(lhs, rhs);
+ after_instructions->push_tail(assignment_2);
+}
+
+/**
+ * If a function call is generated, \c call_ir will point to it on exit.
+ * Otherwise \c call_ir will be set to \c NULL.
+ */
+static ir_rvalue *
+generate_call(exec_list *instructions, ir_function_signature *sig,
+ exec_list *actual_parameters,
+ ir_call **call_ir,
+ struct _mesa_glsl_parse_state *state)
+{
+ void *ctx = state;
+ exec_list post_call_conversions;
+
+ *call_ir = NULL;
+
+ /* Perform implicit conversion of arguments. For out parameters, we need
+ * to place them in a temporary variable and do the conversion after the
+ * call takes place. Since we haven't emitted the call yet, we'll place
+ * the post-call conversions in a temporary exec_list, and emit them later.
+ */
+ exec_list_iterator actual_iter = actual_parameters->iterator();
+ exec_list_iterator formal_iter = sig->parameters.iterator();
+
+ while (actual_iter.has_next()) {
+ ir_rvalue *actual = (ir_rvalue *) actual_iter.get();
+ ir_variable *formal = (ir_variable *) formal_iter.get();
+
+ assert(actual != NULL);
+ assert(formal != NULL);
+
+ if (formal->type->is_numeric() || formal->type->is_boolean()) {
+ switch (formal->mode) {
+ case ir_var_const_in:
+ case ir_var_function_in: {
+ ir_rvalue *converted
+ = convert_component(actual, formal->type);
+ actual->replace_with(converted);
+ break;
+ }
+ case ir_var_function_out:
+ case ir_var_function_inout:
+ fix_parameter(ctx, actual, formal->type,
+ instructions, &post_call_conversions,
+ formal->mode == ir_var_function_inout);
+ break;
+ default:
+ assert (!"Illegal formal parameter mode");
+ break;
+ }