1 /* Analysis of polymorphic call context.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "double-int.h"
35 #include "fold-const.h"
36 #include "print-tree.h"
39 #include "hard-reg-set.h"
43 #include "statistics.h"
45 #include "fixed-value.h"
46 #include "insn-config.h"
54 #include "tree-pass.h"
56 #include "tree-pretty-print.h"
58 #include "basic-block.h"
61 #include "plugin-api.h"
64 #include "ipa-utils.h"
65 #include "tree-ssa-alias.h"
66 #include "internal-fn.h"
67 #include "gimple-fold.h"
68 #include "gimple-expr.h"
70 #include "alloc-pool.h"
71 #include "symbol-summary.h"
73 #include "ipa-inline.h"
74 #include "diagnostic.h"
78 #include "gimple-pretty-print.h"
79 #include "stor-layout.h"
81 #include "data-streamer.h"
82 #include "lto-streamer.h"
83 #include "streamer-hooks.h"
84 #include "tree-ssa-operands.h"
85 #include "tree-into-ssa.h"
87 /* Return true when TYPE contains an polymorphic type and thus is interesting
88 for devirtualization machinery. */
90 static bool contains_type_p (tree
, HOST_WIDE_INT
, tree
,
91 bool consider_placement_new
= true,
92 bool consider_bases
= true);
95 contains_polymorphic_type_p (const_tree type
)
97 type
= TYPE_MAIN_VARIANT (type
);
99 if (RECORD_OR_UNION_TYPE_P (type
))
101 if (TYPE_BINFO (type
)
102 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
104 for (tree fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
105 if (TREE_CODE (fld
) == FIELD_DECL
106 && !DECL_ARTIFICIAL (fld
)
107 && contains_polymorphic_type_p (TREE_TYPE (fld
)))
111 if (TREE_CODE (type
) == ARRAY_TYPE
)
112 return contains_polymorphic_type_p (TREE_TYPE (type
));
116 /* Return true if it seems valid to use placement new to build EXPECTED_TYPE
117 at possition CUR_OFFSET within TYPE.
119 POD can be changed to an instance of a polymorphic type by
120 placement new. Here we play safe and assume that any
121 non-polymorphic type is POD. */
123 possible_placement_new (tree type
, tree expected_type
,
124 HOST_WIDE_INT cur_offset
)
126 return ((TREE_CODE (type
) != RECORD_TYPE
127 || !TYPE_BINFO (type
)
128 || cur_offset
>= POINTER_SIZE
129 || !polymorphic_type_binfo_p (TYPE_BINFO (type
)))
130 && (!TYPE_SIZE (type
)
131 || !tree_fits_shwi_p (TYPE_SIZE (type
))
133 + (expected_type
? tree_to_uhwi (TYPE_SIZE (expected_type
))
135 <= tree_to_uhwi (TYPE_SIZE (type
)))));
138 /* THIS->OUTER_TYPE is a type of memory object where object of OTR_TYPE
139 is contained at THIS->OFFSET. Walk the memory representation of
140 THIS->OUTER_TYPE and find the outermost class type that match
141 OTR_TYPE or contain OTR_TYPE as a base. Update THIS
144 If OTR_TYPE is NULL, just find outermost polymorphic type with
145 virtual table present at possition OFFSET.
147 For example when THIS represents type
153 and we look for type at offset sizeof(int), we end up with B and offset 0.
154 If the same is produced by multiple inheritance, we end up with A and offset
157 If we can not find corresponding class, give up by setting
158 THIS->OUTER_TYPE to OTR_TYPE and THIS->OFFSET to NULL.
159 Return true when lookup was sucesful.
161 When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
162 valid only via alocation of new polymorphic type inside by means
165 When CONSIDER_BASES is false, only look for actual fields, not base types
169 ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type
,
170 bool consider_placement_new
,
173 tree type
= outer_type
;
174 HOST_WIDE_INT cur_offset
= offset
;
175 bool speculative
= false;
176 bool size_unknown
= false;
177 unsigned HOST_WIDE_INT otr_type_size
= POINTER_SIZE
;
179 /* Update OUTER_TYPE to match EXPECTED_TYPE if it is not set. */
182 clear_outer_type (otr_type
);
186 /* See if OFFSET points inside OUTER_TYPE. If it does not, we know
187 that the context is either invalid, or the instance type must be
188 derived from OUTER_TYPE.
190 Because the instance type may contain field whose type is of OUTER_TYPE,
191 we can not derive any effective information about it.
193 TODO: In the case we know all derrived types, we can definitely do better
195 else if (TYPE_SIZE (outer_type
)
196 && tree_fits_shwi_p (TYPE_SIZE (outer_type
))
197 && tree_to_shwi (TYPE_SIZE (outer_type
)) >= 0
198 && tree_to_shwi (TYPE_SIZE (outer_type
)) <= offset
)
200 clear_outer_type (otr_type
);
204 /* If derived type is not allowed, we know that the context is invalid.
205 For dynamic types, we really do not have information about
206 size of the memory location. It is possible that completely
207 different type is stored after outer_type. */
208 if (!maybe_derived_type
&& !dynamic
)
210 clear_speculation ();
216 if (otr_type
&& TYPE_SIZE (otr_type
)
217 && tree_fits_shwi_p (TYPE_SIZE (otr_type
)))
218 otr_type_size
= tree_to_uhwi (TYPE_SIZE (otr_type
));
220 if (!type
|| offset
< 0)
221 goto no_useful_type_info
;
223 /* Find the sub-object the constant actually refers to and mark whether it is
224 an artificial one (as opposed to a user-defined one).
226 This loop is performed twice; first time for outer_type and second time
227 for speculative_outer_type. The second run has SPECULATIVE set. */
230 unsigned HOST_WIDE_INT pos
, size
;
233 /* If we do not know size of TYPE, we need to be more conservative
234 about accepting cases where we can not find EXPECTED_TYPE.
235 Generally the types that do matter here are of constant size.
236 Size_unknown case should be very rare. */
238 && tree_fits_shwi_p (TYPE_SIZE (type
))
239 && tree_to_shwi (TYPE_SIZE (type
)) >= 0)
240 size_unknown
= false;
244 /* On a match, just return what we found. */
246 && types_odr_comparable (type
, otr_type
)
247 && types_same_for_odr (type
, otr_type
))
249 && TREE_CODE (type
) == RECORD_TYPE
251 && polymorphic_type_binfo_p (TYPE_BINFO (type
))))
255 /* If we did not match the offset, just give up on speculation. */
257 /* Also check if speculation did not end up being same as
259 || (types_must_be_same_for_odr (speculative_outer_type
,
261 && (maybe_derived_type
262 == speculative_maybe_derived_type
)))
263 clear_speculation ();
268 /* If type is known to be final, do not worry about derived
269 types. Testing it here may help us to avoid speculation. */
270 if (otr_type
&& TREE_CODE (outer_type
) == RECORD_TYPE
271 && (!in_lto_p
|| odr_type_p (outer_type
))
272 && type_with_linkage_p (outer_type
)
273 && type_known_to_have_no_derivations_p (outer_type
))
274 maybe_derived_type
= false;
276 /* Type can not contain itself on an non-zero offset. In that case
277 just give up. Still accept the case where size is now known.
278 Either the second copy may appear past the end of type or within
279 the non-POD buffer located inside the variably sized type
282 goto no_useful_type_info
;
283 /* If we determined type precisely or we have no clue on
284 speuclation, we are done. */
285 if (!maybe_derived_type
|| !speculative_outer_type
286 || !speculation_consistent_p (speculative_outer_type
,
288 speculative_maybe_derived_type
,
291 clear_speculation ();
294 /* Otherwise look into speculation now. */
298 type
= speculative_outer_type
;
299 cur_offset
= speculative_offset
;
305 /* Walk fields and find corresponding on at OFFSET. */
306 if (TREE_CODE (type
) == RECORD_TYPE
)
308 for (fld
= TYPE_FIELDS (type
); fld
; fld
= DECL_CHAIN (fld
))
310 if (TREE_CODE (fld
) != FIELD_DECL
)
313 pos
= int_bit_position (fld
);
314 if (pos
> (unsigned HOST_WIDE_INT
)cur_offset
)
317 /* Do not consider vptr itself. Not even for placement new. */
318 if (!pos
&& DECL_ARTIFICIAL (fld
)
319 && POINTER_TYPE_P (TREE_TYPE (fld
))
321 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
324 if (!DECL_SIZE (fld
) || !tree_fits_uhwi_p (DECL_SIZE (fld
)))
325 goto no_useful_type_info
;
326 size
= tree_to_uhwi (DECL_SIZE (fld
));
328 /* We can always skip types smaller than pointer size:
329 those can not contain a virtual table pointer.
331 Disqualifying fields that are too small to fit OTR_TYPE
332 saves work needed to walk them for no benefit.
333 Because of the way the bases are packed into a class, the
334 field's size may be smaller than type size, so it needs
335 to be done with a care. */
337 if (pos
<= (unsigned HOST_WIDE_INT
)cur_offset
338 && (pos
+ size
) >= (unsigned HOST_WIDE_INT
)cur_offset
341 || !TYPE_SIZE (TREE_TYPE (fld
))
342 || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (fld
)))
343 || (pos
+ tree_to_uhwi (TYPE_SIZE (TREE_TYPE (fld
))))
344 >= cur_offset
+ otr_type_size
))
349 goto no_useful_type_info
;
351 type
= TYPE_MAIN_VARIANT (TREE_TYPE (fld
));
353 /* DECL_ARTIFICIAL represents a basetype. */
354 if (!DECL_ARTIFICIAL (fld
))
360 /* As soon as we se an field containing the type,
361 we know we are not looking for derivations. */
362 maybe_derived_type
= false;
366 speculative_outer_type
= type
;
367 speculative_offset
= cur_offset
;
368 speculative_maybe_derived_type
= false;
371 else if (!consider_bases
)
372 goto no_useful_type_info
;
374 else if (TREE_CODE (type
) == ARRAY_TYPE
)
376 tree subtype
= TYPE_MAIN_VARIANT (TREE_TYPE (type
));
378 /* Give up if we don't know array field size.
379 Also give up on non-polymorphic types as they are used
380 as buffers for placement new. */
381 if (!TYPE_SIZE (subtype
)
382 || !tree_fits_shwi_p (TYPE_SIZE (subtype
))
383 || tree_to_shwi (TYPE_SIZE (subtype
)) <= 0
384 || !contains_polymorphic_type_p (subtype
))
385 goto no_useful_type_info
;
387 HOST_WIDE_INT new_offset
= cur_offset
% tree_to_shwi (TYPE_SIZE (subtype
));
389 /* We may see buffer for placement new. In this case the expected type
390 can be bigger than the subtype. */
391 if (TYPE_SIZE (subtype
)
392 && (cur_offset
+ otr_type_size
393 > tree_to_uhwi (TYPE_SIZE (subtype
))))
394 goto no_useful_type_info
;
396 cur_offset
= new_offset
;
397 type
= TYPE_MAIN_VARIANT (subtype
);
402 maybe_derived_type
= false;
406 speculative_outer_type
= type
;
407 speculative_offset
= cur_offset
;
408 speculative_maybe_derived_type
= false;
411 /* Give up on anything else. */
415 if (maybe_derived_type
&& !speculative
416 && TREE_CODE (outer_type
) == RECORD_TYPE
417 && TREE_CODE (otr_type
) == RECORD_TYPE
418 && TYPE_BINFO (otr_type
)
420 && get_binfo_at_offset (TYPE_BINFO (otr_type
), 0, outer_type
))
422 clear_outer_type (otr_type
);
423 if (!speculative_outer_type
424 || !speculation_consistent_p (speculative_outer_type
,
426 speculative_maybe_derived_type
,
428 clear_speculation ();
429 if (speculative_outer_type
)
432 type
= speculative_outer_type
;
433 cur_offset
= speculative_offset
;
438 /* We found no way to embedd EXPECTED_TYPE in TYPE.
439 We still permit two special cases - placement new and
440 the case of variadic types containing themselves. */
442 && consider_placement_new
443 && (size_unknown
|| !type
|| maybe_derived_type
444 || possible_placement_new (type
, otr_type
, cur_offset
)))
446 /* In these weird cases we want to accept the context.
447 In non-speculative run we have no useful outer_type info
448 (TODO: we may eventually want to record upper bound on the
449 type size that can be used to prune the walk),
450 but we still want to consider speculation that may
454 clear_outer_type (otr_type
);
455 if (!speculative_outer_type
456 || !speculation_consistent_p (speculative_outer_type
,
458 speculative_maybe_derived_type
,
460 clear_speculation ();
461 if (speculative_outer_type
)
464 type
= speculative_outer_type
;
465 cur_offset
= speculative_offset
;
471 clear_speculation ();
476 clear_speculation ();
479 clear_outer_type (otr_type
);
487 /* Return true if OUTER_TYPE contains OTR_TYPE at OFFSET.
488 CONSIDER_PLACEMENT_NEW makes function to accept cases where OTR_TYPE can
489 be built within OUTER_TYPE by means of placement new. CONSIDER_BASES makes
490 function to accept cases where OTR_TYPE appears as base of OUTER_TYPE or as
491 base of one of fields of OUTER_TYPE. */
494 contains_type_p (tree outer_type
, HOST_WIDE_INT offset
,
496 bool consider_placement_new
,
499 ipa_polymorphic_call_context context
;
501 /* Check that type is within range. */
504 if (TYPE_SIZE (outer_type
) && TYPE_SIZE (otr_type
)
505 && TREE_CODE (outer_type
) == INTEGER_CST
506 && TREE_CODE (otr_type
) == INTEGER_CST
507 && wi::ltu_p (wi::to_offset (outer_type
), (wi::to_offset (otr_type
) + offset
)))
510 context
.offset
= offset
;
511 context
.outer_type
= TYPE_MAIN_VARIANT (outer_type
);
512 context
.maybe_derived_type
= false;
513 return context
.restrict_to_inner_class (otr_type
, consider_placement_new
, consider_bases
);
517 /* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
518 If CHECK_CLONES is true, also check for clones of ctor/dtors. */
521 inlined_polymorphic_ctor_dtor_block_p (tree block
, bool check_clones
)
523 tree fn
= BLOCK_ABSTRACT_ORIGIN (block
);
524 if (fn
== NULL
|| TREE_CODE (fn
) != FUNCTION_DECL
)
527 if (TREE_CODE (TREE_TYPE (fn
)) != METHOD_TYPE
528 || (!DECL_CXX_CONSTRUCTOR_P (fn
) && !DECL_CXX_DESTRUCTOR_P (fn
)))
533 /* Watch for clones where we constant propagated the first
534 argument (pointer to the instance). */
535 fn
= DECL_ABSTRACT_ORIGIN (fn
);
537 || TREE_CODE (TREE_TYPE (fn
)) != METHOD_TYPE
538 || (!DECL_CXX_CONSTRUCTOR_P (fn
) && !DECL_CXX_DESTRUCTOR_P (fn
)))
542 if (flags_from_decl_or_type (fn
) & (ECF_PURE
| ECF_CONST
))
549 /* We know that the instance is stored in variable or parameter
550 (not dynamically allocated) and we want to disprove the fact
551 that it may be in construction at invocation of CALL.
553 BASE represents memory location where instance is stored.
554 If BASE is NULL, it is assumed to be global memory.
555 OUTER_TYPE is known type of the instance or NULL if not
558 For the variable to be in construction we actually need to
559 be in constructor of corresponding global variable or
560 the inline stack of CALL must contain the constructor.
561 Check this condition. This check works safely only before
562 IPA passes, because inline stacks may become out of date
566 decl_maybe_in_construction_p (tree base
, tree outer_type
,
567 gimple call
, tree function
)
570 outer_type
= TYPE_MAIN_VARIANT (outer_type
);
571 gcc_assert (!base
|| DECL_P (base
));
573 /* After inlining the code unification optimizations may invalidate
574 inline stacks. Also we need to give up on global variables after
575 IPA, because addresses of these may have been propagated to their
577 if (DECL_STRUCT_FUNCTION (function
)->after_inlining
)
580 /* Pure functions can not do any changes on the dynamic type;
581 that require writting to memory. */
582 if ((!base
|| !auto_var_in_fn_p (base
, function
))
583 && flags_from_decl_or_type (function
) & (ECF_PURE
| ECF_CONST
))
586 bool check_clones
= !base
|| is_global_var (base
);
587 for (tree block
= gimple_block (call
); block
&& TREE_CODE (block
) == BLOCK
;
588 block
= BLOCK_SUPERCONTEXT (block
))
589 if (tree fn
= inlined_polymorphic_ctor_dtor_block_p (block
, check_clones
))
591 tree type
= TYPE_METHOD_BASETYPE (TREE_TYPE (fn
));
593 if (!outer_type
|| !types_odr_comparable (type
, outer_type
))
595 if (TREE_CODE (type
) == RECORD_TYPE
597 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
600 else if (types_same_for_odr (type
, outer_type
))
604 if (!base
|| (TREE_CODE (base
) == VAR_DECL
&& is_global_var (base
)))
606 if (TREE_CODE (TREE_TYPE (function
)) != METHOD_TYPE
607 || (!DECL_CXX_CONSTRUCTOR_P (function
)
608 && !DECL_CXX_DESTRUCTOR_P (function
)))
610 if (!DECL_ABSTRACT_ORIGIN (function
))
612 /* Watch for clones where we constant propagated the first
613 argument (pointer to the instance). */
614 function
= DECL_ABSTRACT_ORIGIN (function
);
616 || TREE_CODE (TREE_TYPE (function
)) != METHOD_TYPE
617 || (!DECL_CXX_CONSTRUCTOR_P (function
)
618 && !DECL_CXX_DESTRUCTOR_P (function
)))
621 tree type
= TYPE_METHOD_BASETYPE (TREE_TYPE (function
));
622 if (!outer_type
|| !types_odr_comparable (type
, outer_type
))
624 if (TREE_CODE (type
) == RECORD_TYPE
626 && polymorphic_type_binfo_p (TYPE_BINFO (type
)))
629 else if (types_same_for_odr (type
, outer_type
))
635 /* Dump human readable context to F. If NEWLINE is true, it will be terminated
639 ipa_polymorphic_call_context::dump (FILE *f
, bool newline
) const
643 fprintf (f
, "Call is known to be undefined");
647 fprintf (f
, "nothing known");
648 if (outer_type
|| offset
)
650 fprintf (f
, "Outer type%s:", dynamic
? " (dynamic)":"");
651 print_generic_expr (f
, outer_type
, TDF_SLIM
);
652 if (maybe_derived_type
)
653 fprintf (f
, " (or a derived type)");
654 if (maybe_in_construction
)
655 fprintf (f
, " (maybe in construction)");
656 fprintf (f
, " offset " HOST_WIDE_INT_PRINT_DEC
,
659 if (speculative_outer_type
)
661 if (outer_type
|| offset
)
663 fprintf (f
, "Speculative outer type:");
664 print_generic_expr (f
, speculative_outer_type
, TDF_SLIM
);
665 if (speculative_maybe_derived_type
)
666 fprintf (f
, " (or a derived type)");
667 fprintf (f
, " at offset " HOST_WIDE_INT_PRINT_DEC
,
675 /* Print context to stderr. */
678 ipa_polymorphic_call_context::debug () const
683 /* Stream out the context to OB. */
686 ipa_polymorphic_call_context::stream_out (struct output_block
*ob
) const
688 struct bitpack_d bp
= bitpack_create (ob
->main_stream
);
690 bp_pack_value (&bp
, invalid
, 1);
691 bp_pack_value (&bp
, maybe_in_construction
, 1);
692 bp_pack_value (&bp
, maybe_derived_type
, 1);
693 bp_pack_value (&bp
, speculative_maybe_derived_type
, 1);
694 bp_pack_value (&bp
, dynamic
, 1);
695 bp_pack_value (&bp
, outer_type
!= NULL
, 1);
696 bp_pack_value (&bp
, offset
!= 0, 1);
697 bp_pack_value (&bp
, speculative_outer_type
!= NULL
, 1);
698 streamer_write_bitpack (&bp
);
700 if (outer_type
!= NULL
)
701 stream_write_tree (ob
, outer_type
, true);
703 streamer_write_hwi (ob
, offset
);
704 if (speculative_outer_type
!= NULL
)
706 stream_write_tree (ob
, speculative_outer_type
, true);
707 streamer_write_hwi (ob
, speculative_offset
);
710 gcc_assert (!speculative_offset
);
713 /* Stream in the context from IB and DATA_IN. */
716 ipa_polymorphic_call_context::stream_in (struct lto_input_block
*ib
,
717 struct data_in
*data_in
)
719 struct bitpack_d bp
= streamer_read_bitpack (ib
);
721 invalid
= bp_unpack_value (&bp
, 1);
722 maybe_in_construction
= bp_unpack_value (&bp
, 1);
723 maybe_derived_type
= bp_unpack_value (&bp
, 1);
724 speculative_maybe_derived_type
= bp_unpack_value (&bp
, 1);
725 dynamic
= bp_unpack_value (&bp
, 1);
726 bool outer_type_p
= bp_unpack_value (&bp
, 1);
727 bool offset_p
= bp_unpack_value (&bp
, 1);
728 bool speculative_outer_type_p
= bp_unpack_value (&bp
, 1);
731 outer_type
= stream_read_tree (ib
, data_in
);
735 offset
= (HOST_WIDE_INT
) streamer_read_hwi (ib
);
738 if (speculative_outer_type_p
)
740 speculative_outer_type
= stream_read_tree (ib
, data_in
);
741 speculative_offset
= (HOST_WIDE_INT
) streamer_read_hwi (ib
);
745 speculative_outer_type
= NULL
;
746 speculative_offset
= 0;
750 /* Proudce polymorphic call context for call method of instance
751 that is located within BASE (that is assumed to be a decl) at offset OFF. */
754 ipa_polymorphic_call_context::set_by_decl (tree base
, HOST_WIDE_INT off
)
756 gcc_assert (DECL_P (base
));
757 clear_speculation ();
759 if (!contains_polymorphic_type_p (TREE_TYPE (base
)))
765 outer_type
= TYPE_MAIN_VARIANT (TREE_TYPE (base
));
767 /* Make very conservative assumption that all objects
768 may be in construction.
770 It is up to caller to revisit this via
771 get_dynamic_type or decl_maybe_in_construction_p. */
772 maybe_in_construction
= true;
773 maybe_derived_type
= false;
777 /* CST is an invariant (address of decl), try to get meaningful
778 polymorphic call context for polymorphic call of method
779 if instance of OTR_TYPE that is located at offset OFF of this invariant.
780 Return FALSE if nothing meaningful can be found. */
783 ipa_polymorphic_call_context::set_by_invariant (tree cst
,
787 HOST_WIDE_INT offset2
, size
, max_size
;
792 clear_outer_type (otr_type
);
794 if (TREE_CODE (cst
) != ADDR_EXPR
)
797 cst
= TREE_OPERAND (cst
, 0);
798 base
= get_ref_base_and_extent (cst
, &offset2
, &size
, &max_size
);
799 if (!DECL_P (base
) || max_size
== -1 || max_size
!= size
)
802 /* Only type inconsistent programs can have otr_type that is
803 not part of outer type. */
804 if (otr_type
&& !contains_type_p (TREE_TYPE (base
), off
, otr_type
))
807 set_by_decl (base
, off
);
811 /* See if OP is SSA name initialized as a copy or by single assignment.
812 If so, walk the SSA graph up. Because simple PHI conditional is considered
813 copy, GLOBAL_VISITED may be used to avoid infinite loop walking the SSA
817 walk_ssa_copies (tree op
, hash_set
<tree
> **global_visited
= NULL
)
819 hash_set
<tree
> *visited
= NULL
;
821 while (TREE_CODE (op
) == SSA_NAME
822 && !SSA_NAME_IS_DEFAULT_DEF (op
)
823 /* We might be called via fold_stmt during cfgcleanup where
824 SSA form need not be up-to-date. */
825 && !name_registered_for_update_p (op
)
826 && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op
))
827 || gimple_code (SSA_NAME_DEF_STMT (op
)) == GIMPLE_PHI
))
831 if (!*global_visited
)
832 *global_visited
= new hash_set
<tree
>;
833 if ((*global_visited
)->add (op
))
839 visited
= new hash_set
<tree
>;
840 if (visited
->add (op
))
848 This pattern is implicitly produced for casts to non-primary
849 bases. When doing context analysis, we do not really care
850 about the case pointer is NULL, becuase the call will be
852 if (gimple_code (SSA_NAME_DEF_STMT (op
)) == GIMPLE_PHI
)
854 gimple phi
= SSA_NAME_DEF_STMT (op
);
856 if (gimple_phi_num_args (phi
) > 2)
858 if (gimple_phi_num_args (phi
) == 1)
859 op
= gimple_phi_arg_def (phi
, 0);
860 else if (integer_zerop (gimple_phi_arg_def (phi
, 0)))
861 op
= gimple_phi_arg_def (phi
, 1);
862 else if (integer_zerop (gimple_phi_arg_def (phi
, 1)))
863 op
= gimple_phi_arg_def (phi
, 0);
869 if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op
)))
871 op
= gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op
));
881 /* Create polymorphic call context from IP invariant CST.
882 This is typically &global_var.
883 OTR_TYPE specify type of polymorphic call or NULL if unknown, OFF
884 is offset of call. */
886 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree cst
,
890 clear_speculation ();
891 set_by_invariant (cst
, otr_type
, off
);
894 /* Build context for pointer REF contained in FNDECL at statement STMT.
895 if INSTANCE is non-NULL, return pointer to the object described by
896 the context or DECL where context is contained in. */
898 ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl
,
903 tree otr_type
= NULL
;
905 hash_set
<tree
> *visited
= NULL
;
907 if (TREE_CODE (ref
) == OBJ_TYPE_REF
)
909 otr_type
= obj_type_ref_class (ref
);
910 base_pointer
= OBJ_TYPE_REF_OBJECT (ref
);
915 /* Set up basic info in case we find nothing interesting in the analysis. */
916 clear_speculation ();
917 clear_outer_type (otr_type
);
920 /* Walk SSA for outer object. */
923 base_pointer
= walk_ssa_copies (base_pointer
, &visited
);
924 if (TREE_CODE (base_pointer
) == ADDR_EXPR
)
926 HOST_WIDE_INT size
, max_size
;
927 HOST_WIDE_INT offset2
;
928 tree base
= get_ref_base_and_extent (TREE_OPERAND (base_pointer
, 0),
929 &offset2
, &size
, &max_size
);
931 if (max_size
!= -1 && max_size
== size
)
932 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base
)),
935 NULL
/* Do not change outer type. */);
937 /* If this is a varying address, punt. */
938 if ((TREE_CODE (base
) == MEM_REF
|| DECL_P (base
))
942 /* We found dereference of a pointer. Type of the pointer
943 and MEM_REF is meaningless, but we can look futher. */
944 if (TREE_CODE (base
) == MEM_REF
)
946 base_pointer
= TREE_OPERAND (base
, 0);
948 += offset2
+ mem_ref_offset (base
).to_short_addr () * BITS_PER_UNIT
;
951 /* We found base object. In this case the outer_type
953 else if (DECL_P (base
))
957 /* Only type inconsistent programs can have otr_type that is
958 not part of outer type. */
960 && !contains_type_p (TREE_TYPE (base
),
961 offset
+ offset2
, otr_type
))
965 *instance
= base_pointer
;
968 set_by_decl (base
, offset
+ offset2
);
969 if (outer_type
&& maybe_in_construction
&& stmt
)
970 maybe_in_construction
971 = decl_maybe_in_construction_p (base
,
985 else if (TREE_CODE (base_pointer
) == POINTER_PLUS_EXPR
986 && tree_fits_uhwi_p (TREE_OPERAND (base_pointer
, 1)))
988 offset
+= tree_to_shwi (TREE_OPERAND (base_pointer
, 1))
990 base_pointer
= TREE_OPERAND (base_pointer
, 0);
999 /* Try to determine type of the outer object. */
1000 if (TREE_CODE (base_pointer
) == SSA_NAME
1001 && SSA_NAME_IS_DEFAULT_DEF (base_pointer
)
1002 && TREE_CODE (SSA_NAME_VAR (base_pointer
)) == PARM_DECL
)
1004 /* See if parameter is THIS pointer of a method. */
1005 if (TREE_CODE (TREE_TYPE (fndecl
)) == METHOD_TYPE
1006 && SSA_NAME_VAR (base_pointer
) == DECL_ARGUMENTS (fndecl
))
1009 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer
)));
1010 gcc_assert (TREE_CODE (outer_type
) == RECORD_TYPE
1011 || TREE_CODE (outer_type
) == UNION_TYPE
);
1013 /* Dynamic casting has possibly upcasted the type
1014 in the hiearchy. In this case outer type is less
1015 informative than inner type and we should forget
1018 && !contains_type_p (outer_type
, offset
,
1020 || !contains_polymorphic_type_p (outer_type
))
1024 *instance
= base_pointer
;
1030 /* If the function is constructor or destructor, then
1031 the type is possibly in construction, but we know
1032 it is not derived type. */
1033 if (DECL_CXX_CONSTRUCTOR_P (fndecl
)
1034 || DECL_CXX_DESTRUCTOR_P (fndecl
))
1036 maybe_in_construction
= true;
1037 maybe_derived_type
= false;
1041 maybe_derived_type
= true;
1042 maybe_in_construction
= false;
1045 *instance
= base_pointer
;
1048 /* Non-PODs passed by value are really passed by invisible
1049 reference. In this case we also know the type of the
1051 if (DECL_BY_REFERENCE (SSA_NAME_VAR (base_pointer
)))
1054 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (base_pointer
)));
1055 /* Only type inconsistent programs can have otr_type that is
1056 not part of outer type. */
1057 if (otr_type
&& !contains_type_p (outer_type
, offset
,
1062 *instance
= base_pointer
;
1065 /* Non-polymorphic types have no interest for us. */
1066 else if (!otr_type
&& !contains_polymorphic_type_p (outer_type
))
1070 *instance
= base_pointer
;
1073 maybe_derived_type
= false;
1074 maybe_in_construction
= false;
1076 *instance
= base_pointer
;
1081 tree base_type
= TREE_TYPE (base_pointer
);
1083 if (TREE_CODE (base_pointer
) == SSA_NAME
1084 && SSA_NAME_IS_DEFAULT_DEF (base_pointer
)
1085 && !(TREE_CODE (SSA_NAME_VAR (base_pointer
)) == PARM_DECL
1086 || TREE_CODE (SSA_NAME_VAR (base_pointer
)) == RESULT_DECL
))
1090 *instance
= base_pointer
;
1093 if (TREE_CODE (base_pointer
) == SSA_NAME
1094 && SSA_NAME_DEF_STMT (base_pointer
)
1095 && gimple_assign_single_p (SSA_NAME_DEF_STMT (base_pointer
)))
1096 base_type
= TREE_TYPE (gimple_assign_rhs1
1097 (SSA_NAME_DEF_STMT (base_pointer
)));
1099 if (base_type
&& POINTER_TYPE_P (base_type
))
1100 combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base_type
)),
1102 true, NULL
/* Do not change type here */);
1103 /* TODO: There are multiple ways to derive a type. For instance
1104 if BASE_POINTER is passed to an constructor call prior our refernece.
1105 We do not make this type of flow sensitive analysis yet. */
1107 *instance
= base_pointer
;
1111 /* Structure to be passed in between detect_type_change and
1112 check_stmt_for_type_change. */
1114 struct type_change_info
1116 /* Offset into the object where there is the virtual method pointer we are
1118 HOST_WIDE_INT offset
;
1119 /* The declaration or SSA_NAME pointer of the base that we are checking for
1122 /* The reference to virtual table pointer used. */
1125 /* If we actually can tell the type that the object has changed to, it is
1126 stored in this field. Otherwise it remains NULL_TREE. */
1127 tree known_current_type
;
1128 HOST_WIDE_INT known_current_offset
;
1130 /* Set to true if dynamic type change has been detected. */
1131 bool type_maybe_changed
;
1132 /* Set to true if multiple types have been encountered. known_current_type
1133 must be disregarded in that case. */
1134 bool multiple_types_encountered
;
1135 /* Set to true if we possibly missed some dynamic type changes and we should
1136 consider the set to be speculative. */
1138 bool seen_unanalyzed_store
;
1141 /* Return true if STMT is not call and can modify a virtual method table pointer.
1142 We take advantage of fact that vtable stores must appear within constructor
1143 and destructor functions. */
1146 noncall_stmt_may_be_vtbl_ptr_store (gimple stmt
)
1148 if (is_gimple_assign (stmt
))
1150 tree lhs
= gimple_assign_lhs (stmt
);
1152 if (gimple_clobber_p (stmt
))
1154 if (!AGGREGATE_TYPE_P (TREE_TYPE (lhs
)))
1156 if (flag_strict_aliasing
1157 && !POINTER_TYPE_P (TREE_TYPE (lhs
)))
1160 if (TREE_CODE (lhs
) == COMPONENT_REF
1161 && !DECL_VIRTUAL_P (TREE_OPERAND (lhs
, 1)))
1163 /* In the future we might want to use get_base_ref_and_offset to find
1164 if there is a field corresponding to the offset and if so, proceed
1165 almost like if it was a component ref. */
1169 /* Code unification may mess with inline stacks. */
1170 if (cfun
->after_inlining
)
1173 /* Walk the inline stack and watch out for ctors/dtors.
1174 TODO: Maybe we can require the store to appear in toplevel
1175 block of CTOR/DTOR. */
1176 for (tree block
= gimple_block (stmt
); block
&& TREE_CODE (block
) == BLOCK
;
1177 block
= BLOCK_SUPERCONTEXT (block
))
1178 if (BLOCK_ABSTRACT_ORIGIN (block
)
1179 && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block
)) == FUNCTION_DECL
)
1180 return inlined_polymorphic_ctor_dtor_block_p (block
, false);
1181 return (TREE_CODE (TREE_TYPE (current_function_decl
)) == METHOD_TYPE
1182 && (DECL_CXX_CONSTRUCTOR_P (current_function_decl
)
1183 || DECL_CXX_DESTRUCTOR_P (current_function_decl
)));
1186 /* If STMT can be proved to be an assignment to the virtual method table
1187 pointer of ANALYZED_OBJ and the type associated with the new table
1188 identified, return the type. Otherwise return NULL_TREE if type changes
1189 in unknown way or ERROR_MARK_NODE if type is unchanged. */
1192 extr_type_from_vtbl_ptr_store (gimple stmt
, struct type_change_info
*tci
,
1193 HOST_WIDE_INT
*type_offset
)
1195 HOST_WIDE_INT offset
, size
, max_size
;
1196 tree lhs
, rhs
, base
;
1198 if (!gimple_assign_single_p (stmt
))
1201 lhs
= gimple_assign_lhs (stmt
);
1202 rhs
= gimple_assign_rhs1 (stmt
);
1203 if (TREE_CODE (lhs
) != COMPONENT_REF
1204 || !DECL_VIRTUAL_P (TREE_OPERAND (lhs
, 1)))
1207 fprintf (dump_file
, " LHS is not virtual table.\n");
1211 if (tci
->vtbl_ptr_ref
&& operand_equal_p (lhs
, tci
->vtbl_ptr_ref
, 0))
1215 base
= get_ref_base_and_extent (lhs
, &offset
, &size
, &max_size
);
1216 if (DECL_P (tci
->instance
))
1218 if (base
!= tci
->instance
)
1222 fprintf (dump_file
, " base:");
1223 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1224 fprintf (dump_file
, " does not match instance:");
1225 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1226 fprintf (dump_file
, "\n");
1231 else if (TREE_CODE (base
) == MEM_REF
)
1233 if (!operand_equal_p (tci
->instance
, TREE_OPERAND (base
, 0), 0))
1237 fprintf (dump_file
, " base mem ref:");
1238 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1239 fprintf (dump_file
, " does not match instance:");
1240 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1241 fprintf (dump_file
, "\n");
1245 if (!integer_zerop (TREE_OPERAND (base
, 1)))
1247 if (!tree_fits_shwi_p (TREE_OPERAND (base
, 1)))
1251 fprintf (dump_file
, " base mem ref:");
1252 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1253 fprintf (dump_file
, " has non-representable offset:");
1254 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1255 fprintf (dump_file
, "\n");
1260 offset
+= tree_to_shwi (TREE_OPERAND (base
, 1)) * BITS_PER_UNIT
;
1263 else if (!operand_equal_p (tci
->instance
, base
, 0)
1268 fprintf (dump_file
, " base:");
1269 print_generic_expr (dump_file
, base
, TDF_SLIM
);
1270 fprintf (dump_file
, " does not match instance:");
1271 print_generic_expr (dump_file
, tci
->instance
, TDF_SLIM
);
1272 fprintf (dump_file
, " with offset %i\n", (int)tci
->offset
);
1274 return tci
->offset
> POINTER_SIZE
? error_mark_node
: NULL_TREE
;
1276 if (offset
!= tci
->offset
1277 || size
!= POINTER_SIZE
1278 || max_size
!= POINTER_SIZE
)
1281 fprintf (dump_file
, " wrong offset %i!=%i or size %i\n",
1282 (int)offset
, (int)tci
->offset
, (int)size
);
1283 return offset
+ POINTER_SIZE
<= tci
->offset
1285 && tci
->offset
+ POINTER_SIZE
> offset
+ max_size
)
1286 ? error_mark_node
: NULL
;
1291 unsigned HOST_WIDE_INT offset2
;
1293 if (!vtable_pointer_value_to_vtable (rhs
, &vtable
, &offset2
))
1296 fprintf (dump_file
, " Failed to lookup binfo\n");
1300 tree binfo
= subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable
)),
1305 fprintf (dump_file
, " Construction vtable used\n");
1306 /* FIXME: We should suport construction contexts. */
1310 *type_offset
= tree_to_shwi (BINFO_OFFSET (binfo
)) * BITS_PER_UNIT
;
1311 return DECL_CONTEXT (vtable
);
1314 /* Record dynamic type change of TCI to TYPE. */
1317 record_known_type (struct type_change_info
*tci
, tree type
, HOST_WIDE_INT offset
)
1323 fprintf (dump_file
, " Recording type: ");
1324 print_generic_expr (dump_file
, type
, TDF_SLIM
);
1325 fprintf (dump_file
, " at offset %i\n", (int)offset
);
1328 fprintf (dump_file
, " Recording unknown type\n");
1331 /* If we found a constructor of type that is not polymorphic or
1332 that may contain the type in question as a field (not as base),
1333 restrict to the inner class first to make type matching bellow
1337 || (TREE_CODE (type
) != RECORD_TYPE
1338 || !TYPE_BINFO (type
)
1339 || !polymorphic_type_binfo_p (TYPE_BINFO (type
)))))
1341 ipa_polymorphic_call_context context
;
1343 context
.offset
= offset
;
1344 context
.outer_type
= type
;
1345 context
.maybe_in_construction
= false;
1346 context
.maybe_derived_type
= false;
1347 context
.dynamic
= true;
1348 /* If we failed to find the inner type, we know that the call
1349 would be undefined for type produced here. */
1350 if (!context
.restrict_to_inner_class (tci
->otr_type
))
1353 fprintf (dump_file
, " Ignoring; does not contain otr_type\n");
1356 /* Watch for case we reached an POD type and anticipate placement
1358 if (!context
.maybe_derived_type
)
1360 type
= context
.outer_type
;
1361 offset
= context
.offset
;
1364 if (tci
->type_maybe_changed
1365 && (!types_same_for_odr (type
, tci
->known_current_type
)
1366 || offset
!= tci
->known_current_offset
))
1367 tci
->multiple_types_encountered
= true;
1368 tci
->known_current_type
= TYPE_MAIN_VARIANT (type
);
1369 tci
->known_current_offset
= offset
;
1370 tci
->type_maybe_changed
= true;
1373 /* Callback of walk_aliased_vdefs and a helper function for
1374 detect_type_change to check whether a particular statement may modify
1375 the virtual table pointer, and if possible also determine the new type of
1376 the (sub-)object. It stores its result into DATA, which points to a
1377 type_change_info structure. */
1380 check_stmt_for_type_change (ao_ref
*ao ATTRIBUTE_UNUSED
, tree vdef
, void *data
)
1382 gimple stmt
= SSA_NAME_DEF_STMT (vdef
);
1383 struct type_change_info
*tci
= (struct type_change_info
*) data
;
1386 /* If we already gave up, just terminate the rest of walk. */
1387 if (tci
->multiple_types_encountered
)
1390 if (is_gimple_call (stmt
))
1392 if (gimple_call_flags (stmt
) & (ECF_CONST
| ECF_PURE
))
1395 /* Check for a constructor call. */
1396 if ((fn
= gimple_call_fndecl (stmt
)) != NULL_TREE
1397 && DECL_CXX_CONSTRUCTOR_P (fn
)
1398 && TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
1399 && gimple_call_num_args (stmt
))
1401 tree op
= walk_ssa_copies (gimple_call_arg (stmt
, 0));
1402 tree type
= TYPE_METHOD_BASETYPE (TREE_TYPE (fn
));
1403 HOST_WIDE_INT offset
= 0, size
, max_size
;
1407 fprintf (dump_file
, " Checking constructor call: ");
1408 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1411 /* See if THIS parameter seems like instance pointer. */
1412 if (TREE_CODE (op
) == ADDR_EXPR
)
1414 op
= get_ref_base_and_extent (TREE_OPERAND (op
, 0),
1415 &offset
, &size
, &max_size
);
1416 if (size
!= max_size
|| max_size
== -1)
1418 tci
->speculative
= true;
1421 if (op
&& TREE_CODE (op
) == MEM_REF
)
1423 if (!tree_fits_shwi_p (TREE_OPERAND (op
, 1)))
1425 tci
->speculative
= true;
1428 offset
+= tree_to_shwi (TREE_OPERAND (op
, 1))
1430 op
= TREE_OPERAND (op
, 0);
1432 else if (DECL_P (op
))
1436 tci
->speculative
= true;
1439 op
= walk_ssa_copies (op
);
1441 if (operand_equal_p (op
, tci
->instance
, 0)
1443 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
1444 && tree_fits_shwi_p (TYPE_SIZE (type
))
1445 && tree_to_shwi (TYPE_SIZE (type
)) + offset
> tci
->offset
)
1447 record_known_type (tci
, type
, tci
->offset
- offset
);
1451 /* Calls may possibly change dynamic type by placement new. Assume
1452 it will not happen, but make result speculative only. */
1455 fprintf (dump_file
, " Function call may change dynamic type:");
1456 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1458 tci
->speculative
= true;
1461 /* Check for inlined virtual table store. */
1462 else if (noncall_stmt_may_be_vtbl_ptr_store (stmt
))
1465 HOST_WIDE_INT offset
= 0;
1468 fprintf (dump_file
, " Checking vtbl store: ");
1469 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1472 type
= extr_type_from_vtbl_ptr_store (stmt
, tci
, &offset
);
1473 if (type
== error_mark_node
)
1475 gcc_assert (!type
|| TYPE_MAIN_VARIANT (type
) == type
);
1479 fprintf (dump_file
, " Unanalyzed store may change type.\n");
1480 tci
->seen_unanalyzed_store
= true;
1481 tci
->speculative
= true;
1484 record_known_type (tci
, type
, offset
);
1491 /* THIS is polymorphic call context obtained from get_polymorphic_context.
1492 OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
1493 INSTANCE is pointer to the outer instance as returned by
1494 get_polymorphic_context. To avoid creation of temporary expressions,
1495 INSTANCE may also be an declaration of get_polymorphic_context found the
1496 value to be in static storage.
1498 If the type of instance is not fully determined
1499 (either OUTER_TYPE is unknown or MAYBE_IN_CONSTRUCTION/INCLUDE_DERIVED_TYPES
1500 is set), try to walk memory writes and find the actual construction of the
1503 Return true if memory is unchanged from function entry.
1505 We do not include this analysis in the context analysis itself, because
1506 it needs memory SSA to be fully built and the walk may be expensive.
1507 So it is not suitable for use withing fold_stmt and similar uses. */
1510 ipa_polymorphic_call_context::get_dynamic_type (tree instance
,
1515 struct type_change_info tci
;
1517 bool function_entry_reached
= false;
1518 tree instance_ref
= NULL
;
1520 /* Remember OFFSET before it is modified by restrict_to_inner_class.
1521 This is because we do not update INSTANCE when walking inwards. */
1522 HOST_WIDE_INT instance_offset
= offset
;
1525 otr_type
= TYPE_MAIN_VARIANT (otr_type
);
1527 /* Walk into inner type. This may clear maybe_derived_type and save us
1528 from useless work. It also makes later comparsions with static type
1530 if (outer_type
&& otr_type
)
1532 if (!restrict_to_inner_class (otr_type
))
1536 if (!maybe_in_construction
&& !maybe_derived_type
)
1539 /* We need to obtain refernce to virtual table pointer. It is better
1540 to look it up in the code rather than build our own. This require bit
1541 of pattern matching, but we end up verifying that what we found is
1544 What we pattern match is:
1546 tmp = instance->_vptr.A; // vtbl ptr load
1547 tmp2 = tmp[otr_token]; // vtable lookup
1548 OBJ_TYPE_REF(tmp2;instance->0) (instance);
1550 We want to start alias oracle walk from vtbl pointer load,
1551 but we may not be able to identify it, for example, when PRE moved the
1554 if (gimple_code (call
) == GIMPLE_CALL
)
1556 tree ref
= gimple_call_fn (call
);
1557 HOST_WIDE_INT offset2
, size
, max_size
;
1559 if (TREE_CODE (ref
) == OBJ_TYPE_REF
)
1561 ref
= OBJ_TYPE_REF_EXPR (ref
);
1562 ref
= walk_ssa_copies (ref
);
1564 /* If call target is already known, no need to do the expensive
1566 if (is_gimple_min_invariant (ref
))
1569 /* Check if definition looks like vtable lookup. */
1570 if (TREE_CODE (ref
) == SSA_NAME
1571 && !SSA_NAME_IS_DEFAULT_DEF (ref
)
1572 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref
))
1573 && TREE_CODE (gimple_assign_rhs1
1574 (SSA_NAME_DEF_STMT (ref
))) == MEM_REF
)
1576 ref
= get_base_address
1577 (TREE_OPERAND (gimple_assign_rhs1
1578 (SSA_NAME_DEF_STMT (ref
)), 0));
1579 ref
= walk_ssa_copies (ref
);
1580 /* Find base address of the lookup and see if it looks like
1582 if (TREE_CODE (ref
) == SSA_NAME
1583 && !SSA_NAME_IS_DEFAULT_DEF (ref
)
1584 && gimple_assign_load_p (SSA_NAME_DEF_STMT (ref
)))
1586 tree ref_exp
= gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref
));
1587 tree base_ref
= get_ref_base_and_extent
1588 (ref_exp
, &offset2
, &size
, &max_size
);
1590 /* Finally verify that what we found looks like read from OTR_OBJECT
1591 or from INSTANCE with offset OFFSET. */
1593 && ((TREE_CODE (base_ref
) == MEM_REF
1594 && ((offset2
== instance_offset
1595 && TREE_OPERAND (base_ref
, 0) == instance
)
1596 || (!offset2
&& TREE_OPERAND (base_ref
, 0) == otr_object
)))
1597 || (DECL_P (instance
) && base_ref
== instance
1598 && offset2
== instance_offset
)))
1600 stmt
= SSA_NAME_DEF_STMT (ref
);
1601 instance_ref
= ref_exp
;
1608 /* If we failed to look up the refernece in code, build our own. */
1611 /* If the statement in question does not use memory, we can't tell
1613 if (!gimple_vuse (stmt
))
1615 ao_ref_init_from_ptr_and_size (&ao
, otr_object
, NULL
);
1618 /* Otherwise use the real reference. */
1619 ao_ref_init (&ao
, instance_ref
);
1621 /* We look for vtbl pointer read. */
1622 ao
.size
= POINTER_SIZE
;
1623 ao
.max_size
= ao
.size
;
1626 = get_deref_alias_set (TREE_TYPE (BINFO_VTABLE (TYPE_BINFO (otr_type
))));
1630 fprintf (dump_file
, "Determining dynamic type for call: ");
1631 print_gimple_stmt (dump_file
, call
, 0, 0);
1632 fprintf (dump_file
, " Starting walk at: ");
1633 print_gimple_stmt (dump_file
, stmt
, 0, 0);
1634 fprintf (dump_file
, " instance pointer: ");
1635 print_generic_expr (dump_file
, otr_object
, TDF_SLIM
);
1636 fprintf (dump_file
, " Outer instance pointer: ");
1637 print_generic_expr (dump_file
, instance
, TDF_SLIM
);
1638 fprintf (dump_file
, " offset: %i (bits)", (int)offset
);
1639 fprintf (dump_file
, " vtbl reference: ");
1640 print_generic_expr (dump_file
, instance_ref
, TDF_SLIM
);
1641 fprintf (dump_file
, "\n");
1644 tci
.offset
= offset
;
1645 tci
.instance
= instance
;
1646 tci
.vtbl_ptr_ref
= instance_ref
;
1647 gcc_assert (TREE_CODE (instance
) != MEM_REF
);
1648 tci
.known_current_type
= NULL_TREE
;
1649 tci
.known_current_offset
= 0;
1650 tci
.otr_type
= otr_type
;
1651 tci
.type_maybe_changed
= false;
1652 tci
.multiple_types_encountered
= false;
1653 tci
.speculative
= false;
1654 tci
.seen_unanalyzed_store
= false;
1656 walk_aliased_vdefs (&ao
, gimple_vuse (stmt
), check_stmt_for_type_change
,
1657 &tci
, NULL
, &function_entry_reached
);
1659 /* If we did not find any type changing statements, we may still drop
1660 maybe_in_construction flag if the context already have outer type.
1662 Here we make special assumptions about both constructors and
1663 destructors which are all the functions that are allowed to alter the
1664 VMT pointers. It assumes that destructors begin with assignment into
1665 all VMT pointers and that constructors essentially look in the
1668 1) The very first thing they do is that they call constructors of
1669 ancestor sub-objects that have them.
1671 2) Then VMT pointers of this and all its ancestors is set to new
1672 values corresponding to the type corresponding to the constructor.
1674 3) Only afterwards, other stuff such as constructor of member
1675 sub-objects and the code written by the user is run. Only this may
1676 include calling virtual functions, directly or indirectly.
1678 4) placement new can not be used to change type of non-POD statically
1679 allocated variables.
1681 There is no way to call a constructor of an ancestor sub-object in any
1684 This means that we do not have to care whether constructors get the
1685 correct type information because they will always change it (in fact,
1686 if we define the type to be given by the VMT pointer, it is undefined).
1688 The most important fact to derive from the above is that if, for some
1689 statement in the section 3, we try to detect whether the dynamic type
1690 has changed, we can safely ignore all calls as we examine the function
1691 body backwards until we reach statements in section 2 because these
1692 calls cannot be ancestor constructors or destructors (if the input is
1693 not bogus) and so do not change the dynamic type (this holds true only
1694 for automatically allocated objects but at the moment we devirtualize
1695 only these). We then must detect that statements in section 2 change
1696 the dynamic type and can try to derive the new type. That is enough
1697 and we can stop, we will never see the calls into constructors of
1698 sub-objects in this code.
1700 Therefore if the static outer type was found (outer_type)
1701 we can safely ignore tci.speculative that is set on calls and give up
1702 only if there was dyanmic type store that may affect given variable
1703 (seen_unanalyzed_store) */
1705 if (!tci
.type_maybe_changed
1708 && !tci
.seen_unanalyzed_store
1709 && !tci
.multiple_types_encountered
1710 && offset
== tci
.offset
1711 && types_same_for_odr (tci
.known_current_type
,
1714 if (!outer_type
|| tci
.seen_unanalyzed_store
)
1716 if (maybe_in_construction
)
1717 maybe_in_construction
= false;
1719 fprintf (dump_file
, " No dynamic type change found.\n");
1723 if (tci
.known_current_type
1724 && !function_entry_reached
1725 && !tci
.multiple_types_encountered
)
1727 if (!tci
.speculative
)
1729 outer_type
= TYPE_MAIN_VARIANT (tci
.known_current_type
);
1730 offset
= tci
.known_current_offset
;
1732 maybe_in_construction
= false;
1733 maybe_derived_type
= false;
1735 fprintf (dump_file
, " Determined dynamic type.\n");
1737 else if (!speculative_outer_type
1738 || speculative_maybe_derived_type
)
1740 speculative_outer_type
= TYPE_MAIN_VARIANT (tci
.known_current_type
);
1741 speculative_offset
= tci
.known_current_offset
;
1742 speculative_maybe_derived_type
= false;
1744 fprintf (dump_file
, " Determined speculative dynamic type.\n");
1749 fprintf (dump_file
, " Found multiple types%s%s\n",
1750 function_entry_reached
? " (function entry reached)" : "",
1751 function_entry_reached
? " (multiple types encountered)" : "");
1757 /* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE
1758 seems consistent (and useful) with what we already have in the non-speculative context. */
1761 ipa_polymorphic_call_context::speculation_consistent_p (tree spec_outer_type
,
1762 HOST_WIDE_INT spec_offset
,
1763 bool spec_maybe_derived_type
,
1764 tree otr_type
) const
1766 if (!flag_devirtualize_speculatively
)
1769 /* Non-polymorphic types are useless for deriving likely polymorphic
1771 if (!spec_outer_type
|| !contains_polymorphic_type_p (spec_outer_type
))
1774 /* If we know nothing, speculation is always good. */
1778 /* Speculation is only useful to avoid derived types.
1779 This is not 100% true for placement new, where the outer context may
1780 turn out to be useless, but ignore these for now. */
1781 if (!maybe_derived_type
)
1784 /* If types agrees, speculation is consistent, but it makes sense only
1785 when it says something new. */
1786 if (types_must_be_same_for_odr (spec_outer_type
, outer_type
))
1787 return maybe_derived_type
&& !spec_maybe_derived_type
;
1789 /* If speculation does not contain the type in question, ignore it. */
1791 && !contains_type_p (spec_outer_type
, spec_offset
, otr_type
, false, true))
1794 /* If outer type already contains speculation as a filed,
1795 it is useless. We already know from OUTER_TYPE
1796 SPEC_TYPE and that it is not in the construction. */
1797 if (contains_type_p (outer_type
, offset
- spec_offset
,
1798 spec_outer_type
, false, false))
1801 /* If speculative outer type is not more specified than outer
1803 We can only decide this safely if we can compare types with OUTER_TYPE.
1805 if ((!in_lto_p
|| odr_type_p (outer_type
))
1806 && !contains_type_p (spec_outer_type
,
1807 spec_offset
- offset
,
1813 /* Improve THIS with speculation described by NEW_OUTER_TYPE, NEW_OFFSET,
1814 NEW_MAYBE_DERIVED_TYPE
1815 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
1818 ipa_polymorphic_call_context::combine_speculation_with
1819 (tree new_outer_type
, HOST_WIDE_INT new_offset
, bool new_maybe_derived_type
,
1822 if (!new_outer_type
)
1825 /* restrict_to_inner_class may eliminate wrong speculation making our job
1828 restrict_to_inner_class (otr_type
);
1830 if (!speculation_consistent_p (new_outer_type
, new_offset
,
1831 new_maybe_derived_type
, otr_type
))
1834 /* New speculation is a win in case we have no speculation or new
1835 speculation does not consider derivations. */
1836 if (!speculative_outer_type
1837 || (speculative_maybe_derived_type
1838 && !new_maybe_derived_type
))
1840 speculative_outer_type
= new_outer_type
;
1841 speculative_offset
= new_offset
;
1842 speculative_maybe_derived_type
= new_maybe_derived_type
;
1845 else if (types_must_be_same_for_odr (speculative_outer_type
,
1848 if (speculative_offset
!= new_offset
)
1850 /* OK we have two contexts that seems valid but they disagree,
1853 This is not a lattice operation, so we may want to drop it later. */
1854 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1856 "Speculative outer types match, "
1857 "offset mismatch -> invalid speculation\n");
1858 clear_speculation ();
1863 if (speculative_maybe_derived_type
&& !new_maybe_derived_type
)
1865 speculative_maybe_derived_type
= false;
1872 /* Choose type that contains the other. This one either contains the outer
1873 as a field (thus giving exactly one target) or is deeper in the type
1875 else if (speculative_outer_type
1876 && speculative_maybe_derived_type
1877 && (new_offset
> speculative_offset
1878 || (new_offset
== speculative_offset
1879 && contains_type_p (new_outer_type
,
1880 0, speculative_outer_type
, false))))
1882 tree old_outer_type
= speculative_outer_type
;
1883 HOST_WIDE_INT old_offset
= speculative_offset
;
1884 bool old_maybe_derived_type
= speculative_maybe_derived_type
;
1886 speculative_outer_type
= new_outer_type
;
1887 speculative_offset
= new_offset
;
1888 speculative_maybe_derived_type
= new_maybe_derived_type
;
1891 restrict_to_inner_class (otr_type
);
1893 /* If the speculation turned out to make no sense, revert to sensible
1895 if (!speculative_outer_type
)
1897 speculative_outer_type
= old_outer_type
;
1898 speculative_offset
= old_offset
;
1899 speculative_maybe_derived_type
= old_maybe_derived_type
;
1902 return (old_offset
!= speculative_offset
1903 || old_maybe_derived_type
!= speculative_maybe_derived_type
1904 || types_must_be_same_for_odr (speculative_outer_type
,
1910 /* Make speculation less specific so
1911 NEW_OUTER_TYPE, NEW_OFFSET, NEW_MAYBE_DERIVED_TYPE is also included.
1912 If OTR_TYPE is set, assume the context is used with OTR_TYPE. */
1915 ipa_polymorphic_call_context::meet_speculation_with
1916 (tree new_outer_type
, HOST_WIDE_INT new_offset
, bool new_maybe_derived_type
,
1919 if (!new_outer_type
&& speculative_outer_type
)
1921 clear_speculation ();
1925 /* restrict_to_inner_class may eliminate wrong speculation making our job
1928 restrict_to_inner_class (otr_type
);
1930 if (!speculative_outer_type
1931 || !speculation_consistent_p (speculative_outer_type
,
1933 speculative_maybe_derived_type
,
1937 if (!speculation_consistent_p (new_outer_type
, new_offset
,
1938 new_maybe_derived_type
, otr_type
))
1940 clear_speculation ();
1944 else if (types_must_be_same_for_odr (speculative_outer_type
,
1947 if (speculative_offset
!= new_offset
)
1949 clear_speculation ();
1954 if (!speculative_maybe_derived_type
&& new_maybe_derived_type
)
1956 speculative_maybe_derived_type
= true;
1963 /* See if one type contains the other as a field (not base). */
1964 else if (contains_type_p (new_outer_type
, new_offset
- speculative_offset
,
1965 speculative_outer_type
, false, false))
1967 else if (contains_type_p (speculative_outer_type
,
1968 speculative_offset
- new_offset
,
1969 new_outer_type
, false, false))
1971 speculative_outer_type
= new_outer_type
;
1972 speculative_offset
= new_offset
;
1973 speculative_maybe_derived_type
= new_maybe_derived_type
;
1976 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
1977 else if (contains_type_p (new_outer_type
,
1978 new_offset
- speculative_offset
,
1979 speculative_outer_type
, false, true))
1981 if (!speculative_maybe_derived_type
)
1983 speculative_maybe_derived_type
= true;
1988 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
1989 else if (contains_type_p (speculative_outer_type
,
1990 speculative_offset
- new_offset
, new_outer_type
, false, true))
1992 speculative_outer_type
= new_outer_type
;
1993 speculative_offset
= new_offset
;
1994 speculative_maybe_derived_type
= true;
1999 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2000 fprintf (dump_file
, "Giving up on speculative meet\n");
2001 clear_speculation ();
2006 /* Assume that both THIS and a given context is valid and strenghten THIS
2007 if possible. Return true if any strenghtening was made.
2008 If actual type the context is being used in is known, OTR_TYPE should be
2009 set accordingly. This improves quality of combined result. */
2012 ipa_polymorphic_call_context::combine_with (ipa_polymorphic_call_context ctx
,
2015 bool updated
= false;
2017 if (ctx
.useless_p () || invalid
)
2020 /* Restricting context to inner type makes merging easier, however do not
2021 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
2022 if (otr_type
&& !invalid
&& !ctx
.invalid
)
2024 restrict_to_inner_class (otr_type
);
2025 ctx
.restrict_to_inner_class (otr_type
);
2030 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2032 fprintf (dump_file
, "Polymorphic call context combine:");
2034 fprintf (dump_file
, "With context: ");
2035 ctx
.dump (dump_file
);
2038 fprintf (dump_file
, "To be used with type: ");
2039 print_generic_expr (dump_file
, otr_type
, TDF_SLIM
);
2040 fprintf (dump_file
, "\n");
2044 /* If call is known to be invalid, we are done. */
2047 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2048 fprintf (dump_file
, "-> Invalid context\n");
2052 if (!ctx
.outer_type
)
2054 else if (!outer_type
)
2056 outer_type
= ctx
.outer_type
;
2057 offset
= ctx
.offset
;
2058 dynamic
= ctx
.dynamic
;
2059 maybe_in_construction
= ctx
.maybe_in_construction
;
2060 maybe_derived_type
= ctx
.maybe_derived_type
;
2063 /* If types are known to be same, merging is quite easy. */
2064 else if (types_must_be_same_for_odr (outer_type
, ctx
.outer_type
))
2066 if (offset
!= ctx
.offset
2067 && TYPE_SIZE (outer_type
)
2068 && TREE_CODE (TYPE_SIZE (outer_type
)) == INTEGER_CST
)
2070 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2071 fprintf (dump_file
, "Outer types match, offset mismatch -> invalid\n");
2072 clear_speculation ();
2073 clear_outer_type ();
2077 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2078 fprintf (dump_file
, "Outer types match, merging flags\n");
2079 if (maybe_in_construction
&& !ctx
.maybe_in_construction
)
2082 maybe_in_construction
= false;
2084 if (maybe_derived_type
&& !ctx
.maybe_derived_type
)
2087 maybe_derived_type
= false;
2089 if (dynamic
&& !ctx
.dynamic
)
2095 /* If we know the type precisely, there is not much to improve. */
2096 else if (!maybe_derived_type
&& !maybe_in_construction
2097 && !ctx
.maybe_derived_type
&& !ctx
.maybe_in_construction
)
2099 /* It may be easy to check if second context permits the first
2100 and set INVALID otherwise. This is not easy to do in general;
2101 contains_type_p may return false negatives for non-comparable
2104 If OTR_TYPE is known, we however can expect that
2105 restrict_to_inner_class should have discovered the same base
2107 if (otr_type
&& !ctx
.maybe_in_construction
&& !ctx
.maybe_derived_type
)
2109 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2110 fprintf (dump_file
, "Contextes disagree -> invalid\n");
2114 /* See if one type contains the other as a field (not base).
2115 In this case we want to choose the wider type, because it contains
2116 more information. */
2117 else if (contains_type_p (ctx
.outer_type
, ctx
.offset
- offset
,
2118 outer_type
, false, false))
2120 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2121 fprintf (dump_file
, "Second type contain the first as a field\n");
2123 if (maybe_derived_type
)
2125 outer_type
= ctx
.outer_type
;
2126 maybe_derived_type
= ctx
.maybe_derived_type
;
2127 offset
= ctx
.offset
;
2128 dynamic
= ctx
.dynamic
;
2132 /* If we do not know how the context is being used, we can
2133 not clear MAYBE_IN_CONSTRUCTION because it may be offseted
2134 to other component of OUTER_TYPE later and we know nothing
2136 if (otr_type
&& maybe_in_construction
2137 && !ctx
.maybe_in_construction
)
2139 maybe_in_construction
= false;
2143 else if (contains_type_p (outer_type
, offset
- ctx
.offset
,
2144 ctx
.outer_type
, false, false))
2146 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2147 fprintf (dump_file
, "First type contain the second as a field\n");
2149 if (otr_type
&& maybe_in_construction
2150 && !ctx
.maybe_in_construction
)
2152 maybe_in_construction
= false;
2156 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
2157 else if (contains_type_p (ctx
.outer_type
,
2158 ctx
.offset
- offset
, outer_type
, false, true))
2160 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2161 fprintf (dump_file
, "First type is base of second\n");
2162 if (!maybe_derived_type
)
2164 if (!ctx
.maybe_in_construction
2165 && types_odr_comparable (outer_type
, ctx
.outer_type
))
2167 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2168 fprintf (dump_file
, "Second context does not permit base -> invalid\n");
2172 /* Pick variant deeper in the hiearchy. */
2175 outer_type
= ctx
.outer_type
;
2176 maybe_in_construction
= ctx
.maybe_in_construction
;
2177 maybe_derived_type
= ctx
.maybe_derived_type
;
2178 offset
= ctx
.offset
;
2179 dynamic
= ctx
.dynamic
;
2183 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
2184 else if (contains_type_p (outer_type
,
2185 offset
- ctx
.offset
, ctx
.outer_type
, false, true))
2187 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2188 fprintf (dump_file
, "Second type is base of first\n");
2189 if (!ctx
.maybe_derived_type
)
2191 if (!maybe_in_construction
2192 && types_odr_comparable (outer_type
, ctx
.outer_type
))
2194 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2195 fprintf (dump_file
, "First context does not permit base -> invalid\n");
2198 /* Pick the base type. */
2199 else if (maybe_in_construction
)
2201 outer_type
= ctx
.outer_type
;
2202 maybe_in_construction
= ctx
.maybe_in_construction
;
2203 maybe_derived_type
= ctx
.maybe_derived_type
;
2204 offset
= ctx
.offset
;
2205 dynamic
= ctx
.dynamic
;
2210 /* TODO handle merging using hiearchy. */
2211 else if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2212 fprintf (dump_file
, "Giving up on merge\n");
2214 updated
|= combine_speculation_with (ctx
.speculative_outer_type
,
2215 ctx
.speculative_offset
,
2216 ctx
.speculative_maybe_derived_type
,
2219 if (updated
&& dump_file
&& (dump_flags
& TDF_DETAILS
))
2221 fprintf (dump_file
, "Updated as: ");
2223 fprintf (dump_file
, "\n");
2229 clear_speculation ();
2230 clear_outer_type ();
2234 /* Take non-speculative info, merge it with speculative and clear speculation.
2235 Used when we no longer manage to keep track of actual outer type, but we
2236 think it is still there.
2238 If OTR_TYPE is set, the transformation can be done more effectively assuming
2239 that context is going to be used only that way. */
2242 ipa_polymorphic_call_context::make_speculative (tree otr_type
)
2244 tree spec_outer_type
= outer_type
;
2245 HOST_WIDE_INT spec_offset
= offset
;
2246 bool spec_maybe_derived_type
= maybe_derived_type
;
2251 clear_outer_type ();
2252 clear_speculation ();
2257 clear_outer_type ();
2258 combine_speculation_with (spec_outer_type
, spec_offset
,
2259 spec_maybe_derived_type
,
2263 /* Use when we can not track dynamic type change. This speculatively assume
2264 type change is not happening. */
2267 ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor
,
2271 make_speculative (otr_type
);
2272 else if (in_poly_cdtor
)
2273 maybe_in_construction
= true;
2276 /* Return TRUE if this context conveys the same information as OTHER. */
2279 ipa_polymorphic_call_context::equal_to
2280 (const ipa_polymorphic_call_context
&x
) const
2283 return x
.useless_p ();
2286 if (x
.useless_p () || x
.invalid
)
2292 || !types_odr_comparable (outer_type
, x
.outer_type
)
2293 || !types_same_for_odr (outer_type
, x
.outer_type
)
2294 || offset
!= x
.offset
2295 || maybe_in_construction
!= x
.maybe_in_construction
2296 || maybe_derived_type
!= x
.maybe_derived_type
2297 || dynamic
!= x
.dynamic
)
2300 else if (x
.outer_type
)
2304 if (speculative_outer_type
2305 && speculation_consistent_p (speculative_outer_type
, speculative_offset
,
2306 speculative_maybe_derived_type
, NULL_TREE
))
2308 if (!x
.speculative_outer_type
)
2311 if (!types_odr_comparable (speculative_outer_type
,
2312 x
.speculative_outer_type
)
2313 || !types_same_for_odr (speculative_outer_type
,
2314 x
.speculative_outer_type
)
2315 || speculative_offset
!= x
.speculative_offset
2316 || speculative_maybe_derived_type
!= x
.speculative_maybe_derived_type
)
2319 else if (x
.speculative_outer_type
2320 && x
.speculation_consistent_p (x
.speculative_outer_type
,
2321 x
.speculative_offset
,
2322 x
.speculative_maybe_derived_type
,
2329 /* Modify context to be strictly less restrictive than CTX. */
2332 ipa_polymorphic_call_context::meet_with (ipa_polymorphic_call_context ctx
,
2335 bool updated
= false;
2337 if (useless_p () || ctx
.invalid
)
2340 /* Restricting context to inner type makes merging easier, however do not
2341 do that unless we know how the context is used (OTR_TYPE is non-NULL) */
2342 if (otr_type
&& !useless_p () && !ctx
.useless_p ())
2344 restrict_to_inner_class (otr_type
);
2345 ctx
.restrict_to_inner_class (otr_type
);
2353 if (ctx
.useless_p () || invalid
)
2359 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2361 fprintf (dump_file
, "Polymorphic call context meet:");
2363 fprintf (dump_file
, "With context: ");
2364 ctx
.dump (dump_file
);
2367 fprintf (dump_file
, "To be used with type: ");
2368 print_generic_expr (dump_file
, otr_type
, TDF_SLIM
);
2369 fprintf (dump_file
, "\n");
2373 if (!dynamic
&& ctx
.dynamic
)
2379 /* If call is known to be invalid, we are done. */
2382 else if (!ctx
.outer_type
)
2384 clear_outer_type ();
2387 /* If types are known to be same, merging is quite easy. */
2388 else if (types_must_be_same_for_odr (outer_type
, ctx
.outer_type
))
2390 if (offset
!= ctx
.offset
2391 && TYPE_SIZE (outer_type
)
2392 && TREE_CODE (TYPE_SIZE (outer_type
)) == INTEGER_CST
)
2394 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2395 fprintf (dump_file
, "Outer types match, offset mismatch -> clearing\n");
2396 clear_outer_type ();
2399 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2400 fprintf (dump_file
, "Outer types match, merging flags\n");
2401 if (!maybe_in_construction
&& ctx
.maybe_in_construction
)
2404 maybe_in_construction
= true;
2406 if (!maybe_derived_type
&& ctx
.maybe_derived_type
)
2409 maybe_derived_type
= true;
2411 if (!dynamic
&& ctx
.dynamic
)
2417 /* See if one type contains the other as a field (not base). */
2418 else if (contains_type_p (ctx
.outer_type
, ctx
.offset
- offset
,
2419 outer_type
, false, false))
2421 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2422 fprintf (dump_file
, "Second type contain the first as a field\n");
2424 /* The second type is more specified, so we keep the first.
2425 We need to set DYNAMIC flag to avoid declaring context INVALID
2426 of OFFSET ends up being out of range. */
2430 && (!TYPE_SIZE (ctx
.outer_type
)
2431 || !TYPE_SIZE (outer_type
)
2432 || !operand_equal_p (TYPE_SIZE (ctx
.outer_type
),
2433 TYPE_SIZE (outer_type
), 0)))))
2439 else if (contains_type_p (outer_type
, offset
- ctx
.offset
,
2440 ctx
.outer_type
, false, false))
2442 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2443 fprintf (dump_file
, "First type contain the second as a field\n");
2448 && (!TYPE_SIZE (ctx
.outer_type
)
2449 || !TYPE_SIZE (outer_type
)
2450 || !operand_equal_p (TYPE_SIZE (ctx
.outer_type
),
2451 TYPE_SIZE (outer_type
), 0)))))
2453 outer_type
= ctx
.outer_type
;
2454 offset
= ctx
.offset
;
2455 dynamic
= ctx
.dynamic
;
2456 maybe_in_construction
= ctx
.maybe_in_construction
;
2457 maybe_derived_type
= ctx
.maybe_derived_type
;
2460 /* See if OUTER_TYPE is base of CTX.OUTER_TYPE. */
2461 else if (contains_type_p (ctx
.outer_type
,
2462 ctx
.offset
- offset
, outer_type
, false, true))
2464 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2465 fprintf (dump_file
, "First type is base of second\n");
2466 if (!maybe_derived_type
)
2468 maybe_derived_type
= true;
2471 if (!maybe_in_construction
&& ctx
.maybe_in_construction
)
2473 maybe_in_construction
= true;
2476 if (!dynamic
&& ctx
.dynamic
)
2482 /* See if CTX.OUTER_TYPE is base of OUTER_TYPE. */
2483 else if (contains_type_p (outer_type
,
2484 offset
- ctx
.offset
, ctx
.outer_type
, false, true))
2486 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2487 fprintf (dump_file
, "Second type is base of first\n");
2488 outer_type
= ctx
.outer_type
;
2489 offset
= ctx
.offset
;
2491 if (!maybe_derived_type
)
2492 maybe_derived_type
= true;
2493 if (!maybe_in_construction
&& ctx
.maybe_in_construction
)
2494 maybe_in_construction
= true;
2495 if (!dynamic
&& ctx
.dynamic
)
2498 /* TODO handle merging using hiearchy. */
2501 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
2502 fprintf (dump_file
, "Giving up on meet\n");
2503 clear_outer_type ();
2507 updated
|= meet_speculation_with (ctx
.speculative_outer_type
,
2508 ctx
.speculative_offset
,
2509 ctx
.speculative_maybe_derived_type
,
2512 if (updated
&& dump_file
&& (dump_flags
& TDF_DETAILS
))
2514 fprintf (dump_file
, "Updated as: ");
2516 fprintf (dump_file
, "\n");