1/* Manipulation of formal and actual parameters of functions and function
2 calls.
3 Copyright (C) 2017 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "backend.h"
25#include "rtl.h"
26#include "tree.h"
27#include "gimple.h"
28#include "ssa.h"
29#include "cgraph.h"
30#include "fold-const.h"
31#include "stor-layout.h"
32#include "gimplify.h"
33#include "gimple-iterator.h"
34#include "gimplify-me.h"
35#include "tree-dfa.h"
36#include "ipa-param-manipulation.h"
37#include "print-tree.h"
38#include "gimple-pretty-print.h"
39#include "builtins.h"
40
41/* Return a heap allocated vector containing formal parameters of FNDECL. */
42
43vec<tree>
44ipa_get_vector_of_formal_parms (tree fndecl)
45{
46 vec<tree> args;
47 int count;
48 tree parm;
49
50 gcc_assert (!flag_wpa);
51 count = 0;
52 for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
53 count++;
54
55 args.create (count);
56 for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
57 args.quick_push (parm);
58
59 return args;
60}
61
62/* Return a heap allocated vector containing types of formal parameters of
63 function type FNTYPE. */
64
65vec<tree>
66ipa_get_vector_of_formal_parm_types (tree fntype)
67{
68 vec<tree> types;
69 int count = 0;
70 tree t;
71
72 for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
73 count++;
74
75 types.create (count);
76 for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
77 types.quick_push (TREE_VALUE (t));
78
79 return types;
80}
81
82/* Modify the function declaration FNDECL and its type according to the plan in
83 ADJUSTMENTS. It also sets base fields of individual adjustments structures
84 to reflect the actual parameters being modified which are determined by the
85 base_index field. */
86
87void
88ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments)
89{
90 vec<tree> oparms = ipa_get_vector_of_formal_parms (fndecl);
91 tree orig_type = TREE_TYPE (fndecl);
92 tree old_arg_types = TYPE_ARG_TYPES (orig_type);
93
94 /* The following test is an ugly hack, some functions simply don't have any
95 arguments in their type. This is probably a bug but well... */
96 bool care_for_types = (old_arg_types != NULL_TREE);
97 bool last_parm_void;
98 vec<tree> otypes;
99 if (care_for_types)
100 {
101 last_parm_void = (TREE_VALUE (tree_last (old_arg_types))
102 == void_type_node);
103 otypes = ipa_get_vector_of_formal_parm_types (orig_type);
104 if (last_parm_void)
105 gcc_assert (oparms.length () + 1 == otypes.length ());
106 else
107 gcc_assert (oparms.length () == otypes.length ());
108 }
109 else
110 {
111 last_parm_void = false;
112 otypes.create (0);
113 }
114
115 int len = adjustments.length ();
116 tree *link = &DECL_ARGUMENTS (fndecl);
117 tree new_arg_types = NULL;
118 for (int i = 0; i < len; i++)
119 {
120 struct ipa_parm_adjustment *adj;
121 gcc_assert (link);
122
123 adj = &adjustments[i];
124 tree parm;
125 if (adj->op == IPA_PARM_OP_NEW)
126 parm = NULL;
127 else
128 parm = oparms[adj->base_index];
129 adj->base = parm;
130
131 if (adj->op == IPA_PARM_OP_COPY)
132 {
133 if (care_for_types)
134 new_arg_types = tree_cons (NULL_TREE, otypes[adj->base_index],
135 new_arg_types);
136 *link = parm;
137 link = &DECL_CHAIN (parm);
138 }
139 else if (adj->op != IPA_PARM_OP_REMOVE)
140 {
141 tree new_parm;
142 tree ptype;
143
144 if (adj->by_ref)
145 ptype = build_pointer_type (adj->type);
146 else
147 {
148 ptype = adj->type;
149 if (is_gimple_reg_type (ptype)
150 && TYPE_MODE (ptype) != BLKmode)
151 {
152 unsigned malign = GET_MODE_ALIGNMENT (TYPE_MODE (ptype));
153 if (TYPE_ALIGN (ptype) != malign)
154 ptype = build_aligned_type (ptype, malign);
155 }
156 }
157
158 if (care_for_types)
159 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
160
161 new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE,
162 ptype);
163 const char *prefix = adj->arg_prefix ? adj->arg_prefix : "SYNTH";
164 DECL_NAME (new_parm) = create_tmp_var_name (prefix);
165 DECL_ARTIFICIAL (new_parm) = 1;
166 DECL_ARG_TYPE (new_parm) = ptype;
167 DECL_CONTEXT (new_parm) = fndecl;
168 TREE_USED (new_parm) = 1;
169 DECL_IGNORED_P (new_parm) = 1;
170 layout_decl (new_parm, 0);
171
172 if (adj->op == IPA_PARM_OP_NEW)
173 adj->base = NULL;
174 else
175 adj->base = parm;
176 adj->new_decl = new_parm;
177
178 *link = new_parm;
179 link = &DECL_CHAIN (new_parm);
180 }
181 }
182
183 *link = NULL_TREE;
184
185 tree new_reversed = NULL;
186 if (care_for_types)
187 {
188 new_reversed = nreverse (new_arg_types);
189 if (last_parm_void)
190 {
191 if (new_reversed)
192 TREE_CHAIN (new_arg_types) = void_list_node;
193 else
194 new_reversed = void_list_node;
195 }
196 }
197
198 /* Use copy_node to preserve as much as possible from original type
199 (debug info, attribute lists etc.)
200 Exception is METHOD_TYPEs must have THIS argument.
201 When we are asked to remove it, we need to build new FUNCTION_TYPE
202 instead. */
203 tree new_type = NULL;
204 if (TREE_CODE (orig_type) != METHOD_TYPE
205 || (adjustments[0].op == IPA_PARM_OP_COPY
206 && adjustments[0].base_index == 0))
207 {
208 new_type = build_distinct_type_copy (orig_type);
209 TYPE_ARG_TYPES (new_type) = new_reversed;
210 }
211 else
212 {
213 new_type
214 = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
215 new_reversed));
216 TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
217 DECL_VINDEX (fndecl) = NULL_TREE;
218 }
219
220 /* When signature changes, we need to clear builtin info. */
221 if (DECL_BUILT_IN (fndecl))
222 {
223 DECL_BUILT_IN_CLASS (fndecl) = NOT_BUILT_IN;
224 DECL_FUNCTION_CODE (fndecl) = (enum built_in_function) 0;
225 }
226
227 TREE_TYPE (fndecl) = new_type;
228 DECL_VIRTUAL_P (fndecl) = 0;
229 DECL_LANG_SPECIFIC (fndecl) = NULL;
230 otypes.release ();
231 oparms.release ();
232}
233
234/* Modify actual arguments of a function call CS as indicated in ADJUSTMENTS.
235 If this is a directly recursive call, CS must be NULL. Otherwise it must
236 contain the corresponding call graph edge. */
237
238void
239ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
240 ipa_parm_adjustment_vec adjustments)
241{
242 struct cgraph_node *current_node = cgraph_node::get (current_function_decl);
243 vec<tree> vargs;
244 vec<tree, va_gc> **debug_args = NULL;
245 gcall *new_stmt;
246 gimple_stmt_iterator gsi, prev_gsi;
247 tree callee_decl;
248 int i, len;
249
250 len = adjustments.length ();
251 vargs.create (len);
252 callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
253 current_node->remove_stmt_references (stmt);
254
255 gsi = gsi_for_stmt (stmt);
256 prev_gsi = gsi;
257 gsi_prev (&prev_gsi);
258 for (i = 0; i < len; i++)
259 {
260 struct ipa_parm_adjustment *adj;
261
262 adj = &adjustments[i];
263
264 if (adj->op == IPA_PARM_OP_COPY)
265 {
266 tree arg = gimple_call_arg (stmt, adj->base_index);
267
268 vargs.quick_push (arg);
269 }
270 else if (adj->op != IPA_PARM_OP_REMOVE)
271 {
272 tree expr, base, off;
273 location_t loc;
274 unsigned int deref_align = 0;
275 bool deref_base = false;
276
277 /* We create a new parameter out of the value of the old one, we can
278 do the following kind of transformations:
279
280 - A scalar passed by reference is converted to a scalar passed by
281 value. (adj->by_ref is false and the type of the original
282 actual argument is a pointer to a scalar).
283
284 - A part of an aggregate is passed instead of the whole aggregate.
285 The part can be passed either by value or by reference, this is
286 determined by value of adj->by_ref. Moreover, the code below
287 handles both situations when the original aggregate is passed by
288 value (its type is not a pointer) and when it is passed by
289 reference (it is a pointer to an aggregate).
290
291 When the new argument is passed by reference (adj->by_ref is true)
292 it must be a part of an aggregate and therefore we form it by
293 simply taking the address of a reference inside the original
294 aggregate. */
295
296 gcc_checking_assert (adj->offset % BITS_PER_UNIT == 0);
297 base = gimple_call_arg (stmt, adj->base_index);
298 loc = DECL_P (base) ? DECL_SOURCE_LOCATION (base)
299 : EXPR_LOCATION (base);
300
301 if (TREE_CODE (base) != ADDR_EXPR
302 && POINTER_TYPE_P (TREE_TYPE (base)))
303 off = build_int_cst (adj->alias_ptr_type,
304 adj->offset / BITS_PER_UNIT);
305 else
306 {
307 HOST_WIDE_INT base_offset;
308 tree prev_base;
309 bool addrof;
310
311 if (TREE_CODE (base) == ADDR_EXPR)
312 {
313 base = TREE_OPERAND (base, 0);
314 addrof = true;
315 }
316 else
317 addrof = false;
318 prev_base = base;
319 base = get_addr_base_and_unit_offset (base, &base_offset);
320 /* Aggregate arguments can have non-invariant addresses. */
321 if (!base)
322 {
323 base = build_fold_addr_expr (prev_base);
324 off = build_int_cst (adj->alias_ptr_type,
325 adj->offset / BITS_PER_UNIT);
326 }
327 else if (TREE_CODE (base) == MEM_REF)
328 {
329 if (!addrof)
330 {
331 deref_base = true;
332 deref_align = TYPE_ALIGN (TREE_TYPE (base));
333 }
334 off = build_int_cst (adj->alias_ptr_type,
335 base_offset
336 + adj->offset / BITS_PER_UNIT);
337 off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1),
338 off);
339 base = TREE_OPERAND (base, 0);
340 }
341 else
342 {
343 off = build_int_cst (adj->alias_ptr_type,
344 base_offset
345 + adj->offset / BITS_PER_UNIT);
346 base = build_fold_addr_expr (base);
347 }
348 }
349
350 if (!adj->by_ref)
351 {
352 tree type = adj->type;
353 unsigned int align;
354 unsigned HOST_WIDE_INT misalign;
355
356 if (deref_base)
357 {
358 align = deref_align;
359 misalign = 0;
360 }
361 else
362 {
363 get_pointer_alignment_1 (base, &align, &misalign);
364 if (TYPE_ALIGN (type) > align)
365 align = TYPE_ALIGN (type);
366 }
367 misalign += (offset_int::from (wi::to_wide (off),
368 SIGNED).to_short_addr ()
369 * BITS_PER_UNIT);
370 misalign = misalign & (align - 1);
371 if (misalign != 0)
372 align = least_bit_hwi (misalign);
373 if (align < TYPE_ALIGN (type))
374 type = build_aligned_type (type, align);
375 base = force_gimple_operand_gsi (&gsi, base,
376 true, NULL, true, GSI_SAME_STMT);
377 expr = fold_build2_loc (loc, MEM_REF, type, base, off);
378 REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
379 /* If expr is not a valid gimple call argument emit
380 a load into a temporary. */
381 if (is_gimple_reg_type (TREE_TYPE (expr)))
382 {
383 gimple *tem = gimple_build_assign (NULL_TREE, expr);
384 if (gimple_in_ssa_p (cfun))
385 {
386 gimple_set_vuse (tem, gimple_vuse (stmt));
387 expr = make_ssa_name (TREE_TYPE (expr), tem);
388 }
389 else
390 expr = create_tmp_reg (TREE_TYPE (expr));
391 gimple_assign_set_lhs (tem, expr);
392 gsi_insert_before (&gsi, tem, GSI_SAME_STMT);
393 }
394 }
395 else
396 {
397 expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off);
398 REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
399 expr = build_fold_addr_expr (expr);
400 expr = force_gimple_operand_gsi (&gsi, expr,
401 true, NULL, true, GSI_SAME_STMT);
402 }
403 vargs.quick_push (expr);
404 }
405 if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_BIND_STMTS)
406 {
407 unsigned int ix;
408 tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg;
409 gimple *def_temp;
410
411 arg = gimple_call_arg (stmt, adj->base_index);
412 if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
413 {
414 if (!fold_convertible_p (TREE_TYPE (origin), arg))
415 continue;
416 arg = fold_convert_loc (gimple_location (stmt),
417 TREE_TYPE (origin), arg);
418 }
419 if (debug_args == NULL)
420 debug_args = decl_debug_args_insert (callee_decl);
421 for (ix = 0; vec_safe_iterate (*debug_args, ix, &ddecl); ix += 2)
422 if (ddecl == origin)
423 {
424 ddecl = (**debug_args)[ix + 1];
425 break;
426 }
427 if (ddecl == NULL)
428 {
429 ddecl = make_node (DEBUG_EXPR_DECL);
430 DECL_ARTIFICIAL (ddecl) = 1;
431 TREE_TYPE (ddecl) = TREE_TYPE (origin);
432 SET_DECL_MODE (ddecl, DECL_MODE (origin));
433
434 vec_safe_push (*debug_args, origin);
435 vec_safe_push (*debug_args, ddecl);
436 }
437 def_temp = gimple_build_debug_bind (ddecl, unshare_expr (arg), stmt);
438 gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
439 }
440 }
441
442 if (dump_file && (dump_flags & TDF_DETAILS))
443 {
444 fprintf (dump_file, "replacing stmt:");
445 print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
446 }
447
448 new_stmt = gimple_build_call_vec (callee_decl, vargs);
449 vargs.release ();
450 if (gimple_call_lhs (stmt))
451 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
452
453 gimple_set_block (new_stmt, gimple_block (stmt));
454 if (gimple_has_location (stmt))
455 gimple_set_location (new_stmt, gimple_location (stmt));
456 gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
457 gimple_call_copy_flags (new_stmt, stmt);
458 if (gimple_in_ssa_p (cfun))
459 {
460 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
461 if (gimple_vdef (stmt))
462 {
463 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
464 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
465 }
466 }
467
468 if (dump_file && (dump_flags & TDF_DETAILS))
469 {
470 fprintf (dump_file, "with stmt:");
471 print_gimple_stmt (dump_file, new_stmt, 0);
472 fprintf (dump_file, "\n");
473 }
474 gsi_replace (&gsi, new_stmt, true);
475 if (cs)
476 cs->set_call_stmt (new_stmt);
477 do
478 {
479 current_node->record_stmt_references (gsi_stmt (gsi));
480 gsi_prev (&gsi);
481 }
482 while (gsi_stmt (gsi) != gsi_stmt (prev_gsi));
483}
484
485/* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */
486
487static bool
488index_in_adjustments_multiple_times_p (int base_index,
489 ipa_parm_adjustment_vec adjustments)
490{
491 int i, len = adjustments.length ();
492 bool one = false;
493
494 for (i = 0; i < len; i++)
495 {
496 struct ipa_parm_adjustment *adj;
497 adj = &adjustments[i];
498
499 if (adj->base_index == base_index)
500 {
501 if (one)
502 return true;
503 else
504 one = true;
505 }
506 }
507 return false;
508}
509
510/* Return adjustments that should have the same effect on function parameters
511 and call arguments as if they were first changed according to adjustments in
512 INNER and then by adjustments in OUTER. */
513
514ipa_parm_adjustment_vec
515ipa_combine_adjustments (ipa_parm_adjustment_vec inner,
516 ipa_parm_adjustment_vec outer)
517{
518 int i, outlen = outer.length ();
519 int inlen = inner.length ();
520 int removals = 0;
521 ipa_parm_adjustment_vec adjustments, tmp;
522
523 tmp.create (inlen);
524 for (i = 0; i < inlen; i++)
525 {
526 struct ipa_parm_adjustment *n;
527 n = &inner[i];
528
529 if (n->op == IPA_PARM_OP_REMOVE)
530 removals++;
531 else
532 {
533 /* FIXME: Handling of new arguments are not implemented yet. */
534 gcc_assert (n->op != IPA_PARM_OP_NEW);
535 tmp.quick_push (*n);
536 }
537 }
538
539 adjustments.create (outlen + removals);
540 for (i = 0; i < outlen; i++)
541 {
542 struct ipa_parm_adjustment r;
543 struct ipa_parm_adjustment *out = &outer[i];
544 struct ipa_parm_adjustment *in = &tmp[out->base_index];
545
546 memset (&r, 0, sizeof (r));
547 gcc_assert (in->op != IPA_PARM_OP_REMOVE);
548 if (out->op == IPA_PARM_OP_REMOVE)
549 {
550 if (!index_in_adjustments_multiple_times_p (in->base_index, tmp))
551 {
552 r.op = IPA_PARM_OP_REMOVE;
553 adjustments.quick_push (r);
554 }
555 continue;
556 }
557 else
558 {
559 /* FIXME: Handling of new arguments are not implemented yet. */
560 gcc_assert (out->op != IPA_PARM_OP_NEW);
561 }
562
563 r.base_index = in->base_index;
564 r.type = out->type;
565
566 /* FIXME: Create nonlocal value too. */
567
568 if (in->op == IPA_PARM_OP_COPY && out->op == IPA_PARM_OP_COPY)
569 r.op = IPA_PARM_OP_COPY;
570 else if (in->op == IPA_PARM_OP_COPY)
571 r.offset = out->offset;
572 else if (out->op == IPA_PARM_OP_COPY)
573 r.offset = in->offset;
574 else
575 r.offset = in->offset + out->offset;
576 adjustments.quick_push (r);
577 }
578
579 for (i = 0; i < inlen; i++)
580 {
581 struct ipa_parm_adjustment *n = &inner[i];
582
583 if (n->op == IPA_PARM_OP_REMOVE)
584 adjustments.quick_push (*n);
585 }
586
587 tmp.release ();
588 return adjustments;
589}
590
591/* If T is an SSA_NAME, return NULL if it is not a default def or
592 return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
593 the base variable is always returned, regardless if it is a default
594 def. Return T if it is not an SSA_NAME. */
595
596static tree
597get_ssa_base_param (tree t, bool ignore_default_def)
598{
599 if (TREE_CODE (t) == SSA_NAME)
600 {
601 if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
602 return SSA_NAME_VAR (t);
603 else
604 return NULL_TREE;
605 }
606 return t;
607}
608
609/* Given an expression, return an adjustment entry specifying the
610 transformation to be done on EXPR. If no suitable adjustment entry
611 was found, returns NULL.
612
613 If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a
614 default def, otherwise bail on them.
615
616 If CONVERT is non-NULL, this function will set *CONVERT if the
617 expression provided is a component reference. ADJUSTMENTS is the
618 adjustments vector. */
619
620ipa_parm_adjustment *
621ipa_get_adjustment_candidate (tree **expr, bool *convert,
622 ipa_parm_adjustment_vec adjustments,
623 bool ignore_default_def)
624{
625 if (TREE_CODE (**expr) == BIT_FIELD_REF
626 || TREE_CODE (**expr) == IMAGPART_EXPR
627 || TREE_CODE (**expr) == REALPART_EXPR)
628 {
629 *expr = &TREE_OPERAND (**expr, 0);
630 if (convert)
631 *convert = true;
632 }
633
634 HOST_WIDE_INT offset, size, max_size;
635 bool reverse;
636 tree base
637 = get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse);
638 if (!base || size == -1 || max_size == -1)
639 return NULL;
640
641 if (TREE_CODE (base) == MEM_REF)
642 {
643 offset += mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
644 base = TREE_OPERAND (base, 0);
645 }
646
647 base = get_ssa_base_param (base, ignore_default_def);
648 if (!base || TREE_CODE (base) != PARM_DECL)
649 return NULL;
650
651 struct ipa_parm_adjustment *cand = NULL;
652 unsigned int len = adjustments.length ();
653 for (unsigned i = 0; i < len; i++)
654 {
655 struct ipa_parm_adjustment *adj = &adjustments[i];
656
657 if (adj->base == base
658 && (adj->offset == offset || adj->op == IPA_PARM_OP_REMOVE))
659 {
660 cand = adj;
661 break;
662 }
663 }
664
665 if (!cand || cand->op == IPA_PARM_OP_COPY || cand->op == IPA_PARM_OP_REMOVE)
666 return NULL;
667 return cand;
668}
669
670/* If the expression *EXPR should be replaced by a reduction of a parameter, do
671 so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
672 specifies whether the function should care about type incompatibility the
673 current and new expressions. If it is false, the function will leave
674 incompatibility issues to the caller. Return true iff the expression
675 was modified. */
676
677bool
678ipa_modify_expr (tree *expr, bool convert,
679 ipa_parm_adjustment_vec adjustments)
680{
681 struct ipa_parm_adjustment *cand
682 = ipa_get_adjustment_candidate (&expr, &convert, adjustments, false);
683 if (!cand)
684 return false;
685
686 tree src;
687 if (cand->by_ref)
688 {
689 src = build_simple_mem_ref (cand->new_decl);
690 REF_REVERSE_STORAGE_ORDER (src) = cand->reverse;
691 }
692 else
693 src = cand->new_decl;
694
695 if (dump_file && (dump_flags & TDF_DETAILS))
696 {
697 fprintf (dump_file, "About to replace expr ");
698 print_generic_expr (dump_file, *expr);
699 fprintf (dump_file, " with ");
700 print_generic_expr (dump_file, src);
701 fprintf (dump_file, "\n");
702 }
703
704 if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
705 {
706 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
707 *expr = vce;
708 }
709 else
710 *expr = src;
711 return true;
712}
713
714/* Dump the adjustments in the vector ADJUSTMENTS to dump_file in a human
715 friendly way, assuming they are meant to be applied to FNDECL. */
716
717void
718ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
719 tree fndecl)
720{
721 int i, len = adjustments.length ();
722 bool first = true;
723 vec<tree> parms = ipa_get_vector_of_formal_parms (fndecl);
724
725 fprintf (file, "IPA param adjustments: ");
726 for (i = 0; i < len; i++)
727 {
728 struct ipa_parm_adjustment *adj;
729 adj = &adjustments[i];
730
731 if (!first)
732 fprintf (file, " ");
733 else
734 first = false;
735
736 fprintf (file, "%i. base_index: %i - ", i, adj->base_index);
737 print_generic_expr (file, parms[adj->base_index]);
738 if (adj->base)
739 {
740 fprintf (file, ", base: ");
741 print_generic_expr (file, adj->base);
742 }
743 if (adj->new_decl)
744 {
745 fprintf (file, ", new_decl: ");
746 print_generic_expr (file, adj->new_decl);
747 }
748 if (adj->new_ssa_base)
749 {
750 fprintf (file, ", new_ssa_base: ");
751 print_generic_expr (file, adj->new_ssa_base);
752 }
753
754 if (adj->op == IPA_PARM_OP_COPY)
755 fprintf (file, ", copy_param");
756 else if (adj->op == IPA_PARM_OP_REMOVE)
757 fprintf (file, ", remove_param");
758 else
759 fprintf (file, ", offset %li", (long) adj->offset);
760 if (adj->by_ref)
761 fprintf (file, ", by_ref");
762 print_node_brief (file, ", type: ", adj->type, 0);
763 fprintf (file, "\n");
764 }
765 parms.release ();
766}
767
768